@@ -249,15 +249,15 @@ static int transport_sas_phy_reset(struct sas_phy *phy, int hard_reset)
249
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
254
int ret ;
255
- enum phy_func command ;
255
+ enum phy_func cmd ;
256
256
257
257
if (enable )
258
- command = PHY_FUNC_LINK_RESET ;
258
+ cmd = PHY_FUNC_LINK_RESET ;
259
259
else
260
- command = PHY_FUNC_DISABLE ;
260
+ cmd = PHY_FUNC_DISABLE ;
261
261
262
262
if (scsi_is_sas_phy_local (phy )) {
263
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
266
struct sas_internal * i =
267
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
272
sas_phy_disconnected (asd_phy );
271
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
276
} else {
275
277
struct sas_rphy * rphy = dev_to_rphy (phy -> dev .parent );
276
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
285
return ret ;
280
286
}
@@ -357,6 +363,13 @@ static void phy_reset_work(struct work_struct *work)
357
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
373
static int sas_phy_setup (struct sas_phy * phy )
361
374
{
362
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
380
mutex_init (& d -> event_lock );
368
381
INIT_WORK (& d -> reset_work , phy_reset_work );
382
+ INIT_WORK (& d -> enable_work , phy_enable_work );
369
383
d -> phy = phy ;
370
384
phy -> hostdata = d ;
371
385
@@ -399,8 +413,35 @@ static int queue_phy_reset(struct sas_phy *phy, int hard_reset)
399
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
443
static struct sas_function_template sft = {
403
- .phy_enable = sas_phy_enable ,
444
+ .phy_enable = queue_phy_enable ,
404
445
.phy_reset = queue_phy_reset ,
405
446
.phy_setup = sas_phy_setup ,
406
447
.phy_release = sas_phy_release ,
0 commit comments