0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "sas_internal.h"
0010 #include <scsi/scsi_host.h>
0011 #include <scsi/scsi_transport.h>
0012 #include <scsi/scsi_transport_sas.h>
0013 #include "scsi_sas_internal.h"
0014
0015
0016
0017 static void sas_phye_loss_of_signal(struct work_struct *work)
0018 {
0019 struct asd_sas_event *ev = to_asd_sas_event(work);
0020 struct asd_sas_phy *phy = ev->phy;
0021
0022 phy->error = 0;
0023 sas_deform_port(phy, 1);
0024 }
0025
0026 static void sas_phye_oob_done(struct work_struct *work)
0027 {
0028 struct asd_sas_event *ev = to_asd_sas_event(work);
0029 struct asd_sas_phy *phy = ev->phy;
0030
0031 phy->error = 0;
0032 }
0033
0034 static void sas_phye_oob_error(struct work_struct *work)
0035 {
0036 struct asd_sas_event *ev = to_asd_sas_event(work);
0037 struct asd_sas_phy *phy = ev->phy;
0038 struct sas_ha_struct *sas_ha = phy->ha;
0039 struct asd_sas_port *port = phy->port;
0040 struct sas_internal *i =
0041 to_sas_internal(sas_ha->core.shost->transportt);
0042
0043 sas_deform_port(phy, 1);
0044
0045 if (!port && phy->enabled && i->dft->lldd_control_phy) {
0046 phy->error++;
0047 switch (phy->error) {
0048 case 1:
0049 case 2:
0050 i->dft->lldd_control_phy(phy, PHY_FUNC_HARD_RESET,
0051 NULL);
0052 break;
0053 case 3:
0054 default:
0055 phy->error = 0;
0056 phy->enabled = 0;
0057 i->dft->lldd_control_phy(phy, PHY_FUNC_DISABLE, NULL);
0058 break;
0059 }
0060 }
0061 }
0062
0063 static void sas_phye_spinup_hold(struct work_struct *work)
0064 {
0065 struct asd_sas_event *ev = to_asd_sas_event(work);
0066 struct asd_sas_phy *phy = ev->phy;
0067 struct sas_ha_struct *sas_ha = phy->ha;
0068 struct sas_internal *i =
0069 to_sas_internal(sas_ha->core.shost->transportt);
0070
0071 phy->error = 0;
0072 i->dft->lldd_control_phy(phy, PHY_FUNC_RELEASE_SPINUP_HOLD, NULL);
0073 }
0074
0075 static void sas_phye_resume_timeout(struct work_struct *work)
0076 {
0077 struct asd_sas_event *ev = to_asd_sas_event(work);
0078 struct asd_sas_phy *phy = ev->phy;
0079
0080
0081 if (!phy->suspended) {
0082 dev_info(&phy->phy->dev, "resume timeout cancelled\n");
0083 return;
0084 }
0085
0086 phy->error = 0;
0087 phy->suspended = 0;
0088 sas_deform_port(phy, 1);
0089 }
0090
0091
0092 static void sas_phye_shutdown(struct work_struct *work)
0093 {
0094 struct asd_sas_event *ev = to_asd_sas_event(work);
0095 struct asd_sas_phy *phy = ev->phy;
0096 struct sas_ha_struct *sas_ha = phy->ha;
0097 struct sas_internal *i =
0098 to_sas_internal(sas_ha->core.shost->transportt);
0099
0100 if (phy->enabled) {
0101 int ret;
0102
0103 phy->error = 0;
0104 phy->enabled = 0;
0105 ret = i->dft->lldd_control_phy(phy, PHY_FUNC_DISABLE, NULL);
0106 if (ret)
0107 pr_notice("lldd disable phy%d returned %d\n", phy->id,
0108 ret);
0109 } else
0110 pr_notice("phy%d is not enabled, cannot shutdown\n", phy->id);
0111 phy->in_shutdown = 0;
0112 }
0113
0114
0115
0116 int sas_register_phys(struct sas_ha_struct *sas_ha)
0117 {
0118 int i;
0119
0120
0121 for (i = 0; i < sas_ha->num_phys; i++) {
0122 struct asd_sas_phy *phy = sas_ha->sas_phy[i];
0123
0124 phy->error = 0;
0125 atomic_set(&phy->event_nr, 0);
0126 INIT_LIST_HEAD(&phy->port_phy_el);
0127
0128 phy->port = NULL;
0129 phy->ha = sas_ha;
0130 spin_lock_init(&phy->frame_rcvd_lock);
0131 spin_lock_init(&phy->sas_prim_lock);
0132 phy->frame_rcvd_size = 0;
0133
0134 phy->phy = sas_phy_alloc(&sas_ha->core.shost->shost_gendev, i);
0135 if (!phy->phy)
0136 return -ENOMEM;
0137
0138 phy->phy->identify.initiator_port_protocols =
0139 phy->iproto;
0140 phy->phy->identify.target_port_protocols = phy->tproto;
0141 phy->phy->identify.sas_address = SAS_ADDR(sas_ha->sas_addr);
0142 phy->phy->identify.phy_identifier = i;
0143 phy->phy->minimum_linkrate_hw = SAS_LINK_RATE_UNKNOWN;
0144 phy->phy->maximum_linkrate_hw = SAS_LINK_RATE_UNKNOWN;
0145 phy->phy->minimum_linkrate = SAS_LINK_RATE_UNKNOWN;
0146 phy->phy->maximum_linkrate = SAS_LINK_RATE_UNKNOWN;
0147 phy->phy->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN;
0148
0149 sas_phy_add(phy->phy);
0150 }
0151
0152 return 0;
0153 }
0154
0155 const work_func_t sas_phy_event_fns[PHY_NUM_EVENTS] = {
0156 [PHYE_LOSS_OF_SIGNAL] = sas_phye_loss_of_signal,
0157 [PHYE_OOB_DONE] = sas_phye_oob_done,
0158 [PHYE_OOB_ERROR] = sas_phye_oob_error,
0159 [PHYE_SPINUP_HOLD] = sas_phye_spinup_hold,
0160 [PHYE_RESUME_TIMEOUT] = sas_phye_resume_timeout,
0161 [PHYE_SHUTDOWN] = sas_phye_shutdown,
0162 };