WorkStruct: make allyesconfig
[linux-2.6-block.git] / drivers / message / fusion / mptsas.c
CommitLineData
0c33b27d
CH
1/*
2 * linux/drivers/message/fusion/mptsas.c
3 * For use with LSI Logic PCI chip/adapter(s)
4 * running LSI Logic Fusion MPT (Message Passing Technology) firmware.
5 *
6 * Copyright (c) 1999-2005 LSI Logic Corporation
7 * (mailto:mpt_linux_developer@lsil.com)
9a28f49a 8 * Copyright (c) 2005-2006 Dell
0c33b27d
CH
9 */
10/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
11/*
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; version 2 of the License.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 NO WARRANTY
22 THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
23 CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
24 LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
25 MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
26 solely responsible for determining the appropriateness of using and
27 distributing the Program and assumes all risks associated with its
28 exercise of rights under this Agreement, including but not limited to
29 the risks and costs of program errors, damage to or loss of data,
30 programs or equipment, and unavailability or interruption of operations.
31
32 DISCLAIMER OF LIABILITY
33 NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
34 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35 DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
36 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
37 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
38 USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
39 HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
40
41 You should have received a copy of the GNU General Public License
42 along with this program; if not, write to the Free Software
43 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
44*/
45/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
46
47#include <linux/module.h>
48#include <linux/kernel.h>
49#include <linux/init.h>
50#include <linux/errno.h>
51#include <linux/sched.h>
52#include <linux/workqueue.h>
547f9a21 53#include <linux/delay.h> /* for mdelay */
0c33b27d 54
547f9a21 55#include <scsi/scsi.h>
0c33b27d
CH
56#include <scsi/scsi_cmnd.h>
57#include <scsi/scsi_device.h>
58#include <scsi/scsi_host.h>
59#include <scsi/scsi_transport_sas.h>
547f9a21 60#include <scsi/scsi_dbg.h>
0c33b27d
CH
61
62#include "mptbase.h"
63#include "mptscsih.h"
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");
78
0c33b27d
CH
79static int mpt_pt_clear;
80module_param(mpt_pt_clear, int, 0);
81MODULE_PARM_DESC(mpt_pt_clear,
ba856d32 82 " Clear persistency table: enable=1 "
0c33b27d
CH
83 "(default=MPTSCSIH_PT_CLEAR=0)");
84
85static int mptsasDoneCtx = -1;
86static int mptsasTaskCtx = -1;
87static int mptsasInternalCtx = -1; /* Used only for internal commands */
da4fa655 88static int mptsasMgmtCtx = -1;
0c33b27d
CH
89
90
9a28f49a
CH
91enum mptsas_hotplug_action {
92 MPTSAS_ADD_DEVICE,
93 MPTSAS_DEL_DEVICE,
c73787ee
ME
94 MPTSAS_ADD_RAID,
95 MPTSAS_DEL_RAID,
bd23e94c 96 MPTSAS_IGNORE_EVENT,
9a28f49a
CH
97};
98
99struct mptsas_hotplug_event {
100 struct work_struct work;
101 MPT_ADAPTER *ioc;
102 enum mptsas_hotplug_action event_type;
103 u64 sas_address;
104 u32 channel;
105 u32 id;
106 u32 device_info;
107 u16 handle;
108 u16 parent_handle;
109 u8 phy_id;
f44e5461
ME
110 u8 phys_disk_num;
111 u8 phys_disk_num_valid;
9a28f49a
CH
112};
113
e6b2d76a
ME
114struct mptsas_discovery_event {
115 struct work_struct work;
116 MPT_ADAPTER *ioc;
117};
118
0c33b27d
CH
119/*
120 * SAS topology structures
121 *
122 * The MPT Fusion firmware interface spreads information about the
123 * SAS topology over many manufacture pages, thus we need some data
124 * structure to collect it and process it for the SAS transport class.
125 */
126
127struct mptsas_devinfo {
128 u16 handle; /* unique id to address this device */
c73787ee 129 u16 handle_parent; /* unique id to address parent device */
e3094447
CH
130 u16 handle_enclosure; /* enclosure identifier of the enclosure */
131 u16 slot; /* physical slot in enclosure */
0c33b27d
CH
132 u8 phy_id; /* phy number of parent device */
133 u8 port_id; /* sas physical port this device
134 is assoc'd with */
9a28f49a
CH
135 u8 id; /* logical target id of this device */
136 u8 channel; /* logical bus number of this device */
0c33b27d
CH
137 u64 sas_address; /* WWN of this device,
138 SATA is assigned by HBA,expander */
139 u32 device_info; /* bitfield detailed info about this device */
140};
141
547f9a21
EM
142/*
143 * Specific details on ports, wide/narrow
144 */
145struct mptsas_portinfo_details{
547f9a21
EM
146 u16 num_phys; /* number of phys belong to this port */
147 u64 phy_bitmask; /* TODO, extend support for 255 phys */
148 struct sas_rphy *rphy; /* transport layer rphy object */
149 struct sas_port *port; /* transport layer port object */
150 struct scsi_target *starget;
151 struct mptsas_portinfo *port_info;
152};
153
0c33b27d
CH
154struct mptsas_phyinfo {
155 u8 phy_id; /* phy index */
547f9a21 156 u8 port_id; /* firmware port identifier */
0c33b27d
CH
157 u8 negotiated_link_rate; /* nego'd link rate for this phy */
158 u8 hw_link_rate; /* hardware max/min phys link rate */
159 u8 programmed_link_rate; /* programmed max/min phy link rate */
547f9a21 160 u8 sas_port_add_phy; /* flag to request sas_port_add_phy*/
0c33b27d
CH
161 struct mptsas_devinfo identify; /* point to phy device info */
162 struct mptsas_devinfo attached; /* point to attached device info */
547f9a21
EM
163 struct sas_phy *phy; /* transport layer phy object */
164 struct mptsas_portinfo *portinfo;
165 struct mptsas_portinfo_details * port_details;
0c33b27d
CH
166};
167
168struct mptsas_portinfo {
169 struct list_head list;
170 u16 handle; /* unique id to address this */
547f9a21 171 u16 num_phys; /* number of phys */
0c33b27d
CH
172 struct mptsas_phyinfo *phy_info;
173};
174
e3094447
CH
175struct mptsas_enclosure {
176 u64 enclosure_logical_id; /* The WWN for the enclosure */
177 u16 enclosure_handle; /* unique id to address this */
178 u16 flags; /* details enclosure management */
179 u16 num_slot; /* num slots */
180 u16 start_slot; /* first slot */
181 u8 start_id; /* starting logical target id */
182 u8 start_channel; /* starting logical channel id */
183 u8 sep_id; /* SEP device logical target id */
184 u8 sep_channel; /* SEP channel logical channel id */
185};
186
547f9a21 187#ifdef MPT_DEBUG_SAS
b5141128
CH
188static void mptsas_print_phy_data(MPI_SAS_IO_UNIT0_PHY_DATA *phy_data)
189{
190 printk("---- IO UNIT PAGE 0 ------------\n");
191 printk("Handle=0x%X\n",
192 le16_to_cpu(phy_data->AttachedDeviceHandle));
193 printk("Controller Handle=0x%X\n",
194 le16_to_cpu(phy_data->ControllerDevHandle));
195 printk("Port=0x%X\n", phy_data->Port);
196 printk("Port Flags=0x%X\n", phy_data->PortFlags);
197 printk("PHY Flags=0x%X\n", phy_data->PhyFlags);
198 printk("Negotiated Link Rate=0x%X\n", phy_data->NegotiatedLinkRate);
199 printk("Controller PHY Device Info=0x%X\n",
200 le32_to_cpu(phy_data->ControllerPhyDeviceInfo));
201 printk("DiscoveryStatus=0x%X\n",
202 le32_to_cpu(phy_data->DiscoveryStatus));
203 printk("\n");
204}
205
206static void mptsas_print_phy_pg0(SasPhyPage0_t *pg0)
207{
208 __le64 sas_address;
209
210 memcpy(&sas_address, &pg0->SASAddress, sizeof(__le64));
211
212 printk("---- SAS PHY PAGE 0 ------------\n");
213 printk("Attached Device Handle=0x%X\n",
214 le16_to_cpu(pg0->AttachedDevHandle));
215 printk("SAS Address=0x%llX\n",
216 (unsigned long long)le64_to_cpu(sas_address));
217 printk("Attached PHY Identifier=0x%X\n", pg0->AttachedPhyIdentifier);
218 printk("Attached Device Info=0x%X\n",
219 le32_to_cpu(pg0->AttachedDeviceInfo));
220 printk("Programmed Link Rate=0x%X\n", pg0->ProgrammedLinkRate);
221 printk("Change Count=0x%X\n", pg0->ChangeCount);
222 printk("PHY Info=0x%X\n", le32_to_cpu(pg0->PhyInfo));
223 printk("\n");
224}
225
226static void mptsas_print_phy_pg1(SasPhyPage1_t *pg1)
227{
228 printk("---- SAS PHY PAGE 1 ------------\n");
f9a2d2e0
CH
229 printk("Invalid Dword Count=0x%x\n", pg1->InvalidDwordCount);
230 printk("Running Disparity Error Count=0x%x\n",
b5141128 231 pg1->RunningDisparityErrorCount);
f9a2d2e0
CH
232 printk("Loss Dword Synch Count=0x%x\n", pg1->LossDwordSynchCount);
233 printk("PHY Reset Problem Count=0x%x\n", pg1->PhyResetProblemCount);
234 printk("\n");
b5141128
CH
235}
236
237static void mptsas_print_device_pg0(SasDevicePage0_t *pg0)
238{
239 __le64 sas_address;
240
241 memcpy(&sas_address, &pg0->SASAddress, sizeof(__le64));
242
243 printk("---- SAS DEVICE PAGE 0 ---------\n");
244 printk("Handle=0x%X\n" ,le16_to_cpu(pg0->DevHandle));
e3094447 245 printk("Parent Handle=0x%X\n" ,le16_to_cpu(pg0->ParentDevHandle));
b5141128
CH
246 printk("Enclosure Handle=0x%X\n", le16_to_cpu(pg0->EnclosureHandle));
247 printk("Slot=0x%X\n", le16_to_cpu(pg0->Slot));
248 printk("SAS Address=0x%llX\n", le64_to_cpu(sas_address));
249 printk("Target ID=0x%X\n", pg0->TargetID);
250 printk("Bus=0x%X\n", pg0->Bus);
f9a2d2e0
CH
251 /* The PhyNum field specifies the PHY number of the parent
252 * device this device is linked to
253 */
254 printk("Parent Phy Num=0x%X\n", pg0->PhyNum);
255 printk("Access Status=0x%X\n", le16_to_cpu(pg0->AccessStatus));
b5141128
CH
256 printk("Device Info=0x%X\n", le32_to_cpu(pg0->DeviceInfo));
257 printk("Flags=0x%X\n", le16_to_cpu(pg0->Flags));
258 printk("Physical Port=0x%X\n", pg0->PhysicalPort);
259 printk("\n");
260}
261
262static void mptsas_print_expander_pg1(SasExpanderPage1_t *pg1)
263{
264 printk("---- SAS EXPANDER PAGE 1 ------------\n");
265
266 printk("Physical Port=0x%X\n", pg1->PhysicalPort);
f9a2d2e0 267 printk("PHY Identifier=0x%X\n", pg1->PhyIdentifier);
b5141128
CH
268 printk("Negotiated Link Rate=0x%X\n", pg1->NegotiatedLinkRate);
269 printk("Programmed Link Rate=0x%X\n", pg1->ProgrammedLinkRate);
270 printk("Hardware Link Rate=0x%X\n", pg1->HwLinkRate);
271 printk("Owner Device Handle=0x%X\n",
272 le16_to_cpu(pg1->OwnerDevHandle));
273 printk("Attached Device Handle=0x%X\n",
274 le16_to_cpu(pg1->AttachedDevHandle));
275}
276#else
277#define mptsas_print_phy_data(phy_data) do { } while (0)
278#define mptsas_print_phy_pg0(pg0) do { } while (0)
279#define mptsas_print_phy_pg1(pg1) do { } while (0)
280#define mptsas_print_device_pg0(pg0) do { } while (0)
281#define mptsas_print_expander_pg1(pg1) do { } while (0)
282#endif
283
e3094447
CH
284static inline MPT_ADAPTER *phy_to_ioc(struct sas_phy *phy)
285{
286 struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
287 return ((MPT_SCSI_HOST *)shost->hostdata)->ioc;
288}
289
290static inline MPT_ADAPTER *rphy_to_ioc(struct sas_rphy *rphy)
291{
292 struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent);
293 return ((MPT_SCSI_HOST *)shost->hostdata)->ioc;
294}
295
e6b2d76a
ME
296/*
297 * mptsas_find_portinfo_by_handle
298 *
299 * This function should be called with the sas_topology_mutex already held
300 */
301static struct mptsas_portinfo *
302mptsas_find_portinfo_by_handle(MPT_ADAPTER *ioc, u16 handle)
303{
304 struct mptsas_portinfo *port_info, *rc=NULL;
305 int i;
306
307 list_for_each_entry(port_info, &ioc->sas_topology, list)
308 for (i = 0; i < port_info->num_phys; i++)
309 if (port_info->phy_info[i].identify.handle == handle) {
310 rc = port_info;
311 goto out;
312 }
313 out:
314 return rc;
315}
316
bd23e94c
ME
317/*
318 * Returns true if there is a scsi end device
319 */
320static inline int
321mptsas_is_end_device(struct mptsas_devinfo * attached)
322{
547f9a21 323 if ((attached->sas_address) &&
bd23e94c
ME
324 (attached->device_info &
325 MPI_SAS_DEVICE_INFO_END_DEVICE) &&
326 ((attached->device_info &
327 MPI_SAS_DEVICE_INFO_SSP_TARGET) |
328 (attached->device_info &
329 MPI_SAS_DEVICE_INFO_STP_TARGET) |
330 (attached->device_info &
331 MPI_SAS_DEVICE_INFO_SATA_DEVICE)))
332 return 1;
333 else
334 return 0;
335}
336
547f9a21 337/* no mutex */
376ac830 338static void
547f9a21
EM
339mptsas_port_delete(struct mptsas_portinfo_details * port_details)
340{
341 struct mptsas_portinfo *port_info;
342 struct mptsas_phyinfo *phy_info;
343 u8 i;
344
345 if (!port_details)
346 return;
347
348 port_info = port_details->port_info;
349 phy_info = port_info->phy_info;
350
dc22f16d 351 dsaswideprintk((KERN_DEBUG "%s: [%p]: num_phys=%02d "
547f9a21 352 "bitmask=0x%016llX\n",
dc22f16d
EM
353 __FUNCTION__, port_details, port_details->num_phys,
354 port_details->phy_bitmask));
547f9a21
EM
355
356 for (i = 0; i < port_info->num_phys; i++, phy_info++) {
357 if(phy_info->port_details != port_details)
358 continue;
359 memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo));
360 phy_info->port_details = NULL;
361 }
362 kfree(port_details);
363}
364
365static inline struct sas_rphy *
366mptsas_get_rphy(struct mptsas_phyinfo *phy_info)
367{
368 if (phy_info->port_details)
369 return phy_info->port_details->rphy;
370 else
371 return NULL;
372}
373
374static inline void
375mptsas_set_rphy(struct mptsas_phyinfo *phy_info, struct sas_rphy *rphy)
376{
377 if (phy_info->port_details) {
378 phy_info->port_details->rphy = rphy;
379 dsaswideprintk((KERN_DEBUG "sas_rphy_add: rphy=%p\n", rphy));
380 }
381
382#ifdef MPT_DEBUG_SAS_WIDE
383 if (rphy) {
384 dev_printk(KERN_DEBUG, &rphy->dev, "add:");
385 printk("rphy=%p release=%p\n",
386 rphy, rphy->dev.release);
387 }
388#endif
389}
390
391static inline struct sas_port *
392mptsas_get_port(struct mptsas_phyinfo *phy_info)
393{
394 if (phy_info->port_details)
395 return phy_info->port_details->port;
396 else
397 return NULL;
398}
399
400static inline void
401mptsas_set_port(struct mptsas_phyinfo *phy_info, struct sas_port *port)
402{
403 if (phy_info->port_details)
404 phy_info->port_details->port = port;
405
406#ifdef MPT_DEBUG_SAS_WIDE
407 if (port) {
408 dev_printk(KERN_DEBUG, &port->dev, "add: ");
409 printk("port=%p release=%p\n",
410 port, port->dev.release);
411 }
412#endif
413}
414
415static inline struct scsi_target *
416mptsas_get_starget(struct mptsas_phyinfo *phy_info)
417{
418 if (phy_info->port_details)
419 return phy_info->port_details->starget;
420 else
421 return NULL;
422}
423
424static inline void
425mptsas_set_starget(struct mptsas_phyinfo *phy_info, struct scsi_target *
426starget)
427{
428 if (phy_info->port_details)
429 phy_info->port_details->starget = starget;
430}
431
432
433/*
434 * mptsas_setup_wide_ports
435 *
436 * Updates for new and existing narrow/wide port configuration
437 * in the sas_topology
438 */
376ac830 439static void
547f9a21
EM
440mptsas_setup_wide_ports(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
441{
442 struct mptsas_portinfo_details * port_details;
443 struct mptsas_phyinfo *phy_info, *phy_info_cmp;
444 u64 sas_address;
445 int i, j;
446
447 mutex_lock(&ioc->sas_topology_mutex);
448
449 phy_info = port_info->phy_info;
450 for (i = 0 ; i < port_info->num_phys ; i++, phy_info++) {
451 if (phy_info->attached.handle)
452 continue;
453 port_details = phy_info->port_details;
454 if (!port_details)
455 continue;
456 if (port_details->num_phys < 2)
457 continue;
458 /*
459 * Removing a phy from a port, letting the last
460 * phy be removed by firmware events.
461 */
462 dsaswideprintk((KERN_DEBUG
dc22f16d
EM
463 "%s: [%p]: deleting phy = %d\n",
464 __FUNCTION__, port_details, i));
547f9a21
EM
465 port_details->num_phys--;
466 port_details->phy_bitmask &= ~ (1 << phy_info->phy_id);
467 memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo));
468 sas_port_delete_phy(port_details->port, phy_info->phy);
469 phy_info->port_details = NULL;
470 }
471
472 /*
473 * Populate and refresh the tree
474 */
475 phy_info = port_info->phy_info;
476 for (i = 0 ; i < port_info->num_phys ; i++, phy_info++) {
477 sas_address = phy_info->attached.sas_address;
478 dsaswideprintk((KERN_DEBUG "phy_id=%d sas_address=0x%018llX\n",
479 i, sas_address));
480 if (!sas_address)
481 continue;
482 port_details = phy_info->port_details;
483 /*
484 * Forming a port
485 */
486 if (!port_details) {
487 port_details = kzalloc(sizeof(*port_details),
488 GFP_KERNEL);
489 if (!port_details)
490 goto out;
491 port_details->num_phys = 1;
492 port_details->port_info = port_info;
547f9a21
EM
493 if (phy_info->phy_id < 64 )
494 port_details->phy_bitmask |=
495 (1 << phy_info->phy_id);
496 phy_info->sas_port_add_phy=1;
497 dsaswideprintk((KERN_DEBUG "\t\tForming port\n\t\t"
498 "phy_id=%d sas_address=0x%018llX\n",
499 i, sas_address));
500 phy_info->port_details = port_details;
501 }
502
503 if (i == port_info->num_phys - 1)
504 continue;
505 phy_info_cmp = &port_info->phy_info[i + 1];
506 for (j = i + 1 ; j < port_info->num_phys ; j++,
507 phy_info_cmp++) {
508 if (!phy_info_cmp->attached.sas_address)
509 continue;
510 if (sas_address != phy_info_cmp->attached.sas_address)
511 continue;
512 if (phy_info_cmp->port_details == port_details )
513 continue;
514 dsaswideprintk((KERN_DEBUG
515 "\t\tphy_id=%d sas_address=0x%018llX\n",
516 j, phy_info_cmp->attached.sas_address));
517 if (phy_info_cmp->port_details) {
518 port_details->rphy =
519 mptsas_get_rphy(phy_info_cmp);
520 port_details->port =
521 mptsas_get_port(phy_info_cmp);
522 port_details->starget =
523 mptsas_get_starget(phy_info_cmp);
547f9a21
EM
524 port_details->num_phys =
525 phy_info_cmp->port_details->num_phys;
547f9a21
EM
526 if (!phy_info_cmp->port_details->num_phys)
527 kfree(phy_info_cmp->port_details);
528 } else
529 phy_info_cmp->sas_port_add_phy=1;
530 /*
531 * Adding a phy to a port
532 */
533 phy_info_cmp->port_details = port_details;
534 if (phy_info_cmp->phy_id < 64 )
535 port_details->phy_bitmask |=
536 (1 << phy_info_cmp->phy_id);
537 port_details->num_phys++;
538 }
539 }
540
541 out:
542
543#ifdef MPT_DEBUG_SAS_WIDE
544 for (i = 0; i < port_info->num_phys; i++) {
545 port_details = port_info->phy_info[i].port_details;
546 if (!port_details)
547 continue;
548 dsaswideprintk((KERN_DEBUG
dc22f16d 549 "%s: [%p]: phy_id=%02d num_phys=%02d "
547f9a21
EM
550 "bitmask=0x%016llX\n",
551 __FUNCTION__,
dc22f16d
EM
552 port_details, i, port_details->num_phys,
553 port_details->phy_bitmask));
547f9a21
EM
554 dsaswideprintk((KERN_DEBUG"\t\tport = %p rphy=%p\n",
555 port_details->port, port_details->rphy));
556 }
557 dsaswideprintk((KERN_DEBUG"\n"));
558#endif
559 mutex_unlock(&ioc->sas_topology_mutex);
560}
561
562static void
563mptsas_target_reset(MPT_ADAPTER *ioc, VirtTarget * vtarget)
564{
565 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
566
567 if (mptscsih_TMHandler(hd,
568 MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
569 vtarget->bus_id, vtarget->target_id, 0, 0, 5) < 0) {
570 hd->tmPending = 0;
571 hd->tmState = TM_STATE_NONE;
572 printk(MYIOC_s_WARN_FMT
573 "Error processing TaskMgmt id=%d TARGET_RESET\n",
574 ioc->name, vtarget->target_id);
575 }
576}
577
e3094447 578static int
52435430 579mptsas_sas_enclosure_pg0(MPT_ADAPTER *ioc, struct mptsas_enclosure *enclosure,
e3094447
CH
580 u32 form, u32 form_specific)
581{
582 ConfigExtendedPageHeader_t hdr;
583 CONFIGPARMS cfg;
584 SasEnclosurePage0_t *buffer;
585 dma_addr_t dma_handle;
586 int error;
587 __le64 le_identifier;
588
589 memset(&hdr, 0, sizeof(hdr));
590 hdr.PageVersion = MPI_SASENCLOSURE0_PAGEVERSION;
591 hdr.PageNumber = 0;
592 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
593 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_ENCLOSURE;
594
595 cfg.cfghdr.ehdr = &hdr;
596 cfg.physAddr = -1;
597 cfg.pageAddr = form + form_specific;
598 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
599 cfg.dir = 0; /* read */
600 cfg.timeout = 10;
601
602 error = mpt_config(ioc, &cfg);
603 if (error)
604 goto out;
605 if (!hdr.ExtPageLength) {
606 error = -ENXIO;
607 goto out;
608 }
609
610 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
611 &dma_handle);
612 if (!buffer) {
613 error = -ENOMEM;
614 goto out;
615 }
616
617 cfg.physAddr = dma_handle;
618 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
619
620 error = mpt_config(ioc, &cfg);
621 if (error)
622 goto out_free_consistent;
623
624 /* save config data */
625 memcpy(&le_identifier, &buffer->EnclosureLogicalID, sizeof(__le64));
626 enclosure->enclosure_logical_id = le64_to_cpu(le_identifier);
627 enclosure->enclosure_handle = le16_to_cpu(buffer->EnclosureHandle);
628 enclosure->flags = le16_to_cpu(buffer->Flags);
629 enclosure->num_slot = le16_to_cpu(buffer->NumSlots);
630 enclosure->start_slot = le16_to_cpu(buffer->StartSlot);
631 enclosure->start_id = buffer->StartTargetID;
632 enclosure->start_channel = buffer->StartBus;
633 enclosure->sep_id = buffer->SEPTargetID;
634 enclosure->sep_channel = buffer->SEPBus;
635
636 out_free_consistent:
637 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
638 buffer, dma_handle);
639 out:
640 return error;
641}
b5141128 642
f013db32
JB
643static int
644mptsas_slave_configure(struct scsi_device *sdev)
645{
3c0c25b9 646
e8bf3941
JB
647 if (sdev->channel == MPTSAS_RAID_CHANNEL)
648 goto out;
649
650 sas_read_port_mode_page(sdev);
f013db32 651
e8bf3941 652 out:
f013db32
JB
653 return mptscsih_slave_configure(sdev);
654}
655
547f9a21
EM
656static int
657mptsas_target_alloc(struct scsi_target *starget)
658{
659 struct Scsi_Host *host = dev_to_shost(&starget->dev);
660 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
661 VirtTarget *vtarget;
662 u32 target_id;
663 u32 channel;
664 struct sas_rphy *rphy;
665 struct mptsas_portinfo *p;
666 int i;
667
668 vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL);
669 if (!vtarget)
670 return -ENOMEM;
671
672 vtarget->starget = starget;
673 vtarget->ioc_id = hd->ioc->id;
674 vtarget->tflags = MPT_TARGET_FLAGS_Q_YES|MPT_TARGET_FLAGS_VALID_INQUIRY;
675
676 target_id = starget->id;
677 channel = 0;
678
679 hd->Targets[target_id] = vtarget;
680
e8bf3941 681 if (starget->channel == MPTSAS_RAID_CHANNEL)
547f9a21
EM
682 goto out;
683
684 rphy = dev_to_rphy(starget->dev.parent);
685 mutex_lock(&hd->ioc->sas_topology_mutex);
686 list_for_each_entry(p, &hd->ioc->sas_topology, list) {
687 for (i = 0; i < p->num_phys; i++) {
688 if (p->phy_info[i].attached.sas_address !=
689 rphy->identify.sas_address)
690 continue;
691 target_id = p->phy_info[i].attached.id;
692 channel = p->phy_info[i].attached.channel;
693 mptsas_set_starget(&p->phy_info[i], starget);
694
695 /*
696 * Exposing hidden raid components
697 */
698 if (mptscsih_is_phys_disk(hd->ioc, target_id)) {
699 target_id = mptscsih_raid_id_to_num(hd,
700 target_id);
701 vtarget->tflags |=
702 MPT_TARGET_FLAGS_RAID_COMPONENT;
703 }
704 mutex_unlock(&hd->ioc->sas_topology_mutex);
705 goto out;
706 }
707 }
708 mutex_unlock(&hd->ioc->sas_topology_mutex);
709
710 kfree(vtarget);
711 return -ENXIO;
712
713 out:
714 vtarget->target_id = target_id;
715 vtarget->bus_id = channel;
716 starget->hostdata = vtarget;
717 return 0;
718}
719
720static void
721mptsas_target_destroy(struct scsi_target *starget)
722{
723 struct Scsi_Host *host = dev_to_shost(&starget->dev);
724 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
725 struct sas_rphy *rphy;
726 struct mptsas_portinfo *p;
727 int i;
728
729 if (!starget->hostdata)
730 return;
731
e8bf3941 732 if (starget->channel == MPTSAS_RAID_CHANNEL)
547f9a21
EM
733 goto out;
734
735 rphy = dev_to_rphy(starget->dev.parent);
736 list_for_each_entry(p, &hd->ioc->sas_topology, list) {
737 for (i = 0; i < p->num_phys; i++) {
738 if (p->phy_info[i].attached.sas_address !=
739 rphy->identify.sas_address)
740 continue;
741 mptsas_set_starget(&p->phy_info[i], NULL);
742 goto out;
743 }
744 }
745
746 out:
747 kfree(starget->hostdata);
748 starget->hostdata = NULL;
749}
750
751
0c33b27d 752static int
c7c82987 753mptsas_slave_alloc(struct scsi_device *sdev)
0c33b27d 754{
c7c82987 755 struct Scsi_Host *host = sdev->host;
0c33b27d
CH
756 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
757 struct sas_rphy *rphy;
758 struct mptsas_portinfo *p;
759 VirtDevice *vdev;
c7c82987 760 struct scsi_target *starget;
547f9a21 761 int i;
0c33b27d 762
1ca00bb7 763 vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
0c33b27d 764 if (!vdev) {
547f9a21 765 printk(MYIOC_s_ERR_FMT "slave_alloc kzalloc(%zd) FAILED!\n",
0c33b27d
CH
766 hd->ioc->name, sizeof(VirtDevice));
767 return -ENOMEM;
768 }
c7c82987 769 starget = scsi_target(sdev);
547f9a21 770 vdev->vtarget = starget->hostdata;
0c33b27d 771
e8bf3941 772 if (sdev->channel == MPTSAS_RAID_CHANNEL)
816aa907 773 goto out;
816aa907 774
c7c82987 775 rphy = dev_to_rphy(sdev->sdev_target->dev.parent);
9a28f49a 776 mutex_lock(&hd->ioc->sas_topology_mutex);
0c33b27d
CH
777 list_for_each_entry(p, &hd->ioc->sas_topology, list) {
778 for (i = 0; i < p->num_phys; i++) {
547f9a21
EM
779 if (p->phy_info[i].attached.sas_address !=
780 rphy->identify.sas_address)
781 continue;
782 vdev->lun = sdev->lun;
783 /*
784 * Exposing hidden raid components
785 */
786 if (mptscsih_is_phys_disk(hd->ioc,
787 p->phy_info[i].attached.id))
788 sdev->no_uld_attach = 1;
789 mutex_unlock(&hd->ioc->sas_topology_mutex);
790 goto out;
0c33b27d
CH
791 }
792 }
9a28f49a 793 mutex_unlock(&hd->ioc->sas_topology_mutex);
0c33b27d 794
0c33b27d 795 kfree(vdev);
23f236ed 796 return -ENXIO;
0c33b27d
CH
797
798 out:
547f9a21
EM
799 vdev->vtarget->num_luns++;
800 sdev->hostdata = vdev;
0c33b27d
CH
801 return 0;
802}
803
547f9a21
EM
804static int
805mptsas_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
9a28f49a 806{
547f9a21 807 VirtDevice *vdev = SCpnt->device->hostdata;
7d3eecf7 808
547f9a21
EM
809// scsi_print_command(SCpnt);
810 if (vdev->vtarget->deleted) {
811 SCpnt->result = DID_NO_CONNECT << 16;
812 done(SCpnt);
813 return 0;
7d3eecf7 814 }
547f9a21
EM
815
816 return mptscsih_qcmd(SCpnt,done);
9a28f49a
CH
817}
818
547f9a21 819
0c33b27d 820static struct scsi_host_template mptsas_driver_template = {
f78496da 821 .module = THIS_MODULE,
0c33b27d
CH
822 .proc_name = "mptsas",
823 .proc_info = mptscsih_proc_info,
824 .name = "MPT SPI Host",
825 .info = mptscsih_info,
547f9a21
EM
826 .queuecommand = mptsas_qcmd,
827 .target_alloc = mptsas_target_alloc,
0c33b27d 828 .slave_alloc = mptsas_slave_alloc,
f013db32 829 .slave_configure = mptsas_slave_configure,
547f9a21
EM
830 .target_destroy = mptsas_target_destroy,
831 .slave_destroy = mptscsih_slave_destroy,
0c33b27d
CH
832 .change_queue_depth = mptscsih_change_queue_depth,
833 .eh_abort_handler = mptscsih_abort,
834 .eh_device_reset_handler = mptscsih_dev_reset,
835 .eh_bus_reset_handler = mptscsih_bus_reset,
836 .eh_host_reset_handler = mptscsih_host_reset,
837 .bios_param = mptscsih_bios_param,
838 .can_queue = MPT_FC_CAN_QUEUE,
839 .this_id = -1,
840 .sg_tablesize = MPT_SCSI_SG_DEPTH,
841 .max_sectors = 8192,
842 .cmd_per_lun = 7,
843 .use_clustering = ENABLE_CLUSTERING,
844};
845
b5141128 846static int mptsas_get_linkerrors(struct sas_phy *phy)
0c33b27d 847{
b5141128
CH
848 MPT_ADAPTER *ioc = phy_to_ioc(phy);
849 ConfigExtendedPageHeader_t hdr;
850 CONFIGPARMS cfg;
851 SasPhyPage1_t *buffer;
852 dma_addr_t dma_handle;
853 int error;
0c33b27d 854
f4ad7b58
JB
855 /* FIXME: only have link errors on local phys */
856 if (!scsi_is_sas_phy_local(phy))
857 return -EINVAL;
858
b5141128
CH
859 hdr.PageVersion = MPI_SASPHY1_PAGEVERSION;
860 hdr.ExtPageLength = 0;
861 hdr.PageNumber = 1 /* page number 1*/;
862 hdr.Reserved1 = 0;
863 hdr.Reserved2 = 0;
864 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
865 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
0c33b27d 866
b5141128
CH
867 cfg.cfghdr.ehdr = &hdr;
868 cfg.physAddr = -1;
869 cfg.pageAddr = phy->identify.phy_identifier;
870 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
871 cfg.dir = 0; /* read */
872 cfg.timeout = 10;
0c33b27d 873
b5141128
CH
874 error = mpt_config(ioc, &cfg);
875 if (error)
876 return error;
877 if (!hdr.ExtPageLength)
878 return -ENXIO;
0c33b27d 879
b5141128
CH
880 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
881 &dma_handle);
882 if (!buffer)
883 return -ENOMEM;
0c33b27d 884
b5141128
CH
885 cfg.physAddr = dma_handle;
886 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
887
888 error = mpt_config(ioc, &cfg);
889 if (error)
890 goto out_free_consistent;
891
892 mptsas_print_phy_pg1(buffer);
893
894 phy->invalid_dword_count = le32_to_cpu(buffer->InvalidDwordCount);
895 phy->running_disparity_error_count =
896 le32_to_cpu(buffer->RunningDisparityErrorCount);
897 phy->loss_of_dword_sync_count =
898 le32_to_cpu(buffer->LossDwordSynchCount);
899 phy->phy_reset_problem_count =
900 le32_to_cpu(buffer->PhyResetProblemCount);
901
902 out_free_consistent:
903 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
904 buffer, dma_handle);
905 return error;
0c33b27d
CH
906}
907
da4fa655
CH
908static int mptsas_mgmt_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req,
909 MPT_FRAME_HDR *reply)
910{
911 ioc->sas_mgmt.status |= MPT_SAS_MGMT_STATUS_COMMAND_GOOD;
912 if (reply != NULL) {
913 ioc->sas_mgmt.status |= MPT_SAS_MGMT_STATUS_RF_VALID;
914 memcpy(ioc->sas_mgmt.reply, reply,
915 min(ioc->reply_sz, 4 * reply->u.reply.MsgLength));
916 }
917 complete(&ioc->sas_mgmt.done);
918 return 1;
919}
920
921static int mptsas_phy_reset(struct sas_phy *phy, int hard_reset)
922{
923 MPT_ADAPTER *ioc = phy_to_ioc(phy);
924 SasIoUnitControlRequest_t *req;
925 SasIoUnitControlReply_t *reply;
926 MPT_FRAME_HDR *mf;
927 MPIHeader_t *hdr;
928 unsigned long timeleft;
929 int error = -ERESTARTSYS;
930
f4ad7b58
JB
931 /* FIXME: fusion doesn't allow non-local phy reset */
932 if (!scsi_is_sas_phy_local(phy))
933 return -EINVAL;
934
da4fa655
CH
935 /* not implemented for expanders */
936 if (phy->identify.target_port_protocols & SAS_PROTOCOL_SMP)
937 return -ENXIO;
938
eeb846ce 939 if (mutex_lock_interruptible(&ioc->sas_mgmt.mutex))
da4fa655
CH
940 goto out;
941
942 mf = mpt_get_msg_frame(mptsasMgmtCtx, ioc);
943 if (!mf) {
944 error = -ENOMEM;
945 goto out_unlock;
946 }
947
948 hdr = (MPIHeader_t *) mf;
949 req = (SasIoUnitControlRequest_t *)mf;
950 memset(req, 0, sizeof(SasIoUnitControlRequest_t));
951 req->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL;
952 req->MsgContext = hdr->MsgContext;
953 req->Operation = hard_reset ?
954 MPI_SAS_OP_PHY_HARD_RESET : MPI_SAS_OP_PHY_LINK_RESET;
955 req->PhyNum = phy->identify.phy_identifier;
956
957 mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf);
958
959 timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done,
960 10 * HZ);
961 if (!timeleft) {
962 /* On timeout reset the board */
963 mpt_free_msg_frame(ioc, mf);
964 mpt_HardResetHandler(ioc, CAN_SLEEP);
965 error = -ETIMEDOUT;
966 goto out_unlock;
967 }
968
969 /* a reply frame is expected */
970 if ((ioc->sas_mgmt.status &
971 MPT_IOCTL_STATUS_RF_VALID) == 0) {
972 error = -ENXIO;
973 goto out_unlock;
974 }
975
976 /* process the completed Reply Message Frame */
977 reply = (SasIoUnitControlReply_t *)ioc->sas_mgmt.reply;
978 if (reply->IOCStatus != MPI_IOCSTATUS_SUCCESS) {
979 printk("%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",
980 __FUNCTION__,
981 reply->IOCStatus,
982 reply->IOCLogInfo);
983 error = -ENXIO;
984 goto out_unlock;
985 }
986
987 error = 0;
988
989 out_unlock:
eeb846ce 990 mutex_unlock(&ioc->sas_mgmt.mutex);
da4fa655
CH
991 out:
992 return error;
993}
0c33b27d 994
e3094447
CH
995static int
996mptsas_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier)
997{
998 MPT_ADAPTER *ioc = rphy_to_ioc(rphy);
999 int i, error;
1000 struct mptsas_portinfo *p;
1001 struct mptsas_enclosure enclosure_info;
1002 u64 enclosure_handle;
1003
1004 mutex_lock(&ioc->sas_topology_mutex);
1005 list_for_each_entry(p, &ioc->sas_topology, list) {
1006 for (i = 0; i < p->num_phys; i++) {
1007 if (p->phy_info[i].attached.sas_address ==
1008 rphy->identify.sas_address) {
1009 enclosure_handle = p->phy_info[i].
1010 attached.handle_enclosure;
1011 goto found_info;
1012 }
1013 }
1014 }
1015 mutex_unlock(&ioc->sas_topology_mutex);
1016 return -ENXIO;
1017
1018 found_info:
1019 mutex_unlock(&ioc->sas_topology_mutex);
1020 memset(&enclosure_info, 0, sizeof(struct mptsas_enclosure));
52435430 1021 error = mptsas_sas_enclosure_pg0(ioc, &enclosure_info,
e3094447
CH
1022 (MPI_SAS_ENCLOS_PGAD_FORM_HANDLE <<
1023 MPI_SAS_ENCLOS_PGAD_FORM_SHIFT), enclosure_handle);
1024 if (!error)
1025 *identifier = enclosure_info.enclosure_logical_id;
1026 return error;
1027}
1028
1029static int
1030mptsas_get_bay_identifier(struct sas_rphy *rphy)
1031{
1032 MPT_ADAPTER *ioc = rphy_to_ioc(rphy);
1033 struct mptsas_portinfo *p;
1034 int i, rc;
1035
1036 mutex_lock(&ioc->sas_topology_mutex);
1037 list_for_each_entry(p, &ioc->sas_topology, list) {
1038 for (i = 0; i < p->num_phys; i++) {
1039 if (p->phy_info[i].attached.sas_address ==
1040 rphy->identify.sas_address) {
1041 rc = p->phy_info[i].attached.slot;
1042 goto out;
1043 }
1044 }
1045 }
1046 rc = -ENXIO;
1047 out:
1048 mutex_unlock(&ioc->sas_topology_mutex);
1049 return rc;
1050}
1051
b5141128
CH
1052static struct sas_function_template mptsas_transport_functions = {
1053 .get_linkerrors = mptsas_get_linkerrors,
e3094447
CH
1054 .get_enclosure_identifier = mptsas_get_enclosure_identifier,
1055 .get_bay_identifier = mptsas_get_bay_identifier,
da4fa655 1056 .phy_reset = mptsas_phy_reset,
b5141128
CH
1057};
1058
1059static struct scsi_transport_template *mptsas_transport_template;
0c33b27d
CH
1060
1061static int
1062mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
1063{
1064 ConfigExtendedPageHeader_t hdr;
1065 CONFIGPARMS cfg;
1066 SasIOUnitPage0_t *buffer;
1067 dma_addr_t dma_handle;
1068 int error, i;
1069
1070 hdr.PageVersion = MPI_SASIOUNITPAGE0_PAGEVERSION;
1071 hdr.ExtPageLength = 0;
1072 hdr.PageNumber = 0;
1073 hdr.Reserved1 = 0;
1074 hdr.Reserved2 = 0;
1075 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1076 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1077
1078 cfg.cfghdr.ehdr = &hdr;
1079 cfg.physAddr = -1;
1080 cfg.pageAddr = 0;
1081 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1082 cfg.dir = 0; /* read */
1083 cfg.timeout = 10;
1084
1085 error = mpt_config(ioc, &cfg);
1086 if (error)
1087 goto out;
1088 if (!hdr.ExtPageLength) {
1089 error = -ENXIO;
1090 goto out;
1091 }
1092
1093 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1094 &dma_handle);
1095 if (!buffer) {
1096 error = -ENOMEM;
1097 goto out;
1098 }
1099
1100 cfg.physAddr = dma_handle;
1101 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1102
1103 error = mpt_config(ioc, &cfg);
1104 if (error)
1105 goto out_free_consistent;
1106
1107 port_info->num_phys = buffer->NumPhys;
1108 port_info->phy_info = kcalloc(port_info->num_phys,
547f9a21 1109 sizeof(*port_info->phy_info),GFP_KERNEL);
0c33b27d
CH
1110 if (!port_info->phy_info) {
1111 error = -ENOMEM;
1112 goto out_free_consistent;
1113 }
1114
db9c9174
ME
1115 if (port_info->num_phys)
1116 port_info->handle =
1117 le16_to_cpu(buffer->PhyData[0].ControllerDevHandle);
0c33b27d
CH
1118 for (i = 0; i < port_info->num_phys; i++) {
1119 mptsas_print_phy_data(&buffer->PhyData[i]);
1120 port_info->phy_info[i].phy_id = i;
1121 port_info->phy_info[i].port_id =
1122 buffer->PhyData[i].Port;
1123 port_info->phy_info[i].negotiated_link_rate =
1124 buffer->PhyData[i].NegotiatedLinkRate;
547f9a21 1125 port_info->phy_info[i].portinfo = port_info;
0c33b27d
CH
1126 }
1127
1128 out_free_consistent:
1129 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1130 buffer, dma_handle);
1131 out:
1132 return error;
1133}
1134
1135static int
1136mptsas_sas_phy_pg0(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
1137 u32 form, u32 form_specific)
1138{
1139 ConfigExtendedPageHeader_t hdr;
1140 CONFIGPARMS cfg;
1141 SasPhyPage0_t *buffer;
1142 dma_addr_t dma_handle;
1143 int error;
1144
1145 hdr.PageVersion = MPI_SASPHY0_PAGEVERSION;
1146 hdr.ExtPageLength = 0;
1147 hdr.PageNumber = 0;
1148 hdr.Reserved1 = 0;
1149 hdr.Reserved2 = 0;
1150 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1151 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
1152
1153 cfg.cfghdr.ehdr = &hdr;
1154 cfg.dir = 0; /* read */
1155 cfg.timeout = 10;
1156
1157 /* Get Phy Pg 0 for each Phy. */
1158 cfg.physAddr = -1;
1159 cfg.pageAddr = form + form_specific;
1160 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1161
1162 error = mpt_config(ioc, &cfg);
1163 if (error)
1164 goto out;
1165
1166 if (!hdr.ExtPageLength) {
1167 error = -ENXIO;
1168 goto out;
1169 }
1170
1171 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1172 &dma_handle);
1173 if (!buffer) {
1174 error = -ENOMEM;
1175 goto out;
1176 }
1177
1178 cfg.physAddr = dma_handle;
1179 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1180
1181 error = mpt_config(ioc, &cfg);
1182 if (error)
1183 goto out_free_consistent;
1184
1185 mptsas_print_phy_pg0(buffer);
1186
1187 phy_info->hw_link_rate = buffer->HwLinkRate;
1188 phy_info->programmed_link_rate = buffer->ProgrammedLinkRate;
1189 phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle);
1190 phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle);
1191
1192 out_free_consistent:
1193 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1194 buffer, dma_handle);
1195 out:
1196 return error;
1197}
1198
1199static int
1200mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info,
1201 u32 form, u32 form_specific)
1202{
1203 ConfigExtendedPageHeader_t hdr;
1204 CONFIGPARMS cfg;
1205 SasDevicePage0_t *buffer;
1206 dma_addr_t dma_handle;
1207 __le64 sas_address;
bd23e94c
ME
1208 int error=0;
1209
1210 if (ioc->sas_discovery_runtime &&
1211 mptsas_is_end_device(device_info))
1212 goto out;
0c33b27d
CH
1213
1214 hdr.PageVersion = MPI_SASDEVICE0_PAGEVERSION;
1215 hdr.ExtPageLength = 0;
1216 hdr.PageNumber = 0;
1217 hdr.Reserved1 = 0;
1218 hdr.Reserved2 = 0;
1219 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1220 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE;
1221
1222 cfg.cfghdr.ehdr = &hdr;
1223 cfg.pageAddr = form + form_specific;
1224 cfg.physAddr = -1;
1225 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1226 cfg.dir = 0; /* read */
1227 cfg.timeout = 10;
1228
db9c9174 1229 memset(device_info, 0, sizeof(struct mptsas_devinfo));
0c33b27d
CH
1230 error = mpt_config(ioc, &cfg);
1231 if (error)
1232 goto out;
1233 if (!hdr.ExtPageLength) {
1234 error = -ENXIO;
1235 goto out;
1236 }
1237
1238 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1239 &dma_handle);
1240 if (!buffer) {
1241 error = -ENOMEM;
1242 goto out;
1243 }
1244
1245 cfg.physAddr = dma_handle;
1246 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1247
1248 error = mpt_config(ioc, &cfg);
1249 if (error)
1250 goto out_free_consistent;
1251
1252 mptsas_print_device_pg0(buffer);
1253
1254 device_info->handle = le16_to_cpu(buffer->DevHandle);
c73787ee 1255 device_info->handle_parent = le16_to_cpu(buffer->ParentDevHandle);
e3094447
CH
1256 device_info->handle_enclosure =
1257 le16_to_cpu(buffer->EnclosureHandle);
1258 device_info->slot = le16_to_cpu(buffer->Slot);
0c33b27d
CH
1259 device_info->phy_id = buffer->PhyNum;
1260 device_info->port_id = buffer->PhysicalPort;
9a28f49a
CH
1261 device_info->id = buffer->TargetID;
1262 device_info->channel = buffer->Bus;
0c33b27d
CH
1263 memcpy(&sas_address, &buffer->SASAddress, sizeof(__le64));
1264 device_info->sas_address = le64_to_cpu(sas_address);
1265 device_info->device_info =
1266 le32_to_cpu(buffer->DeviceInfo);
1267
1268 out_free_consistent:
1269 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1270 buffer, dma_handle);
1271 out:
1272 return error;
1273}
1274
1275static int
1276mptsas_sas_expander_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info,
1277 u32 form, u32 form_specific)
1278{
1279 ConfigExtendedPageHeader_t hdr;
1280 CONFIGPARMS cfg;
1281 SasExpanderPage0_t *buffer;
1282 dma_addr_t dma_handle;
547f9a21 1283 int i, error;
0c33b27d
CH
1284
1285 hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION;
1286 hdr.ExtPageLength = 0;
1287 hdr.PageNumber = 0;
1288 hdr.Reserved1 = 0;
1289 hdr.Reserved2 = 0;
1290 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1291 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
1292
1293 cfg.cfghdr.ehdr = &hdr;
1294 cfg.physAddr = -1;
1295 cfg.pageAddr = form + form_specific;
1296 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1297 cfg.dir = 0; /* read */
1298 cfg.timeout = 10;
1299
db9c9174 1300 memset(port_info, 0, sizeof(struct mptsas_portinfo));
0c33b27d
CH
1301 error = mpt_config(ioc, &cfg);
1302 if (error)
1303 goto out;
1304
1305 if (!hdr.ExtPageLength) {
1306 error = -ENXIO;
1307 goto out;
1308 }
1309
1310 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1311 &dma_handle);
1312 if (!buffer) {
1313 error = -ENOMEM;
1314 goto out;
1315 }
1316
1317 cfg.physAddr = dma_handle;
1318 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1319
1320 error = mpt_config(ioc, &cfg);
1321 if (error)
1322 goto out_free_consistent;
1323
1324 /* save config data */
1325 port_info->num_phys = buffer->NumPhys;
1326 port_info->handle = le16_to_cpu(buffer->DevHandle);
1327 port_info->phy_info = kcalloc(port_info->num_phys,
547f9a21 1328 sizeof(*port_info->phy_info),GFP_KERNEL);
0c33b27d
CH
1329 if (!port_info->phy_info) {
1330 error = -ENOMEM;
1331 goto out_free_consistent;
1332 }
1333
547f9a21
EM
1334 for (i = 0; i < port_info->num_phys; i++)
1335 port_info->phy_info[i].portinfo = port_info;
1336
0c33b27d
CH
1337 out_free_consistent:
1338 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1339 buffer, dma_handle);
1340 out:
1341 return error;
1342}
1343
1344static int
1345mptsas_sas_expander_pg1(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
1346 u32 form, u32 form_specific)
1347{
1348 ConfigExtendedPageHeader_t hdr;
1349 CONFIGPARMS cfg;
1350 SasExpanderPage1_t *buffer;
1351 dma_addr_t dma_handle;
bd23e94c
ME
1352 int error=0;
1353
1354 if (ioc->sas_discovery_runtime &&
1355 mptsas_is_end_device(&phy_info->attached))
1356 goto out;
0c33b27d
CH
1357
1358 hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION;
1359 hdr.ExtPageLength = 0;
1360 hdr.PageNumber = 1;
1361 hdr.Reserved1 = 0;
1362 hdr.Reserved2 = 0;
1363 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1364 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
1365
1366 cfg.cfghdr.ehdr = &hdr;
1367 cfg.physAddr = -1;
1368 cfg.pageAddr = form + form_specific;
1369 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1370 cfg.dir = 0; /* read */
1371 cfg.timeout = 10;
1372
1373 error = mpt_config(ioc, &cfg);
1374 if (error)
1375 goto out;
1376
1377 if (!hdr.ExtPageLength) {
1378 error = -ENXIO;
1379 goto out;
1380 }
1381
1382 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1383 &dma_handle);
1384 if (!buffer) {
1385 error = -ENOMEM;
1386 goto out;
1387 }
1388
1389 cfg.physAddr = dma_handle;
1390 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1391
1392 error = mpt_config(ioc, &cfg);
1393 if (error)
1394 goto out_free_consistent;
1395
1396
1397 mptsas_print_expander_pg1(buffer);
1398
1399 /* save config data */
024358ee 1400 phy_info->phy_id = buffer->PhyIdentifier;
0c33b27d
CH
1401 phy_info->port_id = buffer->PhysicalPort;
1402 phy_info->negotiated_link_rate = buffer->NegotiatedLinkRate;
1403 phy_info->programmed_link_rate = buffer->ProgrammedLinkRate;
1404 phy_info->hw_link_rate = buffer->HwLinkRate;
1405 phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle);
1406 phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle);
1407
0c33b27d
CH
1408 out_free_consistent:
1409 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1410 buffer, dma_handle);
1411 out:
1412 return error;
1413}
1414
1415static void
1416mptsas_parse_device_info(struct sas_identify *identify,
1417 struct mptsas_devinfo *device_info)
1418{
1419 u16 protocols;
1420
1421 identify->sas_address = device_info->sas_address;
1422 identify->phy_identifier = device_info->phy_id;
1423
1424 /*
1425 * Fill in Phy Initiator Port Protocol.
1426 * Bits 6:3, more than one bit can be set, fall through cases.
1427 */
1428 protocols = device_info->device_info & 0x78;
1429 identify->initiator_port_protocols = 0;
1430 if (protocols & MPI_SAS_DEVICE_INFO_SSP_INITIATOR)
1431 identify->initiator_port_protocols |= SAS_PROTOCOL_SSP;
1432 if (protocols & MPI_SAS_DEVICE_INFO_STP_INITIATOR)
1433 identify->initiator_port_protocols |= SAS_PROTOCOL_STP;
1434 if (protocols & MPI_SAS_DEVICE_INFO_SMP_INITIATOR)
1435 identify->initiator_port_protocols |= SAS_PROTOCOL_SMP;
1436 if (protocols & MPI_SAS_DEVICE_INFO_SATA_HOST)
1437 identify->initiator_port_protocols |= SAS_PROTOCOL_SATA;
1438
1439 /*
1440 * Fill in Phy Target Port Protocol.
1441 * Bits 10:7, more than one bit can be set, fall through cases.
1442 */
1443 protocols = device_info->device_info & 0x780;
1444 identify->target_port_protocols = 0;
1445 if (protocols & MPI_SAS_DEVICE_INFO_SSP_TARGET)
1446 identify->target_port_protocols |= SAS_PROTOCOL_SSP;
1447 if (protocols & MPI_SAS_DEVICE_INFO_STP_TARGET)
1448 identify->target_port_protocols |= SAS_PROTOCOL_STP;
1449 if (protocols & MPI_SAS_DEVICE_INFO_SMP_TARGET)
1450 identify->target_port_protocols |= SAS_PROTOCOL_SMP;
1451 if (protocols & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
1452 identify->target_port_protocols |= SAS_PROTOCOL_SATA;
1453
1454 /*
1455 * Fill in Attached device type.
1456 */
1457 switch (device_info->device_info &
1458 MPI_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) {
1459 case MPI_SAS_DEVICE_INFO_NO_DEVICE:
1460 identify->device_type = SAS_PHY_UNUSED;
1461 break;
1462 case MPI_SAS_DEVICE_INFO_END_DEVICE:
1463 identify->device_type = SAS_END_DEVICE;
1464 break;
1465 case MPI_SAS_DEVICE_INFO_EDGE_EXPANDER:
1466 identify->device_type = SAS_EDGE_EXPANDER_DEVICE;
1467 break;
1468 case MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER:
1469 identify->device_type = SAS_FANOUT_EXPANDER_DEVICE;
1470 break;
1471 }
1472}
1473
1474static int mptsas_probe_one_phy(struct device *dev,
ac01bbbd 1475 struct mptsas_phyinfo *phy_info, int index, int local)
0c33b27d 1476{
e6b2d76a 1477 MPT_ADAPTER *ioc;
9a28f49a 1478 struct sas_phy *phy;
547f9a21
EM
1479 struct sas_port *port;
1480 int error = 0;
0c33b27d 1481
547f9a21
EM
1482 if (!dev) {
1483 error = -ENODEV;
1484 goto out;
1485 }
e6b2d76a
ME
1486
1487 if (!phy_info->phy) {
1488 phy = sas_phy_alloc(dev, index);
547f9a21
EM
1489 if (!phy) {
1490 error = -ENOMEM;
1491 goto out;
1492 }
e6b2d76a
ME
1493 } else
1494 phy = phy_info->phy;
0c33b27d 1495
9a28f49a 1496 mptsas_parse_device_info(&phy->identify, &phy_info->identify);
0c33b27d
CH
1497
1498 /*
1499 * Set Negotiated link rate.
1500 */
1501 switch (phy_info->negotiated_link_rate) {
1502 case MPI_SAS_IOUNIT0_RATE_PHY_DISABLED:
9a28f49a 1503 phy->negotiated_linkrate = SAS_PHY_DISABLED;
0c33b27d
CH
1504 break;
1505 case MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION:
9a28f49a 1506 phy->negotiated_linkrate = SAS_LINK_RATE_FAILED;
0c33b27d
CH
1507 break;
1508 case MPI_SAS_IOUNIT0_RATE_1_5:
9a28f49a 1509 phy->negotiated_linkrate = SAS_LINK_RATE_1_5_GBPS;
0c33b27d
CH
1510 break;
1511 case MPI_SAS_IOUNIT0_RATE_3_0:
9a28f49a 1512 phy->negotiated_linkrate = SAS_LINK_RATE_3_0_GBPS;
0c33b27d
CH
1513 break;
1514 case MPI_SAS_IOUNIT0_RATE_SATA_OOB_COMPLETE:
1515 case MPI_SAS_IOUNIT0_RATE_UNKNOWN:
1516 default:
9a28f49a 1517 phy->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN;
0c33b27d
CH
1518 break;
1519 }
1520
1521 /*
1522 * Set Max hardware link rate.
1523 */
1524 switch (phy_info->hw_link_rate & MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
1525 case MPI_SAS_PHY0_HWRATE_MAX_RATE_1_5:
9a28f49a 1526 phy->maximum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
0c33b27d
CH
1527 break;
1528 case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
9a28f49a 1529 phy->maximum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
0c33b27d
CH
1530 break;
1531 default:
1532 break;
1533 }
1534
1535 /*
1536 * Set Max programmed link rate.
1537 */
1538 switch (phy_info->programmed_link_rate &
1539 MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
1540 case MPI_SAS_PHY0_PRATE_MAX_RATE_1_5:
9a28f49a 1541 phy->maximum_linkrate = SAS_LINK_RATE_1_5_GBPS;
0c33b27d
CH
1542 break;
1543 case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
9a28f49a 1544 phy->maximum_linkrate = SAS_LINK_RATE_3_0_GBPS;
0c33b27d
CH
1545 break;
1546 default:
1547 break;
1548 }
1549
1550 /*
1551 * Set Min hardware link rate.
1552 */
1553 switch (phy_info->hw_link_rate & MPI_SAS_PHY0_HWRATE_MIN_RATE_MASK) {
1554 case MPI_SAS_PHY0_HWRATE_MIN_RATE_1_5:
9a28f49a 1555 phy->minimum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
0c33b27d
CH
1556 break;
1557 case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
9a28f49a 1558 phy->minimum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
0c33b27d
CH
1559 break;
1560 default:
1561 break;
1562 }
1563
1564 /*
1565 * Set Min programmed link rate.
1566 */
1567 switch (phy_info->programmed_link_rate &
1568 MPI_SAS_PHY0_PRATE_MIN_RATE_MASK) {
1569 case MPI_SAS_PHY0_PRATE_MIN_RATE_1_5:
9a28f49a 1570 phy->minimum_linkrate = SAS_LINK_RATE_1_5_GBPS;
0c33b27d
CH
1571 break;
1572 case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
9a28f49a 1573 phy->minimum_linkrate = SAS_LINK_RATE_3_0_GBPS;
0c33b27d
CH
1574 break;
1575 default:
1576 break;
1577 }
1578
e6b2d76a 1579 if (!phy_info->phy) {
ac01bbbd 1580
e6b2d76a
ME
1581 error = sas_phy_add(phy);
1582 if (error) {
1583 sas_phy_free(phy);
547f9a21 1584 goto out;
e6b2d76a
ME
1585 }
1586 phy_info->phy = phy;
0c33b27d
CH
1587 }
1588
547f9a21
EM
1589 if (!phy_info->attached.handle ||
1590 !phy_info->port_details)
1591 goto out;
1592
1593 port = mptsas_get_port(phy_info);
1594 ioc = phy_to_ioc(phy_info->phy);
1595
1596 if (phy_info->sas_port_add_phy) {
1597
1598 if (!port) {
dc22f16d 1599 port = sas_port_alloc_num(dev);
547f9a21
EM
1600 if (!port) {
1601 error = -ENOMEM;
1602 goto out;
1603 }
1604 error = sas_port_add(port);
1605 if (error) {
1606 dfailprintk((MYIOC_s_ERR_FMT
1607 "%s: exit at line=%d\n", ioc->name,
1608 __FUNCTION__, __LINE__));
1609 goto out;
1610 }
1611 mptsas_set_port(phy_info, port);
dc22f16d
EM
1612 dsaswideprintk((KERN_DEBUG
1613 "sas_port_alloc: port=%p dev=%p port_id=%d\n",
1614 port, dev, port->port_identifier));
547f9a21
EM
1615 }
1616 dsaswideprintk((KERN_DEBUG "sas_port_add_phy: phy_id=%d\n",
1617 phy_info->phy_id));
1618 sas_port_add_phy(port, phy_info->phy);
1619 phy_info->sas_port_add_phy = 0;
1620 }
1621
1622 if (!mptsas_get_rphy(phy_info) && port && !port->rphy) {
e6b2d76a 1623
0c33b27d 1624 struct sas_rphy *rphy;
2686de27 1625 struct device *parent;
f013db32 1626 struct sas_identify identify;
0c33b27d 1627
2686de27 1628 parent = dev->parent->parent;
e6b2d76a
ME
1629 /*
1630 * Let the hotplug_work thread handle processing
1631 * the adding/removing of devices that occur
1632 * after start of day.
1633 */
1634 if (ioc->sas_discovery_runtime &&
1635 mptsas_is_end_device(&phy_info->attached))
547f9a21 1636 goto out;
e6b2d76a 1637
f013db32 1638 mptsas_parse_device_info(&identify, &phy_info->attached);
2686de27
JB
1639 if (scsi_is_host_device(parent)) {
1640 struct mptsas_portinfo *port_info;
1641 int i;
1642
1643 mutex_lock(&ioc->sas_topology_mutex);
1644 port_info = mptsas_find_portinfo_by_handle(ioc,
1645 ioc->handle);
1646 mutex_unlock(&ioc->sas_topology_mutex);
1647
1648 for (i = 0; i < port_info->num_phys; i++)
1649 if (port_info->phy_info[i].identify.sas_address ==
0c269e6d
JB
1650 identify.sas_address) {
1651 sas_port_mark_backlink(port);
2686de27 1652 goto out;
0c269e6d 1653 }
2686de27
JB
1654
1655 } else if (scsi_is_sas_rphy(parent)) {
1656 struct sas_rphy *parent_rphy = dev_to_rphy(parent);
1657 if (identify.sas_address ==
0c269e6d
JB
1658 parent_rphy->identify.sas_address) {
1659 sas_port_mark_backlink(port);
2686de27 1660 goto out;
0c269e6d 1661 }
2686de27
JB
1662 }
1663
f013db32
JB
1664 switch (identify.device_type) {
1665 case SAS_END_DEVICE:
547f9a21 1666 rphy = sas_end_device_alloc(port);
f013db32
JB
1667 break;
1668 case SAS_EDGE_EXPANDER_DEVICE:
1669 case SAS_FANOUT_EXPANDER_DEVICE:
547f9a21 1670 rphy = sas_expander_alloc(port, identify.device_type);
f013db32
JB
1671 break;
1672 default:
1673 rphy = NULL;
1674 break;
1675 }
547f9a21
EM
1676 if (!rphy) {
1677 dfailprintk((MYIOC_s_ERR_FMT
1678 "%s: exit at line=%d\n", ioc->name,
1679 __FUNCTION__, __LINE__));
1680 goto out;
1681 }
0c33b27d 1682
f013db32 1683 rphy->identify = identify;
0c33b27d
CH
1684 error = sas_rphy_add(rphy);
1685 if (error) {
547f9a21
EM
1686 dfailprintk((MYIOC_s_ERR_FMT
1687 "%s: exit at line=%d\n", ioc->name,
1688 __FUNCTION__, __LINE__));
0c33b27d 1689 sas_rphy_free(rphy);
547f9a21 1690 goto out;
0c33b27d 1691 }
547f9a21 1692 mptsas_set_rphy(phy_info, rphy);
0c33b27d
CH
1693 }
1694
547f9a21
EM
1695 out:
1696 return error;
0c33b27d
CH
1697}
1698
1699static int
e6b2d76a 1700mptsas_probe_hba_phys(MPT_ADAPTER *ioc)
0c33b27d 1701{
e6b2d76a 1702 struct mptsas_portinfo *port_info, *hba;
0c33b27d
CH
1703 u32 handle = 0xFFFF;
1704 int error = -ENOMEM, i;
1705
e6b2d76a
ME
1706 hba = kzalloc(sizeof(*port_info), GFP_KERNEL);
1707 if (! hba)
0c33b27d 1708 goto out;
0c33b27d 1709
e6b2d76a 1710 error = mptsas_sas_io_unit_pg0(ioc, hba);
0c33b27d
CH
1711 if (error)
1712 goto out_free_port_info;
1713
9a28f49a 1714 mutex_lock(&ioc->sas_topology_mutex);
2686de27 1715 ioc->handle = hba->handle;
e6b2d76a
ME
1716 port_info = mptsas_find_portinfo_by_handle(ioc, hba->handle);
1717 if (!port_info) {
1718 port_info = hba;
1719 list_add_tail(&port_info->list, &ioc->sas_topology);
1720 } else {
1721 port_info->handle = hba->handle;
1722 for (i = 0; i < hba->num_phys; i++)
1723 port_info->phy_info[i].negotiated_link_rate =
1724 hba->phy_info[i].negotiated_link_rate;
547f9a21 1725 kfree(hba->phy_info);
e6b2d76a
ME
1726 kfree(hba);
1727 hba = NULL;
1728 }
9a28f49a
CH
1729 mutex_unlock(&ioc->sas_topology_mutex);
1730
0c33b27d
CH
1731 for (i = 0; i < port_info->num_phys; i++) {
1732 mptsas_sas_phy_pg0(ioc, &port_info->phy_info[i],
1733 (MPI_SAS_PHY_PGAD_FORM_PHY_NUMBER <<
1734 MPI_SAS_PHY_PGAD_FORM_SHIFT), i);
1735
1736 mptsas_sas_device_pg0(ioc, &port_info->phy_info[i].identify,
1737 (MPI_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE <<
1738 MPI_SAS_DEVICE_PGAD_FORM_SHIFT), handle);
024358ee
EM
1739 port_info->phy_info[i].identify.phy_id =
1740 port_info->phy_info[i].phy_id;
0c33b27d
CH
1741 handle = port_info->phy_info[i].identify.handle;
1742
547f9a21 1743 if (port_info->phy_info[i].attached.handle)
0c33b27d
CH
1744 mptsas_sas_device_pg0(ioc,
1745 &port_info->phy_info[i].attached,
1746 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
1747 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
1748 port_info->phy_info[i].attached.handle);
547f9a21 1749 }
0c33b27d 1750
547f9a21
EM
1751 mptsas_setup_wide_ports(ioc, port_info);
1752
1753 for (i = 0; i < port_info->num_phys; i++, ioc->sas_index++)
0c33b27d 1754 mptsas_probe_one_phy(&ioc->sh->shost_gendev,
e6b2d76a 1755 &port_info->phy_info[i], ioc->sas_index, 1);
0c33b27d
CH
1756
1757 return 0;
1758
1759 out_free_port_info:
547f9a21 1760 kfree(hba);
0c33b27d
CH
1761 out:
1762 return error;
1763}
1764
1765static int
e6b2d76a 1766mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle)
0c33b27d 1767{
e6b2d76a 1768 struct mptsas_portinfo *port_info, *p, *ex;
547f9a21
EM
1769 struct device *parent;
1770 struct sas_rphy *rphy;
0c33b27d
CH
1771 int error = -ENOMEM, i, j;
1772
e6b2d76a
ME
1773 ex = kzalloc(sizeof(*port_info), GFP_KERNEL);
1774 if (!ex)
0c33b27d 1775 goto out;
0c33b27d 1776
e6b2d76a 1777 error = mptsas_sas_expander_pg0(ioc, ex,
0c33b27d
CH
1778 (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE <<
1779 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), *handle);
1780 if (error)
1781 goto out_free_port_info;
1782
e6b2d76a 1783 *handle = ex->handle;
0c33b27d 1784
9a28f49a 1785 mutex_lock(&ioc->sas_topology_mutex);
e6b2d76a
ME
1786 port_info = mptsas_find_portinfo_by_handle(ioc, *handle);
1787 if (!port_info) {
1788 port_info = ex;
1789 list_add_tail(&port_info->list, &ioc->sas_topology);
1790 } else {
1791 port_info->handle = ex->handle;
547f9a21 1792 kfree(ex->phy_info);
e6b2d76a
ME
1793 kfree(ex);
1794 ex = NULL;
1795 }
9a28f49a
CH
1796 mutex_unlock(&ioc->sas_topology_mutex);
1797
0c33b27d 1798 for (i = 0; i < port_info->num_phys; i++) {
0c33b27d
CH
1799 mptsas_sas_expander_pg1(ioc, &port_info->phy_info[i],
1800 (MPI_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM <<
1801 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), (i << 16) + *handle);
1802
1803 if (port_info->phy_info[i].identify.handle) {
1804 mptsas_sas_device_pg0(ioc,
1805 &port_info->phy_info[i].identify,
1806 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
1807 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
1808 port_info->phy_info[i].identify.handle);
024358ee
EM
1809 port_info->phy_info[i].identify.phy_id =
1810 port_info->phy_info[i].phy_id;
0c33b27d
CH
1811 }
1812
1813 if (port_info->phy_info[i].attached.handle) {
1814 mptsas_sas_device_pg0(ioc,
1815 &port_info->phy_info[i].attached,
1816 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
1817 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
1818 port_info->phy_info[i].attached.handle);
db9c9174
ME
1819 port_info->phy_info[i].attached.phy_id =
1820 port_info->phy_info[i].phy_id;
0c33b27d 1821 }
547f9a21 1822 }
0c33b27d 1823
547f9a21
EM
1824 parent = &ioc->sh->shost_gendev;
1825 for (i = 0; i < port_info->num_phys; i++) {
9a28f49a 1826 mutex_lock(&ioc->sas_topology_mutex);
0c33b27d
CH
1827 list_for_each_entry(p, &ioc->sas_topology, list) {
1828 for (j = 0; j < p->num_phys; j++) {
547f9a21 1829 if (port_info->phy_info[i].identify.handle !=
0c33b27d 1830 p->phy_info[j].attached.handle)
547f9a21
EM
1831 continue;
1832 rphy = mptsas_get_rphy(&p->phy_info[j]);
1833 parent = &rphy->dev;
0c33b27d
CH
1834 }
1835 }
9a28f49a 1836 mutex_unlock(&ioc->sas_topology_mutex);
547f9a21
EM
1837 }
1838
1839 mptsas_setup_wide_ports(ioc, port_info);
0c33b27d 1840
547f9a21 1841 for (i = 0; i < port_info->num_phys; i++, ioc->sas_index++)
ac01bbbd 1842 mptsas_probe_one_phy(parent, &port_info->phy_info[i],
e6b2d76a 1843 ioc->sas_index, 0);
0c33b27d
CH
1844
1845 return 0;
1846
1847 out_free_port_info:
e6b2d76a 1848 if (ex) {
547f9a21 1849 kfree(ex->phy_info);
e6b2d76a
ME
1850 kfree(ex);
1851 }
0c33b27d
CH
1852 out:
1853 return error;
1854}
1855
e6b2d76a
ME
1856/*
1857 * mptsas_delete_expander_phys
1858 *
1859 *
1860 * This will traverse topology, and remove expanders
1861 * that are no longer present
1862 */
1863static void
1864mptsas_delete_expander_phys(MPT_ADAPTER *ioc)
1865{
1866 struct mptsas_portinfo buffer;
1867 struct mptsas_portinfo *port_info, *n, *parent;
547f9a21
EM
1868 struct mptsas_phyinfo *phy_info;
1869 struct scsi_target * starget;
1870 VirtTarget * vtarget;
1871 struct sas_port * port;
e6b2d76a 1872 int i;
547f9a21 1873 u64 expander_sas_address;
e6b2d76a
ME
1874
1875 mutex_lock(&ioc->sas_topology_mutex);
1876 list_for_each_entry_safe(port_info, n, &ioc->sas_topology, list) {
1877
1878 if (port_info->phy_info &&
1879 (!(port_info->phy_info[0].identify.device_info &
1880 MPI_SAS_DEVICE_INFO_SMP_TARGET)))
1881 continue;
1882
1883 if (mptsas_sas_expander_pg0(ioc, &buffer,
1884 (MPI_SAS_EXPAND_PGAD_FORM_HANDLE <<
1885 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), port_info->handle)) {
1886
547f9a21
EM
1887 /*
1888 * Issue target reset to all child end devices
1889 * then mark them deleted to prevent further
1890 * IO going to them.
1891 */
1892 phy_info = port_info->phy_info;
1893 for (i = 0; i < port_info->num_phys; i++, phy_info++) {
1894 starget = mptsas_get_starget(phy_info);
1895 if (!starget)
1896 continue;
1897 vtarget = starget->hostdata;
1898 if(vtarget->deleted)
1899 continue;
1900 vtarget->deleted = 1;
1901 mptsas_target_reset(ioc, vtarget);
1902 sas_port_delete(mptsas_get_port(phy_info));
1903 mptsas_port_delete(phy_info->port_details);
1904 }
1905
e6b2d76a
ME
1906 /*
1907 * Obtain the port_info instance to the parent port
1908 */
1909 parent = mptsas_find_portinfo_by_handle(ioc,
1910 port_info->phy_info[0].identify.handle_parent);
1911
1912 if (!parent)
1913 goto next_port;
1914
547f9a21
EM
1915 expander_sas_address =
1916 port_info->phy_info[0].identify.sas_address;
1917
e6b2d76a
ME
1918 /*
1919 * Delete rphys in the parent that point
1920 * to this expander. The transport layer will
1921 * cleanup all the children.
1922 */
547f9a21
EM
1923 phy_info = parent->phy_info;
1924 for (i = 0; i < parent->num_phys; i++, phy_info++) {
1925 port = mptsas_get_port(phy_info);
1926 if (!port)
1927 continue;
1928 if (phy_info->attached.sas_address !=
1929 expander_sas_address)
e6b2d76a 1930 continue;
547f9a21 1931#ifdef MPT_DEBUG_SAS_WIDE
dc22f16d
EM
1932 dev_printk(KERN_DEBUG, &port->dev,
1933 "delete port (%d)\n", port->port_identifier);
547f9a21
EM
1934#endif
1935 sas_port_delete(port);
1936 mptsas_port_delete(phy_info->port_details);
e6b2d76a
ME
1937 }
1938 next_port:
547f9a21
EM
1939
1940 phy_info = port_info->phy_info;
1941 for (i = 0; i < port_info->num_phys; i++, phy_info++)
1942 mptsas_port_delete(phy_info->port_details);
1943
e6b2d76a 1944 list_del(&port_info->list);
547f9a21 1945 kfree(port_info->phy_info);
e6b2d76a
ME
1946 kfree(port_info);
1947 }
1948 /*
1949 * Free this memory allocated from inside
1950 * mptsas_sas_expander_pg0
1951 */
547f9a21 1952 kfree(buffer.phy_info);
e6b2d76a
ME
1953 }
1954 mutex_unlock(&ioc->sas_topology_mutex);
1955}
1956
1957/*
1958 * Start of day discovery
1959 */
0c33b27d
CH
1960static void
1961mptsas_scan_sas_topology(MPT_ADAPTER *ioc)
1962{
1963 u32 handle = 0xFFFF;
f44e5461 1964 int i;
0c33b27d 1965
e6b2d76a
ME
1966 mutex_lock(&ioc->sas_discovery_mutex);
1967 mptsas_probe_hba_phys(ioc);
1968 while (!mptsas_probe_expander_phys(ioc, &handle))
0c33b27d 1969 ;
f44e5461
ME
1970 /*
1971 Reporting RAID volumes.
1972 */
1973 if (!ioc->raid_data.pIocPg2)
1974 goto out;
1975 if (!ioc->raid_data.pIocPg2->NumActiveVolumes)
1976 goto out;
1977 for (i=0; i<ioc->raid_data.pIocPg2->NumActiveVolumes; i++) {
e8bf3941 1978 scsi_add_device(ioc->sh, MPTSAS_RAID_CHANNEL,
f44e5461
ME
1979 ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID, 0);
1980 }
1981 out:
e6b2d76a
ME
1982 mutex_unlock(&ioc->sas_discovery_mutex);
1983}
1984
1985/*
1986 * Work queue thread to handle Runtime discovery
1987 * Mere purpose is the hot add/delete of expanders
547f9a21 1988 *(Mutex UNLOCKED)
e6b2d76a
ME
1989 */
1990static void
547f9a21 1991__mptsas_discovery_work(MPT_ADAPTER *ioc)
e6b2d76a 1992{
e6b2d76a
ME
1993 u32 handle = 0xFFFF;
1994
e6b2d76a
ME
1995 ioc->sas_discovery_runtime=1;
1996 mptsas_delete_expander_phys(ioc);
1997 mptsas_probe_hba_phys(ioc);
1998 while (!mptsas_probe_expander_phys(ioc, &handle))
1999 ;
e6b2d76a 2000 ioc->sas_discovery_runtime=0;
547f9a21
EM
2001}
2002
2003/*
2004 * Work queue thread to handle Runtime discovery
2005 * Mere purpose is the hot add/delete of expanders
2006 *(Mutex LOCKED)
2007 */
2008static void
c4028958 2009mptsas_discovery_work(struct work_struct *work)
547f9a21 2010{
c4028958
DH
2011 struct mptsas_discovery_event *ev =
2012 container_of(work, struct mptsas_discovery_event, work);
547f9a21
EM
2013 MPT_ADAPTER *ioc = ev->ioc;
2014
2015 mutex_lock(&ioc->sas_discovery_mutex);
2016 __mptsas_discovery_work(ioc);
e6b2d76a 2017 mutex_unlock(&ioc->sas_discovery_mutex);
547f9a21 2018 kfree(ev);
0c33b27d
CH
2019}
2020
9a28f49a 2021static struct mptsas_phyinfo *
547f9a21 2022mptsas_find_phyinfo_by_sas_address(MPT_ADAPTER *ioc, u64 sas_address)
9a28f49a
CH
2023{
2024 struct mptsas_portinfo *port_info;
9a28f49a 2025 struct mptsas_phyinfo *phy_info = NULL;
547f9a21 2026 int i;
9a28f49a 2027
9a28f49a
CH
2028 mutex_lock(&ioc->sas_topology_mutex);
2029 list_for_each_entry(port_info, &ioc->sas_topology, list) {
2030 for (i = 0; i < port_info->num_phys; i++) {
547f9a21
EM
2031 if (port_info->phy_info[i].attached.sas_address
2032 != sas_address)
2033 continue;
2034 if (!mptsas_is_end_device(
2035 &port_info->phy_info[i].attached))
2036 continue;
2037 phy_info = &port_info->phy_info[i];
2038 break;
9a28f49a
CH
2039 }
2040 }
2041 mutex_unlock(&ioc->sas_topology_mutex);
9a28f49a
CH
2042 return phy_info;
2043}
2044
2045static struct mptsas_phyinfo *
c73787ee 2046mptsas_find_phyinfo_by_target(MPT_ADAPTER *ioc, u32 id)
9a28f49a
CH
2047{
2048 struct mptsas_portinfo *port_info;
2049 struct mptsas_phyinfo *phy_info = NULL;
2050 int i;
2051
9a28f49a
CH
2052 mutex_lock(&ioc->sas_topology_mutex);
2053 list_for_each_entry(port_info, &ioc->sas_topology, list) {
547f9a21
EM
2054 for (i = 0; i < port_info->num_phys; i++) {
2055 if (port_info->phy_info[i].attached.id != id)
2056 continue;
2057 if (!mptsas_is_end_device(
2058 &port_info->phy_info[i].attached))
2059 continue;
2060 phy_info = &port_info->phy_info[i];
2061 break;
2062 }
9a28f49a
CH
2063 }
2064 mutex_unlock(&ioc->sas_topology_mutex);
9a28f49a
CH
2065 return phy_info;
2066}
2067
4b766471
ME
2068/*
2069 * Work queue thread to clear the persitency table
2070 */
2071static void
c4028958 2072mptsas_persist_clear_table(struct work_struct *work)
4b766471 2073{
c4028958 2074 MPT_ADAPTER *ioc = container_of(work, MPT_ADAPTER, sas_persist_task);
4b766471
ME
2075
2076 mptbase_sas_persist_operation(ioc, MPI_SAS_OP_CLEAR_NOT_PRESENT);
2077}
2078
f44e5461
ME
2079static void
2080mptsas_reprobe_lun(struct scsi_device *sdev, void *data)
2081{
2082 sdev->no_uld_attach = data ? 1 : 0;
2083 scsi_device_reprobe(sdev);
2084}
2085
2086static void
2087mptsas_reprobe_target(struct scsi_target *starget, int uld_attach)
2088{
2089 starget_for_each_device(starget, uld_attach ? (void *)1 : NULL,
2090 mptsas_reprobe_lun);
2091}
2092
e6b2d76a
ME
2093/*
2094 * Work queue thread to handle SAS hotplug events
2095 */
9a28f49a 2096static void
c4028958 2097mptsas_hotplug_work(struct work_struct *work)
9a28f49a 2098{
c4028958
DH
2099 struct mptsas_hotplug_event *ev =
2100 container_of(work, struct mptsas_hotplug_event, work);
9a28f49a
CH
2101 MPT_ADAPTER *ioc = ev->ioc;
2102 struct mptsas_phyinfo *phy_info;
2103 struct sas_rphy *rphy;
547f9a21 2104 struct sas_port *port;
c73787ee 2105 struct scsi_device *sdev;
547f9a21 2106 struct scsi_target * starget;
f013db32 2107 struct sas_identify identify;
9a28f49a 2108 char *ds = NULL;
c73787ee 2109 struct mptsas_devinfo sas_device;
f44e5461 2110 VirtTarget *vtarget;
547f9a21 2111 VirtDevice *vdevice;
9a28f49a 2112
e6b2d76a 2113
547f9a21 2114 mutex_lock(&ioc->sas_discovery_mutex);
9a28f49a
CH
2115 switch (ev->event_type) {
2116 case MPTSAS_DEL_DEVICE:
9a28f49a 2117
c73787ee 2118 phy_info = mptsas_find_phyinfo_by_target(ioc, ev->id);
e6b2d76a 2119
f44e5461
ME
2120 /*
2121 * Sanity checks, for non-existing phys and remote rphys.
2122 */
547f9a21
EM
2123 if (!phy_info || !phy_info->port_details) {
2124 dfailprintk((MYIOC_s_ERR_FMT
2125 "%s: exit at line=%d\n", ioc->name,
2126 __FUNCTION__, __LINE__));
9a28f49a 2127 break;
547f9a21
EM
2128 }
2129 rphy = mptsas_get_rphy(phy_info);
2130 if (!rphy) {
2131 dfailprintk((MYIOC_s_ERR_FMT
2132 "%s: exit at line=%d\n", ioc->name,
2133 __FUNCTION__, __LINE__));
2134 break;
2135 }
2136 port = mptsas_get_port(phy_info);
2137 if (!port) {
2138 dfailprintk((MYIOC_s_ERR_FMT
2139 "%s: exit at line=%d\n", ioc->name,
2140 __FUNCTION__, __LINE__));
f44e5461 2141 break;
547f9a21
EM
2142 }
2143
2144 starget = mptsas_get_starget(phy_info);
2145 if (starget) {
2146 vtarget = starget->hostdata;
f44e5461 2147
547f9a21
EM
2148 if (!vtarget) {
2149 dfailprintk((MYIOC_s_ERR_FMT
2150 "%s: exit at line=%d\n", ioc->name,
2151 __FUNCTION__, __LINE__));
f44e5461 2152 break;
547f9a21
EM
2153 }
2154
f44e5461
ME
2155 /*
2156 * Handling RAID components
2157 */
2158 if (ev->phys_disk_num_valid) {
2159 vtarget->target_id = ev->phys_disk_num;
2160 vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT;
547f9a21 2161 mptsas_reprobe_target(starget, 1);
f44e5461
ME
2162 break;
2163 }
547f9a21
EM
2164
2165 vtarget->deleted = 1;
2166 mptsas_target_reset(ioc, vtarget);
9a28f49a
CH
2167 }
2168
c73787ee
ME
2169 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET)
2170 ds = "ssp";
2171 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_STP_TARGET)
2172 ds = "stp";
2173 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
2174 ds = "sata";
2175
2176 printk(MYIOC_s_INFO_FMT
2177 "removing %s device, channel %d, id %d, phy %d\n",
2178 ioc->name, ds, ev->channel, ev->id, phy_info->phy_id);
2179
547f9a21 2180#ifdef MPT_DEBUG_SAS_WIDE
dc22f16d
EM
2181 dev_printk(KERN_DEBUG, &port->dev,
2182 "delete port (%d)\n", port->port_identifier);
547f9a21
EM
2183#endif
2184 sas_port_delete(port);
2185 mptsas_port_delete(phy_info->port_details);
9a28f49a
CH
2186 break;
2187 case MPTSAS_ADD_DEVICE:
c73787ee 2188
bd23e94c
ME
2189 if (ev->phys_disk_num_valid)
2190 mpt_findImVolumes(ioc);
2191
c73787ee 2192 /*
e3094447 2193 * Refresh sas device pg0 data
c73787ee 2194 */
e3094447
CH
2195 if (mptsas_sas_device_pg0(ioc, &sas_device,
2196 (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
547f9a21
EM
2197 MPI_SAS_DEVICE_PGAD_FORM_SHIFT), ev->id)) {
2198 dfailprintk((MYIOC_s_ERR_FMT
2199 "%s: exit at line=%d\n", ioc->name,
2200 __FUNCTION__, __LINE__));
e3094447 2201 break;
547f9a21 2202 }
9a28f49a 2203
547f9a21
EM
2204 ssleep(2);
2205 __mptsas_discovery_work(ioc);
e6b2d76a 2206
547f9a21
EM
2207 phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
2208 sas_device.sas_address);
e6b2d76a 2209
547f9a21
EM
2210 if (!phy_info || !phy_info->port_details) {
2211 dfailprintk((MYIOC_s_ERR_FMT
2212 "%s: exit at line=%d\n", ioc->name,
2213 __FUNCTION__, __LINE__));
2214 break;
e6b2d76a
ME
2215 }
2216
547f9a21
EM
2217 starget = mptsas_get_starget(phy_info);
2218 if (starget) {
2219 vtarget = starget->hostdata;
9a28f49a 2220
547f9a21
EM
2221 if (!vtarget) {
2222 dfailprintk((MYIOC_s_ERR_FMT
2223 "%s: exit at line=%d\n", ioc->name,
2224 __FUNCTION__, __LINE__));
f44e5461 2225 break;
547f9a21 2226 }
f44e5461
ME
2227 /*
2228 * Handling RAID components
2229 */
2230 if (vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) {
2231 vtarget->tflags &= ~MPT_TARGET_FLAGS_RAID_COMPONENT;
2232 vtarget->target_id = ev->id;
547f9a21 2233 mptsas_reprobe_target(starget, 0);
f44e5461 2234 }
9a28f49a
CH
2235 break;
2236 }
2237
547f9a21
EM
2238 if (mptsas_get_rphy(phy_info)) {
2239 dfailprintk((MYIOC_s_ERR_FMT
2240 "%s: exit at line=%d\n", ioc->name,
2241 __FUNCTION__, __LINE__));
f44e5461 2242 break;
547f9a21
EM
2243 }
2244 port = mptsas_get_port(phy_info);
2245 if (!port) {
2246 dfailprintk((MYIOC_s_ERR_FMT
2247 "%s: exit at line=%d\n", ioc->name,
2248 __FUNCTION__, __LINE__));
2249 break;
2250 }
f44e5461 2251
e3094447
CH
2252 memcpy(&phy_info->attached, &sas_device,
2253 sizeof(struct mptsas_devinfo));
9a28f49a 2254
c73787ee
ME
2255 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET)
2256 ds = "ssp";
2257 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_STP_TARGET)
2258 ds = "stp";
2259 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
2260 ds = "sata";
2261
2262 printk(MYIOC_s_INFO_FMT
2263 "attaching %s device, channel %d, id %d, phy %d\n",
2264 ioc->name, ds, ev->channel, ev->id, ev->phy_id);
2265
f013db32 2266 mptsas_parse_device_info(&identify, &phy_info->attached);
547f9a21
EM
2267 rphy = sas_end_device_alloc(port);
2268 if (!rphy) {
2269 dfailprintk((MYIOC_s_ERR_FMT
2270 "%s: exit at line=%d\n", ioc->name,
2271 __FUNCTION__, __LINE__));
9a28f49a 2272 break; /* non-fatal: an rphy can be added later */
547f9a21 2273 }
9a28f49a 2274
f013db32 2275 rphy->identify = identify;
9a28f49a 2276 if (sas_rphy_add(rphy)) {
547f9a21
EM
2277 dfailprintk((MYIOC_s_ERR_FMT
2278 "%s: exit at line=%d\n", ioc->name,
2279 __FUNCTION__, __LINE__));
9a28f49a
CH
2280 sas_rphy_free(rphy);
2281 break;
2282 }
547f9a21 2283 mptsas_set_rphy(phy_info, rphy);
9a28f49a 2284 break;
c73787ee 2285 case MPTSAS_ADD_RAID:
e8bf3941
JB
2286 sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL,
2287 ev->id, 0);
c73787ee
ME
2288 if (sdev) {
2289 scsi_device_put(sdev);
2290 break;
2291 }
2292 printk(MYIOC_s_INFO_FMT
4b766471 2293 "attaching raid volume, channel %d, id %d\n",
e8bf3941
JB
2294 ioc->name, MPTSAS_RAID_CHANNEL, ev->id);
2295 scsi_add_device(ioc->sh, MPTSAS_RAID_CHANNEL, ev->id, 0);
c73787ee
ME
2296 mpt_findImVolumes(ioc);
2297 break;
2298 case MPTSAS_DEL_RAID:
e8bf3941
JB
2299 sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL,
2300 ev->id, 0);
c73787ee
ME
2301 if (!sdev)
2302 break;
2303 printk(MYIOC_s_INFO_FMT
4b766471 2304 "removing raid volume, channel %d, id %d\n",
e8bf3941 2305 ioc->name, MPTSAS_RAID_CHANNEL, ev->id);
547f9a21
EM
2306 vdevice = sdev->hostdata;
2307 vdevice->vtarget->deleted = 1;
2308 mptsas_target_reset(ioc, vdevice->vtarget);
c73787ee
ME
2309 scsi_remove_device(sdev);
2310 scsi_device_put(sdev);
2311 mpt_findImVolumes(ioc);
2312 break;
bd23e94c
ME
2313 case MPTSAS_IGNORE_EVENT:
2314 default:
2315 break;
9a28f49a
CH
2316 }
2317
e6b2d76a 2318 mutex_unlock(&ioc->sas_discovery_mutex);
547f9a21
EM
2319 kfree(ev);
2320
9a28f49a
CH
2321}
2322
2323static void
547f9a21 2324mptsas_send_sas_event(MPT_ADAPTER *ioc,
9a28f49a
CH
2325 EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data)
2326{
2327 struct mptsas_hotplug_event *ev;
2328 u32 device_info = le32_to_cpu(sas_event_data->DeviceInfo);
2329 __le64 sas_address;
2330
2331 if ((device_info &
2332 (MPI_SAS_DEVICE_INFO_SSP_TARGET |
2333 MPI_SAS_DEVICE_INFO_STP_TARGET |
2334 MPI_SAS_DEVICE_INFO_SATA_DEVICE )) == 0)
2335 return;
2336
4b766471
ME
2337 switch (sas_event_data->ReasonCode) {
2338 case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
2339 case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
547f9a21 2340 ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
4b766471
ME
2341 if (!ev) {
2342 printk(KERN_WARNING "mptsas: lost hotplug event\n");
2343 break;
2344 }
9a28f49a 2345
c4028958 2346 INIT_WORK(&ev->work, mptsas_hotplug_work);
4b766471
ME
2347 ev->ioc = ioc;
2348 ev->handle = le16_to_cpu(sas_event_data->DevHandle);
2349 ev->parent_handle =
2350 le16_to_cpu(sas_event_data->ParentDevHandle);
2351 ev->channel = sas_event_data->Bus;
2352 ev->id = sas_event_data->TargetID;
2353 ev->phy_id = sas_event_data->PhyNum;
2354 memcpy(&sas_address, &sas_event_data->SASAddress,
2355 sizeof(__le64));
2356 ev->sas_address = le64_to_cpu(sas_address);
2357 ev->device_info = device_info;
2358
2359 if (sas_event_data->ReasonCode &
2360 MPI_EVENT_SAS_DEV_STAT_RC_ADDED)
2361 ev->event_type = MPTSAS_ADD_DEVICE;
2362 else
2363 ev->event_type = MPTSAS_DEL_DEVICE;
2364 schedule_work(&ev->work);
2365 break;
2366 case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED:
2367 /*
2368 * Persistent table is full.
2369 */
547f9a21 2370 INIT_WORK(&ioc->sas_persist_task,
c4028958 2371 mptsas_persist_clear_table);
547f9a21 2372 schedule_work(&ioc->sas_persist_task);
4b766471
ME
2373 break;
2374 case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
2375 /* TODO */
2376 case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
2377 /* TODO */
2378 default:
2379 break;
9a28f49a 2380 }
9a28f49a
CH
2381}
2382
c73787ee 2383static void
547f9a21 2384mptsas_send_raid_event(MPT_ADAPTER *ioc,
c73787ee
ME
2385 EVENT_DATA_RAID *raid_event_data)
2386{
2387 struct mptsas_hotplug_event *ev;
bd23e94c
ME
2388 int status = le32_to_cpu(raid_event_data->SettingsStatus);
2389 int state = (status >> 8) & 0xff;
c73787ee
ME
2390
2391 if (ioc->bus_type != SAS)
2392 return;
2393
547f9a21 2394 ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
c73787ee
ME
2395 if (!ev) {
2396 printk(KERN_WARNING "mptsas: lost hotplug event\n");
2397 return;
2398 }
2399
c4028958 2400 INIT_WORK(&ev->work, mptsas_hotplug_work);
c73787ee
ME
2401 ev->ioc = ioc;
2402 ev->id = raid_event_data->VolumeID;
bd23e94c 2403 ev->event_type = MPTSAS_IGNORE_EVENT;
c73787ee
ME
2404
2405 switch (raid_event_data->ReasonCode) {
2406 case MPI_EVENT_RAID_RC_PHYSDISK_DELETED:
2407 ev->event_type = MPTSAS_ADD_DEVICE;
2408 break;
2409 case MPI_EVENT_RAID_RC_PHYSDISK_CREATED:
f44e5461
ME
2410 ioc->raid_data.isRaid = 1;
2411 ev->phys_disk_num_valid = 1;
2412 ev->phys_disk_num = raid_event_data->PhysDiskNum;
c73787ee
ME
2413 ev->event_type = MPTSAS_DEL_DEVICE;
2414 break;
bd23e94c
ME
2415 case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED:
2416 switch (state) {
2417 case MPI_PD_STATE_ONLINE:
2418 ioc->raid_data.isRaid = 1;
2419 ev->phys_disk_num_valid = 1;
2420 ev->phys_disk_num = raid_event_data->PhysDiskNum;
2421 ev->event_type = MPTSAS_ADD_DEVICE;
2422 break;
2423 case MPI_PD_STATE_MISSING:
2424 case MPI_PD_STATE_NOT_COMPATIBLE:
2425 case MPI_PD_STATE_OFFLINE_AT_HOST_REQUEST:
2426 case MPI_PD_STATE_FAILED_AT_HOST_REQUEST:
2427 case MPI_PD_STATE_OFFLINE_FOR_ANOTHER_REASON:
2428 ev->event_type = MPTSAS_DEL_DEVICE;
2429 break;
2430 default:
2431 break;
2432 }
2433 break;
c73787ee
ME
2434 case MPI_EVENT_RAID_RC_VOLUME_DELETED:
2435 ev->event_type = MPTSAS_DEL_RAID;
2436 break;
2437 case MPI_EVENT_RAID_RC_VOLUME_CREATED:
2438 ev->event_type = MPTSAS_ADD_RAID;
2439 break;
2440 case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED:
bd23e94c
ME
2441 switch (state) {
2442 case MPI_RAIDVOL0_STATUS_STATE_FAILED:
2443 case MPI_RAIDVOL0_STATUS_STATE_MISSING:
2444 ev->event_type = MPTSAS_DEL_RAID;
2445 break;
2446 case MPI_RAIDVOL0_STATUS_STATE_OPTIMAL:
2447 case MPI_RAIDVOL0_STATUS_STATE_DEGRADED:
2448 ev->event_type = MPTSAS_ADD_RAID;
2449 break;
2450 default:
2451 break;
2452 }
c73787ee
ME
2453 break;
2454 default:
2455 break;
2456 }
2457 schedule_work(&ev->work);
2458}
2459
e6b2d76a 2460static void
547f9a21 2461mptsas_send_discovery_event(MPT_ADAPTER *ioc,
e6b2d76a
ME
2462 EVENT_DATA_SAS_DISCOVERY *discovery_data)
2463{
2464 struct mptsas_discovery_event *ev;
2465
2466 /*
2467 * DiscoveryStatus
2468 *
2469 * This flag will be non-zero when firmware
2470 * kicks off discovery, and return to zero
2471 * once its completed.
2472 */
2473 if (discovery_data->DiscoveryStatus)
2474 return;
2475
547f9a21 2476 ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
e6b2d76a
ME
2477 if (!ev)
2478 return;
c4028958 2479 INIT_WORK(&ev->work, mptsas_discovery_work);
e6b2d76a
ME
2480 ev->ioc = ioc;
2481 schedule_work(&ev->work);
2482};
2483
2484
9a28f49a
CH
2485static int
2486mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
2487{
c73787ee 2488 int rc=1;
9a28f49a
CH
2489 u8 event = le32_to_cpu(reply->Event) & 0xFF;
2490
2491 if (!ioc->sh)
c73787ee 2492 goto out;
9a28f49a 2493
e6b2d76a
ME
2494 /*
2495 * sas_discovery_ignore_events
2496 *
2497 * This flag is to prevent anymore processing of
2498 * sas events once mptsas_remove function is called.
2499 */
2500 if (ioc->sas_discovery_ignore_events) {
2501 rc = mptscsih_event_process(ioc, reply);
2502 goto out;
2503 }
2504
9a28f49a
CH
2505 switch (event) {
2506 case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
547f9a21 2507 mptsas_send_sas_event(ioc,
9a28f49a 2508 (EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)reply->Data);
c73787ee
ME
2509 break;
2510 case MPI_EVENT_INTEGRATED_RAID:
547f9a21 2511 mptsas_send_raid_event(ioc,
c73787ee
ME
2512 (EVENT_DATA_RAID *)reply->Data);
2513 break;
79de278e 2514 case MPI_EVENT_PERSISTENT_TABLE_FULL:
547f9a21 2515 INIT_WORK(&ioc->sas_persist_task,
c4028958 2516 mptsas_persist_clear_table);
547f9a21 2517 schedule_work(&ioc->sas_persist_task);
79de278e 2518 break;
4b766471 2519 case MPI_EVENT_SAS_DISCOVERY:
547f9a21 2520 mptsas_send_discovery_event(ioc,
e6b2d76a
ME
2521 (EVENT_DATA_SAS_DISCOVERY *)reply->Data);
2522 break;
9a28f49a 2523 default:
c73787ee
ME
2524 rc = mptscsih_event_process(ioc, reply);
2525 break;
9a28f49a 2526 }
c73787ee
ME
2527 out:
2528
2529 return rc;
9a28f49a
CH
2530}
2531
0c33b27d
CH
2532static int
2533mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
2534{
2535 struct Scsi_Host *sh;
2536 MPT_SCSI_HOST *hd;
2537 MPT_ADAPTER *ioc;
2538 unsigned long flags;
1ca00bb7 2539 int ii;
0c33b27d
CH
2540 int numSGE = 0;
2541 int scale;
2542 int ioc_cap;
0c33b27d
CH
2543 int error=0;
2544 int r;
2545
2546 r = mpt_attach(pdev,id);
2547 if (r)
2548 return r;
2549
2550 ioc = pci_get_drvdata(pdev);
2551 ioc->DoneCtx = mptsasDoneCtx;
2552 ioc->TaskCtx = mptsasTaskCtx;
2553 ioc->InternalCtx = mptsasInternalCtx;
2554
2555 /* Added sanity check on readiness of the MPT adapter.
2556 */
2557 if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
2558 printk(MYIOC_s_WARN_FMT
2559 "Skipping because it's not operational!\n",
2560 ioc->name);
7acec1e7
MED
2561 error = -ENODEV;
2562 goto out_mptsas_probe;
0c33b27d
CH
2563 }
2564
2565 if (!ioc->active) {
2566 printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
2567 ioc->name);
7acec1e7
MED
2568 error = -ENODEV;
2569 goto out_mptsas_probe;
0c33b27d
CH
2570 }
2571
2572 /* Sanity check - ensure at least 1 port is INITIATOR capable
2573 */
2574 ioc_cap = 0;
2575 for (ii = 0; ii < ioc->facts.NumberOfPorts; ii++) {
2576 if (ioc->pfacts[ii].ProtocolFlags &
2577 MPI_PORTFACTS_PROTOCOL_INITIATOR)
2578 ioc_cap++;
2579 }
2580
2581 if (!ioc_cap) {
2582 printk(MYIOC_s_WARN_FMT
2583 "Skipping ioc=%p because SCSI Initiator mode "
2584 "is NOT enabled!\n", ioc->name, ioc);
466544d8 2585 return 0;
0c33b27d
CH
2586 }
2587
2588 sh = scsi_host_alloc(&mptsas_driver_template, sizeof(MPT_SCSI_HOST));
2589 if (!sh) {
2590 printk(MYIOC_s_WARN_FMT
2591 "Unable to register controller with SCSI subsystem\n",
2592 ioc->name);
7acec1e7
MED
2593 error = -1;
2594 goto out_mptsas_probe;
0c33b27d
CH
2595 }
2596
2597 spin_lock_irqsave(&ioc->FreeQlock, flags);
2598
2599 /* Attach the SCSI Host to the IOC structure
2600 */
2601 ioc->sh = sh;
2602
2603 sh->io_port = 0;
2604 sh->n_io_port = 0;
2605 sh->irq = 0;
2606
2607 /* set 16 byte cdb's */
2608 sh->max_cmd_len = 16;
2609
2610 sh->max_id = ioc->pfacts->MaxDevices + 1;
2611
2612 sh->transportt = mptsas_transport_template;
2613
2614 sh->max_lun = MPT_LAST_LUN + 1;
2615 sh->max_channel = 0;
2616 sh->this_id = ioc->pfacts[0].PortSCSIID;
2617
2618 /* Required entry.
2619 */
2620 sh->unique_id = ioc->id;
2621
2622 INIT_LIST_HEAD(&ioc->sas_topology);
9a28f49a 2623 mutex_init(&ioc->sas_topology_mutex);
e6b2d76a 2624 mutex_init(&ioc->sas_discovery_mutex);
eeb846ce 2625 mutex_init(&ioc->sas_mgmt.mutex);
da4fa655 2626 init_completion(&ioc->sas_mgmt.done);
0c33b27d
CH
2627
2628 /* Verify that we won't exceed the maximum
2629 * number of chain buffers
2630 * We can optimize: ZZ = req_sz/sizeof(SGE)
2631 * For 32bit SGE's:
2632 * numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
2633 * + (req_sz - 64)/sizeof(SGE)
2634 * A slightly different algorithm is required for
2635 * 64bit SGEs.
2636 */
2637 scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
2638 if (sizeof(dma_addr_t) == sizeof(u64)) {
2639 numSGE = (scale - 1) *
2640 (ioc->facts.MaxChainDepth-1) + scale +
2641 (ioc->req_sz - 60) / (sizeof(dma_addr_t) +
2642 sizeof(u32));
2643 } else {
2644 numSGE = 1 + (scale - 1) *
2645 (ioc->facts.MaxChainDepth-1) + scale +
2646 (ioc->req_sz - 64) / (sizeof(dma_addr_t) +
2647 sizeof(u32));
2648 }
2649
2650 if (numSGE < sh->sg_tablesize) {
2651 /* Reset this value */
2652 dprintk((MYIOC_s_INFO_FMT
2653 "Resetting sg_tablesize to %d from %d\n",
2654 ioc->name, numSGE, sh->sg_tablesize));
2655 sh->sg_tablesize = numSGE;
2656 }
2657
2658 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
2659
2660 hd = (MPT_SCSI_HOST *) sh->hostdata;
2661 hd->ioc = ioc;
2662
2663 /* SCSI needs scsi_cmnd lookup table!
2664 * (with size equal to req_depth*PtrSz!)
2665 */
1ca00bb7
CH
2666 hd->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);
2667 if (!hd->ScsiLookup) {
0c33b27d 2668 error = -ENOMEM;
7acec1e7 2669 goto out_mptsas_probe;
0c33b27d
CH
2670 }
2671
1ca00bb7
CH
2672 dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n",
2673 ioc->name, hd->ScsiLookup));
0c33b27d
CH
2674
2675 /* Allocate memory for the device structures.
2676 * A non-Null pointer at an offset
2677 * indicates a device exists.
2678 * max_id = 1 + maximum id (hosts.h)
2679 */
1ca00bb7
CH
2680 hd->Targets = kcalloc(sh->max_id, sizeof(void *), GFP_ATOMIC);
2681 if (!hd->Targets) {
0c33b27d 2682 error = -ENOMEM;
7acec1e7 2683 goto out_mptsas_probe;
0c33b27d
CH
2684 }
2685
1ca00bb7 2686 dprintk((KERN_INFO " vtarget @ %p\n", hd->Targets));
0c33b27d
CH
2687
2688 /* Clear the TM flags
2689 */
2690 hd->tmPending = 0;
2691 hd->tmState = TM_STATE_NONE;
2692 hd->resetPending = 0;
2693 hd->abortSCpnt = NULL;
2694
2695 /* Clear the pointer used to store
2696 * single-threaded commands, i.e., those
2697 * issued during a bus scan, dv and
2698 * configuration pages.
2699 */
2700 hd->cmdPtr = NULL;
2701
2702 /* Initialize this SCSI Hosts' timers
2703 * To use, set the timer expires field
2704 * and add_timer
2705 */
2706 init_timer(&hd->timer);
2707 hd->timer.data = (unsigned long) hd;
2708 hd->timer.function = mptscsih_timer_expired;
2709
0c33b27d
CH
2710 ioc->sas_data.ptClear = mpt_pt_clear;
2711
2712 if (ioc->sas_data.ptClear==1) {
2713 mptbase_sas_persist_operation(
2714 ioc, MPI_SAS_OP_CLEAR_ALL_PERSISTENT);
2715 }
2716
0c33b27d
CH
2717 init_waitqueue_head(&hd->scandv_waitq);
2718 hd->scandv_wait_done = 0;
2719 hd->last_queue_full = 0;
2720
2721 error = scsi_add_host(sh, &ioc->pcidev->dev);
2722 if (error) {
2723 dprintk((KERN_ERR MYNAM
2724 "scsi_add_host failed\n"));
7acec1e7 2725 goto out_mptsas_probe;
0c33b27d
CH
2726 }
2727
2728 mptsas_scan_sas_topology(ioc);
2729
2730 return 0;
2731
547f9a21 2732 out_mptsas_probe:
0c33b27d
CH
2733
2734 mptscsih_remove(pdev);
2735 return error;
2736}
2737
2738static void __devexit mptsas_remove(struct pci_dev *pdev)
2739{
2740 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
2741 struct mptsas_portinfo *p, *n;
547f9a21 2742 int i;
0c33b27d 2743
e6b2d76a 2744 ioc->sas_discovery_ignore_events=1;
0c33b27d
CH
2745 sas_remove_host(ioc->sh);
2746
9a28f49a 2747 mutex_lock(&ioc->sas_topology_mutex);
0c33b27d
CH
2748 list_for_each_entry_safe(p, n, &ioc->sas_topology, list) {
2749 list_del(&p->list);
547f9a21
EM
2750 for (i = 0 ; i < p->num_phys ; i++)
2751 mptsas_port_delete(p->phy_info[i].port_details);
2752 kfree(p->phy_info);
0c33b27d
CH
2753 kfree(p);
2754 }
9a28f49a 2755 mutex_unlock(&ioc->sas_topology_mutex);
0c33b27d
CH
2756
2757 mptscsih_remove(pdev);
2758}
2759
2760static struct pci_device_id mptsas_pci_table[] = {
87cf8986 2761 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1064,
0c33b27d 2762 PCI_ANY_ID, PCI_ANY_ID },
87cf8986 2763 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1068,
0c33b27d 2764 PCI_ANY_ID, PCI_ANY_ID },
87cf8986 2765 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1064E,
0c33b27d 2766 PCI_ANY_ID, PCI_ANY_ID },
87cf8986 2767 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1068E,
0c33b27d 2768 PCI_ANY_ID, PCI_ANY_ID },
87cf8986 2769 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1078,
0c33b27d
CH
2770 PCI_ANY_ID, PCI_ANY_ID },
2771 {0} /* Terminating entry */
2772};
2773MODULE_DEVICE_TABLE(pci, mptsas_pci_table);
2774
2775
2776static struct pci_driver mptsas_driver = {
2777 .name = "mptsas",
2778 .id_table = mptsas_pci_table,
2779 .probe = mptsas_probe,
2780 .remove = __devexit_p(mptsas_remove),
2781 .shutdown = mptscsih_shutdown,
2782#ifdef CONFIG_PM
2783 .suspend = mptscsih_suspend,
2784 .resume = mptscsih_resume,
2785#endif
2786};
2787
2788static int __init
2789mptsas_init(void)
2790{
2791 show_mptmod_ver(my_NAME, my_VERSION);
2792
2793 mptsas_transport_template =
2794 sas_attach_transport(&mptsas_transport_functions);
2795 if (!mptsas_transport_template)
2796 return -ENODEV;
2797
2798 mptsasDoneCtx = mpt_register(mptscsih_io_done, MPTSAS_DRIVER);
2799 mptsasTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSAS_DRIVER);
2800 mptsasInternalCtx =
2801 mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER);
da4fa655 2802 mptsasMgmtCtx = mpt_register(mptsas_mgmt_done, MPTSAS_DRIVER);
0c33b27d 2803
9a28f49a 2804 if (mpt_event_register(mptsasDoneCtx, mptsas_event_process) == 0) {
3a892bef 2805 devtverboseprintk((KERN_INFO MYNAM
0c33b27d
CH
2806 ": Registered for IOC event notifications\n"));
2807 }
2808
2809 if (mpt_reset_register(mptsasDoneCtx, mptscsih_ioc_reset) == 0) {
2810 dprintk((KERN_INFO MYNAM
2811 ": Registered for IOC reset notifications\n"));
2812 }
2813
2814 return pci_register_driver(&mptsas_driver);
2815}
2816
2817static void __exit
2818mptsas_exit(void)
2819{
2820 pci_unregister_driver(&mptsas_driver);
2821 sas_release_transport(mptsas_transport_template);
2822
2823 mpt_reset_deregister(mptsasDoneCtx);
2824 mpt_event_deregister(mptsasDoneCtx);
2825
da4fa655 2826 mpt_deregister(mptsasMgmtCtx);
0c33b27d
CH
2827 mpt_deregister(mptsasInternalCtx);
2828 mpt_deregister(mptsasTaskCtx);
2829 mpt_deregister(mptsasDoneCtx);
2830}
2831
2832module_init(mptsas_init);
2833module_exit(mptsas_exit);