Asynchronous scan support for libata
Subsystems (2)
PATCH 1/1 Asynchronous scan support for libata
Last December, I posted this: http://lwn.net/Articles/213635/
Here's an updated version. It shaves 5 seconds off boot time on my configuration (qla2xxx, emulex, two ata_piix, dual fusion), but could save more or less on other setups.
I think I can remove the 'sync' argument and code from ata_scsi_scan_host() now, but wanted to send out this update today.
---
Some of the drivers (AHCI was mentioned to me as a culprit) take a long time to discover all the devices attached to them. Even for ones which are relatively quick, if you put a lot of them in a machine, it will take a long time in aggregate. This can be fixed by adding support for asynchronous scsi scans, which causes the time-consuming portions of initialisation to take place in threads.
drivers/ata/libata-core.c +50 -47
@@ -6321,6 +6321,53 @@ void ata_host_init(struct ata_host *host, struct device *dev, host->ops = ops; } +void ata_scsi_scan_start (struct Scsi_Host *shost) +{ +struct ata_port *ap =ata_shost_to_port (shost); + +if (ap->ops->error_handler) { +struct ata_eh_info *ehi = &ap->eh_info; +unsigned long flags; + +ata_port_probe (ap); + +/* kick EH for boot probing */ +spin_lock_irqsave (ap->lock, flags); + + ehi->probe_mask = (1 <<ATA_MAX_DEVICES ) -1 ; + ehi->action |=ATA_EH_SOFTRESET ; + ehi->flags |=ATA_EHI_NO_AUTOPSY |ATA_EHI_QUIET ; + + ap->pflags &= ~ATA_PFLAG_INITIALIZING ; + ap->pflags |=ATA_PFLAG_LOADING ; +ata_port_schedule_eh (ap); + +spin_unlock_irqrestore (ap->lock, flags); + +/* wait for EH to finish */ +ata_port_wait_eh (ap); + }else { +int rc; +DPRINTK ("ata%u: bus probe begin\n" , ap->print_id); + rc =ata_bus_probe (ap); +DPRINTK ("ata%u: bus probe end\n" , ap->print_id); + +if (rc) { +/* +* FIXME: do something useful here? +* Current libata behavior will tear down everything +* when the module is removed or the h/w is unplugged. +*/ + } + } +} + +int ata_scsi_scan_finished (struct Scsi_Host *shost,unsigned long time) +{ +ata_scsi_scan_host (ata_shost_to_port (shost),1 ); +return 1 ; +} +/** * ata_host_register - register initialized ATA host * @host: ATA host to register
@@ -6408,56 +6455,10 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht)ata_port_printk (ap,KERN_INFO ,"DUMMY\n" ); } -/* perform each probe synchronously */ DPRINTK ("probe begin\n" );for (i =0 ; i < host->n_ports; i++) {struct ata_port *ap = host->ports[i]; -int rc; - -/* probe */ -if (ap->ops->error_handler) { -struct ata_eh_info *ehi = &ap->eh_info; -unsigned long flags; - -ata_port_probe (ap); - -/* kick EH for boot probing */ -spin_lock_irqsave (ap->lock, flags); - - ehi->probe_mask = (1 <<ATA_MAX_DEVICES ) -1 ; - ehi->action |=ATA_EH_SOFTRESET ; - ehi->flags |=ATA_EHI_NO_AUTOPSY |ATA_EHI_QUIET ; - - ap->pflags &= ~ATA_PFLAG_INITIALIZING ; - ap->pflags |=ATA_PFLAG_LOADING ; -ata_port_schedule_eh (ap); - -spin_unlock_irqrestore (ap->lock, flags); - -/* wait for EH to finish */ -ata_port_wait_eh (ap); - }else { -DPRINTK ("ata%u: bus probe begin\n" , ap->print_id); - rc =ata_bus_probe (ap); -DPRINTK ("ata%u: bus probe end\n" , ap->print_id); - -if (rc) { -/* FIXME: do something useful here? -* Current libata behavior will -* tear down everything when -* the module is removed -* or the h/w is unplugged. -*/ - } - } - } - -/* probes are done, now scan each port's disk(s) */ -DPRINTK ("host probe begin\n" ); -for (i =0 ; i < host->n_ports; i++) { -struct ata_port *ap = host->ports[i]; - -ata_scsi_scan_host (ap,1 ); +scsi_scan_host (ap->scsi_host); }return 0 ;
@@ -6927,6 +6928,8 @@ EXPORT_SYMBOL_GPL(ata_scsi_ioctl);EXPORT_SYMBOL_GPL (ata_scsi_queuecmd);EXPORT_SYMBOL_GPL (ata_scsi_slave_config);EXPORT_SYMBOL_GPL (ata_scsi_slave_destroy); +EXPORT_SYMBOL_GPL (ata_scsi_scan_start); +EXPORT_SYMBOL_GPL (ata_scsi_scan_finished);EXPORT_SYMBOL_GPL (ata_scsi_change_queue_depth);EXPORT_SYMBOL_GPL (ata_host_intr);EXPORT_SYMBOL_GPL (sata_scr_valid);
drivers/ata/libata-scsi.c +7 -0
@@ -2909,6 +2909,13 @@ int ata_scsi_add_hosts(struct ata_host *host, struct scsi_host_template *sht) {int i, rc; +if (!sht->scan_start) { +printk (KERN_WARNING "Overriding NULL scan_start in %s host " +"template\n" , sht->name); + sht->scan_start = ata_scsi_scan_start; + sht->scan_finished = ata_scsi_scan_finished; + } +for (i =0 ; i < host->n_ports; i++) {struct ata_port *ap = host->ports[i];struct Scsi_Host *shost;
include/linux/libata.h +2 -0
@@ -826,6 +826,8 @@ extern int ata_std_bios_param(struct scsi_device *sdev, sector_t capacity, int geom[]);extern int ata_scsi_slave_config (struct scsi_device *sdev);extern void ata_scsi_slave_destroy (struct scsi_device *sdev); +extern void ata_scsi_scan_start (struct Scsi_Host *shost); +extern int ata_scsi_scan_finished (struct Scsi_Host *shost,unsigned long time);extern int ata_scsi_change_queue_depth (struct scsi_device *sdev,int queue_depth);extern struct ata_device *ata_dev_pair (struct ata_device *adev);
drivers/ata/ahci.c +2 -0
@@ -258,6 +258,8 @@ static struct scsi_host_template ahci_sht = { .dma_boundary = AHCI_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, + .scan_start = ata_scsi_scan_start, + .scan_finished = ata_scsi_scan_finished, .bios_param = ata_std_bios_param, };
drivers/ata/ata_generic.c +2 -0
@@ -89,6 +89,8 @@ static struct scsi_host_template generic_sht = { .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, + .scan_start = ata_scsi_scan_start, + .scan_finished = ata_scsi_scan_finished, .bios_param = ata_std_bios_param, };
drivers/ata/ata_piix.c +2 -0
@@ -283,6 +283,8 @@ static struct scsi_host_template piix_sht = { .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, + .scan_start = ata_scsi_scan_start, + .scan_finished = ata_scsi_scan_finished, .bios_param = ata_std_bios_param, };
drivers/ata/pata_ali.c +2 -0
@@ -290,6 +290,8 @@ static struct scsi_host_template ali_sht = { .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, + .scan_start = ata_scsi_scan_start, + .scan_finished = ata_scsi_scan_finished, .bios_param = ata_std_bios_param, };
drivers/ata/pata_amd.c +2 -0
@@ -323,6 +323,8 @@ static struct scsi_host_template amd_sht = { .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, + .scan_start = ata_scsi_scan_start, + .scan_finished = ata_scsi_scan_finished, .bios_param = ata_std_bios_param, };
drivers/ata/pata_artop.c +2 -0
@@ -325,6 +325,8 @@ static struct scsi_host_template artop_sht = { .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, + .scan_start = ata_scsi_scan_start, + .scan_finished = ata_scsi_scan_finished, .bios_param = ata_std_bios_param, };
drivers/ata/pata_atiixp.c +2 -0
@@ -228,6 +228,8 @@ static struct scsi_host_template atiixp_sht = { .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, + .scan_start = ata_scsi_scan_start, + .scan_finished = ata_scsi_scan_finished, .bios_param = ata_std_bios_param, };
drivers/ata/pata_cmd640.c +2 -0
@@ -180,6 +180,8 @@ static struct scsi_host_template cmd640_sht = { .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, + .scan_start = ata_scsi_scan_start, + .scan_finished = ata_scsi_scan_finished, .bios_param = ata_std_bios_param, };
drivers/ata/pata_cmd64x.c +2 -0
@@ -265,6 +265,8 @@ static struct scsi_host_template cmd64x_sht = { .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, + .scan_start = ata_scsi_scan_start, + .scan_finished = ata_scsi_scan_finished, .bios_param = ata_std_bios_param, };
drivers/ata/pata_cs5520.c +2 -0
@@ -154,6 +154,8 @@ static struct scsi_host_template cs5520_sht = { .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, + .scan_start = ata_scsi_scan_start, + .scan_finished = ata_scsi_scan_finished, .bios_param = ata_std_bios_param, };
drivers/ata/pata_cs5530.c +2 -0
@@ -175,6 +175,8 @@ static struct scsi_host_template cs5530_sht = { .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, + .scan_start = ata_scsi_scan_start, + .scan_finished = ata_scsi_scan_finished, .bios_param = ata_std_bios_param, };
drivers/ata/pata_cs5535.c +2 -0
@@ -172,6 +172,8 @@ static struct scsi_host_template cs5535_sht = { .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, + .scan_start = ata_scsi_scan_start, + .scan_finished = ata_scsi_scan_finished, .bios_param = ata_std_bios_param, };
drivers/ata/pata_cypress.c +2 -0
@@ -124,6 +124,8 @@ static struct scsi_host_template cy82c693_sht = { .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, + .scan_start = ata_scsi_scan_start, + .scan_finished = ata_scsi_scan_finished, .bios_param = ata_std_bios_param, };
drivers/ata/pata_efar.c +2 -0
@@ -246,6 +246,8 @@ static struct scsi_host_template efar_sht = { .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, + .scan_start = ata_scsi_scan_start, + .scan_finished = ata_scsi_scan_finished, .bios_param = ata_std_bios_param, };
drivers/ata/pata_hpt366.c +2 -0
@@ -304,6 +304,8 @@ static struct scsi_host_template hpt36x_sht = { .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, + .scan_start = ata_scsi_scan_start, + .scan_finished = ata_scsi_scan_finished, .bios_param = ata_std_bios_param, };
drivers/ata/pata_hpt37x.c +2 -0
@@ -636,6 +636,8 @@ static struct scsi_host_template hpt37x_sht = { .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, + .scan_start = ata_scsi_scan_start, + .scan_finished = ata_scsi_scan_finished, .bios_param = ata_std_bios_param, };
drivers/ata/pata_hpt3x2n.c +2 -0
@@ -352,6 +352,8 @@ static struct scsi_host_template hpt3x2n_sht = { .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, + .scan_start = ata_scsi_scan_start, + .scan_finished = ata_scsi_scan_finished, .bios_param = ata_std_bios_param, };
drivers/ata/pata_hpt3x3.c +2 -0
@@ -116,6 +116,8 @@ static struct scsi_host_template hpt3x3_sht = { .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, + .scan_start = ata_scsi_scan_start, + .scan_finished = ata_scsi_scan_finished, .bios_param = ata_std_bios_param, };
drivers/ata/pata_icside.c +2 -0
@@ -322,6 +322,8 @@ static struct scsi_host_template pata_icside_sht = { .dma_boundary = ~0, /* no dma boundaries */ .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, + .scan_start = ata_scsi_scan_start, + .scan_finished = ata_scsi_scan_finished, .bios_param = ata_std_bios_param, };
drivers/ata/pata_isapnp.c +2 -0
@@ -34,6 +34,8 @@ static struct scsi_host_template isapnp_sht = { .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, + .scan_start = ata_scsi_scan_start, + .scan_finished = ata_scsi_scan_finished, .bios_param = ata_std_bios_param, };
drivers/ata/pata_it8213.c +2 -0
@@ -256,6 +256,8 @@ static struct scsi_host_template it8213_sht = { .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .scan_start = ata_scsi_scan_start, + .scan_finished = ata_scsi_scan_finished, .bios_param = ata_std_bios_param, };
drivers/ata/pata_it821x.c +2 -0
@@ -612,6 +612,8 @@ static struct scsi_host_template it821x_sht = { .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, + .scan_start = ata_scsi_scan_start, + .scan_finished = ata_scsi_scan_finished, .bios_param = ata_std_bios_param, };
drivers/ata/pata_ixp4xx_cf.c +2 -0
@@ -101,6 +101,8 @@ static struct scsi_host_template ixp4xx_sht = { .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, + .scan_start = ata_scsi_scan_start, + .scan_finished = ata_scsi_scan_finished, .bios_param = ata_std_bios_param, };
drivers/ata/pata_jmicron.c +2 -0
@@ -136,6 +136,8 @@ static struct scsi_host_template jmicron_sht = { .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, + .scan_start = ata_scsi_scan_start, + .scan_finished = ata_scsi_scan_finished, /* Use standard CHS mapping rules */ .bios_param = ata_std_bios_param, };
drivers/ata/pata_legacy.c +2 -0
@@ -139,6 +139,8 @@ static struct scsi_host_template legacy_sht = { .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, + .scan_start = ata_scsi_scan_start, + .scan_finished = ata_scsi_scan_finished, .bios_param = ata_std_bios_param, };
drivers/ata/pata_marvell.c +2 -0
@@ -105,6 +105,8 @@ static struct scsi_host_template marvell_sht = { .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, + .scan_start = ata_scsi_scan_start, + .scan_finished = ata_scsi_scan_finished, /* Use standard CHS mapping rules */ .bios_param = ata_std_bios_param, };
drivers/ata/pata_mpc52xx.c +2 -0
@@ -279,6 +279,8 @@ static struct scsi_host_template mpc52xx_ata_sht = { .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .scan_start = ata_scsi_scan_start, + .scan_finished = ata_scsi_scan_finished, .bios_param = ata_std_bios_param, };
drivers/ata/pata_mpiix.c +2 -0
@@ -164,6 +164,8 @@ static struct scsi_host_template mpiix_sht = { .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, + .scan_start = ata_scsi_scan_start, + .scan_finished = ata_scsi_scan_finished, .bios_param = ata_std_bios_param, };
drivers/ata/pata_netcell.c +2 -0
@@ -35,6 +35,8 @@ static struct scsi_host_template netcell_sht = { .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, + .scan_start = ata_scsi_scan_start, + .scan_finished = ata_scsi_scan_finished, /* Use standard CHS mapping rules */ .bios_param = ata_std_bios_param, };
drivers/ata/pata_ns87410.c +2 -0
@@ -157,6 +157,8 @@ static struct scsi_host_template ns87410_sht = { .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, + .scan_start = ata_scsi_scan_start, + .scan_finished = ata_scsi_scan_finished, .bios_param = ata_std_bios_param, };
drivers/ata/pata_oldpiix.c +2 -0
@@ -233,6 +233,8 @@ static struct scsi_host_template oldpiix_sht = { .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, + .scan_start = ata_scsi_scan_start, + .scan_finished = ata_scsi_scan_finished, .bios_param = ata_std_bios_param, };
drivers/ata/pata_opti.c +2 -0
@@ -178,6 +178,8 @@ static struct scsi_host_template opti_sht = { .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, + .scan_start = ata_scsi_scan_start, + .scan_finished = ata_scsi_scan_finished, .bios_param = ata_std_bios_param, };
drivers/ata/pata_optidma.c +2 -0
@@ -362,6 +362,8 @@ static struct scsi_host_template optidma_sht = { .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, + .scan_start = ata_scsi_scan_start, + .scan_finished = ata_scsi_scan_finished, .bios_param = ata_std_bios_param, };
drivers/ata/pata_pcmcia.c +2 -0
@@ -102,6 +102,8 @@ static struct scsi_host_template pcmcia_sht = { .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, + .scan_start = ata_scsi_scan_start, + .scan_finished = ata_scsi_scan_finished, .bios_param = ata_std_bios_param, };
drivers/ata/pata_pdc2027x.c +2 -0
@@ -143,6 +143,8 @@ static struct scsi_host_template pdc2027x_sht = { .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, + .scan_start = ata_scsi_scan_start, + .scan_finished = ata_scsi_scan_finished, .bios_param = ata_std_bios_param, };
drivers/ata/pata_pdc202xx_old.c +2 -0
@@ -243,6 +243,8 @@ static struct scsi_host_template pdc202xx_sht = { .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, + .scan_start = ata_scsi_scan_start, + .scan_finished = ata_scsi_scan_finished, .bios_param = ata_std_bios_param, };
drivers/ata/pata_platform.c +2 -0
@@ -65,6 +65,8 @@ static struct scsi_host_template pata_platform_sht = { .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, + .scan_start = ata_scsi_scan_start, + .scan_finished = ata_scsi_scan_finished, .bios_param = ata_std_bios_param, };
drivers/ata/pata_qdi.c +2 -0
@@ -166,6 +166,8 @@ static struct scsi_host_template qdi_sht = { .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, + .scan_start = ata_scsi_scan_start, + .scan_finished = ata_scsi_scan_finished, .bios_param = ata_std_bios_param, };
drivers/ata/pata_radisys.c +2 -0
@@ -199,6 +199,8 @@ static struct scsi_host_template radisys_sht = { .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, + .scan_start = ata_scsi_scan_start, + .scan_finished = ata_scsi_scan_finished, .bios_param = ata_std_bios_param, };
drivers/ata/pata_rz1000.c +2 -0
@@ -68,6 +68,8 @@ static struct scsi_host_template rz1000_sht = { .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, + .scan_start = ata_scsi_scan_start, + .scan_finished = ata_scsi_scan_finished, .bios_param = ata_std_bios_param, };
drivers/ata/pata_sc1200.c +2 -0
@@ -193,6 +193,8 @@ static struct scsi_host_template sc1200_sht = { .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, + .scan_start = ata_scsi_scan_start, + .scan_finished = ata_scsi_scan_finished, .bios_param = ata_std_bios_param, };
drivers/ata/pata_scc.c +2 -0
@@ -1016,6 +1016,8 @@ static struct scsi_host_template scc_sht = { .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, + .scan_start = ata_scsi_scan_start, + .scan_finished = ata_scsi_scan_finished, .bios_param = ata_std_bios_param, };
drivers/ata/pata_serverworks.c +2 -0
@@ -314,6 +314,8 @@ static struct scsi_host_template serverworks_sht = { .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, + .scan_start = ata_scsi_scan_start, + .scan_finished = ata_scsi_scan_finished, .bios_param = ata_std_bios_param, };
drivers/ata/pata_sil680.c +2 -0
@@ -233,6 +233,8 @@ static struct scsi_host_template sil680_sht = { .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, + .scan_start = ata_scsi_scan_start, + .scan_finished = ata_scsi_scan_finished, .bios_param = ata_std_bios_param, };
drivers/ata/pata_sis.c +2 -0
@@ -524,6 +524,8 @@ static struct scsi_host_template sis_sht = { .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, + .scan_start = ata_scsi_scan_start, + .scan_finished = ata_scsi_scan_finished, .bios_param = ata_std_bios_param, };
drivers/ata/pata_sl82c105.c +2 -0
@@ -220,6 +220,8 @@ static struct scsi_host_template sl82c105_sht = { .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, + .scan_start = ata_scsi_scan_start, + .scan_finished = ata_scsi_scan_finished, .bios_param = ata_std_bios_param, };
drivers/ata/pata_triflex.c +2 -0
@@ -193,6 +193,8 @@ static struct scsi_host_template triflex_sht = { .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, + .scan_start = ata_scsi_scan_start, + .scan_finished = ata_scsi_scan_finished, .bios_param = ata_std_bios_param, };
drivers/ata/pata_via.c +2 -0
@@ -329,6 +329,8 @@ static struct scsi_host_template via_sht = { .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, + .scan_start = ata_scsi_scan_start, + .scan_finished = ata_scsi_scan_finished, .bios_param = ata_std_bios_param, };
drivers/ata/pata_winbond.c +2 -0
@@ -134,6 +134,8 @@ static struct scsi_host_template winbond_sht = { .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, + .scan_start = ata_scsi_scan_start, + .scan_finished = ata_scsi_scan_finished, .bios_param = ata_std_bios_param, };
drivers/ata/pdc_adma.c +2 -0
@@ -147,6 +147,8 @@ static struct scsi_host_template adma_ata_sht = { .queuecommand = ata_scsi_queuecmd, .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, + .scan_start = ata_scsi_scan_start, + .scan_finished = ata_scsi_scan_finished, .bios_param = ata_std_bios_param, .proc_name = DRV_NAME, .can_queue = ATA_DEF_QUEUE,
drivers/ata/sata_inic162x.c +2 -0
@@ -134,6 +134,8 @@ static struct scsi_host_template inic_sht = { .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = inic_slave_config, .slave_destroy = ata_scsi_slave_destroy, + .scan_start = ata_scsi_scan_start, + .scan_finished = ata_scsi_scan_finished, .bios_param = ata_std_bios_param, };
drivers/ata/sata_mv.c +4 -0
@@ -456,6 +456,8 @@ static struct scsi_host_template mv5_sht = { .dma_boundary = MV_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, + .scan_start = ata_scsi_scan_start, + .scan_finished = ata_scsi_scan_finished, .bios_param = ata_std_bios_param, };
@@ -474,6 +476,8 @@ static struct scsi_host_template mv6_sht = { .dma_boundary = MV_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, + .scan_start = ata_scsi_scan_start, + .scan_finished = ata_scsi_scan_finished, .bios_param = ata_std_bios_param, };
drivers/ata/sata_nv.c +4 -0
@@ -317,6 +317,8 @@ static struct scsi_host_template nv_sht = { .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, + .scan_start = ata_scsi_scan_start, + .scan_finished = ata_scsi_scan_finished, .bios_param = ata_std_bios_param, };
@@ -336,6 +338,8 @@ static struct scsi_host_template nv_adma_sht = { .dma_boundary = NV_ADMA_DMA_BOUNDARY, .slave_configure = nv_adma_slave_config, .slave_destroy = ata_scsi_slave_destroy, + .scan_start = ata_scsi_scan_start, + .scan_finished = ata_scsi_scan_finished, .bios_param = ata_std_bios_param, };
drivers/ata/sata_promise.c +2 -0
@@ -163,6 +163,8 @@ static struct scsi_host_template pdc_ata_sht = { .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, + .scan_start = ata_scsi_scan_start, + .scan_finished = ata_scsi_scan_finished, .bios_param = ata_std_bios_param, };
drivers/ata/sata_qstor.c +2 -0
@@ -141,6 +141,8 @@ static struct scsi_host_template qs_ata_sht = { .dma_boundary = QS_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, + .scan_start = ata_scsi_scan_start, + .scan_finished = ata_scsi_scan_finished, .bios_param = ata_std_bios_param, };
drivers/ata/sata_sil.c +2 -0
@@ -181,6 +181,8 @@ static struct scsi_host_template sil_sht = { .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, + .scan_start = ata_scsi_scan_start, + .scan_finished = ata_scsi_scan_finished, .bios_param = ata_std_bios_param, };
drivers/ata/sata_sil24.c +2 -0
@@ -380,6 +380,8 @@ static struct scsi_host_template sil24_sht = { .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, + .scan_start = ata_scsi_scan_start, + .scan_finished = ata_scsi_scan_finished, .bios_param = ata_std_bios_param, };
drivers/ata/sata_sis.c +2 -0
@@ -100,6 +100,8 @@ static struct scsi_host_template sis_sht = { .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, + .scan_start = ata_scsi_scan_start, + .scan_finished = ata_scsi_scan_finished, .bios_param = ata_std_bios_param, };
drivers/ata/sata_svw.c +2 -0
@@ -321,6 +321,8 @@ static struct scsi_host_template k2_sata_sht = { .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, + .scan_start = ata_scsi_scan_start, + .scan_finished = ata_scsi_scan_finished,#ifdef CONFIG_PPC_OF .proc_info = k2_sata_proc_info,#endif
drivers/ata/sata_sx4.c +2 -0
@@ -250,6 +250,8 @@ static struct scsi_host_template pdc_sata_sht = { .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, + .scan_start = ata_scsi_scan_start, + .scan_finished = ata_scsi_scan_finished, .bios_param = ata_std_bios_param, };
drivers/ata/sata_uli.c +2 -0
@@ -90,6 +90,8 @@ static struct scsi_host_template uli_sht = { .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, + .scan_start = ata_scsi_scan_start, + .scan_finished = ata_scsi_scan_finished, .bios_param = ata_std_bios_param, };
drivers/ata/sata_via.c +2 -0
@@ -118,6 +118,8 @@ static struct scsi_host_template svia_sht = { .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, + .scan_start = ata_scsi_scan_start, + .scan_finished = ata_scsi_scan_finished, .bios_param = ata_std_bios_param, };
drivers/ata/sata_vsc.c +2 -0
@@ -312,6 +312,8 @@ static struct scsi_host_template vsc_sata_sht = { .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, + .scan_start = ata_scsi_scan_start, + .scan_finished = ata_scsi_scan_finished, .bios_param = ata_std_bios_param, };
Signature · 4 lines
Intel are signing my paycheques ... these opinions are still mine "Bill, look, we understand that you're interested in selling us this operating system, but compare it to ours. We can't possibly take such a retrograde step."
Quoted 11 lines · Matthew Wilcox
Last December, I posted this: http://lwn.net/Articles/213635/
Here's an updated version. It shaves 5 seconds off boot time on my configuration (qla2xxx, emulex, two
ata_piix, dual fusion), but could save more or less on other setups.I think I can remove the 'sync' argument and code from
ata_scsi_scan_host()now, but wanted to send out this update today.---
Quoted 8 lines
Some of the drivers (AHCI was mentioned to me as a culprit) take a long time to discover all the devices attached to them. Even for ones which are relatively quick, if you put a lot of them in a machine, it will take a long time in aggregate. This can be fixed by adding support for asynchronous scsi scans, which causes the time-consuming portions of initialisation to take place in threads.
Signed-off-by Matthew Wilcox <[email protected]>
I think it's generally okay although it would need to spend quite some time in -mm and we'll need to exclude several drivers which require host-wide silence for mode programming (the current code is buggy but sequential probing hides it pretty well) till host-wide exclusion is implemented.
Thanks.
Signature · 1 line
tejun
Quoted 5 lines · Tejun Heo
I think it's generally okay although it would need to spend quite some time in -mm and we'll need to exclude several drivers which require host-wide silence for mode programming (the current code is buggy but sequential probing hides it pretty well) till host-wide exclusion is implemented.
Can you tell me a bit more about these drivers? Would it be possible to convert them to one host/many channels, which would give us the exclusion we want?
Signature · 4 lines
Intel are signing my paycheques ... these opinions are still mine "Bill, look, we understand that you're interested in selling us this operating system, but compare it to ours. We can't possibly take such a retrograde step."
Quoted 3 lines · Matthew Wilcox
Can you tell me a bit more about these drivers? Would it be possible to convert them to one host/many channels, which would give us the exclusion we want?
As a tangent, I would prefer a more "natural" representation than current, where there is a 1-1 correspondence between scsi_host and ATA controller instance, and a 1-1 correspondence between SCSI channels and ATA ports.
Alas _any_ change to the current setup requires special attention, because it is tied intimately into master/slave exclusion and scheduling.
I occasionally ponder what it would take to create an intelligent request scheduling framework that takes into account inflexible hardware bottlenecks like simplex (one command per controller, $n ports, $m devices), master/slave (one command port, $m devices), NCQ ($n commands per port, $m devices), port multipliers with their own bottlenecks, etc.
I see a lot of common code patterns in this area, but we are all sorta doing our own thing at a low level in drivers, because of subtle (and not-so-subtle) differences in hardware queueing support.
Jeff, thinking out loud
Quoted 10 lines · Matthew Wilcox
Quoted 5 lines · Tejun Heo
I think it's generally okay although it would need to spend quite some time in -mm and we'll need to exclude several drivers which require host-wide silence for mode programming (the current code is buggy but sequential probing hides it pretty well) till host-wide exclusion is implemented.
Can you tell me a bit more about these drivers? Would it be possible to convert them to one host/many channels, which would give us the exclusion we want?
IIRC, sata_promise is of this type and there probably are a few old PATA ones. Ports on the host are mostly independent. There's no need for cross-port synchronization for most of the time but configuring transfer mode requires host-wide quiescence. Currently, the planned way to fix the problem is to implement host-wide exclusion mechanism in the error handler (summon EH of all other threads and wait till all of them are parked) and it's on top of the TODO list, so I don't think it will take too long.
Thanks.
Signature · 1 line
tejun
Quoted 10 lines · On Sat, 8 Sep 2007 11:19:17 -0600 Matthew Wilcox <[email protected]> wrote:
Quoted 5 lines · Tejun Heo
I think it's generally okay although it would need to spend quite some time in -mm and we'll need to exclude several drivers which require host-wide silence for mode programming (the current code is buggy but sequential probing hides it pretty well) till host-wide exclusion is implemented.
Can you tell me a bit more about these drivers? Would it be possible to convert them to one host/many channels, which would give us the exclusion we want?
That would be a more natural way to do it and it would help for the cases we don't support which are one command per controller not one per channel. The PMP code has removed the two devices per channel assumption so in theory we could already fake such a controller as a PMP setup but obviously should expose the two things seperately.
Alan
Quoted 9 lines · Jeff Garzik
Quoted 3 lines · Matthew Wilcox
Can you tell me a bit more about these drivers? Would it be possible to convert them to one host/many channels, which would give us the exclusion we want?
As a tangent, I would prefer a more "natural" representation than current, where there is a 1-1 correspondence between
scsi_hostand ATA controller instance, and a 1-1 correspondence between SCSI channels and ATA ports.
Currently, the biggest problem is the EH thread. SCSI EH is per host and entering entering SCSI EH means host-wide quiescence.
Quoted 9 lines
Alas _any_ change to the current setup requires special attention, because it is tied intimately into master/slave exclusion and scheduling.
I occasionally ponder what it would take to create an intelligent request scheduling framework that takes into account inflexible hardware bottlenecks like simplex (one command per controller, $n ports, $m devices), master/slave (one command port, $m devices), NCQ ($n commands per port, $m devices), port multipliers with their own bottlenecks, etc.
Quoted 3 lines
I see a lot of common code patterns in this area, but we are all sorta doing our own thing at a low level in drivers, because of subtle (and not-so-subtle) differences in hardware queueing support.
Amen. It's slow but things are being shifted from SCSI to block. EH can be shifted to block and made per-queue. Mapping the current SCSI EH architecture to it will take some work but after that changing ATA host <-> SCSI host mapping shouldn't be too difficult.
Thanks.
Signature · 1 line
tejun
Quoted 11 lines · Matthew Wilcox
Last December, I posted this: http://lwn.net/Articles/213635/
Here's an updated version. It shaves 5 seconds off boot time on my configuration (qla2xxx, emulex, two
ata_piix, dual fusion), but could save more or less on other setups.I think I can remove the 'sync' argument and code from
ata_scsi_scan_host()now, but wanted to send out this update today.---
Quoted 8 lines
Some of the drivers (AHCI was mentioned to me as a culprit) take a long time to discover all the devices attached to them. Even for ones which are relatively quick, if you put a lot of them in a machine, it will take a long time in aggregate. This can be fixed by adding support for asynchronous scsi scans, which causes the time-consuming portions of initialisation to take place in threads.
Signed-off-by Matthew Wilcox <[email protected]>
Did you look at SATA alone?
Since SATA does its own scan asynchronously from SCSI itself, doing this seems of little value. This patch doesn't change AHCI scanning at all, for example.
Quite willing to be convinced otherwise, though...
Jeff
Quoted 1 line · Jeff Garzik
Did you look at SATA alone?
No. I don't think I have any pure-SATA machines. I suppose I could disable the drivers for non-SATA and see what happens.
Quoted 3 lines
Since SATA does its own scan asynchronously from SCSI itself, doing this seems of little value. This patch doesn't change AHCI scanning at all, for example.
Its current value lies in allowing SCSI and SATA scans to take place simultaneously; otherwise SATA forces SCSI to finish its scans before it starts. It also allows the SATA asynchronous scan code to become synchronous.
Signature · 4 lines
Intel are signing my paycheques ... these opinions are still mine "Bill, look, we understand that you're interested in selling us this operating system, but compare it to ours. We can't possibly take such a retrograde step."