diff options
author | Dan Williams <dan.j.williams@intel.com> | 2011-12-04 03:06:57 -0500 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2012-02-19 15:18:01 -0500 |
commit | 2a559f4ba443265b4c58925b48296f1cf81b49f9 (patch) | |
tree | 79b2c0ea7e06ce19d00ca097e5df34595afea314 | |
parent | 81c757bc696284f39f07766f0c2ca67af64ce9bd (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.c | 57 | ||||
-rw-r--r-- | drivers/scsi/libsas/sas_internal.h | 3 | ||||
-rw-r--r-- | drivers/scsi/libsas/sas_scsi_host.c | 1 | ||||
-rw-r--r-- | include/scsi/libsas.h | 1 |
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 | ||
252 | int sas_phy_enable(struct sas_phy *phy, int enable) | 252 | static 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 | ||
366 | static 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 | |||
360 | static int sas_phy_setup(struct sas_phy *phy) | 373 | static 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 | ||
416 | static 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 | |||
402 | static struct sas_function_template sft = { | 443 | static 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 | ||
50 | void sas_scsi_recover_host(struct Scsi_Host *shost); | 53 | void 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); | |||
1077 | EXPORT_SYMBOL_GPL(sas_bios_param); | 1077 | EXPORT_SYMBOL_GPL(sas_bios_param); |
1078 | EXPORT_SYMBOL_GPL(sas_task_abort); | 1078 | EXPORT_SYMBOL_GPL(sas_task_abort); |
1079 | EXPORT_SYMBOL_GPL(sas_phy_reset); | 1079 | EXPORT_SYMBOL_GPL(sas_phy_reset); |
1080 | EXPORT_SYMBOL_GPL(sas_phy_enable); | ||
1081 | EXPORT_SYMBOL_GPL(sas_eh_device_reset_handler); | 1080 | EXPORT_SYMBOL_GPL(sas_eh_device_reset_handler); |
1082 | EXPORT_SYMBOL_GPL(sas_eh_bus_reset_handler); | 1081 | EXPORT_SYMBOL_GPL(sas_eh_bus_reset_handler); |
1083 | EXPORT_SYMBOL_GPL(sas_slave_alloc); | 1082 | EXPORT_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 | ||
635 | int sas_set_phy_speed(struct sas_phy *phy, | 635 | int sas_set_phy_speed(struct sas_phy *phy, |
636 | struct sas_phy_linkrates *rates); | 636 | struct sas_phy_linkrates *rates); |
637 | int sas_phy_enable(struct sas_phy *phy, int enabled); | ||
638 | int sas_phy_reset(struct sas_phy *phy, int hard_reset); | 637 | int sas_phy_reset(struct sas_phy *phy, int hard_reset); |
639 | int sas_queue_up(struct sas_task *task); | 638 | int sas_queue_up(struct sas_task *task); |
640 | extern int sas_queuecommand(struct Scsi_Host * ,struct scsi_cmnd *); | 639 | extern int sas_queuecommand(struct Scsi_Host * ,struct scsi_cmnd *); |