implement ata_link, take 2
PATCH 1/3 implement ata_link, take 2
Hello, all.
This is part of patchset series described in [T].
This is the second take of implement-ata_link patchset. This patchset contains 17 patches which can be categorized as follows.
#01-02: prep
#03-04: implement ata_link
#05-08: make libata deal with link instead of port #09-11: misc link stuff (link init, reset_tries, ata_link_abort()) #12-17: add ap->pmp_link[] and update libata to deal with multiple
links
ata_link abstracts PHY and sits between ata_port and ata_device. The following attributes are moved to ata_link from ata_port.
- active command state (active_tag, sactive)
- [hw_]sata_spd_limit
- eh_info and eh_context
- device array
With above and a few extra fields, a link can fully host attached devices including qc management and EH/hotplug. This patchset makes libata ready to handle PM links.
Changes from the last take[L] are.
* updated to fit new #upstream
* ata_eh_handle_dev_fail() is separated out from ata_eh_recover() to ease making EH batch later.
* Link resume handling udpated.
* Power Management is linkified.
This patchset is against
upstream (309bade002e9226781c2d7a015340d0089e399b5)
+ [1] hp-poll patchset, take #2
Thanks.
--
tejun
[T] http://article.gmane.org/gmane.linux.ide/11927
[L] http://article.gmane.org/gmane.linux.ide/10106
[1] http://article.gmane.org/gmane.linux.ide/11862
PATCH 1/17 libata-link: separate out ata_eh_handle_dev_fail()
Separate out ata_eh_handle_dev_fail() from ata_eh_recover(). This is in preparation of ata_link and PMP support.
---
drivers/scsi/libata-eh.c | 91 +++++++++++++++++++++++++--------------------- 1 files changed, 50 insertions(+), 41 deletions(-)
9f7fbf1bc05472523f3fe382d96a1d0b4dfef2a5
drivers/scsi/libata-eh.c +50 -41
@@ -1892,6 +1892,55 @@ static int ata_eh_skip_recovery(struct areturn 1 ; } +static void ata_eh_handle_dev_fail (struct ata_device *dev,int err, +int down_xfermask) +{ +struct ata_port *ap = dev->ap; +struct ata_eh_context *ehc = &ap->eh_context; + +switch (err) { +case -ENODEV : +/* device missing, schedule probing */ + ehc->i.probe_mask |= (1 << dev->devno); +case -EINVAL : + ehc->tries[dev->devno] =0 ; +break ; +case -EIO : +sata_down_spd_limit (ap); +default : + ehc->tries[dev->devno]--; +if (down_xfermask && +ata_down_xfermask_limit (dev, ehc->tries[dev->devno] ==1 )) + ehc->tries[dev->devno] =0 ; + } + +if (ata_dev_enabled (dev) && !ehc->tries[dev->devno]) { +/* disable device if it has used up all its chances */ +ata_dev_disable (dev); + +/* 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 ; + } +} +/** * ata_eh_recover - recover host port after error * @ap: host port to recover
@@ -2003,47 +2052,7 @@ static int ata_eh_recover(struct ata_por goto out; 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 ; -case -EIO : -sata_down_spd_limit (ap); -default : - ehc->tries[dev->devno]--; -if (down_xfermask && -ata_down_xfermask_limit (dev, ehc->tries[dev->devno] ==1 )) - ehc->tries[dev->devno] =0 ; - } - -if (ata_dev_enabled (dev) && !ehc->tries[dev->devno]) { -/* disable device if it has used up all its chances */ -ata_dev_disable (dev); - -/* 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 ; - } +ata_eh_handle_dev_fail (dev, rc, down_xfermask);if (ata_port_nr_enabled (ap)) { ata_port_printk(ap, KERN_WARNING, "failed to recover some "
Signature · 1 line
1.3.2
PATCH 2/17 libata-link: add PMP related ATA constants
In reply to Tejun HeoAdd Port Multiplier related ATA constants and macros. Some of these will be used by ata_link implementation.
---
include/linux/ata.h | 29 +++++++++++++++++++++++++++++ 1 files changed, 29 insertions(+), 0 deletions(-)
4681138079e48198ac890673c23d58a57a4743b4
include/linux/ata.h +29 -0
@@ -154,6 +154,8 @@ enum {ATA_CMD_READ_NATIVE_MAX =0xF8 ,ATA_CMD_READ_NATIVE_MAX_EXT =0x27 ,ATA_CMD_READ_LOG_EXT =0x2f , +ATA_CMD_PMP_READ =0xE4 , +ATA_CMD_PMP_WRITE =0xE8 ,/* READ_LOG_EXT pages */ ATA_LOG_SATA_NCQ = 0x10,
@@ -190,6 +192,28 @@ enum {0=to device, 1=to host */ ATAPI_CDB_LEN =16 , +/* PMP stuff */ +SATA_PMP_MAX_PORTS =15 , +SATA_PMP_CTRL_PORT =15 , + +SATA_PMP_GSCR_DWORDS =128 , +SATA_PMP_GSCR_PROD_ID =0 , +SATA_PMP_GSCR_REV =1 , +SATA_PMP_GSCR_PORT_INFO =2 , +SATA_PMP_GSCR_ERROR =32 , +SATA_PMP_GSCR_ERROR_EN =33 , +SATA_PMP_GSCR_FEAT =64 , +SATA_PMP_GSCR_FEAT_EN =96 , + +SATA_PMP_PSCR_STATUS =0 , +SATA_PMP_PSCR_ERROR =1 , +SATA_PMP_PSCR_CONTROL =2 , + +SATA_PMP_FEAT_BIST = (1 <<0 ), +SATA_PMP_FEAT_PMREQ = (1 <<1 ), +SATA_PMP_FEAT_DYNSSC = (1 <<2 ), +SATA_PMP_FEAT_NOTIFY = (1 <<3 ), +/* cable types */ ATA_CBL_NONE =0 , ATA_CBL_PATA40 = 1,
@@ -366,4 +390,9 @@ static inline int lba_48_ok(u64 block, u return ((block + n_block - 1) < ((u64)1 << 48)) && (n_block <= 65536); } +#define sata_pmp_gscr_vendor (gscr) ((gscr)[SATA_PMP_GSCR_PROD_ID] & 0xffff) +#define sata_pmp_gscr_devid (gscr) ((gscr)[SATA_PMP_GSCR_PROD_ID] >> 16) +#define sata_pmp_gscr_rev (gscr) (((gscr)[SATA_PMP_GSCR_REV] >> 8) & 0xff) +#define sata_pmp_gscr_ports (gscr) ((gscr)[SATA_PMP_GSCR_PORT_INFO] & 0xf) +#endif /* __LINUX_ATA_H__ */
Signature · 1 line
1.3.2
Re: [PATCH 02/17] libata-link: add PMP related ATA constants
ACK 1-2
PATCH 3/17 libata-link: introduce ata_link
In reply to Tejun HeoIntroduce ata_link. It abstracts PHY and sits between ata_port and ata_device. This new level of abstraction is necessary to support SATA Port Multiplier, which basically adds a bunch of links (PHYs) to a ATA host port. Fields related to command execution, spd_limit and EH are per-link and thus moved to ata_link.
Except for the host link, each link can be connected to at most one device and thus contains one struct ata_device. Slave device (PATA or emulated SATA) is a special case for the host link and is handled by struct ata_device storage __dev1 put right after the host link in struct ata_port.
This patch only defines the host link. Multiple link handling will be added later. Also, a lot of ap->link derefences are added but many of them will be removed as each part is converted to deal directly with ata_link instead of ata_port.
This patch introduces no behavior change.
---
drivers/scsi/ahci.c | 20 +++--- drivers/scsi/ata_piix.c | 4 + drivers/scsi/libata-bmdma.c | 4 + drivers/scsi/libata-core.c | 147 +++++++++++++++++++++++-------------------- drivers/scsi/libata-eh.c | 100 +++++++++++++++-------------- drivers/scsi/libata-scsi.c | 40 ++++++------ drivers/scsi/pdc_adma.c | 4 + drivers/scsi/sata_mv.c | 6 +- drivers/scsi/sata_nv.c | 4 + drivers/scsi/sata_promise.c | 4 + drivers/scsi/sata_qstor.c | 4 + drivers/scsi/sata_sil.c | 8 +- drivers/scsi/sata_sil24.c | 10 +-- drivers/scsi/sata_sx4.c | 4 + drivers/scsi/sata_vsc.c | 2 - include/linux/libata.h | 39 +++++++---- 16 files changed, 211 insertions(+), 189 deletions(-)
a083d01fa61bd520c3fc5b6ca4b47f5295a15513
drivers/scsi/ahci.c +10 -10
@@ -651,7 +651,7 @@ static int ahci_softreset(struct ata_por/* restart engine */ ahci_start_engine (ap); -ata_tf_init (ap->device, &tf); +ata_tf_init (ap->link.device, &tf); fis = pp->cmd_tbl;/* issue the first D2H Register FIS */
@@ -726,7 +726,7 @@ static int ahci_hardreset(struct ata_porahci_stop_engine (ap);/* clear D2H reception area to properly wait for D2H FIS */ -ata_tf_init (ap->device, &tf); +ata_tf_init (ap->link.device, &tf); tf.command =0xff ;ata_tf_to_fis (&tf, d2h_fis,0 );
@@ -845,7 +845,7 @@ static void ahci_qc_prep(struct ata_queustatic void ahci_error_intr (struct ata_port *ap,u32 irq_stat) {struct ahci_port_priv *pp = ap->private_data; -struct ata_eh_info *ehi = &ap->eh_info; +struct ata_eh_info *ehi = &ap->link.eh_info;unsigned int err_mask =0 , action =0 ;struct ata_queued_cmd *qc;u32 serror;
@@ -892,7 +892,7 @@ static void ahci_error_intr(struct ata_p ehi->serror |= serror; ehi->action |= action; - qc =ata_qc_from_tag (ap, ap->active_tag); + qc =ata_qc_from_tag (ap, ap->link.active_tag);if (qc) qc->err_mask |= err_mask;else
@@ -908,7 +908,7 @@ static void ahci_host_intr(struct ata_po {void __iomem *mmio = ap->host_set->mmio_base;void __iomem *port_mmio =ahci_port_base (mmio, ap->port_no); -struct ata_eh_info *ehi = &ap->eh_info; +struct ata_eh_info *ehi = &ap->link.eh_info;u32 status, qc_active;int rc;
@@ -920,7 +920,7 @@ static void ahci_host_intr(struct ata_poreturn ; } -if (ap->sactive) +if (ap->link.sactive) qc_active =readl (port_mmio +PORT_SCR_ACT );else qc_active =readl (port_mmio +PORT_CMD_ISSUE );
@@ -938,13 +938,13 @@ static void ahci_host_intr(struct ata_po/* hmmm... a spurious interupt */ /* some devices send D2H reg with I bit set during NCQ command phase */ -if (ap->sactive && status &PORT_IRQ_D2H_REG_FIS ) +if (ap->link.sactive && status &PORT_IRQ_D2H_REG_FIS )return ;/* ignore interim PIO setup fis interrupts */ -if (ata_tag_valid (ap->active_tag)) { +if (ata_tag_valid (ap->link.active_tag)) {struct ata_queued_cmd *qc = -ata_qc_from_tag (ap, ap->active_tag); +ata_qc_from_tag (ap, ap->link.active_tag);if (qc && qc->tf.protocol ==ATA_PROT_PIO && (status &PORT_IRQ_PIOS_FIS ))
@@ -954,7 +954,7 @@ static void ahci_host_intr(struct ata_poif (ata_ratelimit ())ata_port_printk (ap,KERN_INFO ,"spurious interrupt " "(irq_stat 0x%x active_tag %d sactive 0x%x)\n" , - status, ap->active_tag, ap->sactive); + status, ap->link.active_tag, ap->link.sactive); }static void ahci_irq_clear (struct ata_port *ap)
drivers/scsi/ata_piix.c +2 -2
@@ -475,7 +475,7 @@ static int piix_pata_prereset(struct ataif (!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 ; + ap->link.eh_context.i.action &= ~ATA_EH_RESET_MASK ;return 0 ; }
@@ -549,7 +549,7 @@ static int piix_sata_prereset(struct ataif (!present_mask) {ata_port_printk (ap,KERN_INFO ,"SATA port has no device.\n" ); - ap->eh_context.i.action &= ~ATA_EH_RESET_MASK ; + ap->link.eh_context.i.action &= ~ATA_EH_RESET_MASK ;return 0 ; }
drivers/scsi/libata-bmdma.c +2 -2
@@ -714,12 +714,12 @@ void ata_bmdma_drive_eh(struct ata_port ata_reset_fn_t softreset, ata_reset_fn_t hardreset, ata_postreset_fn_t postreset) { - struct ata_eh_context *ehc = &ap->eh_context; + struct ata_eh_context *ehc = &ap->link.eh_context;struct ata_queued_cmd *qc;unsigned long flags;int thaw =0 ; - qc =__ata_qc_from_tag (ap, ap->active_tag); + qc =__ata_qc_from_tag (ap, ap->link.active_tag);if (qc && !(qc->flags &ATA_QCFLAG_FAILED )) qc =NULL ;
drivers/scsi/libata-core.c +78 -69
465 lines not on this page · raw message
drivers/scsi/libata-eh.c +50 -50
344 lines not on this page · raw message
drivers/scsi/libata-scsi.c +21 -19
@@ -440,8 +440,8 @@ int ata_scsi_device_suspend(struct scsi_ action =ATA_EH_SUSPEND ;if (state.event !=PM_EVENT_SUSPEND ) action |=ATA_EH_PM_FREEZE ; - ap->eh_info.dev_action[dev->devno] |= action; - ap->eh_info.flags |=ATA_EHI_QUIET ; + dev->link->eh_info.dev_action[dev->devno] |= action; + dev->link->eh_info.flags |=ATA_EHI_QUIET ;ata_port_schedule_eh (ap);spin_unlock_irqrestore (ap->lock, flags);
@@ -485,7 +485,7 @@ int ata_scsi_device_resume(struct scsi_d {struct ata_port *ap =ata_shost_to_port (sdev->host);struct ata_device *dev =ata_scsi_find_dev (ap, sdev); -struct ata_eh_info *ehi = &ap->eh_info; +struct ata_eh_info *ehi;unsigned long flags;unsigned int action;
@@ -500,6 +500,7 @@ int ata_scsi_device_resume(struct scsi_d goto out_unlock;/* request resume */ + ehi = &dev->link->eh_info; action =ATA_EH_RESUME ;if (sdev->sdev_gendev.power.power_state.event ==PM_EVENT_SUSPEND )__ata_ehi_hotplugged (ehi);
@@ -1420,7 +1421,7 @@ static void ata_scsi_qc_complete(structif (!need_sense && (qc->tf.command ==ATA_CMD_SET_FEATURES ) && ((qc->tf.feature ==SETFEATURES_WC_ON ) || (qc->tf.feature ==SETFEATURES_WC_OFF ))) { - qc->ap->eh_info.action |=ATA_EH_REVALIDATE ; + qc->dev->link->eh_info.action |=ATA_EH_REVALIDATE ;ata_port_schedule_eh (qc->ap); }
@@ -1474,16 +1475,16 @@ static void ata_scsi_qc_complete(struct*/ static int ata_scmd_need_defer (struct ata_device *dev,int is_io) { -struct ata_port *ap = dev->ap; +struct ata_link *link = dev->link;if (!(dev->flags &ATA_DFLAG_NCQ ))return 0 ;if (is_io) { -if (!ata_tag_valid (ap->active_tag)) +if (!ata_tag_valid (link->active_tag))return 0 ; }else { -if (!ata_tag_valid (ap->active_tag) && !ap->sactive) +if (!ata_tag_valid (link->active_tag) && !link->sactive)return 0 ; }return 1 ;
@@ -2466,7 +2467,7 @@ static unsigned int atapi_xlat(struct atstatic struct ata_device *ata_find_dev (struct ata_port *ap,int id) {if (likely (id <ATA_MAX_DEVICES )) -return &ap->device[id]; +return &ap->link.device[id];return NULL ; }
@@ -2498,7 +2499,7 @@ static int ata_scsi_dev_enabled(struct aif (unlikely (!ata_dev_enabled (dev)))return 0 ; -if (!atapi_enabled || (dev->ap->flags &ATA_FLAG_NO_ATAPI )) { +if (!atapi_enabled || (dev->link->ap->flags &ATA_FLAG_NO_ATAPI )) {if (unlikely (dev->class ==ATA_DEV_ATAPI )) { ata_dev_printk(dev, KERN_WARNING, "WARNING: ATAPI is %s, device ignored.\n",
@@ -2925,7 +2926,7 @@ void ata_scsi_scan_host(struct ata_portreturn ;for (i =0 ; i <ATA_MAX_DEVICES ; i++) { -struct ata_device *dev = &ap->device[i]; +struct ata_device *dev = &ap->link.device[i];struct scsi_device *sdev;if (!ata_dev_enabled (dev) || dev->sdev)
@@ -2975,7 +2976,7 @@ int ata_scsi_offline_dev(struct ata_devi*/ static void ata_scsi_remove_dev (struct ata_device *dev) { -struct ata_port *ap = dev->ap; +struct ata_port *ap = dev->link->ap;struct scsi_device *sdev;unsigned long flags;
@@ -3048,7 +3049,7 @@ void ata_scsi_hotplug(void *data)/* unplug detached devices */ for (i =0 ; i <ATA_MAX_DEVICES ; i++) { -struct ata_device *dev = &ap->device[i]; +struct ata_device *dev = &ap->link.device[i];unsigned long flags;if (!(dev->flags &ATA_DFLAG_DETACHED ))
@@ -3069,7 +3070,7 @@ void ata_scsi_hotplug(void *data)* unattached devices. */ for (i =0 ; i <ATA_MAX_DEVICES ; i++) { -struct ata_device *dev = &ap->device[i]; +struct ata_device *dev = &ap->link.device[i];if (ata_dev_enabled (dev) && !dev->sdev) {queue_delayed_work (ata_aux_wq, &ap->hotplug_task,HZ );break ;
@@ -3099,6 +3100,7 @@ static int ata_scsi_user_scan(struct Scs unsigned int id, unsigned int lun) {struct ata_port *ap =ata_shost_to_port (shost); +struct ata_eh_info *ehi = &ap->link.eh_info;unsigned long flags;int rc =0 ;
@@ -3112,15 +3114,15 @@ static int ata_scsi_user_scan(struct Scsspin_lock_irqsave (ap->lock, flags);if (id ==SCAN_WILD_CARD ) { - ap->eh_info.probe_mask |= (1 <<ATA_MAX_DEVICES ) -1 ; - ap->eh_info.action |=ATA_EH_SOFTRESET ; + ehi->probe_mask |= (1 <<ATA_MAX_DEVICES ) -1 ; + ehi->action |=ATA_EH_SOFTRESET ; }else {struct ata_device *dev =ata_find_dev (ap, id);if (dev) { - ap->eh_info.probe_mask |=1 << dev->devno; - ap->eh_info.action |=ATA_EH_SOFTRESET ; - ap->eh_info.flags |=ATA_EHI_RESUME_LINK ; + ehi->probe_mask |=1 << dev->devno; + ehi->action |=ATA_EH_SOFTRESET ; + ehi->flags |=ATA_EHI_RESUME_LINK ; }else rc = -EINVAL ; }
@@ -3152,7 +3154,7 @@ void ata_scsi_dev_rescan(void *data)unsigned int i;for (i =0 ; i <ATA_MAX_DEVICES ; i++) { - dev = &ap->device[i]; + dev = &ap->link.device[i];if (ata_dev_enabled (dev) && dev->sdev)scsi_rescan_device (&(dev->sdev->sdev_gendev));
drivers/scsi/pdc_adma.c +2 -2
@@ -462,7 +462,7 @@ static inline unsigned int adma_intr_pkt pp = ap->private_data;if (!pp || pp->state != adma_state_pkt)continue ; - qc =ata_qc_from_tag (ap, ap->active_tag); + qc =ata_qc_from_tag (ap, ap->link.active_tag);if (qc && (!(qc->tf.flags &ATA_TFLAG_POLLING ))) {if ((status & (aPERR | aPSD | aUIRQ))) qc->err_mask |=AC_ERR_OTHER ;
@@ -487,7 +487,7 @@ static inline unsigned int adma_intr_mmistruct adma_port_priv *pp = ap->private_data;if (!pp || pp->state != adma_state_mmio)continue ; - qc =ata_qc_from_tag (ap, ap->active_tag); + qc =ata_qc_from_tag (ap, ap->link.active_tag);if (qc && (!(qc->tf.flags &ATA_TFLAG_POLLING ))) {/* check main status, clearing INTRQ */
drivers/scsi/sata_mv.c +3 -3
@@ -1417,7 +1417,7 @@ static void mv_host_intr(struct ata_host }if (handled) { - qc =ata_qc_from_tag (ap, ap->active_tag); + qc =ata_qc_from_tag (ap, ap->link.active_tag);if (qc && (qc->flags &ATA_QCFLAG_ACTIVE )) {VPRINTK ("port %u IRQ found for qc, " "ata_status 0x%x\n" , port,ata_status);
@@ -1939,7 +1939,7 @@ static void __mv_phy_reset(struct ata_postruct mv_host_priv *hpriv = ap->host_set->private_data;void __iomem *port_mmio =mv_ap_base (ap);struct ata_taskfile tf; -struct ata_device *dev = &ap->device[0 ]; +struct ata_device *dev = &ap->link.device[0 ];unsigned long timeout;int retry =5 ;u32 sstatus;
@@ -2047,7 +2047,7 @@ static void mv_eng_timeout(struct ata_pomv_dump_all_regs (ap->host_set->mmio_base, ap->port_no,to_pci_dev (ap->host_set->dev)); - qc =ata_qc_from_tag (ap, ap->active_tag); + qc =ata_qc_from_tag (ap, ap->link.active_tag);printk (KERN_ERR "mmio_base %p ap %p qc %p scsi_cmnd %p &cmnd %p\n" , ap->host_set->mmio_base, ap, qc, qc->scsicmd, &qc->scsicmd->cmnd);
drivers/scsi/sata_nv.c +2 -2
@@ -314,7 +314,7 @@ static irqreturn_t nv_generic_interrupt( !(ap->flags & ATA_FLAG_DISABLED)) {struct ata_queued_cmd *qc; - qc =ata_qc_from_tag (ap, ap->active_tag); + qc =ata_qc_from_tag (ap, ap->link.active_tag);if (qc && (!(qc->tf.flags &ATA_TFLAG_POLLING ))) handled +=ata_host_intr (ap, qc);else
@@ -332,7 +332,7 @@ static irqreturn_t nv_generic_interrupt(static int nv_host_intr (struct ata_port *ap,u8 irq_stat) { -struct ata_queued_cmd *qc =ata_qc_from_tag (ap, ap->active_tag); +struct ata_queued_cmd *qc =ata_qc_from_tag (ap, ap->link.active_tag);int handled;/* freeze if hotplugged */
drivers/scsi/sata_promise.c +2 -2
@@ -445,7 +445,7 @@ static void pdc_eng_timeout(struct ata_pspin_lock_irqsave (&host_set->lock, flags); - qc =ata_qc_from_tag (ap, ap->active_tag); + qc =ata_qc_from_tag (ap, ap->link.active_tag);switch (qc->tf.protocol) {case ATA_PROT_DMA :
@@ -552,7 +552,7 @@ static irqreturn_t pdc_interrupt (int ir !(ap->flags & ATA_FLAG_DISABLED)) {struct ata_queued_cmd *qc; - qc =ata_qc_from_tag (ap, ap->active_tag); + qc =ata_qc_from_tag (ap, ap->link.active_tag);if (qc && (!(qc->tf.flags &ATA_TFLAG_POLLING ))) handled +=pdc_host_intr (ap, qc); }
drivers/scsi/sata_qstor.c +2 -2
@@ -401,7 +401,7 @@ static inline unsigned int qs_intr_pkt(sstruct qs_port_priv *pp = ap->private_data;if (!pp || pp->state != qs_state_pkt)continue ; - qc =ata_qc_from_tag (ap, ap->active_tag); + qc =ata_qc_from_tag (ap, ap->link.active_tag);if (qc && (!(qc->tf.flags &ATA_TFLAG_POLLING ))) {switch (sHST) {case 0 :/* successful CPB */
@@ -434,7 +434,7 @@ static inline unsigned int qs_intr_mmio(struct qs_port_priv *pp = ap->private_data;if (!pp || pp->state != qs_state_mmio)continue ; - qc =ata_qc_from_tag (ap, ap->active_tag); + qc =ata_qc_from_tag (ap, ap->link.active_tag);if (qc && (!(qc->tf.flags &ATA_TFLAG_POLLING ))) {/* check main status, clearing INTRQ */
drivers/scsi/sata_sil.c +4 -4
@@ -305,7 +305,7 @@ static void sil_post_set_mode (struct atunsigned int i;for (i =0 ; i <2 ; i++) { - dev = &ap->device[i]; + dev = &ap->link.device[i];if (!ata_dev_enabled (dev)) dev_mode[i] =0 ;/* PIO0/1/2 */ else if (dev->flags &ATA_DFLAG_PIO )
@@ -359,7 +359,7 @@ static void sil_scr_write (struct ata_postatic void sil_host_intr (struct ata_port *ap,u32 bmdma2) { -struct ata_queued_cmd *qc =ata_qc_from_tag (ap, ap->active_tag); +struct ata_queued_cmd *qc =ata_qc_from_tag (ap, ap->link.active_tag);u8 status;if (unlikely (bmdma2 &SIL_DMA_SATA_IRQ )) {
@@ -378,8 +378,8 @@ static void sil_host_intr(struct ata_por* repeat probing needlessly. */ if (!(ap->pflags &ATA_PFLAG_FROZEN )) { -ata_ehi_hotplugged (&ap->eh_info); - ap->eh_info.serror |= serror; +ata_ehi_hotplugged (&ap->link.eh_info); + ap->link.eh_info.serror |= serror; } goto freeze;
drivers/scsi/sata_sil24.c +5 -5
@@ -759,7 +759,7 @@ static void sil24_thaw(struct ata_port *static void sil24_error_intr (struct ata_port *ap) {void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr; -struct ata_eh_info *ehi = &ap->eh_info; +struct ata_eh_info *ehi = &ap->link.eh_info;int freeze =0 ;u32 irq_stat;
@@ -811,7 +811,7 @@ static void sil24_error_intr(struct ata_ }/* record error info */ - qc =ata_qc_from_tag (ap, ap->active_tag); + qc =ata_qc_from_tag (ap, ap->link.active_tag);if (qc) {sil24_update_tf (ap); qc->err_mask |= err_mask;
@@ -855,7 +855,7 @@ static inline void sil24_host_intr(strucif (rc >0 )return ;if (rc <0 ) { -struct ata_eh_info *ehi = &ap->eh_info; +struct ata_eh_info *ehi = &ap->link.eh_info; ehi->err_mask |=AC_ERR_HSM ; ehi->action |=ATA_EH_SOFTRESET ;ata_port_freeze (ap);
@@ -865,7 +865,7 @@ static inline void sil24_host_intr(strucif (ata_ratelimit ())ata_port_printk (ap,KERN_INFO ,"spurious interrupt " "(slot_stat 0x%x active_tag %d sactive 0x%x)\n" , - slot_stat, ap->active_tag, ap->sactive); + slot_stat, ap->link.active_tag, ap->link.sactive); }static irqreturn_t sil24_interrupt (int irq,void *dev_instance,struct pt_regs *regs)
@@ -907,7 +907,7 @@ static irqreturn_t sil24_interrupt(int istatic void sil24_error_handler (struct ata_port *ap) { -struct ata_eh_context *ehc = &ap->eh_context; +struct ata_eh_context *ehc = &ap->link.eh_context;if (sil24_init_port (ap)) {ata_eh_freeze_port (ap);
drivers/scsi/sata_sx4.c +2 -2
@@ -838,7 +838,7 @@ static irqreturn_t pdc20621_interrupt (i !(ap->flags & ATA_FLAG_DISABLED)) {struct ata_queued_cmd *qc; - qc =ata_qc_from_tag (ap, ap->active_tag); + qc =ata_qc_from_tag (ap, ap->link.active_tag);if (qc && (!(qc->tf.flags &ATA_TFLAG_POLLING ))) handled +=pdc20621_host_intr (ap, qc, (i >4 ), mmio_base);
@@ -865,7 +865,7 @@ static void pdc_eng_timeout(struct ata_pspin_lock_irqsave (&host_set->lock, flags); - qc =ata_qc_from_tag (ap, ap->active_tag); + qc =ata_qc_from_tag (ap, ap->link.active_tag);switch (qc->tf.protocol) {case ATA_PROT_DMA :
drivers/scsi/sata_vsc.c +1 -1
@@ -232,7 +232,7 @@ static irqreturn_t vsc_sata_interrupt (iif (ap && !(ap->flags &ATA_FLAG_DISABLED )) {struct ata_queued_cmd *qc; - qc =ata_qc_from_tag (ap, ap->active_tag); + qc =ata_qc_from_tag (ap, ap->link.active_tag);if (qc && (!(qc->tf.flags &ATA_TFLAG_POLLING ))) handled +=ata_host_intr (ap, qc);else if (is_vsc_sata_int_err (i, int_status)) {
include/linux/libata.h +25 -14
@@ -437,7 +437,7 @@ struct ata_ering { };struct ata_device { -struct ata_port *ap; +struct ata_link *link;unsigned int devno;/* 0 or 1 */ unsigned long flags;/* ATA_DFLAG_xxx */ struct scsi_device *sdev;/* attached SCSI device */
@@ -496,6 +496,23 @@ struct ata_eh_context {unsigned int did_probe_mask; }; +struct ata_link { +struct ata_port *ap; + +unsigned int active_tag;/* active tag on this link */ +u32 sactive;/* active NCQ commands */ + +unsigned int hw_sata_spd_limit; +unsigned int sata_spd_limit; + +/* record runtime error info, protected by host_set lock */ +struct ata_eh_info eh_info; +/* EH context */ +struct ata_eh_context eh_context; + +struct ata_device device[1 ]; +}; +struct ata_port {struct Scsi_Host *host;/* our co-allocated scsi host */ const struct ata_port_operations *ops;
@@ -520,22 +537,13 @@ struct ata_port {unsigned int mwdma_mask;unsigned int udma_mask;unsigned int cbl;/* cable type; ATA_CBL_xxx */ -unsigned int hw_sata_spd_limit; -unsigned int sata_spd_limit;/* SATA PHY speed limit */ - -/* record runtime error info, protected by host_set lock */ -struct ata_eh_info eh_info; -/* EH context owned by EH */ -struct ata_eh_context eh_context; - -struct ata_device device[ATA_MAX_DEVICES ];struct ata_queued_cmd qcmd[ATA_MAX_QUEUE ];unsigned long qc_allocated;unsigned int qc_active; -unsigned int active_tag; -u32 sactive; +struct ata_link link;/* host default link */ +struct ata_device __dev1;/* storage for link.device[1] */ struct ata_host_stats stats;struct ata_host_set *host_set;
@@ -851,8 +859,11 @@ extern void ata_do_eh(struct ata_port *a #define ata_port_printk(ap, lv, fmt, args...) \ printk(lv"ata%u: "fmt, (ap)->id , ##args) +#define ata_link_printk(link, lv, fmt, args...) \ + printk(lv"ata%u: "fmt, (link)->ap->id , ##args) + #define ata_dev_printk(dev, lv, fmt, args...) \ - printk(lv"ata%u.%02u: "fmt, (dev)->ap->id, (dev)->devno , ##args) + printk(lv"ata%u.%02u: "fmt, (dev)->link->ap->id, (dev)->devno , ##args)/* * ata_eh_info helpers
@@ -1090,7 +1101,7 @@ static inline void ata_tf_init(struct at {memset (tf,0 ,sizeof (*tf)); - tf->ctl = dev->ap->ctl; + tf->ctl = dev->link->ap->ctl;if (dev->devno ==0 ) tf->device =ATA_DEVICE_OBS ;else
Signature · 1 line
1.3.2
Re: [PATCH 03/17] libata-link: introduce ata_link
Quoted 36 lines · Tejun Heo
include/linux/libata.h +17
-8@@ -496,6 +496,23 @@ struct ata_eh_context {unsigned int did_probe_mask; }; +struct ata_link { +struct ata_port *ap; + +unsigned int active_tag;/* active tag on this link */ +u32 sactive;/* active NCQ commands */ + +unsigned int hw_sata_spd_limit; +unsigned int sata_spd_limit; + +/* record runtime error info, protected by host_set lock */ +struct ata_eh_info eh_info; +/* EH context */ +struct ata_eh_context eh_context; + +struct ata_device device[1 ]; +}; +struct ata_port {struct Scsi_Host *host;/* our co-allocated scsi host */ const struct ata_port_operations *ops;@@ -520,22 +537,13 @@ struct ata_port {unsigned int mwdma_mask;unsigned int udma_mask;unsigned int cbl;/* cable type; ATA_CBL_xxx */ -unsigned int hw_sata_spd_limit; -unsigned int sata_spd_limit;/* SATA PHY speed limit */ - -/* record runtime error info, protected by host_set lock */ -struct ata_eh_info eh_info; -/* EH context owned by EH */ -struct ata_eh_context eh_context; -
include/linux/libata.h struct ata_port { · line 546
Quoted 10 lines
include/linux/libata.h +2
-3-struct ata_device device[ATA_MAX_DEVICES ];struct ata_queued_cmd qcmd[ATA_MAX_QUEUE ];unsigned long qc_allocated;unsigned int qc_active; -unsigned int active_tag; -u32 sactive; +struct ata_link link;/* host default link */ +struct ata_device __dev1;/* storage for link.device[1] */
This storage mess for link.device[] is NAK'd.
This patch overall looks good, but it should really be entirely an equivalent-transformation patch, one that is easy to review and prove correct.
As such, this patch should move 'struct ata_device device[ATA_MAX_DEVICES]' into struct ata_link, rather than the strange arrangement you have above. If you want to do something unusual like this, it's better to do it in a separate patch.
Jeff
Re: [PATCH 03/17] libata-link: introduce ata_link
Quoted 50 lines · Jeff Garzik
Quoted 36 lines · Tejun Heo
include/linux/libata.h +17
-8@@ -496,6 +496,23 @@ struct ata_eh_context {unsigned int did_probe_mask; }; +struct ata_link { +struct ata_port *ap; + +unsigned int active_tag;/* active tag on this link */ +u32 sactive;/* active NCQ commands */ + +unsigned int hw_sata_spd_limit; +unsigned int sata_spd_limit; + +/* record runtime error info, protected by host_set lock */ +struct ata_eh_info eh_info; +/* EH context */ +struct ata_eh_context eh_context; + +struct ata_device device[1 ]; +}; +struct ata_port {struct Scsi_Host *host;/* our co-allocated scsi host */ const struct ata_port_operations *ops;@@ -520,22 +537,13 @@ struct ata_port {unsigned int mwdma_mask;unsigned int udma_mask;unsigned int cbl;/* cable type; ATA_CBL_xxx */ -unsigned int hw_sata_spd_limit; -unsigned int sata_spd_limit;/* SATA PHY speed limit */ - -/* record runtime error info, protected by host_set lock */ -struct ata_eh_info eh_info; -/* EH context owned by EH */ -struct ata_eh_context eh_context; -include/linux/libata.h struct ata_port { · line 546
Quoted 10 lines
include/linux/libata.h +2
-3-struct ata_device device[ATA_MAX_DEVICES ];struct ata_queued_cmd qcmd[ATA_MAX_QUEUE ];unsigned long qc_allocated;unsigned int qc_active; -unsigned int active_tag; -u32 sactive; +struct ata_link link;/* host default link */ +struct ata_device __dev1;/* storage for link.device[1] */ This storage mess for link.device[] is NAK'd.
Quoted 3 lines
This patch overall looks good, but it should really be entirely an equivalent-transformation patch, one that is easy to review and prove correct.
As such, this patch should move 'struct
ata_devicedevice[ATA_MAX_DEVICES]' into structata_link, rather than the strange arrangement you have above. If you want to do something unusual like this, it's better to do it in a separate patch.
Okay, will separate out __dev1 thing.
Signature · 1 line
tejun
PATCH 4/17 libata-link: implement and use link/device iterators
In reply to Tejun HeoMultiple links and different number of devices per link should be considered to iterate over links and devices. This patch implements and uses link and device iterators - ata_port_for_each_link() and ata_link_for_each_dev() - and ata_link_max_devices().
This change makes a lot of functions iterate over only possible devices instead of from dev 0 to dev ATA_MAX_DEVICES. All such changes have been examined and nothing should be broken.
While at it, add a separating comment before device helpers to distinguish them better from link helpers and others.
---
drivers/scsi/libata-core.c | 81 +++++++++++-------------- drivers/scsi/libata-eh.c | 142 +++++++++++++++++++++----------------------- drivers/scsi/libata-scsi.c | 24 +++---- include/linux/libata.h | 14 +++- 4 files changed, 122 insertions(+), 139 deletions(-)
54cdc69a26dfa3426b384b04b357e0fa7903b559
drivers/scsi/libata-core.c +35 -46
@@ -1329,14 +1329,14 @@ static void ata_dev_config_ncq(struct atstatic void ata_set_port_max_cmd_len (struct ata_port *ap) { -int i; +struct ata_device *dev;if (ap->host) { ap->host->max_cmd_len =0 ; -for (i =0 ; i <ATA_MAX_DEVICES ; i++) +ata_link_for_each_dev (dev, &ap->link) ap->host->max_cmd_len = max_t(unsigned int, ap->host->max_cmd_len, - ap->link.device[i].cdb_len); + dev->cdb_len); } }
@@ -1534,13 +1534,13 @@ static int ata_bus_probe(struct ata_port {unsigned int classes[ATA_MAX_DEVICES ];int tries[ATA_MAX_DEVICES ]; -int i, rc, down_xfermask; +int 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_link_for_each_dev (dev, &ap->link) + tries[dev->devno] =ATA_PROBE_MAX_TRIES ; retry: down_xfermask =0 ;
@@ -1548,9 +1548,7 @@ static int ata_bus_probe(struct ata_port/* reset and determine device classes */ ap->ops->phy_reset (ap); -for (i =0 ; i <ATA_MAX_DEVICES ; i++) { - dev = &ap->link.device[i]; - +ata_link_for_each_dev (dev, &ap->link) {if (!(ap->flags &ATA_FLAG_DISABLED ) && dev->class !=ATA_DEV_UNKNOWN ) classes[dev->devno] = dev->class;
@@ -1565,15 +1563,13 @@ static int ata_bus_probe(struct ata_port/* after the reset the device state is PIO 0 and the controller state is undefined. Record the mode */ -for (i =0 ; i <ATA_MAX_DEVICES ; i++) - ap->link.device[i].pio_mode =XFER_PIO_0 ; +ata_link_for_each_dev (dev, &ap->link) + dev->pio_mode =XFER_PIO_0 ;/* read IDENTIFY page and configure devices */ -for (i =0 ; i <ATA_MAX_DEVICES ; i++) { - dev = &ap->link.device[i]; - -if (tries[i]) - dev->class = classes[i]; +ata_link_for_each_dev (dev, &ap->link) { +if (tries[dev->devno]) + dev->class = classes[dev->devno];if (!ata_dev_enabled (dev))continue ;
@@ -1594,9 +1590,10 @@ static int ata_bus_probe(struct ata_port goto fail; } -for (i =0 ; i <ATA_MAX_DEVICES ; i++) -if (ata_dev_enabled (&ap->link.device[i])) +ata_link_for_each_dev (dev, &ap->link) { +if (ata_dev_enabled (dev))return 0 ; + }/* no device present, disable port */ ata_port_disable (ap);
@@ -2139,16 +2136,17 @@ static int ata_dev_set_mode(struct ata_d*/ int ata_set_mode (struct ata_port *ap,struct ata_device **r_failed_dev) { +struct ata_link *link = &ap->link;struct ata_device *dev; -int i, rc =0 , used_dma =0 , found =0 ; +int rc =0 , used_dma =0 , found =0 ;/* has private set_mode? */ if (ap->ops->set_mode) {/* FIXME: make ->set_mode handle no device case and * return error code and failing device on failure. */ -for (i =0 ; i <ATA_MAX_DEVICES ; i++) { -if (ata_dev_ready (&ap->link.device[i])) { +ata_link_for_each_dev (dev, link) { +if (ata_dev_ready (dev)) { ap->ops->set_mode (ap);break ; }
@@ -2157,11 +2155,9 @@ int ata_set_mode(struct ata_port *ap, st }/* step 1: calculate xfer_mask */ -for (i =0 ; i <ATA_MAX_DEVICES ; i++) { +ata_link_for_each_dev (dev, link) {unsigned int pio_mask, dma_mask; - dev = &ap->link.device[i]; -if (!ata_dev_enabled (dev))continue ;
@@ -2180,8 +2176,7 @@ int ata_set_mode(struct ata_port *ap, st goto out;/* step 2: always set host PIO timings */ -for (i =0 ; i <ATA_MAX_DEVICES ; i++) { - dev = &ap->link.device[i]; +ata_link_for_each_dev (dev, link) {if (!ata_dev_enabled (dev))continue ;
@@ -2198,9 +2193,7 @@ int ata_set_mode(struct ata_port *ap, st }/* step 3: set host DMA timings */ -for (i =0 ; i <ATA_MAX_DEVICES ; i++) { - dev = &ap->link.device[i]; - +ata_link_for_each_dev (dev, link) {if (!ata_dev_enabled (dev) || !dev->dma_mode)continue ;
@@ -2211,9 +2204,7 @@ int ata_set_mode(struct ata_port *ap, st }/* step 4: update devices' xfer mode */ -for (i =0 ; i <ATA_MAX_DEVICES ; i++) { - dev = &ap->link.device[i]; - +ata_link_for_each_dev (dev, link) {/* don't udpate suspended devices' xfer mode */ if (!ata_dev_ready (dev))continue ;
@@ -3125,8 +3116,8 @@ static void ata_dev_xfermask(struct ata_struct ata_link *link = dev->link;struct ata_port *ap = link->ap;struct ata_host_set *hs = ap->host_set; +struct ata_device *d;unsigned long xfer_mask; -int i; xfer_mask =ata_pack_xfermask (ap->pio_mask, ap->mwdma_mask, ap->udma_mask);
@@ -3137,10 +3128,8 @@ static void ata_dev_xfermask(struct ata_if (ap->cbl ==ATA_CBL_PATA40 ) xfer_mask &= ~(0xF8 <<ATA_SHIFT_UDMA ); -/* FIXME: Use port-wide xfermask for now */ -for (i =0 ; i <ATA_MAX_DEVICES ; i++) { -struct ata_device *d = &link->device[i]; - +/* FIXME: Use link-wide xfermask for now */ +ata_link_for_each_dev (d, link) {if (ata_dev_absent (d))continue ;
@@ -5149,7 +5138,7 @@ static int ata_host_set_request_pm(struc*/ int ata_host_set_suspend (struct ata_host_set *host_set,pm_message_t mesg) { -int i, j, rc; +int i, rc; rc =ata_host_set_request_pm (host_set, mesg,0 ,ATA_EHI_QUIET ,1 );if (rc)
@@ -5161,10 +5150,9 @@ int ata_host_set_suspend(struct ata_host*/ for (i =0 ; i < host_set->n_ports; i++) {struct ata_port *ap = host_set->ports[i]; +struct ata_device *dev; -for (j =0 ; j <ATA_MAX_DEVICES ; j++) { -struct ata_device *dev = &ap->link.device[j]; - +ata_link_for_each_dev (dev, &ap->link) {if (ata_dev_ready (dev)) {ata_port_printk (ap,KERN_WARNING , "suspend failed, device %d "
@@ -5384,7 +5372,7 @@ #endif ap->link.ap = ap; -for (i =0 ; i <ATA_MAX_DEVICES ; i++) { +for (i =0 ; i <ata_link_max_devices (&ap->link); i++) {struct ata_device *dev = &ap->link.device[i]; dev->link = &ap->link; dev->devno = i;
@@ -5570,7 +5558,8 @@ int ata_device_add(const struct ata_prob/* kick EH for boot probing */ spin_lock_irqsave (ap->lock, flags); - ehi->probe_mask = (1 <<ATA_MAX_DEVICES ) -1 ; + ehi->probe_mask = + (1 <<ata_link_max_devices (&ap->link)) -1 ; ehi->action |=ATA_EH_SOFTRESET ; ehi->flags |=ATA_EHI_NO_AUTOPSY |ATA_EHI_QUIET ;
@@ -5635,7 +5624,7 @@ err_free_ret:void ata_port_detach (struct ata_port *ap) {unsigned long flags; -int i; +struct ata_device *dev;if (!ap->ops->error_handler)return ;
@@ -5652,8 +5641,8 @@ void ata_port_detach(struct ata_port *ap*/ spin_lock_irqsave (ap->lock, flags); -for (i =0 ; i <ATA_MAX_DEVICES ; i++) -ata_dev_disable (&ap->link.device[i]); +ata_link_for_each_dev (dev, &ap->link) +ata_dev_disable (dev);spin_unlock_irqrestore (ap->lock, flags);
drivers/scsi/libata-eh.c +67 -75
327 lines not on this page · raw message
drivers/scsi/libata-scsi.c +9 -15
@@ -511,7 +511,7 @@ int ata_scsi_device_resume(struct scsi_d/* We don't want autopsy and verbose EH messages. Disable * those if we're the only device on this link. */ -if (ata_port_max_devices (ap) ==1 ) +if (ata_link_max_devices (dev->link) ==1 ) ehi->flags |=ATA_EHI_NO_AUTOPSY |ATA_EHI_QUIET ;ata_port_schedule_eh (ap);
@@ -2466,7 +2466,7 @@ static unsigned int atapi_xlat(struct atstatic struct ata_device *ata_find_dev (struct ata_port *ap,int id) { -if (likely (id <ATA_MAX_DEVICES )) +if (likely (id <ata_link_max_devices (&ap->link)))return &ap->link.device[id];return NULL ; }
@@ -2920,19 +2920,18 @@ void ata_scsi_simulate(struct ata_devicevoid ata_scsi_scan_host (struct ata_port *ap) { -unsigned int i; +struct ata_device *dev;if (ap->flags &ATA_FLAG_DISABLED )return ; -for (i =0 ; i <ATA_MAX_DEVICES ; i++) { -struct ata_device *dev = &ap->link.device[i]; +ata_link_for_each_dev (dev, &ap->link) {struct scsi_device *sdev;if (!ata_dev_enabled (dev) || dev->sdev)continue ; - sdev =__scsi_add_device (ap->host,0 , i,0 ,NULL ); + sdev =__scsi_add_device (ap->host,0 , dev->devno,0 ,NULL );if (!IS_ERR (sdev)) { dev->sdev = sdev;scsi_device_put (sdev);
@@ -3038,7 +3037,7 @@ static void ata_scsi_remove_dev(struct avoid ata_scsi_hotplug (void *data) {struct ata_port *ap = data; -int i; +struct ata_device *dev;if (ap->pflags &ATA_PFLAG_UNLOADING ) {DPRINTK ("ENTER/EXIT - unloading\n" );
@@ -3048,8 +3047,7 @@ void ata_scsi_hotplug(void *data)DPRINTK ("ENTER\n" );/* unplug detached devices */ -for (i =0 ; i <ATA_MAX_DEVICES ; i++) { -struct ata_device *dev = &ap->link.device[i]; +ata_link_for_each_dev (dev, &ap->link) {unsigned long flags;if (!(dev->flags &ATA_DFLAG_DETACHED ))
@@ -3069,8 +3067,7 @@ void ata_scsi_hotplug(void *data)* failed silently. Requeue if there are enabled but * unattached devices. */ -for (i =0 ; i <ATA_MAX_DEVICES ; i++) { -struct ata_device *dev = &ap->link.device[i]; +ata_link_for_each_dev (dev, &ap->link) {if (ata_dev_enabled (dev) && !dev->sdev) {queue_delayed_work (ata_aux_wq, &ap->hotplug_task,HZ );break ;
@@ -3151,11 +3148,8 @@ void ata_scsi_dev_rescan(void *data) {struct ata_port *ap = data;struct ata_device *dev; -unsigned int i; - -for (i =0 ; i <ATA_MAX_DEVICES ; i++) { - dev = &ap->link.device[i]; +ata_link_for_each_dev (dev, &ap->link) {if (ata_dev_enabled (dev) && dev->sdev)scsi_rescan_device (&(dev->sdev->sdev_gendev)); }
include/linux/libata.h +11 -3
@@ -986,15 +986,23 @@ static inline unsigned int ata_dev_ready }/* -* port helpers +* link helpers */ -static inline int ata_port_max_devices (const struct ata_port *ap) +static inline int ata_link_max_devices (const struct ata_link *link) { -if (ap->flags &ATA_FLAG_SLAVE_POSS ) +if (link->ap->flags &ATA_FLAG_SLAVE_POSS )return 2 ;return 1 ; } +#define ata_port_for_each_link (lk, ap) \ + for ((lk) = &(ap)->link; (lk); (lk) = NULL) + +#define ata_link_for_each_dev (dev, link) \ + for ((dev) = (link)->device; \ + (dev) - (link)->device < ata_link_max_devices(link) || (dev = NULL); \ + (dev)++) +static inline u8 ata_chk_status (struct ata_port *ap) {
Signature · 1 line
1.3.2
PATCH 5/17 libata-link: linkify PHY-related functions
In reply to Tejun HeoMake the following PHY-related functions to deal with ata_link instead of ata_port.
* sata_print_link_status()
* sata_down_spd_limit()
* ata_set_sata_spd_limit() and friends
* sata_link_debounce/resume()
* sata_scr_valid/read/write/write_flush()
* ata_link_on/offline()
This patch introduces no behavior change.
---
drivers/scsi/ahci.c | 6 + drivers/scsi/libata-bmdma.c | 2 drivers/scsi/libata-core.c | 229 +++++++++++++++++++++++-------------------- drivers/scsi/libata-eh.c | 24 ++--- drivers/scsi/libata.h | 4 - drivers/scsi/sata_mv.c | 14 +-- drivers/scsi/sata_sil24.c | 10 +- include/linux/libata.h | 19 ++-- 8 files changed, 164 insertions(+), 144 deletions(-)
e547f513500d9d4e27c46afa390647f4a9f21a22
drivers/scsi/ahci.c +3 -3
@@ -621,7 +621,7 @@ static int ahci_softreset(struct ata_porDPRINTK ("ENTER\n" ); -if (ata_port_offline (ap)) { +if (ata_link_offline (&ap->link)) {DPRINTK ("PHY reports no device\n" ); *class =ATA_DEV_NONE ;return 0 ;
@@ -695,7 +695,7 @@ static int ahci_softreset(struct ata_pormsleep (150 ); *class =ATA_DEV_NONE ; -if (ata_port_online (ap)) { +if (ata_link_online (&ap->link)) {if (ata_busy_sleep (ap,ATA_TMOUT_BOOT_QUICK ,ATA_TMOUT_BOOT )) { rc = -EIO ; reason ="device not ready" ;
@@ -734,7 +734,7 @@ static int ahci_hardreset(struct ata_porahci_start_engine (ap); -if (rc ==0 &&ata_port_online (ap)) +if (rc ==0 &&ata_link_online (&ap->link)) *class =ahci_dev_classify (ap);if (*class ==ATA_DEV_UNKNOWN ) *class =ATA_DEV_NONE ;
drivers/scsi/libata-bmdma.c +1 -1
@@ -776,7 +776,7 @@ void ata_bmdma_error_handler(struct ata_ata_reset_fn_t hardreset; hardreset =NULL ; -if (sata_scr_valid (ap)) +if (sata_scr_valid (&ap->link)) hardreset = sata_std_hardreset; ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset, hardreset,
drivers/scsi/libata-core.c +123 -106
638 lines not on this page · raw message
drivers/scsi/libata-eh.c +13 -11
@@ -1273,7 +1273,7 @@ static int ata_eh_speed_down(struct ata_return 0 ;/* speed down SATA link speed if possible */ -if (sata_down_spd_limit (dev->link->ap) ==0 ) +if (sata_down_spd_limit (dev->link) ==0 )return ATA_EH_HARDRESET ;/* lower transfer mode */
@@ -1298,7 +1298,8 @@ static int ata_eh_speed_down(struct ata_*/ static void ata_eh_autopsy (struct ata_port *ap) { -struct ata_eh_context *ehc = &ap->link.eh_context; +struct ata_link *link = &ap->link; +struct ata_eh_context *ehc = &link->eh_context;unsigned int action = ehc->i.action;struct ata_device *failed_dev =NULL ;unsigned int all_err_mask =0 ;
@@ -1312,7 +1313,7 @@ static void ata_eh_autopsy(struct ata_poreturn ;/* obtain and analyze SError */ - rc =sata_scr_read (ap,SCR_ERROR , &serror); + rc =sata_scr_read (link,SCR_ERROR , &serror);if (rc ==0 ) { ehc->i.serror |= serror;ata_eh_analyze_serror (ap);
@@ -1501,7 +1502,8 @@ static int ata_eh_reset(struct ata_port ata_prereset_fn_t prereset, ata_reset_fn_t softreset, ata_reset_fn_t hardreset, ata_postreset_fn_t postreset) { - struct ata_eh_context *ehc = &ap->link.eh_context; + struct ata_link *link = &ap->link; +struct ata_eh_context *ehc = &link->eh_context;unsigned int *classes = ehc->classes;int tries =ATA_EH_RESET_TRIES ;int verbose = !(ehc->i.flags &ATA_EHI_QUIET );
@@ -1515,7 +1517,7 @@ static int ata_eh_reset(struct ata_port*/ action = ehc->i.action; ehc->i.action &= ~ATA_EH_RESET_MASK ; -if (softreset && (!hardreset || (!sata_set_spd_needed (ap) && +if (softreset && (!hardreset || (!sata_set_spd_needed (link) && !(action &ATA_EH_HARDRESET )))) ehc->i.action |=ATA_EH_SOFTRESET ;else
@@ -1537,7 +1539,7 @@ static int ata_eh_reset(struct ata_port reset = softreset; else {/* prereset told us not to reset, bang classes and return */ -ata_link_for_each_dev (dev, &ap->link) +ata_link_for_each_dev (dev, link) classes[dev->devno] =ATA_DEV_NONE ;return 0 ; }
@@ -1605,7 +1607,7 @@ static int ata_eh_reset(struct ata_portssleep (5 );if (reset == hardreset) -sata_down_spd_limit (ap); +sata_down_spd_limit (link);if (hardreset) reset = hardreset; goto retry;
@@ -1615,7 +1617,7 @@ static int ata_eh_reset(struct ata_port/* After the reset, the device state is PIO 0 and the * controller state is undefined. Record the mode. */ -ata_link_for_each_dev (dev, &ap->link) +ata_link_for_each_dev (dev, link) dev->pio_mode =XFER_PIO_0 ;if (postreset)
@@ -1643,7 +1645,7 @@ static int ata_eh_revalidate_and_attach(unsigned int action =ata_eh_dev_action (dev);if (action &ATA_EH_REVALIDATE &&ata_dev_ready (dev)) { -if (ata_port_offline (ap)) { +if (ata_link_offline (dev->link)) { rc = -EIO ;break ; }
@@ -1899,7 +1901,7 @@ static void ata_eh_handle_dev_fail(struc ehc->tries[dev->devno] =0 ;break ;case -EIO : -sata_down_spd_limit (ap); +sata_down_spd_limit (&ap->link);default : ehc->tries[dev->devno]--; if (down_xfermask &&
@@ -1912,7 +1914,7 @@ static void ata_eh_handle_dev_fail(strucata_dev_disable (dev);/* detach if offline */ -if (ata_port_offline (ap)) +if (ata_link_offline (&ap->link))ata_eh_detach_dev (dev);/* probe if requested */
drivers/scsi/libata.h +2 -2
@@ -54,8 +54,8 @@ extern unsigned int ata_do_simple_cmd(stextern int ata_dev_read_id (struct ata_device *dev,unsigned int *p_class,int post_reset,u16 *id);extern int ata_dev_configure (struct ata_device *dev,int print_info); -extern int sata_down_spd_limit (struct ata_port *ap); -extern int sata_set_spd_needed (struct ata_port *ap); +extern int sata_down_spd_limit (struct ata_link *link); +extern int sata_set_spd_needed (struct ata_link *link);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 void ata_qc_free (struct ata_queued_cmd *qc);
drivers/scsi/sata_mv.c +7 -7
@@ -1310,8 +1310,8 @@ static void mv_err_intr(struct ata_port edma_err_cause =readl (port_mmio +EDMA_ERR_IRQ_CAUSE_OFS );if (EDMA_ERR_SERR & edma_err_cause) { -sata_scr_read (ap,SCR_ERROR , &serr); -sata_scr_write_flush (ap,SCR_ERROR , serr); +sata_scr_read (&ap->link,SCR_ERROR , &serr); +sata_scr_write_flush (&ap->link,SCR_ERROR , serr); }if (EDMA_ERR_SELF_DIS & edma_err_cause) {struct mv_port_priv *pp = ap->private_data;
@@ -1952,15 +1952,15 @@ static void __mv_phy_reset(struct ata_po/* Issue COMRESET via SControl */ comreset_retry: -sata_scr_write_flush (ap,SCR_CONTROL ,0x301 ); +sata_scr_write_flush (&ap->link,SCR_CONTROL ,0x301 );__msleep (1 , can_sleep); -sata_scr_write_flush (ap,SCR_CONTROL ,0x300 ); +sata_scr_write_flush (&ap->link,SCR_CONTROL ,0x300 );__msleep (20 , can_sleep); timeout = jiffies +msecs_to_jiffies (200 ); do { - sata_scr_read(ap, SCR_STATUS, &sstatus); + sata_scr_read(&ap->link, SCR_STATUS, &sstatus); sstatus &= 0x3; if ((sstatus == 3) || (sstatus == 0)) break;
@@ -1978,10 +1978,10 @@ comreset_retry:"SCtrl 0x%08x\n" ,mv_scr_read (ap,SCR_STATUS ), mv_scr_read(ap, SCR_ERROR), mv_scr_read(ap, SCR_CONTROL)); -if (ata_port_online (ap)) { +if (ata_link_online (&ap->link)) {ata_port_probe (ap); }else { -sata_scr_read (ap,SCR_STATUS , &sstatus); +sata_scr_read (&ap->link,SCR_STATUS , &sstatus);ata_port_printk (ap,KERN_INFO ,"no device found (phy stat %08x)\n" , sstatus);ata_port_disable (ap);
drivers/scsi/sata_sil24.c +5 -5
@@ -546,7 +546,7 @@ static int sil24_softreset(struct ata_poDPRINTK ("ENTER\n" ); -if (ata_port_offline (ap)) { +if (ata_link_offline (&ap->link)) {DPRINTK ("PHY reports no device\n" ); *class =ATA_DEV_NONE ; goto out;
@@ -603,10 +603,10 @@ static int sil24_hardreset(struct ata_pou32 tmp;/* sil24 does the right thing(tm) without any protection */ -sata_set_spd (ap); +sata_set_spd (&ap->link); tout_msec =100 ; -if (ata_port_online (ap)) +if (ata_link_online (&ap->link)) tout_msec =5000 ;writel (PORT_CS_DEV_RST , port +PORT_CTRL_STAT );
@@ -616,14 +616,14 @@ static int sil24_hardreset(struct ata_po/* SStatus oscillates between zero and valid status after * DEV_RST, debounce it. */ - rc =sata_phy_debounce (ap, sata_deb_timing_long); + rc =sata_link_debounce (&ap->link, sata_deb_timing_long);if (rc) { reason ="PHY debouncing failed" ; goto err; }if (tmp &PORT_CS_DEV_RST ) { -if (ata_port_offline (ap)) +if (ata_link_offline (&ap->link))return 0 ; reason ="link not ready" ; goto err;
include/linux/libata.h +10 -9
@@ -676,9 +676,10 @@ extern void ata_port_probe(struct ata_poextern void __sata_phy_reset (struct ata_port *ap);extern void sata_phy_reset (struct ata_port *ap);extern void ata_bus_reset (struct ata_port *ap); -extern 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 sata_set_spd (struct ata_link *link); +extern int sata_link_debounce (struct ata_link *link, +const unsigned long *params); +extern int sata_link_resume (struct ata_link *link,const unsigned long *params);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);
@@ -706,12 +707,12 @@ extern int ata_scsi_ioctl(struct scsi_deextern int ata_scsi_queuecmd (struct scsi_cmnd *cmd,void (*done)(struct scsi_cmnd *));extern int ata_scsi_release (struct Scsi_Host *host);extern unsigned int ata_host_intr (struct ata_port *ap,struct ata_queued_cmd *qc); -extern int sata_scr_valid (struct ata_port *ap); -extern int sata_scr_read (struct ata_port *ap,int reg,u32 *val); -extern int sata_scr_write (struct ata_port *ap,int reg,u32 val); -extern int sata_scr_write_flush (struct ata_port *ap,int reg,u32 val); -extern int ata_port_online (struct ata_port *ap); -extern int ata_port_offline (struct ata_port *ap); +extern int sata_scr_valid (struct ata_link *link); +extern int sata_scr_read (struct ata_link *link,int reg,u32 *val); +extern int sata_scr_write (struct ata_link *link,int reg,u32 val); +extern int sata_scr_write_flush (struct ata_link *link,int reg,u32 val); +extern int ata_link_online (struct ata_link *link); +extern int ata_link_offline (struct ata_link *link);extern int ata_scsi_device_resume (struct scsi_device *);extern int ata_scsi_device_suspend (struct scsi_device *,pm_message_t state); extern int ata_host_set_suspend(struct ata_host_set *host_set,
Signature · 1 line
1.3.2
PATCH 6/17 libata-link: linkify EH action helpers
In reply to Tejun HeoMake ata_eh_about_to_do() and ata_eh_done() deal with ata_link instead of ata_port.
This patch introduces no behavior change.
---
drivers/scsi/libata-eh.c | 39 ++++++++++++++++++++------------------- 1 files changed, 20 insertions(+), 19 deletions(-)
b01d20e457820a1e839d5944f9d654ef5963fa33
drivers/scsi/libata-eh.c +20 -19
@@ -772,27 +772,28 @@ static void ata_eh_detach_dev(struct ata/** * ata_eh_about_to_do - about to perform eh_action -* @ap: target ATA port +* @link: target ATA link * @dev: target ATA dev for per-dev action (can be NULL) * @action: action about to be performed * * Called just before performing EH actions to clear related bits -* in @ap->link.eh_info such that eh actions are not -* unnecessarily repeated. +* in @link->eh_info such that eh actions are not unnecessarily +* repeated. * * LOCKING: * None. */ -static void ata_eh_about_to_do (struct ata_port *ap,struct ata_device *dev, +static void ata_eh_about_to_do (struct ata_link *link,struct ata_device *dev,unsigned int action) { +struct ata_port *ap = link->ap;unsigned long flags;spin_lock_irqsave (ap->lock, flags); -ata_eh_clear_action (&ap->link, dev, &ap->link.eh_info, action); +ata_eh_clear_action (link, dev, &link->eh_info, action); -if (!(ap->link.eh_context.i.flags &ATA_EHI_QUIET )) +if (!(link->eh_context.i.flags &ATA_EHI_QUIET )) ap->pflags |=ATA_PFLAG_RECOVERED ;spin_unlock_irqrestore (ap->lock, flags);
@@ -800,20 +801,20 @@ static void ata_eh_about_to_do(struct at/** * ata_eh_done - EH action complete -* @ap: target ATA port +* @link: target ATA link * @dev: target ATA dev for per-dev action (can be NULL) * @action: action just completed * * Called right after performing EH actions to clear related bits -* in @ap->link.eh_context. +* in @link->eh_context. * * LOCKING: * None. */ -static void ata_eh_done (struct ata_port *ap,struct ata_device *dev, +static void ata_eh_done (struct ata_link *link,struct ata_device *dev,unsigned int action) { -ata_eh_clear_action (&ap->link, dev, &ap->link.eh_context.i, action); +ata_eh_clear_action (link, dev, &link->eh_context.i, action); }/**
@@ -1561,7 +1562,7 @@ static int ata_eh_reset(struct ata_port reset == softreset ? "soft" : "hard");/* reset */ -ata_eh_about_to_do (ap,NULL ,ATA_EH_RESET_MASK ); +ata_eh_about_to_do (link,NULL ,ATA_EH_RESET_MASK ); ehc->i.flags |=ATA_EHI_DID_RESET ; rc =ata_do_reset (ap, reset, classes);
@@ -1580,7 +1581,7 @@ static int ata_eh_reset(struct ata_portreturn -EINVAL ; } -ata_eh_about_to_do (ap,NULL ,ATA_EH_RESET_MASK ); +ata_eh_about_to_do (link,NULL ,ATA_EH_RESET_MASK ); rc =ata_do_reset (ap, reset, classes); if (rc == 0 && classify &&
@@ -1624,7 +1625,7 @@ static int ata_eh_reset(struct ata_portpostreset (ap, classes);/* reset successful, schedule revalidation */ -ata_eh_done (ap,NULL ,ATA_EH_RESET_MASK ); +ata_eh_done (link,NULL ,ATA_EH_RESET_MASK ); ehc->i.action |=ATA_EH_REVALIDATE ; }
@@ -1650,13 +1651,13 @@ static int ata_eh_revalidate_and_attach(break ; } -ata_eh_about_to_do (ap, dev,ATA_EH_REVALIDATE ); +ata_eh_about_to_do (&ap->link, dev,ATA_EH_REVALIDATE ); rc =ata_dev_revalidate (dev, ehc->i.flags &ATA_EHI_DID_RESET );if (rc)break ; -ata_eh_done (ap, dev,ATA_EH_REVALIDATE ); +ata_eh_done (&ap->link, dev,ATA_EH_REVALIDATE );/* schedule the scsi_rescan_device() here */ queue_work (ata_aux_wq, &(ap->scsi_rescan_task));
@@ -1720,7 +1721,7 @@ static int ata_eh_suspend(struct ata_porWARN_ON (dev->flags &ATA_DFLAG_SUSPENDED ); -ata_eh_about_to_do (ap, dev,ATA_EH_SUSPEND ); +ata_eh_about_to_do (&ap->link, dev,ATA_EH_SUSPEND );if (dev->class ==ATA_DEV_ATA && !(action &ATA_EH_PM_FREEZE )) {/* flush cache */
@@ -1743,7 +1744,7 @@ static int ata_eh_suspend(struct ata_por dev->flags |=ATA_DFLAG_SUSPENDED ;spin_unlock_irqrestore (ap->lock, flags); -ata_eh_done (ap, dev,ATA_EH_SUSPEND ); +ata_eh_done (&ap->link, dev,ATA_EH_SUSPEND ); }if (rc)
@@ -1813,7 +1814,7 @@ static int ata_eh_resume(struct ata_portif (!ata_dev_enabled (dev) || !(action &ATA_EH_RESUME ))continue ; -ata_eh_about_to_do (ap, dev,ATA_EH_RESUME ); +ata_eh_about_to_do (&ap->link, dev,ATA_EH_RESUME );if (dev->class ==ATA_DEV_ATA && !(action &ATA_EH_PM_FREEZE )) { err_mask = ata_do_simple_cmd(dev,
@@ -1827,7 +1828,7 @@ static int ata_eh_resume(struct ata_port } } -ata_eh_done (ap, dev,ATA_EH_RESUME ); +ata_eh_done (&ap->link, dev,ATA_EH_RESUME ); }if (rc)
Signature · 1 line
1.3.2
PATCH 7/17 libata-link: linkify reset
In reply to Tejun HeoMake reset methods and related functions deal with ata_link instead of ata_port.
* ata_do_reset()
* ata_eh_reset()
* all prereset/reset/postreset methods and related functions
This patch introduces no behavior change.
---
drivers/scsi/ahci.c | 31 +++++++++++++++++------------ drivers/scsi/ata_piix.c | 14 +++++++------ drivers/scsi/libata-core.c | 47 ++++++++++++++++++++++---------------------- drivers/scsi/libata-eh.c | 35 ++++++++++++++++----------------- drivers/scsi/sata_nv.c | 4 ++-- drivers/scsi/sata_sil24.c | 20 ++++++++++--------- include/linux/libata.h | 15 +++++++------- 7 files changed, 87 insertions(+), 79 deletions(-)
f341ec269e499b6634b5de2fa0ee61bf69f246fd
drivers/scsi/ahci.c +18 -13
@@ -596,19 +596,22 @@ static int ahci_clo(struct ata_port *ap)return 0 ; } -static int ahci_prereset (struct ata_port *ap) +static int ahci_prereset (struct ata_link *link) { +struct ata_port *ap = link->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); +return ata_std_prereset (link); } -static int ahci_softreset (struct ata_port *ap,unsigned int *class) +static int ahci_softreset (struct ata_link *link,unsigned int *class) { +struct ata_port *ap = link->ap;struct ahci_port_priv *pp = ap->private_data;void __iomem *mmio = ap->host_set->mmio_base;void __iomem *port_mmio =ahci_port_base (mmio, ap->port_no);
@@ -621,7 +624,7 @@ static int ahci_softreset(struct ata_porDPRINTK ("ENTER\n" ); -if (ata_link_offline (&ap->link)) { +if (ata_link_offline (link)) {DPRINTK ("PHY reports no device\n" ); *class =ATA_DEV_NONE ;return 0 ;
@@ -651,7 +654,7 @@ static int ahci_softreset(struct ata_por/* restart engine */ ahci_start_engine (ap); -ata_tf_init (ap->link.device, &tf); +ata_tf_init (link->device, &tf); fis = pp->cmd_tbl;/* issue the first D2H Register FIS */
@@ -695,7 +698,7 @@ static int ahci_softreset(struct ata_pormsleep (150 ); *class =ATA_DEV_NONE ; -if (ata_link_online (&ap->link)) { +if (ata_link_online (link)) {if (ata_busy_sleep (ap,ATA_TMOUT_BOOT_QUICK ,ATA_TMOUT_BOOT )) { rc = -EIO ; reason ="device not ready" ;
@@ -710,12 +713,13 @@ static int ahci_softreset(struct ata_por fail_restart:ahci_start_engine (ap); fail: -ata_port_printk (ap,KERN_ERR ,"softreset failed (%s)\n" , reason); +ata_link_printk (link,KERN_ERR ,"softreset failed (%s)\n" , reason);return rc; } -static int ahci_hardreset (struct ata_port *ap,unsigned int *class) +static int ahci_hardreset (struct ata_link *link,unsigned int *class) { +struct ata_port *ap = link->ap;struct ahci_port_priv *pp = ap->private_data;u8 *d2h_fis = pp->rx_fis +RX_FIS_D2H_REG ;struct ata_taskfile tf;
@@ -726,15 +730,15 @@ static int ahci_hardreset(struct ata_porahci_stop_engine (ap);/* clear D2H reception area to properly wait for D2H FIS */ -ata_tf_init (ap->link.device, &tf); +ata_tf_init (link->device, &tf); tf.command =0xff ;ata_tf_to_fis (&tf, d2h_fis,0 ); - rc =sata_std_hardreset (ap, class); + rc =sata_std_hardreset (link, class);ahci_start_engine (ap); -if (rc ==0 &&ata_link_online (&ap->link)) +if (rc ==0 &&ata_link_online (link)) *class =ahci_dev_classify (ap);if (*class ==ATA_DEV_UNKNOWN ) *class =ATA_DEV_NONE ;
@@ -743,12 +747,13 @@ static int ahci_hardreset(struct ata_porreturn rc; } -static void ahci_postreset (struct ata_port *ap,unsigned int *class) +static void ahci_postreset (struct ata_link *link,unsigned int *class) { +struct ata_port *ap = link->ap;void __iomem *port_mmio = (void __iomem *) ap->ioaddr.cmd_addr;u32 new_tmp, tmp; -ata_std_postreset (ap, class); +ata_std_postreset (link, class);/* Make sure port's ATAPI bit is set appropriately */ new_tmp = tmp =readl (port_mmio +PORT_CMD );
drivers/scsi/ata_piix.c +8 -6
@@ -462,15 +462,16 @@ cbl40:/** * piix_pata_prereset - prereset for PATA host controller -* @ap: Target port +* @link: Target link * * Prereset including cable detection. * * LOCKING: * None (inherited from caller). */ -static int piix_pata_prereset (struct ata_port *ap) +static int piix_pata_prereset (struct ata_link *link) { +struct ata_port *ap = link->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])) {
@@ -481,7 +482,7 @@ static int piix_pata_prereset(struct atapiix_pata_cbl_detect (ap); -return ata_std_prereset (ap); +return ata_std_prereset (link); }static void piix_pata_error_handler (struct ata_port *ap)
@@ -492,7 +493,7 @@ static void piix_pata_error_handler(stru/** * piix_sata_prereset - prereset for SATA host controller -* @ap: Target port +* @link: Target link * * Reads and configures SATA PCI device's PCI config register * Port Configuration and Status (PCS) to determine port and
@@ -505,8 +506,9 @@ static void piix_pata_error_handler(stru* RETURNS: * 0 if device is present, -ENODEV otherwise. */ -static int piix_sata_prereset (struct ata_port *ap) +static int piix_sata_prereset (struct ata_link *link) { +struct ata_port *ap = link->ap;struct pci_dev *pdev =to_pci_dev (ap->host_set->dev);const unsigned int *map = ap->host_set->private_data;int base =2 * ap->hard_port_no;
@@ -553,7 +555,7 @@ static int piix_sata_prereset(struct atareturn 0 ; } -return ata_std_prereset (ap); +return ata_std_prereset (link); }static void piix_sata_error_handler (struct ata_port *ap)
drivers/scsi/libata-core.c +23 -24
137 lines not on this page · raw message
drivers/scsi/libata-eh.c +17 -18
@@ -1456,16 +1456,16 @@ static void ata_eh_report(struct ata_por } } -static int ata_do_reset (struct ata_port *ap,ata_reset_fn_t reset, +static int ata_do_reset (struct ata_link *link,ata_reset_fn_t reset,unsigned int *classes) {struct ata_device *dev;int rc; -ata_link_for_each_dev (dev, &ap->link) +ata_link_for_each_dev (dev, link) classes[dev->devno] =ATA_DEV_UNKNOWN ; - rc =reset (ap, classes); + rc =reset (link, classes);if (rc)return rc;
@@ -1473,12 +1473,12 @@ static int ata_do_reset(struct ata_port* is complete and convert all ATA_DEV_UNKNOWN to * ATA_DEV_NONE. */ -ata_link_for_each_dev (dev, &ap->link) +ata_link_for_each_dev (dev, link)if (classes[dev->devno] !=ATA_DEV_UNKNOWN )break ;if (dev) { -ata_link_for_each_dev (dev, &ap->link) { +ata_link_for_each_dev (dev, link) {if (classes[dev->devno] ==ATA_DEV_UNKNOWN ) classes[dev->devno] =ATA_DEV_NONE ; }
@@ -1499,11 +1499,10 @@ static int ata_eh_followup_srst_needed(ireturn 0 ; } -static int ata_eh_reset (struct ata_port *ap,int classify, +static int ata_eh_reset (struct ata_link *link,int classify,ata_prereset_fn_t prereset,ata_reset_fn_t softreset,ata_reset_fn_t hardreset,ata_postreset_fn_t postreset) { -struct ata_link *link = &ap->link;struct ata_eh_context *ehc = &link->eh_context;unsigned int *classes = ehc->classes;int tries =ATA_EH_RESET_TRIES ;
@@ -1525,9 +1524,9 @@ static int ata_eh_reset(struct ata_port ehc->i.action |=ATA_EH_HARDRESET ;if (prereset) { - rc =prereset (ap); + rc =prereset (link);if (rc) { -ata_port_printk (ap,KERN_ERR , +ata_link_printk (link,KERN_ERR ,"prereset failed (errno=%d)\n" , rc);return rc; }
@@ -1547,7 +1546,7 @@ static int ata_eh_reset(struct ata_port/* did prereset() screw up? if so, fix up to avoid oopsing */ if (!reset) { -ata_port_printk (ap,KERN_ERR ,"BUG: prereset() requested " +ata_link_printk (link,KERN_ERR ,"BUG: prereset() requested " "invalid reset type\n" );if (softreset) reset = softreset;
@@ -1558,14 +1557,14 @@ static int ata_eh_reset(struct ata_port retry:/* shut up during boot probing */ if (verbose) -ata_port_printk (ap,KERN_INFO ,"%s resetting port\n" , +ata_link_printk (link,KERN_INFO ,"%s resetting port\n" , reset == softreset ?"soft" :"hard" );/* reset */ ata_eh_about_to_do (link,NULL ,ATA_EH_RESET_MASK ); ehc->i.flags |=ATA_EHI_DID_RESET ; - rc =ata_do_reset (ap, reset, classes); + rc =ata_do_reset (link, reset, classes); did_followup_srst =0 ; if (reset == hardreset &&
@@ -1575,18 +1574,18 @@ static int ata_eh_reset(struct ata_port reset = softreset;if (!reset) { -ata_port_printk (ap,KERN_ERR , +ata_link_printk (link,KERN_ERR ,"follow-up softreset required " "but no softreset avaliable\n" );return -EINVAL ; }ata_eh_about_to_do (link,NULL ,ATA_EH_RESET_MASK ); - rc =ata_do_reset (ap, reset, classes); + rc =ata_do_reset (link, reset, classes);if (rc ==0 && classify && classes[0 ] ==ATA_DEV_UNKNOWN ) { -ata_port_printk (ap,KERN_ERR , +ata_link_printk (link,KERN_ERR ,"classification failed\n" );return -EINVAL ; }
@@ -1603,7 +1602,7 @@ static int ata_eh_reset(struct ata_port }else type ="hard" ; -ata_port_printk (ap,KERN_WARNING , +ata_link_printk (link,KERN_WARNING ,"%sreset failed, retrying in 5 secs\n" , type);ssleep (5 );
@@ -1622,7 +1621,7 @@ static int ata_eh_reset(struct ata_port dev->pio_mode =XFER_PIO_0 ;if (postreset) -postreset (ap, classes); +postreset (link, classes);/* reset successful, schedule revalidation */ ata_eh_done (link,NULL ,ATA_EH_RESET_MASK );
@@ -2008,7 +2007,7 @@ static int ata_eh_recover(struct ata_porif (ehc->i.action &ATA_EH_RESET_MASK ) {ata_eh_freeze_port (ap); - rc =ata_eh_reset (ap,ata_port_nr_vacant (ap), prereset, + rc =ata_eh_reset (&ap->link,ata_port_nr_vacant (ap), prereset, softreset, hardreset, postreset);if (rc) { ata_port_printk(ap, KERN_ERR,
drivers/scsi/sata_nv.c +2 -2
@@ -471,7 +471,7 @@ static void nv_ck804_thaw(struct ata_porwriteb (mask, mmio_base +NV_INT_ENABLE_CK804 ); } -static int nv_hardreset (struct ata_port *ap,unsigned int *class) +static int nv_hardreset (struct ata_link *link,unsigned int *class) {unsigned int dummy;
@@ -479,7 +479,7 @@ static int nv_hardreset(struct ata_port* some controllers. Don't classify on hardreset. For more * info, see http://bugme.osdl.org/show_bug.cgi?id=3352 */ -return sata_std_hardreset (ap, &dummy); +return sata_std_hardreset (link, &dummy); }static void nv_error_handler (struct ata_port *ap)
drivers/scsi/sata_sil24.c +11 -9
@@ -535,8 +535,9 @@ static int sil24_init_port(struct ata_poreturn 0 ; } -static int sil24_softreset (struct ata_port *ap,unsigned int *class) +static int sil24_softreset (struct ata_link *link,unsigned int *class) { +struct ata_port *ap = link->ap;void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;struct sil24_port_priv *pp = ap->private_data;struct sil24_prb *prb = &pp->cmd_block[0 ].ata.prb;
@@ -546,7 +547,7 @@ static int sil24_softreset(struct ata_poDPRINTK ("ENTER\n" ); -if (ata_link_offline (&ap->link)) { +if (ata_link_offline (link)) {DPRINTK ("PHY reports no device\n" ); *class =ATA_DEV_NONE ; goto out;
@@ -591,22 +592,23 @@ static int sil24_softreset(struct ata_poreturn 0 ; err: -ata_port_printk (ap,KERN_ERR ,"softreset failed (%s)\n" , reason); +ata_link_printk (link,KERN_ERR ,"softreset failed (%s)\n" , reason);return -EIO ; } -static int sil24_hardreset (struct ata_port *ap,unsigned int *class) +static int sil24_hardreset (struct ata_link *link,unsigned int *class) { +struct ata_port *ap = link->ap;void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr;const char *reason;int tout_msec, rc;u32 tmp;/* sil24 does the right thing(tm) without any protection */ -sata_set_spd (&ap->link); +sata_set_spd (link); tout_msec =100 ; -if (ata_link_online (&ap->link)) +if (ata_link_online (link)) tout_msec =5000 ;writel (PORT_CS_DEV_RST , port +PORT_CTRL_STAT );
@@ -616,14 +618,14 @@ static int sil24_hardreset(struct ata_po/* SStatus oscillates between zero and valid status after * DEV_RST, debounce it. */ - rc =sata_link_debounce (&ap->link, sata_deb_timing_long); + rc =sata_link_debounce (link, sata_deb_timing_long);if (rc) { reason ="PHY debouncing failed" ; goto err; }if (tmp &PORT_CS_DEV_RST ) { -if (ata_link_offline (&ap->link)) +if (ata_link_offline (link))return 0 ; reason ="link not ready" ; goto err;
@@ -638,7 +640,7 @@ static int sil24_hardreset(struct ata_poreturn -EAGAIN ; err: -ata_port_printk (ap,KERN_ERR ,"hardreset failed (%s)\n" , reason); +ata_link_printk (link,KERN_ERR ,"hardreset failed (%s)\n" , reason);return -EIO ; }
include/linux/libata.h +8 -7
@@ -316,13 +316,14 @@ enum ata_completion_errors {struct scsi_device ;struct ata_port_operations ;struct ata_port ; +struct ata_link ;struct ata_queued_cmd ;/* typedefs */ typedef void (*ata_qc_cb_t ) (struct ata_queued_cmd *qc); -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); +typedef int (*ata_prereset_fn_t )(struct ata_link *link); +typedef int (*ata_reset_fn_t )(struct ata_link *link,unsigned int *classes); +typedef void (*ata_postreset_fn_t )(struct ata_link *link,unsigned int *classes);struct ata_ioports {unsigned long cmd_addr;
@@ -680,10 +681,10 @@ extern int sata_set_spd(struct ata_linkextern int sata_link_debounce (struct ata_link *link,const unsigned long *params);extern int sata_link_resume (struct ata_link *link,const unsigned long *params); -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); -extern void ata_std_postreset (struct ata_port *ap,unsigned int *classes); +extern int ata_std_prereset (struct ata_link *link); +extern int ata_std_softreset (struct ata_link *link,unsigned int *classes); +extern int sata_std_hardreset (struct ata_link *link,unsigned int *class); +extern void ata_std_postreset (struct ata_link *link,unsigned int *classes);extern void sata_std_hp_poll_activate (struct ata_port *ap);extern int sata_std_hp_poll (struct ata_port *ap);extern int ata_dev_revalidate (struct ata_device *dev,int post_reset);
Signature · 1 line
1.3.2
PATCH 8/17 libata-link: linkify config/EH related functions
In reply to Tejun HeoMake the following functions deal with ata_link instead of ata_port.
* ata_set_mode()
* ata_eh_autopsy() and related functions
* ata_eh_report() and related functions
* suspend/resume related functions
* ata_eh_recover() and related functions
---
drivers/scsi/libata-core.c | 8 +- drivers/scsi/libata-eh.c | 161 +++++++++++++++++++++++--------------------- drivers/scsi/libata.h | 3 + 3 files changed, 91 insertions(+), 81 deletions(-)
9f6869b65ed5dc741ca33747d34c7ebb3186e495
drivers/scsi/libata-core.c +4 -4
@@ -1584,7 +1584,7 @@ static int ata_bus_probe(struct ata_port }/* configure transfer mode */ - rc =ata_set_mode (ap, &dev); + rc =ata_set_mode (&ap->link, &dev);if (rc) { down_xfermask =1 ; goto fail;
@@ -2122,7 +2122,7 @@ static int ata_dev_set_mode(struct ata_d/** * ata_set_mode - Program timings and issue SET FEATURES - XFER -* @ap: port on which timings will be programmed +* @link: link on which timings will be programmed * @r_failed_dev: out paramter for failed device * * Set ATA device disk transfer mode (PIO3, UDMA6, etc.). If
@@ -2135,9 +2135,9 @@ static int ata_dev_set_mode(struct ata_d* RETURNS: * 0 on success, negative errno otherwise */ -int ata_set_mode (struct ata_port *ap,struct ata_device **r_failed_dev) +int ata_set_mode (struct ata_link *link,struct ata_device **r_failed_dev) { -struct ata_link *link = &ap->link; +struct ata_port *ap = link->ap;struct ata_device *dev;int rc =0 , used_dma =0 , found =0 ;
drivers/scsi/libata-eh.c +85 -76
495 lines not on this page · raw message
drivers/scsi/libata.h +2 -1
@@ -57,7 +57,8 @@ extern int ata_dev_configure(struct ata_extern int sata_down_spd_limit (struct ata_link *link);extern int sata_set_spd_needed (struct ata_link *link);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_set_mode (struct ata_link *link, +struct ata_device **r_failed_dev);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
PATCH 9/17 libata-link: separate out link initialization functions
In reply to Tejun HeoSeparate out link initialization into ata_link_init() and ata_link_init_sata_spd_limit().
---
drivers/scsi/libata-core.c | 81 ++++++++++++++++++++++++++++++++++---------- 1 files changed, 63 insertions(+), 18 deletions(-)
f8af92d79249b584036d595b8e108d2c77f1b0bd
drivers/scsi/libata-core.c +63 -18
@@ -69,6 +69,7 @@ static unsigned int ata_dev_init_params( u16 heads, u16 sectors);static unsigned int ata_dev_set_xfermode (struct ata_device *dev);static void ata_dev_xfermask (struct ata_device *dev); +static int sata_link_init_spd_limit (struct ata_link *link);static unsigned int ata_unique_id =1 ;static struct workqueue_struct *ata_wq;
@@ -5321,6 +5322,66 @@ void ata_dev_init(struct ata_device *dev }/** +* ata_link_init - Initialize an ata_link structure +* @ap: ATA port link is attached to +* @link: Link structure to initialize +* +* Initialize @link. +* +* LOCKING: +* Kernel thread context (may sleep) +*/ +static void ata_link_init (struct ata_port *ap,struct ata_link *link) +{ +struct ata_device *dev; + +/* clear everything except for devices */ + memset(link, 0, offsetof(struct ata_link, device[0])); + + link->ap = ap; + link->active_tag =ATA_TAG_POISON ; + link->hw_sata_spd_limit =UINT_MAX ; + +ata_link_for_each_dev (dev, link) { + dev->link = link; + dev->devno = dev - link->device; +ata_dev_init (dev); + } +} + +/** +* sata_link_init_spd_limit - Initialize link->sata_spd_limit +* @link: Link to configure sata_spd_limit for +* +* Initialize @link->[hw_]sata_spd_limit to the currently +* configured value. +* +* LOCKING: +* Kernel thread context (may sleep). +* +* RETURNS: +* 0 on success, -errno on failure. +*/ +static int sata_link_init_spd_limit (struct ata_link *link) +{ + +u32 scontrol, spd; +int rc; + + rc =sata_scr_read (link,SCR_CONTROL , &scontrol); +if (rc) +return rc; + + spd = (scontrol >>4 ) &0xf ; +if (spd) + link->hw_sata_spd_limit &= (1 << spd) -1 ; + + link->sata_spd_limit = link->hw_sata_spd_limit; + +return 0 ; +} + +/** * ata_host_init - Initialize an ata_port structure * @ap: Structure to initialize * @host: associated SCSI mid-layer structure
@@ -5338,8 +5399,6 @@ static void ata_host_init(struct ata_porstruct ata_host_set *host_set, const struct ata_probe_ent *ent, unsigned int port_no) { - unsigned int i; - host->max_id = 16; host->max_lun =1 ; host->max_channel =1 ;
@@ -5361,8 +5420,6 @@ static void ata_host_init(struct ata_por ap->udma_mask = ent->udma_mask; ap->flags |= ent->host_flags; ap->ops = ent->port_ops; - ap->link.hw_sata_spd_limit =UINT_MAX ; - ap->link.active_tag =ATA_TAG_POISON ; ap->last_ctl =0xFF ;#if defined(ATA_VERBOSE_DEBUG )
@@ -5386,14 +5443,7 @@ #endifif (ap->flags &ATA_FLAG_SATA ) ap->cbl =ATA_CBL_SATA ; - ap->link.ap = ap; - -for (i =0 ; i <ata_link_max_devices (&ap->link); i++) { -struct ata_device *dev = &ap->link.device[i]; - dev->link = &ap->link; - dev->devno = i; -ata_dev_init (dev); - } +ata_link_init (ap, &ap->link);#ifdef ATA_IRQ_TRAP ap->stats.unhandled_irq =1 ;
@@ -5543,17 +5593,12 @@ int ata_device_add(const struct ata_probDPRINTK ("probe begin\n" );for (i =0 ; i < count; i++) {struct ata_port *ap; -u32 scontrol;int rc; ap = host_set->ports[i];/* init sata_spd_limit to the current value */ -if (sata_scr_read (&ap->link,SCR_CONTROL , &scontrol) ==0 ) { -int spd = (scontrol >>4 ) &0xf ; - ap->link.hw_sata_spd_limit &= (1 << spd) -1 ; - } - ap->link.sata_spd_limit = ap->link.hw_sata_spd_limit; +sata_link_init_spd_limit (&ap->link); rc =scsi_add_host (ap->host, dev);if (rc) {
Signature · 1 line
1.3.2
PATCH 10/17 libata-link: implement link->reset_tries
In reply to Tejun HeoMake reset_tries per-link property. PMP links will use different value from host links.
---
drivers/scsi/libata-core.c | 1 + drivers/scsi/libata-eh.c | 2 +- include/linux/libata.h | 2 ++ 3 files changed, 4 insertions(+), 1 deletions(-)
1987fc0ec41d15c84201e07980cf55c2ccb06b4f
drivers/scsi/libata-core.c +1 -0
@@ -5341,6 +5341,7 @@ static void ata_link_init(struct ata_por link->ap = ap; link->active_tag =ATA_TAG_POISON ; link->hw_sata_spd_limit =UINT_MAX ; + link->reset_tries =ATA_EH_RESET_TRIES ;ata_link_for_each_dev (dev, link) { dev->link = link;
drivers/scsi/libata-eh.c +1 -1
@@ -1508,7 +1508,7 @@ static int ata_eh_reset(struct ata_link {struct ata_eh_context *ehc = &link->eh_context;unsigned int *classes = ehc->classes; -int tries =ATA_EH_RESET_TRIES ; +int tries = link->reset_tries;int verbose = !(ehc->i.flags &ATA_EHI_QUIET );struct ata_device *dev;unsigned int action;
include/linux/libata.h +2 -0
@@ -506,6 +506,8 @@ struct ata_link {unsigned int hw_sata_spd_limit;unsigned int sata_spd_limit; +int reset_tries; +/* record runtime error info, protected by host_set lock */ struct ata_eh_info eh_info;/* EH context */
Signature · 1 line
1.3.2
PATCH 11/17 libata-link: implement ata_link_abort()
In reply to Tejun HeoImplement ata_link_abort().
---
drivers/scsi/libata-core.c | 1 + drivers/scsi/libata-eh.c | 50 ++++++++++++++++++++++++++++++++------------ include/linux/libata.h | 1 + 3 files changed, 38 insertions(+), 14 deletions(-)
1b09612fdc4030df0d6645b1307c5a144511d15b
drivers/scsi/libata-core.c +1 -0
@@ -6166,6 +6166,7 @@ EXPORT_SYMBOL_GPL(ata_scsi_device_resumeEXPORT_SYMBOL_GPL (ata_eng_timeout);EXPORT_SYMBOL_GPL (ata_port_schedule_eh); +EXPORT_SYMBOL_GPL (ata_link_abort);EXPORT_SYMBOL_GPL (ata_port_abort);EXPORT_SYMBOL_GPL (ata_port_freeze);EXPORT_SYMBOL_GPL (ata_eh_freeze_port);
drivers/scsi/libata-eh.c +36 -14
68 lines not on this page · raw message
include/linux/libata.h +1 -0
@@ -844,6 +844,7 @@ #endif /* CONFIG_PCI */extern void ata_eng_timeout (struct ata_port *ap);extern void ata_port_schedule_eh (struct ata_port *ap); +extern int ata_link_abort (struct ata_link *link);extern int ata_port_abort (struct ata_port *ap);extern int ata_port_freeze (struct ata_port *ap);
Signature · 1 line
1.3.2
PATCH 12/17 libata-link: add PMP links
In reply to Tejun HeoAdd link->pmp, ap->nr_pmp_links, ap->pmp_link[], and implement/update link helpers.
printk helpers are updated such that port and link are identifed as 'ataP:' if no PMP is attached, while device is identified as 'ataP.DD:'. If PMP is attached, they become 'ataP:', 'ataP.LL:' and 'ataP.LL' - ie. link and device are identified their PMP number.
If PPM is attached (ap->nr_pmp_links != 0), ata_for_each_link() iterates over PMP links, while __ata_for_each_link() iterates over the host link + PMP links. If PMP is not attached (ap->nr_pmp_links == 0), both iterate over only the host link.
---
drivers/scsi/libata-core.c | 6 +++-- include/linux/libata.h | 52 +++++++++++++++++++++++++++++++++++++++----- 2 files changed, 50 insertions(+), 8 deletions(-)
bbd82bc108860dff2c2f37de3bf4afaf42c2c6eb
drivers/scsi/libata-core.c +4 -2
@@ -5325,13 +5325,14 @@ void ata_dev_init(struct ata_device *dev* ata_link_init - Initialize an ata_link structure * @ap: ATA port link is attached to * @link: Link structure to initialize +* @pmp: Port multiplier port number * * Initialize @link. * * LOCKING: * Kernel thread context (may sleep) */ -static void ata_link_init (struct ata_port *ap,struct ata_link *link) +static void ata_link_init (struct ata_port *ap,struct ata_link *link,int pmp) {struct ata_device *dev;
@@ -5339,6 +5340,7 @@ static void ata_link_init(struct ata_por memset(link, 0, offsetof(struct ata_link, device[0])); link->ap = ap; + link->pmp = pmp; link->active_tag =ATA_TAG_POISON ; link->hw_sata_spd_limit =UINT_MAX ; link->reset_tries =ATA_EH_RESET_TRIES ;
@@ -5444,7 +5446,7 @@ #endifif (ap->flags &ATA_FLAG_SATA ) ap->cbl =ATA_CBL_SATA ; -ata_link_init (ap, &ap->link); +ata_link_init (ap, &ap->link,0 );#ifdef ATA_IRQ_TRAP ap->stats.unhandled_irq =1 ;
include/linux/libata.h +46 -6
84 lines not on this page · raw message
Signature · 1 line
1.3.2
PATCH 13/17 libata-link: update ata_scsi_error() to handle PMP links
In reply to Tejun HeoUpdate ata_scsi_error() to handle PMP links. As error conditions can occur on both host and PMP links, __ata_port_for_each_link() is used.
---
drivers/scsi/libata-eh.c | 13 +++++++++---- 1 files changed, 9 insertions(+), 4 deletions(-)
b01c2d5a1be5b7b11edc375ac8477cf58993be00
drivers/scsi/libata-eh.c +9 -4
@@ -278,15 +278,19 @@ void ata_scsi_error(struct Scsi_Host *ho repeat:/* invoke error handler */ if (ap->ops->error_handler) { +struct ata_link *link; +/* process port resume request */ ata_eh_handle_port_resume (ap);/* fetch & clear EH info */ spin_lock_irqsave (ap->lock, flags); -memset (&ap->link.eh_context,0 ,sizeof (ap->link.eh_context)); - ap->link.eh_context.i = ap->link.eh_info; -memset (&ap->link.eh_info,0 ,sizeof (ap->link.eh_info)); +__ata_port_for_each_link (link, ap) { +memset (&link->eh_context,0 ,sizeof (link->eh_context)); + link->eh_context.i = link->eh_info; +memset (&link->eh_info,0 ,sizeof (link->eh_info)); + } ap->pflags |=ATA_PFLAG_EH_IN_PROGRESS ; ap->pflags &= ~ATA_PFLAG_EH_PENDING ;
@@ -321,7 +325,8 @@ void ata_scsi_error(struct Scsi_Host *ho }/* this run is complete, make sure EH info is clear */ -memset (&ap->link.eh_info,0 ,sizeof (ap->link.eh_info)); +__ata_port_for_each_link (link, ap) +memset (&link->eh_info,0 ,sizeof (link->eh_info));/* Clear host_eh_scheduled while holding ap->lock such * that if exception occurs after this point but
Signature · 1 line
1.3.2
PATCH 14/17 libata-link: update ata_dev_configure() to deal with PMP links
In reply to Tejun HeoUpdate ata_dev_configure() to deal with PMP links.
---
drivers/scsi/libata-core.c | 14 ++++++++++---- 1 files changed, 10 insertions(+), 4 deletions(-)
6ed21e82bcfd8f7aa256f072fee6332682a4671f
drivers/scsi/libata-core.c +10 -4
@@ -1330,14 +1330,20 @@ static void ata_dev_config_ncq(struct atstatic void ata_set_port_max_cmd_len (struct ata_port *ap) { -struct ata_device *dev; +struct ata_link *link; + +if (!ap->host) +return ; + + ap->host->max_cmd_len =0 ; -if (ap->host) { - ap->host->max_cmd_len =0 ; -ata_link_for_each_dev (dev, &ap->link) +ata_port_for_each_link (link, ap) { +struct ata_device *dev; +ata_link_for_each_dev (dev, link) { ap->host->max_cmd_len = max_t(unsigned int, ap->host->max_cmd_len, dev->cdb_len); + } } }
Signature · 1 line
1.3.2
PATCH 15/17 libata-link: update EH to deal with PMP links
In reply to Tejun HeoUpdate ata_eh_autopsy(), ata_eh_report() and ata_eh_recover() to deal with PMP links. ata_eh_autopsy() and ata_eh_report() updates are straightforward. They just repeat the same operation over all configured links.
ata_eh_recover() update is more complex as it first processes all resets and then performs the rest. This is necessary as thawing with some links in unknown state can be dangerous. ehi->action is cleared on successful recovery of a link to avoid repeating recovery due to failures in other links.
ata_eh_recover() iterates over only PMP links if PMP is attached, and, on failure, the failing link is returned in @failed_link instead of disabling devices directly. These are to integrate ata_eh_recover() into PMP EH later.
---
drivers/scsi/libata-eh.c | 248 ++++++++++++++++++++++++++++++++-------------- 1 files changed, 170 insertions(+), 78 deletions(-)
fe716b0b5e94af07f10f1d07397c5e7ebf4d4e5b
drivers/scsi/libata-eh.c +170 -78
@@ -1315,8 +1315,8 @@ static int ata_eh_speed_down(struct ata_ }/** -* ata_eh_autopsy - analyze error and determine recovery action -* @link: ATA link to perform autopsy on +* ata_eh_link_autopsy - analyze error and determine recovery action +* @link: host link to perform autopsy on * * Analyze why @link failed and determine which recovery actions * are needed. This function also sets more detailed AC_ERR_*
@@ -1325,7 +1325,7 @@ static int ata_eh_speed_down(struct ata_* LOCKING: * Kernel thread context (may sleep). */ -static void ata_eh_autopsy (struct ata_link *link) +static void ata_eh_link_autopsy (struct ata_link *link) {struct ata_port *ap = link->ap;struct ata_eh_context *ehc = &link->eh_context;
@@ -1418,7 +1418,25 @@ static void ata_eh_autopsy(struct ata_li }/** -* ata_eh_report - report error handling to user +* ata_eh_autopsy - analyze error and determine recovery action +* @ap: host port to perform autopsy on +* +* Analyze all links of @ap and determine why they failed and +* which recovery actions are needed. +* +* LOCKING: +* Kernel thread context (may sleep). +*/ +static void ata_eh_autopsy (struct ata_port *ap) +{ +struct ata_link *link; + +__ata_port_for_each_link (link, ap) +ata_eh_link_autopsy (link); +} + +/** +* ata_eh_link_report - report error handling to user * @link: ATA link EH is going on * * Report EH to user.
@@ -1426,7 +1444,7 @@ static void ata_eh_autopsy(struct ata_li* LOCKING: * None. */ -static void ata_eh_report (struct ata_link *link) +static void ata_eh_link_report (struct ata_link *link) {struct ata_port *ap = link->ap;struct ata_eh_context *ehc = &link->eh_context;
@@ -1486,6 +1504,23 @@ static void ata_eh_report(struct ata_lin } } +/** +* ata_eh_report - report error handling to user +* @ap: ATA port to report EH about +* +* Report EH to user. +* +* LOCKING: +* None. +*/ +static void ata_eh_report (struct ata_port *ap) +{ +struct ata_link *link; + +__ata_port_for_each_link (link, ap) +ata_eh_link_report (link); +} +static int ata_do_reset (struct ata_link *link,ata_reset_fn_t reset,unsigned int *classes) {
@@ -1883,6 +1918,17 @@ static int ata_link_nr_enabled(struct atreturn cnt; } +static int ata_port_nr_enabled (struct ata_port *ap) +{ +struct ata_link *link; +int cnt =0 ; + +ata_port_for_each_link (link, ap) + cnt +=ata_link_nr_enabled (link); + +return cnt; +} +static int ata_link_nr_vacant (struct ata_link *link) {struct ata_device *dev;
@@ -1978,12 +2024,13 @@ static void ata_eh_handle_dev_fail(struc* @softreset: softreset method (can be NULL) * @hardreset: hardreset method (can be NULL) * @postreset: postreset method (can be NULL) +* @r_failed_link: out parameter for failed link * * This is the alpha and omega, eum and yang, heart and soul of * libata exception handling. On entry, actions required to -* 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 +* recover each link and hotplug requests are recorded in the +* link's eh_context. This function executes all the operations +* with appropriate retrials and fallbacks to resurrect failed * devices, detach goners and greet newcomers. * * LOCKING:
@@ -1994,115 +2041,147 @@ static void ata_eh_handle_dev_fail(struc*/ static int ata_eh_recover (struct ata_port *ap,ata_prereset_fn_t prereset,ata_reset_fn_t softreset,ata_reset_fn_t hardreset, -ata_postreset_fn_t postreset) +ata_postreset_fn_t postreset, +struct ata_link **r_failed_link) { -struct ata_link *link = &ap->link; -struct ata_eh_context *ehc = &link->eh_context; +struct ata_link *link;struct ata_device *dev; -int down_xfermask, rc; +int nr_failed_devs; +int reset, rc;DPRINTK ("ENTER\n" );/* prep for recovery */ -ata_link_for_each_dev (dev, link) { - ehc->tries[dev->devno] =ATA_EH_DEV_TRIES ; +ata_port_for_each_link (link, ap) { +struct ata_eh_context *ehc = &link->eh_context; -/* process hotplug request */ -if (dev->flags &ATA_DFLAG_DETACH ) -ata_eh_detach_dev (dev); +ata_link_for_each_dev (dev, link) { + ehc->tries[dev->devno] =ATA_EH_DEV_TRIES ; -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 ; +/* 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: - down_xfermask =0 ; rc =0 ; + nr_failed_devs =0 ; + reset =0 ;/* if UNLOADING, finish immediately */ if (ap->pflags &ATA_PFLAG_UNLOADING ) goto out; -/* prep for resume */ -ata_eh_prep_resume (link); +/* prep for EH */ +ata_port_for_each_link (link, ap) { +struct ata_eh_context *ehc = &link->eh_context; -/* skip EH if possible. */ -if (ata_eh_skip_recovery (link)) - ehc->i.action =0 ; +/* prep for resume */ +ata_eh_prep_resume (link); -ata_link_for_each_dev (dev, link) - ehc->classes[dev->devno] =ATA_DEV_UNKNOWN ; +/* skip EH if possible. */ +if (ata_eh_skip_recovery (link)) + ehc->i.action =0 ; + +/* do we need to reset? */ +if (ehc->i.action &ATA_EH_RESET_MASK ) + reset =1 ; + +ata_link_for_each_dev (dev, link) + ehc->classes[dev->devno] =ATA_DEV_UNKNOWN ; + }/* reset */ -if (ehc->i.action &ATA_EH_RESET_MASK ) { +if (reset) {ata_eh_freeze_port (ap); - rc =ata_eh_reset (link,ata_link_nr_vacant (link), prereset, - softreset, hardreset, postreset); -if (rc) { -ata_link_printk (link,KERN_ERR , -"reset failed, giving up\n" ); - goto out; +ata_port_for_each_link (link, ap) { +struct ata_eh_context *ehc = &link->eh_context; + +if (!(ehc->i.action &ATA_EH_RESET_MASK )) +continue ; + + rc =ata_eh_reset (link,ata_link_nr_vacant (link), + prereset, softreset, hardreset, + postreset); +if (rc) { +ata_link_printk (link,KERN_ERR , +"reset failed, giving up\n" ); + goto out; + } }ata_eh_thaw_port (ap); } -/* revalidate existing devices and attach new ones */ - rc =ata_eh_revalidate_and_attach (link, &dev); -if (rc) - goto dev_fail; +/* the rest */ +ata_port_for_each_link (link, ap) { +struct ata_eh_context *ehc = &link->eh_context; +int down_xfermask =0 ; -/* resume devices */ - rc =ata_eh_resume (link, &dev); -if (rc) - goto dev_fail; +/* revalidate existing devices and attach new ones */ + rc =ata_eh_revalidate_and_attach (link, &dev); +if (rc) + goto dev_fail; -/* configure transfer mode if the port has been reset */ -if (ehc->i.flags &ATA_EHI_DID_RESET ) { - rc =ata_set_mode (link, &dev); -if (rc) { - down_xfermask =1 ; +/* resume devices */ + rc =ata_eh_resume (link, &dev); +if (rc) goto dev_fail; + +/* configure transfer mode if the port has been reset */ +if (ehc->i.flags &ATA_EHI_DID_RESET ) { + rc =ata_set_mode (link, &dev); +if (rc) { + down_xfermask =1 ; + goto dev_fail; + } } - } -/* suspend devices */ - rc =ata_eh_suspend (link, &dev); -if (rc) - goto dev_fail; +/* suspend devices */ + rc =ata_eh_suspend (link, &dev); +if (rc) + goto dev_fail; - goto out; +/* this link is okay now */ + ehc->i.flags &= ~ATA_EHI_DID_RESET ; +continue ; - dev_fail: -ata_eh_handle_dev_fail (dev, rc, down_xfermask); + dev_fail: +ata_eh_handle_dev_fail (dev, rc, down_xfermask); + nr_failed_devs++; -if (ata_link_nr_enabled (link)) { -ata_link_printk (link,KERN_WARNING ,"failed to recover some " -"devices, retrying in 5 secs\n" ); -ssleep (5 ); - }else { -/* no device left, repeat fast */ -msleep (500 ); +if (ap->pflags &ATA_PFLAG_FROZEN ) +break ; } - goto retry; - - out: -if (rc) { -/* recovery failed, activate hp-poll */ -ata_hp_poll_activate (ap); +if (nr_failed_devs) { +if (ata_port_nr_enabled (ap)) { +ata_port_printk (ap,KERN_WARNING ,"failed to recover " +"some devices, retrying in 5 secs\n" ); +ssleep (5 ); + }else { +/* no device left, repeat fast */ +msleep (500 ); + } -ata_link_for_each_dev (dev, link); -ata_dev_disable (dev); + goto retry; } + out: +if (rc && r_failed_link) + *r_failed_link = link; +DPRINTK ("EXIT, rc=%d\n" , rc);return rc; }
@@ -2166,9 +2245,22 @@ 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->link); -ata_eh_report (&ap->link); -ata_eh_recover (ap, prereset, softreset, hardreset, postreset); + struct ata_device *dev; +int rc; + +ata_eh_autopsy (ap); +ata_eh_report (ap); + + rc =ata_eh_recover (ap, prereset, softreset, hardreset, postreset, +NULL ); +if (rc) { +/* recovery failed, activate hp-poll */ +ata_hp_poll_activate (ap); + +ata_link_for_each_dev (dev, &ap->link) +ata_dev_disable (dev); + } +ata_eh_finish (ap); }
Signature · 1 line
1.3.2
PATCH 16/17 libata-link: update hotplug to handle PMP links
In reply to Tejun HeoUpdate hotplug to handle PMP links. When PMP is attached, the PMP number corresponds to I of SCSI C:H:I:L.
---
drivers/scsi/libata-core.c | 7 ++- drivers/scsi/libata-scsi.c | 109 +++++++++++++++++++++++++++++++------------- 2 files changed, 81 insertions(+), 35 deletions(-)
ca948d6e6db6fa8c27ea7f8bd72ff276b9a7f774
drivers/scsi/libata-core.c +5 -2
@@ -5694,6 +5694,7 @@ err_free_ret:void ata_port_detach (struct ata_port *ap) {unsigned long flags; +struct ata_link *link;struct ata_device *dev;if (!ap->ops->error_handler)
@@ -5711,8 +5712,10 @@ void ata_port_detach(struct ata_port *ap*/ spin_lock_irqsave (ap->lock, flags); -ata_link_for_each_dev (dev, &ap->link) -ata_dev_disable (dev); +ata_port_for_each_link (link, ap) { +ata_link_for_each_dev (dev, link) +ata_dev_disable (dev); + }spin_unlock_irqrestore (ap->lock, flags);
drivers/scsi/libata-scsi.c +76 -33
178 lines not on this page · raw message
Signature · 1 line
1.3.2
PATCH 17/17 libata-link: update Power Management to handle PMP links
In reply to Tejun HeoUpdate Power Management to consider PMP links.
---
drivers/scsi/libata-core.c | 20 +++++++++++++------- drivers/scsi/libata-eh.c | 16 ++++++++++------ 2 files changed, 23 insertions(+), 13 deletions(-)
e65868d12527ea6e764aed3b996d103df352dac1
drivers/scsi/libata-core.c +13 -7
@@ -5106,6 +5106,7 @@ static int ata_host_set_request_pm(strucfor (i =0 ; i < host_set->n_ports; i++) {struct ata_port *ap = host_set->ports[i]; +struct ata_link *link;/* Previous resume operation might still be in * progress. Wait for PM_PENDING to clear.
@@ -5125,8 +5126,10 @@ static int ata_host_set_request_pm(struc } ap->pflags |=ATA_PFLAG_PM_PENDING ; - ap->link.eh_info.action |= action; - ap->link.eh_info.flags |= ehi_flags; +__ata_port_for_each_link (link, ap) { + link->eh_info.action |= action; + link->eh_info.flags |= ehi_flags; + }ata_port_schedule_eh (ap);
@@ -5173,15 +5176,18 @@ int ata_host_set_suspend(struct ata_host*/ for (i =0 ; i < host_set->n_ports; i++) {struct ata_port *ap = host_set->ports[i]; +struct ata_link *link;struct ata_device *dev; -ata_link_for_each_dev (dev, &ap->link) { -if (ata_dev_ready (dev)) { -ata_port_printk (ap,KERN_WARNING , +ata_port_for_each_link (link, ap) { +ata_link_for_each_dev (dev, link) { +if (ata_dev_ready (dev)) { +ata_port_printk (ap,KERN_WARNING ,"suspend failed, device %d " "still active\n" , dev->devno); - rc = -EBUSY ; - goto fail; + rc = -EBUSY ; + goto fail; + } } } }
drivers/scsi/libata-eh.c +10 -6
@@ -2356,17 +2356,21 @@ static void ata_eh_handle_port_resume(st/* give devices time to request EH */ timeout = jiffies +HZ ;/* 1s max */ while (1 ) { +struct ata_link *link;struct ata_device *dev; -ata_link_for_each_dev (dev, &ap->link) { -unsigned int action =ata_eh_dev_action (dev); +ata_port_for_each_link (link, ap) { +ata_link_for_each_dev (dev, link) { +unsigned int action =ata_eh_dev_action (dev); -if ((dev->flags &ATA_DFLAG_SUSPENDED ) && - !(action &ATA_EH_RESUME )) -break ; +if ((dev->flags &ATA_DFLAG_SUSPENDED ) && + !(action &ATA_EH_RESUME )) + goto out_of_loop; + } } + out_of_loop: -if (dev ==NULL ||time_after (jiffies, timeout)) +if (link ==NULL ||time_after (jiffies, timeout))break ;msleep (10 ); }
Signature · 1 line
1.3.2
Re: [PATCH 17/17] libata-link: update Power Management to handle PMP links
mostly ACK the read of the patches. I skimmed some of the linkify patches, but they all look pretty sane to me.