Lines Matching +full:d +full:- +full:phy
1 // SPDX-License-Identifier: GPL-2.0-only
32 spin_lock_init(&task->task_state_lock); in sas_alloc_task()
33 task->task_state_flags = SAS_TASK_STATE_PENDING; in sas_alloc_task()
51 task->slow_task = slow; in sas_alloc_slow_task()
52 slow->task = task; in sas_alloc_slow_task()
53 timer_setup(&slow->timer, NULL, 0); in sas_alloc_slow_task()
54 init_completion(&slow->completion); in sas_alloc_slow_task()
62 kfree(task->slow_task); in sas_free_task()
67 /*------------ SAS addr hash -----------*/
77 for (b = (SAS_ADDR_SIZE - 1); b >= 0; b--) { in sas_hash_addr()
98 mutex_init(&sas_ha->disco_mutex); in sas_register_ha()
99 spin_lock_init(&sas_ha->phy_port_lock); in sas_register_ha()
100 sas_hash_addr(sas_ha->hashed_sas_addr, sas_ha->sas_addr); in sas_register_ha()
102 set_bit(SAS_HA_REGISTERED, &sas_ha->state); in sas_register_ha()
103 spin_lock_init(&sas_ha->lock); in sas_register_ha()
104 mutex_init(&sas_ha->drain_mutex); in sas_register_ha()
105 init_waitqueue_head(&sas_ha->eh_wait_q); in sas_register_ha()
106 INIT_LIST_HEAD(&sas_ha->defer_q); in sas_register_ha()
107 INIT_LIST_HEAD(&sas_ha->eh_dev_q); in sas_register_ha()
109 sas_ha->event_thres = SAS_PHY_SHUTDOWN_THRES; in sas_register_ha()
113 pr_notice("couldn't register sas phys:%d\n", error); in sas_register_ha()
119 pr_notice("couldn't register sas ports:%d\n", error); in sas_register_ha()
123 error = -ENOMEM; in sas_register_ha()
124 snprintf(name, sizeof(name), "%s_event_q", dev_name(sas_ha->dev)); in sas_register_ha()
125 sas_ha->event_q = alloc_ordered_workqueue("%s", WQ_MEM_RECLAIM, name); in sas_register_ha()
126 if (!sas_ha->event_q) in sas_register_ha()
129 snprintf(name, sizeof(name), "%s_disco_q", dev_name(sas_ha->dev)); in sas_register_ha()
130 sas_ha->disco_q = alloc_ordered_workqueue("%s", WQ_MEM_RECLAIM, name); in sas_register_ha()
131 if (!sas_ha->disco_q) in sas_register_ha()
134 INIT_LIST_HEAD(&sas_ha->eh_done_q); in sas_register_ha()
135 INIT_LIST_HEAD(&sas_ha->eh_ata_q); in sas_register_ha()
140 destroy_workqueue(sas_ha->event_q); in sas_register_ha()
152 * events to be queued, and flush any in-progress drainers in sas_disable_events()
154 mutex_lock(&sas_ha->drain_mutex); in sas_disable_events()
155 spin_lock_irq(&sas_ha->lock); in sas_disable_events()
156 clear_bit(SAS_HA_REGISTERED, &sas_ha->state); in sas_disable_events()
157 spin_unlock_irq(&sas_ha->lock); in sas_disable_events()
159 mutex_unlock(&sas_ha->drain_mutex); in sas_disable_events()
168 mutex_lock(&sas_ha->drain_mutex); in sas_unregister_ha()
170 mutex_unlock(&sas_ha->drain_mutex); in sas_unregister_ha()
172 destroy_workqueue(sas_ha->disco_q); in sas_unregister_ha()
173 destroy_workqueue(sas_ha->event_q); in sas_unregister_ha()
179 static int sas_get_linkerrors(struct sas_phy *phy) in sas_get_linkerrors() argument
181 if (scsi_is_sas_phy_local(phy)) { in sas_get_linkerrors()
182 struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); in sas_get_linkerrors()
184 struct asd_sas_phy *asd_phy = sas_ha->sas_phy[phy->number]; in sas_get_linkerrors()
186 to_sas_internal(sas_ha->shost->transportt); in sas_get_linkerrors()
188 return i->dft->lldd_control_phy(asd_phy, PHY_FUNC_GET_EVENTS, NULL); in sas_get_linkerrors()
191 return sas_smp_get_phy_events(phy); in sas_get_linkerrors()
199 if (asd_phy->port) in sas_try_ata_reset()
200 dev = asd_phy->port->port_dev; in sas_try_ata_reset()
204 dev = sas_find_dev_by_rphy(dev->rphy); in sas_try_ata_reset()
212 return -ENODEV; in sas_try_ata_reset()
216 * transport_sas_phy_reset - reset a phy and permit libata to manage the link
218 * phy reset request via sysfs in host workqueue context so we know we
221 static int transport_sas_phy_reset(struct sas_phy *phy, int hard_reset) in transport_sas_phy_reset() argument
230 if (scsi_is_sas_phy_local(phy)) { in transport_sas_phy_reset()
231 struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); in transport_sas_phy_reset()
233 struct asd_sas_phy *asd_phy = sas_ha->sas_phy[phy->number]; in transport_sas_phy_reset()
235 to_sas_internal(sas_ha->shost->transportt); in transport_sas_phy_reset()
239 return i->dft->lldd_control_phy(asd_phy, reset_type, NULL); in transport_sas_phy_reset()
241 struct sas_rphy *rphy = dev_to_rphy(phy->dev.parent); in transport_sas_phy_reset()
243 struct domain_device *ata_dev = sas_ex_to_ata(ddev, phy->number); in transport_sas_phy_reset()
250 return sas_smp_phy_control(ddev, phy->number, reset_type, NULL); in transport_sas_phy_reset()
254 int sas_phy_enable(struct sas_phy *phy, int enable) in sas_phy_enable() argument
264 if (scsi_is_sas_phy_local(phy)) { in sas_phy_enable()
265 struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); in sas_phy_enable()
267 struct asd_sas_phy *asd_phy = sas_ha->sas_phy[phy->number]; in sas_phy_enable()
269 to_sas_internal(sas_ha->shost->transportt); in sas_phy_enable()
272 ret = transport_sas_phy_reset(phy, 0); in sas_phy_enable()
274 ret = i->dft->lldd_control_phy(asd_phy, cmd, NULL); in sas_phy_enable()
276 struct sas_rphy *rphy = dev_to_rphy(phy->dev.parent); in sas_phy_enable()
280 ret = transport_sas_phy_reset(phy, 0); in sas_phy_enable()
282 ret = sas_smp_phy_control(ddev, phy->number, cmd, NULL); in sas_phy_enable()
288 int sas_phy_reset(struct sas_phy *phy, int hard_reset) in sas_phy_reset() argument
293 if (!phy->enabled) in sas_phy_reset()
294 return -ENODEV; in sas_phy_reset()
301 if (scsi_is_sas_phy_local(phy)) { in sas_phy_reset()
302 struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); in sas_phy_reset()
304 struct asd_sas_phy *asd_phy = sas_ha->sas_phy[phy->number]; in sas_phy_reset()
306 to_sas_internal(sas_ha->shost->transportt); in sas_phy_reset()
308 ret = i->dft->lldd_control_phy(asd_phy, reset_type, NULL); in sas_phy_reset()
310 struct sas_rphy *rphy = dev_to_rphy(phy->dev.parent); in sas_phy_reset()
312 ret = sas_smp_phy_control(ddev, phy->number, reset_type, NULL); in sas_phy_reset()
318 static int sas_set_phy_speed(struct sas_phy *phy, in sas_set_phy_speed() argument
323 if ((rates->minimum_linkrate && in sas_set_phy_speed()
324 rates->minimum_linkrate > phy->maximum_linkrate) || in sas_set_phy_speed()
325 (rates->maximum_linkrate && in sas_set_phy_speed()
326 rates->maximum_linkrate < phy->minimum_linkrate)) in sas_set_phy_speed()
327 return -EINVAL; in sas_set_phy_speed()
329 if (rates->minimum_linkrate && in sas_set_phy_speed()
330 rates->minimum_linkrate < phy->minimum_linkrate_hw) in sas_set_phy_speed()
331 rates->minimum_linkrate = phy->minimum_linkrate_hw; in sas_set_phy_speed()
333 if (rates->maximum_linkrate && in sas_set_phy_speed()
334 rates->maximum_linkrate > phy->maximum_linkrate_hw) in sas_set_phy_speed()
335 rates->maximum_linkrate = phy->maximum_linkrate_hw; in sas_set_phy_speed()
337 if (scsi_is_sas_phy_local(phy)) { in sas_set_phy_speed()
338 struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); in sas_set_phy_speed()
340 struct asd_sas_phy *asd_phy = sas_ha->sas_phy[phy->number]; in sas_set_phy_speed()
342 to_sas_internal(sas_ha->shost->transportt); in sas_set_phy_speed()
344 ret = i->dft->lldd_control_phy(asd_phy, PHY_FUNC_SET_LINK_RATE, in sas_set_phy_speed()
347 struct sas_rphy *rphy = dev_to_rphy(phy->dev.parent); in sas_set_phy_speed()
349 ret = sas_smp_phy_control(ddev, phy->number, in sas_set_phy_speed()
361 set_bit(SAS_HA_REGISTERED, &ha->state); in sas_prep_resume_ha()
362 set_bit(SAS_HA_RESUMING, &ha->state); in sas_prep_resume_ha()
365 for (i = 0; i < ha->num_phys; i++) { in sas_prep_resume_ha()
366 struct asd_sas_phy *phy = ha->sas_phy[i]; in sas_prep_resume_ha() local
368 memset(phy->attached_sas_addr, 0, SAS_ADDR_SIZE); in sas_prep_resume_ha()
369 phy->frame_rcvd_size = 0; in sas_prep_resume_ha()
378 for (i = 0; i < ha->num_phys; i++) { in phys_suspended()
379 struct asd_sas_phy *phy = ha->sas_phy[i]; in phys_suspended() local
381 if (phy->suspended) in phys_suspended()
392 for (i = 0; i < ha->num_phys; i++) { in sas_resume_insert_broadcast_ha()
393 struct asd_sas_port *port = ha->sas_port[i]; in sas_resume_insert_broadcast_ha()
394 struct domain_device *dev = port->port_dev; in sas_resume_insert_broadcast_ha()
396 if (dev && dev_is_expander(dev->dev_type)) { in sas_resume_insert_broadcast_ha()
399 spin_lock(&port->phy_list_lock); in sas_resume_insert_broadcast_ha()
401 &port->phy_list, struct asd_sas_phy, in sas_resume_insert_broadcast_ha()
403 spin_unlock(&port->phy_list_lock); in sas_resume_insert_broadcast_ha()
418 * at this point we may be racing the phy coming back (as posted in _sas_resume_ha()
420 * libsas context check that the phy remains suspended before in _sas_resume_ha()
425 dev_info(ha->dev, "waiting up to 25 seconds for %d phy%s to resume\n", in _sas_resume_ha()
427 wait_event_timeout(ha->eh_wait_q, phys_suspended(ha) == 0, tmo); in _sas_resume_ha()
428 for (i = 0; i < ha->num_phys; i++) { in _sas_resume_ha()
429 struct asd_sas_phy *phy = ha->sas_phy[i]; in _sas_resume_ha() local
431 if (phy->suspended) { in _sas_resume_ha()
432 dev_warn(&phy->phy->dev, "resume timeout\n"); in _sas_resume_ha()
433 sas_notify_phy_event(phy, PHYE_RESUME_TIMEOUT, in _sas_resume_ha()
441 scsi_unblock_requests(ha->shost); in _sas_resume_ha()
444 clear_bit(SAS_HA_RESUMING, &ha->state); in _sas_resume_ha()
459 /* A no-sync variant, which does not call sas_drain_ha(). */
471 scsi_block_requests(ha->shost); in sas_suspend_ha()
472 for (i = 0; i < ha->num_phys; i++) { in sas_suspend_ha()
473 struct asd_sas_port *port = ha->sas_port[i]; in sas_suspend_ha()
479 mutex_lock(&ha->drain_mutex); in sas_suspend_ha()
481 mutex_unlock(&ha->drain_mutex); in sas_suspend_ha()
485 static void sas_phy_release(struct sas_phy *phy) in sas_phy_release() argument
487 kfree(phy->hostdata); in sas_phy_release()
488 phy->hostdata = NULL; in sas_phy_release()
493 struct sas_phy_data *d = container_of(work, typeof(*d), reset_work.work); in phy_reset_work() local
495 d->reset_result = transport_sas_phy_reset(d->phy, d->hard_reset); in phy_reset_work()
500 struct sas_phy_data *d = container_of(work, typeof(*d), enable_work.work); in phy_enable_work() local
502 d->enable_result = sas_phy_enable(d->phy, d->enable); in phy_enable_work()
505 static int sas_phy_setup(struct sas_phy *phy) in sas_phy_setup() argument
507 struct sas_phy_data *d = kzalloc(sizeof(*d), GFP_KERNEL); in sas_phy_setup() local
509 if (!d) in sas_phy_setup()
510 return -ENOMEM; in sas_phy_setup()
512 mutex_init(&d->event_lock); in sas_phy_setup()
513 INIT_SAS_WORK(&d->reset_work, phy_reset_work); in sas_phy_setup()
514 INIT_SAS_WORK(&d->enable_work, phy_enable_work); in sas_phy_setup()
515 d->phy = phy; in sas_phy_setup()
516 phy->hostdata = d; in sas_phy_setup()
521 static int queue_phy_reset(struct sas_phy *phy, int hard_reset) in queue_phy_reset() argument
523 struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); in queue_phy_reset()
525 struct sas_phy_data *d = phy->hostdata; in queue_phy_reset() local
528 if (!d) in queue_phy_reset()
529 return -ENOMEM; in queue_phy_reset()
531 pm_runtime_get_sync(ha->dev); in queue_phy_reset()
532 /* libsas workqueue coordinates ata-eh reset with discovery */ in queue_phy_reset()
533 mutex_lock(&d->event_lock); in queue_phy_reset()
534 d->reset_result = 0; in queue_phy_reset()
535 d->hard_reset = hard_reset; in queue_phy_reset()
537 spin_lock_irq(&ha->lock); in queue_phy_reset()
538 sas_queue_work(ha, &d->reset_work); in queue_phy_reset()
539 spin_unlock_irq(&ha->lock); in queue_phy_reset()
543 rc = d->reset_result; in queue_phy_reset()
544 mutex_unlock(&d->event_lock); in queue_phy_reset()
545 pm_runtime_put_sync(ha->dev); in queue_phy_reset()
550 static int queue_phy_enable(struct sas_phy *phy, int enable) in queue_phy_enable() argument
552 struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); in queue_phy_enable()
554 struct sas_phy_data *d = phy->hostdata; in queue_phy_enable() local
557 if (!d) in queue_phy_enable()
558 return -ENOMEM; in queue_phy_enable()
560 pm_runtime_get_sync(ha->dev); in queue_phy_enable()
561 /* libsas workqueue coordinates ata-eh reset with discovery */ in queue_phy_enable()
562 mutex_lock(&d->event_lock); in queue_phy_enable()
563 d->enable_result = 0; in queue_phy_enable()
564 d->enable = enable; in queue_phy_enable()
566 spin_lock_irq(&ha->lock); in queue_phy_enable()
567 sas_queue_work(ha, &d->enable_work); in queue_phy_enable()
568 spin_unlock_irq(&ha->lock); in queue_phy_enable()
572 rc = d->enable_result; in queue_phy_enable()
573 mutex_unlock(&d->event_lock); in queue_phy_enable()
574 pm_runtime_put_sync(ha->dev); in queue_phy_enable()
595 return scnprintf(buf, PAGE_SIZE, "%u\n", sha->event_thres); in phy_event_threshold_show()
605 sha->event_thres = simple_strtol(buf, NULL, 10); in phy_event_threshold_store()
608 if (sha->event_thres < 32) in phy_event_threshold_store()
609 sha->event_thres = 32; in phy_event_threshold_store()
630 i->dft = dft; in sas_domain_attach_transport()
631 stt->create_work_queue = 1; in sas_domain_attach_transport()
632 stt->eh_strategy_handler = sas_scsi_recover_host; in sas_domain_attach_transport()
638 struct asd_sas_event *sas_alloc_event(struct asd_sas_phy *phy, in sas_alloc_event() argument
642 struct sas_ha_struct *sas_ha = phy->ha; in sas_alloc_event()
644 to_sas_internal(sas_ha->shost->transportt); in sas_alloc_event()
650 atomic_inc(&phy->event_nr); in sas_alloc_event()
652 if (atomic_read(&phy->event_nr) > phy->ha->event_thres) { in sas_alloc_event()
653 if (i->dft->lldd_control_phy) { in sas_alloc_event()
654 if (cmpxchg(&phy->in_shutdown, 0, 1) == 0) { in sas_alloc_event()
655 pr_notice("The phy%d bursting events, shut it down.\n", in sas_alloc_event()
656 phy->id); in sas_alloc_event()
657 sas_notify_phy_event(phy, PHYE_SHUTDOWN, in sas_alloc_event()
661 /* Do not support PHY control, stop allocating events */ in sas_alloc_event()
662 WARN_ONCE(1, "PHY control not supported.\n"); in sas_alloc_event()
664 atomic_dec(&phy->event_nr); in sas_alloc_event()
674 struct asd_sas_phy *phy = event->phy; in sas_free_event() local
677 atomic_dec(&phy->event_nr); in sas_free_event()
680 /* ---------- SAS Class register/unregister ---------- */
696 return -ENOMEM; in sas_class_init()