aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAaron Lu <aaron.lu@intel.com>2013-04-26 21:33:07 -0400
committerJeff Garzik <jgarzik@redhat.com>2013-04-30 18:02:45 -0400
commitd66af4df0837f21bf267305dc5ccab2d29e24d86 (patch)
treef71109c378a242c909add6ee47b6cac8510e82be
parent3f1317a2be018d03435d48645df6d17eaa2a8421 (diff)
[libata] acpi: make ata_ap_acpi_handle not block
Since commit 30dcf76acc, ata_ap_acpi_handle will always do a namespace walk, which requires acquiring an acpi namespace mutex. This made it impossible to be used when calling path has held a spinlock. For example, it can occur in the following code path for pata_acpi: ata_scsi_queuecmd (ap->lock is acquired) __ata_scsi_queuecmd ata_scsi_translate ata_qc_issue pacpi_qc_issue ata_acpi_stm ata_ap_acpi_handle acpi_get_child acpi_walk_namespace acpi_ut_acquire_mutex (acquire mutex while holding lock) This caused scheduling while atomic bug, as reported in bug #56781. Actually, ata_ap_acpi_handle doesn't have to walk the namespace every time it is called, it can simply return the bound acpi handle on the corresponding SCSI host. The reason previously it is not done this way is, ata_ap_acpi_handle is used in the binding function ata_acpi_bind_host by ata_acpi_gtm when the handle is not bound to the SCSI host yet. Since we already have the ATA port's handle in its binding function, we can simply use it instead of calling ata_ap_acpi_handle there. So introduce a new function __ata_acpi_gtm, where it will receive an acpi handle param in addition to the ATA port which is solely used for debug statement. With this change, we can make ata_ap_acpi_handle simply return the bound handle for SCSI host instead of walking the acpi namespace now. Buglink: https://bugzilla.kernel.org/show_bug.cgi?id=56781 Reported-and-tested-by: <kenzopl@o2.pl> Cc: <stable@vger.kernel.org> Signed-off-by: Aaron Lu <aaron.lu@intel.com> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
-rw-r--r--drivers/ata/libata-acpi.c45
1 files changed, 27 insertions, 18 deletions
diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c
index 1c33f78040c6..f6d80e342310 100644
--- a/drivers/ata/libata-acpi.c
+++ b/drivers/ata/libata-acpi.c
@@ -60,7 +60,8 @@ acpi_handle ata_ap_acpi_handle(struct ata_port *ap)
60 if (ap->flags & ATA_FLAG_ACPI_SATA) 60 if (ap->flags & ATA_FLAG_ACPI_SATA)
61 return NULL; 61 return NULL;
62 62
63 return acpi_get_child(DEVICE_ACPI_HANDLE(ap->host->dev), ap->port_no); 63 return ap->scsi_host ?
64 DEVICE_ACPI_HANDLE(&ap->scsi_host->shost_gendev) : NULL;
64} 65}
65EXPORT_SYMBOL(ata_ap_acpi_handle); 66EXPORT_SYMBOL(ata_ap_acpi_handle);
66 67
@@ -239,28 +240,15 @@ void ata_acpi_dissociate(struct ata_host *host)
239 } 240 }
240} 241}
241 242
242/** 243static int __ata_acpi_gtm(struct ata_port *ap, acpi_handle handle,
243 * ata_acpi_gtm - execute _GTM 244 struct ata_acpi_gtm *gtm)
244 * @ap: target ATA port
245 * @gtm: out parameter for _GTM result
246 *
247 * Evaluate _GTM and store the result in @gtm.
248 *
249 * LOCKING:
250 * EH context.
251 *
252 * RETURNS:
253 * 0 on success, -ENOENT if _GTM doesn't exist, -errno on failure.
254 */
255int ata_acpi_gtm(struct ata_port *ap, struct ata_acpi_gtm *gtm)
256{ 245{
257 struct acpi_buffer output = { .length = ACPI_ALLOCATE_BUFFER }; 246 struct acpi_buffer output = { .length = ACPI_ALLOCATE_BUFFER };
258 union acpi_object *out_obj; 247 union acpi_object *out_obj;
259 acpi_status status; 248 acpi_status status;
260 int rc = 0; 249 int rc = 0;
261 250
262 status = acpi_evaluate_object(ata_ap_acpi_handle(ap), "_GTM", NULL, 251 status = acpi_evaluate_object(handle, "_GTM", NULL, &output);
263 &output);
264 252
265 rc = -ENOENT; 253 rc = -ENOENT;
266 if (status == AE_NOT_FOUND) 254 if (status == AE_NOT_FOUND)
@@ -294,6 +282,27 @@ int ata_acpi_gtm(struct ata_port *ap, struct ata_acpi_gtm *gtm)
294 return rc; 282 return rc;
295} 283}
296 284
285/**
286 * ata_acpi_gtm - execute _GTM
287 * @ap: target ATA port
288 * @gtm: out parameter for _GTM result
289 *
290 * Evaluate _GTM and store the result in @gtm.
291 *
292 * LOCKING:
293 * EH context.
294 *
295 * RETURNS:
296 * 0 on success, -ENOENT if _GTM doesn't exist, -errno on failure.
297 */
298int ata_acpi_gtm(struct ata_port *ap, struct ata_acpi_gtm *gtm)
299{
300 if (ata_ap_acpi_handle(ap))
301 return __ata_acpi_gtm(ap, ata_ap_acpi_handle(ap), gtm);
302 else
303 return -EINVAL;
304}
305
297EXPORT_SYMBOL_GPL(ata_acpi_gtm); 306EXPORT_SYMBOL_GPL(ata_acpi_gtm);
298 307
299/** 308/**
@@ -1047,7 +1056,7 @@ static int ata_acpi_bind_host(struct ata_port *ap, acpi_handle *handle)
1047 if (!*handle) 1056 if (!*handle)
1048 return -ENODEV; 1057 return -ENODEV;
1049 1058
1050 if (ata_acpi_gtm(ap, &ap->__acpi_init_gtm) == 0) 1059 if (__ata_acpi_gtm(ap, *handle, &ap->__acpi_init_gtm) == 0)
1051 ap->pflags |= ATA_PFLAG_INIT_GTM_VALID; 1060 ap->pflags |= ATA_PFLAG_INIT_GTM_VALID;
1052 1061
1053 return 0; 1062 return 0;