aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/libsas/sas_init.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/libsas/sas_init.c')
-rw-r--r--drivers/scsi/libsas/sas_init.c52
1 files changed, 48 insertions, 4 deletions
diff --git a/drivers/scsi/libsas/sas_init.c b/drivers/scsi/libsas/sas_init.c
index 2f0c07fc3f48..965698c8b7bf 100644
--- a/drivers/scsi/libsas/sas_init.c
+++ b/drivers/scsi/libsas/sas_init.c
@@ -87,6 +87,9 @@ int sas_register_ha(struct sas_ha_struct *sas_ha)
87 else if (sas_ha->lldd_queue_size == -1) 87 else if (sas_ha->lldd_queue_size == -1)
88 sas_ha->lldd_queue_size = 128; /* Sanity */ 88 sas_ha->lldd_queue_size = 128; /* Sanity */
89 89
90 sas_ha->state = SAS_HA_REGISTERED;
91 spin_lock_init(&sas_ha->state_lock);
92
90 error = sas_register_phys(sas_ha); 93 error = sas_register_phys(sas_ha);
91 if (error) { 94 if (error) {
92 printk(KERN_NOTICE "couldn't register sas phys:%d\n", error); 95 printk(KERN_NOTICE "couldn't register sas phys:%d\n", error);
@@ -127,12 +130,22 @@ Undo_phys:
127 130
128int sas_unregister_ha(struct sas_ha_struct *sas_ha) 131int sas_unregister_ha(struct sas_ha_struct *sas_ha)
129{ 132{
133 unsigned long flags;
134
135 /* Set the state to unregistered to avoid further
136 * events to be queued */
137 spin_lock_irqsave(&sas_ha->state_lock, flags);
138 sas_ha->state = SAS_HA_UNREGISTERED;
139 spin_unlock_irqrestore(&sas_ha->state_lock, flags);
140 scsi_flush_work(sas_ha->core.shost);
141
142 sas_unregister_ports(sas_ha);
143
130 if (sas_ha->lldd_max_execute_num > 1) { 144 if (sas_ha->lldd_max_execute_num > 1) {
131 sas_shutdown_queue(sas_ha); 145 sas_shutdown_queue(sas_ha);
146 sas_ha->lldd_max_execute_num = 1;
132 } 147 }
133 148
134 sas_unregister_ports(sas_ha);
135
136 return 0; 149 return 0;
137} 150}
138 151
@@ -146,6 +159,36 @@ static int sas_get_linkerrors(struct sas_phy *phy)
146 return sas_smp_get_phy_events(phy); 159 return sas_smp_get_phy_events(phy);
147} 160}
148 161
162int sas_phy_enable(struct sas_phy *phy, int enable)
163{
164 int ret;
165 enum phy_func command;
166
167 if (enable)
168 command = PHY_FUNC_LINK_RESET;
169 else
170 command = PHY_FUNC_DISABLE;
171
172 if (scsi_is_sas_phy_local(phy)) {
173 struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
174 struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(shost);
175 struct asd_sas_phy *asd_phy = sas_ha->sas_phy[phy->number];
176 struct sas_internal *i =
177 to_sas_internal(sas_ha->core.shost->transportt);
178
179 if (!enable) {
180 sas_phy_disconnected(asd_phy);
181 sas_ha->notify_phy_event(asd_phy, PHYE_LOSS_OF_SIGNAL);
182 }
183 ret = i->dft->lldd_control_phy(asd_phy, command, NULL);
184 } else {
185 struct sas_rphy *rphy = dev_to_rphy(phy->dev.parent);
186 struct domain_device *ddev = sas_find_dev_by_rphy(rphy);
187 ret = sas_smp_phy_control(ddev, phy->number, command, NULL);
188 }
189 return ret;
190}
191
149int sas_phy_reset(struct sas_phy *phy, int hard_reset) 192int sas_phy_reset(struct sas_phy *phy, int hard_reset)
150{ 193{
151 int ret; 194 int ret;
@@ -172,8 +215,8 @@ int sas_phy_reset(struct sas_phy *phy, int hard_reset)
172 return ret; 215 return ret;
173} 216}
174 217
175static int sas_set_phy_speed(struct sas_phy *phy, 218int sas_set_phy_speed(struct sas_phy *phy,
176 struct sas_phy_linkrates *rates) 219 struct sas_phy_linkrates *rates)
177{ 220{
178 int ret; 221 int ret;
179 222
@@ -212,6 +255,7 @@ static int sas_set_phy_speed(struct sas_phy *phy,
212} 255}
213 256
214static struct sas_function_template sft = { 257static struct sas_function_template sft = {
258 .phy_enable = sas_phy_enable,
215 .phy_reset = sas_phy_reset, 259 .phy_reset = sas_phy_reset,
216 .set_phy_speed = sas_set_phy_speed, 260 .set_phy_speed = sas_set_phy_speed,
217 .get_linkerrors = sas_get_linkerrors, 261 .get_linkerrors = sas_get_linkerrors,