add hotplug support, take 4
PATCH 3/3 add hotplug support, take 4
Hello,
This is This is part of patchset series described in [T].
This is the fourth take of add-hotplug-support patchset. Changes from the last take[L] are.
* ata_eh_scsi_hotplug() renamed to ata_scsi_hotplug() and moved to libata-scsi.c
* ata_port_detach() now automatically calls scsi_remove_host()
* debug stuff removed from convert-sil24 patch
This patchset is against
upstream (ef2824073fba9def3cf122e89cc485f66dd71f70)
+ [1] set-PIO-0-after-successful-EH-reset
+ [2] prep-for-hotplug-support patchset
+ [3] prep-LLDDs-for-hotplug-support patchset
Thanks.
--
tejun
[T] http://article.gmane.org/gmane.linux.ide/10891
[L] http://article.gmane.org/gmane.linux.ide/10588
[1] http://article.gmane.org/gmane.linux.ide/10890
[2] http://article.gmane.org/gmane.linux.ide/10892
[3] http://article.gmane.org/gmane.linux.ide/10905
PATCH 1/13 libata-hp: implement ata_eh_detach_dev()
Implement ata_eh_detach_dev(). This function is responsible for detaching an ATA device and offlining the associated SCSI device atomically so that the detached device is not accessed after ATA detach is complete.
---
drivers/scsi/libata-eh.c | 28 ++++++++++++++++++++++++++++ drivers/scsi/libata-scsi.c | 24 ++++++++++++++++++++++++ drivers/scsi/libata.h | 1 + 3 files changed, 53 insertions(+), 0 deletions(-)
f42d6c9dfcfd3f3f720b2bee67ab83046ae9e855
drivers/scsi/libata-eh.c +28 -0
@@ -629,6 +629,34 @@ void ata_eh_qc_retry(struct ata_queued_c }/** +* ata_eh_detach_dev - detach ATA device +* @dev: ATA device to detach +* +* Detach @dev. +* +* LOCKING: +* None. +*/ +static void ata_eh_detach_dev (struct ata_device *dev) +{ +struct ata_port *ap = dev->ap; +unsigned long flags; + +ata_dev_disable (dev); + +spin_lock_irqsave (&ap->host_set->lock, flags); + + dev->flags &= ~ATA_DFLAG_DETACH ; + +if (ata_scsi_offline_dev (dev)) { + dev->flags |=ATA_DFLAG_DETACHED ; + ap->flags |=ATA_FLAG_SCSI_HOTPLUG ; + } + +spin_unlock_irqrestore (&ap->host_set->lock, flags); +} + +/** * ata_eh_about_to_do - about to perform eh_action * @ap: target ATA port * @action: action about to be performed
drivers/scsi/libata-scsi.c +24 -0
@@ -2762,3 +2762,27 @@ void ata_scsi_scan_host(struct ata_port } } } + +/** +* ata_scsi_offline_dev - offline attached SCSI device +* @dev: ATA device to offline attached SCSI device for +* +* This function is called from ata_eh_hotplug() and responsible +* for taking the SCSI device attached to @dev offline. This +* function is called with host_set lock which protects dev->sdev +* against clearing. +* +* LOCKING: +* spin_lock_irqsave(host_set lock) +* +* RETURNS: +* 1 if attached SCSI device exists, 0 otherwise. +*/ +int ata_scsi_offline_dev (struct ata_device *dev) +{ +if (dev->sdev) { +scsi_device_set_state (dev->sdev,SDEV_OFFLINE ); +return 1 ; + } +return 0 ; +}
drivers/scsi/libata.h +1 -0
@@ -75,6 +75,7 @@ extern int ata_cmd_ioctl(struct scsi_devextern struct scsi_transport_template ata_scsi_transport_template;extern void ata_scsi_scan_host (struct ata_port *ap); +extern int ata_scsi_offline_dev (struct ata_device *dev);extern unsigned int ata_scsiop_inq_std (struct ata_scsi_args *args,u8 *rbuf,unsigned int buflen);
Signature · 1 line
1.3.2
Re: [PATCH 01/13] libata-hp: implement ata_eh_detach_dev()
Quoted 6 lines · Tejun Heo
Implement
ata_eh_detach_dev(). This function is responsible for detaching an ATA device and offlining the associated SCSI device atomically so that the detached device is not accessed after ATA detach is complete.Signed-off-by Tejun Heo <[email protected]>
ACK
PATCH 2/13 libata-hp: implement hotplug
In reply to Tejun HeoImplement ATA part of hotplug. To avoid probing broken devices over and over again, disabled devices are not automatically detached. They are detached only if probing is requested for the device or the associated port is offline. Also, to avoid infinite probing loop, Each device is probed only once per EH run.
As SATA PHY status is fragile, devices are detached only after it has used up its recovery chances unless explicitly requested by LLDD or user (LLDD may request direct detach if, for example, it supports cold presence detection).
---
drivers/scsi/libata-eh.c | 123 ++++++++++++++++++++++++++++++++++++++-------- include/linux/libata.h | 13 +++++ 2 files changed, 115 insertions(+), 21 deletions(-)
978da67a282e2bb044129f117e6d5468cbe99cfa
drivers/scsi/libata-eh.c +102 -21
@@ -894,10 +894,8 @@ static void ata_eh_analyze_serror(struct err_mask |=AC_ERR_SYSTEM ; action |=ATA_EH_SOFTRESET ; } -if (serror & (SERR_PHYRDY_CHG |SERR_DEV_XCHG )) { - err_mask |=AC_ERR_ATA_BUS ; - action |=ATA_EH_HARDRESET ; - } +if (serror & (SERR_PHYRDY_CHG |SERR_DEV_XCHG )) +ata_ehi_hotplugged (&ehc->i); ehc->i.err_mask |= err_mask; ehc->i.action |= action;
@@ -1449,11 +1447,12 @@ static int ata_eh_reset(struct ata_portreturn rc; } -static int ata_eh_revalidate (struct ata_port *ap, -struct ata_device **r_failed_dev) +static int ata_eh_revalidate_and_attach (struct ata_port *ap, +struct ata_device **r_failed_dev) {struct ata_eh_context *ehc = &ap->eh_context;struct ata_device *dev; +unsigned long flags;int i, rc =0 ;DPRINTK ("ENTER\n" );
@@ -1475,6 +1474,23 @@ static int ata_eh_revalidate(struct ata_break ; ehc->i.action &= ~ATA_EH_REVALIDATE ; + }else if (dev->class ==ATA_DEV_UNKNOWN && + ehc->tries[dev->devno] && +ata_class_enabled (ehc->classes[dev->devno])) { + dev->class = ehc->classes[dev->devno]; + + rc =ata_dev_read_id (dev, &dev->class,1 , dev->id); +if (rc ==0 ) + rc =ata_dev_configure (dev,1 ); + +if (rc) { + dev->class =ATA_DEV_UNKNOWN ; +break ; + } + +spin_lock_irqsave (&ap->host_set->lock, flags); + ap->flags |=ATA_FLAG_SCSI_HOTPLUG ; +spin_unlock_irqrestore (&ap->host_set->lock, flags); } }
@@ -1495,6 +1511,36 @@ static int ata_port_nr_enabled(struct atreturn cnt; } +static int ata_port_nr_vacant (struct ata_port *ap) +{ +int i, cnt =0 ; + +for (i =0 ; i <ATA_MAX_DEVICES ; i++) +if (ap->device[i].class ==ATA_DEV_UNKNOWN ) + cnt++; +return cnt; +} + +static int ata_eh_skip_recovery (struct ata_port *ap) +{ +struct ata_eh_context *ehc = &ap->eh_context; +int i; + +if (ap->flags &ATA_FLAG_FROZEN ||ata_port_nr_enabled (ap)) +return 0 ; + +/* skip if class codes for all vacant slots are ATA_DEV_NONE */ +for (i =0 ; i <ATA_MAX_DEVICES ; i++) { +struct ata_device *dev = &ap->device[i]; + +if (dev->class ==ATA_DEV_UNKNOWN && + ehc->classes[dev->devno] !=ATA_DEV_NONE ) +return 0 ; + } + +return 1 ; +} +/** * ata_eh_recover - recover host port after error * @ap: host port to recover
@@ -1505,9 +1551,10 @@ static int ata_port_nr_enabled(struct at* * This is the alpha and omega, eum and yang, heart and soul of * libata exception handling. On entry, actions required to -* recover each devices are recorded in eh_context. This -* function executes all the operations with appropriate retrials -* and fallbacks to resurrect failed devices. +* recover the port and hotplug requests are recorded in +* eh_context. This function executes all the operations with +* appropriate retrials and fallbacks to resurrect failed +* devices, detach goners and greet newcomers. * * LOCKING: * Kernel thread context (may sleep).
@@ -1530,6 +1577,19 @@ static int ata_eh_recover(struct ata_por dev = &ap->device[i]; ehc->tries[dev->devno] =ATA_EH_DEV_TRIES ; + +/* process hotplug request */ +if (dev->flags &ATA_DFLAG_DETACH ) +ata_eh_detach_dev (dev); + +if (!ata_dev_enabled (dev) && + ((ehc->i.probe_mask & (1 << dev->devno)) && + !(ehc->did_probe_mask & (1 << dev->devno)))) { +ata_eh_detach_dev (dev); +ata_dev_init (dev); + ehc->did_probe_mask |= (1 << dev->devno); + ehc->i.action |=ATA_EH_SOFTRESET ; + } } retry:
@@ -1537,15 +1597,18 @@ static int ata_eh_recover(struct ata_por rc =0 ;/* skip EH if possible. */ -if (!ata_port_nr_enabled (ap) && !(ap->flags &ATA_FLAG_FROZEN )) +if (ata_eh_skip_recovery (ap)) ehc->i.action =0 ; +for (i =0 ; i <ATA_MAX_DEVICES ; i++) + ehc->classes[i] =ATA_DEV_UNKNOWN ; +/* reset */ if (ehc->i.action &ATA_EH_RESET_MASK ) {ata_eh_freeze_port (ap); - rc =ata_eh_reset (ap,0 , prereset, softreset, hardreset, - postreset); + rc =ata_eh_reset (ap,ata_port_nr_vacant (ap), prereset, + softreset, hardreset, postreset);if (rc) {ata_port_printk (ap,KERN_ERR ,"reset failed, giving up\n" );
@@ -1555,8 +1618,8 @@ static int ata_eh_recover(struct ata_porata_eh_thaw_port (ap); } -/* revalidate existing devices */ - rc =ata_eh_revalidate (ap, &dev); +/* revalidate existing devices and attach new ones */ + rc =ata_eh_revalidate_and_attach (ap, &dev);if (rc) goto dev_fail;
@@ -1574,6 +1637,8 @@ static int ata_eh_recover(struct ata_por dev_fail:switch (rc) {case -ENODEV : +/* device missing, schedule probing */ + ehc->i.probe_mask |= (1 << dev->devno);case -EINVAL : ehc->tries[dev->devno] =0 ;break ;
@@ -1586,15 +1651,31 @@ static int ata_eh_recover(struct ata_por ehc->tries[dev->devno] =0 ; } -/* disable device if it has used up all its chances */ -if (ata_dev_enabled (dev) && !ehc->tries[dev->devno]) +if (ata_dev_enabled (dev) && !ehc->tries[dev->devno]) { +/* disable device if it has used up all its chances */ ata_dev_disable (dev); -/* soft didn't work? be haaaaard */ -if (ehc->i.flags &ATA_EHI_DID_RESET ) - ehc->i.action |=ATA_EH_HARDRESET ; -else - ehc->i.action |=ATA_EH_SOFTRESET ; +/* detach if offline */ +if (ata_port_offline (ap)) +ata_eh_detach_dev (dev); + +/* probe if requested */ +if ((ehc->i.probe_mask & (1 << dev->devno)) && + !(ehc->did_probe_mask & (1 << dev->devno))) { +ata_eh_detach_dev (dev); +ata_dev_init (dev); + + ehc->tries[dev->devno] =ATA_EH_DEV_TRIES ; + ehc->did_probe_mask |= (1 << dev->devno); + ehc->i.action |=ATA_EH_SOFTRESET ; + } + }else { +/* soft didn't work? be haaaaard */ +if (ehc->i.flags &ATA_EHI_DID_RESET ) + ehc->i.action |=ATA_EH_HARDRESET ; +else + ehc->i.action |=ATA_EH_SOFTRESET ; + }if (ata_port_nr_enabled (ap)) { ata_port_printk(ap, KERN_WARNING, "failed to recover some "
include/linux/libata.h +13 -0
@@ -822,6 +822,19 @@ #define ata_ehi_clear_desc(ehi) do { \ (ehi)->desc_len =0 ; \ }while (0 ) +static inline void ata_ehi_hotplugged(struct ata_eh_info *ehi) +{ +if (ehi->flags &ATA_EHI_HOTPLUGGED ) +return ; + + ehi->flags |=ATA_EHI_HOTPLUGGED ; + ehi->hotplug_timestamp = jiffies; + + ehi->err_mask |=AC_ERR_ATA_BUS ; + ehi->action |=ATA_EH_SOFTRESET ; + ehi->probe_mask |= (1 <<ATA_MAX_DEVICES ) -1 ; +} +/* * qc helpers */
Signature · 1 line
1.3.2
Re: [PATCH 02/13] libata-hp: implement hotplug
Tejun Heo wrote:
\> + } else if (dev->class == ATA_DEV_UNKNOWN &&
drivers/scsi/libata-eh.c static int ata_eh_revalidate(struct ata_ · line 1489
Quoted 12 lines
drivers/scsi/libata-eh.c +12
-0+ ehc->tries[dev->devno] && + ata_class_enabled(ehc->classes[dev->devno])) { + dev->class = ehc->classes[dev->devno]; + + rc =ata_dev_read_id (dev, &dev->class,1 , dev->id); +if (rc ==0 ) + rc =ata_dev_configure (dev,1 ); + +if (rc) { + dev->class =ATA_DEV_UNKNOWN ; +break ; + }
ACK, with a comment: It seems like this small snippet of logic appears in more than one place, and could be made common
Re: [PATCH 02/13] libata-hp: implement hotplug
Quoted 17 lines · Jeff Garzik
Tejun Heo wrote:
\> + } else if (dev->class==ATA_DEV_UNKNOWN&&drivers/scsi/libata-eh.c static int ata_eh_revalidate(struct ata_ · line 1489
Quoted 12 lines
drivers/scsi/libata-eh.c +12
-0+ ehc->tries[dev->devno] && + ata_class_enabled(ehc->classes[dev->devno])) { + dev->class = ehc->classes[dev->devno]; + + rc =ata_dev_read_id (dev, &dev->class,1 , dev->id); +if (rc ==0 ) + rc =ata_dev_configure (dev,1 ); + +if (rc) { + dev->class =ATA_DEV_UNKNOWN ; +break ; + }ACK, with a comment: It seems like this small snippet of logic appears in more than one place, and could be made common
If you're referring to ata_bus_probe(), it will be removed as soon as all drivers are converted to new EH with a lot of other codes, so I don't think factoring above part is necessary.
Signature · 1 line
tejun
PATCH 3/13 libata-hp: implement SCSI part of hotplug
In reply to Tejun HeoImplement SCSI part of hotplug.
This must be done in a separate context as SCSI makes use of EH during probing. Unfortunately, SCSI probing fails silently if EH is active. ata_eh_scsi_hotplug() does its best to avoid such conditions but, theoretically, it may fail to associate SCSI device to newly found ATA device; however, the chance is very slim and I haven't experienced any such event during testing.
Device removal synchronization is somewhat complex but I think I've got it right and haven't seen it malfunction.
---
drivers/scsi/libata-core.c | 1 drivers/scsi/libata-eh.c | 6 ++ drivers/scsi/libata-scsi.c | 124 ++++++++++++++++++++++++++++++++++++++++++++ drivers/scsi/libata.h | 1 include/linux/libata.h | 2 - 5 files changed, 132 insertions(+), 2 deletions(-)
9b6e334e9835c4941ff6dd39ddebaa56ff29ecdd
drivers/scsi/libata-core.c +1 -0
@@ -5365,6 +5365,7 @@ static void ata_host_init(struct ata_por ap->msg_enable =ATA_MSG_DRV ;INIT_WORK (&ap->port_task,NULL ,NULL ); +INIT_WORK (&ap->hotplug_task, ata_scsi_hotplug, ap);INIT_LIST_HEAD (&ap->eh_done_q);/* set cable type */
drivers/scsi/libata-eh.c +5 -1
@@ -286,9 +286,13 @@ void ata_scsi_error(struct Scsi_Host *ho/* clean up */ spin_lock_irqsave (hs_lock, flags); +if (ap->flags &ATA_FLAG_SCSI_HOTPLUG ) +queue_work (ata_scsi_wq, &ap->hotplug_task); +if (ap->flags &ATA_FLAG_RECOVERED )ata_port_printk (ap,KERN_INFO ,"EH complete\n" ); - ap->flags &= ~ATA_FLAG_RECOVERED ; + + ap->flags &= ~(ATA_FLAG_SCSI_HOTPLUG |ATA_FLAG_RECOVERED );spin_unlock_irqrestore (hs_lock, flags);
drivers/scsi/libata-scsi.c +124 -0
127 lines not on this page · raw message
drivers/scsi/libata.h +1 -0
@@ -76,6 +76,7 @@ extern struct scsi_transport_template atextern void ata_scsi_scan_host (struct ata_port *ap);extern int ata_scsi_offline_dev (struct ata_device *dev); +extern void ata_scsi_hotplug (void *data);extern unsigned int ata_scsiop_inq_std (struct ata_scsi_args *args,u8 *rbuf,unsigned int buflen);
include/linux/libata.h +1 -1
@@ -520,7 +520,7 @@ struct ata_port {struct ata_host_set *host_set;struct device *dev; -struct work_struct port_task; +struct work_struct port_task, hotplug_task;unsigned int hsm_task_state;
Signature · 1 line
1.3.2
PATCH 4/13 libata-hp: implement warmplug
In reply to Tejun HeoImplement warmplug. User-initiated unplug can be detected by hostt->slave_destroy() and plug by transportt->user_scan(). This patch only implements the two callbacks. The next function will hook them.
---
drivers/scsi/libata-core.c | 1 drivers/scsi/libata-scsi.c | 89 ++++++++++++++++++++++++++++++++++++++++++++ include/linux/libata.h | 1 3 files changed, 91 insertions(+), 0 deletions(-)
9a57b5b1dd36ac035559ad01dd69d1ddb6d6481f
drivers/scsi/libata-core.c +1 -0
@@ -5936,6 +5936,7 @@ EXPORT_SYMBOL_GPL(ata_port_queue_task);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_change_queue_depth);EXPORT_SYMBOL_GPL (ata_scsi_release);EXPORT_SYMBOL_GPL (ata_host_intr);
drivers/scsi/libata-scsi.c +89 -0
104 lines not on this page · raw message
include/linux/libata.h +1 -0
@@ -732,6 +732,7 @@ extern int ata_std_bios_param(struct scsstruct block_device *bdev, 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 int ata_scsi_change_queue_depth (struct scsi_device *sdev,int queue_depth);extern struct ata_device *ata_dev_pair (struct ata_device *adev);
Signature · 1 line
1.3.2
PATCH 5/13 libata-hp: hook warmplug
In reply to Tejun HeoHook transportt->user_scan() and hostt->slave_destroy().
---
drivers/scsi/ahci.c | 1 + drivers/scsi/ata_piix.c | 1 + drivers/scsi/libata-scsi.c | 1 + drivers/scsi/pdc_adma.c | 1 + drivers/scsi/sata_mv.c | 1 + drivers/scsi/sata_nv.c | 1 + drivers/scsi/sata_promise.c | 1 + drivers/scsi/sata_qstor.c | 1 + drivers/scsi/sata_sil.c | 1 + drivers/scsi/sata_sil24.c | 1 + drivers/scsi/sata_sis.c | 1 + drivers/scsi/sata_svw.c | 1 + drivers/scsi/sata_sx4.c | 1 + drivers/scsi/sata_uli.c | 1 + drivers/scsi/sata_via.c | 1 + drivers/scsi/sata_vsc.c | 1 + 16 files changed, 16 insertions(+), 0 deletions(-)
506098b74882b8fde1f9904cd5050a63160529ff
drivers/scsi/ahci.c +1 -0
@@ -228,6 +228,7 @@ static struct scsi_host_template ahci_sh .proc_name = DRV_NAME, .dma_boundary = AHCI_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, };
drivers/scsi/ata_piix.c +1 -0
@@ -219,6 +219,7 @@ static struct scsi_host_template piix_sh .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, .resume = ata_scsi_device_resume, .suspend = ata_scsi_device_suspend,
drivers/scsi/libata-scsi.c +1 -0
@@ -107,6 +107,7 @@ static const u8 def_control_mpage[CONTROstruct scsi_transport_template ata_scsi_transport_template = { .eh_strategy_handler = ata_scsi_error, .eh_timed_out = ata_scsi_timed_out, + .user_scan = ata_scsi_user_scan, };
drivers/scsi/pdc_adma.c +1 -0
@@ -152,6 +152,7 @@ static struct scsi_host_template adma_at .proc_name = DRV_NAME, .dma_boundary = ADMA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, };
drivers/scsi/sata_mv.c +1 -0
@@ -390,6 +390,7 @@ static struct scsi_host_template mv_sht .proc_name = DRV_NAME, .dma_boundary = MV_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, };
drivers/scsi/sata_nv.c +1 -0
@@ -216,6 +216,7 @@ static struct scsi_host_template nv_sht .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, };
drivers/scsi/sata_promise.c +1 -0
@@ -121,6 +121,7 @@ static struct scsi_host_template pdc_ata .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, };
drivers/scsi/sata_qstor.c +1 -0
@@ -142,6 +142,7 @@ static struct scsi_host_template qs_ata_ .proc_name = DRV_NAME, .dma_boundary = QS_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, };
drivers/scsi/sata_sil.c +1 -0
@@ -174,6 +174,7 @@ static struct scsi_host_template sil_sht .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, };
drivers/scsi/sata_sil24.c +1 -0
@@ -370,6 +370,7 @@ static struct scsi_host_template sil24_s .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, };
drivers/scsi/sata_sis.c +1 -0
@@ -96,6 +96,7 @@ static struct scsi_host_template sis_sht .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, };
drivers/scsi/sata_svw.c +1 -0
@@ -299,6 +299,7 @@ static struct scsi_host_template k2_sata .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy,#ifdef CONFIG_PPC_OF .proc_info = k2_sata_proc_info,#endif
drivers/scsi/sata_sx4.c +1 -0
@@ -191,6 +191,7 @@ static struct scsi_host_template pdc_sat .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, };
drivers/scsi/sata_uli.c +1 -0
@@ -90,6 +90,7 @@ static struct scsi_host_template uli_sht .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, };
drivers/scsi/sata_via.c +1 -0
@@ -103,6 +103,7 @@ static struct scsi_host_template svia_sh .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, };
drivers/scsi/sata_vsc.c +1 -0
@@ -279,6 +279,7 @@ static struct scsi_host_template vsc_sat .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, };
Signature · 1 line
1.3.2
Re: [PATCH 05/13] libata-hp: hook warmplug
Quoted 3 lines · Tejun Heo
Hook
transportt->user_scan()andhostt->slave_destroy().Signed-off-by Tejun Heo <[email protected]>
ACK 3-5
PATCH 6/13 libata-hp: implement bootplug
In reply to Tejun HeoImplement bootplug - boot probing via hotplug path. While loading, ata_host_add() simply schedules probing and invokes EH. After EH completes, ata_host_add() scans and assicates them with SCSI devices. EH path is slightly modified to handle this (e.g. no autopsy during bootplug). The SCSI part is left in ata_host_add() because it's shared with legacy path and to keep probing order as before (ATA scan all ports in host_set then attach all).
---
drivers/scsi/libata-core.c | 58 +++++++++++++++++++++++++++++++++----------- drivers/scsi/libata-eh.c | 29 +++++++++++++++------- 2 files changed, 63 insertions(+), 24 deletions(-)
fe25a0b404d5a3f12fe68201e719e6b7d75ada66
drivers/scsi/libata-core.c +43 -15
@@ -5413,7 +5413,7 @@ static struct ata_port * ata_host_add(coDPRINTK ("ENTER\n" ); -if (!ent->port_ops->probe_reset && +if (!ent->port_ops->probe_reset && !ent->port_ops->error_handler && !(ent->host_flags & (ATA_FLAG_SATA_RESET |ATA_FLAG_SRST ))) {printk (KERN_ERR "ata%u: no reset mechanism available\n" , port_no);
@@ -5441,6 +5441,12 @@ err_out:return NULL ; } +static int ata_boot_probe_wait (void *dummy) +{ +schedule (); +return 0 ; +} +/** * ata_device_add - Register hardware device with ATA and SCSI layers * @ent: Probe information describing hardware device to be registered
@@ -5459,7 +5465,6 @@ err_out:* RETURNS: * Number of ports registered. Zero on error (no ports registered). */ -int ata_device_add (const struct ata_probe_ent *ent) {unsigned int count =0 , i;
@@ -5536,19 +5541,6 @@ int ata_device_add(const struct ata_prob } ap->sata_spd_limit = ap->hw_sata_spd_limit; -DPRINTK ("ata%u: bus probe begin\n" , ap->id); - rc =ata_bus_probe (ap); -DPRINTK ("ata%u: bus probe end\n" , ap->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. -*/ - } - rc =scsi_add_host (ap->host, dev);if (rc) {ata_port_printk (ap,KERN_ERR ,"scsi_add_host failed\n" );
@@ -5558,6 +5550,42 @@ int ata_device_add(const struct ata_prob* at the very least */ } + +if (!ap->ops->probe_reset) { +int bit =fls (ATA_FLAG_LOADING ) -1 ; +unsigned long flags; + +ata_port_probe (ap); + +spin_lock_irqsave (&ap->host_set->lock, flags); + + ap->eh_info.probe_mask = (1 <<ATA_MAX_DEVICES ) -1 ; + ap->eh_info.action |=ATA_EH_SOFTRESET ; + +set_bit (bit, &ap->flags); +ata_port_schedule_eh (ap); + +spin_unlock_irqrestore (&ap->host_set->lock, flags); + +wait_on_bit (&ap->flags, bit, ata_boot_probe_wait, +TASK_UNINTERRUPTIBLE ); + +while (scsi_host_in_recovery (ap->host)) +msleep (10 ); + }else { +DPRINTK ("ata%u: bus probe begin\n" , ap->id); + rc =ata_bus_probe (ap); +DPRINTK ("ata%u: bus probe end\n" , ap->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) */
drivers/scsi/libata-eh.c +20 -9
@@ -286,11 +286,16 @@ void ata_scsi_error(struct Scsi_Host *ho/* clean up */ spin_lock_irqsave (hs_lock, flags); -if (ap->flags &ATA_FLAG_SCSI_HOTPLUG ) -queue_work (ata_scsi_wq, &ap->hotplug_task); - -if (ap->flags &ATA_FLAG_RECOVERED ) -ata_port_printk (ap,KERN_INFO ,"EH complete\n" ); +if (ap->flags &ATA_FLAG_LOADING ) { +int bit =fls (ATA_FLAG_LOADING ) -1 ; +clear_bit (bit, &ap->flags); +wake_up_bit (&ap->flags, bit); + }else { +if (ap->flags &ATA_FLAG_SCSI_HOTPLUG ) +queue_work (ata_scsi_wq, &ap->hotplug_task); +if (ap->flags &ATA_FLAG_RECOVERED ) +ata_port_printk (ap,KERN_INFO ,"EH complete\n" ); + } ap->flags &= ~(ATA_FLAG_SCSI_HOTPLUG |ATA_FLAG_RECOVERED );
@@ -1329,6 +1334,7 @@ static int ata_eh_reset(struct ata_portstruct ata_eh_context *ehc = &ap->eh_context;unsigned int *classes = ehc->classes;int tries =ATA_EH_RESET_TRIES ; +int verbose = !(ap->flags &ATA_FLAG_LOADING );unsigned int action;ata_reset_fn_t reset;int i, did_followup_srst, rc;
@@ -1376,8 +1382,10 @@ static int ata_eh_reset(struct ata_port } retry: -ata_port_printk (ap,KERN_INFO ,"%s resetting port\n" , - reset == softreset ?"soft" :"hard" ); +/* shut up during boot probing */ +if (verbose) +ata_port_printk (ap,KERN_INFO ,"%s resetting port\n" , + reset == softreset ?"soft" :"hard" );/* reset */ ata_eh_about_to_do (ap,ATA_EH_RESET_MASK );
@@ -1761,8 +1769,11 @@ void ata_do_eh(struct ata_port *ap, ata_ ata_reset_fn_t softreset, ata_reset_fn_t hardreset, ata_postreset_fn_t postreset) { -ata_eh_autopsy (ap ); -ata_eh_report (ap); + if (!(ap->flags & ATA_FLAG_LOADING)) { + ata_eh_autopsy(ap); +ata_eh_report (ap); + } +ata_eh_recover (ap, prereset, softreset, hardreset, postreset);ata_eh_finish (ap); }
Signature · 1 line
1.3.2
Re: [PATCH 06/13] libata-hp: implement bootplug
drivers/scsi/libata-core.c err_out: · line 5446
Quoted 3 lines · Tejun Heo
drivers/scsi/libata-core.c +3
-0+static int ata_boot_probe_wait (void *dummy) +{ +schedule ();
schedule_timeout(1) is preferred
drivers/scsi/libata-core.c int ata_device_add(const struct ata_prob · line 5574
Quoted 7 lines
drivers/scsi/libata-core.c +7
-0+spin_unlock_irqrestore (&ap->host_set->lock, flags); + +wait_on_bit (&ap->flags, bit, ata_boot_probe_wait, +TASK_UNINTERRUPTIBLE ); + +while (scsi_host_in_recovery (ap->host)) +msleep (10 );
Is this seemingly infinite loop _guaranteed_ to stop eventually?
Quoted 78 lines
drivers/scsi/libata-core.c +14
-0+ }else { +DPRINTK ("ata%u: bus probe begin\n" , ap->id); + rc =ata_bus_probe (ap); +DPRINTK ("ata%u: bus probe end\n" , ap->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) */ drivers/scsi/libata-eh.c +20
-9@@ -286,11 +286,16 @@ void ata_scsi_error(struct Scsi_Host *ho/* clean up */ spin_lock_irqsave (hs_lock, flags); -if (ap->flags &ATA_FLAG_SCSI_HOTPLUG ) -queue_work (ata_scsi_wq, &ap->hotplug_task); - -if (ap->flags &ATA_FLAG_RECOVERED ) -ata_port_printk (ap,KERN_INFO ,"EH complete\n" ); +if (ap->flags &ATA_FLAG_LOADING ) { +int bit =fls (ATA_FLAG_LOADING ) -1 ; +clear_bit (bit, &ap->flags); +wake_up_bit (&ap->flags, bit); + }else { +if (ap->flags &ATA_FLAG_SCSI_HOTPLUG ) +queue_work (ata_scsi_wq, &ap->hotplug_task); +if (ap->flags &ATA_FLAG_RECOVERED ) +ata_port_printk (ap,KERN_INFO ,"EH complete\n" ); + } ap->flags &= ~(ATA_FLAG_SCSI_HOTPLUG |ATA_FLAG_RECOVERED );@@ -1329,6 +1334,7 @@ static int ata_eh_reset(struct ata_portstruct ata_eh_context *ehc = &ap->eh_context;unsigned int *classes = ehc->classes;int tries =ATA_EH_RESET_TRIES ; +int verbose = !(ap->flags &ATA_FLAG_LOADING );unsigned int action;ata_reset_fn_t reset;int i, did_followup_srst, rc;@@ -1376,8 +1382,10 @@ static int ata_eh_reset(struct ata_port } retry: -ata_port_printk (ap,KERN_INFO ,"%s resetting port\n" , - reset == softreset ?"soft" :"hard" ); +/* shut up during boot probing */ +if (verbose) +ata_port_printk (ap,KERN_INFO ,"%s resetting port\n" , + reset == softreset ?"soft" :"hard" );/* reset */ ata_eh_about_to_do (ap,ATA_EH_RESET_MASK );@@ -1761,8 +1769,11 @@ void ata_do_eh(struct ata_port *ap, ata_ ata_reset_fn_t softreset, ata_reset_fn_t hardreset, ata_postreset_fn_t postreset) { -ata_eh_autopsy (ap ); -ata_eh_report (ap); + if (!(ap->flags & ATA_FLAG_LOADING)) { + ata_eh_autopsy(ap); +ata_eh_report (ap); + } +ata_eh_recover (ap, prereset, softreset, hardreset, postreset);ata_eh_finish (ap); }
Re: [PATCH 06/13] libata-hp: implement bootplug
Quoted 6 lines · Jeff Garzik
drivers/scsi/libata-core.c err_out: · line 5446
Quoted 3 lines · Tejun Heo
drivers/scsi/libata-core.c +3
-0+static int ata_boot_probe_wait (void *dummy) +{ +schedule ();
schedule_timeout(1)is preferred
Can you elaborate? AFAICS, the function is entered in TASK_UNINTERRUPTIBLE state. No busy looping there. It's called from wait_on_bit() which takes care of sleep/wakeup conditions.
Quoted 9 lines
drivers/scsi/libata-core.c int ata_device_add(const struct ata_prob · line 5574
Quoted 7 lines
drivers/scsi/libata-core.c +7
-0+spin_unlock_irqrestore (&ap->host_set->lock, flags); + +wait_on_bit (&ap->flags, bit, ata_boot_probe_wait, +TASK_UNINTERRUPTIBLE ); + +while (scsi_host_in_recovery (ap->host)) +msleep (10 );Is this seemingly infinite loop _guaranteed_ to stop eventually?
Yeap. Main thread is woken up after EH completes and EH is guaranteed to complete.
Signature · 1 line
tejun
Re: [PATCH 06/13] libata-hp: implement bootplug
Quoted 9 lines · Tejun Heo
Quoted 6 lines · Jeff Garzik
drivers/scsi/libata-core.c err_out: · line 5446
Quoted 3 lines · Tejun Heo
drivers/scsi/libata-core.c +3
-0+static int ata_boot_probe_wait (void *dummy) +{ +schedule ();
schedule_timeout(1)is preferredCan you elaborate? AFAICS, the function is entered in
TASK_UNINTERRUPTIBLEstate. No busy looping there. It's called fromwait_on_bit()which takes care of sleep/wakeup conditions.
Well, the purpose is to _wait, and so schedule_timeout() is more appropriate than schedule(). I also that an unconditional schedule() is a bit unfriendly if there is nothing useful to schedule at the moment.
Jeff
Re: [PATCH 06/13] libata-hp: implement bootplug
Quoted 9 lines · Jeff Garzik
Quoted 8 lines · Tejun Heo
Quoted 6 lines · Jeff Garzik
drivers/scsi/libata-core.c err_out: · line 5446
Quoted 3 lines · Tejun Heo
drivers/scsi/libata-core.c +3
-0+static int ata_boot_probe_wait (void *dummy) +{ +schedule ();
schedule_timeout(1)is preferred
Quoted 3 lines
Quoted 1 line
Can you elaborate? AFAICS, the function is entered in
TASK_UNINTERRUPTIBLEstate. No busy looping there. It's called fromwait_on_bit()which takes care of sleep/wakeup conditions.Well, the purpose is to
_wait, and soschedule_timeout()is more appropriate thanschedule(). I also that an unconditionalschedule()is a bit unfriendly if there is nothing useful to schedule at the moment.
Hmmm... I'm not very sure whether using schedule_timeout() inside wait_on_bit() is allowed or not. I think it should work but I don't think it's supposed to be used that way.
Actually, I'm thinking about dropping the wait_on_bit() and implement generic helper to wait for EH completion as it's done in more than one places (during boot probing and unload unplugging and suspend/resume in future). It probably will use completion. Would that be better?
Signature · 1 line
tejun
Re: [PATCH 06/13] libata-hp: implement bootplug
Quoted 10 lines · Tejun Heo
Quoted 9 lines · Jeff Garzik
Quoted 8 lines · Tejun Heo
Quoted 6 lines · Jeff Garzik
drivers/scsi/libata-core.c err_out: · line 5446
Quoted 3 lines · Tejun Heo
drivers/scsi/libata-core.c +3
-0+static int ata_boot_probe_wait (void *dummy) +{ +schedule ();
schedule_timeout(1)is preferred
Quoted 5 lines
Quoted 3 lines
Quoted 1 line
Can you elaborate? AFAICS, the function is entered in
TASK_UNINTERRUPTIBLEstate. No busy looping there. It's called fromwait_on_bit()which takes care of sleep/wakeup conditions.Well, the purpose is to
_wait, and soschedule_timeout()is more appropriate thanschedule(). I also that an unconditionalschedule()is a bit unfriendly if there is nothing useful to schedule at the moment.Hmmm... I'm not very sure whether using
schedule_timeout()insidewait_on_bit()is allowed or not. I think it should work but I don't think it's supposed to be used that way.
If schedule() can work, so can schedule_timeout()
Quoted 1 line
Actually, I'm thinking about dropping the
wait_on_bit()and implement generic helper to wait for EH completion as it's done in more than one places (during boot probing and unload unplugging and suspend/resume in future). It probably will use completion. Would that be better?
Sure, that's what completions are for :)
Jeff
PATCH 7/13 libata-hp: implement unload-unplug
In reply to Tejun HeoImplement unload unplug - driver unloading / PCI removal via hot unplug path. This is done by ata_port_detach() which requests detach of all devices, schedules EH and wait for it to complete. EH path is slightly modified to handle this (e.g. force zero eh_info during unloading). With this patch, EH and unloading are properly synchronized and unloading should be safe under any circumstances.
---
drivers/scsi/ahci.c | 10 ++----- drivers/scsi/libata-core.c | 59 ++++++++++++++++++++++++++++++++++++++++---- drivers/scsi/libata-eh.c | 7 +++-- include/linux/libata.h | 1 + 4 files changed, 61 insertions(+), 16 deletions(-)
dc54139a72085d78f1fc35a721cff16cdeb38ef9
drivers/scsi/ahci.c +3 -7
@@ -1389,21 +1389,17 @@ static void ahci_remove_one (struct pci_struct device *dev =pci_dev_to_dev (pdev);struct ata_host_set *host_set =dev_get_drvdata (dev);struct ahci_host_priv *hpriv = host_set->private_data; -struct ata_port *ap;unsigned int i;int have_msi; -for (i =0 ; i < host_set->n_ports; i++) { - ap = host_set->ports[i]; - -scsi_remove_host (ap->host); - } +for (i =0 ; i < host_set->n_ports; i++) +ata_port_detach (host_set->ports[i]); have_msi = hpriv->flags &AHCI_FLAG_MSI ;free_irq (host_set->irq, host_set);for (i =0 ; i < host_set->n_ports; i++) { - ap = host_set->ports[i]; +struct ata_port *ap = host_set->ports[i];ata_scsi_release (ap->host);scsi_host_put (ap->host);
drivers/scsi/libata-core.c +53 -6
83 lines not on this page · raw message
drivers/scsi/libata-eh.c +4 -3
@@ -234,7 +234,8 @@ void ata_scsi_error(struct Scsi_Host *hospin_lock_irqsave (hs_lock, flags);memset (&ap->eh_context,0 ,sizeof (ap->eh_context)); - ap->eh_context.i = ap->eh_info; +if (!(ap->flags &ATA_FLAG_UNLOADING )) + ap->eh_context.i = ap->eh_info;memset (&ap->eh_info,0 ,sizeof (ap->eh_info)); ap->flags &= ~ATA_FLAG_EH_PENDING ;
@@ -290,7 +291,7 @@ void ata_scsi_error(struct Scsi_Host *hoint bit =fls (ATA_FLAG_LOADING ) -1 ;clear_bit (bit, &ap->flags);wake_up_bit (&ap->flags, bit); - }else { + }else if (!(ap->flags &ATA_FLAG_UNLOADING )) {if (ap->flags &ATA_FLAG_SCSI_HOTPLUG )queue_work (ata_scsi_wq, &ap->hotplug_task);if (ap->flags &ATA_FLAG_RECOVERED )
@@ -1769,7 +1770,7 @@ void ata_do_eh(struct ata_port *ap, ata_ ata_reset_fn_t softreset, ata_reset_fn_t hardreset, ata_postreset_fn_t postreset) { - if (!(ap->flags & ATA_FLAG_LOADING)) { + if (!(ap->flags & (ATA_FLAG_LOADING | ATA_FLAG_UNLOADING))) { ata_eh_autopsy(ap);ata_eh_report (ap); }
include/linux/libata.h +1 -0
@@ -647,6 +647,7 @@ extern int ata_pci_device_resume(structextern int ata_pci_clear_simplex (struct pci_dev *pdev);#endif /* CONFIG_PCI */ extern int ata_device_add (const struct ata_probe_ent *ent); +extern void ata_port_detach (struct ata_port *ap);extern void ata_host_set_remove (struct ata_host_set *host_set);extern int ata_scsi_detect (struct scsi_host_template *sht);extern int ata_scsi_ioctl (struct scsi_device *dev,int cmd,void __user *arg);
Signature · 1 line
1.3.2
Re: [PATCH 07/13] libata-hp: implement unload-unplug
Quoted 8 lines · Tejun Heo
Implement unload unplug - driver unloading / PCI removal via hot unplug path. This is done by
ata_port_detach()which requests detach of all devices, schedules EH and wait for it to complete. EH path is slightly modified to handle this (e.g. force zeroeh_infoduring unloading). With this patch, EH and unloading are properly synchronized and unloading should be safe under any circumstances.Signed-off-by Tejun Heo <[email protected]>
How does this behave for controller hotplug? For that case, there is nothing to EH...
Jeff
Re: [PATCH 07/13] libata-hp: implement unload-unplug
Quoted 11 lines · Jeff Garzik
Quoted 8 lines · Tejun Heo
Implement unload unplug - driver unloading / PCI removal via hot unplug path. This is done by
ata_port_detach()which requests detach of all devices, schedules EH and wait for it to complete. EH path is slightly modified to handle this (e.g. force zeroeh_infoduring unloading). With this patch, EH and unloading are properly synchronized and unloading should be safe under any circumstances.Signed-off-by Tejun Heo <[email protected]>How does this behave for controller hotplug? For that case, there is nothing to EH...
I've only tested with module unloading but when EH is invoked for unplugging, autopsy and report are skipped and recover is called with zero ehi but with all DFLAG_DETACH set. This amounts to unconditional detachment of all devices without any other operation (well, of course, other than being synchronized to other EH invocations). So, I guess it should work okay. Can you tell me how to test such condition? I guess I can yank out my sil3132 and unload sata_sil24. Would that be enough?
Signature · 1 line
tejun
Re: [PATCH 07/13] libata-hp: implement unload-unplug
Quoted 9 lines · Tejun Heo
Quoted 8 lines · Jeff Garzik
Quoted 7 lines · Tejun Heo
Implement unload unplug - driver unloading / PCI removal via hot unplug path. This is done by
ata_port_detach()which requests detach of all devices, schedules EH and wait for it to complete. EH path is slightly modified to handle this (e.g. force zeroeh_infoduring unloading). With this patch, EH and unloading are properly synchronized and unloading should be safe under any circumstances.
Quoted 5 lines
Quoted 3 lines
Quoted 1 line
Signed-off-by Tejun Heo <[email protected]>How does this behave for controller hotplug? For that case, there is nothing to EH...
I've only tested with module unloading but when EH is invoked for unplugging, autopsy and report are skipped and recover is called with zero ehi but with all
DFLAG_DETACHset. This amounts to unconditional detachment of all devices without any other operation (well, of course, other than being synchronized to other EH invocations). So, I guess it should work okay. Can you tell me how to test such condition? I guess I can yank out my sil3132 and unloadsata_sil24. Would that be enough?
ISTR there is some sysfs trigger for PCI eject, that will allow you test this.
Jeff
PATCH 8/13 ata_piix: convert ata_piix to new probing mechanism
In reply to Tejun HeoConvert ata_piix to new probing mechanism. Automatic hotplug is not supported due to hardware limitation (no PHY event interrupt), but warm plugging works.
---
drivers/scsi/ata_piix.c | 87 +++++++++++++++++------------------------------ 1 files changed, 32 insertions(+), 55 deletions(-)
b5bcb83ff6ea2ec505c54d91f8fa806521750eae
drivers/scsi/ata_piix.c +32 -55
@@ -146,11 +146,10 @@ struct piix_map_db {static int piix_init_one (struct pci_dev *pdev,const struct pci_device_id *ent); - -static int piix_pata_probe_reset (struct ata_port *ap,unsigned int *classes); -static int piix_sata_probe_reset (struct ata_port *ap,unsigned int *classes);static void piix_set_piomode (struct ata_port *ap,struct ata_device *adev);static void piix_set_dmamode (struct ata_port *ap,struct ata_device *adev); +static void piix_pata_error_handler (struct ata_port *ap); +static void piix_sata_error_handler (struct ata_port *ap);static unsigned int in_module_init =1 ;
@@ -237,8 +236,6 @@ static const struct ata_port_operations .exec_command = ata_exec_command, .dev_select = ata_std_dev_select, - .probe_reset = piix_pata_probe_reset, - .bmdma_setup = ata_bmdma_setup, .bmdma_start = ata_bmdma_start, .bmdma_stop = ata_bmdma_stop,
@@ -249,7 +246,7 @@ static const struct ata_port_operations .freeze = ata_bmdma_freeze, .thaw = ata_bmdma_thaw, - .error_handler = ata_bmdma_error_handler, + .error_handler = piix_pata_error_handler, .post_internal_cmd = ata_bmdma_post_internal_cmd, .irq_handler = ata_interrupt,
@@ -269,8 +266,6 @@ static const struct ata_port_operations .exec_command = ata_exec_command, .dev_select = ata_std_dev_select, - .probe_reset = piix_sata_probe_reset, - .bmdma_setup = ata_bmdma_setup, .bmdma_start = ata_bmdma_start, .bmdma_stop = ata_bmdma_stop,
@@ -281,7 +276,7 @@ static const struct ata_port_operations .freeze = ata_bmdma_freeze, .thaw = ata_bmdma_thaw, - .error_handler = ata_bmdma_error_handler, + .error_handler = piix_sata_error_handler, .post_internal_cmd = ata_bmdma_post_internal_cmd, .irq_handler = ata_interrupt,
@@ -466,59 +461,51 @@ cbl40: }/** -* piix_pata_probeinit - probeinit for PATA host controller +* piix_pata_prereset - prereset for PATA host controller * @ap: Target port * -* Probeinit including cable detection. -* -* LOCKING: -* None (inherited from caller). -*/ -static void piix_pata_probeinit (struct ata_port *ap) -{ -piix_pata_cbl_detect (ap); -ata_std_probeinit (ap); -} - -/** -* piix_pata_probe_reset - Perform reset on PATA port and classify -* @ap: Port to reset -* @classes: Resulting classes of attached devices -* -* Reset PATA phy and classify attached devices. +* Prereset including cable detection. * * LOCKING: * None (inherited from caller). */ -static int piix_pata_probe_reset (struct ata_port *ap,unsigned int *classes) +static int piix_pata_prereset (struct ata_port *ap) {struct pci_dev *pdev =to_pci_dev (ap->host_set->dev);if (!pci_test_config_bits (pdev, &piix_enable_bits[ap->hard_port_no])) {ata_port_printk (ap,KERN_INFO ,"port disabled. ignoring.\n" ); + ap->eh_context.i.action &= ~ATA_EH_RESET_MASK ;return 0 ; } -return ata_drive_probe_reset (ap, piix_pata_probeinit, - ata_std_softreset,NULL , - ata_std_postreset, classes); +piix_pata_cbl_detect (ap); + +return ata_std_prereset (ap); +} + +static void piix_pata_error_handler (struct ata_port *ap) +{ +ata_bmdma_drive_eh (ap, piix_pata_prereset, ata_std_softreset,NULL , + ata_std_postreset); }/** -* piix_sata_probe - Probe PCI device for present SATA devices -* @ap: Port associated with the PCI device we wish to probe +* piix_sata_prereset - prereset for SATA host controller +* @ap: Target port * * Reads and configures SATA PCI device's PCI config register * Port Configuration and Status (PCS) to determine port and -* device availability. +* device availability. Return -ENODEV to skip reset if no +* device is present. * * LOCKING: * None (inherited from caller). * * RETURNS: -* Mask of avaliable devices on the port. +* 0 if device is present, -ENODEV otherwise. */ -static unsigned int piix_sata_probe (struct ata_port *ap) +static int piix_sata_prereset (struct ata_port *ap) {struct pci_dev *pdev =to_pci_dev (ap->host_set->dev);const unsigned int *map = ap->host_set->private_data;
@@ -560,29 +547,19 @@ static unsigned int piix_sata_probe (strDPRINTK ("ata%u: LEAVE, pcs=0x%x present_mask=0x%x\n" , ap->id, pcs, present_mask); -return present_mask; -} - -/** -* piix_sata_probe_reset - Perform reset on SATA port and classify -* @ap: Port to reset -* @classes: Resulting classes of attached devices -* -* Reset SATA phy and classify attached devices. -* -* LOCKING: -* None (inherited from caller). -*/ -static int piix_sata_probe_reset (struct ata_port *ap,unsigned int *classes) -{ -if (!piix_sata_probe (ap)) { +if (!present_mask) {ata_port_printk (ap,KERN_INFO ,"SATA port has no device.\n" ); + ap->eh_context.i.action &= ~ATA_EH_RESET_MASK ;return 0 ; } -return ata_drive_probe_reset (ap, ata_std_probeinit, - ata_std_softreset,NULL , - ata_std_postreset, classes); +return ata_std_prereset (ap); +} + +static void piix_sata_error_handler (struct ata_port *ap) +{ +ata_bmdma_drive_eh (ap, piix_sata_prereset, ata_std_softreset,NULL , + ata_std_postreset); }/**
Signature · 1 line
1.3.2
PATCH 9/13 sata_sil: convert to new probing mechanism and add hotplug support
In reply to Tejun HeoConvert to new probing mechanism and add hotplug support by enabling SATA IRQ for SError.N, marking ehi for hotplug and scheduling EH on SATA IRQs.
Sil3112/3512/3114 family of controllers use COMRESET as TF clearing point and can reliably wait for FIS34 after COMRESET whether the FIS is the first FIS34 after POR or in response to the COMRESET. Thus, setting ATA_FLAG_HRST_TO_RESUME is enough for device detection after hotplug.
---
drivers/scsi/sata_sil.c | 21 +++++++++++++-------- 1 files changed, 13 insertions(+), 8 deletions(-)
1068249a03081de450a306060e8a740d639920b3
drivers/scsi/sata_sil.c +13 -8
@@ -56,7 +56,7 @@ enum {SIL_FLAG_MOD15WRITE = (1 <<30 ),SIL_DFL_HOST_FLAGS =ATA_FLAG_SATA |ATA_FLAG_NO_LEGACY | - ATA_FLAG_MMIO, + ATA_FLAG_MMIO | ATA_FLAG_HRST_TO_RESUME,/* * Controller IDs
@@ -186,7 +186,6 @@ static const struct ata_port_operations .check_status = ata_check_status, .exec_command = ata_exec_command, .dev_select = ata_std_dev_select, - .probe_reset = ata_std_probe_reset, .post_set_mode = sil_post_set_mode, .bmdma_setup = ata_bmdma_setup, .bmdma_start = ata_bmdma_start,
@@ -344,6 +343,11 @@ static void sil_host_intr(struct ata_porstruct ata_queued_cmd *qc =ata_qc_from_tag (ap, ap->active_tag);u8 status; +if (unlikely (bmdma2 &SIL_DMA_SATA_IRQ )) { +ata_ehi_hotplugged (&ap->eh_info); + goto freeze; + } +if (unlikely (!qc || qc->tf.ctl &ATA_NIEN )) goto freeze;
@@ -416,7 +420,7 @@ static irqreturn_t sil_interrupt(int irqif (unlikely (!ap || ap->flags &ATA_FLAG_DISABLED ))continue ; -if (!(bmdma2 &SIL_DMA_COMPLETE )) +if (!(bmdma2 & (SIL_DMA_COMPLETE |SIL_DMA_SATA_IRQ )))continue ;sil_host_intr (ap, bmdma2);
@@ -433,6 +437,9 @@ static void sil_freeze(struct ata_port *void __iomem *mmio_base = ap->host_set->mmio_base;u32 tmp; +/* global IRQ mask doesn't block SATA IRQ, turn off explicitly */ +writel (0 , mmio_base + sil_port[ap->port_no].sien); +/* plug IRQ */ tmp =readl (mmio_base +SIL_SYSCFG ); tmp |=SIL_MASK_IDE0_INT << ap->port_no;
@@ -449,6 +456,9 @@ static void sil_thaw(struct ata_port *apata_chk_status (ap);ata_bmdma_irq_clear (ap); +/* turn on SATA IRQ */ +writel (SIL_SIEN_N , mmio_base + sil_port[ap->port_no].sien); +/* turn on IRQ */ tmp =readl (mmio_base +SIL_SYSCFG ); tmp &= ~(SIL_MASK_IDE0_INT << ap->port_no);
@@ -622,11 +632,6 @@ static int sil_init_one (struct pci_dev mmio_base + sil_port[2].bmdma); } -/* mask all SATA phy-related interrupts */ -/* TODO: unmask bit 6 (SError N bit) for hotplug */ -for (i =0 ; i < probe_ent->n_ports; i++) -writel (0 , mmio_base + sil_port[i].sien); -pci_set_master (pdev);/* FIXME: check ata_device_add return value */
Signature · 1 line
1.3.2
Re: [PATCH 09/13] sata_sil: convert to new probing mechanism and add hotplug support
Quoted 11 lines · Tejun Heo
Convert to new probing mechanism and add hotplug support by enabling SATA IRQ for SError.N, marking ehi for hotplug and scheduling EH on SATA IRQs.
Sil3112/3512/3114 family of controllers use COMRESET as TF clearing point and can reliably wait for FIS34 after COMRESET whether the FIS is the first FIS34 after POR or in response to the COMRESET. Thus, setting
ATA_FLAG_HRST_TO_RESUMEis enough for device detection after hotplug.Signed-off-by Tejun Heo <[email protected]>
What is FIS34? I've never heard of that... :)
ACK patch 8, and the content of this patch (#9)
PATCH 10/13 ahci: convert to new probing mechanism and add hotplug support
In reply to Tejun HeoConvert to new probing mechanism and add hotplug support by enabling PORT_IRQ_PHYRDY, marking ehi for hotplug and scheduling EH on CONNECT/PHYRDY interrupts.
Unfortunately, ahci cannot reliably wait for the first FIS34 after hotplug. It sometimes succeeds but times out more often than not, so ATA_FLAG_CANT_WAIT_FIS34 is used.
This patch also fixes ahci_hardreset() such that D2H Register FIS RX area is cleared before issuing COMRESET. Without this, ata_busy_sleep() after COMRESET might prematually finish if the previous TF contains DRDY && !BSY.
---
drivers/scsi/ahci.c | 47 +++++++++++++++++++++++++++-------------------- 1 files changed, 27 insertions(+), 20 deletions(-)
8cf0cb52955e53d055c16c85b648c5b9b9ef2679
drivers/scsi/ahci.c +27 -20
@@ -136,6 +136,7 @@ enum {PORT_IRQ_FREEZE =PORT_IRQ_HBUS_ERR |PORT_IRQ_IF_ERR |PORT_IRQ_CONNECT | +PORT_IRQ_PHYRDY |PORT_IRQ_UNK_FIS ,PORT_IRQ_ERROR =PORT_IRQ_FREEZE | PORT_IRQ_TF_ERR |
@@ -200,7 +201,6 @@ static void ahci_scr_write (struct ata_pstatic int ahci_init_one (struct pci_dev *pdev,const struct pci_device_id *ent);static unsigned int ahci_qc_issue (struct ata_queued_cmd *qc);static irqreturn_t ahci_interrupt (int irq,void *dev_instance,struct pt_regs *regs); -static int ahci_probe_reset (struct ata_port *ap,unsigned int *classes);static void ahci_irq_clear (struct ata_port *ap);static int ahci_port_start (struct ata_port *ap);static void ahci_port_stop (struct ata_port *ap);
@@ -241,8 +241,6 @@ static const struct ata_port_operations .tf_read = ahci_tf_read, - .probe_reset = ahci_probe_reset, - .qc_prep = ahci_qc_prep, .qc_issue = ahci_qc_issue,
@@ -267,7 +265,8 @@ static const struct ata_port_info ahci_p { .sht = &ahci_sht, .host_flags =ATA_FLAG_SATA |ATA_FLAG_NO_LEGACY | - ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA, +ATA_FLAG_MMIO |ATA_FLAG_PIO_DMA | + ATA_FLAG_SKIP_D2H_BSY, .pio_mask = 0x1f, /* pio0-4 */ .udma_mask = 0x7f, /* udma0-6 ; FIXME */ .port_ops = &ahci_ops,
@@ -277,6 +276,7 @@ static const struct ata_port_info ahci_p .sht = &ahci_sht, .host_flags =ATA_FLAG_SATA |ATA_FLAG_NO_LEGACY |ATA_FLAG_MMIO |ATA_FLAG_PIO_DMA | +ATA_FLAG_SKIP_D2H_BSY | AHCI_FLAG_RESET_NEEDS_CLO, .pio_mask = 0x1f, /* pio0-4 */ .udma_mask = 0x7f, /* udma0-6 ; FIXME */
@@ -569,6 +569,17 @@ static int ahci_clo(struct ata_port *ap)return 0 ; } +static int ahci_prereset (struct ata_port *ap) +{ +if ((ap->flags &AHCI_FLAG_RESET_NEEDS_CLO ) && + (ata_busy_wait (ap,ATA_BUSY ,1000 ) &ATA_BUSY )) { +/* ATA_BUSY hasn't cleared, so send a CLO */ +ahci_clo (ap); + } + +return ata_std_prereset (ap); +} +static int ahci_softreset (struct ata_port *ap,unsigned int *class) {struct ahci_port_priv *pp = ap->private_data;
@@ -678,12 +689,22 @@ static int ahci_softreset(struct ata_porstatic int ahci_hardreset (struct ata_port *ap,unsigned int *class) { +struct ahci_port_priv *pp = ap->private_data; +u8 *d2h_fis = pp->rx_fis +RX_FIS_D2H_REG ; +struct ata_taskfile tf;int rc;DPRINTK ("ENTER\n" );ahci_stop_engine (ap); + +/* clear D2H reception area to properly wait for FIS34 */ +ata_tf_init (ap->device, &tf); + tf.command =0xff ; +ata_tf_to_fis (&tf, d2h_fis,0 ); + rc =sata_std_hardreset (ap, class); +ahci_start_engine (ap);if (rc ==0 &&ata_port_online (ap))
@@ -714,19 +735,6 @@ static void ahci_postreset(struct ata_po } } -static int ahci_probe_reset (struct ata_port *ap,unsigned int *classes) -{ -if ((ap->flags &AHCI_FLAG_RESET_NEEDS_CLO ) && - (ata_busy_wait (ap,ATA_BUSY ,1000 ) &ATA_BUSY )) { -/* ATA_BUSY hasn't cleared, so send a CLO */ -ahci_clo (ap); - } - -return ata_drive_probe_reset (ap, ata_std_probeinit, - ahci_softreset, ahci_hardreset, - ahci_postreset, classes); -} -static u8 ahci_check_status (struct ata_port *ap) {void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr;
@@ -839,8 +847,7 @@ static void ahci_error_intr(struct ata_p }if (irq_stat & (PORT_IRQ_CONNECT |PORT_IRQ_PHYRDY )) { - err_mask |=AC_ERR_ATA_BUS ; - action |=ATA_EH_SOFTRESET ; +ata_ehi_hotplugged (ehi);ata_ehi_push_desc (ehi,", %s" , irq_stat &PORT_IRQ_CONNECT ?"connection status changed" :"PHY RDY changed" ); }
@@ -1027,7 +1034,7 @@ static void ahci_error_handler(struct at }/* perform recovery */ -ata_do_eh (ap, ata_std_prereset, ahci_softreset, ahci_hardreset, +ata_do_eh (ap, ahci_prereset, ahci_softreset, ahci_hardreset, ahci_postreset); }
Signature · 1 line
1.3.2
Re: [PATCH 10/13] ahci: convert to new probing mechanism and add hotplug support
Quoted 8 lines · Tejun Heo
Convert to new probing mechanism and add hotplug support by enabling
PORT_IRQ_PHYRDY, marking ehi for hotplug and scheduling EH on CONNECT/PHYRDY interrupts.Unfortunately, ahci cannot reliably wait for the first FIS34 after hotplug. It sometimes succeeds but times out more often than not, so
ATA_FLAG_CANT_WAIT_FIS34is used.
Quoted 6 lines
This patch also fixes
ahci_hardreset()such that D2H Register FIS RX area is cleared before issuing COMRESET. Without this,ata_busy_sleep()after COMRESET might prematually finish if the previous TF contains DRDY && !BSY.Signed-off-by Tejun Heo <[email protected]>
NAK all mention of FIS34, ACK everything else
PATCH 11/13 sata_sil24: convert to new probing mechanism and add hotplug support
In reply to Tejun HeoConvert to new probing mechanism and add hotplug support by enabling PORT_IRQ_PHYRDY_CHG, marking ehi for hotplug and scheduling EH on PORT_IRQ_PHYRDY_CHG or PORT_IRQ_DEV_XCHG.
Sil3124/32 family of controllers don't have any mechanism to wait for the first FIS34 after hotplug, so ATA_FLAG_CANT_WAIT_FIS34 is used.
---
drivers/scsi/sata_sil24.c | 27 ++++++++------------------- 1 files changed, 8 insertions(+), 19 deletions(-)
cea49da1f8d8278d477d8b82fc6ae0a4f195faae
drivers/scsi/sata_sil24.c +8 -19
@@ -159,7 +159,8 @@ enum {PORT_IRQ_SDB_NOTIFY = (1 <<11 ),/* SDB notify received */ DEF_PORT_IRQ =PORT_IRQ_COMPLETE |PORT_IRQ_ERROR | -PORT_IRQ_DEV_XCHG |PORT_IRQ_UNK_FIS , +PORT_IRQ_PHYRDY_CHG |PORT_IRQ_DEV_XCHG | +PORT_IRQ_UNK_FIS ,/* bits[27:16] are unmasked (raw) */ PORT_IRQ_RAW_SHIFT = 16,
@@ -228,7 +229,7 @@ enum {/* host flags */ SIL24_COMMON_FLAGS =ATA_FLAG_SATA |ATA_FLAG_NO_LEGACY |ATA_FLAG_MMIO |ATA_FLAG_PIO_DMA | -ATA_FLAG_NCQ , +ATA_FLAG_NCQ |ATA_FLAG_SKIP_D2H_BSY ,SIL24_FLAG_PCIX_IRQ_WOC = (1 <<24 ),/* IRQ loss errata on PCI-X */ IRQ_STAT_4PORTS = 0xf,
@@ -325,7 +326,6 @@ static u8 sil24_check_status(struct ata_static u32 sil24_scr_read (struct ata_port *ap,unsigned sc_reg);static void sil24_scr_write (struct ata_port *ap,unsigned sc_reg,u32 val);static void sil24_tf_read (struct ata_port *ap,struct ata_taskfile *tf); -static int sil24_probe_reset (struct ata_port *ap,unsigned int *classes);static void sil24_qc_prep (struct ata_queued_cmd *qc);static unsigned int sil24_qc_issue (struct ata_queued_cmd *qc);static void sil24_irq_clear (struct ata_port *ap);
@@ -385,8 +385,6 @@ static const struct ata_port_operations .tf_read = sil24_tf_read, - .probe_reset = sil24_probe_reset, - .qc_prep = sil24_qc_prep, .qc_issue = sil24_qc_issue,
@@ -635,13 +633,6 @@ static int sil24_hardreset(struct ata_poreturn -EIO ; } -static int sil24_probe_reset (struct ata_port *ap,unsigned int *classes) -{ -return ata_drive_probe_reset (ap, ata_std_probeinit, - sil24_softreset, sil24_hardreset, - ata_std_postreset, classes); -} -static inline void sil24_fill_sg (struct ata_queued_cmd *qc,struct sil24_sge *sge) {
@@ -772,13 +763,11 @@ static void sil24_error_intr(struct ata_ata_ehi_push_desc (ehi,"irq_stat 0x%08x" , irq_stat); -if (irq_stat &PORT_IRQ_DEV_XCHG ) { - ehi->err_mask |=AC_ERR_ATA_BUS ; -/* sil24 doesn't recover very well from phy -* disconnection with a softreset. Force hardreset. -*/ - ehi->action |=ATA_EH_HARDRESET ; -ata_ehi_push_desc (ehi,", device_exchanged" ); +if (irq_stat & (PORT_IRQ_PHYRDY_CHG |PORT_IRQ_DEV_XCHG )) { +ata_ehi_hotplugged (ehi); +ata_ehi_push_desc (ehi,", %s" , + irq_stat &PORT_IRQ_PHYRDY_CHG ? +"PHY RDY changed" :"device exchanged" ); freeze =1 ; }
Signature · 1 line
1.3.2
Re: [PATCH 11/13] sata_sil24: convert to new probing mechanism and add hotplug support
Quoted 8 lines · Tejun Heo
Convert to new probing mechanism and add hotplug support by enabling
PORT_IRQ_PHYRDY_CHG, marking ehi for hotplug and scheduling EH onPORT_IRQ_PHYRDY_CHGorPORT_IRQ_DEV_XCHG.Sil3124/32 family of controllers don't have any mechanism to wait for the first FIS34 after hotplug, so
ATA_FLAG_CANT_WAIT_FIS34is used.Signed-off-by Tejun Heo <[email protected]>
same comment as before. "FIS34" string must die :)
PATCH 12/13 libata-hp: killl ops->probe_reset
In reply to Tejun HeoNow that all drivers implementing new EH are converted to new probing mechanism, ops->probe_reset doesn't have any user. Kill it.
---
drivers/scsi/libata-core.c | 187 +++----------------------------------------- include/linux/libata.h | 8 -- 2 files changed, 13 insertions(+), 182 deletions(-)
9fb8ab9ef597845ec62798779071cf7a868b5fab
drivers/scsi/libata-core.c +13 -174
@@ -1479,31 +1479,21 @@ static int ata_bus_probe(struct ata_port down_xfermask =0 ;/* reset and determine device classes */ -for (i =0 ; i <ATA_MAX_DEVICES ; i++) - classes[i] =ATA_DEV_UNKNOWN ; + ap->ops->phy_reset (ap); -if (ap->ops->probe_reset) { - rc = ap->ops->probe_reset (ap, classes); -if (rc) { -ata_port_printk (ap,KERN_ERR , -"reset failed (errno=%d)\n" , rc); -return rc; - } - }else { - ap->ops->phy_reset (ap); +for (i =0 ; i <ATA_MAX_DEVICES ; i++) { + dev = &ap->device[i]; -for (i =0 ; i <ATA_MAX_DEVICES ; i++) { -if (!(ap->flags &ATA_FLAG_DISABLED )) - classes[i] = ap->device[i].class; - ap->device[i].class =ATA_DEV_UNKNOWN ; - } +if (!(ap->flags &ATA_FLAG_DISABLED ) && + dev->class !=ATA_DEV_UNKNOWN ) + classes[dev->devno] = dev->class; +else + classes[dev->devno] =ATA_DEV_NONE ; -ata_port_probe (ap); + dev->class =ATA_DEV_UNKNOWN ; } -for (i =0 ; i <ATA_MAX_DEVICES ; i++) -if (classes[i] ==ATA_DEV_UNKNOWN ) - classes[i] =ATA_DEV_NONE ; +ata_port_probe (ap);/* after the reset the device state is PIO 0 and the controller state is undefined. Record the mode */
@@ -2605,37 +2595,11 @@ int ata_std_prereset(struct ata_port *ap }/** -* ata_std_probeinit - initialize probing -* @ap: port to be probed -* -* @ap is about to be probed. Initialize it. This function is -* to be used as standard callback for ata_drive_probe_reset(). -* -* NOTE!!! Do not use this function as probeinit if a low level -* driver implements only hardreset. Just pass NULL as probeinit -* in that case. Using this function is probably okay but doing -* so makes reset sequence different from the original -* ->phy_reset implementation and Jeff nervous. :-P -*/ -void ata_std_probeinit (struct ata_port *ap) -{ -static const unsigned long deb_timing[] = {5 ,100 ,5000 }; - -/* resume link */ -sata_phy_resume (ap, deb_timing); - -/* wait for device */ -if (ata_port_online (ap)) -ata_busy_sleep (ap,ATA_TMOUT_BOOT_QUICK ,ATA_TMOUT_BOOT ); -} - -/** * ata_std_softreset - reset host port via ATA SRST * @ap: port to reset * @classes: resulting classes of attached devices * -* Reset host port using ATA SRST. This function is to be used -* as standard callback for ata_drive_*_reset() functions. +* Reset host port using ATA SRST. * * LOCKING: * Kernel thread context (may sleep)
@@ -2690,8 +2654,6 @@ int ata_std_softreset(struct ata_port *a* @class: resulting class of attached device * * SATA phy-reset host port using DET bits of SControl register. -* This function is to be used as standard callback for -* ata_drive_*_reset(). * * LOCKING: * Kernel thread context (may sleep)
@@ -2770,9 +2732,6 @@ int sata_std_hardreset(struct ata_port ** the device might have been reset more than once using * different reset methods before postreset is invoked. * -* This function is to be used as standard callback for -* ata_drive_*_reset(). -* * LOCKING: * Kernel thread context (may sleep) */
@@ -2819,32 +2778,6 @@ void ata_std_postreset(struct ata_port *DPRINTK ("EXIT\n" ); } -/** -* ata_std_probe_reset - standard probe reset method -* @ap: prot to perform probe-reset -* @classes: resulting classes of attached devices -* -* The stock off-the-shelf ->probe_reset method. -* -* LOCKING: -* Kernel thread context (may sleep) -* -* RETURNS: -* 0 on success, -errno otherwise. -*/ -int ata_std_probe_reset (struct ata_port *ap,unsigned int *classes) -{ -ata_reset_fn_t hardreset; - - hardreset =NULL ; -if (sata_scr_valid (ap)) - hardreset = sata_std_hardreset; - -return ata_drive_probe_reset (ap, ata_std_probeinit, - ata_std_softreset, hardreset, - ata_std_postreset, classes); -} -int ata_do_reset (struct ata_port *ap,ata_reset_fn_t reset,unsigned int *classes) {
@@ -2874,97 +2807,6 @@ int ata_do_reset(struct ata_port *ap, at }/** -* ata_drive_probe_reset - Perform probe reset with given methods -* @ap: port to reset -* @probeinit: probeinit method (can be NULL) -* @softreset: softreset method (can be NULL) -* @hardreset: hardreset method (can be NULL) -* @postreset: postreset method (can be NULL) -* @classes: resulting classes of attached devices -* -* Reset the specified port and classify attached devices using -* given methods. This function prefers softreset but tries all -* possible reset sequences to reset and classify devices. This -* function is intended to be used for constructing ->probe_reset -* callback by low level drivers. -* -* Reset methods should follow the following rules. -* -* - Return 0 on sucess, -errno on failure. -* - If classification is supported, fill classes[] with -* recognized class codes. -* - If classification is not supported, leave classes[] alone. -* -* LOCKING: -* Kernel thread context (may sleep) -* -* RETURNS: -* 0 on success, -EINVAL if no reset method is avaliable, -ENODEV -* if classification fails, and any error code from reset -* methods. -*/ -int ata_drive_probe_reset (struct ata_port *ap,ata_probeinit_fn_t probeinit, -ata_reset_fn_t softreset,ata_reset_fn_t hardreset, -ata_postreset_fn_t postreset,unsigned int *classes) -{ -int rc = -EINVAL ; - -ata_eh_freeze_port (ap); - -if (probeinit) -probeinit (ap); - -if (softreset && !sata_set_spd_needed (ap)) { - rc =ata_do_reset (ap, softreset, classes); -if (rc ==0 && classes[0 ] !=ATA_DEV_UNKNOWN ) - goto done; -ata_port_printk (ap,KERN_INFO ,"softreset failed, " -"will try hardreset in 5 secs\n" ); -ssleep (5 ); - } - -if (!hardreset) - goto done; - -while (1 ) { - rc =ata_do_reset (ap, hardreset, classes); -if (rc ==0 ) { -if (classes[0 ] !=ATA_DEV_UNKNOWN ) - goto done; -break ; - } - -if (sata_down_spd_limit (ap)) - goto done; - -ata_port_printk (ap,KERN_INFO ,"hardreset failed, " -"will retry in 5 secs\n" ); -ssleep (5 ); - } - -if (softreset) { -ata_port_printk (ap,KERN_INFO , -"hardreset succeeded without classification, " -"will retry softreset in 5 secs\n" ); -ssleep (5 ); - - rc =ata_do_reset (ap, softreset, classes); - } - - done: -if (rc ==0 ) { -if (postreset) -postreset (ap, classes); - -ata_eh_thaw_port (ap); - -if (classes[0 ] ==ATA_DEV_UNKNOWN ) - rc = -ENODEV ; - } -return rc; -} - -/** * ata_dev_same_device - Determine whether new ID matches configured device * @dev: device to compare against * @new_class: class of the new device
@@ -5413,7 +5255,7 @@ static struct ata_port * ata_host_add(coDPRINTK ("ENTER\n" ); -if (!ent->port_ops->probe_reset && !ent->port_ops->error_handler && +if (!ent->port_ops->error_handler && !(ent->host_flags & (ATA_FLAG_SATA_RESET |ATA_FLAG_SRST ))) {printk (KERN_ERR "ata%u: no reset mechanism available\n" , port_no);
@@ -5551,7 +5393,7 @@ int ata_device_add(const struct ata_prob*/ } -if (!ap->ops->probe_reset) { +if (ap->ops->error_handler) {int bit =fls (ATA_FLAG_LOADING ) -1 ;unsigned long flags;
@@ -5993,13 +5835,10 @@ EXPORT_SYMBOL_GPL(sata_phy_resume);EXPORT_SYMBOL_GPL (sata_phy_reset);EXPORT_SYMBOL_GPL (__sata_phy_reset);EXPORT_SYMBOL_GPL (ata_bus_reset); -EXPORT_SYMBOL_GPL (ata_std_probeinit);EXPORT_SYMBOL_GPL (ata_std_prereset);EXPORT_SYMBOL_GPL (ata_std_softreset);EXPORT_SYMBOL_GPL (sata_std_hardreset);EXPORT_SYMBOL_GPL (ata_std_postreset); -EXPORT_SYMBOL_GPL (ata_std_probe_reset); -EXPORT_SYMBOL_GPL (ata_drive_probe_reset);EXPORT_SYMBOL_GPL (ata_dev_revalidate);EXPORT_SYMBOL_GPL (ata_dev_classify);EXPORT_SYMBOL_GPL (ata_dev_pair);
include/linux/libata.h +0 -8
@@ -302,7 +302,6 @@ struct ata_queued_cmd;/* typedefs */ typedef void (*ata_qc_cb_t ) (struct ata_queued_cmd *qc); -typedef void (*ata_probeinit_fn_t )(struct ata_port *ap);typedef int (*ata_prereset_fn_t )(struct ata_port *ap);typedef int (*ata_reset_fn_t )(struct ata_port *ap,unsigned int *classes);typedef void (*ata_postreset_fn_t )(struct ata_port *ap,unsigned int *classes);
@@ -551,7 +550,6 @@ struct ata_port_operations {void (*phy_reset) (struct ata_port *ap);/* obsolete */ void (*set_mode) (struct ata_port *ap); -int (*probe_reset) (struct ata_port *ap,unsigned int *classes);void (*post_set_mode) (struct ata_port *ap);
@@ -626,11 +624,6 @@ extern void ata_bus_reset(struct ata_porextern int sata_set_spd (struct ata_port *ap);extern int sata_phy_debounce (struct ata_port *ap,const unsigned long *param);extern int sata_phy_resume (struct ata_port *ap,const unsigned long *param); -extern int ata_drive_probe_reset (struct ata_port *ap, -ata_probeinit_fn_t probeinit, -ata_reset_fn_t softreset,ata_reset_fn_t hardreset, -ata_postreset_fn_t postreset,unsigned int *classes); -extern void ata_std_probeinit (struct ata_port *ap);extern int ata_std_prereset (struct ata_port *ap);extern int ata_std_softreset (struct ata_port *ap,unsigned int *classes);extern int sata_std_hardreset (struct ata_port *ap,unsigned int *class);
@@ -686,7 +679,6 @@ extern void ata_std_dev_select (struct aextern u8 ata_check_status (struct ata_port *ap);extern u8 ata_altstatus (struct ata_port *ap);extern void ata_exec_command (struct ata_port *ap,const struct ata_taskfile *tf); -extern int ata_std_probe_reset (struct ata_port *ap,unsigned int *classes);extern int ata_port_start (struct ata_port *ap);extern void ata_port_stop (struct ata_port *ap);extern void ata_host_stop (struct ata_host_set *host_set);
Signature · 1 line
1.3.2
PATCH 13/13 libata-hp: move ata_do_reset() to libata-eh.c
In reply to Tejun HeoWith ops->probe_init() gone, no user is left in libata-core.c. Move ata_do_reset() to libata-eh.c and make it static.
---
drivers/scsi/libata-core.c | 28 ---------------------------- drivers/scsi/libata-eh.c | 28 ++++++++++++++++++++++++++++ drivers/scsi/libata.h | 2 -- 3 files changed, 28 insertions(+), 30 deletions(-)
854a6e658abac125cb2dbe8d081448d9a76c166a
drivers/scsi/libata-core.c +0 -28
@@ -2778,34 +2778,6 @@ void ata_std_postreset(struct ata_port *DPRINTK ("EXIT\n" ); } -int ata_do_reset (struct ata_port *ap,ata_reset_fn_t reset, -unsigned int *classes) -{ -int i, rc; - -for (i =0 ; i <ATA_MAX_DEVICES ; i++) - classes[i] =ATA_DEV_UNKNOWN ; - - rc =reset (ap, classes); -if (rc) -return rc; - -/* If any class isn't ATA_DEV_UNKNOWN, consider classification -* is complete and convert all ATA_DEV_UNKNOWN to -* ATA_DEV_NONE. -*/ -for (i =0 ; i <ATA_MAX_DEVICES ; i++) -if (classes[i] !=ATA_DEV_UNKNOWN ) -break ; - -if (i <ATA_MAX_DEVICES ) -for (i =0 ; i <ATA_MAX_DEVICES ; i++) -if (classes[i] ==ATA_DEV_UNKNOWN ) - classes[i] =ATA_DEV_NONE ; - -return 0 ; -} -/** * ata_dev_same_device - Determine whether new ID matches configured device * @dev: device to compare against
drivers/scsi/libata-eh.c +28 -0
@@ -1316,6 +1316,34 @@ static void ata_eh_report(struct ata_por } } +static int ata_do_reset (struct ata_port *ap,ata_reset_fn_t reset, +unsigned int *classes) +{ +int i, rc; + +for (i =0 ; i <ATA_MAX_DEVICES ; i++) + classes[i] =ATA_DEV_UNKNOWN ; + + rc =reset (ap, classes); +if (rc) +return rc; + +/* If any class isn't ATA_DEV_UNKNOWN, consider classification +* is complete and convert all ATA_DEV_UNKNOWN to +* ATA_DEV_NONE. +*/ +for (i =0 ; i <ATA_MAX_DEVICES ; i++) +if (classes[i] !=ATA_DEV_UNKNOWN ) +break ; + +if (i <ATA_MAX_DEVICES ) +for (i =0 ; i <ATA_MAX_DEVICES ; i++) +if (classes[i] ==ATA_DEV_UNKNOWN ) + classes[i] =ATA_DEV_NONE ; + +return 0 ; +} +static int ata_eh_followup_srst_needed (int rc,int classify,const unsigned int *classes) {
drivers/scsi/libata.h +0 -2
@@ -57,8 +57,6 @@ extern int sata_down_spd_limit(struct atextern int sata_set_spd_needed (struct ata_port *ap);extern int ata_down_xfermask_limit (struct ata_device *dev,int force_pio0);extern int ata_set_mode (struct ata_port *ap,struct ata_device **r_failed_dev); -extern int ata_do_reset (struct ata_port *ap,ata_reset_fn_t reset, -unsigned int *classes);extern void ata_qc_free (struct ata_queued_cmd *qc);extern void ata_qc_issue (struct ata_queued_cmd *qc);extern void __ata_qc_complete (struct ata_queued_cmd *qc);
Signature · 1 line
1.3.2
Re: [PATCH 13/13] libata-hp: move ata_do_reset() to libata-eh.c
Quoted 4 lines · Tejun Heo
With
ops->probe_init()gone, no user is left inlibata-core.c. Moveata_do_reset()tolibata-eh.cand make it static.Signed-off-by Tejun Heo <[email protected]>
ACK 12-13