aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/libsas/sas_init.c
diff options
context:
space:
mode:
authorDarrick J. Wong <djwong@us.ibm.com>2007-01-11 14:14:57 -0800
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2007-01-13 16:13:00 -0600
commitacbf167d4ad8c27f9743a4b539d51ae9535bf21c (patch)
treee53f8330f60acaef42d74a745b3dd5131b424e49 /drivers/scsi/libsas/sas_init.c
parent[SCSI] libsas: Don't give scsi_cmnds to the EH if they never made it to the SAS LLDD or have already returned (diff)
downloadlinux-dev-acbf167d4ad8c27f9743a4b539d51ae9535bf21c.tar.xz
linux-dev-acbf167d4ad8c27f9743a4b539d51ae9535bf21c.zip
[SCSI] libsas: Add a sysfs knob to enable/disable a phy
This patch lets a user arbitrarily enable or disable a phy via sysfs. Potential applications include shutting down a phy to replace one lane of wide port, and (more importantly) providing a method for the libata SATL to control the phy. Signed-off-by: Darrick J. Wong <djwong@us.ibm.com> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/libsas/sas_init.c')
-rw-r--r--drivers/scsi/libsas/sas_init.c35
1 files changed, 33 insertions, 2 deletions
diff --git a/drivers/scsi/libsas/sas_init.c b/drivers/scsi/libsas/sas_init.c
index 2f0c07fc3f48..90cce34cb6f5 100644
--- a/drivers/scsi/libsas/sas_init.c
+++ b/drivers/scsi/libsas/sas_init.c
@@ -146,6 +146,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 +202,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,6 +242,7 @@ 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,