diff --git a/drivers/scsi/libsas/sas_init.c b/drivers/scsi/libsas/sas_init.c
index 2b8c09e..e461b98 100644
--- a/drivers/scsi/libsas/sas_init.c
+++ b/drivers/scsi/libsas/sas_init.c
@@ -245,15 +245,15 @@ static int transport_sas_phy_reset(struct sas_phy *phy, int hard_reset)
 	return ret;
 }
 
-int sas_phy_enable(struct sas_phy *phy, int enable)
+static int sas_phy_enable(struct sas_phy *phy, int enable)
 {
 	int ret;
-	enum phy_func command;
+	enum phy_func cmd;
 
 	if (enable)
-		command = PHY_FUNC_LINK_RESET;
+		cmd = PHY_FUNC_LINK_RESET;
 	else
-		command = PHY_FUNC_DISABLE;
+		cmd = PHY_FUNC_DISABLE;
 
 	if (scsi_is_sas_phy_local(phy)) {
 		struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
@@ -262,15 +262,21 @@ int sas_phy_enable(struct sas_phy *phy, int enable)
 		struct sas_internal *i =
 			to_sas_internal(sas_ha->core.shost->transportt);
 
-		if (!enable) {
+		if (enable)
+			ret = transport_sas_phy_reset(phy, 0);
+		else {
 			sas_phy_disconnected(asd_phy);
 			sas_ha->notify_phy_event(asd_phy, PHYE_LOSS_OF_SIGNAL);
+			ret = i->dft->lldd_control_phy(asd_phy, cmd, NULL);
 		}
-		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);
+
+		if (enable)
+			ret = transport_sas_phy_reset(phy, 0);
+		else
+			ret = sas_smp_phy_control(ddev, phy->number, cmd, NULL);
 	}
 	return ret;
 }
diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c
index e51a909..2061e53 100644
--- a/drivers/scsi/libsas/sas_scsi_host.c
+++ b/drivers/scsi/libsas/sas_scsi_host.c
@@ -1083,7 +1083,6 @@ EXPORT_SYMBOL_GPL(sas_change_queue_type);
 EXPORT_SYMBOL_GPL(sas_bios_param);
 EXPORT_SYMBOL_GPL(sas_task_abort);
 EXPORT_SYMBOL_GPL(sas_phy_reset);
-EXPORT_SYMBOL_GPL(sas_phy_enable);
 EXPORT_SYMBOL_GPL(sas_eh_device_reset_handler);
 EXPORT_SYMBOL_GPL(sas_eh_bus_reset_handler);
 EXPORT_SYMBOL_GPL(sas_slave_alloc);
diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c
index 760b80b..45ab52b 100644
--- a/drivers/scsi/scsi_transport_sas.c
+++ b/drivers/scsi/scsi_transport_sas.c
@@ -556,20 +556,20 @@ show_sas_device_type(struct device *dev,
 }
 static DEVICE_ATTR(device_type, S_IRUGO, show_sas_device_type, NULL);
 
-static ssize_t do_sas_phy_enable(struct device *dev,
-		size_t count, int enable)
+static ssize_t do_sas_phy_enable(struct device *dev, size_t count, int enable)
 {
 	struct sas_phy *phy = transport_class_to_phy(dev);
 	struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
-	struct sas_internal *i = to_sas_internal(shost->transportt);
-	int error;
 
-	error = i->f->phy_enable(phy, enable);
-	if (error)
-		return error;
+	phy->enable = enable;
+	phy->enable_result = 0;
+	scsi_queue_work(shost, &phy->enable_work);
+	scsi_flush_work(shost);
+	if (phy->enable_result)
+		return phy->enable_result;
 	phy->enabled = enable;
 	return count;
-};
+}
 
 static ssize_t
 store_sas_phy_enable(struct device *dev, struct device_attribute *attr,
@@ -695,6 +695,15 @@ static void sas_phy_reset_work(struct work_struct *work)
 	phy->reset_result = i->f->phy_reset(phy, phy->hard_reset);
 }
 
+static void sas_phy_enable_work(struct work_struct *work)
+{
+	struct sas_phy *phy = container_of(work, typeof(*phy), enable_work);
+	struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
+	struct sas_internal *i = to_sas_internal(shost->transportt);
+
+	phy->enable_result = i->f->phy_enable(phy, phy->enable);
+}
+
 /**
  * sas_phy_alloc  -  allocates and initialize a SAS PHY structure
  * @parent:	Parent device
@@ -724,6 +733,7 @@ struct sas_phy *sas_phy_alloc(struct device *parent, int number)
 	phy->dev.release = sas_phy_release;
 	INIT_LIST_HEAD(&phy->port_siblings);
 	INIT_WORK(&phy->reset_work, sas_phy_reset_work);
+	INIT_WORK(&phy->enable_work, sas_phy_enable_work);
 	if (scsi_is_sas_expander_device(parent)) {
 		struct sas_rphy *rphy = dev_to_rphy(parent);
 		dev_set_name(&phy->dev, "phy-%d:%d:%d", shost->host_no,
diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h
index 3ffc605..6e8f25d 100644
--- a/include/scsi/libsas.h
+++ b/include/scsi/libsas.h
@@ -624,7 +624,6 @@ extern int sas_unregister_ha(struct sas_ha_struct *);
 
 int sas_set_phy_speed(struct sas_phy *phy,
 		      struct sas_phy_linkrates *rates);
-int sas_phy_enable(struct sas_phy *phy, int enabled);
 int sas_phy_reset(struct sas_phy *phy, int hard_reset);
 int sas_queue_up(struct sas_task *task);
 extern int sas_queuecommand(struct Scsi_Host * ,struct scsi_cmnd *);
diff --git a/include/scsi/scsi_transport_sas.h b/include/scsi/scsi_transport_sas.h
index c7eea0d..698e383 100644
--- a/include/scsi/scsi_transport_sas.h
+++ b/include/scsi/scsi_transport_sas.h
@@ -78,6 +78,9 @@ struct sas_phy {
 	int			hard_reset;
 	int			reset_result;
 	struct work_struct      reset_work;
+	int			enable;
+	int			enable_result;
+	struct work_struct	enable_work;
 };
 
 #define dev_to_phy(d) \
