diff options
author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-10-17 09:32:49 -0300 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-10-17 09:32:49 -0300 |
commit | 214e2ca2b82d335935a861c253fe94c61ad77aad (patch) | |
tree | eee42ff74d10470789d919b8499737ad0e919360 /drivers/scsi/libsas/sas_ata.c | |
parent | 1fdead8ad31d3aa833bc37739273fcde89ace93c (diff) | |
parent | ddffeb8c4d0331609ef2581d84de4d763607bd37 (diff) |
Merge tag 'v3.7-rc1' into staging/for_v3.8
Linux 3.7-rc1
* tag 'v3.7-rc1': (9579 commits)
Linux 3.7-rc1
x86, boot: Explicitly include autoconf.h for hostprogs
perf: Fix UAPI fallout
ARM: config: make sure that platforms are ordered by option string
ARM: config: sort select statements alphanumerically
UAPI: (Scripted) Disintegrate include/linux/byteorder
UAPI: (Scripted) Disintegrate include/linux
UAPI: Unexport linux/blk_types.h
UAPI: Unexport part of linux/ppp-comp.h
perf: Handle new rbtree implementation
procfs: don't need a PATH_MAX allocation to hold a string representation of an int
vfs: embed struct filename inside of names_cache allocation if possible
audit: make audit_inode take struct filename
vfs: make path_openat take a struct filename pointer
vfs: turn do_path_lookup into wrapper around struct filename variant
audit: allow audit code to satisfy getname requests from its names_list
vfs: define struct filename and have getname() return it
btrfs: Fix compilation with user namespace support enabled
userns: Fix posix_acl_file_xattr_userns gid conversion
userns: Properly print bluetooth socket uids
...
Diffstat (limited to 'drivers/scsi/libsas/sas_ata.c')
-rw-r--r-- | drivers/scsi/libsas/sas_ata.c | 91 |
1 files changed, 87 insertions, 4 deletions
diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c index a59fcdc8fd6..bdb81cda840 100644 --- a/drivers/scsi/libsas/sas_ata.c +++ b/drivers/scsi/libsas/sas_ata.c @@ -580,10 +580,7 @@ int sas_ata_init(struct domain_device *found_dev) struct ata_port *ap; int rc; - ata_host_init(&found_dev->sata_dev.ata_host, - ha->dev, - sata_port_info.flags, - &sas_sata_ops); + ata_host_init(&found_dev->sata_dev.ata_host, ha->dev, &sas_sata_ops); ap = ata_sas_port_alloc(&found_dev->sata_dev.ata_host, &sata_port_info, shost); @@ -700,6 +697,92 @@ void sas_probe_sata(struct asd_sas_port *port) if (ata_dev_disabled(sas_to_ata_dev(dev))) sas_fail_probe(dev, __func__, -ENODEV); } + +} + +static bool sas_ata_flush_pm_eh(struct asd_sas_port *port, const char *func) +{ + struct domain_device *dev, *n; + bool retry = false; + + list_for_each_entry_safe(dev, n, &port->dev_list, dev_list_node) { + int rc; + + if (!dev_is_sata(dev)) + continue; + + sas_ata_wait_eh(dev); + rc = dev->sata_dev.pm_result; + if (rc == -EAGAIN) + retry = true; + else if (rc) { + /* since we don't have a + * ->port_{suspend|resume} routine in our + * ata_port ops, and no entanglements with + * acpi, suspend should just be mechanical trip + * through eh, catch cases where these + * assumptions are invalidated + */ + WARN_ONCE(1, "failed %s %s error: %d\n", func, + dev_name(&dev->rphy->dev), rc); + } + + /* if libata failed to power manage the device, tear it down */ + if (ata_dev_disabled(sas_to_ata_dev(dev))) + sas_fail_probe(dev, func, -ENODEV); + } + + return retry; +} + +void sas_suspend_sata(struct asd_sas_port *port) +{ + struct domain_device *dev; + + retry: + mutex_lock(&port->ha->disco_mutex); + list_for_each_entry(dev, &port->dev_list, dev_list_node) { + struct sata_device *sata; + + if (!dev_is_sata(dev)) + continue; + + sata = &dev->sata_dev; + if (sata->ap->pm_mesg.event == PM_EVENT_SUSPEND) + continue; + + sata->pm_result = -EIO; + ata_sas_port_async_suspend(sata->ap, &sata->pm_result); + } + mutex_unlock(&port->ha->disco_mutex); + + if (sas_ata_flush_pm_eh(port, __func__)) + goto retry; +} + +void sas_resume_sata(struct asd_sas_port *port) +{ + struct domain_device *dev; + + retry: + mutex_lock(&port->ha->disco_mutex); + list_for_each_entry(dev, &port->dev_list, dev_list_node) { + struct sata_device *sata; + + if (!dev_is_sata(dev)) + continue; + + sata = &dev->sata_dev; + if (sata->ap->pm_mesg.event == PM_EVENT_ON) + continue; + + sata->pm_result = -EIO; + ata_sas_port_async_resume(sata->ap, &sata->pm_result); + } + mutex_unlock(&port->ha->disco_mutex); + + if (sas_ata_flush_pm_eh(port, __func__)) + goto retry; } /** |