aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2011-12-04 03:06:57 -0500
committerJames Bottomley <JBottomley@Parallels.com>2012-02-19 15:18:01 -0500
commit2a559f4ba443265b4c58925b48296f1cf81b49f9 (patch)
tree79b2c0ea7e06ce19d00ca097e5df34595afea314
parent81c757bc696284f39f07766f0c2ca67af64ce9bd (diff)
[SCSI] libsas: sas_phy_enable via transport_sas_phy_reset
Execute the link-reset triggered by sas_phy_enable via transport_sas_phy_reset so that it can be managed by libata. Signed-off-by: Dan Williams <dan.j.williams@intel.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
-rw-r--r--drivers/scsi/libsas/sas_init.c57
-rw-r--r--drivers/scsi/libsas/sas_internal.h3
-rw-r--r--drivers/scsi/libsas/sas_scsi_host.c1
-rw-r--r--include/scsi/libsas.h1
4 files changed, 52 insertions, 10 deletions
diff --git a/drivers/scsi/libsas/sas_init.c b/drivers/scsi/libsas/sas_init.c
index a15fb861daba..53ae893e8b0b 100644
--- a/drivers/scsi/libsas/sas_init.c
+++ b/drivers/scsi/libsas/sas_init.c
@@ -249,15 +249,15 @@ static int transport_sas_phy_reset(struct sas_phy *phy, int hard_reset)
249 return ret; 249 return ret;
250} 250}
251 251
252int sas_phy_enable(struct sas_phy *phy, int enable) 252static int sas_phy_enable(struct sas_phy *phy, int enable)
253{ 253{
254 int ret; 254 int ret;
255 enum phy_func command; 255 enum phy_func cmd;
256 256
257 if (enable) 257 if (enable)
258 command = PHY_FUNC_LINK_RESET; 258 cmd = PHY_FUNC_LINK_RESET;
259 else 259 else
260 command = PHY_FUNC_DISABLE; 260 cmd = PHY_FUNC_DISABLE;
261 261
262 if (scsi_is_sas_phy_local(phy)) { 262 if (scsi_is_sas_phy_local(phy)) {
263 struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); 263 struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
@@ -266,15 +266,21 @@ int sas_phy_enable(struct sas_phy *phy, int enable)
266 struct sas_internal *i = 266 struct sas_internal *i =
267 to_sas_internal(sas_ha->core.shost->transportt); 267 to_sas_internal(sas_ha->core.shost->transportt);
268 268
269 if (!enable) { 269 if (enable)
270 ret = transport_sas_phy_reset(phy, 0);
271 else {
270 sas_phy_disconnected(asd_phy); 272 sas_phy_disconnected(asd_phy);
271 sas_ha->notify_phy_event(asd_phy, PHYE_LOSS_OF_SIGNAL); 273 sas_ha->notify_phy_event(asd_phy, PHYE_LOSS_OF_SIGNAL);
274 ret = i->dft->lldd_control_phy(asd_phy, cmd, NULL);
272 } 275 }
273 ret = i->dft->lldd_control_phy(asd_phy, command, NULL);
274 } else { 276 } else {
275 struct sas_rphy *rphy = dev_to_rphy(phy->dev.parent); 277 struct sas_rphy *rphy = dev_to_rphy(phy->dev.parent);
276 struct domain_device *ddev = sas_find_dev_by_rphy(rphy); 278 struct domain_device *ddev = sas_find_dev_by_rphy(rphy);
277 ret = sas_smp_phy_control(ddev, phy->number, command, NULL); 279
280 if (enable)
281 ret = transport_sas_phy_reset(phy, 0);
282 else
283 ret = sas_smp_phy_control(ddev, phy->number, cmd, NULL);
278 } 284 }
279 return ret; 285 return ret;
280} 286}
@@ -357,6 +363,13 @@ static void phy_reset_work(struct work_struct *work)
357 d->reset_result = transport_sas_phy_reset(d->phy, d->hard_reset); 363 d->reset_result = transport_sas_phy_reset(d->phy, d->hard_reset);
358} 364}
359 365
366static void phy_enable_work(struct work_struct *work)
367{
368 struct sas_phy_data *d = container_of(work, typeof(*d), enable_work);
369
370 d->enable_result = sas_phy_enable(d->phy, d->enable);
371}
372
360static int sas_phy_setup(struct sas_phy *phy) 373static int sas_phy_setup(struct sas_phy *phy)
361{ 374{
362 struct sas_phy_data *d = kzalloc(sizeof(*d), GFP_KERNEL); 375 struct sas_phy_data *d = kzalloc(sizeof(*d), GFP_KERNEL);
@@ -366,6 +379,7 @@ static int sas_phy_setup(struct sas_phy *phy)
366 379
367 mutex_init(&d->event_lock); 380 mutex_init(&d->event_lock);
368 INIT_WORK(&d->reset_work, phy_reset_work); 381 INIT_WORK(&d->reset_work, phy_reset_work);
382 INIT_WORK(&d->enable_work, phy_enable_work);
369 d->phy = phy; 383 d->phy = phy;
370 phy->hostdata = d; 384 phy->hostdata = d;
371 385
@@ -399,8 +413,35 @@ static int queue_phy_reset(struct sas_phy *phy, int hard_reset)
399 return rc; 413 return rc;
400} 414}
401 415
416static int queue_phy_enable(struct sas_phy *phy, int enable)
417{
418 struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
419 struct sas_ha_struct *ha = SHOST_TO_SAS_HA(shost);
420 struct sas_phy_data *d = phy->hostdata;
421 int rc;
422
423 if (!d)
424 return -ENOMEM;
425
426 /* libsas workqueue coordinates ata-eh reset with discovery */
427 mutex_lock(&d->event_lock);
428 d->enable_result = 0;
429 d->enable = enable;
430
431 spin_lock_irq(&ha->state_lock);
432 sas_queue_work(ha, &d->enable_work);
433 spin_unlock_irq(&ha->state_lock);
434
435 rc = sas_drain_work(ha);
436 if (rc == 0)
437 rc = d->enable_result;
438 mutex_unlock(&d->event_lock);
439
440 return rc;
441}
442
402static struct sas_function_template sft = { 443static struct sas_function_template sft = {
403 .phy_enable = sas_phy_enable, 444 .phy_enable = queue_phy_enable,
404 .phy_reset = queue_phy_reset, 445 .phy_reset = queue_phy_reset,
405 .phy_setup = sas_phy_setup, 446 .phy_setup = sas_phy_setup,
406 .phy_release = sas_phy_release, 447 .phy_release = sas_phy_release,
diff --git a/drivers/scsi/libsas/sas_internal.h b/drivers/scsi/libsas/sas_internal.h
index ae9698d9d857..9e960b2d535a 100644
--- a/drivers/scsi/libsas/sas_internal.h
+++ b/drivers/scsi/libsas/sas_internal.h
@@ -45,6 +45,9 @@ struct sas_phy_data {
45 int hard_reset; 45 int hard_reset;
46 int reset_result; 46 int reset_result;
47 struct work_struct reset_work; 47 struct work_struct reset_work;
48 int enable;
49 int enable_result;
50 struct work_struct enable_work;
48}; 51};
49 52
50void sas_scsi_recover_host(struct Scsi_Host *shost); 53void sas_scsi_recover_host(struct Scsi_Host *shost);
diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c
index af71a6d0edae..5cc44fddfe95 100644
--- a/drivers/scsi/libsas/sas_scsi_host.c
+++ b/drivers/scsi/libsas/sas_scsi_host.c
@@ -1077,7 +1077,6 @@ EXPORT_SYMBOL_GPL(sas_change_queue_type);
1077EXPORT_SYMBOL_GPL(sas_bios_param); 1077EXPORT_SYMBOL_GPL(sas_bios_param);
1078EXPORT_SYMBOL_GPL(sas_task_abort); 1078EXPORT_SYMBOL_GPL(sas_task_abort);
1079EXPORT_SYMBOL_GPL(sas_phy_reset); 1079EXPORT_SYMBOL_GPL(sas_phy_reset);
1080EXPORT_SYMBOL_GPL(sas_phy_enable);
1081EXPORT_SYMBOL_GPL(sas_eh_device_reset_handler); 1080EXPORT_SYMBOL_GPL(sas_eh_device_reset_handler);
1082EXPORT_SYMBOL_GPL(sas_eh_bus_reset_handler); 1081EXPORT_SYMBOL_GPL(sas_eh_bus_reset_handler);
1083EXPORT_SYMBOL_GPL(sas_slave_alloc); 1082EXPORT_SYMBOL_GPL(sas_slave_alloc);
diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h
index 6b80310e08af..f388ba536128 100644
--- a/include/scsi/libsas.h
+++ b/include/scsi/libsas.h
@@ -634,7 +634,6 @@ extern int sas_unregister_ha(struct sas_ha_struct *);
634 634
635int sas_set_phy_speed(struct sas_phy *phy, 635int sas_set_phy_speed(struct sas_phy *phy,
636 struct sas_phy_linkrates *rates); 636 struct sas_phy_linkrates *rates);
637int sas_phy_enable(struct sas_phy *phy, int enabled);
638int sas_phy_reset(struct sas_phy *phy, int hard_reset); 637int sas_phy_reset(struct sas_phy *phy, int hard_reset);
639int sas_queue_up(struct sas_task *task); 638int sas_queue_up(struct sas_task *task);
640extern int sas_queuecommand(struct Scsi_Host * ,struct scsi_cmnd *); 639extern int sas_queuecommand(struct Scsi_Host * ,struct scsi_cmnd *);