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()
52 task->slow_task = slow; in sas_alloc_slow_task()
53 slow->task = task; in sas_alloc_slow_task()
54 timer_setup(&slow->timer, NULL, 0); in sas_alloc_slow_task()
55 init_completion(&slow->completion); in sas_alloc_slow_task()
64 kfree(task->slow_task); in sas_free_task()
70 /*------------ SAS addr hash -----------*/
80 for (b = (SAS_ADDR_SIZE - 1); b >= 0; b--) { in sas_hash_addr()
101 mutex_init(&sas_ha->disco_mutex); in sas_register_ha()
102 spin_lock_init(&sas_ha->phy_port_lock); in sas_register_ha()
103 sas_hash_addr(sas_ha->hashed_sas_addr, sas_ha->sas_addr); in sas_register_ha()
105 set_bit(SAS_HA_REGISTERED, &sas_ha->state); in sas_register_ha()
106 spin_lock_init(&sas_ha->lock); in sas_register_ha()
107 mutex_init(&sas_ha->drain_mutex); in sas_register_ha()
108 init_waitqueue_head(&sas_ha->eh_wait_q); in sas_register_ha()
109 INIT_LIST_HEAD(&sas_ha->defer_q); in sas_register_ha()
110 INIT_LIST_HEAD(&sas_ha->eh_dev_q); in sas_register_ha()
112 sas_ha->event_thres = SAS_PHY_SHUTDOWN_THRES; in sas_register_ha()
116 pr_notice("couldn't register sas phys:%d\n", error); in sas_register_ha()
122 pr_notice("couldn't register sas ports:%d\n", error); in sas_register_ha()
128 pr_notice("couldn't start event thread:%d\n", error); in sas_register_ha()
132 error = -ENOMEM; in sas_register_ha()
133 snprintf(name, sizeof(name), "%s_event_q", dev_name(sas_ha->dev)); in sas_register_ha()
134 sas_ha->event_q = create_singlethread_workqueue(name); in sas_register_ha()
135 if (!sas_ha->event_q) in sas_register_ha()
138 snprintf(name, sizeof(name), "%s_disco_q", dev_name(sas_ha->dev)); in sas_register_ha()
139 sas_ha->disco_q = create_singlethread_workqueue(name); in sas_register_ha()
140 if (!sas_ha->disco_q) in sas_register_ha()
143 INIT_LIST_HEAD(&sas_ha->eh_done_q); in sas_register_ha()
144 INIT_LIST_HEAD(&sas_ha->eh_ata_q); in sas_register_ha()
149 destroy_workqueue(sas_ha->event_q); in sas_register_ha()
160 * events to be queued, and flush any in-progress drainers in sas_disable_events()
162 mutex_lock(&sas_ha->drain_mutex); in sas_disable_events()
163 spin_lock_irq(&sas_ha->lock); in sas_disable_events()
164 clear_bit(SAS_HA_REGISTERED, &sas_ha->state); in sas_disable_events()
165 spin_unlock_irq(&sas_ha->lock); in sas_disable_events()
167 mutex_unlock(&sas_ha->drain_mutex); in sas_disable_events()
176 mutex_lock(&sas_ha->drain_mutex); in sas_unregister_ha()
178 mutex_unlock(&sas_ha->drain_mutex); in sas_unregister_ha()
180 destroy_workqueue(sas_ha->disco_q); in sas_unregister_ha()
181 destroy_workqueue(sas_ha->event_q); in sas_unregister_ha()
186 static int sas_get_linkerrors(struct sas_phy *phy) in sas_get_linkerrors() argument
188 if (scsi_is_sas_phy_local(phy)) { in sas_get_linkerrors()
189 struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); in sas_get_linkerrors()
191 struct asd_sas_phy *asd_phy = sas_ha->sas_phy[phy->number]; in sas_get_linkerrors()
193 to_sas_internal(sas_ha->core.shost->transportt); in sas_get_linkerrors()
195 return i->dft->lldd_control_phy(asd_phy, PHY_FUNC_GET_EVENTS, NULL); in sas_get_linkerrors()
198 return sas_smp_get_phy_events(phy); in sas_get_linkerrors()
206 if (asd_phy->port) in sas_try_ata_reset()
207 dev = asd_phy->port->port_dev; in sas_try_ata_reset()
211 dev = sas_find_dev_by_rphy(dev->rphy); in sas_try_ata_reset()
219 return -ENODEV; in sas_try_ata_reset()
223 * transport_sas_phy_reset - reset a phy and permit libata to manage the link
225 * phy reset request via sysfs in host workqueue context so we know we
228 static int transport_sas_phy_reset(struct sas_phy *phy, int hard_reset) in transport_sas_phy_reset() argument
237 if (scsi_is_sas_phy_local(phy)) { in transport_sas_phy_reset()
238 struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); in transport_sas_phy_reset()
240 struct asd_sas_phy *asd_phy = sas_ha->sas_phy[phy->number]; in transport_sas_phy_reset()
242 to_sas_internal(sas_ha->core.shost->transportt); in transport_sas_phy_reset()
246 return i->dft->lldd_control_phy(asd_phy, reset_type, NULL); in transport_sas_phy_reset()
248 struct sas_rphy *rphy = dev_to_rphy(phy->dev.parent); in transport_sas_phy_reset()
250 struct domain_device *ata_dev = sas_ex_to_ata(ddev, phy->number); in transport_sas_phy_reset()
257 return sas_smp_phy_control(ddev, phy->number, reset_type, NULL); in transport_sas_phy_reset()
261 static int sas_phy_enable(struct sas_phy *phy, int enable) in sas_phy_enable() argument
271 if (scsi_is_sas_phy_local(phy)) { in sas_phy_enable()
272 struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); in sas_phy_enable()
274 struct asd_sas_phy *asd_phy = sas_ha->sas_phy[phy->number]; in sas_phy_enable()
276 to_sas_internal(sas_ha->core.shost->transportt); in sas_phy_enable()
279 ret = transport_sas_phy_reset(phy, 0); in sas_phy_enable()
281 ret = i->dft->lldd_control_phy(asd_phy, cmd, NULL); in sas_phy_enable()
283 struct sas_rphy *rphy = dev_to_rphy(phy->dev.parent); in sas_phy_enable()
287 ret = transport_sas_phy_reset(phy, 0); in sas_phy_enable()
289 ret = sas_smp_phy_control(ddev, phy->number, cmd, NULL); in sas_phy_enable()
294 int sas_phy_reset(struct sas_phy *phy, int hard_reset) in sas_phy_reset() argument
299 if (!phy->enabled) in sas_phy_reset()
300 return -ENODEV; in sas_phy_reset()
307 if (scsi_is_sas_phy_local(phy)) { in sas_phy_reset()
308 struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); in sas_phy_reset()
310 struct asd_sas_phy *asd_phy = sas_ha->sas_phy[phy->number]; in sas_phy_reset()
312 to_sas_internal(sas_ha->core.shost->transportt); in sas_phy_reset()
314 ret = i->dft->lldd_control_phy(asd_phy, reset_type, NULL); in sas_phy_reset()
316 struct sas_rphy *rphy = dev_to_rphy(phy->dev.parent); in sas_phy_reset()
318 ret = sas_smp_phy_control(ddev, phy->number, reset_type, NULL); in sas_phy_reset()
323 int sas_set_phy_speed(struct sas_phy *phy, in sas_set_phy_speed() argument
328 if ((rates->minimum_linkrate && in sas_set_phy_speed()
329 rates->minimum_linkrate > phy->maximum_linkrate) || in sas_set_phy_speed()
330 (rates->maximum_linkrate && in sas_set_phy_speed()
331 rates->maximum_linkrate < phy->minimum_linkrate)) in sas_set_phy_speed()
332 return -EINVAL; in sas_set_phy_speed()
334 if (rates->minimum_linkrate && in sas_set_phy_speed()
335 rates->minimum_linkrate < phy->minimum_linkrate_hw) in sas_set_phy_speed()
336 rates->minimum_linkrate = phy->minimum_linkrate_hw; in sas_set_phy_speed()
338 if (rates->maximum_linkrate && in sas_set_phy_speed()
339 rates->maximum_linkrate > phy->maximum_linkrate_hw) in sas_set_phy_speed()
340 rates->maximum_linkrate = phy->maximum_linkrate_hw; in sas_set_phy_speed()
342 if (scsi_is_sas_phy_local(phy)) { in sas_set_phy_speed()
343 struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); in sas_set_phy_speed()
345 struct asd_sas_phy *asd_phy = sas_ha->sas_phy[phy->number]; in sas_set_phy_speed()
347 to_sas_internal(sas_ha->core.shost->transportt); in sas_set_phy_speed()
349 ret = i->dft->lldd_control_phy(asd_phy, PHY_FUNC_SET_LINK_RATE, in sas_set_phy_speed()
352 struct sas_rphy *rphy = dev_to_rphy(phy->dev.parent); in sas_set_phy_speed()
354 ret = sas_smp_phy_control(ddev, phy->number, in sas_set_phy_speed()
366 set_bit(SAS_HA_REGISTERED, &ha->state); in sas_prep_resume_ha()
369 for (i = 0; i < ha->num_phys; i++) { in sas_prep_resume_ha()
370 struct asd_sas_phy *phy = ha->sas_phy[i]; in sas_prep_resume_ha() local
372 memset(phy->attached_sas_addr, 0, SAS_ADDR_SIZE); in sas_prep_resume_ha()
373 phy->frame_rcvd_size = 0; in sas_prep_resume_ha()
382 for (i = 0; i < ha->num_phys; i++) { in phys_suspended()
383 struct asd_sas_phy *phy = ha->sas_phy[i]; in phys_suspended() local
385 if (phy->suspended) in phys_suspended()
398 * at this point we may be racing the phy coming back (as posted in sas_resume_ha()
400 * libsas context check that the phy remains suspended before in sas_resume_ha()
405 dev_info(ha->dev, "waiting up to 25 seconds for %d phy%s to resume\n", in sas_resume_ha()
407 wait_event_timeout(ha->eh_wait_q, phys_suspended(ha) == 0, tmo); in sas_resume_ha()
408 for (i = 0; i < ha->num_phys; i++) { in sas_resume_ha()
409 struct asd_sas_phy *phy = ha->sas_phy[i]; in sas_resume_ha() local
411 if (phy->suspended) { in sas_resume_ha()
412 dev_warn(&phy->phy->dev, "resume timeout\n"); in sas_resume_ha()
413 sas_notify_phy_event(phy, PHYE_RESUME_TIMEOUT); in sas_resume_ha()
420 scsi_unblock_requests(ha->core.shost); in sas_resume_ha()
430 scsi_block_requests(ha->core.shost); in sas_suspend_ha()
431 for (i = 0; i < ha->num_phys; i++) { in sas_suspend_ha()
432 struct asd_sas_port *port = ha->sas_port[i]; in sas_suspend_ha()
438 mutex_lock(&ha->drain_mutex); in sas_suspend_ha()
440 mutex_unlock(&ha->drain_mutex); in sas_suspend_ha()
444 static void sas_phy_release(struct sas_phy *phy) in sas_phy_release() argument
446 kfree(phy->hostdata); in sas_phy_release()
447 phy->hostdata = NULL; in sas_phy_release()
452 struct sas_phy_data *d = container_of(work, typeof(*d), reset_work.work); in phy_reset_work() local
454 d->reset_result = transport_sas_phy_reset(d->phy, d->hard_reset); in phy_reset_work()
459 struct sas_phy_data *d = container_of(work, typeof(*d), enable_work.work); in phy_enable_work() local
461 d->enable_result = sas_phy_enable(d->phy, d->enable); in phy_enable_work()
464 static int sas_phy_setup(struct sas_phy *phy) in sas_phy_setup() argument
466 struct sas_phy_data *d = kzalloc(sizeof(*d), GFP_KERNEL); in sas_phy_setup() local
468 if (!d) in sas_phy_setup()
469 return -ENOMEM; in sas_phy_setup()
471 mutex_init(&d->event_lock); in sas_phy_setup()
472 INIT_SAS_WORK(&d->reset_work, phy_reset_work); in sas_phy_setup()
473 INIT_SAS_WORK(&d->enable_work, phy_enable_work); in sas_phy_setup()
474 d->phy = phy; in sas_phy_setup()
475 phy->hostdata = d; in sas_phy_setup()
480 static int queue_phy_reset(struct sas_phy *phy, int hard_reset) in queue_phy_reset() argument
482 struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); in queue_phy_reset()
484 struct sas_phy_data *d = phy->hostdata; in queue_phy_reset() local
487 if (!d) in queue_phy_reset()
488 return -ENOMEM; in queue_phy_reset()
490 /* libsas workqueue coordinates ata-eh reset with discovery */ in queue_phy_reset()
491 mutex_lock(&d->event_lock); in queue_phy_reset()
492 d->reset_result = 0; in queue_phy_reset()
493 d->hard_reset = hard_reset; in queue_phy_reset()
495 spin_lock_irq(&ha->lock); in queue_phy_reset()
496 sas_queue_work(ha, &d->reset_work); in queue_phy_reset()
497 spin_unlock_irq(&ha->lock); in queue_phy_reset()
501 rc = d->reset_result; in queue_phy_reset()
502 mutex_unlock(&d->event_lock); in queue_phy_reset()
507 static int queue_phy_enable(struct sas_phy *phy, int enable) in queue_phy_enable() argument
509 struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); in queue_phy_enable()
511 struct sas_phy_data *d = phy->hostdata; in queue_phy_enable() local
514 if (!d) in queue_phy_enable()
515 return -ENOMEM; in queue_phy_enable()
517 /* libsas workqueue coordinates ata-eh reset with discovery */ in queue_phy_enable()
518 mutex_lock(&d->event_lock); in queue_phy_enable()
519 d->enable_result = 0; in queue_phy_enable()
520 d->enable = enable; in queue_phy_enable()
522 spin_lock_irq(&ha->lock); in queue_phy_enable()
523 sas_queue_work(ha, &d->enable_work); in queue_phy_enable()
524 spin_unlock_irq(&ha->lock); in queue_phy_enable()
528 rc = d->enable_result; in queue_phy_enable()
529 mutex_unlock(&d->event_lock); in queue_phy_enable()
550 return scnprintf(buf, PAGE_SIZE, "%u\n", sha->event_thres); in phy_event_threshold_show()
560 sha->event_thres = simple_strtol(buf, NULL, 10); in phy_event_threshold_store()
563 if (sha->event_thres < 32) in phy_event_threshold_store()
564 sha->event_thres = 32; in phy_event_threshold_store()
585 i->dft = dft; in sas_domain_attach_transport()
586 stt->create_work_queue = 1; in sas_domain_attach_transport()
587 stt->eh_strategy_handler = sas_scsi_recover_host; in sas_domain_attach_transport()
594 struct asd_sas_event *sas_alloc_event(struct asd_sas_phy *phy) in sas_alloc_event() argument
598 struct sas_ha_struct *sas_ha = phy->ha; in sas_alloc_event()
600 to_sas_internal(sas_ha->core.shost->transportt); in sas_alloc_event()
606 atomic_inc(&phy->event_nr); in sas_alloc_event()
608 if (atomic_read(&phy->event_nr) > phy->ha->event_thres) { in sas_alloc_event()
609 if (i->dft->lldd_control_phy) { in sas_alloc_event()
610 if (cmpxchg(&phy->in_shutdown, 0, 1) == 0) { in sas_alloc_event()
611 pr_notice("The phy%d bursting events, shut it down.\n", in sas_alloc_event()
612 phy->id); in sas_alloc_event()
613 sas_notify_phy_event(phy, PHYE_SHUTDOWN); in sas_alloc_event()
616 /* Do not support PHY control, stop allocating events */ in sas_alloc_event()
617 WARN_ONCE(1, "PHY control not supported.\n"); in sas_alloc_event()
619 atomic_dec(&phy->event_nr); in sas_alloc_event()
629 struct asd_sas_phy *phy = event->phy; in sas_free_event() local
632 atomic_dec(&phy->event_nr); in sas_free_event()
635 /* ---------- SAS Class register/unregister ---------- */
651 return -ENOMEM; in sas_class_init()