Merge branch 'bkl/fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/frederic...
[safe/jmp/linux-2.6] / drivers / scsi / scsi_transport_sas.c
index f4461d3..927e99c 100644 (file)
@@ -155,6 +155,17 @@ static struct {
 sas_bitfield_name_search(linkspeed, sas_linkspeed_names)
 sas_bitfield_name_set(linkspeed, sas_linkspeed_names)
 
+static struct sas_end_device *sas_sdev_to_rdev(struct scsi_device *sdev)
+{
+       struct sas_rphy *rphy = target_to_rphy(sdev->sdev_target);
+       struct sas_end_device *rdev;
+
+       BUG_ON(rphy->identify.device_type != SAS_END_DEVICE);
+
+       rdev = rphy_to_end_device(rphy);
+       return rdev;
+}
+
 static void sas_smp_request(struct request_queue *q, struct Scsi_Host *shost,
                            struct sas_rphy *rphy)
 {
@@ -163,21 +174,19 @@ static void sas_smp_request(struct request_queue *q, struct Scsi_Host *shost,
        int (*handler)(struct Scsi_Host *, struct sas_rphy *, struct request *);
 
        while (!blk_queue_plugged(q)) {
-               req = elv_next_request(q);
+               req = blk_fetch_request(q);
                if (!req)
                        break;
 
-               blkdev_dequeue_request(req);
-
                spin_unlock_irq(q->queue_lock);
 
                handler = to_sas_internal(shost->transportt)->f->smp_handler;
                ret = handler(shost, rphy, req);
                req->errors = ret;
 
-               spin_lock_irq(q->queue_lock);
+               blk_end_request_all(req, ret);
 
-               req->end_io(req, ret);
+               spin_lock_irq(q->queue_lock);
        }
 }
 
@@ -207,7 +216,7 @@ static int sas_bsg_initialize(struct Scsi_Host *shost, struct sas_rphy *rphy)
        struct request_queue *q;
        int error;
        struct device *dev;
-       char namebuf[BUS_ID_SIZE];
+       char namebuf[20];
        const char *name;
        void (*release)(struct device *);
 
@@ -219,7 +228,7 @@ static int sas_bsg_initialize(struct Scsi_Host *shost, struct sas_rphy *rphy)
        if (rphy) {
                q = blk_init_queue(sas_non_host_smp_request, NULL);
                dev = &rphy->dev;
-               name = dev->bus_id;
+               name = dev_name(dev);
                release = NULL;
        } else {
                q = blk_init_queue(sas_host_smp_request, NULL);
@@ -360,6 +369,85 @@ void sas_remove_host(struct Scsi_Host *shost)
 }
 EXPORT_SYMBOL(sas_remove_host);
 
+/**
+ * sas_tlr_supported - checking TLR bit in vpd 0x90
+ * @sdev: scsi device struct
+ *
+ * Check Transport Layer Retries are supported or not.
+ * If vpd page 0x90 is present, TRL is supported.
+ *
+ */
+unsigned int
+sas_tlr_supported(struct scsi_device *sdev)
+{
+       const int vpd_len = 32;
+       struct sas_end_device *rdev = sas_sdev_to_rdev(sdev);
+       char *buffer = kzalloc(vpd_len, GFP_KERNEL);
+       int ret = 0;
+
+       if (scsi_get_vpd_page(sdev, 0x90, buffer, vpd_len))
+               goto out;
+
+       /*
+        * Magic numbers: the VPD Protocol page (0x90)
+        * has a 4 byte header and then one entry per device port
+        * the TLR bit is at offset 8 on each port entry
+        * if we take the first port, that's at total offset 12
+        */
+       ret = buffer[12] & 0x01;
+
+ out:
+       kfree(buffer);
+       rdev->tlr_supported = ret;
+       return ret;
+
+}
+EXPORT_SYMBOL_GPL(sas_tlr_supported);
+
+/**
+ * sas_disable_tlr - setting TLR flags
+ * @sdev: scsi device struct
+ *
+ * Seting tlr_enabled flag to 0.
+ *
+ */
+void
+sas_disable_tlr(struct scsi_device *sdev)
+{
+       struct sas_end_device *rdev = sas_sdev_to_rdev(sdev);
+
+       rdev->tlr_enabled = 0;
+}
+EXPORT_SYMBOL_GPL(sas_disable_tlr);
+
+/**
+ * sas_enable_tlr - setting TLR flags
+ * @sdev: scsi device struct
+ *
+ * Seting tlr_enabled flag 1.
+ *
+ */
+void sas_enable_tlr(struct scsi_device *sdev)
+{
+       unsigned int tlr_supported = 0;
+       tlr_supported  = sas_tlr_supported(sdev);
+
+       if (tlr_supported) {
+               struct sas_end_device *rdev = sas_sdev_to_rdev(sdev);
+
+               rdev->tlr_enabled = 1;
+       }
+
+       return;
+}
+EXPORT_SYMBOL_GPL(sas_enable_tlr);
+
+unsigned int sas_is_tlr_enabled(struct scsi_device *sdev)
+{
+       struct sas_end_device *rdev = sas_sdev_to_rdev(sdev);
+       return rdev->tlr_enabled;
+}
+EXPORT_SYMBOL_GPL(sas_is_tlr_enabled);
 
 /*
  * SAS Phy attributes
@@ -629,10 +717,10 @@ struct sas_phy *sas_phy_alloc(struct device *parent, int number)
        INIT_LIST_HEAD(&phy->port_siblings);
        if (scsi_is_sas_expander_device(parent)) {
                struct sas_rphy *rphy = dev_to_rphy(parent);
-               sprintf(phy->dev.bus_id, "phy-%d:%d:%d", shost->host_no,
+               dev_set_name(&phy->dev, "phy-%d:%d:%d", shost->host_no,
                        rphy->scsi_target_id, number);
        } else
-               sprintf(phy->dev.bus_id, "phy-%d:%d", shost->host_no, number);
+               dev_set_name(&phy->dev, "phy-%d:%d", shost->host_no, number);
 
        transport_setup_device(&phy->dev);
 
@@ -668,7 +756,7 @@ EXPORT_SYMBOL(sas_phy_add);
  *
  * Note:
  *   This function must only be called on a PHY that has not
- *   sucessfully been added using sas_phy_add().
+ *   successfully been added using sas_phy_add().
  */
 void sas_phy_free(struct sas_phy *phy)
 {
@@ -770,7 +858,7 @@ static void sas_port_create_link(struct sas_port *port,
        int res;
 
        res = sysfs_create_link(&port->dev.kobj, &phy->dev.kobj,
-                               phy->dev.bus_id);
+                               dev_name(&phy->dev));
        if (res)
                goto err;
        res = sysfs_create_link(&phy->dev.kobj, &port->dev.kobj, "port");
@@ -779,13 +867,13 @@ static void sas_port_create_link(struct sas_port *port,
        return;
 err:
        printk(KERN_ERR "%s: Cannot create port links, err=%d\n",
-              __FUNCTION__, res);
+              __func__, res);
 }
 
 static void sas_port_delete_link(struct sas_port *port,
                                 struct sas_phy *phy)
 {
-       sysfs_remove_link(&port->dev.kobj, phy->dev.bus_id);
+       sysfs_remove_link(&port->dev.kobj, dev_name(&phy->dev));
        sysfs_remove_link(&phy->dev.kobj, "port");
 }
 
@@ -821,11 +909,11 @@ struct sas_port *sas_port_alloc(struct device *parent, int port_id)
 
        if (scsi_is_sas_expander_device(parent)) {
                struct sas_rphy *rphy = dev_to_rphy(parent);
-               sprintf(port->dev.bus_id, "port-%d:%d:%d", shost->host_no,
-                       rphy->scsi_target_id, port->port_identifier);
+               dev_set_name(&port->dev, "port-%d:%d:%d", shost->host_no,
+                            rphy->scsi_target_id, port->port_identifier);
        } else
-               sprintf(port->dev.bus_id, "port-%d:%d", shost->host_no,
-                       port->port_identifier);
+               dev_set_name(&port->dev, "port-%d:%d", shost->host_no,
+                            port->port_identifier);
 
        transport_setup_device(&port->dev);
 
@@ -898,7 +986,7 @@ EXPORT_SYMBOL(sas_port_add);
  *
  * Note:
  *   This function must only be called on a PORT that has not
- *   sucessfully been added using sas_port_add().
+ *   successfully been added using sas_port_add().
  */
 void sas_port_free(struct sas_port *port)
 {
@@ -935,7 +1023,7 @@ void sas_port_delete(struct sas_port *port)
        if (port->is_backlink) {
                struct device *parent = port->dev.parent;
 
-               sysfs_remove_link(&port->dev.kobj, parent->bus_id);
+               sysfs_remove_link(&port->dev.kobj, dev_name(parent));
                port->is_backlink = 0;
        }
 
@@ -984,7 +1072,8 @@ void sas_port_add_phy(struct sas_port *port, struct sas_phy *phy)
                /* If this trips, you added a phy that was already
                 * part of a different port */
                if (unlikely(tmp != phy)) {
-                       dev_printk(KERN_ERR, &port->dev, "trying to add phy %s fails: it's already part of another port\n", phy->dev.bus_id);
+                       dev_printk(KERN_ERR, &port->dev, "trying to add phy %s fails: it's already part of another port\n",
+                                  dev_name(&phy->dev));
                        BUG();
                }
        } else {
@@ -1023,13 +1112,13 @@ void sas_port_mark_backlink(struct sas_port *port)
                return;
        port->is_backlink = 1;
        res = sysfs_create_link(&port->dev.kobj, &parent->kobj,
-                               parent->bus_id);
+                               dev_name(parent));
        if (res)
                goto err;
        return;
 err:
        printk(KERN_ERR "%s: Cannot create port backlink, err=%d\n",
-              __FUNCTION__, res);
+              __func__, res);
 
 }
 EXPORT_SYMBOL(sas_port_mark_backlink);
@@ -1147,15 +1236,10 @@ sas_rphy_simple_attr(identify.phy_identifier, phy_identifier, "%d\n", u8);
 int sas_read_port_mode_page(struct scsi_device *sdev)
 {
        char *buffer = kzalloc(BUF_SIZE, GFP_KERNEL), *msdata;
-       struct sas_rphy *rphy = target_to_rphy(sdev->sdev_target);
-       struct sas_end_device *rdev;
+       struct sas_end_device *rdev = sas_sdev_to_rdev(sdev);
        struct scsi_mode_data mode_data;
        int res, error;
 
-       BUG_ON(rphy->identify.device_type != SAS_END_DEVICE);
-
-       rdev = rphy_to_end_device(rphy);
-
        if (!buffer)
                return -ENOMEM;
 
@@ -1208,6 +1292,10 @@ sas_end_dev_simple_attr(I_T_nexus_loss_timeout, I_T_nexus_loss_timeout,
                        "%d\n", int);
 sas_end_dev_simple_attr(initiator_response_timeout, initiator_response_timeout,
                        "%d\n", int);
+sas_end_dev_simple_attr(tlr_supported, tlr_supported,
+                       "%d\n", int);
+sas_end_dev_simple_attr(tlr_enabled, tlr_enabled,
+                       "%d\n", int);
 
 static DECLARE_TRANSPORT_CLASS(sas_expander_class,
                               "sas_expander", NULL, NULL, NULL);
@@ -1367,11 +1455,12 @@ struct sas_rphy *sas_end_device_alloc(struct sas_port *parent)
        rdev->rphy.dev.release = sas_end_device_release;
        if (scsi_is_sas_expander_device(parent->dev.parent)) {
                struct sas_rphy *rphy = dev_to_rphy(parent->dev.parent);
-               sprintf(rdev->rphy.dev.bus_id, "end_device-%d:%d:%d",
-                       shost->host_no, rphy->scsi_target_id, parent->port_identifier);
+               dev_set_name(&rdev->rphy.dev, "end_device-%d:%d:%d",
+                            shost->host_no, rphy->scsi_target_id,
+                            parent->port_identifier);
        } else
-               sprintf(rdev->rphy.dev.bus_id, "end_device-%d:%d",
-                       shost->host_no, parent->port_identifier);
+               dev_set_name(&rdev->rphy.dev, "end_device-%d:%d",
+                            shost->host_no, parent->port_identifier);
        rdev->rphy.identify.device_type = SAS_END_DEVICE;
        sas_rphy_initialize(&rdev->rphy);
        transport_setup_device(&rdev->rphy.dev);
@@ -1411,8 +1500,8 @@ struct sas_rphy *sas_expander_alloc(struct sas_port *parent,
        mutex_lock(&sas_host->lock);
        rdev->rphy.scsi_target_id = sas_host->next_expander_id++;
        mutex_unlock(&sas_host->lock);
-       sprintf(rdev->rphy.dev.bus_id, "expander-%d:%d",
-               shost->host_no, rdev->rphy.scsi_target_id);
+       dev_set_name(&rdev->rphy.dev, "expander-%d:%d",
+                    shost->host_no, rdev->rphy.scsi_target_id);
        rdev->rphy.identify.device_type = type;
        sas_rphy_initialize(&rdev->rphy);
        transport_setup_device(&rdev->rphy.dev);
@@ -1445,7 +1534,7 @@ int sas_rphy_add(struct sas_rphy *rphy)
        transport_add_device(&rphy->dev);
        transport_configure_device(&rphy->dev);
        if (sas_bsg_initialize(shost, rphy))
-               printk("fail to a bsg device %s\n", rphy->dev.bus_id);
+               printk("fail to a bsg device %s\n", dev_name(&rphy->dev));
 
 
        mutex_lock(&sas_host->lock);
@@ -1476,7 +1565,7 @@ EXPORT_SYMBOL(sas_rphy_add);
  *
  * Note:
  *   This function must only be called on a remote
- *   PHY that has not sucessfully been added using
+ *   PHY that has not successfully been added using
  *   sas_rphy_add() (or has been sas_rphy_remove()'d)
  */
 void sas_rphy_free(struct sas_rphy *rphy)
@@ -1692,10 +1781,6 @@ sas_attach_transport(struct sas_function_template *ft)
        i->f = ft;
 
        count = 0;
-       SETUP_PORT_ATTRIBUTE(num_phys);
-       i->host_attrs[count] = NULL;
-
-       count = 0;
        SETUP_PHY_ATTRIBUTE(initiator_port_protocols);
        SETUP_PHY_ATTRIBUTE(target_port_protocols);
        SETUP_PHY_ATTRIBUTE(device_type);
@@ -1737,6 +1822,8 @@ sas_attach_transport(struct sas_function_template *ft)
        SETUP_END_DEV_ATTRIBUTE(end_dev_ready_led_meaning);
        SETUP_END_DEV_ATTRIBUTE(end_dev_I_T_nexus_loss_timeout);
        SETUP_END_DEV_ATTRIBUTE(end_dev_initiator_response_timeout);
+       SETUP_END_DEV_ATTRIBUTE(end_dev_tlr_supported);
+       SETUP_END_DEV_ATTRIBUTE(end_dev_tlr_enabled);
        i->end_dev_attrs[count] = NULL;
 
        count = 0;