From 90d573867ed25a3cedaae6649f8e7e42bcb17215 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sun, 4 Dec 2011 00:06:57 -0800 Subject: [PATCH] --- yaml --- r: 292999 b: refs/heads/master c: 2a559f4ba443265b4c58925b48296f1cf81b49f9 h: refs/heads/master i: 292997: 7edec74d2ab8fa37328ad554af14791e8ef14b9c 292995: cf6ace7e8179adafe990db4015f410cebc0fc1fd 292991: 916ef954cfedc5b7acf4286d9747ef8c6158ee6a v: v3 --- [refs] | 2 +- trunk/drivers/scsi/libsas/sas_init.c | 57 +++++++++++++++++++---- trunk/drivers/scsi/libsas/sas_internal.h | 3 ++ trunk/drivers/scsi/libsas/sas_scsi_host.c | 1 - trunk/include/scsi/libsas.h | 1 - 5 files changed, 53 insertions(+), 11 deletions(-) diff --git a/[refs] b/[refs] index 15b24f306050..b308dee02d0b 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 81c757bc696284f39f07766f0c2ca67af64ce9bd +refs/heads/master: 2a559f4ba443265b4c58925b48296f1cf81b49f9 diff --git a/trunk/drivers/scsi/libsas/sas_init.c b/trunk/drivers/scsi/libsas/sas_init.c index a15fb861daba..53ae893e8b0b 100644 --- a/trunk/drivers/scsi/libsas/sas_init.c +++ b/trunk/drivers/scsi/libsas/sas_init.c @@ -249,15 +249,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); @@ -266,15 +266,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; } @@ -357,6 +363,13 @@ static void phy_reset_work(struct work_struct *work) d->reset_result = transport_sas_phy_reset(d->phy, d->hard_reset); } +static void phy_enable_work(struct work_struct *work) +{ + struct sas_phy_data *d = container_of(work, typeof(*d), enable_work); + + d->enable_result = sas_phy_enable(d->phy, d->enable); +} + static int sas_phy_setup(struct sas_phy *phy) { struct sas_phy_data *d = kzalloc(sizeof(*d), GFP_KERNEL); @@ -366,6 +379,7 @@ static int sas_phy_setup(struct sas_phy *phy) mutex_init(&d->event_lock); INIT_WORK(&d->reset_work, phy_reset_work); + INIT_WORK(&d->enable_work, phy_enable_work); d->phy = phy; phy->hostdata = d; @@ -399,8 +413,35 @@ static int queue_phy_reset(struct sas_phy *phy, int hard_reset) return rc; } +static int queue_phy_enable(struct sas_phy *phy, int enable) +{ + struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); + struct sas_ha_struct *ha = SHOST_TO_SAS_HA(shost); + struct sas_phy_data *d = phy->hostdata; + int rc; + + if (!d) + return -ENOMEM; + + /* libsas workqueue coordinates ata-eh reset with discovery */ + mutex_lock(&d->event_lock); + d->enable_result = 0; + d->enable = enable; + + spin_lock_irq(&ha->state_lock); + sas_queue_work(ha, &d->enable_work); + spin_unlock_irq(&ha->state_lock); + + rc = sas_drain_work(ha); + if (rc == 0) + rc = d->enable_result; + mutex_unlock(&d->event_lock); + + return rc; +} + static struct sas_function_template sft = { - .phy_enable = sas_phy_enable, + .phy_enable = queue_phy_enable, .phy_reset = queue_phy_reset, .phy_setup = sas_phy_setup, .phy_release = sas_phy_release, diff --git a/trunk/drivers/scsi/libsas/sas_internal.h b/trunk/drivers/scsi/libsas/sas_internal.h index ae9698d9d857..9e960b2d535a 100644 --- a/trunk/drivers/scsi/libsas/sas_internal.h +++ b/trunk/drivers/scsi/libsas/sas_internal.h @@ -45,6 +45,9 @@ struct sas_phy_data { int hard_reset; int reset_result; struct work_struct reset_work; + int enable; + int enable_result; + struct work_struct enable_work; }; void sas_scsi_recover_host(struct Scsi_Host *shost); diff --git a/trunk/drivers/scsi/libsas/sas_scsi_host.c b/trunk/drivers/scsi/libsas/sas_scsi_host.c index af71a6d0edae..5cc44fddfe95 100644 --- a/trunk/drivers/scsi/libsas/sas_scsi_host.c +++ b/trunk/drivers/scsi/libsas/sas_scsi_host.c @@ -1077,7 +1077,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/trunk/include/scsi/libsas.h b/trunk/include/scsi/libsas.h index 6b80310e08af..f388ba536128 100644 --- a/trunk/include/scsi/libsas.h +++ b/trunk/include/scsi/libsas.h @@ -634,7 +634,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 *);