]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - drivers/scsi/libsas/sas_init.c
include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit...
[mv-sheeva.git] / drivers / scsi / libsas / sas_init.c
index d65bc4e0f2147f33a6ca81cb44fecac9ef3b1e66..2dc55343f671f6c7b4fa681278233c85c3db314e 100644 (file)
@@ -24,6 +24,7 @@
  */
 
 #include <linux/module.h>
+#include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/device.h>
 #include <linux/spinlock.h>
@@ -36,7 +37,7 @@
 
 #include "../scsi_sas_internal.h"
 
-kmem_cache_t *sas_task_cache;
+struct kmem_cache *sas_task_cache;
 
 /*------------ SAS addr hash -----------*/
 void sas_hash_addr(u8 *hashed, const u8 *sas_addr)
@@ -87,6 +88,9 @@ int sas_register_ha(struct sas_ha_struct *sas_ha)
        else if (sas_ha->lldd_queue_size == -1)
                sas_ha->lldd_queue_size = 128; /* Sanity */
 
+       sas_ha->state = SAS_HA_REGISTERED;
+       spin_lock_init(&sas_ha->state_lock);
+
        error = sas_register_phys(sas_ha);
        if (error) {
                printk(KERN_NOTICE "couldn't register sas phys:%d\n", error);
@@ -127,12 +131,22 @@ Undo_phys:
 
 int sas_unregister_ha(struct sas_ha_struct *sas_ha)
 {
+       unsigned long flags;
+
+       /* Set the state to unregistered to avoid further
+        * events to be queued */
+       spin_lock_irqsave(&sas_ha->state_lock, flags);
+       sas_ha->state = SAS_HA_UNREGISTERED;
+       spin_unlock_irqrestore(&sas_ha->state_lock, flags);
+       scsi_flush_work(sas_ha->core.shost);
+
+       sas_unregister_ports(sas_ha);
+
        if (sas_ha->lldd_max_execute_num > 1) {
                sas_shutdown_queue(sas_ha);
+               sas_ha->lldd_max_execute_num = 1;
        }
 
-       sas_unregister_ports(sas_ha);
-
        return 0;
 }
 
@@ -146,6 +160,36 @@ static int sas_get_linkerrors(struct sas_phy *phy)
        return sas_smp_get_phy_events(phy);
 }
 
+int sas_phy_enable(struct sas_phy *phy, int enable)
+{
+       int ret;
+       enum phy_func command;
+
+       if (enable)
+               command = PHY_FUNC_LINK_RESET;
+       else
+               command = PHY_FUNC_DISABLE;
+
+       if (scsi_is_sas_phy_local(phy)) {
+               struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
+               struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(shost);
+               struct asd_sas_phy *asd_phy = sas_ha->sas_phy[phy->number];
+               struct sas_internal *i =
+                       to_sas_internal(sas_ha->core.shost->transportt);
+
+               if (!enable) {
+                       sas_phy_disconnected(asd_phy);
+                       sas_ha->notify_phy_event(asd_phy, PHYE_LOSS_OF_SIGNAL);
+               }
+               ret = i->dft->lldd_control_phy(asd_phy, command, NULL);
+       } else {
+               struct sas_rphy *rphy = dev_to_rphy(phy->dev.parent);
+               struct domain_device *ddev = sas_find_dev_by_rphy(rphy);
+               ret = sas_smp_phy_control(ddev, phy->number, command, NULL);
+       }
+       return ret;
+}
+
 int sas_phy_reset(struct sas_phy *phy, int hard_reset)
 {
        int ret;
@@ -172,8 +216,8 @@ int sas_phy_reset(struct sas_phy *phy, int hard_reset)
        return ret;
 }
 
-static int sas_set_phy_speed(struct sas_phy *phy,
-                            struct sas_phy_linkrates *rates)
+int sas_set_phy_speed(struct sas_phy *phy,
+                     struct sas_phy_linkrates *rates)
 {
        int ret;
 
@@ -212,9 +256,11 @@ static int sas_set_phy_speed(struct sas_phy *phy,
 }
 
 static struct sas_function_template sft = {
+       .phy_enable = sas_phy_enable,
        .phy_reset = sas_phy_reset,
        .set_phy_speed = sas_set_phy_speed,
        .get_linkerrors = sas_get_linkerrors,
+       .smp_handler = sas_smp_handler,
 };
 
 struct scsi_transport_template *
@@ -248,7 +294,7 @@ EXPORT_SYMBOL_GPL(sas_domain_release_transport);
 static int __init sas_class_init(void)
 {
        sas_task_cache = kmem_cache_create("sas_task", sizeof(struct sas_task),
-                                          0, SLAB_HWCACHE_ALIGN, NULL, NULL);
+                                          0, SLAB_HWCACHE_ALIGN, NULL);
        if (!sas_task_cache)
                return -ENOMEM;