prep for hotplug support
PATCH 8/9 prep for hotplug support
Hello, all.
This is the first take of prep-for-hotplug-support patchset. As the name suggests, this patchset prepares libata for hotplug support. This patchset contains 15 patches.
#01-02 update sata_sil (hotplug related constants, new interrupt handler)
#03-04 misc libata preps
#05-12 prepare ata_bus_probe()
#13-15 hotplug flags, extra fields, hotplug_wq
This patchset is against
upstream (c2a6585296009379e0f4eff39cdcb108b457ebf2)
+ [1] misc-reset-updates patchset (repost)
+ [2] implement-and-use-ata_wait_register patchset (repost)
+ [3] misc-ata_bus_probe-updates patchset
+ [4] fixes-errata-workaround-and-reset-updates patchset, take 2
+ [5] implement-scsi_eh_schedule patchset
+ [6] fix-scsi_kill_request-busy-count-handling patch
+ [7] new-EH-framework patchset, take 2
+ [8] new-EH-implementation patchset, take 2
+ [9] add-NCQ-support, take 2
Thanks.
--
tejun
[1] http://article.gmane.org/gmane.linux.ide/9495
[2] http://article.gmane.org/gmane.linux.ide/9499
[3] http://article.gmane.org/gmane.linux.ide/9506
[4] http://article.gmane.org/gmane.linux.ide/9516
[5] http://article.gmane.org/gmane.linux.ide/9290
[6] http://article.gmane.org/gmane.linux.ide/9487
[7] http://article.gmane.org/gmane.linux.ide/9524
[8] http://article.gmane.org/gmane.linux.ide/9540
[9] http://article.gmane.org/gmane.linux.ide/9555
PATCH 1/13 libata-hp: separate out __ata_scsi_find_dev()
Separate out __ata_scsi_find_dev() from ata_scsi_find_dev(). The underscored version doesn't check whether the ATA device is enabled and useuable. It unconditionally returns the associated ATA device if channel/id/lun is valid. This function will be used by hotplug.
---
drivers/scsi/libata-scsi.c | 31 ++++++++++++++++--------------- 1 files changed, 16 insertions(+), 15 deletions(-)
ec6e2517ec4dd32773cfed7e8d8ad3e559509d51
drivers/scsi/libata-scsi.c +16 -15
@@ -52,8 +52,9 @@#define SECTOR_SIZE 512typedef unsigned int (*ata_xlat_func_t )(struct ata_queued_cmd *qc,const u8 *scsicmd); -static struct ata_device * -ata_scsi_find_dev (struct ata_port *ap,const struct scsi_device *scsidev); + +static struct ata_device *__ata_scsi_find_dev (struct ata_port *ap, +const struct scsi_device *scsidev);#define RW_RECOVERY_MPAGE 0x1#define RW_RECOVERY_MPAGE_LEN 12
@@ -2317,6 +2318,17 @@ static unsigned int atapi_xlat(struct atreturn 0 ; } +static struct ata_device * +__ata_scsi_find_dev (struct ata_port *ap,const struct scsi_device *scsidev) +{ +/* skip commands not addressed to targets we simulate */ +if (likely (scsidev->id <ATA_MAX_DEVICES && + scsidev->channel ==0 && scsidev->lun ==0 )) +return &ap->device[scsidev->id]; + +return NULL ; +} +/** * ata_scsi_find_dev - lookup ata_device from scsi_cmnd * @ap: ATA port to which the device is attached
@@ -2333,23 +2345,12 @@ static unsigned int atapi_xlat(struct at* RETURNS: * Associated ATA device, or %NULL if not found. */ -static struct ata_device *ata_scsi_find_dev (struct ata_port *ap,const struct scsi_device *scsidev) { -struct ata_device *dev; - -/* skip commands not addressed to targets we simulate */ -if (likely (scsidev->id <ATA_MAX_DEVICES )) - dev = &ap->device[scsidev->id]; -else -return NULL ; - -if (unlikely ((scsidev->channel !=0 ) || - (scsidev->lun !=0 ))) -return NULL ; +struct ata_device *dev =__ata_scsi_find_dev (ap, scsidev); -if (unlikely (!ata_dev_enabled (dev))) +if (unlikely (!dev || !ata_dev_enabled (dev)))return NULL ;if (!atapi_enabled || (ap->flags &ATA_FLAG_NO_ATAPI )) {
Signature · 1 line
1.2.4
PATCH 2/13 libata-hp: add more SERR_* constants in preparation for hotplug support
In reply to Tejun HeoAdd PHY status related SERR_* constants in preparation for hotplug support.
---
include/linux/ata.h | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-)
55f539ff11bacd214ae47e1f0e7ea8d57869dc76
include/linux/ata.h +2 -0
@@ -208,6 +208,8 @@ enum {SERR_PERSISTENT = (1 <<9 ),/* persistent data/comm error */ SERR_PROTOCOL = (1 <<10 ),/* protocol violation */ SERR_INTERNAL = (1 <<11 ),/* host internal error */ +SERR_PHYRDY_CHG = (1 <<16 ),/* PHY RDY changed */ +SERR_DEV_XCHG = (1 <<26 ),/* device exchanged */ /* struct ata_taskfile flags */ ATA_TFLAG_LBA48 = (1 << 0), /* enable 48-bit LBA and "HOB" */
Signature · 1 line
1.2.4
PATCH 3/13 libata-hp: implement ata_dev_init()
In reply to Tejun HeoMove initialization of struct ata_device into ata_dev_init() in preparation for hotplug. This patch calls ata_dev_init() from ata_host_init() and thus makes no functional difference.
---
drivers/scsi/libata-core.c | 28 ++++++++++++++++++++++------ 1 files changed, 22 insertions(+), 6 deletions(-)
442eed97d84e43eb0860e19398c508c4a02c2860
drivers/scsi/libata-core.c +22 -6
@@ -1433,6 +1433,27 @@ err_out_nosup: }/** +* ata_dev_init - Initialize an ata_device structure +* @ap: ATA port device to initialize is attached to +* @dev: Device structure to initialize +* +* Initialize @dev in preparation for probing. +* +* LOCKING: +* Inherited from caller. +*/ +static void ata_dev_init (struct ata_port *ap,struct ata_device *dev) +{ +memset ((void *)dev +ATA_DEVICE_CLEAR_OFFSET ,0 , +sizeof (*dev) -ATA_DEVICE_CLEAR_OFFSET ); + dev->devno = dev - ap->device; + dev->pio_mask =UINT_MAX ; + dev->mwdma_mask =UINT_MAX ; + dev->udma_mask =UINT_MAX ; +ata_ering_init (&dev->ering,ATA_DEV_ERING_SIZE ); +} + +/** * ata_bus_probe - Reset and probe ATA bus * @ap: Bus to probe *
@@ -4828,7 +4849,6 @@ static void ata_host_remove(struct ata_p* LOCKING: * Inherited from caller. */ -static void ata_host_init (struct ata_port *ap,struct Scsi_Host *host,struct ata_host_set *host_set,const struct ata_probe_ent *ent,unsigned int port_no)
@@ -4865,11 +4885,7 @@ static void ata_host_init(struct ata_porfor (i =0 ; i <ATA_MAX_DEVICES ; i++) {struct ata_device *dev = &ap->device[i]; - dev->devno = i; - dev->pio_mask =UINT_MAX ; - dev->mwdma_mask =UINT_MAX ; - dev->udma_mask =UINT_MAX ; -ata_ering_init (&dev->ering,ATA_DEV_ERING_SIZE ); +ata_dev_init (ap, dev); }#ifdef ATA_IRQ_TRAP
Signature · 1 line
1.2.4
PATCH 4/13 libata-hp: make some fields of ata_device persistent
In reply to Tejun HeoLifetimes of some fields span over device plugging/unplugging. This patch moves such persistent fields to the top of ata_device and separate them with ATA_DEVICE_CLEAR_OFFSET. Fields above the offset are initialized once during host initializatino while all other fields are cleared before hotplugging. Currently only dev->devno is persistent.
---
drivers/scsi/libata-core.c | 2 +- include/linux/libata.h | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-)
9160b11ebb15ef4f9501a1aba807ed221ef713ed
drivers/scsi/libata-core.c +1 -1
@@ -1446,7 +1446,6 @@ static void ata_dev_init(struct ata_port {memset ((void *)dev +ATA_DEVICE_CLEAR_OFFSET ,0 ,sizeof (*dev) -ATA_DEVICE_CLEAR_OFFSET ); - dev->devno = dev - ap->device; dev->pio_mask =UINT_MAX ; dev->mwdma_mask =UINT_MAX ; dev->udma_mask =UINT_MAX ;
@@ -4885,6 +4884,7 @@ static void ata_host_init(struct ata_porfor (i =0 ; i <ATA_MAX_DEVICES ; i++) {struct ata_device *dev = &ap->device[i]; + dev->devno = i;ata_dev_init (ap, dev); }
include/linux/libata.h +4 -1
@@ -395,10 +395,11 @@ struct ata_ering {struct ata_ering_entry name_entries[size];struct ata_device { +unsigned int devno;/* 0 or 1 */ +/* fields above n_sectors are not cleared across device init */ u64 n_sectors;/* size of device, if ATA */ unsigned long flags;/* ATA_DFLAG_xxx */ unsigned int class;/* ATA_DEV_xxx */ -unsigned int devno;/* 0 or 1 */ u16 *id;/* IDENTIFY xxx DEVICE data */ u8 pio_mode;u8 dma_mode;
@@ -423,6 +424,8 @@ struct ata_device {DEFINE_ATA_ERING (ering,ATA_DEV_ERING_SIZE ); }; +#define ATA_DEVICE_CLEAR_OFFSET offsetof(struct ata_device, n_sectors) +struct ata_port {struct Scsi_Host *host;/* our co-allocated scsi host */ const struct ata_port_operations *ops;
Signature · 1 line
1.2.4
PATCH 6/13 libata-hp: prepare for persistent device flags
In reply to Tejun HeoThis patch makes dev->flags persistent, defines ATA_DFLAG_INIT_MASK as lower 16 bits of device flags and clear them in ata_dev_init(). So, device flags in bits [0:15] are cleared over hotplugging while flags from bit 16 upward are maintained.
---
drivers/scsi/libata-core.c | 2 ++ include/linux/libata.h | 3 ++- 2 files changed, 4 insertions(+), 1 deletions(-)
3a7b8630e4c5cc409562164a941b40bc2b6b8728
drivers/scsi/libata-core.c +2 -0
@@ -1444,6 +1444,8 @@ err_out_nosup:*/ static void ata_dev_init (struct ata_port *ap,struct ata_device *dev) { + dev->flags &= ~ATA_DFLAG_INIT_MASK ; +memset ((void *)dev +ATA_DEVICE_CLEAR_OFFSET ,0 ,sizeof (*dev) -ATA_DEVICE_CLEAR_OFFSET ); dev->pio_mask =UINT_MAX ;
include/linux/libata.h +2 -1
@@ -128,6 +128,7 @@ enum {ATA_DFLAG_PIO = (1 <<8 ),/* device currently in PIO mode */ ATA_DFLAG_FAILED = (1 <<9 ),/* device has failed */ +ATA_DFLAG_INIT_MASK = (1 <<16 ) -1 ,ATA_DEV_UNKNOWN =0 ,/* unknown device */ ATA_DEV_ATA = 1, /* ATA device */
@@ -396,9 +397,9 @@ struct ata_ering {struct ata_device {unsigned int devno;/* 0 or 1 */ +unsigned long flags;/* ATA_DFLAG_xxx */ /* fields above n_sectors are not cleared across device init */ u64 n_sectors;/* size of device, if ATA */ -unsigned long flags;/* ATA_DFLAG_xxx */ unsigned int class;/* ATA_DEV_xxx */ u16 *id;/* IDENTIFY xxx DEVICE data */ u8 pio_mode;
Signature · 1 line
1.2.4
PATCH 10/13 libata-hp: make ata_bus_probe() extern
In reply to Tejun HeoMake ata_bus_probe() extern and put its prototype in libata private header file. It will be called from libata-eh.c.
---
drivers/scsi/libata-core.c | 2 +- drivers/scsi/libata.h | 1 + 2 files changed, 2 insertions(+), 1 deletions(-)
b0d71bd83fe780a3831d5a2414df632cd3f0aaf9
drivers/scsi/libata-core.c +1 -1
@@ -1473,7 +1473,7 @@ static void ata_dev_init(struct ata_port* the port has no enabled device after probing, or any negative * errno from ->probe_reset. */ -static int ata_bus_probe (struct ata_port *ap) +int ata_bus_probe (struct ata_port *ap) {int existing_dev_failed =0 ;unsigned int classes[ATA_MAX_DEVICES ];
drivers/scsi/libata.h +1 -0
@@ -43,6 +43,7 @@ struct ata_scsi_args {extern int atapi_enabled;extern int atapi_dmadir;extern int libata_fua; +extern int ata_bus_probe (struct ata_port *ap);extern struct ata_queued_cmd *ata_qc_new_init (struct ata_port *ap,struct ata_device *dev);extern int ata_rwcmd_protocol (struct ata_queued_cmd *qc);
Signature · 1 line
1.2.4
PATCH 5/13 libata-hp: call ata_dev_init() from ata_bus_probe()
In reply to Tejun HeoCall ata_dev_init() before actual probing instead of during host initialization. This is in preparation of hotplug.
---
drivers/scsi/libata-core.c | 12 +++++------- 1 files changed, 5 insertions(+), 7 deletions(-)
bc205de9459b473c8fef86b3f4e6e356aa9186fd
drivers/scsi/libata-core.c +5 -7
@@ -1466,7 +1466,6 @@ static void ata_dev_init(struct ata_port* RETURNS: * Zero on success, negative errno otherwise. */ -static int ata_bus_probe (struct ata_port *ap) {unsigned int classes[ATA_MAX_DEVICES ];
@@ -1476,8 +1475,10 @@ static int ata_bus_probe(struct ata_portata_port_probe (ap); -for (i =0 ; i <ATA_MAX_DEVICES ; i++) +for (i =0 ; i <ATA_MAX_DEVICES ; i++) { tries[i] =ATA_PROBE_MAX_TRIES ; +ata_dev_init (ap, &ap->device[i]); + } retry: down_xfermask =0 ;
@@ -4882,11 +4883,8 @@ static void ata_host_init(struct ata_porINIT_WORK (&ap->port_task,NULL ,NULL );INIT_LIST_HEAD (&ap->eh_done_q); -for (i =0 ; i <ATA_MAX_DEVICES ; i++) { -struct ata_device *dev = &ap->device[i]; - dev->devno = i; -ata_dev_init (ap, dev); - } +for (i =0 ; i <ATA_MAX_DEVICES ; i++) + ap->device[i].devno = i;#ifdef ATA_IRQ_TRAP ap->stats.unhandled_irq =1 ;
Signature · 1 line
1.2.4
PATCH 7/13 libata-hp: implement ap->orig_sata_spd_limit
In reply to Tejun HeoAdd ap->orig_sata_spd_limit and initialize it once during the boot initialization (or driver load initialization). ap->sata_spd_limit is reset to ap->orig_sata_spd_limit on hotplug. This prevents limits introduced by earlier devices from affecting new devices.
---
drivers/scsi/libata-core.c | 20 ++++++++++++-------- include/linux/libata.h | 1 + 2 files changed, 13 insertions(+), 8 deletions(-)
37d8c01b360760e0c22e5cede70921c116c21ad4
drivers/scsi/libata-core.c +12 -8
@@ -1444,6 +1444,9 @@ err_out_nosup:*/ static void ata_dev_init (struct ata_port *ap,struct ata_device *dev) { +/* for now, SATA spd limit is bound to the first device */ + ap->sata_spd_limit = ap->orig_sata_spd_limit; + dev->flags &= ~ATA_DFLAG_INIT_MASK ; memset((void *)dev + ATA_DEVICE_CLEAR_OFFSET, 0,
@@ -2503,17 +2506,10 @@ static int sata_phy_resume(struct ata_povoid ata_std_probeinit (struct ata_port *ap) {if ((ap->flags &ATA_FLAG_SATA ) && ap->ops->scr_read) { -u32 spd; -/* set cable type and resume link */ ap->cbl =ATA_CBL_SATA ;sata_phy_resume (ap); -/* init sata_spd_limit to the current value */ - spd = (scr_read (ap,SCR_CONTROL ) &0xf0 ) >>4 ; -if (spd) - ap->sata_spd_limit &= (1 << spd) -1 ; -/* wait for device */ if (sata_dev_present (ap))ata_busy_sleep (ap,ATA_TMOUT_BOOT_QUICK ,ATA_TMOUT_BOOT );
@@ -4878,7 +4874,7 @@ static void ata_host_init(struct ata_por ap->flags |= ent->host_flags; ap->ops = ent->port_ops; ap->cbl =ATA_CBL_NONE ; - ap->sata_spd_limit =UINT_MAX ; + ap->orig_sata_spd_limit =UINT_MAX ; ap->active_tag =ATA_TAG_POISON ; ap->last_ctl =0xFF ;
@@ -5037,6 +5033,14 @@ int ata_device_add(const struct ata_prob ap = host_set->ports[i]; +/* init ap->orig_sata_spd_limit to boot value */ +if ((ap->flags &ATA_FLAG_SATA ) && ap->ops->scr_read) { +u32 spd; + spd = (scr_read (ap,SCR_CONTROL ) &0xf0 ) >>4 ; +if (spd) + ap->orig_sata_spd_limit &= (1 << spd) -1 ; + } +DPRINTK ("ata%u: bus probe begin\n" , ap->id); rc =ata_bus_probe (ap);DPRINTK ("ata%u: bus probe end\n" , ap->id);
include/linux/libata.h +1 -0
@@ -449,6 +449,7 @@ struct ata_port {unsigned int mwdma_mask;unsigned int udma_mask;unsigned int cbl;/* cable type; ATA_CBL_xxx */ +unsigned int orig_sata_spd_limit;/* boot value */ unsigned int sata_spd_limit;/* SATA PHY speed limit */ struct ata_device device[ATA_MAX_DEVICES ];
Signature · 1 line
1.2.4
PATCH 9/13 libata-hp: prepare ata_bus_probe() for hotplug
In reply to Tejun HeoUpdate ata_bus_probe() such that it probes only for ATA_DEV_UNKNOWN devices, ignore errors from already existing devices and return 1 in such cases. This is in preparation for hotplug.
---
drivers/scsi/libata-core.c | 37 +++++++++++++++++++++++++++++-------- 1 files changed, 29 insertions(+), 8 deletions(-)
57aed4a29833e54263afce342e44361642a6b8a0
drivers/scsi/libata-core.c +29 -8
@@ -1469,18 +1469,24 @@ static void ata_dev_init(struct ata_port* PCI/etc. bus probe sem. * * RETURNS: -* Zero on success, negative errno otherwise. +* Zero on success, one if any existing device failed, -ENODEV if +* the port has no enabled device after probing, or any negative +* errno from ->probe_reset. */ static int ata_bus_probe (struct ata_port *ap) { +int existing_dev_failed =0 ;unsigned int classes[ATA_MAX_DEVICES ];int tries[ATA_MAX_DEVICES ];int i, rc, down_xfermask;struct ata_device *dev;for (i =0 ; i <ATA_MAX_DEVICES ; i++) { - tries[i] =ATA_PROBE_MAX_TRIES ; -ata_dev_init (ap, &ap->device[i]); +if (ap->device[i].class ==ATA_DEV_UNKNOWN ) { + tries[i] =ATA_PROBE_MAX_TRIES ; +ata_dev_init (ap, &ap->device[i]); + }else + tries[i] =-1 ; } retry:
@@ -1514,6 +1520,16 @@ static int ata_bus_probe(struct ata_portfor (i =0 ; i <ATA_MAX_DEVICES ; i++) { dev = &ap->device[i]; +/* Existing devices are EH's responsitbilities. Just +* revalidate them. +*/ +if (tries[i] <0 ) { +if (ata_dev_enabled (dev)) +if (ata_dev_revalidate (ap, dev,1 )) + existing_dev_failed =1 ; +continue ; + } +if (tries[i]) dev->class = classes[i];
@@ -1547,14 +1563,19 @@ static int ata_bus_probe(struct ata_port rc =ata_set_mode (ap, &dev);if (rc) { - down_xfermask =1 ; - goto fail; +if (tries[dev->devno] <0 ) { + existing_dev_failed =1 ; + }else { + down_xfermask =1 ; + goto fail; + } } + rc = -ENODEV ;for (i =0 ; i <ATA_MAX_DEVICES ; i++)if (ata_dev_enabled (&ap->device[i])) -return 0 ; -return -ENODEV ; + rc =0 ; +return existing_dev_failed ?1 : rc; fail:switch (rc) {
@@ -5041,7 +5062,7 @@ int ata_device_add(const struct ata_prob rc =ata_bus_probe (ap);DPRINTK ("ata%u: bus probe end\n" , ap->id); -if (rc && !ap->ops->error_handler) { +if (rc <0 && !ap->ops->error_handler) {/* no device attached and no hotplug support */ ata_port_disable (ap); ap->ops->port_disable (ap);
Signature · 1 line
1.2.4
PATCH 11/13 libata-hp: add hotplug flags and flag handling functions
In reply to Tejun HeoAdd ap->hotplug_flags field, define ATA_HOTPLUG_*, ATA_DFLAG_DETACH_* and flag manipulation functions.
As ap->hotplug_flags will be accessed by EH and SCSI hotplug work simultaneosly, changes should be atomic. Define functions to manipulate ap->hostplug_flags - ata_set_hotplug_flags(), ata_clr_hotplug_flags() and ata_schedule_probe(), which is a shortcut for setting ATA_HOTPLUG_PROBE, a common operation for LLDDs.
---
include/linux/libata.h | 37 ++++++++++++++++++++++++++++++++++++- 1 files changed, 36 insertions(+), 1 deletions(-)
a0d2a754a788df7a123013480a3295d0c61c0940
include/linux/libata.h +36 -1
@@ -130,6 +130,9 @@ enum {ATA_DFLAG_FAILED = (1 <<9 ),/* device has failed */ ATA_DFLAG_INIT_MASK = (1 <<16 ) -1 , +ATA_DFLAG_DETACH_ATA = (1 <<16 ),/* detach ATA device */ +ATA_DFLAG_DETACH_SCSI = (1 <<17 ),/* detach SCSI device */ +ATA_DEV_UNKNOWN =0 ,/* unknown device */ ATA_DEV_ATA =1 ,/* ATA device */ ATA_DEV_ATA_UNSUP = 2, /* ATA device (unsupported) */
@@ -161,9 +164,15 @@ enum {ATA_FLAG_DISABLED = (1 <<19 ),/* port is disabled, ignore it */ ATA_FLAG_FROZEN = (1 <<20 ),/* port is frozen */ ATA_FLAG_SUSPENDED = (1 <<21 ),/* port is suspended (power) */ -/* bits 24:31 of ap->flags are reserved for LLDD specific flags */ +/* struct ata_port hotplug_flags */ +ATA_HOTPLUG_RUNNING = (1 <<0 ),/* hotplugging online */ +ATA_HOTPLUG_PROBE = (1 <<1 ),/* probe requested */ +ATA_HOTPLUG_DID_PROBE = (1 <<2 ),/* already probed in this run */ +ATA_HOTPLUG_SCSI_PLUG = (1 <<3 ),/* SCSI hotplug scheduled */ +ATA_HOTPLUG_SCSI_UNPLUG = (1 <<4 ),/* SCSI hotunplug scheduled */ +/* struct ata_queued_cmd flags */ ATA_QCFLAG_ACTIVE = (1 <<0 ),/* cmd not yet ack'd to scsi lyer */ ATA_QCFLAG_SG = (1 << 1), /* have s/g table? */
@@ -471,6 +480,8 @@ struct ata_port {u32 msg_enable;struct list_head eh_done_q; +unsigned long hotplug_flags; +void *private_data; };
@@ -800,6 +811,30 @@ static inline unsigned int ata_dev_absenreturn ata_class_absent (dev->class); } +/* hotplug flag manipulation helpers */ +static inline void ata_set_hotplug_flags (struct ata_port *ap, +unsigned int flags) +{ +unsigned long old; +do { + old = ap->hotplug_flags; + }while (cmpxchg (&ap->hotplug_flags, old, old | flags) != old); +} + +static inline void ata_clr_hotplug_flags (struct ata_port *ap, +unsigned int flags) +{ +unsigned long old; +do { + old = ap->hotplug_flags; + }while (cmpxchg (&ap->hotplug_flags, old, old & ~flags) != old); +} + +static inline void ata_schedule_probe (struct ata_port *ap) +{ +ata_set_hotplug_flags (ap,ATA_HOTPLUG_PROBE ); +} +static inline u8 ata_chk_status (struct ata_port *ap) {return ap->ops->check_status (ap);
Signature · 1 line
1.2.4
PATCH 12/13 libata-hp: store attached SCSI device
In reply to Tejun HeoAdd device persistent field dev->sdev and store the attached SCSI device. With hotplug, libata needs to know the attached SCSI device to offline and detach it, but scsi_device_lookup() cannot be used because libata will reuse SCSI ID numbers - dead but not gone devices (due to zombie opens, etc...) interfere with the lookup.
dev->sdev doesn't hold reference to the SCSI device. dev->sdev is cleared when the SCSI device goes away.
---
drivers/scsi/libata-scsi.c | 14 ++++++++++---- include/linux/libata.h | 1 + 2 files changed, 11 insertions(+), 4 deletions(-)
784f79074e0ab0441363c7a87d1b93d6d11ac437
drivers/scsi/libata-scsi.c +10 -4
@@ -2740,17 +2740,23 @@ void ata_scsi_simulate(struct ata_port *void ata_scsi_scan_host (struct ata_port *ap) { -struct ata_device *dev;unsigned int i;if (ap->flags &ATA_FLAG_DISABLED )return ;for (i =0 ; i <ATA_MAX_DEVICES ; i++) { - dev = &ap->device[i]; +struct ata_device *dev = &ap->device[i]; -if (ata_dev_enabled (dev)) -scsi_scan_target (&ap->host->shost_gendev,0 , i,0 ,0 ); +if (ata_dev_enabled (dev) && dev->sdev ==NULL ) { +struct scsi_device *sdev; + + sdev =__scsi_add_device (ap->host,0 , i,0 ,NULL ); +if (!IS_ERR (sdev)) { + dev->sdev = sdev; +scsi_device_put (sdev); + } + } } }
include/linux/libata.h +1 -0
@@ -407,6 +407,7 @@ struct ata_ering {struct ata_device {unsigned int devno;/* 0 or 1 */ unsigned long flags;/* ATA_DFLAG_xxx */ +struct scsi_device *sdev;/* attached SCSI device */ /* fields above n_sectors are not cleared across device init */ u64 n_sectors;/* size of device, if ATA */ unsigned int class;/* ATA_DEV_xxx */
Signature · 1 line
1.2.4
PATCH 8/13 libata-hp: move device enable/disable out of ata_bus_probe()
In reply to Tejun HeoFor drivers support hot/warm plugging, the controller should stay enabled whether devices are attached to it or not. Move ata_port_probe() and disable calls out of ata_bus_probe() and disable only if the driver doesn't implement new style ->error_handler, which is responsible for hotplug.
While at it, kill the FIXME about controllers with no device attached. Hotplug is coming and all drivers should support it in not so distant future.
---
drivers/scsi/libata-core.c | 19 ++++++------------- 1 files changed, 6 insertions(+), 13 deletions(-)
84a5e767247a9a0047e4b485fbd9de7582d9b283
drivers/scsi/libata-core.c +6 -13
@@ -1478,8 +1478,6 @@ static int ata_bus_probe(struct ata_portint i, rc, down_xfermask;struct ata_device *dev; -ata_port_probe (ap); -for (i =0 ; i <ATA_MAX_DEVICES ; i++) { tries[i] =ATA_PROBE_MAX_TRIES ;ata_dev_init (ap, &ap->device[i]);
@@ -1556,10 +1554,6 @@ static int ata_bus_probe(struct ata_portfor (i =0 ; i <ATA_MAX_DEVICES ; i++)if (ata_dev_enabled (&ap->device[i]))return 0 ; - -/* no device present, disable port */ -ata_port_disable (ap); - ap->ops->port_disable (ap);return -ENODEV ; fail:
@@ -5033,6 +5027,8 @@ int ata_device_add(const struct ata_prob ap = host_set->ports[i]; +ata_port_probe (ap); +/* init ap->orig_sata_spd_limit to boot value */ if ((ap->flags &ATA_FLAG_SATA ) && ap->ops->scr_read) {u32 spd;
@@ -5045,13 +5041,10 @@ int ata_device_add(const struct ata_prob 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. -*/ +if (rc && !ap->ops->error_handler) { +/* no device attached and no hotplug support */ +ata_port_disable (ap); + ap->ops->port_disable (ap); } rc =scsi_add_host (ap->host, dev);
Signature · 1 line
1.2.4
PATCH 13/13 libata-hp: add ata_hotplug_wq
In reply to Tejun HeoIt's best to run ATA hotplug from EH but attaching SCSI devices needs working EH. ata_hotplug_wq is used to give SCSI hotplug operations a separate context.
---
drivers/scsi/libata-core.c | 9 +++++++++ drivers/scsi/libata.h | 1 + 2 files changed, 10 insertions(+), 0 deletions(-)
1438492c4408fc908d3fb5865fd56231360a2fcd
drivers/scsi/libata-core.c +9 -0
@@ -72,6 +72,8 @@ static void ata_dev_xfermask(struct ata_static unsigned int ata_unique_id =1 ;static struct workqueue_struct *ata_wq; +struct workqueue_struct *ata_hotplug_wq; +int atapi_enabled =1 ;module_param (atapi_enabled, int,0444 );MODULE_PARM_DESC (atapi_enabled,"Enable discovery of ATAPI devices (0=off, 1=on)" );
@@ -5300,6 +5302,12 @@ static int __init ata_init(void)if (!ata_wq)return -ENOMEM ; + ata_hotplug_wq =create_workqueue ("ata_hotplug" ); +if (!ata_hotplug_wq) { +destroy_workqueue (ata_wq); +return -ENOMEM ; + } +printk (KERN_DEBUG "libata version " DRV_VERSION " loaded.\n" );return 0 ; }
@@ -5307,6 +5315,7 @@ static int __init ata_init(void) static void __exit ata_exit(void) {destroy_workqueue (ata_wq); +destroy_workqueue (ata_hotplug_wq); }module_init (ata_init);
drivers/scsi/libata.h +1 -0
@@ -40,6 +40,7 @@ struct ata_scsi_args { };/* libata-core.c */ +extern struct workqueue_struct *ata_hotplug_wq;extern int atapi_enabled;extern int atapi_dmadir;extern int libata_fua;
Signature · 1 line
1.2.4
Quoted 3 lines · Tejun Heo
This is the first take of prep-for-hotplug-support patchset. As the name suggests, this patchset prepares libata for hotplug support. This patchset contains 15 patches.
13 patches, obviously. :/
Quoted 1 line
#01-02 update
sata_sil(hotplug related constants, new interrupt handler)
These two are moved to the next patchset right before sata_sil hotplug update at the last minutes and I forgot to update the head message. Sorry.
Quoted 3 lines
#03-04 misc libata preps
#05-12 prepareata_bus_probe()
#13-15 hotplug flags, extra fields,hotplug_wq
Signature · 1 line
tejun
Re: [PATCH 13/13] libata-hp: add ata_hotplug_wq
In reply to Tejun HeoQuoted 17 lines · Tejun Heo
1438492c4408fc908d3fb5865fd56231360a2fcddrivers/scsi/libata-core.c +2
-0@@ -72,6 +72,8 @@ static void ata_dev_xfermask(struct ata_static unsigned int ata_unique_id =1 ;static struct workqueue_struct *ata_wq; +struct workqueue_struct *ata_hotplug_wq; +int atapi_enabled =1 ;module_param (atapi_enabled, int,0444 );MODULE_PARM_DESC (atapi_enabled,"Enable discovery of ATAPI devices (0=off, 1=on)" );@@ -5300,6 +5302,12 @@ static int __init ata_init(void)if (!ata_wq)return -ENOMEM ;
drivers/scsi/libata-core.c static int __init ata_init(void) · line 5313
Quoted 10 lines
drivers/scsi/libata-core.c +6
-0+ ata_hotplug_wq =create_workqueue ("ata_hotplug" ); +if (!ata_hotplug_wq) { +destroy_workqueue (ata_wq); +return -ENOMEM ; + } +printk (KERN_DEBUG "libata version " DRV_VERSION " loaded.\n" );return 0 ; }
create_workqueue() creates one workqueue for each logic CPU in the system, so when loading libata.ko in a system with 8 CPU's 8 work queues for ata_hotplug will be created. Does it make sense to use create_singlethread_workqueue() to create only one workqueue for ata_hotplug since hotplug is not the operation happened with high frequency?
Thanks,
Forrest
Re: [PATCH 13/13] libata-hp: add ata_hotplug_wq
Quoted 19 lines · forrest
Quoted 18 lines · Tejun Heo
1438492c4408fc908d3fb5865fd56231360a2fcddrivers/scsi/libata-core.c +2
-0@@ -72,6 +72,8 @@ static void ata_dev_xfermask(struct ata_static unsigned int ata_unique_id =1 ;static struct workqueue_struct *ata_wq; +struct workqueue_struct *ata_hotplug_wq; +int atapi_enabled =1 ;module_param (atapi_enabled, int,0444 );MODULE_PARM_DESC (atapi_enabled,"Enable discovery of ATAPI devices (0=off, 1=on)" );@@ -5300,6 +5302,12 @@ static int __init ata_init(void)if (!ata_wq)return -ENOMEM ;
Quoted 17 lines
drivers/scsi/libata-core.c static int __init ata_init(void) · line 5313
Quoted 9 lines
drivers/scsi/libata-core.c +6
-0+ ata_hotplug_wq =create_workqueue ("ata_hotplug" ); +if (!ata_hotplug_wq) { +destroy_workqueue (ata_wq); +return -ENOMEM ; + } +printk (KERN_DEBUG "libata version " DRV_VERSION " loaded.\n" );return 0 ; }
create_workqueue()creates one workqueue for each logic CPU in the system, so when loading libata.ko in a system with 8 CPU's 8 work queues forata_hotplugwill be created. Does it make sense to usecreate_singlethread_workqueue()to create only one workqueue forata_hotplugsince hotplug is not the operation happened with high frequency?
Yeap, that makes a lot of sense. Will change to single threaded variant.
Thanks.
Signature · 1 line
tejun
Re: [PATCH 07/13] libata-hp: implement ap->orig_sata_spd_limit
In reply to Tejun HeoQuoted 6 lines · Tejun Heo
Add
ap->orig_sata_spd_limitand initialize it once during the boot initialization (or driver load initialization).ap->sata_spd_limitis reset toap->orig_sata_spd_limiton hotplug. This prevents limits introduced by earlier devices from affecting new devices.Signed-off-by Tejun Heo <[email protected]>
Rather than "orig_" call it "hw_" or similar. This is similar to the block layer's max_sectors and max_hw_sectors situation.
Jeff
Re: [PATCH 12/13] libata-hp: store attached SCSI device
In reply to Tejun HeoQuoted 10 lines · Tejun Heo
Add device persistent field
dev->sdevand store the attached SCSI device. With hotplug, libata needs to know the attached SCSI device to offline and detach it, butscsi_device_lookup()cannot be used because libata will reuse SCSI ID numbers - dead but not gone devices (due to zombie opens, etc...) interfere with the lookup.
dev->sdevdoesn't hold reference to the SCSI device.dev->sdevis cleared when the SCSI device goes away.Signed-off-by Tejun Heo <[email protected]>
ACK, though we'll have to revisit once libata supports direct use of block layer for ATA disks. But given other email it sounds like you are thinking about this already.
Jeff
Quoted 10 lines · Tejun Heo
Hello, all.
This is the first take of prep-for-hotplug-support patchset. As the name suggests, this patchset prepares libata for hotplug support. This patchset contains 15 patches.
#01-02 update
sata_sil(hotplug related constants, new interrupt handler)
#03-04 misc libata preps
#05-12 prepareata_bus_probe()
#13-15 hotplug flags, extra fields,hotplug_wq
ACK, modulo the minor comments just sent.
Also, in general libata needs a rethink when it comes to workqueues. Sometimes a single thread is more appropriate than the workqueue default of one-thread-per-CPU. Using workqueues in the default state is quite efficient, but can also given you a huge number of idle threads on a $BIGNUM CPU box. Workqueues on a 16-CPU box can be pretty insane...
Jeff
Re: [PATCH 07/13] libata-hp: implement ap->orig_sata_spd_limit
In reply to Jeff GarzikQuoted 10 lines · Jeff Garzik
Quoted 6 lines · Tejun Heo
Add
ap->orig_sata_spd_limitand initialize it once during the boot initialization (or driver load initialization).ap->sata_spd_limitis reset toap->orig_sata_spd_limiton hotplug. This prevents limits introduced by earlier devices from affecting new devices.Signed-off-by Tejun Heo <[email protected]>Rather than "
orig_" call it "hw_" or similar. This is similar to the block layer'smax_sectorsandmax_hw_sectorssituation.
Sure. I'll choose one of hw_sata_spd_limit or phy_sata_spd_limit.
Signature · 1 line
tejun
Quoted 7 lines · Jeff Garzik
Quoted 6 lines · Tejun Heo
Hello, all.
This is the first take of prep-for-hotplug-support patchset. As the name suggests, this patchset prepares libata for hotplug support. This patchset contains 15 patches.
Quoted 9 lines
Quoted 4 lines
#01-02 update sata_sil (hotplug related constants, new interrupt handler) #03-04 misc libata preps #05-12 prepare ata_bus_probe() #13-15 hotplug flags, extra fields, hotplug_wqACK, modulo the minor comments just sent.
Also, in general libata needs a rethink when it comes to workqueues. Sometimes a single thread is more appropriate than the workqueue default of one-thread-per-CPU. Using workqueues in the default state is quite efficient, but can also given you a huge number of idle threads on a $BIGNUM CPU box. Workqueues on a 16-CPU box can be pretty insane...
Yeah, Forrest pointed out the same thing and I've converted hotplug_wq to single threaded variant, which should be enough for SCSI hotplugging.
For ata_wq, I think it's wiser to keep it multi-threaded for the time
being. Maybe what should be done is to allocate a single threaded workqueue per host_set.
$BIGNUM CPU boxes tend to have $BIGNUM GB of memories, so multithreaded wq might not be that critical resource-wise. But, still, inefficient and doesn't scale well.
Signature · 1 line
tejun
Quoted 3 lines · Tejun Heo
Yeah, Forrest pointed out the same thing and I've converted
hotplug_wqto single threaded variant, which should be enough for SCSI hotplugging.
Forata_wq, I think it's wiser to keep it multi-threaded for the time
being. Maybe what should be done is to allocate a single threaded workqueue perhost_set.
One thread per host_set would suck for any situation where that's doing ATAPI or PIO tasks. Would love to find a good metric...
Quoted 1 line
$BIGNUM CPU boxes tend to have $BIGNUM GB of memories, so multithreaded wq might not be that critical resource-wise. But, still, inefficient
That's a bad assumption on modern machines. Think of a single 16-core, 8-thread SPARC Niagara CPU, for example :)
Jeff
Quoted 4 lines · Jeff Garzik
Quoted 1 line · Tejun Heo
Yeah, Forrest pointed out the same thing and I've converted
hotplug_wqto single threaded variant, which should be enough for SCSI hotplugging. Forata_wq, I think it's wiser to keep it multi-threaded for the time being. Maybe what should be done is to allocate a single threaded workqueue perhost_set.One thread per
host_setwould suck for any situation where that's doing ATAPI or PIO tasks. Would love to find a good metric...
Dynamic pool of worker threads maybe?
Quoted 5 lines
Quoted 2 lines
$BIGNUM CPU boxes tend to have $BIGNUM GB of memories, so multithreaded wq might not be that critical resource-wise. But, still, inefficient
That's a bad assumption on modern machines. Think of a single 16-core, 8-thread SPARC Niagara CPU, for example :)
Yeah, that one is pretty extreme. But most mainstream machines have <= 8 threads of execution and even they are equipped with GB's of memory. But, I do agree that we want something better.
Signature · 1 line
tejun