sata_dwc_460ex: fix resource leak on error path
[pandora-kernel.git] / drivers / ata / libata-scsi.c
index 72a9770..8460e62 100644 (file)
@@ -111,12 +111,14 @@ static const char *ata_lpm_policy_names[] = {
        [ATA_LPM_MIN_POWER]     = "min_power",
 };
 
-static ssize_t ata_scsi_lpm_store(struct device *dev,
+static ssize_t ata_scsi_lpm_store(struct device *device,
                                  struct device_attribute *attr,
                                  const char *buf, size_t count)
 {
-       struct Scsi_Host *shost = class_to_shost(dev);
+       struct Scsi_Host *shost = class_to_shost(device);
        struct ata_port *ap = ata_shost_to_port(shost);
+       struct ata_link *link;
+       struct ata_device *dev;
        enum ata_lpm_policy policy;
        unsigned long flags;
 
@@ -132,10 +134,20 @@ static ssize_t ata_scsi_lpm_store(struct device *dev,
                return -EINVAL;
 
        spin_lock_irqsave(ap->lock, flags);
+
+       ata_for_each_link(link, ap, EDGE) {
+               ata_for_each_dev(dev, &ap->link, ENABLED) {
+                       if (dev->horkage & ATA_HORKAGE_NOLPM) {
+                               count = -EOPNOTSUPP;
+                               goto out_unlock;
+                       }
+               }
+       }
+
        ap->target_lpm_policy = policy;
        ata_port_schedule_eh(ap);
+out_unlock:
        spin_unlock_irqrestore(ap->lock, flags);
-
        return count;
 }
 
@@ -309,7 +321,8 @@ ata_scsi_activity_show(struct device *dev, struct device_attribute *attr,
        struct ata_port *ap = ata_shost_to_port(sdev->host);
        struct ata_device *atadev = ata_scsi_find_dev(ap, sdev);
 
-       if (ap->ops->sw_activity_show && (ap->flags & ATA_FLAG_SW_ACTIVITY))
+       if (atadev && ap->ops->sw_activity_show &&
+           (ap->flags & ATA_FLAG_SW_ACTIVITY))
                return ap->ops->sw_activity_show(atadev, buf);
        return -EINVAL;
 }
@@ -324,7 +337,8 @@ ata_scsi_activity_store(struct device *dev, struct device_attribute *attr,
        enum sw_activity val;
        int rc;
 
-       if (ap->ops->sw_activity_store && (ap->flags & ATA_FLAG_SW_ACTIVITY)) {
+       if (atadev && ap->ops->sw_activity_store &&
+           (ap->flags & ATA_FLAG_SW_ACTIVITY)) {
                val = simple_strtoul(buf, NULL, 0);
                switch (val) {
                case OFF: case BLINK_ON: case BLINK_OFF:
@@ -1217,6 +1231,10 @@ void ata_scsi_slave_destroy(struct scsi_device *sdev)
 
 /**
  *     __ata_change_queue_depth - helper for ata_scsi_change_queue_depth
+ *     @ap: ATA port to which the device change the queue depth
+ *     @sdev: SCSI device to configure queue depth for
+ *     @queue_depth: new queue depth
+ *     @reason: calling context
  *
  *     libsas and libata have different approaches for associating a sdev to
  *     its ata_port.