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.
6 * Copyright (c) 1999-2005 LSI Logic Corporation
7 * (mailto:mpt_linux_developer@lsil.com)
8 * Copyright (c) 2005-2006 Dell
10 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
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.
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.
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.
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
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
45 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
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>
54 #include <scsi/scsi_cmnd.h>
55 #include <scsi/scsi_device.h>
56 #include <scsi/scsi_host.h>
57 #include <scsi/scsi_transport_sas.h>
63 #define my_NAME "Fusion MPT SAS Host driver"
64 #define my_VERSION MPT_LINUX_VERSION_COMMON
65 #define MYNAM "mptsas"
67 MODULE_AUTHOR(MODULEAUTHOR
);
68 MODULE_DESCRIPTION(my_NAME
);
69 MODULE_LICENSE("GPL");
71 static int mpt_pq_filter
;
72 module_param(mpt_pq_filter
, int, 0);
73 MODULE_PARM_DESC(mpt_pq_filter
,
74 "Enable peripheral qualifier filter: enable=1 "
77 static int mpt_pt_clear
;
78 module_param(mpt_pt_clear
, int, 0);
79 MODULE_PARM_DESC(mpt_pt_clear
,
80 "Clear persistency table: enable=1 "
81 "(default=MPTSCSIH_PT_CLEAR=0)");
83 static int mptsasDoneCtx
= -1;
84 static int mptsasTaskCtx
= -1;
85 static int mptsasInternalCtx
= -1; /* Used only for internal commands */
86 static int mptsasMgmtCtx
= -1;
89 enum mptsas_hotplug_action
{
96 struct mptsas_hotplug_event
{
97 struct work_struct work
;
99 enum mptsas_hotplug_action event_type
;
110 * SAS topology structures
112 * The MPT Fusion firmware interface spreads information about the
113 * SAS topology over many manufacture pages, thus we need some data
114 * structure to collect it and process it for the SAS transport class.
117 struct mptsas_devinfo
{
118 u16 handle
; /* unique id to address this device */
119 u16 handle_parent
; /* unique id to address parent device */
120 u16 handle_enclosure
; /* enclosure identifier of the enclosure */
121 u16 slot
; /* physical slot in enclosure */
122 u8 phy_id
; /* phy number of parent device */
123 u8 port_id
; /* sas physical port this device
125 u8 id
; /* logical target id of this device */
126 u8 channel
; /* logical bus number of this device */
127 u64 sas_address
; /* WWN of this device,
128 SATA is assigned by HBA,expander */
129 u32 device_info
; /* bitfield detailed info about this device */
132 struct mptsas_phyinfo
{
133 u8 phy_id
; /* phy index */
134 u8 port_id
; /* port number this phy is part of */
135 u8 negotiated_link_rate
; /* nego'd link rate for this phy */
136 u8 hw_link_rate
; /* hardware max/min phys link rate */
137 u8 programmed_link_rate
; /* programmed max/min phy link rate */
138 struct mptsas_devinfo identify
; /* point to phy device info */
139 struct mptsas_devinfo attached
; /* point to attached device info */
141 struct sas_rphy
*rphy
;
144 struct mptsas_portinfo
{
145 struct list_head list
;
146 u16 handle
; /* unique id to address this */
147 u8 num_phys
; /* number of phys */
148 struct mptsas_phyinfo
*phy_info
;
151 struct mptsas_enclosure
{
152 u64 enclosure_logical_id
; /* The WWN for the enclosure */
153 u16 enclosure_handle
; /* unique id to address this */
154 u16 flags
; /* details enclosure management */
155 u16 num_slot
; /* num slots */
156 u16 start_slot
; /* first slot */
157 u8 start_id
; /* starting logical target id */
158 u8 start_channel
; /* starting logical channel id */
159 u8 sep_id
; /* SEP device logical target id */
160 u8 sep_channel
; /* SEP channel logical channel id */
165 static void mptsas_print_phy_data(MPI_SAS_IO_UNIT0_PHY_DATA
*phy_data
)
167 printk("---- IO UNIT PAGE 0 ------------\n");
168 printk("Handle=0x%X\n",
169 le16_to_cpu(phy_data
->AttachedDeviceHandle
));
170 printk("Controller Handle=0x%X\n",
171 le16_to_cpu(phy_data
->ControllerDevHandle
));
172 printk("Port=0x%X\n", phy_data
->Port
);
173 printk("Port Flags=0x%X\n", phy_data
->PortFlags
);
174 printk("PHY Flags=0x%X\n", phy_data
->PhyFlags
);
175 printk("Negotiated Link Rate=0x%X\n", phy_data
->NegotiatedLinkRate
);
176 printk("Controller PHY Device Info=0x%X\n",
177 le32_to_cpu(phy_data
->ControllerPhyDeviceInfo
));
178 printk("DiscoveryStatus=0x%X\n",
179 le32_to_cpu(phy_data
->DiscoveryStatus
));
183 static void mptsas_print_phy_pg0(SasPhyPage0_t
*pg0
)
187 memcpy(&sas_address
, &pg0
->SASAddress
, sizeof(__le64
));
189 printk("---- SAS PHY PAGE 0 ------------\n");
190 printk("Attached Device Handle=0x%X\n",
191 le16_to_cpu(pg0
->AttachedDevHandle
));
192 printk("SAS Address=0x%llX\n",
193 (unsigned long long)le64_to_cpu(sas_address
));
194 printk("Attached PHY Identifier=0x%X\n", pg0
->AttachedPhyIdentifier
);
195 printk("Attached Device Info=0x%X\n",
196 le32_to_cpu(pg0
->AttachedDeviceInfo
));
197 printk("Programmed Link Rate=0x%X\n", pg0
->ProgrammedLinkRate
);
198 printk("Change Count=0x%X\n", pg0
->ChangeCount
);
199 printk("PHY Info=0x%X\n", le32_to_cpu(pg0
->PhyInfo
));
203 static void mptsas_print_phy_pg1(SasPhyPage1_t
*pg1
)
205 printk("---- SAS PHY PAGE 1 ------------\n");
206 printk("Invalid Dword Count=0x%x\n", pg1
->InvalidDwordCount
);
207 printk("Running Disparity Error Count=0x%x\n",
208 pg1
->RunningDisparityErrorCount
);
209 printk("Loss Dword Synch Count=0x%x\n", pg1
->LossDwordSynchCount
);
210 printk("PHY Reset Problem Count=0x%x\n", pg1
->PhyResetProblemCount
);
214 static void mptsas_print_device_pg0(SasDevicePage0_t
*pg0
)
218 memcpy(&sas_address
, &pg0
->SASAddress
, sizeof(__le64
));
220 printk("---- SAS DEVICE PAGE 0 ---------\n");
221 printk("Handle=0x%X\n" ,le16_to_cpu(pg0
->DevHandle
));
222 printk("Parent Handle=0x%X\n" ,le16_to_cpu(pg0
->ParentDevHandle
));
223 printk("Enclosure Handle=0x%X\n", le16_to_cpu(pg0
->EnclosureHandle
));
224 printk("Slot=0x%X\n", le16_to_cpu(pg0
->Slot
));
225 printk("SAS Address=0x%llX\n", le64_to_cpu(sas_address
));
226 printk("Target ID=0x%X\n", pg0
->TargetID
);
227 printk("Bus=0x%X\n", pg0
->Bus
);
228 /* The PhyNum field specifies the PHY number of the parent
229 * device this device is linked to
231 printk("Parent Phy Num=0x%X\n", pg0
->PhyNum
);
232 printk("Access Status=0x%X\n", le16_to_cpu(pg0
->AccessStatus
));
233 printk("Device Info=0x%X\n", le32_to_cpu(pg0
->DeviceInfo
));
234 printk("Flags=0x%X\n", le16_to_cpu(pg0
->Flags
));
235 printk("Physical Port=0x%X\n", pg0
->PhysicalPort
);
239 static void mptsas_print_expander_pg1(SasExpanderPage1_t
*pg1
)
241 printk("---- SAS EXPANDER PAGE 1 ------------\n");
243 printk("Physical Port=0x%X\n", pg1
->PhysicalPort
);
244 printk("PHY Identifier=0x%X\n", pg1
->PhyIdentifier
);
245 printk("Negotiated Link Rate=0x%X\n", pg1
->NegotiatedLinkRate
);
246 printk("Programmed Link Rate=0x%X\n", pg1
->ProgrammedLinkRate
);
247 printk("Hardware Link Rate=0x%X\n", pg1
->HwLinkRate
);
248 printk("Owner Device Handle=0x%X\n",
249 le16_to_cpu(pg1
->OwnerDevHandle
));
250 printk("Attached Device Handle=0x%X\n",
251 le16_to_cpu(pg1
->AttachedDevHandle
));
254 #define mptsas_print_phy_data(phy_data) do { } while (0)
255 #define mptsas_print_phy_pg0(pg0) do { } while (0)
256 #define mptsas_print_phy_pg1(pg1) do { } while (0)
257 #define mptsas_print_device_pg0(pg0) do { } while (0)
258 #define mptsas_print_expander_pg1(pg1) do { } while (0)
261 static inline MPT_ADAPTER
*phy_to_ioc(struct sas_phy
*phy
)
263 struct Scsi_Host
*shost
= dev_to_shost(phy
->dev
.parent
);
264 return ((MPT_SCSI_HOST
*)shost
->hostdata
)->ioc
;
267 static inline MPT_ADAPTER
*rphy_to_ioc(struct sas_rphy
*rphy
)
269 struct Scsi_Host
*shost
= dev_to_shost(rphy
->dev
.parent
->parent
);
270 return ((MPT_SCSI_HOST
*)shost
->hostdata
)->ioc
;
274 mptsas_sas_enclosure_pg0(MPT_ADAPTER
*ioc
, struct mptsas_enclosure
*enclosure
,
275 u32 form
, u32 form_specific
)
277 ConfigExtendedPageHeader_t hdr
;
279 SasEnclosurePage0_t
*buffer
;
280 dma_addr_t dma_handle
;
282 __le64 le_identifier
;
284 memset(&hdr
, 0, sizeof(hdr
));
285 hdr
.PageVersion
= MPI_SASENCLOSURE0_PAGEVERSION
;
287 hdr
.PageType
= MPI_CONFIG_PAGETYPE_EXTENDED
;
288 hdr
.ExtPageType
= MPI_CONFIG_EXTPAGETYPE_ENCLOSURE
;
290 cfg
.cfghdr
.ehdr
= &hdr
;
292 cfg
.pageAddr
= form
+ form_specific
;
293 cfg
.action
= MPI_CONFIG_ACTION_PAGE_HEADER
;
294 cfg
.dir
= 0; /* read */
297 error
= mpt_config(ioc
, &cfg
);
300 if (!hdr
.ExtPageLength
) {
305 buffer
= pci_alloc_consistent(ioc
->pcidev
, hdr
.ExtPageLength
* 4,
312 cfg
.physAddr
= dma_handle
;
313 cfg
.action
= MPI_CONFIG_ACTION_PAGE_READ_CURRENT
;
315 error
= mpt_config(ioc
, &cfg
);
317 goto out_free_consistent
;
319 /* save config data */
320 memcpy(&le_identifier
, &buffer
->EnclosureLogicalID
, sizeof(__le64
));
321 enclosure
->enclosure_logical_id
= le64_to_cpu(le_identifier
);
322 enclosure
->enclosure_handle
= le16_to_cpu(buffer
->EnclosureHandle
);
323 enclosure
->flags
= le16_to_cpu(buffer
->Flags
);
324 enclosure
->num_slot
= le16_to_cpu(buffer
->NumSlots
);
325 enclosure
->start_slot
= le16_to_cpu(buffer
->StartSlot
);
326 enclosure
->start_id
= buffer
->StartTargetID
;
327 enclosure
->start_channel
= buffer
->StartBus
;
328 enclosure
->sep_id
= buffer
->SEPTargetID
;
329 enclosure
->sep_channel
= buffer
->SEPBus
;
332 pci_free_consistent(ioc
->pcidev
, hdr
.ExtPageLength
* 4,
339 * This is pretty ugly. We will be able to seriously clean it up
340 * once the DV code in mptscsih goes away and we can properly
341 * implement ->target_alloc.
344 mptsas_slave_alloc(struct scsi_device
*sdev
)
346 struct Scsi_Host
*host
= sdev
->host
;
347 MPT_SCSI_HOST
*hd
= (MPT_SCSI_HOST
*)host
->hostdata
;
348 struct sas_rphy
*rphy
;
349 struct mptsas_portinfo
*p
;
352 struct scsi_target
*starget
;
356 vdev
= kzalloc(sizeof(VirtDevice
), GFP_KERNEL
);
358 printk(MYIOC_s_ERR_FMT
"slave_alloc kmalloc(%zd) FAILED!\n",
359 hd
->ioc
->name
, sizeof(VirtDevice
));
362 sdev
->hostdata
= vdev
;
363 starget
= scsi_target(sdev
);
364 vtarget
= starget
->hostdata
;
365 vtarget
->ioc_id
= hd
->ioc
->id
;
366 vdev
->vtarget
= vtarget
;
367 if (vtarget
->num_luns
== 0) {
368 vtarget
->tflags
= MPT_TARGET_FLAGS_Q_YES
|MPT_TARGET_FLAGS_VALID_INQUIRY
;
369 hd
->Targets
[sdev
->id
] = vtarget
;
373 RAID volumes placed beyond the last expected port.
375 if (sdev
->channel
== hd
->ioc
->num_ports
) {
376 target_id
= sdev
->id
;
382 rphy
= dev_to_rphy(sdev
->sdev_target
->dev
.parent
);
383 mutex_lock(&hd
->ioc
->sas_topology_mutex
);
384 list_for_each_entry(p
, &hd
->ioc
->sas_topology
, list
) {
385 for (i
= 0; i
< p
->num_phys
; i
++) {
386 if (p
->phy_info
[i
].attached
.sas_address
==
387 rphy
->identify
.sas_address
) {
388 target_id
= p
->phy_info
[i
].attached
.id
;
389 vtarget
->bus_id
= p
->phy_info
[i
].attached
.channel
;
390 vdev
->lun
= sdev
->lun
;
391 mutex_unlock(&hd
->ioc
->sas_topology_mutex
);
396 mutex_unlock(&hd
->ioc
->sas_topology_mutex
);
402 vtarget
->target_id
= target_id
;
408 mptsas_slave_destroy(struct scsi_device
*sdev
)
410 struct Scsi_Host
*host
= sdev
->host
;
411 MPT_SCSI_HOST
*hd
= (MPT_SCSI_HOST
*)host
->hostdata
;
412 struct sas_rphy
*rphy
;
413 struct mptsas_portinfo
*p
;
418 * Handle hotplug removal case.
419 * We need to clear out attached data structure.
421 rphy
= dev_to_rphy(sdev
->sdev_target
->dev
.parent
);
423 mutex_lock(&hd
->ioc
->sas_topology_mutex
);
424 list_for_each_entry(p
, &hd
->ioc
->sas_topology
, list
) {
425 for (i
= 0; i
< p
->num_phys
; i
++) {
426 if (p
->phy_info
[i
].attached
.sas_address
==
427 rphy
->identify
.sas_address
) {
428 memset(&p
->phy_info
[i
].attached
, 0,
429 sizeof(struct mptsas_devinfo
));
430 p
->phy_info
[i
].rphy
= NULL
;
437 mutex_unlock(&hd
->ioc
->sas_topology_mutex
);
439 * Issue target reset to flush firmware outstanding commands.
441 vdev
= sdev
->hostdata
;
442 if (vdev
->configured_lun
){
443 if (mptscsih_TMHandler(hd
,
444 MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET
,
445 vdev
->vtarget
->bus_id
,
446 vdev
->vtarget
->target_id
,
447 0, 0, 5 /* 5 second timeout */)
450 /* The TM request failed!
453 printk(MYIOC_s_WARN_FMT
454 "Error processing TaskMgmt id=%d TARGET_RESET\n",
456 vdev
->vtarget
->target_id
);
459 hd
->tmState
= TM_STATE_NONE
;
462 mptscsih_slave_destroy(sdev
);
465 static struct scsi_host_template mptsas_driver_template
= {
466 .module
= THIS_MODULE
,
467 .proc_name
= "mptsas",
468 .proc_info
= mptscsih_proc_info
,
469 .name
= "MPT SPI Host",
470 .info
= mptscsih_info
,
471 .queuecommand
= mptscsih_qcmd
,
472 .target_alloc
= mptscsih_target_alloc
,
473 .slave_alloc
= mptsas_slave_alloc
,
474 .slave_configure
= mptscsih_slave_configure
,
475 .target_destroy
= mptscsih_target_destroy
,
476 .slave_destroy
= mptsas_slave_destroy
,
477 .change_queue_depth
= mptscsih_change_queue_depth
,
478 .eh_abort_handler
= mptscsih_abort
,
479 .eh_device_reset_handler
= mptscsih_dev_reset
,
480 .eh_bus_reset_handler
= mptscsih_bus_reset
,
481 .eh_host_reset_handler
= mptscsih_host_reset
,
482 .bios_param
= mptscsih_bios_param
,
483 .can_queue
= MPT_FC_CAN_QUEUE
,
485 .sg_tablesize
= MPT_SCSI_SG_DEPTH
,
488 .use_clustering
= ENABLE_CLUSTERING
,
491 static int mptsas_get_linkerrors(struct sas_phy
*phy
)
493 MPT_ADAPTER
*ioc
= phy_to_ioc(phy
);
494 ConfigExtendedPageHeader_t hdr
;
496 SasPhyPage1_t
*buffer
;
497 dma_addr_t dma_handle
;
500 hdr
.PageVersion
= MPI_SASPHY1_PAGEVERSION
;
501 hdr
.ExtPageLength
= 0;
502 hdr
.PageNumber
= 1 /* page number 1*/;
505 hdr
.PageType
= MPI_CONFIG_PAGETYPE_EXTENDED
;
506 hdr
.ExtPageType
= MPI_CONFIG_EXTPAGETYPE_SAS_PHY
;
508 cfg
.cfghdr
.ehdr
= &hdr
;
510 cfg
.pageAddr
= phy
->identify
.phy_identifier
;
511 cfg
.action
= MPI_CONFIG_ACTION_PAGE_HEADER
;
512 cfg
.dir
= 0; /* read */
515 error
= mpt_config(ioc
, &cfg
);
518 if (!hdr
.ExtPageLength
)
521 buffer
= pci_alloc_consistent(ioc
->pcidev
, hdr
.ExtPageLength
* 4,
526 cfg
.physAddr
= dma_handle
;
527 cfg
.action
= MPI_CONFIG_ACTION_PAGE_READ_CURRENT
;
529 error
= mpt_config(ioc
, &cfg
);
531 goto out_free_consistent
;
533 mptsas_print_phy_pg1(buffer
);
535 phy
->invalid_dword_count
= le32_to_cpu(buffer
->InvalidDwordCount
);
536 phy
->running_disparity_error_count
=
537 le32_to_cpu(buffer
->RunningDisparityErrorCount
);
538 phy
->loss_of_dword_sync_count
=
539 le32_to_cpu(buffer
->LossDwordSynchCount
);
540 phy
->phy_reset_problem_count
=
541 le32_to_cpu(buffer
->PhyResetProblemCount
);
544 pci_free_consistent(ioc
->pcidev
, hdr
.ExtPageLength
* 4,
549 static int mptsas_mgmt_done(MPT_ADAPTER
*ioc
, MPT_FRAME_HDR
*req
,
550 MPT_FRAME_HDR
*reply
)
552 ioc
->sas_mgmt
.status
|= MPT_SAS_MGMT_STATUS_COMMAND_GOOD
;
554 ioc
->sas_mgmt
.status
|= MPT_SAS_MGMT_STATUS_RF_VALID
;
555 memcpy(ioc
->sas_mgmt
.reply
, reply
,
556 min(ioc
->reply_sz
, 4 * reply
->u
.reply
.MsgLength
));
558 complete(&ioc
->sas_mgmt
.done
);
562 static int mptsas_phy_reset(struct sas_phy
*phy
, int hard_reset
)
564 MPT_ADAPTER
*ioc
= phy_to_ioc(phy
);
565 SasIoUnitControlRequest_t
*req
;
566 SasIoUnitControlReply_t
*reply
;
569 unsigned long timeleft
;
570 int error
= -ERESTARTSYS
;
572 /* not implemented for expanders */
573 if (phy
->identify
.target_port_protocols
& SAS_PROTOCOL_SMP
)
576 if (mutex_lock_interruptible(&ioc
->sas_mgmt
.mutex
))
579 mf
= mpt_get_msg_frame(mptsasMgmtCtx
, ioc
);
585 hdr
= (MPIHeader_t
*) mf
;
586 req
= (SasIoUnitControlRequest_t
*)mf
;
587 memset(req
, 0, sizeof(SasIoUnitControlRequest_t
));
588 req
->Function
= MPI_FUNCTION_SAS_IO_UNIT_CONTROL
;
589 req
->MsgContext
= hdr
->MsgContext
;
590 req
->Operation
= hard_reset
?
591 MPI_SAS_OP_PHY_HARD_RESET
: MPI_SAS_OP_PHY_LINK_RESET
;
592 req
->PhyNum
= phy
->identify
.phy_identifier
;
594 mpt_put_msg_frame(mptsasMgmtCtx
, ioc
, mf
);
596 timeleft
= wait_for_completion_timeout(&ioc
->sas_mgmt
.done
,
599 /* On timeout reset the board */
600 mpt_free_msg_frame(ioc
, mf
);
601 mpt_HardResetHandler(ioc
, CAN_SLEEP
);
606 /* a reply frame is expected */
607 if ((ioc
->sas_mgmt
.status
&
608 MPT_IOCTL_STATUS_RF_VALID
) == 0) {
613 /* process the completed Reply Message Frame */
614 reply
= (SasIoUnitControlReply_t
*)ioc
->sas_mgmt
.reply
;
615 if (reply
->IOCStatus
!= MPI_IOCSTATUS_SUCCESS
) {
616 printk("%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",
627 mutex_unlock(&ioc
->sas_mgmt
.mutex
);
633 mptsas_get_enclosure_identifier(struct sas_rphy
*rphy
, u64
*identifier
)
635 MPT_ADAPTER
*ioc
= rphy_to_ioc(rphy
);
637 struct mptsas_portinfo
*p
;
638 struct mptsas_enclosure enclosure_info
;
639 u64 enclosure_handle
;
641 mutex_lock(&ioc
->sas_topology_mutex
);
642 list_for_each_entry(p
, &ioc
->sas_topology
, list
) {
643 for (i
= 0; i
< p
->num_phys
; i
++) {
644 if (p
->phy_info
[i
].attached
.sas_address
==
645 rphy
->identify
.sas_address
) {
646 enclosure_handle
= p
->phy_info
[i
].
647 attached
.handle_enclosure
;
652 mutex_unlock(&ioc
->sas_topology_mutex
);
656 mutex_unlock(&ioc
->sas_topology_mutex
);
657 memset(&enclosure_info
, 0, sizeof(struct mptsas_enclosure
));
658 error
= mptsas_sas_enclosure_pg0(ioc
, &enclosure_info
,
659 (MPI_SAS_ENCLOS_PGAD_FORM_HANDLE
<<
660 MPI_SAS_ENCLOS_PGAD_FORM_SHIFT
), enclosure_handle
);
662 *identifier
= enclosure_info
.enclosure_logical_id
;
667 mptsas_get_bay_identifier(struct sas_rphy
*rphy
)
669 MPT_ADAPTER
*ioc
= rphy_to_ioc(rphy
);
670 struct mptsas_portinfo
*p
;
673 mutex_lock(&ioc
->sas_topology_mutex
);
674 list_for_each_entry(p
, &ioc
->sas_topology
, list
) {
675 for (i
= 0; i
< p
->num_phys
; i
++) {
676 if (p
->phy_info
[i
].attached
.sas_address
==
677 rphy
->identify
.sas_address
) {
678 rc
= p
->phy_info
[i
].attached
.slot
;
685 mutex_unlock(&ioc
->sas_topology_mutex
);
689 static struct sas_function_template mptsas_transport_functions
= {
690 .get_linkerrors
= mptsas_get_linkerrors
,
691 .get_enclosure_identifier
= mptsas_get_enclosure_identifier
,
692 .get_bay_identifier
= mptsas_get_bay_identifier
,
693 .phy_reset
= mptsas_phy_reset
,
696 static struct scsi_transport_template
*mptsas_transport_template
;
699 mptsas_sas_io_unit_pg0(MPT_ADAPTER
*ioc
, struct mptsas_portinfo
*port_info
)
701 ConfigExtendedPageHeader_t hdr
;
703 SasIOUnitPage0_t
*buffer
;
704 dma_addr_t dma_handle
;
707 hdr
.PageVersion
= MPI_SASIOUNITPAGE0_PAGEVERSION
;
708 hdr
.ExtPageLength
= 0;
712 hdr
.PageType
= MPI_CONFIG_PAGETYPE_EXTENDED
;
713 hdr
.ExtPageType
= MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT
;
715 cfg
.cfghdr
.ehdr
= &hdr
;
718 cfg
.action
= MPI_CONFIG_ACTION_PAGE_HEADER
;
719 cfg
.dir
= 0; /* read */
722 error
= mpt_config(ioc
, &cfg
);
725 if (!hdr
.ExtPageLength
) {
730 buffer
= pci_alloc_consistent(ioc
->pcidev
, hdr
.ExtPageLength
* 4,
737 cfg
.physAddr
= dma_handle
;
738 cfg
.action
= MPI_CONFIG_ACTION_PAGE_READ_CURRENT
;
740 error
= mpt_config(ioc
, &cfg
);
742 goto out_free_consistent
;
744 port_info
->num_phys
= buffer
->NumPhys
;
745 port_info
->phy_info
= kcalloc(port_info
->num_phys
,
746 sizeof(struct mptsas_phyinfo
),GFP_KERNEL
);
747 if (!port_info
->phy_info
) {
749 goto out_free_consistent
;
752 if (port_info
->num_phys
)
754 le16_to_cpu(buffer
->PhyData
[0].ControllerDevHandle
);
755 for (i
= 0; i
< port_info
->num_phys
; i
++) {
756 mptsas_print_phy_data(&buffer
->PhyData
[i
]);
757 port_info
->phy_info
[i
].phy_id
= i
;
758 port_info
->phy_info
[i
].port_id
=
759 buffer
->PhyData
[i
].Port
;
760 port_info
->phy_info
[i
].negotiated_link_rate
=
761 buffer
->PhyData
[i
].NegotiatedLinkRate
;
765 pci_free_consistent(ioc
->pcidev
, hdr
.ExtPageLength
* 4,
772 mptsas_sas_phy_pg0(MPT_ADAPTER
*ioc
, struct mptsas_phyinfo
*phy_info
,
773 u32 form
, u32 form_specific
)
775 ConfigExtendedPageHeader_t hdr
;
777 SasPhyPage0_t
*buffer
;
778 dma_addr_t dma_handle
;
781 hdr
.PageVersion
= MPI_SASPHY0_PAGEVERSION
;
782 hdr
.ExtPageLength
= 0;
786 hdr
.PageType
= MPI_CONFIG_PAGETYPE_EXTENDED
;
787 hdr
.ExtPageType
= MPI_CONFIG_EXTPAGETYPE_SAS_PHY
;
789 cfg
.cfghdr
.ehdr
= &hdr
;
790 cfg
.dir
= 0; /* read */
793 /* Get Phy Pg 0 for each Phy. */
795 cfg
.pageAddr
= form
+ form_specific
;
796 cfg
.action
= MPI_CONFIG_ACTION_PAGE_HEADER
;
798 error
= mpt_config(ioc
, &cfg
);
802 if (!hdr
.ExtPageLength
) {
807 buffer
= pci_alloc_consistent(ioc
->pcidev
, hdr
.ExtPageLength
* 4,
814 cfg
.physAddr
= dma_handle
;
815 cfg
.action
= MPI_CONFIG_ACTION_PAGE_READ_CURRENT
;
817 error
= mpt_config(ioc
, &cfg
);
819 goto out_free_consistent
;
821 mptsas_print_phy_pg0(buffer
);
823 phy_info
->hw_link_rate
= buffer
->HwLinkRate
;
824 phy_info
->programmed_link_rate
= buffer
->ProgrammedLinkRate
;
825 phy_info
->identify
.handle
= le16_to_cpu(buffer
->OwnerDevHandle
);
826 phy_info
->attached
.handle
= le16_to_cpu(buffer
->AttachedDevHandle
);
829 pci_free_consistent(ioc
->pcidev
, hdr
.ExtPageLength
* 4,
836 mptsas_sas_device_pg0(MPT_ADAPTER
*ioc
, struct mptsas_devinfo
*device_info
,
837 u32 form
, u32 form_specific
)
839 ConfigExtendedPageHeader_t hdr
;
841 SasDevicePage0_t
*buffer
;
842 dma_addr_t dma_handle
;
846 hdr
.PageVersion
= MPI_SASDEVICE0_PAGEVERSION
;
847 hdr
.ExtPageLength
= 0;
851 hdr
.PageType
= MPI_CONFIG_PAGETYPE_EXTENDED
;
852 hdr
.ExtPageType
= MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE
;
854 cfg
.cfghdr
.ehdr
= &hdr
;
855 cfg
.pageAddr
= form
+ form_specific
;
857 cfg
.action
= MPI_CONFIG_ACTION_PAGE_HEADER
;
858 cfg
.dir
= 0; /* read */
861 memset(device_info
, 0, sizeof(struct mptsas_devinfo
));
862 error
= mpt_config(ioc
, &cfg
);
865 if (!hdr
.ExtPageLength
) {
870 buffer
= pci_alloc_consistent(ioc
->pcidev
, hdr
.ExtPageLength
* 4,
877 cfg
.physAddr
= dma_handle
;
878 cfg
.action
= MPI_CONFIG_ACTION_PAGE_READ_CURRENT
;
880 error
= mpt_config(ioc
, &cfg
);
882 goto out_free_consistent
;
884 mptsas_print_device_pg0(buffer
);
886 device_info
->handle
= le16_to_cpu(buffer
->DevHandle
);
887 device_info
->handle_parent
= le16_to_cpu(buffer
->ParentDevHandle
);
888 device_info
->handle_enclosure
=
889 le16_to_cpu(buffer
->EnclosureHandle
);
890 device_info
->slot
= le16_to_cpu(buffer
->Slot
);
891 device_info
->phy_id
= buffer
->PhyNum
;
892 device_info
->port_id
= buffer
->PhysicalPort
;
893 device_info
->id
= buffer
->TargetID
;
894 device_info
->channel
= buffer
->Bus
;
895 memcpy(&sas_address
, &buffer
->SASAddress
, sizeof(__le64
));
896 device_info
->sas_address
= le64_to_cpu(sas_address
);
897 device_info
->device_info
=
898 le32_to_cpu(buffer
->DeviceInfo
);
901 pci_free_consistent(ioc
->pcidev
, hdr
.ExtPageLength
* 4,
908 mptsas_sas_expander_pg0(MPT_ADAPTER
*ioc
, struct mptsas_portinfo
*port_info
,
909 u32 form
, u32 form_specific
)
911 ConfigExtendedPageHeader_t hdr
;
913 SasExpanderPage0_t
*buffer
;
914 dma_addr_t dma_handle
;
917 hdr
.PageVersion
= MPI_SASEXPANDER0_PAGEVERSION
;
918 hdr
.ExtPageLength
= 0;
922 hdr
.PageType
= MPI_CONFIG_PAGETYPE_EXTENDED
;
923 hdr
.ExtPageType
= MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER
;
925 cfg
.cfghdr
.ehdr
= &hdr
;
927 cfg
.pageAddr
= form
+ form_specific
;
928 cfg
.action
= MPI_CONFIG_ACTION_PAGE_HEADER
;
929 cfg
.dir
= 0; /* read */
932 memset(port_info
, 0, sizeof(struct mptsas_portinfo
));
933 error
= mpt_config(ioc
, &cfg
);
937 if (!hdr
.ExtPageLength
) {
942 buffer
= pci_alloc_consistent(ioc
->pcidev
, hdr
.ExtPageLength
* 4,
949 cfg
.physAddr
= dma_handle
;
950 cfg
.action
= MPI_CONFIG_ACTION_PAGE_READ_CURRENT
;
952 error
= mpt_config(ioc
, &cfg
);
954 goto out_free_consistent
;
956 /* save config data */
957 port_info
->num_phys
= buffer
->NumPhys
;
958 port_info
->handle
= le16_to_cpu(buffer
->DevHandle
);
959 port_info
->phy_info
= kcalloc(port_info
->num_phys
,
960 sizeof(struct mptsas_phyinfo
),GFP_KERNEL
);
961 if (!port_info
->phy_info
) {
963 goto out_free_consistent
;
967 pci_free_consistent(ioc
->pcidev
, hdr
.ExtPageLength
* 4,
974 mptsas_sas_expander_pg1(MPT_ADAPTER
*ioc
, struct mptsas_phyinfo
*phy_info
,
975 u32 form
, u32 form_specific
)
977 ConfigExtendedPageHeader_t hdr
;
979 SasExpanderPage1_t
*buffer
;
980 dma_addr_t dma_handle
;
983 hdr
.PageVersion
= MPI_SASEXPANDER0_PAGEVERSION
;
984 hdr
.ExtPageLength
= 0;
988 hdr
.PageType
= MPI_CONFIG_PAGETYPE_EXTENDED
;
989 hdr
.ExtPageType
= MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER
;
991 cfg
.cfghdr
.ehdr
= &hdr
;
993 cfg
.pageAddr
= form
+ form_specific
;
994 cfg
.action
= MPI_CONFIG_ACTION_PAGE_HEADER
;
995 cfg
.dir
= 0; /* read */
998 error
= mpt_config(ioc
, &cfg
);
1002 if (!hdr
.ExtPageLength
) {
1007 buffer
= pci_alloc_consistent(ioc
->pcidev
, hdr
.ExtPageLength
* 4,
1014 cfg
.physAddr
= dma_handle
;
1015 cfg
.action
= MPI_CONFIG_ACTION_PAGE_READ_CURRENT
;
1017 error
= mpt_config(ioc
, &cfg
);
1019 goto out_free_consistent
;
1022 mptsas_print_expander_pg1(buffer
);
1024 /* save config data */
1025 phy_info
->phy_id
= buffer
->PhyIdentifier
;
1026 phy_info
->port_id
= buffer
->PhysicalPort
;
1027 phy_info
->negotiated_link_rate
= buffer
->NegotiatedLinkRate
;
1028 phy_info
->programmed_link_rate
= buffer
->ProgrammedLinkRate
;
1029 phy_info
->hw_link_rate
= buffer
->HwLinkRate
;
1030 phy_info
->identify
.handle
= le16_to_cpu(buffer
->OwnerDevHandle
);
1031 phy_info
->attached
.handle
= le16_to_cpu(buffer
->AttachedDevHandle
);
1034 out_free_consistent
:
1035 pci_free_consistent(ioc
->pcidev
, hdr
.ExtPageLength
* 4,
1036 buffer
, dma_handle
);
1042 * Returns true if there is a scsi end device
1045 mptsas_is_end_device(struct mptsas_devinfo
* attached
)
1047 if ((attached
->handle
) &&
1048 (attached
->device_info
&
1049 MPI_SAS_DEVICE_INFO_END_DEVICE
) &&
1050 ((attached
->device_info
&
1051 MPI_SAS_DEVICE_INFO_SSP_TARGET
) |
1052 (attached
->device_info
&
1053 MPI_SAS_DEVICE_INFO_STP_TARGET
) |
1054 (attached
->device_info
&
1055 MPI_SAS_DEVICE_INFO_SATA_DEVICE
)))
1062 mptsas_parse_device_info(struct sas_identify
*identify
,
1063 struct mptsas_devinfo
*device_info
)
1067 identify
->sas_address
= device_info
->sas_address
;
1068 identify
->phy_identifier
= device_info
->phy_id
;
1071 * Fill in Phy Initiator Port Protocol.
1072 * Bits 6:3, more than one bit can be set, fall through cases.
1074 protocols
= device_info
->device_info
& 0x78;
1075 identify
->initiator_port_protocols
= 0;
1076 if (protocols
& MPI_SAS_DEVICE_INFO_SSP_INITIATOR
)
1077 identify
->initiator_port_protocols
|= SAS_PROTOCOL_SSP
;
1078 if (protocols
& MPI_SAS_DEVICE_INFO_STP_INITIATOR
)
1079 identify
->initiator_port_protocols
|= SAS_PROTOCOL_STP
;
1080 if (protocols
& MPI_SAS_DEVICE_INFO_SMP_INITIATOR
)
1081 identify
->initiator_port_protocols
|= SAS_PROTOCOL_SMP
;
1082 if (protocols
& MPI_SAS_DEVICE_INFO_SATA_HOST
)
1083 identify
->initiator_port_protocols
|= SAS_PROTOCOL_SATA
;
1086 * Fill in Phy Target Port Protocol.
1087 * Bits 10:7, more than one bit can be set, fall through cases.
1089 protocols
= device_info
->device_info
& 0x780;
1090 identify
->target_port_protocols
= 0;
1091 if (protocols
& MPI_SAS_DEVICE_INFO_SSP_TARGET
)
1092 identify
->target_port_protocols
|= SAS_PROTOCOL_SSP
;
1093 if (protocols
& MPI_SAS_DEVICE_INFO_STP_TARGET
)
1094 identify
->target_port_protocols
|= SAS_PROTOCOL_STP
;
1095 if (protocols
& MPI_SAS_DEVICE_INFO_SMP_TARGET
)
1096 identify
->target_port_protocols
|= SAS_PROTOCOL_SMP
;
1097 if (protocols
& MPI_SAS_DEVICE_INFO_SATA_DEVICE
)
1098 identify
->target_port_protocols
|= SAS_PROTOCOL_SATA
;
1101 * Fill in Attached device type.
1103 switch (device_info
->device_info
&
1104 MPI_SAS_DEVICE_INFO_MASK_DEVICE_TYPE
) {
1105 case MPI_SAS_DEVICE_INFO_NO_DEVICE
:
1106 identify
->device_type
= SAS_PHY_UNUSED
;
1108 case MPI_SAS_DEVICE_INFO_END_DEVICE
:
1109 identify
->device_type
= SAS_END_DEVICE
;
1111 case MPI_SAS_DEVICE_INFO_EDGE_EXPANDER
:
1112 identify
->device_type
= SAS_EDGE_EXPANDER_DEVICE
;
1114 case MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER
:
1115 identify
->device_type
= SAS_FANOUT_EXPANDER_DEVICE
;
1120 static int mptsas_probe_one_phy(struct device
*dev
,
1121 struct mptsas_phyinfo
*phy_info
, int index
, int local
)
1123 struct sas_phy
*phy
;
1126 phy
= sas_phy_alloc(dev
, index
);
1130 phy
->port_identifier
= phy_info
->port_id
;
1131 mptsas_parse_device_info(&phy
->identify
, &phy_info
->identify
);
1134 * Set Negotiated link rate.
1136 switch (phy_info
->negotiated_link_rate
) {
1137 case MPI_SAS_IOUNIT0_RATE_PHY_DISABLED
:
1138 phy
->negotiated_linkrate
= SAS_PHY_DISABLED
;
1140 case MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION
:
1141 phy
->negotiated_linkrate
= SAS_LINK_RATE_FAILED
;
1143 case MPI_SAS_IOUNIT0_RATE_1_5
:
1144 phy
->negotiated_linkrate
= SAS_LINK_RATE_1_5_GBPS
;
1146 case MPI_SAS_IOUNIT0_RATE_3_0
:
1147 phy
->negotiated_linkrate
= SAS_LINK_RATE_3_0_GBPS
;
1149 case MPI_SAS_IOUNIT0_RATE_SATA_OOB_COMPLETE
:
1150 case MPI_SAS_IOUNIT0_RATE_UNKNOWN
:
1152 phy
->negotiated_linkrate
= SAS_LINK_RATE_UNKNOWN
;
1157 * Set Max hardware link rate.
1159 switch (phy_info
->hw_link_rate
& MPI_SAS_PHY0_PRATE_MAX_RATE_MASK
) {
1160 case MPI_SAS_PHY0_HWRATE_MAX_RATE_1_5
:
1161 phy
->maximum_linkrate_hw
= SAS_LINK_RATE_1_5_GBPS
;
1163 case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0
:
1164 phy
->maximum_linkrate_hw
= SAS_LINK_RATE_3_0_GBPS
;
1171 * Set Max programmed link rate.
1173 switch (phy_info
->programmed_link_rate
&
1174 MPI_SAS_PHY0_PRATE_MAX_RATE_MASK
) {
1175 case MPI_SAS_PHY0_PRATE_MAX_RATE_1_5
:
1176 phy
->maximum_linkrate
= SAS_LINK_RATE_1_5_GBPS
;
1178 case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0
:
1179 phy
->maximum_linkrate
= SAS_LINK_RATE_3_0_GBPS
;
1186 * Set Min hardware link rate.
1188 switch (phy_info
->hw_link_rate
& MPI_SAS_PHY0_HWRATE_MIN_RATE_MASK
) {
1189 case MPI_SAS_PHY0_HWRATE_MIN_RATE_1_5
:
1190 phy
->minimum_linkrate_hw
= SAS_LINK_RATE_1_5_GBPS
;
1192 case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0
:
1193 phy
->minimum_linkrate_hw
= SAS_LINK_RATE_3_0_GBPS
;
1200 * Set Min programmed link rate.
1202 switch (phy_info
->programmed_link_rate
&
1203 MPI_SAS_PHY0_PRATE_MIN_RATE_MASK
) {
1204 case MPI_SAS_PHY0_PRATE_MIN_RATE_1_5
:
1205 phy
->minimum_linkrate
= SAS_LINK_RATE_1_5_GBPS
;
1207 case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0
:
1208 phy
->minimum_linkrate
= SAS_LINK_RATE_3_0_GBPS
;
1215 phy
->local_attached
= 1;
1217 error
= sas_phy_add(phy
);
1222 phy_info
->phy
= phy
;
1224 if (phy_info
->attached
.handle
) {
1225 struct sas_rphy
*rphy
;
1227 rphy
= sas_rphy_alloc(phy
);
1229 return 0; /* non-fatal: an rphy can be added later */
1231 mptsas_parse_device_info(&rphy
->identify
, &phy_info
->attached
);
1232 error
= sas_rphy_add(rphy
);
1234 sas_rphy_free(rphy
);
1238 phy_info
->rphy
= rphy
;
1245 mptsas_probe_hba_phys(MPT_ADAPTER
*ioc
, int *index
)
1247 struct mptsas_portinfo
*port_info
;
1248 u32 handle
= 0xFFFF;
1249 int error
= -ENOMEM
, i
;
1251 port_info
= kzalloc(sizeof(*port_info
), GFP_KERNEL
);
1255 error
= mptsas_sas_io_unit_pg0(ioc
, port_info
);
1257 goto out_free_port_info
;
1259 ioc
->num_ports
= port_info
->num_phys
;
1260 mutex_lock(&ioc
->sas_topology_mutex
);
1261 list_add_tail(&port_info
->list
, &ioc
->sas_topology
);
1262 mutex_unlock(&ioc
->sas_topology_mutex
);
1264 for (i
= 0; i
< port_info
->num_phys
; i
++) {
1265 mptsas_sas_phy_pg0(ioc
, &port_info
->phy_info
[i
],
1266 (MPI_SAS_PHY_PGAD_FORM_PHY_NUMBER
<<
1267 MPI_SAS_PHY_PGAD_FORM_SHIFT
), i
);
1269 mptsas_sas_device_pg0(ioc
, &port_info
->phy_info
[i
].identify
,
1270 (MPI_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE
<<
1271 MPI_SAS_DEVICE_PGAD_FORM_SHIFT
), handle
);
1272 port_info
->phy_info
[i
].identify
.phy_id
=
1273 port_info
->phy_info
[i
].phy_id
;
1274 handle
= port_info
->phy_info
[i
].identify
.handle
;
1276 if (port_info
->phy_info
[i
].attached
.handle
) {
1277 mptsas_sas_device_pg0(ioc
,
1278 &port_info
->phy_info
[i
].attached
,
1279 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE
<<
1280 MPI_SAS_DEVICE_PGAD_FORM_SHIFT
),
1281 port_info
->phy_info
[i
].attached
.handle
);
1284 mptsas_probe_one_phy(&ioc
->sh
->shost_gendev
,
1285 &port_info
->phy_info
[i
], *index
, 1);
1298 mptsas_probe_expander_phys(MPT_ADAPTER
*ioc
, u32
*handle
, int *index
)
1300 struct mptsas_portinfo
*port_info
, *p
;
1301 int error
= -ENOMEM
, i
, j
;
1303 port_info
= kzalloc(sizeof(*port_info
), GFP_KERNEL
);
1307 error
= mptsas_sas_expander_pg0(ioc
, port_info
,
1308 (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE
<<
1309 MPI_SAS_EXPAND_PGAD_FORM_SHIFT
), *handle
);
1311 goto out_free_port_info
;
1313 *handle
= port_info
->handle
;
1315 mutex_lock(&ioc
->sas_topology_mutex
);
1316 list_add_tail(&port_info
->list
, &ioc
->sas_topology
);
1317 mutex_unlock(&ioc
->sas_topology_mutex
);
1319 for (i
= 0; i
< port_info
->num_phys
; i
++) {
1320 struct device
*parent
;
1322 mptsas_sas_expander_pg1(ioc
, &port_info
->phy_info
[i
],
1323 (MPI_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM
<<
1324 MPI_SAS_EXPAND_PGAD_FORM_SHIFT
), (i
<< 16) + *handle
);
1326 if (port_info
->phy_info
[i
].identify
.handle
) {
1327 mptsas_sas_device_pg0(ioc
,
1328 &port_info
->phy_info
[i
].identify
,
1329 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE
<<
1330 MPI_SAS_DEVICE_PGAD_FORM_SHIFT
),
1331 port_info
->phy_info
[i
].identify
.handle
);
1332 port_info
->phy_info
[i
].identify
.phy_id
=
1333 port_info
->phy_info
[i
].phy_id
;
1336 if (port_info
->phy_info
[i
].attached
.handle
) {
1337 mptsas_sas_device_pg0(ioc
,
1338 &port_info
->phy_info
[i
].attached
,
1339 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE
<<
1340 MPI_SAS_DEVICE_PGAD_FORM_SHIFT
),
1341 port_info
->phy_info
[i
].attached
.handle
);
1342 port_info
->phy_info
[i
].attached
.phy_id
=
1343 port_info
->phy_info
[i
].phy_id
;
1347 * If we find a parent port handle this expander is
1348 * attached to another expander, else it hangs of the
1351 parent
= &ioc
->sh
->shost_gendev
;
1352 mutex_lock(&ioc
->sas_topology_mutex
);
1353 list_for_each_entry(p
, &ioc
->sas_topology
, list
) {
1354 for (j
= 0; j
< p
->num_phys
; j
++) {
1355 if (port_info
->phy_info
[i
].identify
.handle
==
1356 p
->phy_info
[j
].attached
.handle
)
1357 parent
= &p
->phy_info
[j
].rphy
->dev
;
1360 mutex_unlock(&ioc
->sas_topology_mutex
);
1362 mptsas_probe_one_phy(parent
, &port_info
->phy_info
[i
],
1370 kfree(port_info
->phy_info
);
1377 mptsas_scan_sas_topology(MPT_ADAPTER
*ioc
)
1379 u32 handle
= 0xFFFF;
1382 mptsas_probe_hba_phys(ioc
, &index
);
1383 while (!mptsas_probe_expander_phys(ioc
, &handle
, &index
))
1387 static struct mptsas_phyinfo
*
1388 mptsas_find_phyinfo_by_parent(MPT_ADAPTER
*ioc
, u16 parent_handle
, u8 phy_id
)
1390 struct mptsas_portinfo
*port_info
;
1391 struct mptsas_devinfo device_info
;
1392 struct mptsas_phyinfo
*phy_info
= NULL
;
1396 * Retrieve the parent sas_address
1398 error
= mptsas_sas_device_pg0(ioc
, &device_info
,
1399 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE
<<
1400 MPI_SAS_DEVICE_PGAD_FORM_SHIFT
),
1403 printk("mptsas: failed to retrieve device page\n");
1408 * The phy_info structures are never deallocated during lifetime of
1409 * a host, so the code below is safe without additional refcounting.
1411 mutex_lock(&ioc
->sas_topology_mutex
);
1412 list_for_each_entry(port_info
, &ioc
->sas_topology
, list
) {
1413 for (i
= 0; i
< port_info
->num_phys
; i
++) {
1414 if (port_info
->phy_info
[i
].identify
.sas_address
==
1415 device_info
.sas_address
&&
1416 port_info
->phy_info
[i
].phy_id
== phy_id
) {
1417 phy_info
= &port_info
->phy_info
[i
];
1422 mutex_unlock(&ioc
->sas_topology_mutex
);
1427 static struct mptsas_phyinfo
*
1428 mptsas_find_phyinfo_by_target(MPT_ADAPTER
*ioc
, u32 id
)
1430 struct mptsas_portinfo
*port_info
;
1431 struct mptsas_phyinfo
*phy_info
= NULL
;
1435 * The phy_info structures are never deallocated during lifetime of
1436 * a host, so the code below is safe without additional refcounting.
1438 mutex_lock(&ioc
->sas_topology_mutex
);
1439 list_for_each_entry(port_info
, &ioc
->sas_topology
, list
) {
1440 for (i
= 0; i
< port_info
->num_phys
; i
++)
1441 if (mptsas_is_end_device(&port_info
->phy_info
[i
].attached
))
1442 if (port_info
->phy_info
[i
].attached
.id
== id
) {
1443 phy_info
= &port_info
->phy_info
[i
];
1447 mutex_unlock(&ioc
->sas_topology_mutex
);
1453 * Work queue thread to clear the persitency table
1456 mptscsih_sas_persist_clear_table(void * arg
)
1458 MPT_ADAPTER
*ioc
= (MPT_ADAPTER
*)arg
;
1460 mptbase_sas_persist_operation(ioc
, MPI_SAS_OP_CLEAR_NOT_PRESENT
);
1464 mptsas_hotplug_work(void *arg
)
1466 struct mptsas_hotplug_event
*ev
= arg
;
1467 MPT_ADAPTER
*ioc
= ev
->ioc
;
1468 struct mptsas_phyinfo
*phy_info
;
1469 struct sas_rphy
*rphy
;
1470 struct scsi_device
*sdev
;
1472 struct mptsas_devinfo sas_device
;
1474 switch (ev
->event_type
) {
1475 case MPTSAS_DEL_DEVICE
:
1477 phy_info
= mptsas_find_phyinfo_by_target(ioc
, ev
->id
);
1479 printk("mptsas: remove event for non-existant PHY.\n");
1483 if (phy_info
->attached
.device_info
& MPI_SAS_DEVICE_INFO_SSP_TARGET
)
1485 if (phy_info
->attached
.device_info
& MPI_SAS_DEVICE_INFO_STP_TARGET
)
1487 if (phy_info
->attached
.device_info
& MPI_SAS_DEVICE_INFO_SATA_DEVICE
)
1490 printk(MYIOC_s_INFO_FMT
1491 "removing %s device, channel %d, id %d, phy %d\n",
1492 ioc
->name
, ds
, ev
->channel
, ev
->id
, phy_info
->phy_id
);
1494 if (phy_info
->rphy
) {
1495 sas_rphy_delete(phy_info
->rphy
);
1496 memset(&phy_info
->attached
, 0, sizeof(struct mptsas_devinfo
));
1497 phy_info
->rphy
= NULL
;
1500 case MPTSAS_ADD_DEVICE
:
1503 * Refresh sas device pg0 data
1505 if (mptsas_sas_device_pg0(ioc
, &sas_device
,
1506 (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID
<<
1507 MPI_SAS_DEVICE_PGAD_FORM_SHIFT
), ev
->id
))
1510 phy_info
= mptsas_find_phyinfo_by_parent(ioc
,
1511 sas_device
.handle_parent
, sas_device
.phy_id
);
1513 printk("mptsas: add event for non-existant PHY.\n");
1517 if (phy_info
->rphy
) {
1518 printk("mptsas: trying to add existing device.\n");
1522 memcpy(&phy_info
->attached
, &sas_device
,
1523 sizeof(struct mptsas_devinfo
));
1525 if (phy_info
->attached
.device_info
& MPI_SAS_DEVICE_INFO_SSP_TARGET
)
1527 if (phy_info
->attached
.device_info
& MPI_SAS_DEVICE_INFO_STP_TARGET
)
1529 if (phy_info
->attached
.device_info
& MPI_SAS_DEVICE_INFO_SATA_DEVICE
)
1532 printk(MYIOC_s_INFO_FMT
1533 "attaching %s device, channel %d, id %d, phy %d\n",
1534 ioc
->name
, ds
, ev
->channel
, ev
->id
, ev
->phy_id
);
1537 rphy
= sas_rphy_alloc(phy_info
->phy
);
1539 break; /* non-fatal: an rphy can be added later */
1541 mptsas_parse_device_info(&rphy
->identify
, &phy_info
->attached
);
1542 if (sas_rphy_add(rphy
)) {
1543 sas_rphy_free(rphy
);
1547 phy_info
->rphy
= rphy
;
1549 case MPTSAS_ADD_RAID
:
1550 sdev
= scsi_device_lookup(
1556 scsi_device_put(sdev
);
1559 printk(MYIOC_s_INFO_FMT
1560 "attaching raid volume, channel %d, id %d\n",
1561 ioc
->name
, ioc
->num_ports
, ev
->id
);
1562 scsi_add_device(ioc
->sh
,
1566 mpt_findImVolumes(ioc
);
1568 case MPTSAS_DEL_RAID
:
1569 sdev
= scsi_device_lookup(
1576 printk(MYIOC_s_INFO_FMT
1577 "removing raid volume, channel %d, id %d\n",
1578 ioc
->name
, ioc
->num_ports
, ev
->id
);
1579 scsi_remove_device(sdev
);
1580 scsi_device_put(sdev
);
1581 mpt_findImVolumes(ioc
);
1589 mptscsih_send_sas_event(MPT_ADAPTER
*ioc
,
1590 EVENT_DATA_SAS_DEVICE_STATUS_CHANGE
*sas_event_data
)
1592 struct mptsas_hotplug_event
*ev
;
1593 u32 device_info
= le32_to_cpu(sas_event_data
->DeviceInfo
);
1597 (MPI_SAS_DEVICE_INFO_SSP_TARGET
|
1598 MPI_SAS_DEVICE_INFO_STP_TARGET
|
1599 MPI_SAS_DEVICE_INFO_SATA_DEVICE
)) == 0)
1602 switch (sas_event_data
->ReasonCode
) {
1603 case MPI_EVENT_SAS_DEV_STAT_RC_ADDED
:
1604 case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING
:
1605 ev
= kmalloc(sizeof(*ev
), GFP_ATOMIC
);
1607 printk(KERN_WARNING
"mptsas: lost hotplug event\n");
1611 INIT_WORK(&ev
->work
, mptsas_hotplug_work
, ev
);
1613 ev
->handle
= le16_to_cpu(sas_event_data
->DevHandle
);
1615 le16_to_cpu(sas_event_data
->ParentDevHandle
);
1616 ev
->channel
= sas_event_data
->Bus
;
1617 ev
->id
= sas_event_data
->TargetID
;
1618 ev
->phy_id
= sas_event_data
->PhyNum
;
1619 memcpy(&sas_address
, &sas_event_data
->SASAddress
,
1621 ev
->sas_address
= le64_to_cpu(sas_address
);
1622 ev
->device_info
= device_info
;
1624 if (sas_event_data
->ReasonCode
&
1625 MPI_EVENT_SAS_DEV_STAT_RC_ADDED
)
1626 ev
->event_type
= MPTSAS_ADD_DEVICE
;
1628 ev
->event_type
= MPTSAS_DEL_DEVICE
;
1629 schedule_work(&ev
->work
);
1631 case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED
:
1633 * Persistent table is full.
1635 INIT_WORK(&ioc
->mptscsih_persistTask
,
1636 mptscsih_sas_persist_clear_table
,
1638 schedule_work(&ioc
->mptscsih_persistTask
);
1640 case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA
:
1642 case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET
:
1650 mptscsih_send_raid_event(MPT_ADAPTER
*ioc
,
1651 EVENT_DATA_RAID
*raid_event_data
)
1653 struct mptsas_hotplug_event
*ev
;
1654 RAID_VOL0_STATUS
* volumeStatus
;
1656 if (ioc
->bus_type
!= SAS
)
1659 ev
= kmalloc(sizeof(*ev
), GFP_ATOMIC
);
1661 printk(KERN_WARNING
"mptsas: lost hotplug event\n");
1665 memset(ev
,0,sizeof(struct mptsas_hotplug_event
));
1666 INIT_WORK(&ev
->work
, mptsas_hotplug_work
, ev
);
1668 ev
->id
= raid_event_data
->VolumeID
;
1670 switch (raid_event_data
->ReasonCode
) {
1671 case MPI_EVENT_RAID_RC_PHYSDISK_DELETED
:
1672 ev
->event_type
= MPTSAS_ADD_DEVICE
;
1674 case MPI_EVENT_RAID_RC_PHYSDISK_CREATED
:
1675 ev
->event_type
= MPTSAS_DEL_DEVICE
;
1677 case MPI_EVENT_RAID_RC_VOLUME_DELETED
:
1678 ev
->event_type
= MPTSAS_DEL_RAID
;
1680 case MPI_EVENT_RAID_RC_VOLUME_CREATED
:
1681 ev
->event_type
= MPTSAS_ADD_RAID
;
1683 case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED
:
1684 volumeStatus
= (RAID_VOL0_STATUS
*) &
1685 raid_event_data
->SettingsStatus
;
1686 ev
->event_type
= (volumeStatus
->State
==
1687 MPI_RAIDVOL0_STATUS_STATE_FAILED
) ?
1688 MPTSAS_DEL_RAID
: MPTSAS_ADD_RAID
;
1693 schedule_work(&ev
->work
);
1697 mptsas_event_process(MPT_ADAPTER
*ioc
, EventNotificationReply_t
*reply
)
1700 u8 event
= le32_to_cpu(reply
->Event
) & 0xFF;
1706 case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE
:
1707 mptscsih_send_sas_event(ioc
,
1708 (EVENT_DATA_SAS_DEVICE_STATUS_CHANGE
*)reply
->Data
);
1710 case MPI_EVENT_INTEGRATED_RAID
:
1711 mptscsih_send_raid_event(ioc
,
1712 (EVENT_DATA_RAID
*)reply
->Data
);
1714 case MPI_EVENT_PERSISTENT_TABLE_FULL
:
1715 INIT_WORK(&ioc
->mptscsih_persistTask
,
1716 mptscsih_sas_persist_clear_table
,
1718 schedule_work(&ioc
->mptscsih_persistTask
);
1720 case MPI_EVENT_SAS_DISCOVERY
:
1722 rc
= mptscsih_event_process(ioc
, reply
);
1731 mptsas_probe(struct pci_dev
*pdev
, const struct pci_device_id
*id
)
1733 struct Scsi_Host
*sh
;
1736 unsigned long flags
;
1744 r
= mpt_attach(pdev
,id
);
1748 ioc
= pci_get_drvdata(pdev
);
1749 ioc
->DoneCtx
= mptsasDoneCtx
;
1750 ioc
->TaskCtx
= mptsasTaskCtx
;
1751 ioc
->InternalCtx
= mptsasInternalCtx
;
1753 /* Added sanity check on readiness of the MPT adapter.
1755 if (ioc
->last_state
!= MPI_IOC_STATE_OPERATIONAL
) {
1756 printk(MYIOC_s_WARN_FMT
1757 "Skipping because it's not operational!\n",
1760 goto out_mptsas_probe
;
1764 printk(MYIOC_s_WARN_FMT
"Skipping because it's disabled!\n",
1767 goto out_mptsas_probe
;
1770 /* Sanity check - ensure at least 1 port is INITIATOR capable
1773 for (ii
= 0; ii
< ioc
->facts
.NumberOfPorts
; ii
++) {
1774 if (ioc
->pfacts
[ii
].ProtocolFlags
&
1775 MPI_PORTFACTS_PROTOCOL_INITIATOR
)
1780 printk(MYIOC_s_WARN_FMT
1781 "Skipping ioc=%p because SCSI Initiator mode "
1782 "is NOT enabled!\n", ioc
->name
, ioc
);
1786 sh
= scsi_host_alloc(&mptsas_driver_template
, sizeof(MPT_SCSI_HOST
));
1788 printk(MYIOC_s_WARN_FMT
1789 "Unable to register controller with SCSI subsystem\n",
1792 goto out_mptsas_probe
;
1795 spin_lock_irqsave(&ioc
->FreeQlock
, flags
);
1797 /* Attach the SCSI Host to the IOC structure
1805 /* set 16 byte cdb's */
1806 sh
->max_cmd_len
= 16;
1808 sh
->max_id
= ioc
->pfacts
->MaxDevices
+ 1;
1810 sh
->transportt
= mptsas_transport_template
;
1812 sh
->max_lun
= MPT_LAST_LUN
+ 1;
1813 sh
->max_channel
= 0;
1814 sh
->this_id
= ioc
->pfacts
[0].PortSCSIID
;
1818 sh
->unique_id
= ioc
->id
;
1820 INIT_LIST_HEAD(&ioc
->sas_topology
);
1821 mutex_init(&ioc
->sas_topology_mutex
);
1823 mutex_init(&ioc
->sas_mgmt
.mutex
);
1824 init_completion(&ioc
->sas_mgmt
.done
);
1826 /* Verify that we won't exceed the maximum
1827 * number of chain buffers
1828 * We can optimize: ZZ = req_sz/sizeof(SGE)
1830 * numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
1831 * + (req_sz - 64)/sizeof(SGE)
1832 * A slightly different algorithm is required for
1835 scale
= ioc
->req_sz
/(sizeof(dma_addr_t
) + sizeof(u32
));
1836 if (sizeof(dma_addr_t
) == sizeof(u64
)) {
1837 numSGE
= (scale
- 1) *
1838 (ioc
->facts
.MaxChainDepth
-1) + scale
+
1839 (ioc
->req_sz
- 60) / (sizeof(dma_addr_t
) +
1842 numSGE
= 1 + (scale
- 1) *
1843 (ioc
->facts
.MaxChainDepth
-1) + scale
+
1844 (ioc
->req_sz
- 64) / (sizeof(dma_addr_t
) +
1848 if (numSGE
< sh
->sg_tablesize
) {
1849 /* Reset this value */
1850 dprintk((MYIOC_s_INFO_FMT
1851 "Resetting sg_tablesize to %d from %d\n",
1852 ioc
->name
, numSGE
, sh
->sg_tablesize
));
1853 sh
->sg_tablesize
= numSGE
;
1856 spin_unlock_irqrestore(&ioc
->FreeQlock
, flags
);
1858 hd
= (MPT_SCSI_HOST
*) sh
->hostdata
;
1861 /* SCSI needs scsi_cmnd lookup table!
1862 * (with size equal to req_depth*PtrSz!)
1864 hd
->ScsiLookup
= kcalloc(ioc
->req_depth
, sizeof(void *), GFP_ATOMIC
);
1865 if (!hd
->ScsiLookup
) {
1867 goto out_mptsas_probe
;
1870 dprintk((MYIOC_s_INFO_FMT
"ScsiLookup @ %p\n",
1871 ioc
->name
, hd
->ScsiLookup
));
1873 /* Allocate memory for the device structures.
1874 * A non-Null pointer at an offset
1875 * indicates a device exists.
1876 * max_id = 1 + maximum id (hosts.h)
1878 hd
->Targets
= kcalloc(sh
->max_id
, sizeof(void *), GFP_ATOMIC
);
1881 goto out_mptsas_probe
;
1884 dprintk((KERN_INFO
" vtarget @ %p\n", hd
->Targets
));
1886 /* Clear the TM flags
1889 hd
->tmState
= TM_STATE_NONE
;
1890 hd
->resetPending
= 0;
1891 hd
->abortSCpnt
= NULL
;
1893 /* Clear the pointer used to store
1894 * single-threaded commands, i.e., those
1895 * issued during a bus scan, dv and
1896 * configuration pages.
1900 /* Initialize this SCSI Hosts' timers
1901 * To use, set the timer expires field
1904 init_timer(&hd
->timer
);
1905 hd
->timer
.data
= (unsigned long) hd
;
1906 hd
->timer
.function
= mptscsih_timer_expired
;
1908 hd
->mpt_pq_filter
= mpt_pq_filter
;
1909 ioc
->sas_data
.ptClear
= mpt_pt_clear
;
1911 if (ioc
->sas_data
.ptClear
==1) {
1912 mptbase_sas_persist_operation(
1913 ioc
, MPI_SAS_OP_CLEAR_ALL_PERSISTENT
);
1916 ddvprintk((MYIOC_s_INFO_FMT
1917 "mpt_pq_filter %x mpt_pq_filter %x\n",
1922 init_waitqueue_head(&hd
->scandv_waitq
);
1923 hd
->scandv_wait_done
= 0;
1924 hd
->last_queue_full
= 0;
1926 error
= scsi_add_host(sh
, &ioc
->pcidev
->dev
);
1928 dprintk((KERN_ERR MYNAM
1929 "scsi_add_host failed\n"));
1930 goto out_mptsas_probe
;
1933 mptsas_scan_sas_topology(ioc
);
1936 Reporting RAID volumes.
1938 if (!ioc
->raid_data
.pIocPg2
)
1940 if (!ioc
->raid_data
.pIocPg2
->NumActiveVolumes
)
1942 for (ii
=0;ii
<ioc
->raid_data
.pIocPg2
->NumActiveVolumes
;ii
++) {
1945 ioc
->raid_data
.pIocPg2
->RaidVolume
[ii
].VolumeID
,
1953 mptscsih_remove(pdev
);
1957 static void __devexit
mptsas_remove(struct pci_dev
*pdev
)
1959 MPT_ADAPTER
*ioc
= pci_get_drvdata(pdev
);
1960 struct mptsas_portinfo
*p
, *n
;
1962 sas_remove_host(ioc
->sh
);
1964 mutex_lock(&ioc
->sas_topology_mutex
);
1965 list_for_each_entry_safe(p
, n
, &ioc
->sas_topology
, list
) {
1971 mutex_unlock(&ioc
->sas_topology_mutex
);
1973 mptscsih_remove(pdev
);
1976 static struct pci_device_id mptsas_pci_table
[] = {
1977 { PCI_VENDOR_ID_LSI_LOGIC
, PCI_DEVICE_ID_LSI_SAS1064
,
1978 PCI_ANY_ID
, PCI_ANY_ID
},
1979 { PCI_VENDOR_ID_LSI_LOGIC
, PCI_DEVICE_ID_LSI_SAS1066
,
1980 PCI_ANY_ID
, PCI_ANY_ID
},
1981 { PCI_VENDOR_ID_LSI_LOGIC
, PCI_DEVICE_ID_LSI_SAS1068
,
1982 PCI_ANY_ID
, PCI_ANY_ID
},
1983 { PCI_VENDOR_ID_LSI_LOGIC
, PCI_DEVICE_ID_LSI_SAS1064E
,
1984 PCI_ANY_ID
, PCI_ANY_ID
},
1985 { PCI_VENDOR_ID_LSI_LOGIC
, PCI_DEVICE_ID_LSI_SAS1066E
,
1986 PCI_ANY_ID
, PCI_ANY_ID
},
1987 { PCI_VENDOR_ID_LSI_LOGIC
, PCI_DEVICE_ID_LSI_SAS1068E
,
1988 PCI_ANY_ID
, PCI_ANY_ID
},
1989 {0} /* Terminating entry */
1991 MODULE_DEVICE_TABLE(pci
, mptsas_pci_table
);
1994 static struct pci_driver mptsas_driver
= {
1996 .id_table
= mptsas_pci_table
,
1997 .probe
= mptsas_probe
,
1998 .remove
= __devexit_p(mptsas_remove
),
1999 .shutdown
= mptscsih_shutdown
,
2001 .suspend
= mptscsih_suspend
,
2002 .resume
= mptscsih_resume
,
2009 show_mptmod_ver(my_NAME
, my_VERSION
);
2011 mptsas_transport_template
=
2012 sas_attach_transport(&mptsas_transport_functions
);
2013 if (!mptsas_transport_template
)
2016 mptsasDoneCtx
= mpt_register(mptscsih_io_done
, MPTSAS_DRIVER
);
2017 mptsasTaskCtx
= mpt_register(mptscsih_taskmgmt_complete
, MPTSAS_DRIVER
);
2019 mpt_register(mptscsih_scandv_complete
, MPTSAS_DRIVER
);
2020 mptsasMgmtCtx
= mpt_register(mptsas_mgmt_done
, MPTSAS_DRIVER
);
2022 if (mpt_event_register(mptsasDoneCtx
, mptsas_event_process
) == 0) {
2023 devtverboseprintk((KERN_INFO MYNAM
2024 ": Registered for IOC event notifications\n"));
2027 if (mpt_reset_register(mptsasDoneCtx
, mptscsih_ioc_reset
) == 0) {
2028 dprintk((KERN_INFO MYNAM
2029 ": Registered for IOC reset notifications\n"));
2032 return pci_register_driver(&mptsas_driver
);
2038 pci_unregister_driver(&mptsas_driver
);
2039 sas_release_transport(mptsas_transport_template
);
2041 mpt_reset_deregister(mptsasDoneCtx
);
2042 mpt_event_deregister(mptsasDoneCtx
);
2044 mpt_deregister(mptsasMgmtCtx
);
2045 mpt_deregister(mptsasInternalCtx
);
2046 mpt_deregister(mptsasTaskCtx
);
2047 mpt_deregister(mptsasDoneCtx
);
2050 module_init(mptsas_init
);
2051 module_exit(mptsas_exit
);