[SCSI] mpt fusion: SAS topology scan changes, expander events
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / message / fusion / mptsas.c
CommitLineData
0c33b27d
CH
1/*
2 * linux/drivers/message/fusion/mptsas.c
f36789e2
PS
3 * For use with LSI PCI chip/adapter(s)
4 * running LSI Fusion MPT (Message Passing Technology) firmware.
0c33b27d 5 *
cddc0ab7 6 * Copyright (c) 1999-2008 LSI Corporation
16d20101 7 * (mailto:DL-MPTFusionLinux@lsi.com)
0c33b27d
CH
8 */
9/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
10/*
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; version 2 of the License.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 NO WARRANTY
21 THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
22 CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
23 LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
24 MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
25 solely responsible for determining the appropriateness of using and
26 distributing the Program and assumes all risks associated with its
27 exercise of rights under this Agreement, including but not limited to
28 the risks and costs of program errors, damage to or loss of data,
29 programs or equipment, and unavailability or interruption of operations.
30
31 DISCLAIMER OF LIABILITY
32 NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
33 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34 DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
35 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
36 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
37 USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
38 HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
39
40 You should have received a copy of the GNU General Public License
41 along with this program; if not, write to the Free Software
42 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
43*/
44/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
45
46#include <linux/module.h>
47#include <linux/kernel.h>
48#include <linux/init.h>
49#include <linux/errno.h>
cd354f1a 50#include <linux/jiffies.h>
0c33b27d 51#include <linux/workqueue.h>
547f9a21 52#include <linux/delay.h> /* for mdelay */
0c33b27d 53
547f9a21 54#include <scsi/scsi.h>
0c33b27d
CH
55#include <scsi/scsi_cmnd.h>
56#include <scsi/scsi_device.h>
57#include <scsi/scsi_host.h>
58#include <scsi/scsi_transport_sas.h>
547f9a21 59#include <scsi/scsi_dbg.h>
0c33b27d
CH
60
61#include "mptbase.h"
62#include "mptscsih.h"
56af97ae 63#include "mptsas.h"
0c33b27d
CH
64
65
66#define my_NAME "Fusion MPT SAS Host driver"
67#define my_VERSION MPT_LINUX_VERSION_COMMON
68#define MYNAM "mptsas"
69
e8bf3941
JB
70/*
71 * Reserved channel for integrated raid
72 */
73#define MPTSAS_RAID_CHANNEL 1
74
0c33b27d
CH
75MODULE_AUTHOR(MODULEAUTHOR);
76MODULE_DESCRIPTION(my_NAME);
77MODULE_LICENSE("GPL");
9f4203b3 78MODULE_VERSION(my_VERSION);
0c33b27d 79
0c33b27d
CH
80static int mpt_pt_clear;
81module_param(mpt_pt_clear, int, 0);
82MODULE_PARM_DESC(mpt_pt_clear,
ba856d32 83 " Clear persistency table: enable=1 "
0c33b27d
CH
84 "(default=MPTSCSIH_PT_CLEAR=0)");
85
793955f5
EM
86/* scsi-mid layer global parmeter is max_report_luns, which is 511 */
87#define MPTSAS_MAX_LUN (16895)
88static int max_lun = MPTSAS_MAX_LUN;
89module_param(max_lun, int, 0);
90MODULE_PARM_DESC(max_lun, " max lun, default=16895 ");
91
f606f571
PS
92static u8 mptsasDoneCtx = MPT_MAX_PROTOCOL_DRIVERS;
93static u8 mptsasTaskCtx = MPT_MAX_PROTOCOL_DRIVERS;
94static u8 mptsasInternalCtx = MPT_MAX_PROTOCOL_DRIVERS; /* Used only for internal commands */
95static u8 mptsasMgmtCtx = MPT_MAX_PROTOCOL_DRIVERS;
e7deff33 96static u8 mptsasDeviceResetCtx = MPT_MAX_PROTOCOL_DRIVERS;
0c33b27d 97
3eb0822c
KD
98static void mptsas_firmware_event_work(struct work_struct *work);
99static void mptsas_send_sas_event(struct fw_event_work *fw_event);
100static void mptsas_send_raid_event(struct fw_event_work *fw_event);
101static void mptsas_send_ir2_event(struct fw_event_work *fw_event);
102static void mptsas_parse_device_info(struct sas_identify *identify,
103 struct mptsas_devinfo *device_info);
104static inline void mptsas_set_rphy(MPT_ADAPTER *ioc,
105 struct mptsas_phyinfo *phy_info, struct sas_rphy *rphy);
106static struct mptsas_phyinfo *mptsas_find_phyinfo_by_sas_address
107 (MPT_ADAPTER *ioc, u64 sas_address);
108static int mptsas_sas_device_pg0(MPT_ADAPTER *ioc,
109 struct mptsas_devinfo *device_info, u32 form, u32 form_specific);
110static int mptsas_sas_enclosure_pg0(MPT_ADAPTER *ioc,
111 struct mptsas_enclosure *enclosure, u32 form, u32 form_specific);
112static int mptsas_add_end_device(MPT_ADAPTER *ioc,
113 struct mptsas_phyinfo *phy_info);
114static void mptsas_del_end_device(MPT_ADAPTER *ioc,
115 struct mptsas_phyinfo *phy_info);
f9c34022
KD
116static void mptsas_send_link_status_event(struct fw_event_work *fw_event);
117static struct mptsas_portinfo *mptsas_find_portinfo_by_sas_address
118 (MPT_ADAPTER *ioc, u64 sas_address);
119static void mptsas_expander_delete(MPT_ADAPTER *ioc,
120 struct mptsas_portinfo *port_info, u8 force);
121static void mptsas_send_expander_event(struct fw_event_work *fw_event);
0c33b27d 122
d6ecdd63
PS
123static void mptsas_print_phy_data(MPT_ADAPTER *ioc,
124 MPI_SAS_IO_UNIT0_PHY_DATA *phy_data)
125{
29dd3609
EM
126 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
127 "---- IO UNIT PAGE 0 ------------\n", ioc->name));
128 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Handle=0x%X\n",
129 ioc->name, le16_to_cpu(phy_data->AttachedDeviceHandle)));
130 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Controller Handle=0x%X\n",
131 ioc->name, le16_to_cpu(phy_data->ControllerDevHandle)));
132 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Port=0x%X\n",
133 ioc->name, phy_data->Port));
134 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Port Flags=0x%X\n",
135 ioc->name, phy_data->PortFlags));
136 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "PHY Flags=0x%X\n",
137 ioc->name, phy_data->PhyFlags));
138 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Negotiated Link Rate=0x%X\n",
139 ioc->name, phy_data->NegotiatedLinkRate));
140 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
141 "Controller PHY Device Info=0x%X\n", ioc->name,
142 le32_to_cpu(phy_data->ControllerPhyDeviceInfo)));
143 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "DiscoveryStatus=0x%X\n\n",
144 ioc->name, le32_to_cpu(phy_data->DiscoveryStatus)));
b5141128
CH
145}
146
d6ecdd63 147static void mptsas_print_phy_pg0(MPT_ADAPTER *ioc, SasPhyPage0_t *pg0)
b5141128
CH
148{
149 __le64 sas_address;
150
151 memcpy(&sas_address, &pg0->SASAddress, sizeof(__le64));
152
29dd3609
EM
153 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
154 "---- SAS PHY PAGE 0 ------------\n", ioc->name));
155 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
156 "Attached Device Handle=0x%X\n", ioc->name,
157 le16_to_cpu(pg0->AttachedDevHandle)));
158 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SAS Address=0x%llX\n",
159 ioc->name, (unsigned long long)le64_to_cpu(sas_address)));
160 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
161 "Attached PHY Identifier=0x%X\n", ioc->name,
162 pg0->AttachedPhyIdentifier));
163 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Attached Device Info=0x%X\n",
164 ioc->name, le32_to_cpu(pg0->AttachedDeviceInfo)));
165 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Programmed Link Rate=0x%X\n",
166 ioc->name, pg0->ProgrammedLinkRate));
167 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Change Count=0x%X\n",
168 ioc->name, pg0->ChangeCount));
169 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "PHY Info=0x%X\n\n",
170 ioc->name, le32_to_cpu(pg0->PhyInfo)));
b5141128
CH
171}
172
d6ecdd63 173static void mptsas_print_phy_pg1(MPT_ADAPTER *ioc, SasPhyPage1_t *pg1)
b5141128 174{
29dd3609
EM
175 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
176 "---- SAS PHY PAGE 1 ------------\n", ioc->name));
177 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Invalid Dword Count=0x%x\n",
178 ioc->name, pg1->InvalidDwordCount));
179 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
180 "Running Disparity Error Count=0x%x\n", ioc->name,
181 pg1->RunningDisparityErrorCount));
182 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
183 "Loss Dword Synch Count=0x%x\n", ioc->name,
184 pg1->LossDwordSynchCount));
185 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
186 "PHY Reset Problem Count=0x%x\n\n", ioc->name,
187 pg1->PhyResetProblemCount));
b5141128
CH
188}
189
d6ecdd63 190static void mptsas_print_device_pg0(MPT_ADAPTER *ioc, SasDevicePage0_t *pg0)
b5141128
CH
191{
192 __le64 sas_address;
193
194 memcpy(&sas_address, &pg0->SASAddress, sizeof(__le64));
195
29dd3609
EM
196 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
197 "---- SAS DEVICE PAGE 0 ---------\n", ioc->name));
198 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Handle=0x%X\n",
199 ioc->name, le16_to_cpu(pg0->DevHandle)));
200 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Parent Handle=0x%X\n",
201 ioc->name, le16_to_cpu(pg0->ParentDevHandle)));
202 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Enclosure Handle=0x%X\n",
203 ioc->name, le16_to_cpu(pg0->EnclosureHandle)));
204 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Slot=0x%X\n",
205 ioc->name, le16_to_cpu(pg0->Slot)));
206 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SAS Address=0x%llX\n",
207 ioc->name, (unsigned long long)le64_to_cpu(sas_address)));
208 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Target ID=0x%X\n",
209 ioc->name, pg0->TargetID));
210 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Bus=0x%X\n",
211 ioc->name, pg0->Bus));
212 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Parent Phy Num=0x%X\n",
213 ioc->name, pg0->PhyNum));
214 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Access Status=0x%X\n",
215 ioc->name, le16_to_cpu(pg0->AccessStatus)));
216 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Device Info=0x%X\n",
217 ioc->name, le32_to_cpu(pg0->DeviceInfo)));
218 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Flags=0x%X\n",
219 ioc->name, le16_to_cpu(pg0->Flags)));
220 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Physical Port=0x%X\n\n",
221 ioc->name, pg0->PhysicalPort));
b5141128
CH
222}
223
d6ecdd63
PS
224static void mptsas_print_expander_pg1(MPT_ADAPTER *ioc, SasExpanderPage1_t *pg1)
225{
29dd3609
EM
226 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
227 "---- SAS EXPANDER PAGE 1 ------------\n", ioc->name));
228 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Physical Port=0x%X\n",
229 ioc->name, pg1->PhysicalPort));
230 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "PHY Identifier=0x%X\n",
231 ioc->name, pg1->PhyIdentifier));
232 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Negotiated Link Rate=0x%X\n",
233 ioc->name, pg1->NegotiatedLinkRate));
234 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Programmed Link Rate=0x%X\n",
235 ioc->name, pg1->ProgrammedLinkRate));
236 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Hardware Link Rate=0x%X\n",
237 ioc->name, pg1->HwLinkRate));
238 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Owner Device Handle=0x%X\n",
239 ioc->name, le16_to_cpu(pg1->OwnerDevHandle)));
240 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
241 "Attached Device Handle=0x%X\n\n", ioc->name,
242 le16_to_cpu(pg1->AttachedDevHandle)));
b5141128 243}
b5141128 244
3eb0822c
KD
245/* inhibit sas firmware event handling */
246static void
247mptsas_fw_event_off(MPT_ADAPTER *ioc)
248{
249 unsigned long flags;
250
251 spin_lock_irqsave(&ioc->fw_event_lock, flags);
252 ioc->fw_events_off = 1;
253 ioc->sas_discovery_quiesce_io = 0;
254 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
255
256}
257
258/* enable sas firmware event handling */
259static void
260mptsas_fw_event_on(MPT_ADAPTER *ioc)
261{
262 unsigned long flags;
263
264 spin_lock_irqsave(&ioc->fw_event_lock, flags);
265 ioc->fw_events_off = 0;
266 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
267}
268
269/* queue a sas firmware event */
270static void
271mptsas_add_fw_event(MPT_ADAPTER *ioc, struct fw_event_work *fw_event,
272 unsigned long delay)
273{
274 unsigned long flags;
275
276 spin_lock_irqsave(&ioc->fw_event_lock, flags);
277 list_add_tail(&fw_event->list, &ioc->fw_event_list);
278 INIT_DELAYED_WORK(&fw_event->work, mptsas_firmware_event_work);
279 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: add (fw_event=0x%p)\n",
280 ioc->name, __func__, fw_event));
281 queue_delayed_work(ioc->fw_event_q, &fw_event->work,
282 delay);
283 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
284}
285
286/* free memory assoicated to a sas firmware event */
287static void
288mptsas_free_fw_event(MPT_ADAPTER *ioc, struct fw_event_work *fw_event)
289{
290 unsigned long flags;
291
292 spin_lock_irqsave(&ioc->fw_event_lock, flags);
293 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: kfree (fw_event=0x%p)\n",
294 ioc->name, __func__, fw_event));
295 list_del(&fw_event->list);
296 kfree(fw_event);
297 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
298}
299
300/* walk the firmware event queue, and either stop or wait for
301 * outstanding events to complete */
302static void
303mptsas_cleanup_fw_event_q(MPT_ADAPTER *ioc)
304{
305 struct fw_event_work *fw_event, *next;
306 struct mptsas_target_reset_event *target_reset_list, *n;
307 u8 flush_q;
308 MPT_SCSI_HOST *hd = shost_priv(ioc->sh);
309
310 /* flush the target_reset_list */
311 if (!list_empty(&hd->target_reset_list)) {
312 list_for_each_entry_safe(target_reset_list, n,
313 &hd->target_reset_list, list) {
314 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
315 "%s: removing target reset for id=%d\n",
316 ioc->name, __func__,
317 target_reset_list->sas_event_data.TargetID));
318 list_del(&target_reset_list->list);
319 kfree(target_reset_list);
320 }
321 }
322
323 if (list_empty(&ioc->fw_event_list) ||
324 !ioc->fw_event_q || in_interrupt())
325 return;
326
327 flush_q = 0;
328 list_for_each_entry_safe(fw_event, next, &ioc->fw_event_list, list) {
329 if (cancel_delayed_work(&fw_event->work))
330 mptsas_free_fw_event(ioc, fw_event);
331 else
332 flush_q = 1;
333 }
334 if (flush_q)
335 flush_workqueue(ioc->fw_event_q);
336}
337
338
e3094447
CH
339static inline MPT_ADAPTER *phy_to_ioc(struct sas_phy *phy)
340{
341 struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
342 return ((MPT_SCSI_HOST *)shost->hostdata)->ioc;
343}
344
345static inline MPT_ADAPTER *rphy_to_ioc(struct sas_rphy *rphy)
346{
347 struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent);
348 return ((MPT_SCSI_HOST *)shost->hostdata)->ioc;
349}
350
e6b2d76a
ME
351/*
352 * mptsas_find_portinfo_by_handle
353 *
354 * This function should be called with the sas_topology_mutex already held
355 */
356static struct mptsas_portinfo *
357mptsas_find_portinfo_by_handle(MPT_ADAPTER *ioc, u16 handle)
358{
359 struct mptsas_portinfo *port_info, *rc=NULL;
360 int i;
361
362 list_for_each_entry(port_info, &ioc->sas_topology, list)
363 for (i = 0; i < port_info->num_phys; i++)
364 if (port_info->phy_info[i].identify.handle == handle) {
365 rc = port_info;
366 goto out;
367 }
368 out:
369 return rc;
370}
371
f9c34022
KD
372/**
373 * mptsas_find_portinfo_by_sas_address -
374 * @ioc: Pointer to MPT_ADAPTER structure
375 * @handle:
376 *
377 * This function should be called with the sas_topology_mutex already held
378 *
379 **/
380static struct mptsas_portinfo *
381mptsas_find_portinfo_by_sas_address(MPT_ADAPTER *ioc, u64 sas_address)
382{
383 struct mptsas_portinfo *port_info, *rc = NULL;
384 int i;
385
386 if (sas_address >= ioc->hba_port_sas_addr &&
387 sas_address < (ioc->hba_port_sas_addr +
388 ioc->hba_port_num_phy))
389 return ioc->hba_port_info;
390
391 mutex_lock(&ioc->sas_topology_mutex);
392 list_for_each_entry(port_info, &ioc->sas_topology, list)
393 for (i = 0; i < port_info->num_phys; i++)
394 if (port_info->phy_info[i].identify.sas_address ==
395 sas_address) {
396 rc = port_info;
397 goto out;
398 }
399 out:
400 mutex_unlock(&ioc->sas_topology_mutex);
401 return rc;
402}
403
bd23e94c
ME
404/*
405 * Returns true if there is a scsi end device
406 */
407static inline int
408mptsas_is_end_device(struct mptsas_devinfo * attached)
409{
547f9a21 410 if ((attached->sas_address) &&
bd23e94c
ME
411 (attached->device_info &
412 MPI_SAS_DEVICE_INFO_END_DEVICE) &&
413 ((attached->device_info &
414 MPI_SAS_DEVICE_INFO_SSP_TARGET) |
415 (attached->device_info &
416 MPI_SAS_DEVICE_INFO_STP_TARGET) |
417 (attached->device_info &
418 MPI_SAS_DEVICE_INFO_SATA_DEVICE)))
419 return 1;
420 else
421 return 0;
422}
423
547f9a21 424/* no mutex */
376ac830 425static void
d6ecdd63 426mptsas_port_delete(MPT_ADAPTER *ioc, struct mptsas_portinfo_details * port_details)
547f9a21
EM
427{
428 struct mptsas_portinfo *port_info;
429 struct mptsas_phyinfo *phy_info;
430 u8 i;
431
432 if (!port_details)
433 return;
434
435 port_info = port_details->port_info;
436 phy_info = port_info->phy_info;
437
29dd3609 438 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: [%p]: num_phys=%02d "
cadbd4a5 439 "bitmask=0x%016llX\n", ioc->name, __func__, port_details,
f99be43b
EM
440 port_details->num_phys, (unsigned long long)
441 port_details->phy_bitmask));
547f9a21
EM
442
443 for (i = 0; i < port_info->num_phys; i++, phy_info++) {
444 if(phy_info->port_details != port_details)
445 continue;
446 memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo));
3eb0822c 447 mptsas_set_rphy(ioc, phy_info, NULL);
547f9a21
EM
448 phy_info->port_details = NULL;
449 }
450 kfree(port_details);
451}
452
453static inline struct sas_rphy *
454mptsas_get_rphy(struct mptsas_phyinfo *phy_info)
455{
456 if (phy_info->port_details)
457 return phy_info->port_details->rphy;
458 else
459 return NULL;
460}
461
462static inline void
d6ecdd63 463mptsas_set_rphy(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info, struct sas_rphy *rphy)
547f9a21
EM
464{
465 if (phy_info->port_details) {
466 phy_info->port_details->rphy = rphy;
29dd3609
EM
467 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "sas_rphy_add: rphy=%p\n",
468 ioc->name, rphy));
547f9a21
EM
469 }
470
547f9a21 471 if (rphy) {
c51d0bea
EM
472 dsaswideprintk(ioc, dev_printk(KERN_DEBUG,
473 &rphy->dev, MYIOC_s_FMT "add:", ioc->name));
29dd3609
EM
474 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "rphy=%p release=%p\n",
475 ioc->name, rphy, rphy->dev.release));
547f9a21 476 }
547f9a21
EM
477}
478
479static inline struct sas_port *
480mptsas_get_port(struct mptsas_phyinfo *phy_info)
481{
482 if (phy_info->port_details)
483 return phy_info->port_details->port;
484 else
485 return NULL;
486}
487
488static inline void
d6ecdd63 489mptsas_set_port(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info, struct sas_port *port)
547f9a21
EM
490{
491 if (phy_info->port_details)
492 phy_info->port_details->port = port;
493
547f9a21 494 if (port) {
c51d0bea
EM
495 dsaswideprintk(ioc, dev_printk(KERN_DEBUG,
496 &port->dev, MYIOC_s_FMT "add:", ioc->name));
29dd3609
EM
497 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "port=%p release=%p\n",
498 ioc->name, port, port->dev.release));
547f9a21 499 }
547f9a21
EM
500}
501
502static inline struct scsi_target *
503mptsas_get_starget(struct mptsas_phyinfo *phy_info)
504{
505 if (phy_info->port_details)
506 return phy_info->port_details->starget;
507 else
508 return NULL;
509}
510
511static inline void
512mptsas_set_starget(struct mptsas_phyinfo *phy_info, struct scsi_target *
513starget)
514{
515 if (phy_info->port_details)
516 phy_info->port_details->starget = starget;
517}
518
3eb0822c
KD
519/**
520 * mptsas_add_device_component -
521 * @ioc: Pointer to MPT_ADAPTER structure
522 * @channel: fw mapped id's
523 * @id:
524 * @sas_address:
525 * @device_info:
526 *
527 **/
528static void
529mptsas_add_device_component(MPT_ADAPTER *ioc, u8 channel, u8 id,
530 u64 sas_address, u32 device_info, u16 slot, u64 enclosure_logical_id)
531{
532 struct mptsas_device_info *sas_info, *next;
533 struct scsi_device *sdev;
534 struct scsi_target *starget;
535 struct sas_rphy *rphy;
536
537 /*
538 * Delete all matching devices out of the list
539 */
540 mutex_lock(&ioc->sas_device_info_mutex);
541 list_for_each_entry_safe(sas_info, next, &ioc->sas_device_info_list,
542 list) {
543 if ((sas_info->sas_address == sas_address ||
544 (sas_info->fw.channel == channel &&
545 sas_info->fw.id == id))) {
546 list_del(&sas_info->list);
547 kfree(sas_info);
548 }
549 }
550
551 sas_info = kzalloc(sizeof(struct mptsas_device_info), GFP_KERNEL);
552 if (!sas_info)
553 goto out;
554
555 /*
556 * Set Firmware mapping
557 */
558 sas_info->fw.id = id;
559 sas_info->fw.channel = channel;
560
561 sas_info->sas_address = sas_address;
562 sas_info->device_info = device_info;
563 sas_info->slot = slot;
564 sas_info->enclosure_logical_id = enclosure_logical_id;
565 INIT_LIST_HEAD(&sas_info->list);
566 list_add_tail(&sas_info->list, &ioc->sas_device_info_list);
567
568 /*
569 * Set OS mapping
570 */
571 shost_for_each_device(sdev, ioc->sh) {
572 starget = scsi_target(sdev);
573 rphy = dev_to_rphy(starget->dev.parent);
574 if (rphy->identify.sas_address == sas_address) {
575 sas_info->os.id = starget->id;
576 sas_info->os.channel = starget->channel;
577 }
578 }
579
580 out:
581 mutex_unlock(&ioc->sas_device_info_mutex);
582 return;
583}
584
585/**
586 * mptsas_add_device_component_by_fw -
587 * @ioc: Pointer to MPT_ADAPTER structure
588 * @channel: fw mapped id's
589 * @id:
590 *
591 **/
592static void
593mptsas_add_device_component_by_fw(MPT_ADAPTER *ioc, u8 channel, u8 id)
594{
595 struct mptsas_devinfo sas_device;
596 struct mptsas_enclosure enclosure_info;
597 int rc;
598
599 rc = mptsas_sas_device_pg0(ioc, &sas_device,
600 (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
601 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
602 (channel << 8) + id);
603 if (rc)
604 return;
605
606 memset(&enclosure_info, 0, sizeof(struct mptsas_enclosure));
607 mptsas_sas_enclosure_pg0(ioc, &enclosure_info,
608 (MPI_SAS_ENCLOS_PGAD_FORM_HANDLE <<
609 MPI_SAS_ENCLOS_PGAD_FORM_SHIFT),
610 sas_device.handle_enclosure);
611
612 mptsas_add_device_component(ioc, sas_device.channel,
613 sas_device.id, sas_device.sas_address, sas_device.device_info,
614 sas_device.slot, enclosure_info.enclosure_logical_id);
615}
616
617/**
618 * mptsas_add_device_component_starget -
619 * @ioc: Pointer to MPT_ADAPTER structure
620 * @starget:
621 *
622 **/
623static void
624mptsas_add_device_component_starget(MPT_ADAPTER *ioc,
625 struct scsi_target *starget)
626{
627 VirtTarget *vtarget;
628 struct sas_rphy *rphy;
629 struct mptsas_phyinfo *phy_info = NULL;
630 struct mptsas_enclosure enclosure_info;
631
632 rphy = dev_to_rphy(starget->dev.parent);
633 vtarget = starget->hostdata;
634 phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
635 rphy->identify.sas_address);
636 if (!phy_info)
637 return;
638
639 memset(&enclosure_info, 0, sizeof(struct mptsas_enclosure));
640 mptsas_sas_enclosure_pg0(ioc, &enclosure_info,
641 (MPI_SAS_ENCLOS_PGAD_FORM_HANDLE <<
642 MPI_SAS_ENCLOS_PGAD_FORM_SHIFT),
643 phy_info->attached.handle_enclosure);
644
645 mptsas_add_device_component(ioc, phy_info->attached.channel,
646 phy_info->attached.id, phy_info->attached.sas_address,
647 phy_info->attached.device_info,
648 phy_info->attached.slot, enclosure_info.enclosure_logical_id);
649}
650
651/**
652 * mptsas_del_device_components - Cleaning the list
653 * @ioc: Pointer to MPT_ADAPTER structure
654 *
655 **/
656static void
657mptsas_del_device_components(MPT_ADAPTER *ioc)
658{
659 struct mptsas_device_info *sas_info, *next;
660
661 mutex_lock(&ioc->sas_device_info_mutex);
662 list_for_each_entry_safe(sas_info, next, &ioc->sas_device_info_list,
663 list) {
664 list_del(&sas_info->list);
665 kfree(sas_info);
666 }
667 mutex_unlock(&ioc->sas_device_info_mutex);
668}
669
547f9a21
EM
670
671/*
672 * mptsas_setup_wide_ports
673 *
674 * Updates for new and existing narrow/wide port configuration
675 * in the sas_topology
676 */
376ac830 677static void
547f9a21
EM
678mptsas_setup_wide_ports(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
679{
680 struct mptsas_portinfo_details * port_details;
681 struct mptsas_phyinfo *phy_info, *phy_info_cmp;
682 u64 sas_address;
683 int i, j;
684
685 mutex_lock(&ioc->sas_topology_mutex);
686
687 phy_info = port_info->phy_info;
688 for (i = 0 ; i < port_info->num_phys ; i++, phy_info++) {
689 if (phy_info->attached.handle)
690 continue;
691 port_details = phy_info->port_details;
692 if (!port_details)
693 continue;
694 if (port_details->num_phys < 2)
695 continue;
696 /*
697 * Removing a phy from a port, letting the last
698 * phy be removed by firmware events.
699 */
29dd3609
EM
700 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT
701 "%s: [%p]: deleting phy = %d\n",
cadbd4a5 702 ioc->name, __func__, port_details, i));
547f9a21
EM
703 port_details->num_phys--;
704 port_details->phy_bitmask &= ~ (1 << phy_info->phy_id);
705 memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo));
706 sas_port_delete_phy(port_details->port, phy_info->phy);
707 phy_info->port_details = NULL;
708 }
709
710 /*
711 * Populate and refresh the tree
712 */
713 phy_info = port_info->phy_info;
714 for (i = 0 ; i < port_info->num_phys ; i++, phy_info++) {
715 sas_address = phy_info->attached.sas_address;
29dd3609
EM
716 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "phy_id=%d sas_address=0x%018llX\n",
717 ioc->name, i, (unsigned long long)sas_address));
547f9a21
EM
718 if (!sas_address)
719 continue;
720 port_details = phy_info->port_details;
721 /*
722 * Forming a port
723 */
724 if (!port_details) {
725 port_details = kzalloc(sizeof(*port_details),
726 GFP_KERNEL);
727 if (!port_details)
728 goto out;
729 port_details->num_phys = 1;
730 port_details->port_info = port_info;
547f9a21
EM
731 if (phy_info->phy_id < 64 )
732 port_details->phy_bitmask |=
733 (1 << phy_info->phy_id);
734 phy_info->sas_port_add_phy=1;
29dd3609 735 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "\t\tForming port\n\t\t"
f99be43b 736 "phy_id=%d sas_address=0x%018llX\n",
29dd3609 737 ioc->name, i, (unsigned long long)sas_address));
547f9a21
EM
738 phy_info->port_details = port_details;
739 }
740
741 if (i == port_info->num_phys - 1)
742 continue;
743 phy_info_cmp = &port_info->phy_info[i + 1];
744 for (j = i + 1 ; j < port_info->num_phys ; j++,
745 phy_info_cmp++) {
746 if (!phy_info_cmp->attached.sas_address)
747 continue;
748 if (sas_address != phy_info_cmp->attached.sas_address)
749 continue;
750 if (phy_info_cmp->port_details == port_details )
751 continue;
29dd3609 752 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT
f99be43b 753 "\t\tphy_id=%d sas_address=0x%018llX\n",
29dd3609 754 ioc->name, j, (unsigned long long)
f99be43b 755 phy_info_cmp->attached.sas_address));
547f9a21
EM
756 if (phy_info_cmp->port_details) {
757 port_details->rphy =
758 mptsas_get_rphy(phy_info_cmp);
759 port_details->port =
760 mptsas_get_port(phy_info_cmp);
761 port_details->starget =
762 mptsas_get_starget(phy_info_cmp);
547f9a21
EM
763 port_details->num_phys =
764 phy_info_cmp->port_details->num_phys;
547f9a21
EM
765 if (!phy_info_cmp->port_details->num_phys)
766 kfree(phy_info_cmp->port_details);
767 } else
768 phy_info_cmp->sas_port_add_phy=1;
769 /*
770 * Adding a phy to a port
771 */
772 phy_info_cmp->port_details = port_details;
773 if (phy_info_cmp->phy_id < 64 )
774 port_details->phy_bitmask |=
775 (1 << phy_info_cmp->phy_id);
776 port_details->num_phys++;
777 }
778 }
779
780 out:
781
547f9a21
EM
782 for (i = 0; i < port_info->num_phys; i++) {
783 port_details = port_info->phy_info[i].port_details;
784 if (!port_details)
785 continue;
29dd3609 786 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT
f99be43b 787 "%s: [%p]: phy_id=%02d num_phys=%02d "
cadbd4a5 788 "bitmask=0x%016llX\n", ioc->name, __func__,
f99be43b
EM
789 port_details, i, port_details->num_phys,
790 (unsigned long long)port_details->phy_bitmask));
29dd3609
EM
791 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "\t\tport = %p rphy=%p\n",
792 ioc->name, port_details->port, port_details->rphy));
547f9a21 793 }
29dd3609 794 dsaswideprintk(ioc, printk("\n"));
547f9a21
EM
795 mutex_unlock(&ioc->sas_topology_mutex);
796}
797
df9e062a
EM
798/**
799 * csmisas_find_vtarget
800 *
801 * @ioc
802 * @volume_id
803 * @volume_bus
804 *
805 **/
806static VirtTarget *
807mptsas_find_vtarget(MPT_ADAPTER *ioc, u8 channel, u8 id)
808{
809 struct scsi_device *sdev;
a69de507 810 VirtDevice *vdevice;
df9e062a
EM
811 VirtTarget *vtarget = NULL;
812
813 shost_for_each_device(sdev, ioc->sh) {
e7deff33
KD
814 vdevice = sdev->hostdata;
815 if ((vdevice == NULL) ||
816 (vdevice->vtarget == NULL))
df9e062a 817 continue;
a69de507 818 if (vdevice->vtarget->id == id &&
e7deff33 819 vdevice->vtarget->channel == channel)
a69de507 820 vtarget = vdevice->vtarget;
df9e062a
EM
821 }
822 return vtarget;
823}
824
3eb0822c
KD
825static void
826mptsas_queue_device_delete(MPT_ADAPTER *ioc,
827 MpiEventDataSasDeviceStatusChange_t *sas_event_data)
828{
829 struct fw_event_work *fw_event;
830 int sz;
831
832 sz = offsetof(struct fw_event_work, event_data) +
833 sizeof(MpiEventDataSasDeviceStatusChange_t);
834 fw_event = kzalloc(sz, GFP_ATOMIC);
835 if (!fw_event) {
836 printk(MYIOC_s_WARN_FMT "%s: failed at (line=%d)\n",
837 ioc->name, __func__, __LINE__);
838 return;
839 }
840 memcpy(fw_event->event_data, sas_event_data,
841 sizeof(MpiEventDataSasDeviceStatusChange_t));
842 fw_event->event = MPI_EVENT_SAS_DEVICE_STATUS_CHANGE;
843 fw_event->ioc = ioc;
844 mptsas_add_fw_event(ioc, fw_event, msecs_to_jiffies(1));
845}
846
847
df9e062a
EM
848/**
849 * mptsas_target_reset
850 *
851 * Issues TARGET_RESET to end device using handshaking method
852 *
853 * @ioc
854 * @channel
855 * @id
856 *
857 * Returns (1) success
858 * (0) failure
859 *
860 **/
861static int
862mptsas_target_reset(MPT_ADAPTER *ioc, u8 channel, u8 id)
863{
864 MPT_FRAME_HDR *mf;
865 SCSITaskMgmt_t *pScsiTm;
ea2a788d
KD
866 if (mpt_set_taskmgmt_in_progress_flag(ioc) != 0)
867 return 0;
868
df9e062a 869
e7deff33
KD
870 mf = mpt_get_msg_frame(mptsasDeviceResetCtx, ioc);
871 if (mf == NULL) {
872 dfailprintk(ioc, printk(MYIOC_s_WARN_FMT
ea2a788d
KD
873 "%s, no msg frames @%d!!\n", ioc->name,
874 __func__, __LINE__));
875 goto out_fail;
df9e062a
EM
876 }
877
ea2a788d
KD
878 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt request (mf=%p)\n",
879 ioc->name, mf));
880
df9e062a
EM
881 /* Format the Request
882 */
883 pScsiTm = (SCSITaskMgmt_t *) mf;
884 memset (pScsiTm, 0, sizeof(SCSITaskMgmt_t));
885 pScsiTm->TargetID = id;
886 pScsiTm->Bus = channel;
887 pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
888 pScsiTm->TaskType = MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET;
889 pScsiTm->MsgFlags = MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION;
890
d6ecdd63 891 DBG_DUMP_TM_REQUEST_FRAME(ioc, (u32 *)mf);
df9e062a 892
ea2a788d
KD
893 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
894 "TaskMgmt type=%d (sas device delete) fw_channel = %d fw_id = %d)\n",
895 ioc->name, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET, channel, id));
896
e7deff33 897 mpt_put_msg_frame_hi_pri(mptsasDeviceResetCtx, ioc, mf);
df9e062a
EM
898
899 return 1;
ea2a788d
KD
900
901 out_fail:
902
903 mpt_clear_taskmgmt_in_progress_flag(ioc);
904 return 0;
df9e062a
EM
905}
906
907/**
908 * mptsas_target_reset_queue
909 *
910 * Receive request for TARGET_RESET after recieving an firmware
911 * event NOT_RESPONDING_EVENT, then put command in link list
912 * and queue if task_queue already in use.
913 *
914 * @ioc
915 * @sas_event_data
916 *
917 **/
547f9a21 918static void
df9e062a
EM
919mptsas_target_reset_queue(MPT_ADAPTER *ioc,
920 EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data)
547f9a21 921{
e7eae9f6 922 MPT_SCSI_HOST *hd = shost_priv(ioc->sh);
df9e062a
EM
923 VirtTarget *vtarget = NULL;
924 struct mptsas_target_reset_event *target_reset_list;
925 u8 id, channel;
547f9a21 926
df9e062a
EM
927 id = sas_event_data->TargetID;
928 channel = sas_event_data->Bus;
929
930 if (!(vtarget = mptsas_find_vtarget(ioc, channel, id)))
931 return;
932
933 vtarget->deleted = 1; /* block IO */
934
935 target_reset_list = kzalloc(sizeof(*target_reset_list),
936 GFP_ATOMIC);
937 if (!target_reset_list) {
e7deff33
KD
938 dfailprintk(ioc, printk(MYIOC_s_WARN_FMT
939 "%s, failed to allocate mem @%d..!!\n",
940 ioc->name, __func__, __LINE__));
df9e062a
EM
941 return;
942 }
943
944 memcpy(&target_reset_list->sas_event_data, sas_event_data,
945 sizeof(*sas_event_data));
946 list_add_tail(&target_reset_list->list, &hd->target_reset_list);
947
e7deff33 948 target_reset_list->time_count = jiffies;
df9e062a
EM
949
950 if (mptsas_target_reset(ioc, channel, id)) {
951 target_reset_list->target_reset_issued = 1;
df9e062a
EM
952 }
953}
954
955/**
e7deff33
KD
956 * mptsas_taskmgmt_complete - Completion for TARGET_RESET after
957 * NOT_RESPONDING_EVENT, enable work queue to finish off removing device
958 * from upper layers. then send next TARGET_RESET in the queue.
959 * @ioc: Pointer to MPT_ADAPTER structure
df9e062a
EM
960 *
961 **/
e7deff33
KD
962static int
963mptsas_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
df9e062a 964{
e7eae9f6 965 MPT_SCSI_HOST *hd = shost_priv(ioc->sh);
df9e062a 966 struct list_head *head = &hd->target_reset_list;
df9e062a 967 u8 id, channel;
e7deff33
KD
968 struct mptsas_target_reset_event *target_reset_list;
969 SCSITaskMgmtReply_t *pScsiTmReply;
970
971 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt completed: "
972 "(mf = %p, mr = %p)\n", ioc->name, mf, mr));
973
974 pScsiTmReply = (SCSITaskMgmtReply_t *)mr;
975 if (pScsiTmReply) {
976 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
977 "\tTaskMgmt completed: fw_channel = %d, fw_id = %d,\n"
978 "\ttask_type = 0x%02X, iocstatus = 0x%04X "
979 "loginfo = 0x%08X,\n\tresponse_code = 0x%02X, "
980 "term_cmnds = %d\n", ioc->name,
981 pScsiTmReply->Bus, pScsiTmReply->TargetID,
982 pScsiTmReply->TaskType,
983 le16_to_cpu(pScsiTmReply->IOCStatus),
984 le32_to_cpu(pScsiTmReply->IOCLogInfo),
985 pScsiTmReply->ResponseCode,
986 le32_to_cpu(pScsiTmReply->TerminationCount)));
987
988 if (pScsiTmReply->ResponseCode)
989 mptscsih_taskmgmt_response_code(ioc,
990 pScsiTmReply->ResponseCode);
991 }
992
993 if (pScsiTmReply && (pScsiTmReply->TaskType ==
994 MPI_SCSITASKMGMT_TASKTYPE_QUERY_TASK || pScsiTmReply->TaskType ==
995 MPI_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET)) {
996 ioc->taskmgmt_cmds.status |= MPT_MGMT_STATUS_COMMAND_GOOD;
997 ioc->taskmgmt_cmds.status |= MPT_MGMT_STATUS_RF_VALID;
998 memcpy(ioc->taskmgmt_cmds.reply, mr,
999 min(MPT_DEFAULT_FRAME_SIZE, 4 * mr->u.reply.MsgLength));
1000 if (ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_PENDING) {
1001 ioc->taskmgmt_cmds.status &= ~MPT_MGMT_STATUS_PENDING;
1002 complete(&ioc->taskmgmt_cmds.done);
1003 return 1;
1004 }
1005 return 0;
1006 }
1007
1008 mpt_clear_taskmgmt_in_progress_flag(ioc);
df9e062a
EM
1009
1010 if (list_empty(head))
e7deff33
KD
1011 return 1;
1012
1013 target_reset_list = list_entry(head->next,
1014 struct mptsas_target_reset_event, list);
df9e062a 1015
e7deff33
KD
1016 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1017 "TaskMgmt: completed (%d seconds)\n",
1018 ioc->name, jiffies_to_msecs(jiffies -
1019 target_reset_list->time_count)/1000));
df9e062a 1020
e7deff33
KD
1021 id = pScsiTmReply->TargetID;
1022 channel = pScsiTmReply->Bus;
1023 target_reset_list->time_count = jiffies;
df9e062a
EM
1024
1025 /*
1026 * retry target reset
1027 */
1028 if (!target_reset_list->target_reset_issued) {
e7deff33 1029 if (mptsas_target_reset(ioc, channel, id))
df9e062a 1030 target_reset_list->target_reset_issued = 1;
e7deff33 1031 return 1;
df9e062a
EM
1032 }
1033
1034 /*
1035 * enable work queue to remove device from upper layers
1036 */
1037 list_del(&target_reset_list->list);
3eb0822c
KD
1038 if ((mptsas_find_vtarget(ioc, channel, id)) && !ioc->fw_events_off)
1039 mptsas_queue_device_delete(ioc,
1040 &target_reset_list->sas_event_data);
ea2a788d 1041
e7deff33 1042
df9e062a
EM
1043 /*
1044 * issue target reset to next device in the queue
1045 */
1046
1047 head = &hd->target_reset_list;
1048 if (list_empty(head))
e7deff33 1049 return 1;
df9e062a
EM
1050
1051 target_reset_list = list_entry(head->next, struct mptsas_target_reset_event,
1052 list);
1053
e7deff33
KD
1054 id = target_reset_list->sas_event_data.TargetID;
1055 channel = target_reset_list->sas_event_data.Bus;
1056 target_reset_list->time_count = jiffies;
df9e062a 1057
e7deff33 1058 if (mptsas_target_reset(ioc, channel, id))
df9e062a 1059 target_reset_list->target_reset_issued = 1;
df9e062a 1060
e7deff33 1061 return 1;
df9e062a
EM
1062}
1063
1064/**
1065 * mptscsih_ioc_reset
1066 *
1067 * @ioc
1068 * @reset_phase
1069 *
1070 **/
1071static int
1072mptsas_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
1073{
ba76ef24 1074 MPT_SCSI_HOST *hd;
df9e062a
EM
1075 int rc;
1076
1077 rc = mptscsih_ioc_reset(ioc, reset_phase);
3eb0822c
KD
1078 if ((ioc->bus_type != SAS) || (!rc))
1079 return rc;
df9e062a 1080
e7eae9f6 1081 hd = shost_priv(ioc->sh);
ba76ef24 1082 if (!hd->ioc)
df9e062a
EM
1083 goto out;
1084
3eb0822c
KD
1085 switch (reset_phase) {
1086 case MPT_IOC_SETUP_RESET:
1087 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1088 "%s: MPT_IOC_SETUP_RESET\n", ioc->name, __func__));
1089 mptsas_fw_event_off(ioc);
1090 break;
1091 case MPT_IOC_PRE_RESET:
1092 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1093 "%s: MPT_IOC_PRE_RESET\n", ioc->name, __func__));
1094 break;
1095 case MPT_IOC_POST_RESET:
1096 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1097 "%s: MPT_IOC_POST_RESET\n", ioc->name, __func__));
1098 if (ioc->sas_mgmt.status & MPT_MGMT_STATUS_PENDING) {
1099 ioc->sas_mgmt.status |= MPT_MGMT_STATUS_DID_IOCRESET;
1100 complete(&ioc->sas_mgmt.done);
1101 }
1102 mptsas_cleanup_fw_event_q(ioc);
1103 mptsas_fw_event_on(ioc);
1104 break;
1105 default:
1106 break;
547f9a21 1107 }
df9e062a
EM
1108
1109 out:
1110 return rc;
547f9a21
EM
1111}
1112
3eb0822c
KD
1113
1114/**
1115 * enum device_state -
1116 * @DEVICE_RETRY: need to retry the TUR
1117 * @DEVICE_ERROR: TUR return error, don't add device
1118 * @DEVICE_READY: device can be added
1119 *
1120 */
1121enum device_state{
1122 DEVICE_RETRY,
1123 DEVICE_ERROR,
1124 DEVICE_READY,
1125};
1126
e3094447 1127static int
52435430 1128mptsas_sas_enclosure_pg0(MPT_ADAPTER *ioc, struct mptsas_enclosure *enclosure,
e3094447
CH
1129 u32 form, u32 form_specific)
1130{
1131 ConfigExtendedPageHeader_t hdr;
1132 CONFIGPARMS cfg;
1133 SasEnclosurePage0_t *buffer;
1134 dma_addr_t dma_handle;
1135 int error;
1136 __le64 le_identifier;
1137
1138 memset(&hdr, 0, sizeof(hdr));
1139 hdr.PageVersion = MPI_SASENCLOSURE0_PAGEVERSION;
1140 hdr.PageNumber = 0;
1141 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1142 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_ENCLOSURE;
1143
1144 cfg.cfghdr.ehdr = &hdr;
1145 cfg.physAddr = -1;
1146 cfg.pageAddr = form + form_specific;
1147 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1148 cfg.dir = 0; /* read */
1149 cfg.timeout = 10;
1150
1151 error = mpt_config(ioc, &cfg);
1152 if (error)
1153 goto out;
1154 if (!hdr.ExtPageLength) {
1155 error = -ENXIO;
1156 goto out;
1157 }
1158
1159 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1160 &dma_handle);
1161 if (!buffer) {
1162 error = -ENOMEM;
1163 goto out;
1164 }
1165
1166 cfg.physAddr = dma_handle;
1167 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1168
1169 error = mpt_config(ioc, &cfg);
1170 if (error)
1171 goto out_free_consistent;
1172
1173 /* save config data */
1174 memcpy(&le_identifier, &buffer->EnclosureLogicalID, sizeof(__le64));
1175 enclosure->enclosure_logical_id = le64_to_cpu(le_identifier);
1176 enclosure->enclosure_handle = le16_to_cpu(buffer->EnclosureHandle);
1177 enclosure->flags = le16_to_cpu(buffer->Flags);
1178 enclosure->num_slot = le16_to_cpu(buffer->NumSlots);
1179 enclosure->start_slot = le16_to_cpu(buffer->StartSlot);
1180 enclosure->start_id = buffer->StartTargetID;
1181 enclosure->start_channel = buffer->StartBus;
1182 enclosure->sep_id = buffer->SEPTargetID;
1183 enclosure->sep_channel = buffer->SEPBus;
1184
1185 out_free_consistent:
1186 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1187 buffer, dma_handle);
1188 out:
1189 return error;
1190}
b5141128 1191
3eb0822c
KD
1192/**
1193 * mptsas_add_end_device - report a new end device to sas transport layer
1194 * @ioc: Pointer to MPT_ADAPTER structure
1195 * @phy_info: decribes attached device
1196 *
1197 * return (0) success (1) failure
1198 *
1199 **/
1200static int
1201mptsas_add_end_device(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info)
1202{
1203 struct sas_rphy *rphy;
1204 struct sas_port *port;
1205 struct sas_identify identify;
1206 char *ds = NULL;
1207 u8 fw_id;
1208
1209 if (!phy_info) {
1210 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
1211 "%s: exit at line=%d\n", ioc->name,
1212 __func__, __LINE__));
1213 return 1;
1214 }
1215
1216 fw_id = phy_info->attached.id;
1217
1218 if (mptsas_get_rphy(phy_info)) {
1219 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
1220 "%s: fw_id=%d exit at line=%d\n", ioc->name,
1221 __func__, fw_id, __LINE__));
1222 return 2;
1223 }
1224
1225 port = mptsas_get_port(phy_info);
1226 if (!port) {
1227 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
1228 "%s: fw_id=%d exit at line=%d\n", ioc->name,
1229 __func__, fw_id, __LINE__));
1230 return 3;
1231 }
1232
1233 if (phy_info->attached.device_info &
1234 MPI_SAS_DEVICE_INFO_SSP_TARGET)
1235 ds = "ssp";
1236 if (phy_info->attached.device_info &
1237 MPI_SAS_DEVICE_INFO_STP_TARGET)
1238 ds = "stp";
1239 if (phy_info->attached.device_info &
1240 MPI_SAS_DEVICE_INFO_SATA_DEVICE)
1241 ds = "sata";
1242
1243 printk(MYIOC_s_INFO_FMT "attaching %s device: fw_channel %d, fw_id %d,"
1244 " phy %d, sas_addr 0x%llx\n", ioc->name, ds,
1245 phy_info->attached.channel, phy_info->attached.id,
1246 phy_info->attached.phy_id, (unsigned long long)
1247 phy_info->attached.sas_address);
1248
1249 mptsas_parse_device_info(&identify, &phy_info->attached);
1250 rphy = sas_end_device_alloc(port);
1251 if (!rphy) {
1252 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
1253 "%s: fw_id=%d exit at line=%d\n", ioc->name,
1254 __func__, fw_id, __LINE__));
1255 return 5; /* non-fatal: an rphy can be added later */
1256 }
1257
1258 rphy->identify = identify;
1259 if (sas_rphy_add(rphy)) {
1260 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
1261 "%s: fw_id=%d exit at line=%d\n", ioc->name,
1262 __func__, fw_id, __LINE__));
1263 sas_rphy_free(rphy);
1264 return 6;
1265 }
1266 mptsas_set_rphy(ioc, phy_info, rphy);
1267 return 0;
1268}
1269
1270/**
1271 * mptsas_del_end_device - report a deleted end device to sas transport
1272 * layer
1273 * @ioc: Pointer to MPT_ADAPTER structure
1274 * @phy_info: decribes attached device
1275 *
1276 **/
1277static void
1278mptsas_del_end_device(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info)
1279{
1280 struct sas_rphy *rphy;
1281 struct sas_port *port;
1282 struct mptsas_portinfo *port_info;
1283 struct mptsas_phyinfo *phy_info_parent;
1284 int i;
1285 char *ds = NULL;
1286 u8 fw_id;
1287 u64 sas_address;
1288
1289 if (!phy_info)
1290 return;
1291
1292 fw_id = phy_info->attached.id;
1293 sas_address = phy_info->attached.sas_address;
1294
1295 if (!phy_info->port_details) {
1296 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
1297 "%s: fw_id=%d exit at line=%d\n", ioc->name,
1298 __func__, fw_id, __LINE__));
1299 return;
1300 }
1301 rphy = mptsas_get_rphy(phy_info);
1302 if (!rphy) {
1303 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
1304 "%s: fw_id=%d exit at line=%d\n", ioc->name,
1305 __func__, fw_id, __LINE__));
1306 return;
1307 }
1308
1309 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_INITIATOR
1310 || phy_info->attached.device_info
1311 & MPI_SAS_DEVICE_INFO_SMP_INITIATOR
1312 || phy_info->attached.device_info
1313 & MPI_SAS_DEVICE_INFO_STP_INITIATOR)
1314 ds = "initiator";
1315 if (phy_info->attached.device_info &
1316 MPI_SAS_DEVICE_INFO_SSP_TARGET)
1317 ds = "ssp";
1318 if (phy_info->attached.device_info &
1319 MPI_SAS_DEVICE_INFO_STP_TARGET)
1320 ds = "stp";
1321 if (phy_info->attached.device_info &
1322 MPI_SAS_DEVICE_INFO_SATA_DEVICE)
1323 ds = "sata";
1324
1325 dev_printk(KERN_DEBUG, &rphy->dev, MYIOC_s_FMT
1326 "removing %s device: fw_channel %d, fw_id %d, phy %d,"
1327 "sas_addr 0x%llx\n", ioc->name, ds, phy_info->attached.channel,
1328 phy_info->attached.id, phy_info->attached.phy_id,
1329 (unsigned long long) sas_address);
1330
1331 port = mptsas_get_port(phy_info);
1332 if (!port) {
1333 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
1334 "%s: fw_id=%d exit at line=%d\n", ioc->name,
1335 __func__, fw_id, __LINE__));
1336 return;
1337 }
1338 port_info = phy_info->portinfo;
1339 phy_info_parent = port_info->phy_info;
1340 for (i = 0; i < port_info->num_phys; i++, phy_info_parent++) {
1341 if (!phy_info_parent->phy)
1342 continue;
1343 if (phy_info_parent->attached.sas_address !=
1344 sas_address)
1345 continue;
1346 dev_printk(KERN_DEBUG, &phy_info_parent->phy->dev,
1347 MYIOC_s_FMT "delete phy %d, phy-obj (0x%p)\n",
1348 ioc->name, phy_info_parent->phy_id,
1349 phy_info_parent->phy);
1350 sas_port_delete_phy(port, phy_info_parent->phy);
1351 }
1352
1353 dev_printk(KERN_DEBUG, &port->dev, MYIOC_s_FMT
1354 "delete port %d, sas_addr (0x%llx)\n", ioc->name,
1355 port->port_identifier, (unsigned long long)sas_address);
1356 sas_port_delete(port);
1357 mptsas_set_port(ioc, phy_info, NULL);
1358 mptsas_port_delete(ioc, phy_info->port_details);
1359}
1360
1361struct mptsas_phyinfo *
1362mptsas_refreshing_device_handles(MPT_ADAPTER *ioc,
1363 struct mptsas_devinfo *sas_device)
1364{
1365 struct mptsas_phyinfo *phy_info;
1366 struct mptsas_portinfo *port_info;
1367 int i;
1368
1369 phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
1370 sas_device->sas_address);
1371 if (!phy_info)
1372 goto out;
1373 port_info = phy_info->portinfo;
1374 if (!port_info)
1375 goto out;
1376 mutex_lock(&ioc->sas_topology_mutex);
1377 for (i = 0; i < port_info->num_phys; i++) {
1378 if (port_info->phy_info[i].attached.sas_address !=
1379 sas_device->sas_address)
1380 continue;
1381 port_info->phy_info[i].attached.channel = sas_device->channel;
1382 port_info->phy_info[i].attached.id = sas_device->id;
1383 port_info->phy_info[i].attached.sas_address =
1384 sas_device->sas_address;
1385 port_info->phy_info[i].attached.handle = sas_device->handle;
1386 port_info->phy_info[i].attached.handle_parent =
1387 sas_device->handle_parent;
1388 port_info->phy_info[i].attached.handle_enclosure =
1389 sas_device->handle_enclosure;
1390 }
1391 mutex_unlock(&ioc->sas_topology_mutex);
1392 out:
1393 return phy_info;
1394}
1395
1396/**
1397 * mptsas_firmware_event_work - work thread for processing fw events
1398 * @work: work queue payload containing info describing the event
1399 * Context: user
1400 *
1401 */
1402static void
1403mptsas_firmware_event_work(struct work_struct *work)
1404{
1405 struct fw_event_work *fw_event =
1406 container_of(work, struct fw_event_work, work.work);
1407 MPT_ADAPTER *ioc = fw_event->ioc;
1408
1409
1410 /* events handling turned off during host reset */
1411 if (ioc->fw_events_off) {
1412 mptsas_free_fw_event(ioc, fw_event);
1413 return;
1414 }
1415
1416 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: fw_event=(0x%p), "
1417 "event = (0x%02x)\n", ioc->name, __func__, fw_event,
1418 (fw_event->event & 0xFF)));
1419
1420 switch (fw_event->event) {
1421 case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
1422 mptsas_send_sas_event(fw_event);
1423 break;
1424 case MPI_EVENT_INTEGRATED_RAID:
1425 mptsas_send_raid_event(fw_event);
1426 break;
1427 case MPI_EVENT_IR2:
1428 mptsas_send_ir2_event(fw_event);
1429 break;
1430 case MPI_EVENT_PERSISTENT_TABLE_FULL:
1431 mptbase_sas_persist_operation(ioc,
1432 MPI_SAS_OP_CLEAR_NOT_PRESENT);
1433 mptsas_free_fw_event(ioc, fw_event);
1434 break;
f9c34022
KD
1435 case MPI_EVENT_SAS_EXPANDER_STATUS_CHANGE:
1436 mptsas_send_expander_event(fw_event);
1437 break;
1438 case MPI_EVENT_SAS_PHY_LINK_STATUS:
1439 mptsas_send_link_status_event(fw_event);
1440 break;
3eb0822c
KD
1441 }
1442}
1443
1444
1445
f013db32
JB
1446static int
1447mptsas_slave_configure(struct scsi_device *sdev)
1448{
3eb0822c
KD
1449 struct Scsi_Host *host = sdev->host;
1450 MPT_SCSI_HOST *hd = shost_priv(host);
1451 MPT_ADAPTER *ioc = hd->ioc;
3c0c25b9 1452
e8bf3941
JB
1453 if (sdev->channel == MPTSAS_RAID_CHANNEL)
1454 goto out;
1455
1456 sas_read_port_mode_page(sdev);
f013db32 1457
3eb0822c
KD
1458 mptsas_add_device_component_starget(ioc, scsi_target(sdev));
1459
e8bf3941 1460 out:
f013db32
JB
1461 return mptscsih_slave_configure(sdev);
1462}
1463
547f9a21
EM
1464static int
1465mptsas_target_alloc(struct scsi_target *starget)
1466{
1467 struct Scsi_Host *host = dev_to_shost(&starget->dev);
e7eae9f6 1468 MPT_SCSI_HOST *hd = shost_priv(host);
547f9a21 1469 VirtTarget *vtarget;
793955f5 1470 u8 id, channel;
547f9a21
EM
1471 struct sas_rphy *rphy;
1472 struct mptsas_portinfo *p;
1473 int i;
e80b002b 1474 MPT_ADAPTER *ioc = hd->ioc;
547f9a21
EM
1475
1476 vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL);
1477 if (!vtarget)
1478 return -ENOMEM;
1479
1480 vtarget->starget = starget;
e80b002b 1481 vtarget->ioc_id = ioc->id;
793955f5
EM
1482 vtarget->tflags = MPT_TARGET_FLAGS_Q_YES;
1483 id = starget->id;
547f9a21
EM
1484 channel = 0;
1485
793955f5
EM
1486 /*
1487 * RAID volumes placed beyond the last expected port.
1488 */
1489 if (starget->channel == MPTSAS_RAID_CHANNEL) {
e80b002b
EM
1490 for (i=0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++)
1491 if (id == ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID)
1492 channel = ioc->raid_data.pIocPg2->RaidVolume[i].VolumeBus;
547f9a21 1493 goto out;
793955f5 1494 }
547f9a21
EM
1495
1496 rphy = dev_to_rphy(starget->dev.parent);
e80b002b
EM
1497 mutex_lock(&ioc->sas_topology_mutex);
1498 list_for_each_entry(p, &ioc->sas_topology, list) {
547f9a21
EM
1499 for (i = 0; i < p->num_phys; i++) {
1500 if (p->phy_info[i].attached.sas_address !=
1501 rphy->identify.sas_address)
1502 continue;
793955f5 1503 id = p->phy_info[i].attached.id;
547f9a21
EM
1504 channel = p->phy_info[i].attached.channel;
1505 mptsas_set_starget(&p->phy_info[i], starget);
1506
1507 /*
1508 * Exposing hidden raid components
1509 */
e80b002b
EM
1510 if (mptscsih_is_phys_disk(ioc, channel, id)) {
1511 id = mptscsih_raid_id_to_num(ioc,
793955f5 1512 channel, id);
547f9a21
EM
1513 vtarget->tflags |=
1514 MPT_TARGET_FLAGS_RAID_COMPONENT;
b506ade9 1515 p->phy_info[i].attached.phys_disk_num = id;
547f9a21 1516 }
e80b002b 1517 mutex_unlock(&ioc->sas_topology_mutex);
547f9a21
EM
1518 goto out;
1519 }
1520 }
e80b002b 1521 mutex_unlock(&ioc->sas_topology_mutex);
547f9a21
EM
1522
1523 kfree(vtarget);
1524 return -ENXIO;
1525
1526 out:
793955f5
EM
1527 vtarget->id = id;
1528 vtarget->channel = channel;
547f9a21
EM
1529 starget->hostdata = vtarget;
1530 return 0;
1531}
1532
1533static void
1534mptsas_target_destroy(struct scsi_target *starget)
1535{
1536 struct Scsi_Host *host = dev_to_shost(&starget->dev);
e7eae9f6 1537 MPT_SCSI_HOST *hd = shost_priv(host);
547f9a21
EM
1538 struct sas_rphy *rphy;
1539 struct mptsas_portinfo *p;
1540 int i;
3eb0822c
KD
1541 MPT_ADAPTER *ioc = hd->ioc;
1542 VirtTarget *vtarget;
547f9a21
EM
1543
1544 if (!starget->hostdata)
1545 return;
1546
3eb0822c
KD
1547 vtarget = starget->hostdata;
1548
1549
e8bf3941 1550 if (starget->channel == MPTSAS_RAID_CHANNEL)
547f9a21
EM
1551 goto out;
1552
1553 rphy = dev_to_rphy(starget->dev.parent);
e80b002b 1554 list_for_each_entry(p, &ioc->sas_topology, list) {
547f9a21
EM
1555 for (i = 0; i < p->num_phys; i++) {
1556 if (p->phy_info[i].attached.sas_address !=
1557 rphy->identify.sas_address)
1558 continue;
3eb0822c
KD
1559
1560 starget_printk(KERN_INFO, starget, MYIOC_s_FMT
1561 "delete device: fw_channel %d, fw_id %d, phy %d, "
1562 "sas_addr 0x%llx\n", ioc->name,
1563 p->phy_info[i].attached.channel,
1564 p->phy_info[i].attached.id,
1565 p->phy_info[i].attached.phy_id, (unsigned long long)
1566 p->phy_info[i].attached.sas_address);
1567
547f9a21 1568 mptsas_set_starget(&p->phy_info[i], NULL);
547f9a21
EM
1569 }
1570 }
1571
1572 out:
3eb0822c 1573 vtarget->starget = NULL;
547f9a21
EM
1574 kfree(starget->hostdata);
1575 starget->hostdata = NULL;
1576}
1577
1578
0c33b27d 1579static int
c7c82987 1580mptsas_slave_alloc(struct scsi_device *sdev)
0c33b27d 1581{
c7c82987 1582 struct Scsi_Host *host = sdev->host;
e7eae9f6 1583 MPT_SCSI_HOST *hd = shost_priv(host);
0c33b27d
CH
1584 struct sas_rphy *rphy;
1585 struct mptsas_portinfo *p;
a69de507 1586 VirtDevice *vdevice;
c7c82987 1587 struct scsi_target *starget;
547f9a21 1588 int i;
e80b002b 1589 MPT_ADAPTER *ioc = hd->ioc;
0c33b27d 1590
a69de507
EM
1591 vdevice = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
1592 if (!vdevice) {
547f9a21 1593 printk(MYIOC_s_ERR_FMT "slave_alloc kzalloc(%zd) FAILED!\n",
e80b002b 1594 ioc->name, sizeof(VirtDevice));
0c33b27d
CH
1595 return -ENOMEM;
1596 }
c7c82987 1597 starget = scsi_target(sdev);
a69de507 1598 vdevice->vtarget = starget->hostdata;
0c33b27d 1599
e8bf3941 1600 if (sdev->channel == MPTSAS_RAID_CHANNEL)
816aa907 1601 goto out;
816aa907 1602
c7c82987 1603 rphy = dev_to_rphy(sdev->sdev_target->dev.parent);
e80b002b
EM
1604 mutex_lock(&ioc->sas_topology_mutex);
1605 list_for_each_entry(p, &ioc->sas_topology, list) {
0c33b27d 1606 for (i = 0; i < p->num_phys; i++) {
547f9a21
EM
1607 if (p->phy_info[i].attached.sas_address !=
1608 rphy->identify.sas_address)
1609 continue;
a69de507 1610 vdevice->lun = sdev->lun;
547f9a21
EM
1611 /*
1612 * Exposing hidden raid components
1613 */
e80b002b 1614 if (mptscsih_is_phys_disk(ioc,
793955f5
EM
1615 p->phy_info[i].attached.channel,
1616 p->phy_info[i].attached.id))
547f9a21 1617 sdev->no_uld_attach = 1;
e80b002b 1618 mutex_unlock(&ioc->sas_topology_mutex);
547f9a21 1619 goto out;
0c33b27d
CH
1620 }
1621 }
e80b002b 1622 mutex_unlock(&ioc->sas_topology_mutex);
0c33b27d 1623
a69de507 1624 kfree(vdevice);
23f236ed 1625 return -ENXIO;
0c33b27d
CH
1626
1627 out:
a69de507
EM
1628 vdevice->vtarget->num_luns++;
1629 sdev->hostdata = vdevice;
0c33b27d
CH
1630 return 0;
1631}
1632
547f9a21
EM
1633static int
1634mptsas_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
9a28f49a 1635{
7b5a65b9
KD
1636 MPT_SCSI_HOST *hd;
1637 MPT_ADAPTER *ioc;
a69de507 1638 VirtDevice *vdevice = SCpnt->device->hostdata;
7d3eecf7 1639
a69de507 1640 if (!vdevice || !vdevice->vtarget || vdevice->vtarget->deleted) {
547f9a21
EM
1641 SCpnt->result = DID_NO_CONNECT << 16;
1642 done(SCpnt);
1643 return 0;
7d3eecf7 1644 }
547f9a21 1645
7b5a65b9
KD
1646 hd = shost_priv(SCpnt->device->host);
1647 ioc = hd->ioc;
1648
1649 if (ioc->sas_discovery_quiesce_io)
1650 return SCSI_MLQUEUE_HOST_BUSY;
1651
793955f5
EM
1652// scsi_print_command(SCpnt);
1653
547f9a21 1654 return mptscsih_qcmd(SCpnt,done);
9a28f49a
CH
1655}
1656
547f9a21 1657
0c33b27d 1658static struct scsi_host_template mptsas_driver_template = {
f78496da 1659 .module = THIS_MODULE,
0c33b27d
CH
1660 .proc_name = "mptsas",
1661 .proc_info = mptscsih_proc_info,
1662 .name = "MPT SPI Host",
1663 .info = mptscsih_info,
547f9a21
EM
1664 .queuecommand = mptsas_qcmd,
1665 .target_alloc = mptsas_target_alloc,
0c33b27d 1666 .slave_alloc = mptsas_slave_alloc,
f013db32 1667 .slave_configure = mptsas_slave_configure,
547f9a21
EM
1668 .target_destroy = mptsas_target_destroy,
1669 .slave_destroy = mptscsih_slave_destroy,
0c33b27d
CH
1670 .change_queue_depth = mptscsih_change_queue_depth,
1671 .eh_abort_handler = mptscsih_abort,
1672 .eh_device_reset_handler = mptscsih_dev_reset,
1673 .eh_bus_reset_handler = mptscsih_bus_reset,
1674 .eh_host_reset_handler = mptscsih_host_reset,
1675 .bios_param = mptscsih_bios_param,
1676 .can_queue = MPT_FC_CAN_QUEUE,
1677 .this_id = -1,
1678 .sg_tablesize = MPT_SCSI_SG_DEPTH,
1679 .max_sectors = 8192,
1680 .cmd_per_lun = 7,
1681 .use_clustering = ENABLE_CLUSTERING,
edb9068d 1682 .shost_attrs = mptscsih_host_attrs,
0c33b27d
CH
1683};
1684
b5141128 1685static int mptsas_get_linkerrors(struct sas_phy *phy)
0c33b27d 1686{
b5141128
CH
1687 MPT_ADAPTER *ioc = phy_to_ioc(phy);
1688 ConfigExtendedPageHeader_t hdr;
1689 CONFIGPARMS cfg;
1690 SasPhyPage1_t *buffer;
1691 dma_addr_t dma_handle;
1692 int error;
0c33b27d 1693
f4ad7b58
JB
1694 /* FIXME: only have link errors on local phys */
1695 if (!scsi_is_sas_phy_local(phy))
1696 return -EINVAL;
1697
b5141128
CH
1698 hdr.PageVersion = MPI_SASPHY1_PAGEVERSION;
1699 hdr.ExtPageLength = 0;
1700 hdr.PageNumber = 1 /* page number 1*/;
1701 hdr.Reserved1 = 0;
1702 hdr.Reserved2 = 0;
1703 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1704 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
0c33b27d 1705
b5141128
CH
1706 cfg.cfghdr.ehdr = &hdr;
1707 cfg.physAddr = -1;
1708 cfg.pageAddr = phy->identify.phy_identifier;
1709 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1710 cfg.dir = 0; /* read */
1711 cfg.timeout = 10;
0c33b27d 1712
b5141128
CH
1713 error = mpt_config(ioc, &cfg);
1714 if (error)
1715 return error;
1716 if (!hdr.ExtPageLength)
1717 return -ENXIO;
0c33b27d 1718
b5141128
CH
1719 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1720 &dma_handle);
1721 if (!buffer)
1722 return -ENOMEM;
0c33b27d 1723
b5141128
CH
1724 cfg.physAddr = dma_handle;
1725 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1726
1727 error = mpt_config(ioc, &cfg);
1728 if (error)
1729 goto out_free_consistent;
1730
d6ecdd63 1731 mptsas_print_phy_pg1(ioc, buffer);
b5141128
CH
1732
1733 phy->invalid_dword_count = le32_to_cpu(buffer->InvalidDwordCount);
1734 phy->running_disparity_error_count =
1735 le32_to_cpu(buffer->RunningDisparityErrorCount);
1736 phy->loss_of_dword_sync_count =
1737 le32_to_cpu(buffer->LossDwordSynchCount);
1738 phy->phy_reset_problem_count =
1739 le32_to_cpu(buffer->PhyResetProblemCount);
1740
1741 out_free_consistent:
1742 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1743 buffer, dma_handle);
1744 return error;
0c33b27d
CH
1745}
1746
da4fa655
CH
1747static int mptsas_mgmt_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req,
1748 MPT_FRAME_HDR *reply)
1749{
f0f09d3b 1750 ioc->sas_mgmt.status |= MPT_MGMT_STATUS_COMMAND_GOOD;
da4fa655 1751 if (reply != NULL) {
f0f09d3b 1752 ioc->sas_mgmt.status |= MPT_MGMT_STATUS_RF_VALID;
da4fa655
CH
1753 memcpy(ioc->sas_mgmt.reply, reply,
1754 min(ioc->reply_sz, 4 * reply->u.reply.MsgLength));
1755 }
1756 complete(&ioc->sas_mgmt.done);
1757 return 1;
1758}
1759
1760static int mptsas_phy_reset(struct sas_phy *phy, int hard_reset)
1761{
1762 MPT_ADAPTER *ioc = phy_to_ioc(phy);
1763 SasIoUnitControlRequest_t *req;
1764 SasIoUnitControlReply_t *reply;
1765 MPT_FRAME_HDR *mf;
1766 MPIHeader_t *hdr;
1767 unsigned long timeleft;
1768 int error = -ERESTARTSYS;
1769
f4ad7b58
JB
1770 /* FIXME: fusion doesn't allow non-local phy reset */
1771 if (!scsi_is_sas_phy_local(phy))
1772 return -EINVAL;
1773
da4fa655
CH
1774 /* not implemented for expanders */
1775 if (phy->identify.target_port_protocols & SAS_PROTOCOL_SMP)
1776 return -ENXIO;
1777
eeb846ce 1778 if (mutex_lock_interruptible(&ioc->sas_mgmt.mutex))
da4fa655
CH
1779 goto out;
1780
1781 mf = mpt_get_msg_frame(mptsasMgmtCtx, ioc);
1782 if (!mf) {
1783 error = -ENOMEM;
1784 goto out_unlock;
1785 }
1786
1787 hdr = (MPIHeader_t *) mf;
1788 req = (SasIoUnitControlRequest_t *)mf;
1789 memset(req, 0, sizeof(SasIoUnitControlRequest_t));
1790 req->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL;
1791 req->MsgContext = hdr->MsgContext;
1792 req->Operation = hard_reset ?
1793 MPI_SAS_OP_PHY_HARD_RESET : MPI_SAS_OP_PHY_LINK_RESET;
1794 req->PhyNum = phy->identify.phy_identifier;
1795
1796 mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf);
1797
1798 timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done,
1799 10 * HZ);
1800 if (!timeleft) {
1801 /* On timeout reset the board */
1802 mpt_free_msg_frame(ioc, mf);
1803 mpt_HardResetHandler(ioc, CAN_SLEEP);
1804 error = -ETIMEDOUT;
1805 goto out_unlock;
1806 }
1807
1808 /* a reply frame is expected */
1809 if ((ioc->sas_mgmt.status &
f0f09d3b 1810 MPT_MGMT_STATUS_RF_VALID) == 0) {
da4fa655
CH
1811 error = -ENXIO;
1812 goto out_unlock;
1813 }
1814
1815 /* process the completed Reply Message Frame */
1816 reply = (SasIoUnitControlReply_t *)ioc->sas_mgmt.reply;
1817 if (reply->IOCStatus != MPI_IOCSTATUS_SUCCESS) {
29dd3609 1818 printk(MYIOC_s_INFO_FMT "%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",
cadbd4a5 1819 ioc->name, __func__, reply->IOCStatus, reply->IOCLogInfo);
da4fa655
CH
1820 error = -ENXIO;
1821 goto out_unlock;
1822 }
1823
1824 error = 0;
1825
1826 out_unlock:
eeb846ce 1827 mutex_unlock(&ioc->sas_mgmt.mutex);
da4fa655
CH
1828 out:
1829 return error;
1830}
0c33b27d 1831
e3094447
CH
1832static int
1833mptsas_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier)
1834{
1835 MPT_ADAPTER *ioc = rphy_to_ioc(rphy);
1836 int i, error;
1837 struct mptsas_portinfo *p;
1838 struct mptsas_enclosure enclosure_info;
1839 u64 enclosure_handle;
1840
1841 mutex_lock(&ioc->sas_topology_mutex);
1842 list_for_each_entry(p, &ioc->sas_topology, list) {
1843 for (i = 0; i < p->num_phys; i++) {
1844 if (p->phy_info[i].attached.sas_address ==
1845 rphy->identify.sas_address) {
1846 enclosure_handle = p->phy_info[i].
1847 attached.handle_enclosure;
1848 goto found_info;
1849 }
1850 }
1851 }
1852 mutex_unlock(&ioc->sas_topology_mutex);
1853 return -ENXIO;
1854
1855 found_info:
1856 mutex_unlock(&ioc->sas_topology_mutex);
1857 memset(&enclosure_info, 0, sizeof(struct mptsas_enclosure));
52435430 1858 error = mptsas_sas_enclosure_pg0(ioc, &enclosure_info,
e3094447
CH
1859 (MPI_SAS_ENCLOS_PGAD_FORM_HANDLE <<
1860 MPI_SAS_ENCLOS_PGAD_FORM_SHIFT), enclosure_handle);
1861 if (!error)
1862 *identifier = enclosure_info.enclosure_logical_id;
1863 return error;
1864}
1865
1866static int
1867mptsas_get_bay_identifier(struct sas_rphy *rphy)
1868{
1869 MPT_ADAPTER *ioc = rphy_to_ioc(rphy);
1870 struct mptsas_portinfo *p;
1871 int i, rc;
1872
1873 mutex_lock(&ioc->sas_topology_mutex);
1874 list_for_each_entry(p, &ioc->sas_topology, list) {
1875 for (i = 0; i < p->num_phys; i++) {
1876 if (p->phy_info[i].attached.sas_address ==
1877 rphy->identify.sas_address) {
1878 rc = p->phy_info[i].attached.slot;
1879 goto out;
1880 }
1881 }
1882 }
1883 rc = -ENXIO;
1884 out:
1885 mutex_unlock(&ioc->sas_topology_mutex);
1886 return rc;
1887}
1888
159e36fe
FT
1889static int mptsas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
1890 struct request *req)
1891{
1892 MPT_ADAPTER *ioc = ((MPT_SCSI_HOST *) shost->hostdata)->ioc;
1893 MPT_FRAME_HDR *mf;
1894 SmpPassthroughRequest_t *smpreq;
1895 struct request *rsp = req->next_rq;
1896 int ret;
1897 int flagsLength;
1898 unsigned long timeleft;
1899 char *psge;
1900 dma_addr_t dma_addr_in = 0;
1901 dma_addr_t dma_addr_out = 0;
1902 u64 sas_address = 0;
1903
1904 if (!rsp) {
29dd3609 1905 printk(MYIOC_s_ERR_FMT "%s: the smp response space is missing\n",
cadbd4a5 1906 ioc->name, __func__);
159e36fe
FT
1907 return -EINVAL;
1908 }
1909
1910 /* do we need to support multiple segments? */
1911 if (req->bio->bi_vcnt > 1 || rsp->bio->bi_vcnt > 1) {
29dd3609 1912 printk(MYIOC_s_ERR_FMT "%s: multiple segments req %u %u, rsp %u %u\n",
cadbd4a5 1913 ioc->name, __func__, req->bio->bi_vcnt, req->data_len,
29dd3609 1914 rsp->bio->bi_vcnt, rsp->data_len);
159e36fe
FT
1915 return -EINVAL;
1916 }
1917
1918 ret = mutex_lock_interruptible(&ioc->sas_mgmt.mutex);
1919 if (ret)
1920 goto out;
1921
1922 mf = mpt_get_msg_frame(mptsasMgmtCtx, ioc);
1923 if (!mf) {
1924 ret = -ENOMEM;
1925 goto out_unlock;
1926 }
1927
1928 smpreq = (SmpPassthroughRequest_t *)mf;
1929 memset(smpreq, 0, sizeof(*smpreq));
1930
1931 smpreq->RequestDataLength = cpu_to_le16(req->data_len - 4);
1932 smpreq->Function = MPI_FUNCTION_SMP_PASSTHROUGH;
1933
1934 if (rphy)
1935 sas_address = rphy->identify.sas_address;
1936 else {
1937 struct mptsas_portinfo *port_info;
1938
1939 mutex_lock(&ioc->sas_topology_mutex);
f9c34022 1940 port_info = ioc->hba_port_info;
159e36fe
FT
1941 if (port_info && port_info->phy_info)
1942 sas_address =
1943 port_info->phy_info[0].phy->identify.sas_address;
1944 mutex_unlock(&ioc->sas_topology_mutex);
1945 }
1946
1947 *((u64 *)&smpreq->SASAddress) = cpu_to_le64(sas_address);
1948
1949 psge = (char *)
1950 (((int *) mf) + (offsetof(SmpPassthroughRequest_t, SGL) / 4));
1951
1952 /* request */
1953 flagsLength = (MPI_SGE_FLAGS_SIMPLE_ELEMENT |
1954 MPI_SGE_FLAGS_END_OF_BUFFER |
14d0f0b0
KD
1955 MPI_SGE_FLAGS_DIRECTION)
1956 << MPI_SGE_FLAGS_SHIFT;
159e36fe
FT
1957 flagsLength |= (req->data_len - 4);
1958
1959 dma_addr_out = pci_map_single(ioc->pcidev, bio_data(req->bio),
1960 req->data_len, PCI_DMA_BIDIRECTIONAL);
1961 if (!dma_addr_out)
1962 goto put_mf;
14d0f0b0 1963 ioc->add_sge(psge, flagsLength, dma_addr_out);
159e36fe
FT
1964 psge += (sizeof(u32) + sizeof(dma_addr_t));
1965
1966 /* response */
1967 flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ;
1968 flagsLength |= rsp->data_len + 4;
1969 dma_addr_in = pci_map_single(ioc->pcidev, bio_data(rsp->bio),
1970 rsp->data_len, PCI_DMA_BIDIRECTIONAL);
1971 if (!dma_addr_in)
1972 goto unmap;
14d0f0b0 1973 ioc->add_sge(psge, flagsLength, dma_addr_in);
159e36fe
FT
1974
1975 mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf);
1976
1977 timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done, 10 * HZ);
1978 if (!timeleft) {
cadbd4a5 1979 printk(MYIOC_s_ERR_FMT "%s: smp timeout!\n", ioc->name, __func__);
159e36fe
FT
1980 /* On timeout reset the board */
1981 mpt_HardResetHandler(ioc, CAN_SLEEP);
1982 ret = -ETIMEDOUT;
1983 goto unmap;
1984 }
1985 mf = NULL;
1986
f0f09d3b 1987 if (ioc->sas_mgmt.status & MPT_MGMT_STATUS_RF_VALID) {
159e36fe
FT
1988 SmpPassthroughReply_t *smprep;
1989
1990 smprep = (SmpPassthroughReply_t *)ioc->sas_mgmt.reply;
1991 memcpy(req->sense, smprep, sizeof(*smprep));
1992 req->sense_len = sizeof(*smprep);
38b3167f
FT
1993 req->data_len = 0;
1994 rsp->data_len -= smprep->ResponseDataLength;
159e36fe 1995 } else {
29dd3609 1996 printk(MYIOC_s_ERR_FMT "%s: smp passthru reply failed to be returned\n",
cadbd4a5 1997 ioc->name, __func__);
159e36fe
FT
1998 ret = -ENXIO;
1999 }
2000unmap:
2001 if (dma_addr_out)
2002 pci_unmap_single(ioc->pcidev, dma_addr_out, req->data_len,
2003 PCI_DMA_BIDIRECTIONAL);
2004 if (dma_addr_in)
2005 pci_unmap_single(ioc->pcidev, dma_addr_in, rsp->data_len,
2006 PCI_DMA_BIDIRECTIONAL);
2007put_mf:
2008 if (mf)
2009 mpt_free_msg_frame(ioc, mf);
2010out_unlock:
2011 mutex_unlock(&ioc->sas_mgmt.mutex);
2012out:
2013 return ret;
2014}
2015
b5141128
CH
2016static struct sas_function_template mptsas_transport_functions = {
2017 .get_linkerrors = mptsas_get_linkerrors,
e3094447
CH
2018 .get_enclosure_identifier = mptsas_get_enclosure_identifier,
2019 .get_bay_identifier = mptsas_get_bay_identifier,
da4fa655 2020 .phy_reset = mptsas_phy_reset,
159e36fe 2021 .smp_handler = mptsas_smp_handler,
b5141128
CH
2022};
2023
2024static struct scsi_transport_template *mptsas_transport_template;
0c33b27d
CH
2025
2026static int
2027mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
2028{
2029 ConfigExtendedPageHeader_t hdr;
2030 CONFIGPARMS cfg;
2031 SasIOUnitPage0_t *buffer;
2032 dma_addr_t dma_handle;
2033 int error, i;
2034
2035 hdr.PageVersion = MPI_SASIOUNITPAGE0_PAGEVERSION;
2036 hdr.ExtPageLength = 0;
2037 hdr.PageNumber = 0;
2038 hdr.Reserved1 = 0;
2039 hdr.Reserved2 = 0;
2040 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
2041 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
2042
2043 cfg.cfghdr.ehdr = &hdr;
2044 cfg.physAddr = -1;
2045 cfg.pageAddr = 0;
2046 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
2047 cfg.dir = 0; /* read */
2048 cfg.timeout = 10;
2049
2050 error = mpt_config(ioc, &cfg);
2051 if (error)
2052 goto out;
2053 if (!hdr.ExtPageLength) {
2054 error = -ENXIO;
2055 goto out;
2056 }
2057
2058 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2059 &dma_handle);
2060 if (!buffer) {
2061 error = -ENOMEM;
2062 goto out;
2063 }
2064
2065 cfg.physAddr = dma_handle;
2066 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
2067
2068 error = mpt_config(ioc, &cfg);
2069 if (error)
2070 goto out_free_consistent;
2071
2072 port_info->num_phys = buffer->NumPhys;
2073 port_info->phy_info = kcalloc(port_info->num_phys,
547f9a21 2074 sizeof(*port_info->phy_info),GFP_KERNEL);
0c33b27d
CH
2075 if (!port_info->phy_info) {
2076 error = -ENOMEM;
2077 goto out_free_consistent;
2078 }
2079
edb9068d
PS
2080 ioc->nvdata_version_persistent =
2081 le16_to_cpu(buffer->NvdataVersionPersistent);
2082 ioc->nvdata_version_default =
2083 le16_to_cpu(buffer->NvdataVersionDefault);
2084
0c33b27d 2085 for (i = 0; i < port_info->num_phys; i++) {
d6ecdd63 2086 mptsas_print_phy_data(ioc, &buffer->PhyData[i]);
0c33b27d
CH
2087 port_info->phy_info[i].phy_id = i;
2088 port_info->phy_info[i].port_id =
2089 buffer->PhyData[i].Port;
2090 port_info->phy_info[i].negotiated_link_rate =
2091 buffer->PhyData[i].NegotiatedLinkRate;
547f9a21 2092 port_info->phy_info[i].portinfo = port_info;
2ecce492
EM
2093 port_info->phy_info[i].handle =
2094 le16_to_cpu(buffer->PhyData[i].ControllerDevHandle);
0c33b27d
CH
2095 }
2096
2097 out_free_consistent:
2098 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2099 buffer, dma_handle);
2100 out:
2101 return error;
2102}
2103
edb9068d
PS
2104static int
2105mptsas_sas_io_unit_pg1(MPT_ADAPTER *ioc)
2106{
2107 ConfigExtendedPageHeader_t hdr;
2108 CONFIGPARMS cfg;
2109 SasIOUnitPage1_t *buffer;
2110 dma_addr_t dma_handle;
2111 int error;
2112 u16 device_missing_delay;
2113
2114 memset(&hdr, 0, sizeof(ConfigExtendedPageHeader_t));
2115 memset(&cfg, 0, sizeof(CONFIGPARMS));
2116
2117 cfg.cfghdr.ehdr = &hdr;
2118 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
2119 cfg.timeout = 10;
2120 cfg.cfghdr.ehdr->PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
2121 cfg.cfghdr.ehdr->ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
2122 cfg.cfghdr.ehdr->PageVersion = MPI_SASIOUNITPAGE1_PAGEVERSION;
2123 cfg.cfghdr.ehdr->PageNumber = 1;
2124
2125 error = mpt_config(ioc, &cfg);
2126 if (error)
2127 goto out;
2128 if (!hdr.ExtPageLength) {
2129 error = -ENXIO;
2130 goto out;
2131 }
2132
2133 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2134 &dma_handle);
2135 if (!buffer) {
2136 error = -ENOMEM;
2137 goto out;
2138 }
2139
2140 cfg.physAddr = dma_handle;
2141 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
2142
2143 error = mpt_config(ioc, &cfg);
2144 if (error)
2145 goto out_free_consistent;
2146
2147 ioc->io_missing_delay =
2148 le16_to_cpu(buffer->IODeviceMissingDelay);
2149 device_missing_delay = le16_to_cpu(buffer->ReportDeviceMissingDelay);
2150 ioc->device_missing_delay = (device_missing_delay & MPI_SAS_IOUNIT1_REPORT_MISSING_UNIT_16) ?
2151 (device_missing_delay & MPI_SAS_IOUNIT1_REPORT_MISSING_TIMEOUT_MASK) * 16 :
2152 device_missing_delay & MPI_SAS_IOUNIT1_REPORT_MISSING_TIMEOUT_MASK;
2153
2154 out_free_consistent:
2155 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2156 buffer, dma_handle);
2157 out:
2158 return error;
2159}
2160
0c33b27d
CH
2161static int
2162mptsas_sas_phy_pg0(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
2163 u32 form, u32 form_specific)
2164{
2165 ConfigExtendedPageHeader_t hdr;
2166 CONFIGPARMS cfg;
2167 SasPhyPage0_t *buffer;
2168 dma_addr_t dma_handle;
2169 int error;
2170
2171 hdr.PageVersion = MPI_SASPHY0_PAGEVERSION;
2172 hdr.ExtPageLength = 0;
2173 hdr.PageNumber = 0;
2174 hdr.Reserved1 = 0;
2175 hdr.Reserved2 = 0;
2176 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
2177 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
2178
2179 cfg.cfghdr.ehdr = &hdr;
2180 cfg.dir = 0; /* read */
2181 cfg.timeout = 10;
2182
2183 /* Get Phy Pg 0 for each Phy. */
2184 cfg.physAddr = -1;
2185 cfg.pageAddr = form + form_specific;
2186 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
2187
2188 error = mpt_config(ioc, &cfg);
2189 if (error)
2190 goto out;
2191
2192 if (!hdr.ExtPageLength) {
2193 error = -ENXIO;
2194 goto out;
2195 }
2196
2197 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2198 &dma_handle);
2199 if (!buffer) {
2200 error = -ENOMEM;
2201 goto out;
2202 }
2203
2204 cfg.physAddr = dma_handle;
2205 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
2206
2207 error = mpt_config(ioc, &cfg);
2208 if (error)
2209 goto out_free_consistent;
2210
d6ecdd63 2211 mptsas_print_phy_pg0(ioc, buffer);
0c33b27d
CH
2212
2213 phy_info->hw_link_rate = buffer->HwLinkRate;
2214 phy_info->programmed_link_rate = buffer->ProgrammedLinkRate;
2215 phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle);
2216 phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle);
2217
2218 out_free_consistent:
2219 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2220 buffer, dma_handle);
2221 out:
2222 return error;
2223}
2224
2225static int
2226mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info,
2227 u32 form, u32 form_specific)
2228{
2229 ConfigExtendedPageHeader_t hdr;
2230 CONFIGPARMS cfg;
2231 SasDevicePage0_t *buffer;
2232 dma_addr_t dma_handle;
2233 __le64 sas_address;
bd23e94c
ME
2234 int error=0;
2235
2236 if (ioc->sas_discovery_runtime &&
2237 mptsas_is_end_device(device_info))
2238 goto out;
0c33b27d
CH
2239
2240 hdr.PageVersion = MPI_SASDEVICE0_PAGEVERSION;
2241 hdr.ExtPageLength = 0;
2242 hdr.PageNumber = 0;
2243 hdr.Reserved1 = 0;
2244 hdr.Reserved2 = 0;
2245 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
2246 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE;
2247
2248 cfg.cfghdr.ehdr = &hdr;
2249 cfg.pageAddr = form + form_specific;
2250 cfg.physAddr = -1;
2251 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
2252 cfg.dir = 0; /* read */
2253 cfg.timeout = 10;
2254
db9c9174 2255 memset(device_info, 0, sizeof(struct mptsas_devinfo));
0c33b27d
CH
2256 error = mpt_config(ioc, &cfg);
2257 if (error)
2258 goto out;
2259 if (!hdr.ExtPageLength) {
2260 error = -ENXIO;
2261 goto out;
2262 }
2263
2264 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2265 &dma_handle);
2266 if (!buffer) {
2267 error = -ENOMEM;
2268 goto out;
2269 }
2270
2271 cfg.physAddr = dma_handle;
2272 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
2273
2274 error = mpt_config(ioc, &cfg);
2275 if (error)
2276 goto out_free_consistent;
2277
d6ecdd63 2278 mptsas_print_device_pg0(ioc, buffer);
0c33b27d
CH
2279
2280 device_info->handle = le16_to_cpu(buffer->DevHandle);
c73787ee 2281 device_info->handle_parent = le16_to_cpu(buffer->ParentDevHandle);
e3094447
CH
2282 device_info->handle_enclosure =
2283 le16_to_cpu(buffer->EnclosureHandle);
2284 device_info->slot = le16_to_cpu(buffer->Slot);
0c33b27d
CH
2285 device_info->phy_id = buffer->PhyNum;
2286 device_info->port_id = buffer->PhysicalPort;
9a28f49a 2287 device_info->id = buffer->TargetID;
b506ade9 2288 device_info->phys_disk_num = ~0;
9a28f49a 2289 device_info->channel = buffer->Bus;
0c33b27d
CH
2290 memcpy(&sas_address, &buffer->SASAddress, sizeof(__le64));
2291 device_info->sas_address = le64_to_cpu(sas_address);
2292 device_info->device_info =
2293 le32_to_cpu(buffer->DeviceInfo);
2294
2295 out_free_consistent:
2296 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2297 buffer, dma_handle);
2298 out:
2299 return error;
2300}
2301
2302static int
2303mptsas_sas_expander_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info,
2304 u32 form, u32 form_specific)
2305{
2306 ConfigExtendedPageHeader_t hdr;
2307 CONFIGPARMS cfg;
2308 SasExpanderPage0_t *buffer;
2309 dma_addr_t dma_handle;
547f9a21 2310 int i, error;
0c33b27d
CH
2311
2312 hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION;
2313 hdr.ExtPageLength = 0;
2314 hdr.PageNumber = 0;
2315 hdr.Reserved1 = 0;
2316 hdr.Reserved2 = 0;
2317 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
2318 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
2319
2320 cfg.cfghdr.ehdr = &hdr;
2321 cfg.physAddr = -1;
2322 cfg.pageAddr = form + form_specific;
2323 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
2324 cfg.dir = 0; /* read */
2325 cfg.timeout = 10;
2326
db9c9174 2327 memset(port_info, 0, sizeof(struct mptsas_portinfo));
0c33b27d
CH
2328 error = mpt_config(ioc, &cfg);
2329 if (error)
2330 goto out;
2331
2332 if (!hdr.ExtPageLength) {
2333 error = -ENXIO;
2334 goto out;
2335 }
2336
2337 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2338 &dma_handle);
2339 if (!buffer) {
2340 error = -ENOMEM;
2341 goto out;
2342 }
2343
2344 cfg.physAddr = dma_handle;
2345 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
2346
2347 error = mpt_config(ioc, &cfg);
2348 if (error)
2349 goto out_free_consistent;
2350
51f39eae
KO
2351 if (!buffer->NumPhys) {
2352 error = -ENODEV;
2353 goto out_free_consistent;
2354 }
2355
0c33b27d
CH
2356 /* save config data */
2357 port_info->num_phys = buffer->NumPhys;
0c33b27d 2358 port_info->phy_info = kcalloc(port_info->num_phys,
547f9a21 2359 sizeof(*port_info->phy_info),GFP_KERNEL);
0c33b27d
CH
2360 if (!port_info->phy_info) {
2361 error = -ENOMEM;
2362 goto out_free_consistent;
2363 }
2364
2ecce492 2365 for (i = 0; i < port_info->num_phys; i++) {
547f9a21 2366 port_info->phy_info[i].portinfo = port_info;
2ecce492
EM
2367 port_info->phy_info[i].handle =
2368 le16_to_cpu(buffer->DevHandle);
2369 }
547f9a21 2370
0c33b27d
CH
2371 out_free_consistent:
2372 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2373 buffer, dma_handle);
2374 out:
2375 return error;
2376}
2377
2378static int
2379mptsas_sas_expander_pg1(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
2380 u32 form, u32 form_specific)
2381{
2382 ConfigExtendedPageHeader_t hdr;
2383 CONFIGPARMS cfg;
2384 SasExpanderPage1_t *buffer;
2385 dma_addr_t dma_handle;
bd23e94c
ME
2386 int error=0;
2387
2388 if (ioc->sas_discovery_runtime &&
2389 mptsas_is_end_device(&phy_info->attached))
2390 goto out;
0c33b27d
CH
2391
2392 hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION;
2393 hdr.ExtPageLength = 0;
2394 hdr.PageNumber = 1;
2395 hdr.Reserved1 = 0;
2396 hdr.Reserved2 = 0;
2397 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
2398 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
2399
2400 cfg.cfghdr.ehdr = &hdr;
2401 cfg.physAddr = -1;
2402 cfg.pageAddr = form + form_specific;
2403 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
2404 cfg.dir = 0; /* read */
2405 cfg.timeout = 10;
2406
2407 error = mpt_config(ioc, &cfg);
2408 if (error)
2409 goto out;
2410
2411 if (!hdr.ExtPageLength) {
2412 error = -ENXIO;
2413 goto out;
2414 }
2415
2416 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2417 &dma_handle);
2418 if (!buffer) {
2419 error = -ENOMEM;
2420 goto out;
2421 }
2422
2423 cfg.physAddr = dma_handle;
2424 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
2425
2426 error = mpt_config(ioc, &cfg);
2427 if (error)
2428 goto out_free_consistent;
2429
2430
d6ecdd63 2431 mptsas_print_expander_pg1(ioc, buffer);
0c33b27d
CH
2432
2433 /* save config data */
024358ee 2434 phy_info->phy_id = buffer->PhyIdentifier;
0c33b27d
CH
2435 phy_info->port_id = buffer->PhysicalPort;
2436 phy_info->negotiated_link_rate = buffer->NegotiatedLinkRate;
2437 phy_info->programmed_link_rate = buffer->ProgrammedLinkRate;
2438 phy_info->hw_link_rate = buffer->HwLinkRate;
2439 phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle);
2440 phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle);
2441
0c33b27d
CH
2442 out_free_consistent:
2443 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2444 buffer, dma_handle);
2445 out:
2446 return error;
2447}
2448
2449static void
2450mptsas_parse_device_info(struct sas_identify *identify,
2451 struct mptsas_devinfo *device_info)
2452{
2453 u16 protocols;
2454
2455 identify->sas_address = device_info->sas_address;
2456 identify->phy_identifier = device_info->phy_id;
2457
2458 /*
2459 * Fill in Phy Initiator Port Protocol.
2460 * Bits 6:3, more than one bit can be set, fall through cases.
2461 */
2462 protocols = device_info->device_info & 0x78;
2463 identify->initiator_port_protocols = 0;
2464 if (protocols & MPI_SAS_DEVICE_INFO_SSP_INITIATOR)
2465 identify->initiator_port_protocols |= SAS_PROTOCOL_SSP;
2466 if (protocols & MPI_SAS_DEVICE_INFO_STP_INITIATOR)
2467 identify->initiator_port_protocols |= SAS_PROTOCOL_STP;
2468 if (protocols & MPI_SAS_DEVICE_INFO_SMP_INITIATOR)
2469 identify->initiator_port_protocols |= SAS_PROTOCOL_SMP;
2470 if (protocols & MPI_SAS_DEVICE_INFO_SATA_HOST)
2471 identify->initiator_port_protocols |= SAS_PROTOCOL_SATA;
2472
2473 /*
2474 * Fill in Phy Target Port Protocol.
2475 * Bits 10:7, more than one bit can be set, fall through cases.
2476 */
2477 protocols = device_info->device_info & 0x780;
2478 identify->target_port_protocols = 0;
2479 if (protocols & MPI_SAS_DEVICE_INFO_SSP_TARGET)
2480 identify->target_port_protocols |= SAS_PROTOCOL_SSP;
2481 if (protocols & MPI_SAS_DEVICE_INFO_STP_TARGET)
2482 identify->target_port_protocols |= SAS_PROTOCOL_STP;
2483 if (protocols & MPI_SAS_DEVICE_INFO_SMP_TARGET)
2484 identify->target_port_protocols |= SAS_PROTOCOL_SMP;
2485 if (protocols & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
2486 identify->target_port_protocols |= SAS_PROTOCOL_SATA;
2487
2488 /*
2489 * Fill in Attached device type.
2490 */
2491 switch (device_info->device_info &
2492 MPI_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) {
2493 case MPI_SAS_DEVICE_INFO_NO_DEVICE:
2494 identify->device_type = SAS_PHY_UNUSED;
2495 break;
2496 case MPI_SAS_DEVICE_INFO_END_DEVICE:
2497 identify->device_type = SAS_END_DEVICE;
2498 break;
2499 case MPI_SAS_DEVICE_INFO_EDGE_EXPANDER:
2500 identify->device_type = SAS_EDGE_EXPANDER_DEVICE;
2501 break;
2502 case MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER:
2503 identify->device_type = SAS_FANOUT_EXPANDER_DEVICE;
2504 break;
2505 }
2506}
2507
2508static int mptsas_probe_one_phy(struct device *dev,
ac01bbbd 2509 struct mptsas_phyinfo *phy_info, int index, int local)
0c33b27d 2510{
e6b2d76a 2511 MPT_ADAPTER *ioc;
9a28f49a 2512 struct sas_phy *phy;
547f9a21
EM
2513 struct sas_port *port;
2514 int error = 0;
0c33b27d 2515
547f9a21
EM
2516 if (!dev) {
2517 error = -ENODEV;
2518 goto out;
2519 }
e6b2d76a
ME
2520
2521 if (!phy_info->phy) {
2522 phy = sas_phy_alloc(dev, index);
547f9a21
EM
2523 if (!phy) {
2524 error = -ENOMEM;
2525 goto out;
2526 }
e6b2d76a
ME
2527 } else
2528 phy = phy_info->phy;
0c33b27d 2529
9a28f49a 2530 mptsas_parse_device_info(&phy->identify, &phy_info->identify);
0c33b27d
CH
2531
2532 /*
2533 * Set Negotiated link rate.
2534 */
2535 switch (phy_info->negotiated_link_rate) {
2536 case MPI_SAS_IOUNIT0_RATE_PHY_DISABLED:
9a28f49a 2537 phy->negotiated_linkrate = SAS_PHY_DISABLED;
0c33b27d
CH
2538 break;
2539 case MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION:
9a28f49a 2540 phy->negotiated_linkrate = SAS_LINK_RATE_FAILED;
0c33b27d
CH
2541 break;
2542 case MPI_SAS_IOUNIT0_RATE_1_5:
9a28f49a 2543 phy->negotiated_linkrate = SAS_LINK_RATE_1_5_GBPS;
0c33b27d
CH
2544 break;
2545 case MPI_SAS_IOUNIT0_RATE_3_0:
9a28f49a 2546 phy->negotiated_linkrate = SAS_LINK_RATE_3_0_GBPS;
0c33b27d
CH
2547 break;
2548 case MPI_SAS_IOUNIT0_RATE_SATA_OOB_COMPLETE:
2549 case MPI_SAS_IOUNIT0_RATE_UNKNOWN:
2550 default:
9a28f49a 2551 phy->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN;
0c33b27d
CH
2552 break;
2553 }
2554
2555 /*
2556 * Set Max hardware link rate.
2557 */
2558 switch (phy_info->hw_link_rate & MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
2559 case MPI_SAS_PHY0_HWRATE_MAX_RATE_1_5:
9a28f49a 2560 phy->maximum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
0c33b27d
CH
2561 break;
2562 case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
9a28f49a 2563 phy->maximum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
0c33b27d
CH
2564 break;
2565 default:
2566 break;
2567 }
2568
2569 /*
2570 * Set Max programmed link rate.
2571 */
2572 switch (phy_info->programmed_link_rate &
2573 MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
2574 case MPI_SAS_PHY0_PRATE_MAX_RATE_1_5:
9a28f49a 2575 phy->maximum_linkrate = SAS_LINK_RATE_1_5_GBPS;
0c33b27d
CH
2576 break;
2577 case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
9a28f49a 2578 phy->maximum_linkrate = SAS_LINK_RATE_3_0_GBPS;
0c33b27d
CH
2579 break;
2580 default:
2581 break;
2582 }
2583
2584 /*
2585 * Set Min hardware link rate.
2586 */
2587 switch (phy_info->hw_link_rate & MPI_SAS_PHY0_HWRATE_MIN_RATE_MASK) {
2588 case MPI_SAS_PHY0_HWRATE_MIN_RATE_1_5:
9a28f49a 2589 phy->minimum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
0c33b27d
CH
2590 break;
2591 case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
9a28f49a 2592 phy->minimum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
0c33b27d
CH
2593 break;
2594 default:
2595 break;
2596 }
2597
2598 /*
2599 * Set Min programmed link rate.
2600 */
2601 switch (phy_info->programmed_link_rate &
2602 MPI_SAS_PHY0_PRATE_MIN_RATE_MASK) {
2603 case MPI_SAS_PHY0_PRATE_MIN_RATE_1_5:
9a28f49a 2604 phy->minimum_linkrate = SAS_LINK_RATE_1_5_GBPS;
0c33b27d
CH
2605 break;
2606 case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
9a28f49a 2607 phy->minimum_linkrate = SAS_LINK_RATE_3_0_GBPS;
0c33b27d
CH
2608 break;
2609 default:
2610 break;
2611 }
2612
e6b2d76a 2613 if (!phy_info->phy) {
ac01bbbd 2614
e6b2d76a
ME
2615 error = sas_phy_add(phy);
2616 if (error) {
2617 sas_phy_free(phy);
547f9a21 2618 goto out;
e6b2d76a
ME
2619 }
2620 phy_info->phy = phy;
0c33b27d
CH
2621 }
2622
547f9a21
EM
2623 if (!phy_info->attached.handle ||
2624 !phy_info->port_details)
2625 goto out;
2626
2627 port = mptsas_get_port(phy_info);
2628 ioc = phy_to_ioc(phy_info->phy);
2629
2630 if (phy_info->sas_port_add_phy) {
2631
2632 if (!port) {
dc22f16d 2633 port = sas_port_alloc_num(dev);
547f9a21
EM
2634 if (!port) {
2635 error = -ENOMEM;
2636 goto out;
2637 }
2638 error = sas_port_add(port);
2639 if (error) {
d6ecdd63 2640 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
547f9a21 2641 "%s: exit at line=%d\n", ioc->name,
cadbd4a5 2642 __func__, __LINE__));
547f9a21
EM
2643 goto out;
2644 }
d6ecdd63 2645 mptsas_set_port(ioc, phy_info, port);
29dd3609 2646 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT
dc22f16d 2647 "sas_port_alloc: port=%p dev=%p port_id=%d\n",
29dd3609 2648 ioc->name, port, dev, port->port_identifier));
547f9a21 2649 }
29dd3609
EM
2650 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "sas_port_add_phy: phy_id=%d\n",
2651 ioc->name, phy_info->phy_id));
547f9a21
EM
2652 sas_port_add_phy(port, phy_info->phy);
2653 phy_info->sas_port_add_phy = 0;
2654 }
2655
2656 if (!mptsas_get_rphy(phy_info) && port && !port->rphy) {
e6b2d76a 2657
0c33b27d 2658 struct sas_rphy *rphy;
2686de27 2659 struct device *parent;
f013db32 2660 struct sas_identify identify;
0c33b27d 2661
2686de27 2662 parent = dev->parent->parent;
e6b2d76a
ME
2663 /*
2664 * Let the hotplug_work thread handle processing
2665 * the adding/removing of devices that occur
2666 * after start of day.
2667 */
2668 if (ioc->sas_discovery_runtime &&
2669 mptsas_is_end_device(&phy_info->attached))
547f9a21 2670 goto out;
e6b2d76a 2671
f013db32 2672 mptsas_parse_device_info(&identify, &phy_info->attached);
2686de27
JB
2673 if (scsi_is_host_device(parent)) {
2674 struct mptsas_portinfo *port_info;
2675 int i;
2676
f9c34022 2677 port_info = ioc->hba_port_info;
2686de27
JB
2678
2679 for (i = 0; i < port_info->num_phys; i++)
2680 if (port_info->phy_info[i].identify.sas_address ==
0c269e6d
JB
2681 identify.sas_address) {
2682 sas_port_mark_backlink(port);
2686de27 2683 goto out;
0c269e6d 2684 }
2686de27
JB
2685
2686 } else if (scsi_is_sas_rphy(parent)) {
2687 struct sas_rphy *parent_rphy = dev_to_rphy(parent);
2688 if (identify.sas_address ==
0c269e6d
JB
2689 parent_rphy->identify.sas_address) {
2690 sas_port_mark_backlink(port);
2686de27 2691 goto out;
0c269e6d 2692 }
2686de27
JB
2693 }
2694
f013db32
JB
2695 switch (identify.device_type) {
2696 case SAS_END_DEVICE:
547f9a21 2697 rphy = sas_end_device_alloc(port);
f013db32
JB
2698 break;
2699 case SAS_EDGE_EXPANDER_DEVICE:
2700 case SAS_FANOUT_EXPANDER_DEVICE:
547f9a21 2701 rphy = sas_expander_alloc(port, identify.device_type);
f013db32
JB
2702 break;
2703 default:
2704 rphy = NULL;
2705 break;
2706 }
547f9a21 2707 if (!rphy) {
d6ecdd63 2708 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
547f9a21 2709 "%s: exit at line=%d\n", ioc->name,
cadbd4a5 2710 __func__, __LINE__));
547f9a21
EM
2711 goto out;
2712 }
0c33b27d 2713
f013db32 2714 rphy->identify = identify;
0c33b27d
CH
2715 error = sas_rphy_add(rphy);
2716 if (error) {
d6ecdd63 2717 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
547f9a21 2718 "%s: exit at line=%d\n", ioc->name,
cadbd4a5 2719 __func__, __LINE__));
0c33b27d 2720 sas_rphy_free(rphy);
547f9a21 2721 goto out;
0c33b27d 2722 }
d6ecdd63 2723 mptsas_set_rphy(ioc, phy_info, rphy);
0c33b27d
CH
2724 }
2725
547f9a21
EM
2726 out:
2727 return error;
0c33b27d
CH
2728}
2729
2730static int
e6b2d76a 2731mptsas_probe_hba_phys(MPT_ADAPTER *ioc)
0c33b27d 2732{
e6b2d76a 2733 struct mptsas_portinfo *port_info, *hba;
0c33b27d
CH
2734 int error = -ENOMEM, i;
2735
f9c34022 2736 hba = kzalloc(sizeof(struct mptsas_portinfo), GFP_KERNEL);
e6b2d76a 2737 if (! hba)
0c33b27d 2738 goto out;
0c33b27d 2739
e6b2d76a 2740 error = mptsas_sas_io_unit_pg0(ioc, hba);
0c33b27d
CH
2741 if (error)
2742 goto out_free_port_info;
2743
edb9068d 2744 mptsas_sas_io_unit_pg1(ioc);
9a28f49a 2745 mutex_lock(&ioc->sas_topology_mutex);
f9c34022 2746 port_info = ioc->hba_port_info;
e6b2d76a 2747 if (!port_info) {
f9c34022
KD
2748 ioc->hba_port_info = port_info = hba;
2749 ioc->hba_port_num_phy = port_info->num_phys;
e6b2d76a
ME
2750 list_add_tail(&port_info->list, &ioc->sas_topology);
2751 } else {
2ecce492 2752 for (i = 0; i < hba->num_phys; i++) {
e6b2d76a
ME
2753 port_info->phy_info[i].negotiated_link_rate =
2754 hba->phy_info[i].negotiated_link_rate;
2ecce492
EM
2755 port_info->phy_info[i].handle =
2756 hba->phy_info[i].handle;
2757 port_info->phy_info[i].port_id =
2758 hba->phy_info[i].port_id;
2759 }
547f9a21 2760 kfree(hba->phy_info);
e6b2d76a
ME
2761 kfree(hba);
2762 hba = NULL;
2763 }
9a28f49a 2764 mutex_unlock(&ioc->sas_topology_mutex);
f9c34022
KD
2765#if defined(CPQ_CIM)
2766 ioc->num_ports = port_info->num_phys;
2767#endif
0c33b27d
CH
2768 for (i = 0; i < port_info->num_phys; i++) {
2769 mptsas_sas_phy_pg0(ioc, &port_info->phy_info[i],
2770 (MPI_SAS_PHY_PGAD_FORM_PHY_NUMBER <<
2771 MPI_SAS_PHY_PGAD_FORM_SHIFT), i);
f9c34022
KD
2772 port_info->phy_info[i].identify.handle =
2773 port_info->phy_info[i].handle;
0c33b27d 2774 mptsas_sas_device_pg0(ioc, &port_info->phy_info[i].identify,
2ecce492
EM
2775 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
2776 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
f9c34022
KD
2777 port_info->phy_info[i].identify.handle);
2778 if (!ioc->hba_port_sas_addr)
2779 ioc->hba_port_sas_addr =
2780 port_info->phy_info[i].identify.sas_address;
024358ee 2781 port_info->phy_info[i].identify.phy_id =
2ecce492 2782 port_info->phy_info[i].phy_id = i;
547f9a21 2783 if (port_info->phy_info[i].attached.handle)
0c33b27d
CH
2784 mptsas_sas_device_pg0(ioc,
2785 &port_info->phy_info[i].attached,
2786 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
2787 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
2788 port_info->phy_info[i].attached.handle);
547f9a21 2789 }
0c33b27d 2790
547f9a21
EM
2791 mptsas_setup_wide_ports(ioc, port_info);
2792
2793 for (i = 0; i < port_info->num_phys; i++, ioc->sas_index++)
0c33b27d 2794 mptsas_probe_one_phy(&ioc->sh->shost_gendev,
e6b2d76a 2795 &port_info->phy_info[i], ioc->sas_index, 1);
0c33b27d
CH
2796
2797 return 0;
2798
2799 out_free_port_info:
547f9a21 2800 kfree(hba);
0c33b27d
CH
2801 out:
2802 return error;
2803}
2804
f9c34022
KD
2805static void
2806mptsas_expander_refresh(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
0c33b27d 2807{
f9c34022
KD
2808 struct mptsas_portinfo *parent;
2809 struct device *parent_dev;
2810 struct sas_rphy *rphy;
2811 int i;
2812 u64 sas_address; /* expander sas address */
2813 u32 handle;
9a28f49a 2814
f9c34022
KD
2815 handle = port_info->phy_info[0].handle;
2816 sas_address = port_info->phy_info[0].identify.sas_address;
0c33b27d 2817 for (i = 0; i < port_info->num_phys; i++) {
0c33b27d 2818 mptsas_sas_expander_pg1(ioc, &port_info->phy_info[i],
f9c34022
KD
2819 (MPI_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM <<
2820 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), (i << 16) + handle);
0c33b27d 2821
f9c34022
KD
2822 mptsas_sas_device_pg0(ioc,
2823 &port_info->phy_info[i].identify,
2824 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
2825 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
2826 port_info->phy_info[i].identify.handle);
2827 port_info->phy_info[i].identify.phy_id =
2828 port_info->phy_info[i].phy_id;
0c33b27d
CH
2829
2830 if (port_info->phy_info[i].attached.handle) {
2831 mptsas_sas_device_pg0(ioc,
f9c34022
KD
2832 &port_info->phy_info[i].attached,
2833 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
2834 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
2835 port_info->phy_info[i].attached.handle);
db9c9174
ME
2836 port_info->phy_info[i].attached.phy_id =
2837 port_info->phy_info[i].phy_id;
0c33b27d 2838 }
547f9a21 2839 }
0c33b27d 2840
f9c34022
KD
2841 mutex_lock(&ioc->sas_topology_mutex);
2842 parent = mptsas_find_portinfo_by_handle(ioc,
2843 port_info->phy_info[0].identify.handle_parent);
2844 if (!parent) {
9a28f49a 2845 mutex_unlock(&ioc->sas_topology_mutex);
f9c34022
KD
2846 return;
2847 }
2848 for (i = 0, parent_dev = NULL; i < parent->num_phys && !parent_dev;
2849 i++) {
2850 if (parent->phy_info[i].attached.sas_address == sas_address) {
2851 rphy = mptsas_get_rphy(&parent->phy_info[i]);
2852 parent_dev = &rphy->dev;
2853 }
547f9a21 2854 }
f9c34022 2855 mutex_unlock(&ioc->sas_topology_mutex);
547f9a21
EM
2856
2857 mptsas_setup_wide_ports(ioc, port_info);
547f9a21 2858 for (i = 0; i < port_info->num_phys; i++, ioc->sas_index++)
f9c34022 2859 mptsas_probe_one_phy(parent_dev, &port_info->phy_info[i],
e6b2d76a 2860 ioc->sas_index, 0);
f9c34022 2861}
0c33b27d 2862
f9c34022
KD
2863static void
2864mptsas_expander_event_add(MPT_ADAPTER *ioc,
2865 MpiEventDataSasExpanderStatusChange_t *expander_data)
2866{
2867 struct mptsas_portinfo *port_info;
2868 int i;
2869 __le64 sas_address;
0c33b27d 2870
f9c34022
KD
2871 port_info = kzalloc(sizeof(struct mptsas_portinfo), GFP_KERNEL);
2872 if (!port_info)
2873 BUG();
2874 port_info->num_phys = (expander_data->NumPhys) ?
2875 expander_data->NumPhys : 1;
2876 port_info->phy_info = kcalloc(port_info->num_phys,
2877 sizeof(struct mptsas_phyinfo), GFP_KERNEL);
2878 if (!port_info->phy_info)
2879 BUG();
2880 memcpy(&sas_address, &expander_data->SASAddress, sizeof(__le64));
2881 for (i = 0; i < port_info->num_phys; i++) {
2882 port_info->phy_info[i].portinfo = port_info;
2883 port_info->phy_info[i].handle =
2884 le16_to_cpu(expander_data->DevHandle);
2885 port_info->phy_info[i].identify.sas_address =
2886 le64_to_cpu(sas_address);
2887 port_info->phy_info[i].identify.handle_parent =
2888 le16_to_cpu(expander_data->ParentDevHandle);
e6b2d76a 2889 }
f9c34022
KD
2890
2891 mutex_lock(&ioc->sas_topology_mutex);
2892 list_add_tail(&port_info->list, &ioc->sas_topology);
2893 mutex_unlock(&ioc->sas_topology_mutex);
2894
2895 printk(MYIOC_s_INFO_FMT "add expander: num_phys %d, "
2896 "sas_addr (0x%llx)\n", ioc->name, port_info->num_phys,
2897 (unsigned long long)sas_address);
2898
2899 mptsas_expander_refresh(ioc, port_info);
0c33b27d
CH
2900}
2901
f9c34022
KD
2902/**
2903 * mptsas_delete_expander_siblings - remove siblings attached to expander
2904 * @ioc: Pointer to MPT_ADAPTER structure
2905 * @parent: the parent port_info object
2906 * @expander: the expander port_info object
2907 **/
e6b2d76a 2908static void
f9c34022
KD
2909mptsas_delete_expander_siblings(MPT_ADAPTER *ioc, struct mptsas_portinfo
2910 *parent, struct mptsas_portinfo *expander)
e6b2d76a 2911{
547f9a21 2912 struct mptsas_phyinfo *phy_info;
f9c34022
KD
2913 struct mptsas_portinfo *port_info;
2914 struct sas_rphy *rphy;
e6b2d76a
ME
2915 int i;
2916
f9c34022
KD
2917 phy_info = expander->phy_info;
2918 for (i = 0; i < expander->num_phys; i++, phy_info++) {
2919 rphy = mptsas_get_rphy(phy_info);
2920 if (!rphy)
2921 continue;
2922 if (rphy->identify.device_type == SAS_END_DEVICE)
2923 mptsas_del_end_device(ioc, phy_info);
2924 }
e6b2d76a 2925
f9c34022
KD
2926 phy_info = expander->phy_info;
2927 for (i = 0; i < expander->num_phys; i++, phy_info++) {
2928 rphy = mptsas_get_rphy(phy_info);
2929 if (!rphy)
e6b2d76a 2930 continue;
f9c34022
KD
2931 if (rphy->identify.device_type ==
2932 MPI_SAS_DEVICE_INFO_EDGE_EXPANDER ||
2933 rphy->identify.device_type ==
2934 MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER) {
2935 port_info = mptsas_find_portinfo_by_sas_address(ioc,
2936 rphy->identify.sas_address);
2937 if (!port_info)
2938 continue;
2939 if (port_info == parent) /* backlink rphy */
2940 continue;
2941 /*
2942 Delete this expander even if the expdevpage is exists
2943 because the parent expander is already deleted
2944 */
2945 mptsas_expander_delete(ioc, port_info, 1);
2946 }
2947 }
2948}
e6b2d76a 2949
e6b2d76a 2950
f9c34022
KD
2951/**
2952 * mptsas_expander_delete - remove this expander
2953 * @ioc: Pointer to MPT_ADAPTER structure
2954 * @port_info: expander port_info struct
2955 * @force: Flag to forcefully delete the expander
2956 *
2957 **/
e6b2d76a 2958
f9c34022
KD
2959static void mptsas_expander_delete(MPT_ADAPTER *ioc,
2960 struct mptsas_portinfo *port_info, u8 force)
2961{
e6b2d76a 2962
f9c34022
KD
2963 struct mptsas_portinfo *parent;
2964 int i;
2965 u64 expander_sas_address;
2966 struct mptsas_phyinfo *phy_info;
2967 struct mptsas_portinfo buffer;
2968 struct mptsas_portinfo_details *port_details;
2969 struct sas_port *port;
547f9a21 2970
f9c34022
KD
2971 if (!port_info)
2972 return;
547f9a21 2973
f9c34022
KD
2974 /* see if expander is still there before deleting */
2975 mptsas_sas_expander_pg0(ioc, &buffer,
2976 (MPI_SAS_EXPAND_PGAD_FORM_HANDLE <<
2977 MPI_SAS_EXPAND_PGAD_FORM_SHIFT),
2978 port_info->phy_info[0].identify.handle);
547f9a21 2979
f9c34022 2980 if (buffer.num_phys) {
547f9a21 2981 kfree(buffer.phy_info);
f9c34022
KD
2982 if (!force)
2983 return;
e6b2d76a 2984 }
f9c34022
KD
2985
2986
2987 /*
2988 * Obtain the port_info instance to the parent port
2989 */
2990 port_details = NULL;
2991 expander_sas_address =
2992 port_info->phy_info[0].identify.sas_address;
2993 parent = mptsas_find_portinfo_by_handle(ioc,
2994 port_info->phy_info[0].identify.handle_parent);
2995 mptsas_delete_expander_siblings(ioc, parent, port_info);
2996 if (!parent)
2997 goto out;
2998
2999 /*
3000 * Delete rphys in the parent that point
3001 * to this expander.
3002 */
3003 phy_info = parent->phy_info;
3004 port = NULL;
3005 for (i = 0; i < parent->num_phys; i++, phy_info++) {
3006 if (!phy_info->phy)
3007 continue;
3008 if (phy_info->attached.sas_address !=
3009 expander_sas_address)
3010 continue;
3011 if (!port) {
3012 port = mptsas_get_port(phy_info);
3013 port_details = phy_info->port_details;
3014 }
3015 dev_printk(KERN_DEBUG, &phy_info->phy->dev,
3016 MYIOC_s_FMT "delete phy %d, phy-obj (0x%p)\n", ioc->name,
3017 phy_info->phy_id, phy_info->phy);
3018 sas_port_delete_phy(port, phy_info->phy);
3019 }
3020 if (port) {
3021 dev_printk(KERN_DEBUG, &port->dev,
3022 MYIOC_s_FMT "delete port %d, sas_addr (0x%llx)\n",
3023 ioc->name, port->port_identifier,
3024 (unsigned long long)expander_sas_address);
3025 sas_port_delete(port);
3026 mptsas_port_delete(ioc, port_details);
3027 }
3028 out:
3029
3030 printk(MYIOC_s_INFO_FMT "delete expander: num_phys %d, "
3031 "sas_addr (0x%llx)\n", ioc->name, port_info->num_phys,
3032 (unsigned long long)expander_sas_address);
3033
3034 /*
3035 * free link
3036 */
3037 list_del(&port_info->list);
3038 kfree(port_info->phy_info);
3039 kfree(port_info);
e6b2d76a
ME
3040}
3041
f9c34022
KD
3042
3043/**
3044 * mptsas_send_expander_event - expanders events
3045 * @ioc: Pointer to MPT_ADAPTER structure
3046 * @expander_data: event data
3047 *
3048 *
3049 * This function handles adding, removing, and refreshing
3050 * device handles within the expander objects.
e6b2d76a 3051 */
0c33b27d 3052static void
f9c34022 3053mptsas_send_expander_event(struct fw_event_work *fw_event)
0c33b27d 3054{
f9c34022
KD
3055 MPT_ADAPTER *ioc;
3056 MpiEventDataSasExpanderStatusChange_t *expander_data;
3057 struct mptsas_portinfo *port_info;
3058 __le64 sas_address;
f44e5461 3059 int i;
0c33b27d 3060
f9c34022
KD
3061 ioc = fw_event->ioc;
3062 expander_data = (MpiEventDataSasExpanderStatusChange_t *)
3063 fw_event->event_data;
3064 memcpy(&sas_address, &expander_data->SASAddress, sizeof(__le64));
3065 port_info = mptsas_find_portinfo_by_sas_address(ioc, sas_address);
3066
3067 if (expander_data->ReasonCode == MPI_EVENT_SAS_EXP_RC_ADDED) {
3068 if (port_info) {
3069 for (i = 0; i < port_info->num_phys; i++) {
3070 port_info->phy_info[i].portinfo = port_info;
3071 port_info->phy_info[i].handle =
3072 le16_to_cpu(expander_data->DevHandle);
3073 port_info->phy_info[i].identify.sas_address =
3074 le64_to_cpu(sas_address);
3075 port_info->phy_info[i].identify.handle_parent =
3076 le16_to_cpu(expander_data->ParentDevHandle);
3077 }
3078 mptsas_expander_refresh(ioc, port_info);
3079 } else if (!port_info && expander_data->NumPhys)
3080 mptsas_expander_event_add(ioc, expander_data);
3081 } else if (expander_data->ReasonCode ==
3082 MPI_EVENT_SAS_EXP_RC_NOT_RESPONDING)
3083 mptsas_expander_delete(ioc, port_info, 0);
3084
3085 mptsas_free_fw_event(ioc, fw_event);
3086}
3087
3088
3089/**
3090 * mptsas_expander_add -
3091 * @ioc: Pointer to MPT_ADAPTER structure
3092 * @handle:
3093 *
3094 */
3095struct mptsas_portinfo *
3096mptsas_expander_add(MPT_ADAPTER *ioc, u16 handle)
3097{
3098 struct mptsas_portinfo buffer, *port_info;
3099 int i;
3100
3101 if ((mptsas_sas_expander_pg0(ioc, &buffer,
3102 (MPI_SAS_EXPAND_PGAD_FORM_HANDLE <<
3103 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), handle)))
3104 return NULL;
3105
3106 port_info = kzalloc(sizeof(struct mptsas_portinfo), GFP_ATOMIC);
3107 if (!port_info) {
3108 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
3109 "%s: exit at line=%d\n", ioc->name,
3110 __func__, __LINE__));
3111 return NULL;
3112 }
3113 port_info->num_phys = buffer.num_phys;
3114 port_info->phy_info = buffer.phy_info;
3115 for (i = 0; i < port_info->num_phys; i++)
3116 port_info->phy_info[i].portinfo = port_info;
3117 mutex_lock(&ioc->sas_topology_mutex);
3118 list_add_tail(&port_info->list, &ioc->sas_topology);
3119 mutex_unlock(&ioc->sas_topology_mutex);
3120 printk(MYIOC_s_INFO_FMT "add expander: num_phys %d, "
3121 "sas_addr (0x%llx)\n", ioc->name, port_info->num_phys,
3122 (unsigned long long)buffer.phy_info[0].identify.sas_address);
3123 mptsas_expander_refresh(ioc, port_info);
3124 return port_info;
3125}
3126
3127static void
3128mptsas_send_link_status_event(struct fw_event_work *fw_event)
3129{
3130 MPT_ADAPTER *ioc;
3131 MpiEventDataSasPhyLinkStatus_t *link_data;
3132 struct mptsas_portinfo *port_info;
3133 struct mptsas_phyinfo *phy_info = NULL;
3134 __le64 sas_address;
3135 u8 phy_num;
3136 u8 link_rate;
3137
3138 ioc = fw_event->ioc;
3139 link_data = (MpiEventDataSasPhyLinkStatus_t *)fw_event->event_data;
3140
3141 memcpy(&sas_address, &link_data->SASAddress, sizeof(__le64));
3142 sas_address = le64_to_cpu(sas_address);
3143 link_rate = link_data->LinkRates >> 4;
3144 phy_num = link_data->PhyNum;
3145
3146 port_info = mptsas_find_portinfo_by_sas_address(ioc, sas_address);
3147 if (port_info) {
3148 phy_info = &port_info->phy_info[phy_num];
3149 if (phy_info)
3150 phy_info->negotiated_link_rate = link_rate;
3151 }
3152
3153 if (link_rate == MPI_SAS_IOUNIT0_RATE_1_5 ||
3154 link_rate == MPI_SAS_IOUNIT0_RATE_3_0) {
3155
3156 if (!port_info)
3157 goto out;
3158
3159 if (port_info == ioc->hba_port_info)
3160 mptsas_probe_hba_phys(ioc);
3161 else
3162 mptsas_expander_refresh(ioc, port_info);
3163 } else if (phy_info && phy_info->phy) {
3164 if (link_rate == MPI_SAS_IOUNIT0_RATE_PHY_DISABLED)
3165 phy_info->phy->negotiated_linkrate =
3166 SAS_PHY_DISABLED;
3167 else if (link_rate ==
3168 MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION)
3169 phy_info->phy->negotiated_linkrate =
3170 SAS_LINK_RATE_FAILED;
3171 else
3172 phy_info->phy->negotiated_linkrate =
3173 SAS_LINK_RATE_UNKNOWN;
f44e5461
ME
3174 }
3175 out:
f9c34022 3176 mptsas_free_fw_event(ioc, fw_event);
e6b2d76a
ME
3177}
3178
f9c34022
KD
3179/**
3180 * mptsas_probe_expanders - adding expanders
3181 * @ioc: Pointer to MPT_ADAPTER structure
3182 *
3183 **/
e6b2d76a 3184static void
f9c34022 3185mptsas_probe_expanders(MPT_ADAPTER *ioc)
e6b2d76a 3186{
f9c34022
KD
3187 struct mptsas_portinfo buffer, *port_info;
3188 u32 handle;
3189 int i;
e6b2d76a 3190
f9c34022
KD
3191 handle = 0xFFFF;
3192 while (!mptsas_sas_expander_pg0(ioc, &buffer,
3193 (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE <<
3194 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), handle)) {
3195
3196 handle = buffer.phy_info[0].handle;
3197 port_info = mptsas_find_portinfo_by_sas_address(ioc,
3198 buffer.phy_info[0].identify.sas_address);
3199
3200 if (port_info) {
3201 /* refreshing handles */
3202 for (i = 0; i < buffer.num_phys; i++) {
3203 port_info->phy_info[i].handle = handle;
3204 port_info->phy_info[i].identify.handle_parent =
3205 buffer.phy_info[0].identify.handle_parent;
3206 }
3207 mptsas_expander_refresh(ioc, port_info);
3208 kfree(buffer.phy_info);
3209 continue;
3210 }
3211
3212 port_info = kzalloc(sizeof(struct mptsas_portinfo), GFP_KERNEL);
3213 if (!port_info) {
3214 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
3215 "%s: exit at line=%d\n", ioc->name,
3216 __func__, __LINE__));
3217 return;
3218 }
3219 port_info->num_phys = buffer.num_phys;
3220 port_info->phy_info = buffer.phy_info;
3221 for (i = 0; i < port_info->num_phys; i++)
3222 port_info->phy_info[i].portinfo = port_info;
3223 mutex_lock(&ioc->sas_topology_mutex);
3224 list_add_tail(&port_info->list, &ioc->sas_topology);
3225 mutex_unlock(&ioc->sas_topology_mutex);
3226 printk(MYIOC_s_INFO_FMT "add expander: num_phys %d, "
3227 "sas_addr (0x%llx)\n", ioc->name, port_info->num_phys,
3228 (unsigned long long)buffer.phy_info[0].identify.sas_address);
3229 mptsas_expander_refresh(ioc, port_info);
3230 }
3231}
3232
3233static void
3234mptsas_probe_devices(MPT_ADAPTER *ioc)
3235{
3236 u16 handle;
3237 struct mptsas_devinfo sas_device;
3238 struct mptsas_phyinfo *phy_info;
3239
3240 handle = 0xFFFF;
3241 while (!(mptsas_sas_device_pg0(ioc, &sas_device,
3242 MPI_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE, handle))) {
3243
3244 handle = sas_device.handle;
3245
3246 if ((sas_device.device_info &
3247 (MPI_SAS_DEVICE_INFO_SSP_TARGET |
3248 MPI_SAS_DEVICE_INFO_STP_TARGET |
3249 MPI_SAS_DEVICE_INFO_SATA_DEVICE)) == 0)
3250 continue;
3251
3252 phy_info = mptsas_refreshing_device_handles(ioc, &sas_device);
3253 if (!phy_info)
3254 continue;
3255
3256 if (mptsas_get_rphy(phy_info))
3257 continue;
3258
3259 mptsas_add_end_device(ioc, phy_info);
3260 }
547f9a21
EM
3261}
3262
3263/*
f9c34022 3264 * Start of day discovery
547f9a21
EM
3265 */
3266static void
f9c34022 3267mptsas_scan_sas_topology(MPT_ADAPTER *ioc)
547f9a21 3268{
f9c34022
KD
3269 struct scsi_device *sdev;
3270 int i;
547f9a21 3271
f9c34022
KD
3272 mptsas_probe_hba_phys(ioc);
3273 mptsas_probe_expanders(ioc);
3274 mptsas_probe_devices(ioc);
0c33b27d 3275
f9c34022
KD
3276 /*
3277 Reporting RAID volumes.
3278 */
3279 if (!ioc->ir_firmware || !ioc->raid_data.pIocPg2 ||
3280 !ioc->raid_data.pIocPg2->NumActiveVolumes)
3281 return;
3282 for (i = 0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++) {
3283 sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL,
3284 ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID, 0);
3285 if (sdev) {
3286 scsi_device_put(sdev);
3287 continue;
3288 }
3289 printk(MYIOC_s_INFO_FMT "attaching raid volume, channel %d, "
3290 "id %d\n", ioc->name, MPTSAS_RAID_CHANNEL,
3291 ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID);
3292 scsi_add_device(ioc->sh, MPTSAS_RAID_CHANNEL,
3293 ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID, 0);
3294 }
3295}
3eb0822c 3296
9a28f49a 3297static struct mptsas_phyinfo *
547f9a21 3298mptsas_find_phyinfo_by_sas_address(MPT_ADAPTER *ioc, u64 sas_address)
9a28f49a
CH
3299{
3300 struct mptsas_portinfo *port_info;
9a28f49a 3301 struct mptsas_phyinfo *phy_info = NULL;
547f9a21 3302 int i;
9a28f49a 3303
9a28f49a
CH
3304 mutex_lock(&ioc->sas_topology_mutex);
3305 list_for_each_entry(port_info, &ioc->sas_topology, list) {
3306 for (i = 0; i < port_info->num_phys; i++) {
b506ade9
EM
3307 if (!mptsas_is_end_device(
3308 &port_info->phy_info[i].attached))
3309 continue;
547f9a21
EM
3310 if (port_info->phy_info[i].attached.sas_address
3311 != sas_address)
3312 continue;
b506ade9
EM
3313 phy_info = &port_info->phy_info[i];
3314 break;
3315 }
3316 }
3317 mutex_unlock(&ioc->sas_topology_mutex);
3318 return phy_info;
3319}
3320
9a28f49a
CH
3321
3322static struct mptsas_phyinfo *
b506ade9 3323mptsas_find_phyinfo_by_phys_disk_num(MPT_ADAPTER *ioc, u8 channel, u8 id)
9a28f49a
CH
3324{
3325 struct mptsas_portinfo *port_info;
3326 struct mptsas_phyinfo *phy_info = NULL;
3327 int i;
3328
9a28f49a
CH
3329 mutex_lock(&ioc->sas_topology_mutex);
3330 list_for_each_entry(port_info, &ioc->sas_topology, list) {
547f9a21 3331 for (i = 0; i < port_info->num_phys; i++) {
547f9a21
EM
3332 if (!mptsas_is_end_device(
3333 &port_info->phy_info[i].attached))
3334 continue;
b506ade9
EM
3335 if (port_info->phy_info[i].attached.phys_disk_num == ~0)
3336 continue;
3337 if (port_info->phy_info[i].attached.phys_disk_num != id)
3338 continue;
3339 if (port_info->phy_info[i].attached.channel != channel)
3340 continue;
547f9a21
EM
3341 phy_info = &port_info->phy_info[i];
3342 break;
3343 }
9a28f49a
CH
3344 }
3345 mutex_unlock(&ioc->sas_topology_mutex);
9a28f49a
CH
3346 return phy_info;
3347}
3348
f44e5461
ME
3349static void
3350mptsas_reprobe_lun(struct scsi_device *sdev, void *data)
3351{
f99be43b
EM
3352 int rc;
3353
f44e5461 3354 sdev->no_uld_attach = data ? 1 : 0;
f99be43b 3355 rc = scsi_device_reprobe(sdev);
f44e5461
ME
3356}
3357
3358static void
3359mptsas_reprobe_target(struct scsi_target *starget, int uld_attach)
3360{
3361 starget_for_each_device(starget, uld_attach ? (void *)1 : NULL,
3362 mptsas_reprobe_lun);
3363}
3364
b506ade9
EM
3365static void
3366mptsas_adding_inactive_raid_components(MPT_ADAPTER *ioc, u8 channel, u8 id)
3367{
3368 CONFIGPARMS cfg;
3369 ConfigPageHeader_t hdr;
3370 dma_addr_t dma_handle;
3371 pRaidVolumePage0_t buffer = NULL;
3372 RaidPhysDiskPage0_t phys_disk;
3373 int i;
3eb0822c
KD
3374 struct mptsas_phyinfo *phy_info;
3375 struct mptsas_devinfo sas_device;
b506ade9
EM
3376
3377 memset(&cfg, 0 , sizeof(CONFIGPARMS));
3378 memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
3379 hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME;
3380 cfg.pageAddr = (channel << 8) + id;
3381 cfg.cfghdr.hdr = &hdr;
3382 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
3383
3384 if (mpt_config(ioc, &cfg) != 0)
3385 goto out;
3386
3387 if (!hdr.PageLength)
3388 goto out;
3389
3390 buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4,
3391 &dma_handle);
3392
3393 if (!buffer)
3394 goto out;
3395
3396 cfg.physAddr = dma_handle;
3397 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
3398
3399 if (mpt_config(ioc, &cfg) != 0)
3400 goto out;
3401
3402 if (!(buffer->VolumeStatus.Flags &
3403 MPI_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE))
3404 goto out;
3405
3406 if (!buffer->NumPhysDisks)
3407 goto out;
3408
3409 for (i = 0; i < buffer->NumPhysDisks; i++) {
3410
3411 if (mpt_raid_phys_disk_pg0(ioc,
3412 buffer->PhysDisk[i].PhysDiskNum, &phys_disk) != 0)
3413 continue;
3414
3eb0822c
KD
3415 if (mptsas_sas_device_pg0(ioc, &sas_device,
3416 (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
3417 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
3418 (phys_disk.PhysDiskBus << 8) +
3419 phys_disk.PhysDiskID))
3420 continue;
b506ade9 3421
3eb0822c
KD
3422 phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
3423 sas_device.sas_address);
3424 mptsas_add_end_device(ioc, phy_info);
b506ade9
EM
3425 }
3426
3427 out:
3428 if (buffer)
3429 pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer,
3430 dma_handle);
3431}
e6b2d76a
ME
3432/*
3433 * Work queue thread to handle SAS hotplug events
3434 */
9a28f49a 3435static void
3eb0822c
KD
3436mptsas_hotplug_work(MPT_ADAPTER *ioc, struct fw_event_work *fw_event,
3437 struct mptsas_hotplug_event *hot_plug_info)
9a28f49a 3438{
9a28f49a 3439 struct mptsas_phyinfo *phy_info;
547f9a21 3440 struct scsi_target * starget;
c73787ee 3441 struct mptsas_devinfo sas_device;
f44e5461 3442 VirtTarget *vtarget;
3eb0822c 3443 int i;
9a28f49a 3444
3eb0822c 3445 switch (hot_plug_info->event_type) {
9a28f49a 3446
3eb0822c
KD
3447 case MPTSAS_ADD_PHYSDISK:
3448
3449 if (!ioc->raid_data.pIocPg2)
3450 break;
3451
3452 for (i = 0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++) {
3453 if (ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID ==
3454 hot_plug_info->id) {
3455 printk(MYIOC_s_WARN_FMT "firmware bug: unable "
3456 "to add hidden disk - target_id matchs "
3457 "volume_id\n", ioc->name);
3458 mptsas_free_fw_event(ioc, fw_event);
3459 return;
3460 }
b506ade9 3461 }
3eb0822c 3462 mpt_findImVolumes(ioc);
b506ade9 3463
3eb0822c
KD
3464 case MPTSAS_ADD_DEVICE:
3465 memset(&sas_device, 0, sizeof(struct mptsas_devinfo));
3466 mptsas_sas_device_pg0(ioc, &sas_device,
3467 (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
3468 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
3469 (hot_plug_info->channel << 8) +
3470 hot_plug_info->id);
3471
3472 if (!sas_device.handle)
3473 return;
3474
3475 phy_info = mptsas_refreshing_device_handles(ioc, &sas_device);
b506ade9 3476 if (!phy_info)
3eb0822c 3477 break;
e6b2d76a 3478
3eb0822c
KD
3479 if (mptsas_get_rphy(phy_info))
3480 break;
3481
3482 mptsas_add_end_device(ioc, phy_info);
3483 break;
3484
3485 case MPTSAS_DEL_DEVICE:
3486 phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
3487 hot_plug_info->sas_address);
3488 mptsas_del_end_device(ioc, phy_info);
3489 break;
3490
3491 case MPTSAS_DEL_PHYSDISK:
3492
3493 mpt_findImVolumes(ioc);
3494
3495 phy_info = mptsas_find_phyinfo_by_phys_disk_num(
3496 ioc, hot_plug_info->channel,
3497 hot_plug_info->phys_disk_num);
3498 mptsas_del_end_device(ioc, phy_info);
3499 break;
3500
3501 case MPTSAS_ADD_PHYSDISK_REPROBE:
3502
3503 if (mptsas_sas_device_pg0(ioc, &sas_device,
3504 (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
3505 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
3506 (hot_plug_info->channel << 8) + hot_plug_info->id)) {
d6ecdd63 3507 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
3eb0822c
KD
3508 "%s: fw_id=%d exit at line=%d\n", ioc->name,
3509 __func__, hot_plug_info->id, __LINE__));
b506ade9
EM
3510 break;
3511 }
3eb0822c
KD
3512
3513 phy_info = mptsas_find_phyinfo_by_sas_address(
3514 ioc, sas_device.sas_address);
3515
3516 if (!phy_info) {
d6ecdd63 3517 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
3eb0822c
KD
3518 "%s: fw_id=%d exit at line=%d\n", ioc->name,
3519 __func__, hot_plug_info->id, __LINE__));
9a28f49a 3520 break;
547f9a21 3521 }
3eb0822c
KD
3522
3523 starget = mptsas_get_starget(phy_info);
3524 if (!starget) {
d6ecdd63 3525 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
3eb0822c
KD
3526 "%s: fw_id=%d exit at line=%d\n", ioc->name,
3527 __func__, hot_plug_info->id, __LINE__));
547f9a21
EM
3528 break;
3529 }
b506ade9 3530
3eb0822c
KD
3531 vtarget = starget->hostdata;
3532 if (!vtarget) {
d6ecdd63 3533 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
3eb0822c
KD
3534 "%s: fw_id=%d exit at line=%d\n", ioc->name,
3535 __func__, hot_plug_info->id, __LINE__));
f44e5461 3536 break;
547f9a21
EM
3537 }
3538
3eb0822c 3539 mpt_findImVolumes(ioc);
547f9a21 3540
3eb0822c
KD
3541 starget_printk(KERN_INFO, starget, MYIOC_s_FMT "RAID Hidding: "
3542 "fw_channel=%d, fw_id=%d, physdsk %d, sas_addr 0x%llx\n",
3543 ioc->name, hot_plug_info->channel, hot_plug_info->id,
3544 hot_plug_info->phys_disk_num, (unsigned long long)
3545 sas_device.sas_address);
9a28f49a 3546
3eb0822c
KD
3547 vtarget->id = hot_plug_info->phys_disk_num;
3548 vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT;
3549 phy_info->attached.phys_disk_num = hot_plug_info->phys_disk_num;
3550 mptsas_reprobe_target(starget, 1);
9a28f49a 3551 break;
c73787ee 3552
3eb0822c 3553 case MPTSAS_DEL_PHYSDISK_REPROBE:
bd23e94c 3554
e3094447
CH
3555 if (mptsas_sas_device_pg0(ioc, &sas_device,
3556 (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
b506ade9 3557 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
3eb0822c 3558 (hot_plug_info->channel << 8) + hot_plug_info->id)) {
d6ecdd63 3559 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
3eb0822c
KD
3560 "%s: fw_id=%d exit at line=%d\n",
3561 ioc->name, __func__,
3562 hot_plug_info->id, __LINE__));
e3094447 3563 break;
547f9a21 3564 }
9a28f49a 3565
547f9a21
EM
3566 phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
3567 sas_device.sas_address);
3eb0822c 3568 if (!phy_info) {
d6ecdd63 3569 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
3eb0822c
KD
3570 "%s: fw_id=%d exit at line=%d\n", ioc->name,
3571 __func__, hot_plug_info->id, __LINE__));
547f9a21 3572 break;
e6b2d76a
ME
3573 }
3574
547f9a21 3575 starget = mptsas_get_starget(phy_info);
3eb0822c
KD
3576 if (!starget) {
3577 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
3578 "%s: fw_id=%d exit at line=%d\n", ioc->name,
3579 __func__, hot_plug_info->id, __LINE__));
9a28f49a
CH
3580 break;
3581 }
3582
3eb0822c
KD
3583 vtarget = starget->hostdata;
3584 if (!vtarget) {
d6ecdd63 3585 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
3eb0822c
KD
3586 "%s: fw_id=%d exit at line=%d\n", ioc->name,
3587 __func__, hot_plug_info->id, __LINE__));
f44e5461 3588 break;
547f9a21 3589 }
b506ade9 3590
3eb0822c 3591 if (!(vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT)) {
d6ecdd63 3592 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
3eb0822c
KD
3593 "%s: fw_id=%d exit at line=%d\n", ioc->name,
3594 __func__, hot_plug_info->id, __LINE__));
547f9a21
EM
3595 break;
3596 }
c73787ee 3597
3eb0822c 3598 mpt_findImVolumes(ioc);
9a28f49a 3599
3eb0822c
KD
3600 starget_printk(KERN_INFO, starget, MYIOC_s_FMT "RAID Exposing:"
3601 " fw_channel=%d, fw_id=%d, physdsk %d, sas_addr 0x%llx\n",
3602 ioc->name, hot_plug_info->channel, hot_plug_info->id,
3603 hot_plug_info->phys_disk_num, (unsigned long long)
3604 sas_device.sas_address);
3605
3606 vtarget->tflags &= ~MPT_TARGET_FLAGS_RAID_COMPONENT;
3607 vtarget->id = hot_plug_info->id;
3608 phy_info->attached.phys_disk_num = ~0;
3609 mptsas_reprobe_target(starget, 0);
3610 mptsas_add_device_component_by_fw(ioc,
3611 hot_plug_info->channel, hot_plug_info->id);
9a28f49a 3612 break;
3eb0822c 3613
c73787ee 3614 case MPTSAS_ADD_RAID:
3eb0822c 3615
c73787ee 3616 mpt_findImVolumes(ioc);
3eb0822c
KD
3617 printk(MYIOC_s_INFO_FMT "attaching raid volume, channel %d, "
3618 "id %d\n", ioc->name, MPTSAS_RAID_CHANNEL,
3619 hot_plug_info->id);
3620 scsi_add_device(ioc->sh, MPTSAS_RAID_CHANNEL,
3621 hot_plug_info->id, 0);
c73787ee 3622 break;
3eb0822c 3623
c73787ee 3624 case MPTSAS_DEL_RAID:
3eb0822c 3625
c73787ee 3626 mpt_findImVolumes(ioc);
3eb0822c
KD
3627 printk(MYIOC_s_INFO_FMT "removing raid volume, channel %d, "
3628 "id %d\n", ioc->name, MPTSAS_RAID_CHANNEL,
3629 hot_plug_info->id);
3630 scsi_remove_device(hot_plug_info->sdev);
3631 scsi_device_put(hot_plug_info->sdev);
c73787ee 3632 break;
3eb0822c 3633
b506ade9 3634 case MPTSAS_ADD_INACTIVE_VOLUME:
3eb0822c
KD
3635
3636 mpt_findImVolumes(ioc);
b506ade9 3637 mptsas_adding_inactive_raid_components(ioc,
3eb0822c 3638 hot_plug_info->channel, hot_plug_info->id);
b506ade9 3639 break;
3eb0822c 3640
bd23e94c
ME
3641 default:
3642 break;
9a28f49a
CH
3643 }
3644
3eb0822c 3645 mptsas_free_fw_event(ioc, fw_event);
9a28f49a
CH
3646}
3647
3648static void
3eb0822c 3649mptsas_send_sas_event(struct fw_event_work *fw_event)
9a28f49a 3650{
3eb0822c
KD
3651 MPT_ADAPTER *ioc;
3652 struct mptsas_hotplug_event hot_plug_info;
3653 EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data;
3654 u32 device_info;
3655 u64 sas_address;
3656
3657 ioc = fw_event->ioc;
3658 sas_event_data = (EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)
3659 fw_event->event_data;
3660 device_info = le32_to_cpu(sas_event_data->DeviceInfo);
9a28f49a
CH
3661
3662 if ((device_info &
3eb0822c
KD
3663 (MPI_SAS_DEVICE_INFO_SSP_TARGET |
3664 MPI_SAS_DEVICE_INFO_STP_TARGET |
3665 MPI_SAS_DEVICE_INFO_SATA_DEVICE)) == 0) {
3666 mptsas_free_fw_event(ioc, fw_event);
9a28f49a 3667 return;
3eb0822c
KD
3668 }
3669
3670 if (sas_event_data->ReasonCode ==
3671 MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED) {
3672 mptbase_sas_persist_operation(ioc,
3673 MPI_SAS_OP_CLEAR_NOT_PRESENT);
3674 mptsas_free_fw_event(ioc, fw_event);
3675 return;
3676 }
9a28f49a 3677
4b766471 3678 switch (sas_event_data->ReasonCode) {
4b766471 3679 case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
df9e062a 3680 case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
3eb0822c
KD
3681 memset(&hot_plug_info, 0, sizeof(struct mptsas_hotplug_event));
3682 hot_plug_info.handle = le16_to_cpu(sas_event_data->DevHandle);
3683 hot_plug_info.channel = sas_event_data->Bus;
3684 hot_plug_info.id = sas_event_data->TargetID;
3685 hot_plug_info.phy_id = sas_event_data->PhyNum;
4b766471 3686 memcpy(&sas_address, &sas_event_data->SASAddress,
3eb0822c
KD
3687 sizeof(u64));
3688 hot_plug_info.sas_address = le64_to_cpu(sas_address);
3689 hot_plug_info.device_info = device_info;
4b766471
ME
3690 if (sas_event_data->ReasonCode &
3691 MPI_EVENT_SAS_DEV_STAT_RC_ADDED)
3eb0822c 3692 hot_plug_info.event_type = MPTSAS_ADD_DEVICE;
4b766471 3693 else
3eb0822c
KD
3694 hot_plug_info.event_type = MPTSAS_DEL_DEVICE;
3695 mptsas_hotplug_work(ioc, fw_event, &hot_plug_info);
4b766471 3696 break;
3eb0822c 3697
4b766471 3698 case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED:
3eb0822c
KD
3699 mptbase_sas_persist_operation(ioc,
3700 MPI_SAS_OP_CLEAR_NOT_PRESENT);
3701 mptsas_free_fw_event(ioc, fw_event);
4b766471 3702 break;
3eb0822c 3703
4b766471 3704 case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
3eb0822c 3705 /* TODO */
4b766471 3706 case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
3eb0822c 3707 /* TODO */
4b766471 3708 default:
3eb0822c 3709 mptsas_free_fw_event(ioc, fw_event);
4b766471 3710 break;
9a28f49a 3711 }
9a28f49a 3712}
3eb0822c 3713
c73787ee 3714static void
3eb0822c 3715mptsas_send_raid_event(struct fw_event_work *fw_event)
c73787ee 3716{
3eb0822c
KD
3717 MPT_ADAPTER *ioc;
3718 EVENT_DATA_RAID *raid_event_data;
3719 struct mptsas_hotplug_event hot_plug_info;
3720 int status;
3721 int state;
3722 struct scsi_device *sdev = NULL;
3723 VirtDevice *vdevice = NULL;
3724 RaidPhysDiskPage0_t phys_disk;
3725
3726 ioc = fw_event->ioc;
3727 raid_event_data = (EVENT_DATA_RAID *)fw_event->event_data;
3728 status = le32_to_cpu(raid_event_data->SettingsStatus);
3729 state = (status >> 8) & 0xff;
3730
3731 memset(&hot_plug_info, 0, sizeof(struct mptsas_hotplug_event));
3732 hot_plug_info.id = raid_event_data->VolumeID;
3733 hot_plug_info.channel = raid_event_data->VolumeBus;
3734 hot_plug_info.phys_disk_num = raid_event_data->PhysDiskNum;
3735
3736 if (raid_event_data->ReasonCode == MPI_EVENT_RAID_RC_VOLUME_DELETED ||
3737 raid_event_data->ReasonCode == MPI_EVENT_RAID_RC_VOLUME_CREATED ||
3738 raid_event_data->ReasonCode ==
3739 MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED) {
3740 sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL,
3741 hot_plug_info.id, 0);
3742 hot_plug_info.sdev = sdev;
3743 if (sdev)
3744 vdevice = sdev->hostdata;
c73787ee
ME
3745 }
3746
3eb0822c
KD
3747 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Entering %s: "
3748 "ReasonCode=%02x\n", ioc->name, __func__,
3749 raid_event_data->ReasonCode));
c73787ee
ME
3750
3751 switch (raid_event_data->ReasonCode) {
3752 case MPI_EVENT_RAID_RC_PHYSDISK_DELETED:
3eb0822c 3753 hot_plug_info.event_type = MPTSAS_DEL_PHYSDISK_REPROBE;
c73787ee
ME
3754 break;
3755 case MPI_EVENT_RAID_RC_PHYSDISK_CREATED:
3eb0822c 3756 hot_plug_info.event_type = MPTSAS_ADD_PHYSDISK_REPROBE;
c73787ee 3757 break;
bd23e94c
ME
3758 case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED:
3759 switch (state) {
3760 case MPI_PD_STATE_ONLINE:
b506ade9 3761 case MPI_PD_STATE_NOT_COMPATIBLE:
3eb0822c
KD
3762 mpt_raid_phys_disk_pg0(ioc,
3763 raid_event_data->PhysDiskNum, &phys_disk);
3764 hot_plug_info.id = phys_disk.PhysDiskID;
3765 hot_plug_info.channel = phys_disk.PhysDiskBus;
3766 hot_plug_info.event_type = MPTSAS_ADD_PHYSDISK;
bd23e94c 3767 break;
3eb0822c 3768 case MPI_PD_STATE_FAILED:
bd23e94c 3769 case MPI_PD_STATE_MISSING:
bd23e94c
ME
3770 case MPI_PD_STATE_OFFLINE_AT_HOST_REQUEST:
3771 case MPI_PD_STATE_FAILED_AT_HOST_REQUEST:
3772 case MPI_PD_STATE_OFFLINE_FOR_ANOTHER_REASON:
3eb0822c 3773 hot_plug_info.event_type = MPTSAS_DEL_PHYSDISK;
bd23e94c
ME
3774 break;
3775 default:
3776 break;
3777 }
3778 break;
c73787ee 3779 case MPI_EVENT_RAID_RC_VOLUME_DELETED:
3eb0822c
KD
3780 if (!sdev)
3781 break;
3782 vdevice->vtarget->deleted = 1; /* block IO */
3783 hot_plug_info.event_type = MPTSAS_DEL_RAID;
c73787ee
ME
3784 break;
3785 case MPI_EVENT_RAID_RC_VOLUME_CREATED:
3eb0822c
KD
3786 if (sdev) {
3787 scsi_device_put(sdev);
3788 break;
3789 }
3790 hot_plug_info.event_type = MPTSAS_ADD_RAID;
c73787ee
ME
3791 break;
3792 case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED:
3eb0822c
KD
3793 if (!(status & MPI_RAIDVOL0_STATUS_FLAG_ENABLED)) {
3794 if (!sdev)
3795 break;
3796 vdevice->vtarget->deleted = 1; /* block IO */
3797 hot_plug_info.event_type = MPTSAS_DEL_RAID;
3798 break;
3799 }
bd23e94c
ME
3800 switch (state) {
3801 case MPI_RAIDVOL0_STATUS_STATE_FAILED:
3802 case MPI_RAIDVOL0_STATUS_STATE_MISSING:
3eb0822c
KD
3803 if (!sdev)
3804 break;
3805 vdevice->vtarget->deleted = 1; /* block IO */
3806 hot_plug_info.event_type = MPTSAS_DEL_RAID;
bd23e94c
ME
3807 break;
3808 case MPI_RAIDVOL0_STATUS_STATE_OPTIMAL:
3809 case MPI_RAIDVOL0_STATUS_STATE_DEGRADED:
3eb0822c
KD
3810 if (sdev) {
3811 scsi_device_put(sdev);
3812 break;
3813 }
3814 hot_plug_info.event_type = MPTSAS_ADD_RAID;
bd23e94c
ME
3815 break;
3816 default:
3817 break;
3818 }
c73787ee
ME
3819 break;
3820 default:
3821 break;
3822 }
3eb0822c
KD
3823
3824 if (hot_plug_info.event_type != MPTSAS_IGNORE_EVENT)
3825 mptsas_hotplug_work(ioc, fw_event, &hot_plug_info);
3826 else
3827 mptsas_free_fw_event(ioc, fw_event);
c73787ee
ME
3828}
3829
b506ade9
EM
3830/*
3831 * mptsas_send_ir2_event - handle exposing hidden disk when
3832 * an inactive raid volume is added
3833 *
3834 * @ioc: Pointer to MPT_ADAPTER structure
3835 * @ir2_data
3836 *
3837 */
3838static void
3eb0822c 3839mptsas_send_ir2_event(struct fw_event_work *fw_event)
b506ade9 3840{
3eb0822c
KD
3841 MPT_ADAPTER *ioc;
3842 struct mptsas_hotplug_event hot_plug_info;
3843 MPI_EVENT_DATA_IR2 *ir2_data;
3844 u8 reasonCode;
3845
3846 ioc = fw_event->ioc;
3847 ir2_data = (MPI_EVENT_DATA_IR2 *)fw_event->event_data;
3848 reasonCode = ir2_data->ReasonCode;
3849
3850 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Entering %s: "
3851 "ReasonCode=%02x\n", ioc->name, __func__, reasonCode));
3852
3853 memset(&hot_plug_info, 0, sizeof(struct mptsas_hotplug_event));
3854 hot_plug_info.id = ir2_data->TargetID;
3855 hot_plug_info.channel = ir2_data->Bus;
3856 switch (reasonCode) {
3857 case MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED:
3858 hot_plug_info.event_type = MPTSAS_ADD_INACTIVE_VOLUME;
3859 break;
3860 default:
3861 mptsas_free_fw_event(ioc, fw_event);
b506ade9 3862 return;
3eb0822c
KD
3863 }
3864 mptsas_hotplug_work(ioc, fw_event, &hot_plug_info);
3865}
e6b2d76a 3866
9a28f49a
CH
3867static int
3868mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
3869{
3eb0822c
KD
3870 u32 event = le32_to_cpu(reply->Event);
3871 int sz, event_data_sz;
3872 struct fw_event_work *fw_event;
3873 unsigned long delay;
9a28f49a 3874
3eb0822c
KD
3875 /* events turned off due to host reset or driver unloading */
3876 if (ioc->fw_events_off)
3877 return 0;
e6b2d76a 3878
3eb0822c 3879 delay = msecs_to_jiffies(1);
9a28f49a
CH
3880 switch (event) {
3881 case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
3eb0822c
KD
3882 {
3883 EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data =
3884 (EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)reply->Data;
3885
3886 if (sas_event_data->ReasonCode ==
3887 MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING) {
3888 mptsas_target_reset_queue(ioc, sas_event_data);
3889 return 0;
3890 }
79de278e 3891 break;
3eb0822c 3892 }
f9c34022
KD
3893 case MPI_EVENT_SAS_EXPANDER_STATUS_CHANGE:
3894 {
3895 MpiEventDataSasExpanderStatusChange_t *expander_data =
3896 (MpiEventDataSasExpanderStatusChange_t *)reply->Data;
3897
3898
3899 if (expander_data->ReasonCode ==
3900 MPI_EVENT_SAS_EXP_RC_NOT_RESPONDING &&
3901 ioc->device_missing_delay)
3902 delay = HZ * ioc->device_missing_delay;
e6b2d76a 3903 break;
f9c34022
KD
3904 }
3905 case MPI_EVENT_SAS_DISCOVERY:
3906 {
3907 u32 discovery_status;
3908 EventDataSasDiscovery_t *discovery_data =
3909 (EventDataSasDiscovery_t *)reply->Data;
3910
3911 discovery_status = le32_to_cpu(discovery_data->DiscoveryStatus);
3912 ioc->sas_discovery_quiesce_io = discovery_status ? 1 : 0;
3913 return 0;
3914 }
3eb0822c
KD
3915 case MPI_EVENT_INTEGRATED_RAID:
3916 case MPI_EVENT_PERSISTENT_TABLE_FULL:
b506ade9 3917 case MPI_EVENT_IR2:
3eb0822c
KD
3918 case MPI_EVENT_SAS_PHY_LINK_STATUS:
3919 case MPI_EVENT_QUEUE_FULL:
b506ade9 3920 break;
9a28f49a 3921 default:
3eb0822c 3922 return 0;
9a28f49a 3923 }
c73787ee 3924
3eb0822c
KD
3925 event_data_sz = ((reply->MsgLength * 4) -
3926 offsetof(EventNotificationReply_t, Data));
3927 sz = offsetof(struct fw_event_work, event_data) + event_data_sz;
3928 fw_event = kzalloc(sz, GFP_ATOMIC);
3929 if (!fw_event) {
3930 printk(MYIOC_s_WARN_FMT "%s: failed at (line=%d)\n", ioc->name,
3931 __func__, __LINE__);
3932 return 0;
3933 }
3934 memcpy(fw_event->event_data, reply->Data, event_data_sz);
3935 fw_event->event = event;
3936 fw_event->ioc = ioc;
3937 mptsas_add_fw_event(ioc, fw_event, delay);
3938 return 0;
9a28f49a
CH
3939}
3940
0c33b27d
CH
3941static int
3942mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
3943{
3944 struct Scsi_Host *sh;
3945 MPT_SCSI_HOST *hd;
3946 MPT_ADAPTER *ioc;
3947 unsigned long flags;
1ca00bb7 3948 int ii;
0c33b27d
CH
3949 int numSGE = 0;
3950 int scale;
3951 int ioc_cap;
0c33b27d
CH
3952 int error=0;
3953 int r;
3954
3955 r = mpt_attach(pdev,id);
3956 if (r)
3957 return r;
3958
3959 ioc = pci_get_drvdata(pdev);
3eb0822c 3960 mptsas_fw_event_off(ioc);
0c33b27d
CH
3961 ioc->DoneCtx = mptsasDoneCtx;
3962 ioc->TaskCtx = mptsasTaskCtx;
3963 ioc->InternalCtx = mptsasInternalCtx;
3964
3965 /* Added sanity check on readiness of the MPT adapter.
3966 */
3967 if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
3968 printk(MYIOC_s_WARN_FMT
3969 "Skipping because it's not operational!\n",
3970 ioc->name);
7acec1e7
MED
3971 error = -ENODEV;
3972 goto out_mptsas_probe;
0c33b27d
CH
3973 }
3974
3975 if (!ioc->active) {
3976 printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
3977 ioc->name);
7acec1e7
MED
3978 error = -ENODEV;
3979 goto out_mptsas_probe;
0c33b27d
CH
3980 }
3981
3982 /* Sanity check - ensure at least 1 port is INITIATOR capable
3983 */
3984 ioc_cap = 0;
3985 for (ii = 0; ii < ioc->facts.NumberOfPorts; ii++) {
3986 if (ioc->pfacts[ii].ProtocolFlags &
3987 MPI_PORTFACTS_PROTOCOL_INITIATOR)
3988 ioc_cap++;
3989 }
3990
3991 if (!ioc_cap) {
3992 printk(MYIOC_s_WARN_FMT
3993 "Skipping ioc=%p because SCSI Initiator mode "
3994 "is NOT enabled!\n", ioc->name, ioc);
466544d8 3995 return 0;
0c33b27d
CH
3996 }
3997
3998 sh = scsi_host_alloc(&mptsas_driver_template, sizeof(MPT_SCSI_HOST));
3999 if (!sh) {
4000 printk(MYIOC_s_WARN_FMT
4001 "Unable to register controller with SCSI subsystem\n",
4002 ioc->name);
7acec1e7
MED
4003 error = -1;
4004 goto out_mptsas_probe;
0c33b27d
CH
4005 }
4006
4007 spin_lock_irqsave(&ioc->FreeQlock, flags);
4008
4009 /* Attach the SCSI Host to the IOC structure
4010 */
4011 ioc->sh = sh;
4012
4013 sh->io_port = 0;
4014 sh->n_io_port = 0;
4015 sh->irq = 0;
4016
4017 /* set 16 byte cdb's */
4018 sh->max_cmd_len = 16;
4019
793955f5
EM
4020 sh->max_id = ioc->pfacts[0].PortSCSIID;
4021 sh->max_lun = max_lun;
0c33b27d
CH
4022
4023 sh->transportt = mptsas_transport_template;
4024
0c33b27d
CH
4025 /* Required entry.
4026 */
4027 sh->unique_id = ioc->id;
4028
4029 INIT_LIST_HEAD(&ioc->sas_topology);
9a28f49a 4030 mutex_init(&ioc->sas_topology_mutex);
e6b2d76a 4031 mutex_init(&ioc->sas_discovery_mutex);
eeb846ce 4032 mutex_init(&ioc->sas_mgmt.mutex);
da4fa655 4033 init_completion(&ioc->sas_mgmt.done);
0c33b27d
CH
4034
4035 /* Verify that we won't exceed the maximum
4036 * number of chain buffers
4037 * We can optimize: ZZ = req_sz/sizeof(SGE)
4038 * For 32bit SGE's:
4039 * numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
4040 * + (req_sz - 64)/sizeof(SGE)
4041 * A slightly different algorithm is required for
4042 * 64bit SGEs.
4043 */
14d0f0b0
KD
4044 scale = ioc->req_sz/ioc->SGE_size;
4045 if (ioc->sg_addr_size == sizeof(u64)) {
0c33b27d
CH
4046 numSGE = (scale - 1) *
4047 (ioc->facts.MaxChainDepth-1) + scale +
14d0f0b0 4048 (ioc->req_sz - 60) / ioc->SGE_size;
0c33b27d
CH
4049 } else {
4050 numSGE = 1 + (scale - 1) *
4051 (ioc->facts.MaxChainDepth-1) + scale +
14d0f0b0 4052 (ioc->req_sz - 64) / ioc->SGE_size;
0c33b27d
CH
4053 }
4054
4055 if (numSGE < sh->sg_tablesize) {
4056 /* Reset this value */
d6ecdd63 4057 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
0c33b27d
CH
4058 "Resetting sg_tablesize to %d from %d\n",
4059 ioc->name, numSGE, sh->sg_tablesize));
4060 sh->sg_tablesize = numSGE;
4061 }
4062
e7eae9f6 4063 hd = shost_priv(sh);
0c33b27d
CH
4064 hd->ioc = ioc;
4065
4066 /* SCSI needs scsi_cmnd lookup table!
4067 * (with size equal to req_depth*PtrSz!)
4068 */
e8206381
EM
4069 ioc->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);
4070 if (!ioc->ScsiLookup) {
0c33b27d 4071 error = -ENOMEM;
bc6e089a 4072 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
7acec1e7 4073 goto out_mptsas_probe;
0c33b27d 4074 }
e8206381 4075 spin_lock_init(&ioc->scsi_lookup_lock);
0c33b27d 4076
d6ecdd63 4077 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ScsiLookup @ %p\n",
e8206381 4078 ioc->name, ioc->ScsiLookup));
0c33b27d 4079
0c33b27d
CH
4080 /* Clear the TM flags
4081 */
0c33b27d
CH
4082 hd->abortSCpnt = NULL;
4083
4084 /* Clear the pointer used to store
4085 * single-threaded commands, i.e., those
4086 * issued during a bus scan, dv and
4087 * configuration pages.
4088 */
4089 hd->cmdPtr = NULL;
4090
4091 /* Initialize this SCSI Hosts' timers
4092 * To use, set the timer expires field
4093 * and add_timer
4094 */
4095 init_timer(&hd->timer);
4096 hd->timer.data = (unsigned long) hd;
4097 hd->timer.function = mptscsih_timer_expired;
4098
0c33b27d
CH
4099 ioc->sas_data.ptClear = mpt_pt_clear;
4100
df9e062a
EM
4101 hd->last_queue_full = 0;
4102 INIT_LIST_HEAD(&hd->target_reset_list);
3eb0822c
KD
4103 INIT_LIST_HEAD(&ioc->sas_device_info_list);
4104 mutex_init(&ioc->sas_device_info_mutex);
4105
df9e062a
EM
4106 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
4107
0c33b27d
CH
4108 if (ioc->sas_data.ptClear==1) {
4109 mptbase_sas_persist_operation(
4110 ioc, MPI_SAS_OP_CLEAR_ALL_PERSISTENT);
4111 }
4112
0c33b27d
CH
4113 error = scsi_add_host(sh, &ioc->pcidev->dev);
4114 if (error) {
29dd3609
EM
4115 dprintk(ioc, printk(MYIOC_s_ERR_FMT
4116 "scsi_add_host failed\n", ioc->name));
7acec1e7 4117 goto out_mptsas_probe;
0c33b27d
CH
4118 }
4119
4120 mptsas_scan_sas_topology(ioc);
3eb0822c 4121 mptsas_fw_event_on(ioc);
0c33b27d
CH
4122 return 0;
4123
547f9a21 4124 out_mptsas_probe:
0c33b27d
CH
4125
4126 mptscsih_remove(pdev);
4127 return error;
4128}
4129
7b5a65b9
KD
4130void
4131mptsas_shutdown(struct pci_dev *pdev)
4132{
4133 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
4134
3eb0822c
KD
4135 mptsas_fw_event_off(ioc);
4136 mptsas_cleanup_fw_event_q(ioc);
7b5a65b9
KD
4137}
4138
0c33b27d
CH
4139static void __devexit mptsas_remove(struct pci_dev *pdev)
4140{
4141 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
4142 struct mptsas_portinfo *p, *n;
547f9a21 4143 int i;
0c33b27d 4144
7b5a65b9
KD
4145 mptsas_shutdown(pdev);
4146
3eb0822c
KD
4147 mptsas_del_device_components(ioc);
4148
b506ade9 4149 ioc->sas_discovery_ignore_events = 1;
0c33b27d
CH
4150 sas_remove_host(ioc->sh);
4151
9a28f49a 4152 mutex_lock(&ioc->sas_topology_mutex);
0c33b27d
CH
4153 list_for_each_entry_safe(p, n, &ioc->sas_topology, list) {
4154 list_del(&p->list);
547f9a21 4155 for (i = 0 ; i < p->num_phys ; i++)
d6ecdd63 4156 mptsas_port_delete(ioc, p->phy_info[i].port_details);
3eb0822c 4157
547f9a21 4158 kfree(p->phy_info);
0c33b27d
CH
4159 kfree(p);
4160 }
9a28f49a 4161 mutex_unlock(&ioc->sas_topology_mutex);
f9c34022 4162 ioc->hba_port_info = NULL;
0c33b27d
CH
4163 mptscsih_remove(pdev);
4164}
4165
4166static struct pci_device_id mptsas_pci_table[] = {
87cf8986 4167 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1064,
0c33b27d 4168 PCI_ANY_ID, PCI_ANY_ID },
87cf8986 4169 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1068,
0c33b27d 4170 PCI_ANY_ID, PCI_ANY_ID },
87cf8986 4171 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1064E,
0c33b27d 4172 PCI_ANY_ID, PCI_ANY_ID },
87cf8986 4173 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1068E,
0c33b27d 4174 PCI_ANY_ID, PCI_ANY_ID },
87cf8986 4175 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1078,
0c33b27d
CH
4176 PCI_ANY_ID, PCI_ANY_ID },
4177 {0} /* Terminating entry */
4178};
4179MODULE_DEVICE_TABLE(pci, mptsas_pci_table);
4180
4181
4182static struct pci_driver mptsas_driver = {
4183 .name = "mptsas",
4184 .id_table = mptsas_pci_table,
4185 .probe = mptsas_probe,
4186 .remove = __devexit_p(mptsas_remove),
7b5a65b9 4187 .shutdown = mptsas_shutdown,
0c33b27d
CH
4188#ifdef CONFIG_PM
4189 .suspend = mptscsih_suspend,
4190 .resume = mptscsih_resume,
4191#endif
4192};
4193
4194static int __init
4195mptsas_init(void)
4196{
57ce21bf
PS
4197 int error;
4198
0c33b27d
CH
4199 show_mptmod_ver(my_NAME, my_VERSION);
4200
4201 mptsas_transport_template =
4202 sas_attach_transport(&mptsas_transport_functions);
4203 if (!mptsas_transport_template)
4204 return -ENODEV;
4205
4206 mptsasDoneCtx = mpt_register(mptscsih_io_done, MPTSAS_DRIVER);
e7deff33 4207 mptsasTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSAS_DRIVER);
0c33b27d
CH
4208 mptsasInternalCtx =
4209 mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER);
da4fa655 4210 mptsasMgmtCtx = mpt_register(mptsas_mgmt_done, MPTSAS_DRIVER);
e7deff33
KD
4211 mptsasDeviceResetCtx =
4212 mpt_register(mptsas_taskmgmt_complete, MPTSAS_DRIVER);
0c33b27d 4213
d6ecdd63
PS
4214 mpt_event_register(mptsasDoneCtx, mptsas_event_process);
4215 mpt_reset_register(mptsasDoneCtx, mptsas_ioc_reset);
0c33b27d 4216
57ce21bf
PS
4217 error = pci_register_driver(&mptsas_driver);
4218 if (error)
4219 sas_release_transport(mptsas_transport_template);
4220
4221 return error;
0c33b27d
CH
4222}
4223
4224static void __exit
4225mptsas_exit(void)
4226{
4227 pci_unregister_driver(&mptsas_driver);
4228 sas_release_transport(mptsas_transport_template);
4229
4230 mpt_reset_deregister(mptsasDoneCtx);
4231 mpt_event_deregister(mptsasDoneCtx);
4232
da4fa655 4233 mpt_deregister(mptsasMgmtCtx);
0c33b27d
CH
4234 mpt_deregister(mptsasInternalCtx);
4235 mpt_deregister(mptsasTaskCtx);
4236 mpt_deregister(mptsasDoneCtx);
e7deff33 4237 mpt_deregister(mptsasDeviceResetCtx);
0c33b27d
CH
4238}
4239
4240module_init(mptsas_init);
4241module_exit(mptsas_exit);