[SCSI] megaraid: Add support for change_queue_depth
[GitHub/mt8127/android_kernel_alcatel_ttab.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
b5141128
CH
855 hdr.PageVersion = MPI_SASPHY1_PAGEVERSION;
856 hdr.ExtPageLength = 0;
857 hdr.PageNumber = 1 /* page number 1*/;
858 hdr.Reserved1 = 0;
859 hdr.Reserved2 = 0;
860 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
861 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
0c33b27d 862
b5141128
CH
863 cfg.cfghdr.ehdr = &hdr;
864 cfg.physAddr = -1;
865 cfg.pageAddr = phy->identify.phy_identifier;
866 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
867 cfg.dir = 0; /* read */
868 cfg.timeout = 10;
0c33b27d 869
b5141128
CH
870 error = mpt_config(ioc, &cfg);
871 if (error)
872 return error;
873 if (!hdr.ExtPageLength)
874 return -ENXIO;
0c33b27d 875
b5141128
CH
876 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
877 &dma_handle);
878 if (!buffer)
879 return -ENOMEM;
0c33b27d 880
b5141128
CH
881 cfg.physAddr = dma_handle;
882 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
883
884 error = mpt_config(ioc, &cfg);
885 if (error)
886 goto out_free_consistent;
887
888 mptsas_print_phy_pg1(buffer);
889
890 phy->invalid_dword_count = le32_to_cpu(buffer->InvalidDwordCount);
891 phy->running_disparity_error_count =
892 le32_to_cpu(buffer->RunningDisparityErrorCount);
893 phy->loss_of_dword_sync_count =
894 le32_to_cpu(buffer->LossDwordSynchCount);
895 phy->phy_reset_problem_count =
896 le32_to_cpu(buffer->PhyResetProblemCount);
897
898 out_free_consistent:
899 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
900 buffer, dma_handle);
901 return error;
0c33b27d
CH
902}
903
da4fa655
CH
904static int mptsas_mgmt_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req,
905 MPT_FRAME_HDR *reply)
906{
907 ioc->sas_mgmt.status |= MPT_SAS_MGMT_STATUS_COMMAND_GOOD;
908 if (reply != NULL) {
909 ioc->sas_mgmt.status |= MPT_SAS_MGMT_STATUS_RF_VALID;
910 memcpy(ioc->sas_mgmt.reply, reply,
911 min(ioc->reply_sz, 4 * reply->u.reply.MsgLength));
912 }
913 complete(&ioc->sas_mgmt.done);
914 return 1;
915}
916
917static int mptsas_phy_reset(struct sas_phy *phy, int hard_reset)
918{
919 MPT_ADAPTER *ioc = phy_to_ioc(phy);
920 SasIoUnitControlRequest_t *req;
921 SasIoUnitControlReply_t *reply;
922 MPT_FRAME_HDR *mf;
923 MPIHeader_t *hdr;
924 unsigned long timeleft;
925 int error = -ERESTARTSYS;
926
927 /* not implemented for expanders */
928 if (phy->identify.target_port_protocols & SAS_PROTOCOL_SMP)
929 return -ENXIO;
930
eeb846ce 931 if (mutex_lock_interruptible(&ioc->sas_mgmt.mutex))
da4fa655
CH
932 goto out;
933
934 mf = mpt_get_msg_frame(mptsasMgmtCtx, ioc);
935 if (!mf) {
936 error = -ENOMEM;
937 goto out_unlock;
938 }
939
940 hdr = (MPIHeader_t *) mf;
941 req = (SasIoUnitControlRequest_t *)mf;
942 memset(req, 0, sizeof(SasIoUnitControlRequest_t));
943 req->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL;
944 req->MsgContext = hdr->MsgContext;
945 req->Operation = hard_reset ?
946 MPI_SAS_OP_PHY_HARD_RESET : MPI_SAS_OP_PHY_LINK_RESET;
947 req->PhyNum = phy->identify.phy_identifier;
948
949 mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf);
950
951 timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done,
952 10 * HZ);
953 if (!timeleft) {
954 /* On timeout reset the board */
955 mpt_free_msg_frame(ioc, mf);
956 mpt_HardResetHandler(ioc, CAN_SLEEP);
957 error = -ETIMEDOUT;
958 goto out_unlock;
959 }
960
961 /* a reply frame is expected */
962 if ((ioc->sas_mgmt.status &
963 MPT_IOCTL_STATUS_RF_VALID) == 0) {
964 error = -ENXIO;
965 goto out_unlock;
966 }
967
968 /* process the completed Reply Message Frame */
969 reply = (SasIoUnitControlReply_t *)ioc->sas_mgmt.reply;
970 if (reply->IOCStatus != MPI_IOCSTATUS_SUCCESS) {
971 printk("%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",
972 __FUNCTION__,
973 reply->IOCStatus,
974 reply->IOCLogInfo);
975 error = -ENXIO;
976 goto out_unlock;
977 }
978
979 error = 0;
980
981 out_unlock:
eeb846ce 982 mutex_unlock(&ioc->sas_mgmt.mutex);
da4fa655
CH
983 out:
984 return error;
985}
0c33b27d 986
e3094447
CH
987static int
988mptsas_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier)
989{
990 MPT_ADAPTER *ioc = rphy_to_ioc(rphy);
991 int i, error;
992 struct mptsas_portinfo *p;
993 struct mptsas_enclosure enclosure_info;
994 u64 enclosure_handle;
995
996 mutex_lock(&ioc->sas_topology_mutex);
997 list_for_each_entry(p, &ioc->sas_topology, list) {
998 for (i = 0; i < p->num_phys; i++) {
999 if (p->phy_info[i].attached.sas_address ==
1000 rphy->identify.sas_address) {
1001 enclosure_handle = p->phy_info[i].
1002 attached.handle_enclosure;
1003 goto found_info;
1004 }
1005 }
1006 }
1007 mutex_unlock(&ioc->sas_topology_mutex);
1008 return -ENXIO;
1009
1010 found_info:
1011 mutex_unlock(&ioc->sas_topology_mutex);
1012 memset(&enclosure_info, 0, sizeof(struct mptsas_enclosure));
52435430 1013 error = mptsas_sas_enclosure_pg0(ioc, &enclosure_info,
e3094447
CH
1014 (MPI_SAS_ENCLOS_PGAD_FORM_HANDLE <<
1015 MPI_SAS_ENCLOS_PGAD_FORM_SHIFT), enclosure_handle);
1016 if (!error)
1017 *identifier = enclosure_info.enclosure_logical_id;
1018 return error;
1019}
1020
1021static int
1022mptsas_get_bay_identifier(struct sas_rphy *rphy)
1023{
1024 MPT_ADAPTER *ioc = rphy_to_ioc(rphy);
1025 struct mptsas_portinfo *p;
1026 int i, rc;
1027
1028 mutex_lock(&ioc->sas_topology_mutex);
1029 list_for_each_entry(p, &ioc->sas_topology, list) {
1030 for (i = 0; i < p->num_phys; i++) {
1031 if (p->phy_info[i].attached.sas_address ==
1032 rphy->identify.sas_address) {
1033 rc = p->phy_info[i].attached.slot;
1034 goto out;
1035 }
1036 }
1037 }
1038 rc = -ENXIO;
1039 out:
1040 mutex_unlock(&ioc->sas_topology_mutex);
1041 return rc;
1042}
1043
b5141128
CH
1044static struct sas_function_template mptsas_transport_functions = {
1045 .get_linkerrors = mptsas_get_linkerrors,
e3094447
CH
1046 .get_enclosure_identifier = mptsas_get_enclosure_identifier,
1047 .get_bay_identifier = mptsas_get_bay_identifier,
da4fa655 1048 .phy_reset = mptsas_phy_reset,
b5141128
CH
1049};
1050
1051static struct scsi_transport_template *mptsas_transport_template;
0c33b27d
CH
1052
1053static int
1054mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
1055{
1056 ConfigExtendedPageHeader_t hdr;
1057 CONFIGPARMS cfg;
1058 SasIOUnitPage0_t *buffer;
1059 dma_addr_t dma_handle;
1060 int error, i;
1061
1062 hdr.PageVersion = MPI_SASIOUNITPAGE0_PAGEVERSION;
1063 hdr.ExtPageLength = 0;
1064 hdr.PageNumber = 0;
1065 hdr.Reserved1 = 0;
1066 hdr.Reserved2 = 0;
1067 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1068 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1069
1070 cfg.cfghdr.ehdr = &hdr;
1071 cfg.physAddr = -1;
1072 cfg.pageAddr = 0;
1073 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1074 cfg.dir = 0; /* read */
1075 cfg.timeout = 10;
1076
1077 error = mpt_config(ioc, &cfg);
1078 if (error)
1079 goto out;
1080 if (!hdr.ExtPageLength) {
1081 error = -ENXIO;
1082 goto out;
1083 }
1084
1085 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1086 &dma_handle);
1087 if (!buffer) {
1088 error = -ENOMEM;
1089 goto out;
1090 }
1091
1092 cfg.physAddr = dma_handle;
1093 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1094
1095 error = mpt_config(ioc, &cfg);
1096 if (error)
1097 goto out_free_consistent;
1098
1099 port_info->num_phys = buffer->NumPhys;
1100 port_info->phy_info = kcalloc(port_info->num_phys,
547f9a21 1101 sizeof(*port_info->phy_info),GFP_KERNEL);
0c33b27d
CH
1102 if (!port_info->phy_info) {
1103 error = -ENOMEM;
1104 goto out_free_consistent;
1105 }
1106
db9c9174
ME
1107 if (port_info->num_phys)
1108 port_info->handle =
1109 le16_to_cpu(buffer->PhyData[0].ControllerDevHandle);
0c33b27d
CH
1110 for (i = 0; i < port_info->num_phys; i++) {
1111 mptsas_print_phy_data(&buffer->PhyData[i]);
1112 port_info->phy_info[i].phy_id = i;
1113 port_info->phy_info[i].port_id =
1114 buffer->PhyData[i].Port;
1115 port_info->phy_info[i].negotiated_link_rate =
1116 buffer->PhyData[i].NegotiatedLinkRate;
547f9a21 1117 port_info->phy_info[i].portinfo = port_info;
0c33b27d
CH
1118 }
1119
1120 out_free_consistent:
1121 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1122 buffer, dma_handle);
1123 out:
1124 return error;
1125}
1126
1127static int
1128mptsas_sas_phy_pg0(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
1129 u32 form, u32 form_specific)
1130{
1131 ConfigExtendedPageHeader_t hdr;
1132 CONFIGPARMS cfg;
1133 SasPhyPage0_t *buffer;
1134 dma_addr_t dma_handle;
1135 int error;
1136
1137 hdr.PageVersion = MPI_SASPHY0_PAGEVERSION;
1138 hdr.ExtPageLength = 0;
1139 hdr.PageNumber = 0;
1140 hdr.Reserved1 = 0;
1141 hdr.Reserved2 = 0;
1142 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1143 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
1144
1145 cfg.cfghdr.ehdr = &hdr;
1146 cfg.dir = 0; /* read */
1147 cfg.timeout = 10;
1148
1149 /* Get Phy Pg 0 for each Phy. */
1150 cfg.physAddr = -1;
1151 cfg.pageAddr = form + form_specific;
1152 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1153
1154 error = mpt_config(ioc, &cfg);
1155 if (error)
1156 goto out;
1157
1158 if (!hdr.ExtPageLength) {
1159 error = -ENXIO;
1160 goto out;
1161 }
1162
1163 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1164 &dma_handle);
1165 if (!buffer) {
1166 error = -ENOMEM;
1167 goto out;
1168 }
1169
1170 cfg.physAddr = dma_handle;
1171 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1172
1173 error = mpt_config(ioc, &cfg);
1174 if (error)
1175 goto out_free_consistent;
1176
1177 mptsas_print_phy_pg0(buffer);
1178
1179 phy_info->hw_link_rate = buffer->HwLinkRate;
1180 phy_info->programmed_link_rate = buffer->ProgrammedLinkRate;
1181 phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle);
1182 phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle);
1183
1184 out_free_consistent:
1185 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1186 buffer, dma_handle);
1187 out:
1188 return error;
1189}
1190
1191static int
1192mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info,
1193 u32 form, u32 form_specific)
1194{
1195 ConfigExtendedPageHeader_t hdr;
1196 CONFIGPARMS cfg;
1197 SasDevicePage0_t *buffer;
1198 dma_addr_t dma_handle;
1199 __le64 sas_address;
bd23e94c
ME
1200 int error=0;
1201
1202 if (ioc->sas_discovery_runtime &&
1203 mptsas_is_end_device(device_info))
1204 goto out;
0c33b27d
CH
1205
1206 hdr.PageVersion = MPI_SASDEVICE0_PAGEVERSION;
1207 hdr.ExtPageLength = 0;
1208 hdr.PageNumber = 0;
1209 hdr.Reserved1 = 0;
1210 hdr.Reserved2 = 0;
1211 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1212 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE;
1213
1214 cfg.cfghdr.ehdr = &hdr;
1215 cfg.pageAddr = form + form_specific;
1216 cfg.physAddr = -1;
1217 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1218 cfg.dir = 0; /* read */
1219 cfg.timeout = 10;
1220
db9c9174 1221 memset(device_info, 0, sizeof(struct mptsas_devinfo));
0c33b27d
CH
1222 error = mpt_config(ioc, &cfg);
1223 if (error)
1224 goto out;
1225 if (!hdr.ExtPageLength) {
1226 error = -ENXIO;
1227 goto out;
1228 }
1229
1230 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1231 &dma_handle);
1232 if (!buffer) {
1233 error = -ENOMEM;
1234 goto out;
1235 }
1236
1237 cfg.physAddr = dma_handle;
1238 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1239
1240 error = mpt_config(ioc, &cfg);
1241 if (error)
1242 goto out_free_consistent;
1243
1244 mptsas_print_device_pg0(buffer);
1245
1246 device_info->handle = le16_to_cpu(buffer->DevHandle);
c73787ee 1247 device_info->handle_parent = le16_to_cpu(buffer->ParentDevHandle);
e3094447
CH
1248 device_info->handle_enclosure =
1249 le16_to_cpu(buffer->EnclosureHandle);
1250 device_info->slot = le16_to_cpu(buffer->Slot);
0c33b27d
CH
1251 device_info->phy_id = buffer->PhyNum;
1252 device_info->port_id = buffer->PhysicalPort;
9a28f49a
CH
1253 device_info->id = buffer->TargetID;
1254 device_info->channel = buffer->Bus;
0c33b27d
CH
1255 memcpy(&sas_address, &buffer->SASAddress, sizeof(__le64));
1256 device_info->sas_address = le64_to_cpu(sas_address);
1257 device_info->device_info =
1258 le32_to_cpu(buffer->DeviceInfo);
1259
1260 out_free_consistent:
1261 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1262 buffer, dma_handle);
1263 out:
1264 return error;
1265}
1266
1267static int
1268mptsas_sas_expander_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info,
1269 u32 form, u32 form_specific)
1270{
1271 ConfigExtendedPageHeader_t hdr;
1272 CONFIGPARMS cfg;
1273 SasExpanderPage0_t *buffer;
1274 dma_addr_t dma_handle;
547f9a21 1275 int i, error;
0c33b27d
CH
1276
1277 hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION;
1278 hdr.ExtPageLength = 0;
1279 hdr.PageNumber = 0;
1280 hdr.Reserved1 = 0;
1281 hdr.Reserved2 = 0;
1282 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1283 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
1284
1285 cfg.cfghdr.ehdr = &hdr;
1286 cfg.physAddr = -1;
1287 cfg.pageAddr = form + form_specific;
1288 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1289 cfg.dir = 0; /* read */
1290 cfg.timeout = 10;
1291
db9c9174 1292 memset(port_info, 0, sizeof(struct mptsas_portinfo));
0c33b27d
CH
1293 error = mpt_config(ioc, &cfg);
1294 if (error)
1295 goto out;
1296
1297 if (!hdr.ExtPageLength) {
1298 error = -ENXIO;
1299 goto out;
1300 }
1301
1302 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1303 &dma_handle);
1304 if (!buffer) {
1305 error = -ENOMEM;
1306 goto out;
1307 }
1308
1309 cfg.physAddr = dma_handle;
1310 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1311
1312 error = mpt_config(ioc, &cfg);
1313 if (error)
1314 goto out_free_consistent;
1315
1316 /* save config data */
1317 port_info->num_phys = buffer->NumPhys;
1318 port_info->handle = le16_to_cpu(buffer->DevHandle);
1319 port_info->phy_info = kcalloc(port_info->num_phys,
547f9a21 1320 sizeof(*port_info->phy_info),GFP_KERNEL);
0c33b27d
CH
1321 if (!port_info->phy_info) {
1322 error = -ENOMEM;
1323 goto out_free_consistent;
1324 }
1325
547f9a21
EM
1326 for (i = 0; i < port_info->num_phys; i++)
1327 port_info->phy_info[i].portinfo = port_info;
1328
0c33b27d
CH
1329 out_free_consistent:
1330 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1331 buffer, dma_handle);
1332 out:
1333 return error;
1334}
1335
1336static int
1337mptsas_sas_expander_pg1(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
1338 u32 form, u32 form_specific)
1339{
1340 ConfigExtendedPageHeader_t hdr;
1341 CONFIGPARMS cfg;
1342 SasExpanderPage1_t *buffer;
1343 dma_addr_t dma_handle;
bd23e94c
ME
1344 int error=0;
1345
1346 if (ioc->sas_discovery_runtime &&
1347 mptsas_is_end_device(&phy_info->attached))
1348 goto out;
0c33b27d
CH
1349
1350 hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION;
1351 hdr.ExtPageLength = 0;
1352 hdr.PageNumber = 1;
1353 hdr.Reserved1 = 0;
1354 hdr.Reserved2 = 0;
1355 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1356 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
1357
1358 cfg.cfghdr.ehdr = &hdr;
1359 cfg.physAddr = -1;
1360 cfg.pageAddr = form + form_specific;
1361 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1362 cfg.dir = 0; /* read */
1363 cfg.timeout = 10;
1364
1365 error = mpt_config(ioc, &cfg);
1366 if (error)
1367 goto out;
1368
1369 if (!hdr.ExtPageLength) {
1370 error = -ENXIO;
1371 goto out;
1372 }
1373
1374 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1375 &dma_handle);
1376 if (!buffer) {
1377 error = -ENOMEM;
1378 goto out;
1379 }
1380
1381 cfg.physAddr = dma_handle;
1382 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1383
1384 error = mpt_config(ioc, &cfg);
1385 if (error)
1386 goto out_free_consistent;
1387
1388
1389 mptsas_print_expander_pg1(buffer);
1390
1391 /* save config data */
024358ee 1392 phy_info->phy_id = buffer->PhyIdentifier;
0c33b27d
CH
1393 phy_info->port_id = buffer->PhysicalPort;
1394 phy_info->negotiated_link_rate = buffer->NegotiatedLinkRate;
1395 phy_info->programmed_link_rate = buffer->ProgrammedLinkRate;
1396 phy_info->hw_link_rate = buffer->HwLinkRate;
1397 phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle);
1398 phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle);
1399
0c33b27d
CH
1400 out_free_consistent:
1401 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1402 buffer, dma_handle);
1403 out:
1404 return error;
1405}
1406
1407static void
1408mptsas_parse_device_info(struct sas_identify *identify,
1409 struct mptsas_devinfo *device_info)
1410{
1411 u16 protocols;
1412
1413 identify->sas_address = device_info->sas_address;
1414 identify->phy_identifier = device_info->phy_id;
1415
1416 /*
1417 * Fill in Phy Initiator Port Protocol.
1418 * Bits 6:3, more than one bit can be set, fall through cases.
1419 */
1420 protocols = device_info->device_info & 0x78;
1421 identify->initiator_port_protocols = 0;
1422 if (protocols & MPI_SAS_DEVICE_INFO_SSP_INITIATOR)
1423 identify->initiator_port_protocols |= SAS_PROTOCOL_SSP;
1424 if (protocols & MPI_SAS_DEVICE_INFO_STP_INITIATOR)
1425 identify->initiator_port_protocols |= SAS_PROTOCOL_STP;
1426 if (protocols & MPI_SAS_DEVICE_INFO_SMP_INITIATOR)
1427 identify->initiator_port_protocols |= SAS_PROTOCOL_SMP;
1428 if (protocols & MPI_SAS_DEVICE_INFO_SATA_HOST)
1429 identify->initiator_port_protocols |= SAS_PROTOCOL_SATA;
1430
1431 /*
1432 * Fill in Phy Target Port Protocol.
1433 * Bits 10:7, more than one bit can be set, fall through cases.
1434 */
1435 protocols = device_info->device_info & 0x780;
1436 identify->target_port_protocols = 0;
1437 if (protocols & MPI_SAS_DEVICE_INFO_SSP_TARGET)
1438 identify->target_port_protocols |= SAS_PROTOCOL_SSP;
1439 if (protocols & MPI_SAS_DEVICE_INFO_STP_TARGET)
1440 identify->target_port_protocols |= SAS_PROTOCOL_STP;
1441 if (protocols & MPI_SAS_DEVICE_INFO_SMP_TARGET)
1442 identify->target_port_protocols |= SAS_PROTOCOL_SMP;
1443 if (protocols & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
1444 identify->target_port_protocols |= SAS_PROTOCOL_SATA;
1445
1446 /*
1447 * Fill in Attached device type.
1448 */
1449 switch (device_info->device_info &
1450 MPI_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) {
1451 case MPI_SAS_DEVICE_INFO_NO_DEVICE:
1452 identify->device_type = SAS_PHY_UNUSED;
1453 break;
1454 case MPI_SAS_DEVICE_INFO_END_DEVICE:
1455 identify->device_type = SAS_END_DEVICE;
1456 break;
1457 case MPI_SAS_DEVICE_INFO_EDGE_EXPANDER:
1458 identify->device_type = SAS_EDGE_EXPANDER_DEVICE;
1459 break;
1460 case MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER:
1461 identify->device_type = SAS_FANOUT_EXPANDER_DEVICE;
1462 break;
1463 }
1464}
1465
1466static int mptsas_probe_one_phy(struct device *dev,
ac01bbbd 1467 struct mptsas_phyinfo *phy_info, int index, int local)
0c33b27d 1468{
e6b2d76a 1469 MPT_ADAPTER *ioc;
9a28f49a 1470 struct sas_phy *phy;
547f9a21
EM
1471 struct sas_port *port;
1472 int error = 0;
0c33b27d 1473
547f9a21
EM
1474 if (!dev) {
1475 error = -ENODEV;
1476 goto out;
1477 }
e6b2d76a
ME
1478
1479 if (!phy_info->phy) {
1480 phy = sas_phy_alloc(dev, index);
547f9a21
EM
1481 if (!phy) {
1482 error = -ENOMEM;
1483 goto out;
1484 }
e6b2d76a
ME
1485 } else
1486 phy = phy_info->phy;
0c33b27d 1487
9a28f49a 1488 mptsas_parse_device_info(&phy->identify, &phy_info->identify);
0c33b27d
CH
1489
1490 /*
1491 * Set Negotiated link rate.
1492 */
1493 switch (phy_info->negotiated_link_rate) {
1494 case MPI_SAS_IOUNIT0_RATE_PHY_DISABLED:
9a28f49a 1495 phy->negotiated_linkrate = SAS_PHY_DISABLED;
0c33b27d
CH
1496 break;
1497 case MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION:
9a28f49a 1498 phy->negotiated_linkrate = SAS_LINK_RATE_FAILED;
0c33b27d
CH
1499 break;
1500 case MPI_SAS_IOUNIT0_RATE_1_5:
9a28f49a 1501 phy->negotiated_linkrate = SAS_LINK_RATE_1_5_GBPS;
0c33b27d
CH
1502 break;
1503 case MPI_SAS_IOUNIT0_RATE_3_0:
9a28f49a 1504 phy->negotiated_linkrate = SAS_LINK_RATE_3_0_GBPS;
0c33b27d
CH
1505 break;
1506 case MPI_SAS_IOUNIT0_RATE_SATA_OOB_COMPLETE:
1507 case MPI_SAS_IOUNIT0_RATE_UNKNOWN:
1508 default:
9a28f49a 1509 phy->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN;
0c33b27d
CH
1510 break;
1511 }
1512
1513 /*
1514 * Set Max hardware link rate.
1515 */
1516 switch (phy_info->hw_link_rate & MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
1517 case MPI_SAS_PHY0_HWRATE_MAX_RATE_1_5:
9a28f49a 1518 phy->maximum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
0c33b27d
CH
1519 break;
1520 case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
9a28f49a 1521 phy->maximum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
0c33b27d
CH
1522 break;
1523 default:
1524 break;
1525 }
1526
1527 /*
1528 * Set Max programmed link rate.
1529 */
1530 switch (phy_info->programmed_link_rate &
1531 MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
1532 case MPI_SAS_PHY0_PRATE_MAX_RATE_1_5:
9a28f49a 1533 phy->maximum_linkrate = SAS_LINK_RATE_1_5_GBPS;
0c33b27d
CH
1534 break;
1535 case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
9a28f49a 1536 phy->maximum_linkrate = SAS_LINK_RATE_3_0_GBPS;
0c33b27d
CH
1537 break;
1538 default:
1539 break;
1540 }
1541
1542 /*
1543 * Set Min hardware link rate.
1544 */
1545 switch (phy_info->hw_link_rate & MPI_SAS_PHY0_HWRATE_MIN_RATE_MASK) {
1546 case MPI_SAS_PHY0_HWRATE_MIN_RATE_1_5:
9a28f49a 1547 phy->minimum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
0c33b27d
CH
1548 break;
1549 case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
9a28f49a 1550 phy->minimum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
0c33b27d
CH
1551 break;
1552 default:
1553 break;
1554 }
1555
1556 /*
1557 * Set Min programmed link rate.
1558 */
1559 switch (phy_info->programmed_link_rate &
1560 MPI_SAS_PHY0_PRATE_MIN_RATE_MASK) {
1561 case MPI_SAS_PHY0_PRATE_MIN_RATE_1_5:
9a28f49a 1562 phy->minimum_linkrate = SAS_LINK_RATE_1_5_GBPS;
0c33b27d
CH
1563 break;
1564 case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
9a28f49a 1565 phy->minimum_linkrate = SAS_LINK_RATE_3_0_GBPS;
0c33b27d
CH
1566 break;
1567 default:
1568 break;
1569 }
1570
e6b2d76a 1571 if (!phy_info->phy) {
ac01bbbd 1572
e6b2d76a
ME
1573 if (local)
1574 phy->local_attached = 1;
1575
1576 error = sas_phy_add(phy);
1577 if (error) {
1578 sas_phy_free(phy);
547f9a21 1579 goto out;
e6b2d76a
ME
1580 }
1581 phy_info->phy = phy;
0c33b27d
CH
1582 }
1583
547f9a21
EM
1584 if (!phy_info->attached.handle ||
1585 !phy_info->port_details)
1586 goto out;
1587
1588 port = mptsas_get_port(phy_info);
1589 ioc = phy_to_ioc(phy_info->phy);
1590
1591 if (phy_info->sas_port_add_phy) {
1592
1593 if (!port) {
dc22f16d 1594 port = sas_port_alloc_num(dev);
547f9a21
EM
1595 if (!port) {
1596 error = -ENOMEM;
1597 goto out;
1598 }
1599 error = sas_port_add(port);
1600 if (error) {
1601 dfailprintk((MYIOC_s_ERR_FMT
1602 "%s: exit at line=%d\n", ioc->name,
1603 __FUNCTION__, __LINE__));
1604 goto out;
1605 }
1606 mptsas_set_port(phy_info, port);
dc22f16d
EM
1607 dsaswideprintk((KERN_DEBUG
1608 "sas_port_alloc: port=%p dev=%p port_id=%d\n",
1609 port, dev, port->port_identifier));
547f9a21
EM
1610 }
1611 dsaswideprintk((KERN_DEBUG "sas_port_add_phy: phy_id=%d\n",
1612 phy_info->phy_id));
1613 sas_port_add_phy(port, phy_info->phy);
1614 phy_info->sas_port_add_phy = 0;
1615 }
1616
1617 if (!mptsas_get_rphy(phy_info) && port && !port->rphy) {
e6b2d76a 1618
0c33b27d 1619 struct sas_rphy *rphy;
2686de27 1620 struct device *parent;
f013db32 1621 struct sas_identify identify;
0c33b27d 1622
2686de27 1623 parent = dev->parent->parent;
e6b2d76a
ME
1624 /*
1625 * Let the hotplug_work thread handle processing
1626 * the adding/removing of devices that occur
1627 * after start of day.
1628 */
1629 if (ioc->sas_discovery_runtime &&
1630 mptsas_is_end_device(&phy_info->attached))
547f9a21 1631 goto out;
e6b2d76a 1632
f013db32 1633 mptsas_parse_device_info(&identify, &phy_info->attached);
2686de27
JB
1634 if (scsi_is_host_device(parent)) {
1635 struct mptsas_portinfo *port_info;
1636 int i;
1637
1638 mutex_lock(&ioc->sas_topology_mutex);
1639 port_info = mptsas_find_portinfo_by_handle(ioc,
1640 ioc->handle);
1641 mutex_unlock(&ioc->sas_topology_mutex);
1642
1643 for (i = 0; i < port_info->num_phys; i++)
1644 if (port_info->phy_info[i].identify.sas_address ==
1645 identify.sas_address)
1646 goto out;
1647
1648 } else if (scsi_is_sas_rphy(parent)) {
1649 struct sas_rphy *parent_rphy = dev_to_rphy(parent);
1650 if (identify.sas_address ==
1651 parent_rphy->identify.sas_address)
1652 goto out;
1653 }
1654
f013db32
JB
1655 switch (identify.device_type) {
1656 case SAS_END_DEVICE:
547f9a21 1657 rphy = sas_end_device_alloc(port);
f013db32
JB
1658 break;
1659 case SAS_EDGE_EXPANDER_DEVICE:
1660 case SAS_FANOUT_EXPANDER_DEVICE:
547f9a21 1661 rphy = sas_expander_alloc(port, identify.device_type);
f013db32
JB
1662 break;
1663 default:
1664 rphy = NULL;
1665 break;
1666 }
547f9a21
EM
1667 if (!rphy) {
1668 dfailprintk((MYIOC_s_ERR_FMT
1669 "%s: exit at line=%d\n", ioc->name,
1670 __FUNCTION__, __LINE__));
1671 goto out;
1672 }
0c33b27d 1673
f013db32 1674 rphy->identify = identify;
0c33b27d
CH
1675 error = sas_rphy_add(rphy);
1676 if (error) {
547f9a21
EM
1677 dfailprintk((MYIOC_s_ERR_FMT
1678 "%s: exit at line=%d\n", ioc->name,
1679 __FUNCTION__, __LINE__));
0c33b27d 1680 sas_rphy_free(rphy);
547f9a21 1681 goto out;
0c33b27d 1682 }
547f9a21 1683 mptsas_set_rphy(phy_info, rphy);
0c33b27d
CH
1684 }
1685
547f9a21
EM
1686 out:
1687 return error;
0c33b27d
CH
1688}
1689
1690static int
e6b2d76a 1691mptsas_probe_hba_phys(MPT_ADAPTER *ioc)
0c33b27d 1692{
e6b2d76a 1693 struct mptsas_portinfo *port_info, *hba;
0c33b27d
CH
1694 u32 handle = 0xFFFF;
1695 int error = -ENOMEM, i;
1696
e6b2d76a
ME
1697 hba = kzalloc(sizeof(*port_info), GFP_KERNEL);
1698 if (! hba)
0c33b27d 1699 goto out;
0c33b27d 1700
e6b2d76a 1701 error = mptsas_sas_io_unit_pg0(ioc, hba);
0c33b27d
CH
1702 if (error)
1703 goto out_free_port_info;
1704
9a28f49a 1705 mutex_lock(&ioc->sas_topology_mutex);
2686de27 1706 ioc->handle = hba->handle;
e6b2d76a
ME
1707 port_info = mptsas_find_portinfo_by_handle(ioc, hba->handle);
1708 if (!port_info) {
1709 port_info = hba;
1710 list_add_tail(&port_info->list, &ioc->sas_topology);
1711 } else {
1712 port_info->handle = hba->handle;
1713 for (i = 0; i < hba->num_phys; i++)
1714 port_info->phy_info[i].negotiated_link_rate =
1715 hba->phy_info[i].negotiated_link_rate;
547f9a21 1716 kfree(hba->phy_info);
e6b2d76a
ME
1717 kfree(hba);
1718 hba = NULL;
1719 }
9a28f49a
CH
1720 mutex_unlock(&ioc->sas_topology_mutex);
1721
0c33b27d
CH
1722 for (i = 0; i < port_info->num_phys; i++) {
1723 mptsas_sas_phy_pg0(ioc, &port_info->phy_info[i],
1724 (MPI_SAS_PHY_PGAD_FORM_PHY_NUMBER <<
1725 MPI_SAS_PHY_PGAD_FORM_SHIFT), i);
1726
1727 mptsas_sas_device_pg0(ioc, &port_info->phy_info[i].identify,
1728 (MPI_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE <<
1729 MPI_SAS_DEVICE_PGAD_FORM_SHIFT), handle);
024358ee
EM
1730 port_info->phy_info[i].identify.phy_id =
1731 port_info->phy_info[i].phy_id;
0c33b27d
CH
1732 handle = port_info->phy_info[i].identify.handle;
1733
547f9a21 1734 if (port_info->phy_info[i].attached.handle)
0c33b27d
CH
1735 mptsas_sas_device_pg0(ioc,
1736 &port_info->phy_info[i].attached,
1737 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
1738 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
1739 port_info->phy_info[i].attached.handle);
547f9a21 1740 }
0c33b27d 1741
547f9a21
EM
1742 mptsas_setup_wide_ports(ioc, port_info);
1743
1744 for (i = 0; i < port_info->num_phys; i++, ioc->sas_index++)
0c33b27d 1745 mptsas_probe_one_phy(&ioc->sh->shost_gendev,
e6b2d76a 1746 &port_info->phy_info[i], ioc->sas_index, 1);
0c33b27d
CH
1747
1748 return 0;
1749
1750 out_free_port_info:
547f9a21 1751 kfree(hba);
0c33b27d
CH
1752 out:
1753 return error;
1754}
1755
1756static int
e6b2d76a 1757mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle)
0c33b27d 1758{
e6b2d76a 1759 struct mptsas_portinfo *port_info, *p, *ex;
547f9a21
EM
1760 struct device *parent;
1761 struct sas_rphy *rphy;
0c33b27d
CH
1762 int error = -ENOMEM, i, j;
1763
e6b2d76a
ME
1764 ex = kzalloc(sizeof(*port_info), GFP_KERNEL);
1765 if (!ex)
0c33b27d 1766 goto out;
0c33b27d 1767
e6b2d76a 1768 error = mptsas_sas_expander_pg0(ioc, ex,
0c33b27d
CH
1769 (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE <<
1770 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), *handle);
1771 if (error)
1772 goto out_free_port_info;
1773
e6b2d76a 1774 *handle = ex->handle;
0c33b27d 1775
9a28f49a 1776 mutex_lock(&ioc->sas_topology_mutex);
e6b2d76a
ME
1777 port_info = mptsas_find_portinfo_by_handle(ioc, *handle);
1778 if (!port_info) {
1779 port_info = ex;
1780 list_add_tail(&port_info->list, &ioc->sas_topology);
1781 } else {
1782 port_info->handle = ex->handle;
547f9a21 1783 kfree(ex->phy_info);
e6b2d76a
ME
1784 kfree(ex);
1785 ex = NULL;
1786 }
9a28f49a
CH
1787 mutex_unlock(&ioc->sas_topology_mutex);
1788
0c33b27d 1789 for (i = 0; i < port_info->num_phys; i++) {
0c33b27d
CH
1790 mptsas_sas_expander_pg1(ioc, &port_info->phy_info[i],
1791 (MPI_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM <<
1792 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), (i << 16) + *handle);
1793
1794 if (port_info->phy_info[i].identify.handle) {
1795 mptsas_sas_device_pg0(ioc,
1796 &port_info->phy_info[i].identify,
1797 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
1798 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
1799 port_info->phy_info[i].identify.handle);
024358ee
EM
1800 port_info->phy_info[i].identify.phy_id =
1801 port_info->phy_info[i].phy_id;
0c33b27d
CH
1802 }
1803
1804 if (port_info->phy_info[i].attached.handle) {
1805 mptsas_sas_device_pg0(ioc,
1806 &port_info->phy_info[i].attached,
1807 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
1808 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
1809 port_info->phy_info[i].attached.handle);
db9c9174
ME
1810 port_info->phy_info[i].attached.phy_id =
1811 port_info->phy_info[i].phy_id;
0c33b27d 1812 }
547f9a21 1813 }
0c33b27d 1814
547f9a21
EM
1815 parent = &ioc->sh->shost_gendev;
1816 for (i = 0; i < port_info->num_phys; i++) {
9a28f49a 1817 mutex_lock(&ioc->sas_topology_mutex);
0c33b27d
CH
1818 list_for_each_entry(p, &ioc->sas_topology, list) {
1819 for (j = 0; j < p->num_phys; j++) {
547f9a21 1820 if (port_info->phy_info[i].identify.handle !=
0c33b27d 1821 p->phy_info[j].attached.handle)
547f9a21
EM
1822 continue;
1823 rphy = mptsas_get_rphy(&p->phy_info[j]);
1824 parent = &rphy->dev;
0c33b27d
CH
1825 }
1826 }
9a28f49a 1827 mutex_unlock(&ioc->sas_topology_mutex);
547f9a21
EM
1828 }
1829
1830 mptsas_setup_wide_ports(ioc, port_info);
0c33b27d 1831
547f9a21 1832 for (i = 0; i < port_info->num_phys; i++, ioc->sas_index++)
ac01bbbd 1833 mptsas_probe_one_phy(parent, &port_info->phy_info[i],
e6b2d76a 1834 ioc->sas_index, 0);
0c33b27d
CH
1835
1836 return 0;
1837
1838 out_free_port_info:
e6b2d76a 1839 if (ex) {
547f9a21 1840 kfree(ex->phy_info);
e6b2d76a
ME
1841 kfree(ex);
1842 }
0c33b27d
CH
1843 out:
1844 return error;
1845}
1846
e6b2d76a
ME
1847/*
1848 * mptsas_delete_expander_phys
1849 *
1850 *
1851 * This will traverse topology, and remove expanders
1852 * that are no longer present
1853 */
1854static void
1855mptsas_delete_expander_phys(MPT_ADAPTER *ioc)
1856{
1857 struct mptsas_portinfo buffer;
1858 struct mptsas_portinfo *port_info, *n, *parent;
547f9a21
EM
1859 struct mptsas_phyinfo *phy_info;
1860 struct scsi_target * starget;
1861 VirtTarget * vtarget;
1862 struct sas_port * port;
e6b2d76a 1863 int i;
547f9a21 1864 u64 expander_sas_address;
e6b2d76a
ME
1865
1866 mutex_lock(&ioc->sas_topology_mutex);
1867 list_for_each_entry_safe(port_info, n, &ioc->sas_topology, list) {
1868
1869 if (port_info->phy_info &&
1870 (!(port_info->phy_info[0].identify.device_info &
1871 MPI_SAS_DEVICE_INFO_SMP_TARGET)))
1872 continue;
1873
1874 if (mptsas_sas_expander_pg0(ioc, &buffer,
1875 (MPI_SAS_EXPAND_PGAD_FORM_HANDLE <<
1876 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), port_info->handle)) {
1877
547f9a21
EM
1878 /*
1879 * Issue target reset to all child end devices
1880 * then mark them deleted to prevent further
1881 * IO going to them.
1882 */
1883 phy_info = port_info->phy_info;
1884 for (i = 0; i < port_info->num_phys; i++, phy_info++) {
1885 starget = mptsas_get_starget(phy_info);
1886 if (!starget)
1887 continue;
1888 vtarget = starget->hostdata;
1889 if(vtarget->deleted)
1890 continue;
1891 vtarget->deleted = 1;
1892 mptsas_target_reset(ioc, vtarget);
1893 sas_port_delete(mptsas_get_port(phy_info));
1894 mptsas_port_delete(phy_info->port_details);
1895 }
1896
e6b2d76a
ME
1897 /*
1898 * Obtain the port_info instance to the parent port
1899 */
1900 parent = mptsas_find_portinfo_by_handle(ioc,
1901 port_info->phy_info[0].identify.handle_parent);
1902
1903 if (!parent)
1904 goto next_port;
1905
547f9a21
EM
1906 expander_sas_address =
1907 port_info->phy_info[0].identify.sas_address;
1908
e6b2d76a
ME
1909 /*
1910 * Delete rphys in the parent that point
1911 * to this expander. The transport layer will
1912 * cleanup all the children.
1913 */
547f9a21
EM
1914 phy_info = parent->phy_info;
1915 for (i = 0; i < parent->num_phys; i++, phy_info++) {
1916 port = mptsas_get_port(phy_info);
1917 if (!port)
1918 continue;
1919 if (phy_info->attached.sas_address !=
1920 expander_sas_address)
e6b2d76a 1921 continue;
547f9a21 1922#ifdef MPT_DEBUG_SAS_WIDE
dc22f16d
EM
1923 dev_printk(KERN_DEBUG, &port->dev,
1924 "delete port (%d)\n", port->port_identifier);
547f9a21
EM
1925#endif
1926 sas_port_delete(port);
1927 mptsas_port_delete(phy_info->port_details);
e6b2d76a
ME
1928 }
1929 next_port:
547f9a21
EM
1930
1931 phy_info = port_info->phy_info;
1932 for (i = 0; i < port_info->num_phys; i++, phy_info++)
1933 mptsas_port_delete(phy_info->port_details);
1934
e6b2d76a 1935 list_del(&port_info->list);
547f9a21 1936 kfree(port_info->phy_info);
e6b2d76a
ME
1937 kfree(port_info);
1938 }
1939 /*
1940 * Free this memory allocated from inside
1941 * mptsas_sas_expander_pg0
1942 */
547f9a21 1943 kfree(buffer.phy_info);
e6b2d76a
ME
1944 }
1945 mutex_unlock(&ioc->sas_topology_mutex);
1946}
1947
1948/*
1949 * Start of day discovery
1950 */
0c33b27d
CH
1951static void
1952mptsas_scan_sas_topology(MPT_ADAPTER *ioc)
1953{
1954 u32 handle = 0xFFFF;
f44e5461 1955 int i;
0c33b27d 1956
e6b2d76a
ME
1957 mutex_lock(&ioc->sas_discovery_mutex);
1958 mptsas_probe_hba_phys(ioc);
1959 while (!mptsas_probe_expander_phys(ioc, &handle))
0c33b27d 1960 ;
f44e5461
ME
1961 /*
1962 Reporting RAID volumes.
1963 */
1964 if (!ioc->raid_data.pIocPg2)
1965 goto out;
1966 if (!ioc->raid_data.pIocPg2->NumActiveVolumes)
1967 goto out;
1968 for (i=0; i<ioc->raid_data.pIocPg2->NumActiveVolumes; i++) {
e8bf3941 1969 scsi_add_device(ioc->sh, MPTSAS_RAID_CHANNEL,
f44e5461
ME
1970 ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID, 0);
1971 }
1972 out:
e6b2d76a
ME
1973 mutex_unlock(&ioc->sas_discovery_mutex);
1974}
1975
1976/*
1977 * Work queue thread to handle Runtime discovery
1978 * Mere purpose is the hot add/delete of expanders
547f9a21 1979 *(Mutex UNLOCKED)
e6b2d76a
ME
1980 */
1981static void
547f9a21 1982__mptsas_discovery_work(MPT_ADAPTER *ioc)
e6b2d76a 1983{
e6b2d76a
ME
1984 u32 handle = 0xFFFF;
1985
e6b2d76a
ME
1986 ioc->sas_discovery_runtime=1;
1987 mptsas_delete_expander_phys(ioc);
1988 mptsas_probe_hba_phys(ioc);
1989 while (!mptsas_probe_expander_phys(ioc, &handle))
1990 ;
e6b2d76a 1991 ioc->sas_discovery_runtime=0;
547f9a21
EM
1992}
1993
1994/*
1995 * Work queue thread to handle Runtime discovery
1996 * Mere purpose is the hot add/delete of expanders
1997 *(Mutex LOCKED)
1998 */
1999static void
2000mptsas_discovery_work(void * arg)
2001{
2002 struct mptsas_discovery_event *ev = arg;
2003 MPT_ADAPTER *ioc = ev->ioc;
2004
2005 mutex_lock(&ioc->sas_discovery_mutex);
2006 __mptsas_discovery_work(ioc);
e6b2d76a 2007 mutex_unlock(&ioc->sas_discovery_mutex);
547f9a21 2008 kfree(ev);
0c33b27d
CH
2009}
2010
9a28f49a 2011static struct mptsas_phyinfo *
547f9a21 2012mptsas_find_phyinfo_by_sas_address(MPT_ADAPTER *ioc, u64 sas_address)
9a28f49a
CH
2013{
2014 struct mptsas_portinfo *port_info;
9a28f49a 2015 struct mptsas_phyinfo *phy_info = NULL;
547f9a21 2016 int i;
9a28f49a 2017
9a28f49a
CH
2018 mutex_lock(&ioc->sas_topology_mutex);
2019 list_for_each_entry(port_info, &ioc->sas_topology, list) {
2020 for (i = 0; i < port_info->num_phys; i++) {
547f9a21
EM
2021 if (port_info->phy_info[i].attached.sas_address
2022 != sas_address)
2023 continue;
2024 if (!mptsas_is_end_device(
2025 &port_info->phy_info[i].attached))
2026 continue;
2027 phy_info = &port_info->phy_info[i];
2028 break;
9a28f49a
CH
2029 }
2030 }
2031 mutex_unlock(&ioc->sas_topology_mutex);
9a28f49a
CH
2032 return phy_info;
2033}
2034
2035static struct mptsas_phyinfo *
c73787ee 2036mptsas_find_phyinfo_by_target(MPT_ADAPTER *ioc, u32 id)
9a28f49a
CH
2037{
2038 struct mptsas_portinfo *port_info;
2039 struct mptsas_phyinfo *phy_info = NULL;
2040 int i;
2041
9a28f49a
CH
2042 mutex_lock(&ioc->sas_topology_mutex);
2043 list_for_each_entry(port_info, &ioc->sas_topology, list) {
547f9a21
EM
2044 for (i = 0; i < port_info->num_phys; i++) {
2045 if (port_info->phy_info[i].attached.id != id)
2046 continue;
2047 if (!mptsas_is_end_device(
2048 &port_info->phy_info[i].attached))
2049 continue;
2050 phy_info = &port_info->phy_info[i];
2051 break;
2052 }
9a28f49a
CH
2053 }
2054 mutex_unlock(&ioc->sas_topology_mutex);
9a28f49a
CH
2055 return phy_info;
2056}
2057
4b766471
ME
2058/*
2059 * Work queue thread to clear the persitency table
2060 */
2061static void
547f9a21 2062mptsas_persist_clear_table(void * arg)
4b766471
ME
2063{
2064 MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg;
2065
2066 mptbase_sas_persist_operation(ioc, MPI_SAS_OP_CLEAR_NOT_PRESENT);
2067}
2068
f44e5461
ME
2069static void
2070mptsas_reprobe_lun(struct scsi_device *sdev, void *data)
2071{
2072 sdev->no_uld_attach = data ? 1 : 0;
2073 scsi_device_reprobe(sdev);
2074}
2075
2076static void
2077mptsas_reprobe_target(struct scsi_target *starget, int uld_attach)
2078{
2079 starget_for_each_device(starget, uld_attach ? (void *)1 : NULL,
2080 mptsas_reprobe_lun);
2081}
2082
e6b2d76a
ME
2083/*
2084 * Work queue thread to handle SAS hotplug events
2085 */
9a28f49a
CH
2086static void
2087mptsas_hotplug_work(void *arg)
2088{
2089 struct mptsas_hotplug_event *ev = arg;
2090 MPT_ADAPTER *ioc = ev->ioc;
2091 struct mptsas_phyinfo *phy_info;
2092 struct sas_rphy *rphy;
547f9a21 2093 struct sas_port *port;
c73787ee 2094 struct scsi_device *sdev;
547f9a21 2095 struct scsi_target * starget;
f013db32 2096 struct sas_identify identify;
9a28f49a 2097 char *ds = NULL;
c73787ee 2098 struct mptsas_devinfo sas_device;
f44e5461 2099 VirtTarget *vtarget;
547f9a21 2100 VirtDevice *vdevice;
9a28f49a 2101
e6b2d76a 2102
547f9a21 2103 mutex_lock(&ioc->sas_discovery_mutex);
9a28f49a
CH
2104 switch (ev->event_type) {
2105 case MPTSAS_DEL_DEVICE:
9a28f49a 2106
c73787ee 2107 phy_info = mptsas_find_phyinfo_by_target(ioc, ev->id);
e6b2d76a 2108
f44e5461
ME
2109 /*
2110 * Sanity checks, for non-existing phys and remote rphys.
2111 */
547f9a21
EM
2112 if (!phy_info || !phy_info->port_details) {
2113 dfailprintk((MYIOC_s_ERR_FMT
2114 "%s: exit at line=%d\n", ioc->name,
2115 __FUNCTION__, __LINE__));
9a28f49a 2116 break;
547f9a21
EM
2117 }
2118 rphy = mptsas_get_rphy(phy_info);
2119 if (!rphy) {
2120 dfailprintk((MYIOC_s_ERR_FMT
2121 "%s: exit at line=%d\n", ioc->name,
2122 __FUNCTION__, __LINE__));
2123 break;
2124 }
2125 port = mptsas_get_port(phy_info);
2126 if (!port) {
2127 dfailprintk((MYIOC_s_ERR_FMT
2128 "%s: exit at line=%d\n", ioc->name,
2129 __FUNCTION__, __LINE__));
f44e5461 2130 break;
547f9a21
EM
2131 }
2132
2133 starget = mptsas_get_starget(phy_info);
2134 if (starget) {
2135 vtarget = starget->hostdata;
f44e5461 2136
547f9a21
EM
2137 if (!vtarget) {
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
f44e5461
ME
2144 /*
2145 * Handling RAID components
2146 */
2147 if (ev->phys_disk_num_valid) {
2148 vtarget->target_id = ev->phys_disk_num;
2149 vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT;
547f9a21 2150 mptsas_reprobe_target(starget, 1);
f44e5461
ME
2151 break;
2152 }
547f9a21
EM
2153
2154 vtarget->deleted = 1;
2155 mptsas_target_reset(ioc, vtarget);
9a28f49a
CH
2156 }
2157
c73787ee
ME
2158 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET)
2159 ds = "ssp";
2160 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_STP_TARGET)
2161 ds = "stp";
2162 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
2163 ds = "sata";
2164
2165 printk(MYIOC_s_INFO_FMT
2166 "removing %s device, channel %d, id %d, phy %d\n",
2167 ioc->name, ds, ev->channel, ev->id, phy_info->phy_id);
2168
547f9a21 2169#ifdef MPT_DEBUG_SAS_WIDE
dc22f16d
EM
2170 dev_printk(KERN_DEBUG, &port->dev,
2171 "delete port (%d)\n", port->port_identifier);
547f9a21
EM
2172#endif
2173 sas_port_delete(port);
2174 mptsas_port_delete(phy_info->port_details);
9a28f49a
CH
2175 break;
2176 case MPTSAS_ADD_DEVICE:
c73787ee 2177
bd23e94c
ME
2178 if (ev->phys_disk_num_valid)
2179 mpt_findImVolumes(ioc);
2180
c73787ee 2181 /*
e3094447 2182 * Refresh sas device pg0 data
c73787ee 2183 */
e3094447
CH
2184 if (mptsas_sas_device_pg0(ioc, &sas_device,
2185 (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
547f9a21
EM
2186 MPI_SAS_DEVICE_PGAD_FORM_SHIFT), ev->id)) {
2187 dfailprintk((MYIOC_s_ERR_FMT
2188 "%s: exit at line=%d\n", ioc->name,
2189 __FUNCTION__, __LINE__));
e3094447 2190 break;
547f9a21 2191 }
9a28f49a 2192
547f9a21
EM
2193 ssleep(2);
2194 __mptsas_discovery_work(ioc);
e6b2d76a 2195
547f9a21
EM
2196 phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
2197 sas_device.sas_address);
e6b2d76a 2198
547f9a21
EM
2199 if (!phy_info || !phy_info->port_details) {
2200 dfailprintk((MYIOC_s_ERR_FMT
2201 "%s: exit at line=%d\n", ioc->name,
2202 __FUNCTION__, __LINE__));
2203 break;
e6b2d76a
ME
2204 }
2205
547f9a21
EM
2206 starget = mptsas_get_starget(phy_info);
2207 if (starget) {
2208 vtarget = starget->hostdata;
9a28f49a 2209
547f9a21
EM
2210 if (!vtarget) {
2211 dfailprintk((MYIOC_s_ERR_FMT
2212 "%s: exit at line=%d\n", ioc->name,
2213 __FUNCTION__, __LINE__));
f44e5461 2214 break;
547f9a21 2215 }
f44e5461
ME
2216 /*
2217 * Handling RAID components
2218 */
2219 if (vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) {
2220 vtarget->tflags &= ~MPT_TARGET_FLAGS_RAID_COMPONENT;
2221 vtarget->target_id = ev->id;
547f9a21 2222 mptsas_reprobe_target(starget, 0);
f44e5461 2223 }
9a28f49a
CH
2224 break;
2225 }
2226
547f9a21
EM
2227 if (mptsas_get_rphy(phy_info)) {
2228 dfailprintk((MYIOC_s_ERR_FMT
2229 "%s: exit at line=%d\n", ioc->name,
2230 __FUNCTION__, __LINE__));
f44e5461 2231 break;
547f9a21
EM
2232 }
2233 port = mptsas_get_port(phy_info);
2234 if (!port) {
2235 dfailprintk((MYIOC_s_ERR_FMT
2236 "%s: exit at line=%d\n", ioc->name,
2237 __FUNCTION__, __LINE__));
2238 break;
2239 }
f44e5461 2240
e3094447
CH
2241 memcpy(&phy_info->attached, &sas_device,
2242 sizeof(struct mptsas_devinfo));
9a28f49a 2243
c73787ee
ME
2244 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET)
2245 ds = "ssp";
2246 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_STP_TARGET)
2247 ds = "stp";
2248 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
2249 ds = "sata";
2250
2251 printk(MYIOC_s_INFO_FMT
2252 "attaching %s device, channel %d, id %d, phy %d\n",
2253 ioc->name, ds, ev->channel, ev->id, ev->phy_id);
2254
f013db32 2255 mptsas_parse_device_info(&identify, &phy_info->attached);
547f9a21
EM
2256 rphy = sas_end_device_alloc(port);
2257 if (!rphy) {
2258 dfailprintk((MYIOC_s_ERR_FMT
2259 "%s: exit at line=%d\n", ioc->name,
2260 __FUNCTION__, __LINE__));
9a28f49a 2261 break; /* non-fatal: an rphy can be added later */
547f9a21 2262 }
9a28f49a 2263
f013db32 2264 rphy->identify = identify;
9a28f49a 2265 if (sas_rphy_add(rphy)) {
547f9a21
EM
2266 dfailprintk((MYIOC_s_ERR_FMT
2267 "%s: exit at line=%d\n", ioc->name,
2268 __FUNCTION__, __LINE__));
9a28f49a
CH
2269 sas_rphy_free(rphy);
2270 break;
2271 }
547f9a21 2272 mptsas_set_rphy(phy_info, rphy);
9a28f49a 2273 break;
c73787ee 2274 case MPTSAS_ADD_RAID:
e8bf3941
JB
2275 sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL,
2276 ev->id, 0);
c73787ee
ME
2277 if (sdev) {
2278 scsi_device_put(sdev);
2279 break;
2280 }
2281 printk(MYIOC_s_INFO_FMT
4b766471 2282 "attaching raid volume, channel %d, id %d\n",
e8bf3941
JB
2283 ioc->name, MPTSAS_RAID_CHANNEL, ev->id);
2284 scsi_add_device(ioc->sh, MPTSAS_RAID_CHANNEL, ev->id, 0);
c73787ee
ME
2285 mpt_findImVolumes(ioc);
2286 break;
2287 case MPTSAS_DEL_RAID:
e8bf3941
JB
2288 sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL,
2289 ev->id, 0);
c73787ee
ME
2290 if (!sdev)
2291 break;
2292 printk(MYIOC_s_INFO_FMT
4b766471 2293 "removing raid volume, channel %d, id %d\n",
e8bf3941 2294 ioc->name, MPTSAS_RAID_CHANNEL, ev->id);
547f9a21
EM
2295 vdevice = sdev->hostdata;
2296 vdevice->vtarget->deleted = 1;
2297 mptsas_target_reset(ioc, vdevice->vtarget);
c73787ee
ME
2298 scsi_remove_device(sdev);
2299 scsi_device_put(sdev);
2300 mpt_findImVolumes(ioc);
2301 break;
bd23e94c
ME
2302 case MPTSAS_IGNORE_EVENT:
2303 default:
2304 break;
9a28f49a
CH
2305 }
2306
e6b2d76a 2307 mutex_unlock(&ioc->sas_discovery_mutex);
547f9a21
EM
2308 kfree(ev);
2309
9a28f49a
CH
2310}
2311
2312static void
547f9a21 2313mptsas_send_sas_event(MPT_ADAPTER *ioc,
9a28f49a
CH
2314 EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data)
2315{
2316 struct mptsas_hotplug_event *ev;
2317 u32 device_info = le32_to_cpu(sas_event_data->DeviceInfo);
2318 __le64 sas_address;
2319
2320 if ((device_info &
2321 (MPI_SAS_DEVICE_INFO_SSP_TARGET |
2322 MPI_SAS_DEVICE_INFO_STP_TARGET |
2323 MPI_SAS_DEVICE_INFO_SATA_DEVICE )) == 0)
2324 return;
2325
4b766471
ME
2326 switch (sas_event_data->ReasonCode) {
2327 case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
2328 case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
547f9a21 2329 ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
4b766471
ME
2330 if (!ev) {
2331 printk(KERN_WARNING "mptsas: lost hotplug event\n");
2332 break;
2333 }
9a28f49a 2334
4b766471
ME
2335 INIT_WORK(&ev->work, mptsas_hotplug_work, ev);
2336 ev->ioc = ioc;
2337 ev->handle = le16_to_cpu(sas_event_data->DevHandle);
2338 ev->parent_handle =
2339 le16_to_cpu(sas_event_data->ParentDevHandle);
2340 ev->channel = sas_event_data->Bus;
2341 ev->id = sas_event_data->TargetID;
2342 ev->phy_id = sas_event_data->PhyNum;
2343 memcpy(&sas_address, &sas_event_data->SASAddress,
2344 sizeof(__le64));
2345 ev->sas_address = le64_to_cpu(sas_address);
2346 ev->device_info = device_info;
2347
2348 if (sas_event_data->ReasonCode &
2349 MPI_EVENT_SAS_DEV_STAT_RC_ADDED)
2350 ev->event_type = MPTSAS_ADD_DEVICE;
2351 else
2352 ev->event_type = MPTSAS_DEL_DEVICE;
2353 schedule_work(&ev->work);
2354 break;
2355 case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED:
2356 /*
2357 * Persistent table is full.
2358 */
547f9a21
EM
2359 INIT_WORK(&ioc->sas_persist_task,
2360 mptsas_persist_clear_table, (void *)ioc);
2361 schedule_work(&ioc->sas_persist_task);
4b766471
ME
2362 break;
2363 case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
2364 /* TODO */
2365 case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
2366 /* TODO */
2367 default:
2368 break;
9a28f49a 2369 }
9a28f49a
CH
2370}
2371
c73787ee 2372static void
547f9a21 2373mptsas_send_raid_event(MPT_ADAPTER *ioc,
c73787ee
ME
2374 EVENT_DATA_RAID *raid_event_data)
2375{
2376 struct mptsas_hotplug_event *ev;
bd23e94c
ME
2377 int status = le32_to_cpu(raid_event_data->SettingsStatus);
2378 int state = (status >> 8) & 0xff;
c73787ee
ME
2379
2380 if (ioc->bus_type != SAS)
2381 return;
2382
547f9a21 2383 ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
c73787ee
ME
2384 if (!ev) {
2385 printk(KERN_WARNING "mptsas: lost hotplug event\n");
2386 return;
2387 }
2388
c73787ee
ME
2389 INIT_WORK(&ev->work, mptsas_hotplug_work, ev);
2390 ev->ioc = ioc;
2391 ev->id = raid_event_data->VolumeID;
bd23e94c 2392 ev->event_type = MPTSAS_IGNORE_EVENT;
c73787ee
ME
2393
2394 switch (raid_event_data->ReasonCode) {
2395 case MPI_EVENT_RAID_RC_PHYSDISK_DELETED:
2396 ev->event_type = MPTSAS_ADD_DEVICE;
2397 break;
2398 case MPI_EVENT_RAID_RC_PHYSDISK_CREATED:
f44e5461
ME
2399 ioc->raid_data.isRaid = 1;
2400 ev->phys_disk_num_valid = 1;
2401 ev->phys_disk_num = raid_event_data->PhysDiskNum;
c73787ee
ME
2402 ev->event_type = MPTSAS_DEL_DEVICE;
2403 break;
bd23e94c
ME
2404 case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED:
2405 switch (state) {
2406 case MPI_PD_STATE_ONLINE:
2407 ioc->raid_data.isRaid = 1;
2408 ev->phys_disk_num_valid = 1;
2409 ev->phys_disk_num = raid_event_data->PhysDiskNum;
2410 ev->event_type = MPTSAS_ADD_DEVICE;
2411 break;
2412 case MPI_PD_STATE_MISSING:
2413 case MPI_PD_STATE_NOT_COMPATIBLE:
2414 case MPI_PD_STATE_OFFLINE_AT_HOST_REQUEST:
2415 case MPI_PD_STATE_FAILED_AT_HOST_REQUEST:
2416 case MPI_PD_STATE_OFFLINE_FOR_ANOTHER_REASON:
2417 ev->event_type = MPTSAS_DEL_DEVICE;
2418 break;
2419 default:
2420 break;
2421 }
2422 break;
c73787ee
ME
2423 case MPI_EVENT_RAID_RC_VOLUME_DELETED:
2424 ev->event_type = MPTSAS_DEL_RAID;
2425 break;
2426 case MPI_EVENT_RAID_RC_VOLUME_CREATED:
2427 ev->event_type = MPTSAS_ADD_RAID;
2428 break;
2429 case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED:
bd23e94c
ME
2430 switch (state) {
2431 case MPI_RAIDVOL0_STATUS_STATE_FAILED:
2432 case MPI_RAIDVOL0_STATUS_STATE_MISSING:
2433 ev->event_type = MPTSAS_DEL_RAID;
2434 break;
2435 case MPI_RAIDVOL0_STATUS_STATE_OPTIMAL:
2436 case MPI_RAIDVOL0_STATUS_STATE_DEGRADED:
2437 ev->event_type = MPTSAS_ADD_RAID;
2438 break;
2439 default:
2440 break;
2441 }
c73787ee
ME
2442 break;
2443 default:
2444 break;
2445 }
2446 schedule_work(&ev->work);
2447}
2448
e6b2d76a 2449static void
547f9a21 2450mptsas_send_discovery_event(MPT_ADAPTER *ioc,
e6b2d76a
ME
2451 EVENT_DATA_SAS_DISCOVERY *discovery_data)
2452{
2453 struct mptsas_discovery_event *ev;
2454
2455 /*
2456 * DiscoveryStatus
2457 *
2458 * This flag will be non-zero when firmware
2459 * kicks off discovery, and return to zero
2460 * once its completed.
2461 */
2462 if (discovery_data->DiscoveryStatus)
2463 return;
2464
547f9a21 2465 ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
e6b2d76a
ME
2466 if (!ev)
2467 return;
547f9a21 2468 INIT_WORK(&ev->work, mptsas_discovery_work, ev);
e6b2d76a
ME
2469 ev->ioc = ioc;
2470 schedule_work(&ev->work);
2471};
2472
2473
9a28f49a
CH
2474static int
2475mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
2476{
c73787ee 2477 int rc=1;
9a28f49a
CH
2478 u8 event = le32_to_cpu(reply->Event) & 0xFF;
2479
2480 if (!ioc->sh)
c73787ee 2481 goto out;
9a28f49a 2482
e6b2d76a
ME
2483 /*
2484 * sas_discovery_ignore_events
2485 *
2486 * This flag is to prevent anymore processing of
2487 * sas events once mptsas_remove function is called.
2488 */
2489 if (ioc->sas_discovery_ignore_events) {
2490 rc = mptscsih_event_process(ioc, reply);
2491 goto out;
2492 }
2493
9a28f49a
CH
2494 switch (event) {
2495 case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
547f9a21 2496 mptsas_send_sas_event(ioc,
9a28f49a 2497 (EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)reply->Data);
c73787ee
ME
2498 break;
2499 case MPI_EVENT_INTEGRATED_RAID:
547f9a21 2500 mptsas_send_raid_event(ioc,
c73787ee
ME
2501 (EVENT_DATA_RAID *)reply->Data);
2502 break;
79de278e 2503 case MPI_EVENT_PERSISTENT_TABLE_FULL:
547f9a21
EM
2504 INIT_WORK(&ioc->sas_persist_task,
2505 mptsas_persist_clear_table,
79de278e 2506 (void *)ioc);
547f9a21 2507 schedule_work(&ioc->sas_persist_task);
79de278e 2508 break;
4b766471 2509 case MPI_EVENT_SAS_DISCOVERY:
547f9a21 2510 mptsas_send_discovery_event(ioc,
e6b2d76a
ME
2511 (EVENT_DATA_SAS_DISCOVERY *)reply->Data);
2512 break;
9a28f49a 2513 default:
c73787ee
ME
2514 rc = mptscsih_event_process(ioc, reply);
2515 break;
9a28f49a 2516 }
c73787ee
ME
2517 out:
2518
2519 return rc;
9a28f49a
CH
2520}
2521
0c33b27d
CH
2522static int
2523mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
2524{
2525 struct Scsi_Host *sh;
2526 MPT_SCSI_HOST *hd;
2527 MPT_ADAPTER *ioc;
2528 unsigned long flags;
1ca00bb7 2529 int ii;
0c33b27d
CH
2530 int numSGE = 0;
2531 int scale;
2532 int ioc_cap;
0c33b27d
CH
2533 int error=0;
2534 int r;
2535
2536 r = mpt_attach(pdev,id);
2537 if (r)
2538 return r;
2539
2540 ioc = pci_get_drvdata(pdev);
2541 ioc->DoneCtx = mptsasDoneCtx;
2542 ioc->TaskCtx = mptsasTaskCtx;
2543 ioc->InternalCtx = mptsasInternalCtx;
2544
2545 /* Added sanity check on readiness of the MPT adapter.
2546 */
2547 if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
2548 printk(MYIOC_s_WARN_FMT
2549 "Skipping because it's not operational!\n",
2550 ioc->name);
7acec1e7
MED
2551 error = -ENODEV;
2552 goto out_mptsas_probe;
0c33b27d
CH
2553 }
2554
2555 if (!ioc->active) {
2556 printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
2557 ioc->name);
7acec1e7
MED
2558 error = -ENODEV;
2559 goto out_mptsas_probe;
0c33b27d
CH
2560 }
2561
2562 /* Sanity check - ensure at least 1 port is INITIATOR capable
2563 */
2564 ioc_cap = 0;
2565 for (ii = 0; ii < ioc->facts.NumberOfPorts; ii++) {
2566 if (ioc->pfacts[ii].ProtocolFlags &
2567 MPI_PORTFACTS_PROTOCOL_INITIATOR)
2568 ioc_cap++;
2569 }
2570
2571 if (!ioc_cap) {
2572 printk(MYIOC_s_WARN_FMT
2573 "Skipping ioc=%p because SCSI Initiator mode "
2574 "is NOT enabled!\n", ioc->name, ioc);
466544d8 2575 return 0;
0c33b27d
CH
2576 }
2577
2578 sh = scsi_host_alloc(&mptsas_driver_template, sizeof(MPT_SCSI_HOST));
2579 if (!sh) {
2580 printk(MYIOC_s_WARN_FMT
2581 "Unable to register controller with SCSI subsystem\n",
2582 ioc->name);
7acec1e7
MED
2583 error = -1;
2584 goto out_mptsas_probe;
0c33b27d
CH
2585 }
2586
2587 spin_lock_irqsave(&ioc->FreeQlock, flags);
2588
2589 /* Attach the SCSI Host to the IOC structure
2590 */
2591 ioc->sh = sh;
2592
2593 sh->io_port = 0;
2594 sh->n_io_port = 0;
2595 sh->irq = 0;
2596
2597 /* set 16 byte cdb's */
2598 sh->max_cmd_len = 16;
2599
2600 sh->max_id = ioc->pfacts->MaxDevices + 1;
2601
2602 sh->transportt = mptsas_transport_template;
2603
2604 sh->max_lun = MPT_LAST_LUN + 1;
2605 sh->max_channel = 0;
2606 sh->this_id = ioc->pfacts[0].PortSCSIID;
2607
2608 /* Required entry.
2609 */
2610 sh->unique_id = ioc->id;
2611
2612 INIT_LIST_HEAD(&ioc->sas_topology);
9a28f49a 2613 mutex_init(&ioc->sas_topology_mutex);
e6b2d76a 2614 mutex_init(&ioc->sas_discovery_mutex);
eeb846ce 2615 mutex_init(&ioc->sas_mgmt.mutex);
da4fa655 2616 init_completion(&ioc->sas_mgmt.done);
0c33b27d
CH
2617
2618 /* Verify that we won't exceed the maximum
2619 * number of chain buffers
2620 * We can optimize: ZZ = req_sz/sizeof(SGE)
2621 * For 32bit SGE's:
2622 * numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
2623 * + (req_sz - 64)/sizeof(SGE)
2624 * A slightly different algorithm is required for
2625 * 64bit SGEs.
2626 */
2627 scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
2628 if (sizeof(dma_addr_t) == sizeof(u64)) {
2629 numSGE = (scale - 1) *
2630 (ioc->facts.MaxChainDepth-1) + scale +
2631 (ioc->req_sz - 60) / (sizeof(dma_addr_t) +
2632 sizeof(u32));
2633 } else {
2634 numSGE = 1 + (scale - 1) *
2635 (ioc->facts.MaxChainDepth-1) + scale +
2636 (ioc->req_sz - 64) / (sizeof(dma_addr_t) +
2637 sizeof(u32));
2638 }
2639
2640 if (numSGE < sh->sg_tablesize) {
2641 /* Reset this value */
2642 dprintk((MYIOC_s_INFO_FMT
2643 "Resetting sg_tablesize to %d from %d\n",
2644 ioc->name, numSGE, sh->sg_tablesize));
2645 sh->sg_tablesize = numSGE;
2646 }
2647
2648 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
2649
2650 hd = (MPT_SCSI_HOST *) sh->hostdata;
2651 hd->ioc = ioc;
2652
2653 /* SCSI needs scsi_cmnd lookup table!
2654 * (with size equal to req_depth*PtrSz!)
2655 */
1ca00bb7
CH
2656 hd->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);
2657 if (!hd->ScsiLookup) {
0c33b27d 2658 error = -ENOMEM;
7acec1e7 2659 goto out_mptsas_probe;
0c33b27d
CH
2660 }
2661
1ca00bb7
CH
2662 dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n",
2663 ioc->name, hd->ScsiLookup));
0c33b27d
CH
2664
2665 /* Allocate memory for the device structures.
2666 * A non-Null pointer at an offset
2667 * indicates a device exists.
2668 * max_id = 1 + maximum id (hosts.h)
2669 */
1ca00bb7
CH
2670 hd->Targets = kcalloc(sh->max_id, sizeof(void *), GFP_ATOMIC);
2671 if (!hd->Targets) {
0c33b27d 2672 error = -ENOMEM;
7acec1e7 2673 goto out_mptsas_probe;
0c33b27d
CH
2674 }
2675
1ca00bb7 2676 dprintk((KERN_INFO " vtarget @ %p\n", hd->Targets));
0c33b27d
CH
2677
2678 /* Clear the TM flags
2679 */
2680 hd->tmPending = 0;
2681 hd->tmState = TM_STATE_NONE;
2682 hd->resetPending = 0;
2683 hd->abortSCpnt = NULL;
2684
2685 /* Clear the pointer used to store
2686 * single-threaded commands, i.e., those
2687 * issued during a bus scan, dv and
2688 * configuration pages.
2689 */
2690 hd->cmdPtr = NULL;
2691
2692 /* Initialize this SCSI Hosts' timers
2693 * To use, set the timer expires field
2694 * and add_timer
2695 */
2696 init_timer(&hd->timer);
2697 hd->timer.data = (unsigned long) hd;
2698 hd->timer.function = mptscsih_timer_expired;
2699
0c33b27d
CH
2700 ioc->sas_data.ptClear = mpt_pt_clear;
2701
2702 if (ioc->sas_data.ptClear==1) {
2703 mptbase_sas_persist_operation(
2704 ioc, MPI_SAS_OP_CLEAR_ALL_PERSISTENT);
2705 }
2706
0c33b27d
CH
2707 init_waitqueue_head(&hd->scandv_waitq);
2708 hd->scandv_wait_done = 0;
2709 hd->last_queue_full = 0;
2710
2711 error = scsi_add_host(sh, &ioc->pcidev->dev);
2712 if (error) {
2713 dprintk((KERN_ERR MYNAM
2714 "scsi_add_host failed\n"));
7acec1e7 2715 goto out_mptsas_probe;
0c33b27d
CH
2716 }
2717
2718 mptsas_scan_sas_topology(ioc);
2719
2720 return 0;
2721
547f9a21 2722 out_mptsas_probe:
0c33b27d
CH
2723
2724 mptscsih_remove(pdev);
2725 return error;
2726}
2727
2728static void __devexit mptsas_remove(struct pci_dev *pdev)
2729{
2730 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
2731 struct mptsas_portinfo *p, *n;
547f9a21 2732 int i;
0c33b27d 2733
e6b2d76a 2734 ioc->sas_discovery_ignore_events=1;
0c33b27d
CH
2735 sas_remove_host(ioc->sh);
2736
9a28f49a 2737 mutex_lock(&ioc->sas_topology_mutex);
0c33b27d
CH
2738 list_for_each_entry_safe(p, n, &ioc->sas_topology, list) {
2739 list_del(&p->list);
547f9a21
EM
2740 for (i = 0 ; i < p->num_phys ; i++)
2741 mptsas_port_delete(p->phy_info[i].port_details);
2742 kfree(p->phy_info);
0c33b27d
CH
2743 kfree(p);
2744 }
9a28f49a 2745 mutex_unlock(&ioc->sas_topology_mutex);
0c33b27d
CH
2746
2747 mptscsih_remove(pdev);
2748}
2749
2750static struct pci_device_id mptsas_pci_table[] = {
87cf8986 2751 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1064,
0c33b27d 2752 PCI_ANY_ID, PCI_ANY_ID },
87cf8986 2753 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1068,
0c33b27d 2754 PCI_ANY_ID, PCI_ANY_ID },
87cf8986 2755 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1064E,
0c33b27d 2756 PCI_ANY_ID, PCI_ANY_ID },
87cf8986 2757 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1068E,
0c33b27d 2758 PCI_ANY_ID, PCI_ANY_ID },
87cf8986 2759 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1078,
0c33b27d
CH
2760 PCI_ANY_ID, PCI_ANY_ID },
2761 {0} /* Terminating entry */
2762};
2763MODULE_DEVICE_TABLE(pci, mptsas_pci_table);
2764
2765
2766static struct pci_driver mptsas_driver = {
2767 .name = "mptsas",
2768 .id_table = mptsas_pci_table,
2769 .probe = mptsas_probe,
2770 .remove = __devexit_p(mptsas_remove),
2771 .shutdown = mptscsih_shutdown,
2772#ifdef CONFIG_PM
2773 .suspend = mptscsih_suspend,
2774 .resume = mptscsih_resume,
2775#endif
2776};
2777
2778static int __init
2779mptsas_init(void)
2780{
2781 show_mptmod_ver(my_NAME, my_VERSION);
2782
2783 mptsas_transport_template =
2784 sas_attach_transport(&mptsas_transport_functions);
2785 if (!mptsas_transport_template)
2786 return -ENODEV;
2787
2788 mptsasDoneCtx = mpt_register(mptscsih_io_done, MPTSAS_DRIVER);
2789 mptsasTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSAS_DRIVER);
2790 mptsasInternalCtx =
2791 mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER);
da4fa655 2792 mptsasMgmtCtx = mpt_register(mptsas_mgmt_done, MPTSAS_DRIVER);
0c33b27d 2793
9a28f49a 2794 if (mpt_event_register(mptsasDoneCtx, mptsas_event_process) == 0) {
3a892bef 2795 devtverboseprintk((KERN_INFO MYNAM
0c33b27d
CH
2796 ": Registered for IOC event notifications\n"));
2797 }
2798
2799 if (mpt_reset_register(mptsasDoneCtx, mptscsih_ioc_reset) == 0) {
2800 dprintk((KERN_INFO MYNAM
2801 ": Registered for IOC reset notifications\n"));
2802 }
2803
2804 return pci_register_driver(&mptsas_driver);
2805}
2806
2807static void __exit
2808mptsas_exit(void)
2809{
2810 pci_unregister_driver(&mptsas_driver);
2811 sas_release_transport(mptsas_transport_template);
2812
2813 mpt_reset_deregister(mptsasDoneCtx);
2814 mpt_event_deregister(mptsasDoneCtx);
2815
da4fa655 2816 mpt_deregister(mptsasMgmtCtx);
0c33b27d
CH
2817 mpt_deregister(mptsasInternalCtx);
2818 mpt_deregister(mptsasTaskCtx);
2819 mpt_deregister(mptsasDoneCtx);
2820}
2821
2822module_init(mptsas_init);
2823module_exit(mptsas_exit);