diff options
Diffstat (limited to 'drivers/scsi/libsas/sas_init.c')
-rw-r--r-- | drivers/scsi/libsas/sas_init.c | 52 |
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 | ||
128 | int sas_unregister_ha(struct sas_ha_struct *sas_ha) | 131 | int 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 | ||
162 | int 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 | |||
149 | int sas_phy_reset(struct sas_phy *phy, int hard_reset) | 192 | int 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 | ||
175 | static int sas_set_phy_speed(struct sas_phy *phy, | 218 | int 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 | ||
214 | static struct sas_function_template sft = { | 257 | static 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, |