blob: 7de19a84dc745dd2ea4199ffef4f17f79397d65a [file] [log] [blame]
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001/*
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)
8 * Copyright (c) 2005 Dell
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>
53
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>
58
59#include "mptbase.h"
60#include "mptscsih.h"
61
62
63#define my_NAME "Fusion MPT SAS Host driver"
64#define my_VERSION MPT_LINUX_VERSION_COMMON
65#define MYNAM "mptsas"
66
67MODULE_AUTHOR(MODULEAUTHOR);
68MODULE_DESCRIPTION(my_NAME);
69MODULE_LICENSE("GPL");
70
71static int mpt_pq_filter;
72module_param(mpt_pq_filter, int, 0);
73MODULE_PARM_DESC(mpt_pq_filter,
74 "Enable peripheral qualifier filter: enable=1 "
75 "(default=0)");
76
77static int mpt_pt_clear;
78module_param(mpt_pt_clear, int, 0);
79MODULE_PARM_DESC(mpt_pt_clear,
80 "Clear persistency table: enable=1 "
81 "(default=MPTSCSIH_PT_CLEAR=0)");
82
83static int mptsasDoneCtx = -1;
84static int mptsasTaskCtx = -1;
85static int mptsasInternalCtx = -1; /* Used only for internal commands */
86
87
88/*
89 * SAS topology structures
90 *
91 * The MPT Fusion firmware interface spreads information about the
92 * SAS topology over many manufacture pages, thus we need some data
93 * structure to collect it and process it for the SAS transport class.
94 */
95
96struct mptsas_devinfo {
97 u16 handle; /* unique id to address this device */
98 u8 phy_id; /* phy number of parent device */
99 u8 port_id; /* sas physical port this device
100 is assoc'd with */
101 u8 target; /* logical target id of this device */
102 u8 bus; /* logical bus number of this device */
103 u64 sas_address; /* WWN of this device,
104 SATA is assigned by HBA,expander */
105 u32 device_info; /* bitfield detailed info about this device */
106};
107
108struct mptsas_phyinfo {
109 u8 phy_id; /* phy index */
110 u8 port_id; /* port number this phy is part of */
111 u8 negotiated_link_rate; /* nego'd link rate for this phy */
112 u8 hw_link_rate; /* hardware max/min phys link rate */
113 u8 programmed_link_rate; /* programmed max/min phy link rate */
114 struct mptsas_devinfo identify; /* point to phy device info */
115 struct mptsas_devinfo attached; /* point to attached device info */
116 struct sas_rphy *rphy;
117};
118
119struct mptsas_portinfo {
120 struct list_head list;
121 u16 handle; /* unique id to address this */
122 u8 num_phys; /* number of phys */
123 struct mptsas_phyinfo *phy_info;
124};
125
126/*
127 * This is pretty ugly. We will be able to seriously clean it up
128 * once the DV code in mptscsih goes away and we can properly
129 * implement ->target_alloc.
130 */
131static int
132mptsas_slave_alloc(struct scsi_device *device)
133{
134 struct Scsi_Host *host = device->host;
135 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
136 struct sas_rphy *rphy;
137 struct mptsas_portinfo *p;
138 VirtDevice *vdev;
139 uint target = device->id;
140 int i;
141
142 if ((vdev = hd->Targets[target]) != NULL)
143 goto out;
144
145 vdev = kmalloc(sizeof(VirtDevice), GFP_KERNEL);
146 if (!vdev) {
147 printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",
148 hd->ioc->name, sizeof(VirtDevice));
149 return -ENOMEM;
150 }
151
152 memset(vdev, 0, sizeof(VirtDevice));
153 vdev->tflags = MPT_TARGET_FLAGS_Q_YES|MPT_TARGET_FLAGS_VALID_INQUIRY;
154 vdev->ioc_id = hd->ioc->id;
155
156 rphy = dev_to_rphy(device->sdev_target->dev.parent);
157 list_for_each_entry(p, &hd->ioc->sas_topology, list) {
158 for (i = 0; i < p->num_phys; i++) {
159 if (p->phy_info[i].attached.sas_address ==
160 rphy->identify.sas_address) {
161 vdev->target_id =
162 p->phy_info[i].attached.target;
163 vdev->bus_id = p->phy_info[i].attached.bus;
164 hd->Targets[device->id] = vdev;
165 goto out;
166 }
167 }
168 }
169
170 printk("No matching SAS device found!!\n");
171 kfree(vdev);
172 return -ENODEV;
173
174 out:
175 vdev->num_luns++;
176 device->hostdata = vdev;
177 return 0;
178}
179
180static struct scsi_host_template mptsas_driver_template = {
181 .proc_name = "mptsas",
182 .proc_info = mptscsih_proc_info,
183 .name = "MPT SPI Host",
184 .info = mptscsih_info,
185 .queuecommand = mptscsih_qcmd,
186 .slave_alloc = mptsas_slave_alloc,
187 .slave_configure = mptscsih_slave_configure,
188 .slave_destroy = mptscsih_slave_destroy,
189 .change_queue_depth = mptscsih_change_queue_depth,
190 .eh_abort_handler = mptscsih_abort,
191 .eh_device_reset_handler = mptscsih_dev_reset,
192 .eh_bus_reset_handler = mptscsih_bus_reset,
193 .eh_host_reset_handler = mptscsih_host_reset,
194 .bios_param = mptscsih_bios_param,
195 .can_queue = MPT_FC_CAN_QUEUE,
196 .this_id = -1,
197 .sg_tablesize = MPT_SCSI_SG_DEPTH,
198 .max_sectors = 8192,
199 .cmd_per_lun = 7,
200 .use_clustering = ENABLE_CLUSTERING,
201};
202
203static struct sas_function_template mptsas_transport_functions = {
204};
205
206static struct scsi_transport_template *mptsas_transport_template;
207
208#ifdef SASDEBUG
209static void mptsas_print_phy_data(MPI_SAS_IO_UNIT0_PHY_DATA *phy_data)
210{
211 printk("---- IO UNIT PAGE 0 ------------\n");
212 printk("Handle=0x%X\n",
213 le16_to_cpu(phy_data->AttachedDeviceHandle));
214 printk("Controller Handle=0x%X\n",
215 le16_to_cpu(phy_data->ControllerDevHandle));
216 printk("Port=0x%X\n", phy_data->Port);
217 printk("Port Flags=0x%X\n", phy_data->PortFlags);
218 printk("PHY Flags=0x%X\n", phy_data->PhyFlags);
219 printk("Negotiated Link Rate=0x%X\n", phy_data->NegotiatedLinkRate);
220 printk("Controller PHY Device Info=0x%X\n",
221 le32_to_cpu(phy_data->ControllerPhyDeviceInfo));
222 printk("DiscoveryStatus=0x%X\n",
223 le32_to_cpu(phy_data->DiscoveryStatus));
224 printk("\n");
225}
226
227static void mptsas_print_phy_pg0(SasPhyPage0_t *pg0)
228{
229 __le64 sas_address;
230
231 memcpy(&sas_address, &pg0->SASAddress, sizeof(__le64));
232
233 printk("---- SAS PHY PAGE 0 ------------\n");
234 printk("Attached Device Handle=0x%X\n",
235 le16_to_cpu(pg0->AttachedDevHandle));
236 printk("SAS Address=0x%llX\n",
237 (unsigned long long)le64_to_cpu(sas_address));
238 printk("Attached PHY Identifier=0x%X\n", pg0->AttachedPhyIdentifier);
239 printk("Attached Device Info=0x%X\n",
240 le32_to_cpu(pg0->AttachedDeviceInfo));
241 printk("Programmed Link Rate=0x%X\n", pg0->ProgrammedLinkRate);
242 printk("Change Count=0x%X\n", pg0->ChangeCount);
243 printk("PHY Info=0x%X\n", le32_to_cpu(pg0->PhyInfo));
244 printk("\n");
245}
246
247static void mptsas_print_device_pg0(SasDevicePage0_t *pg0)
248{
249 __le64 sas_address;
250
251 memcpy(&sas_address, &pg0->SASAddress, sizeof(__le64));
252
253 printk("---- SAS DEVICE PAGE 0 ---------\n");
254 printk("Handle=0x%X\n" ,le16_to_cpu(pg0->DevHandle));
255 printk("Enclosure Handle=0x%X\n", le16_to_cpu(pg0->EnclosureHandle));
256 printk("Slot=0x%X\n", le16_to_cpu(pg0->Slot));
257 printk("SAS Address=0x%llX\n", le64_to_cpu(sas_address));
258 printk("Target ID=0x%X\n", pg0->TargetID);
259 printk("Bus=0x%X\n", pg0->Bus);
Eric Moore024358e2005-10-21 20:56:36 +0200260 printk("Parent Phy Num=0x%X\n", pg0->PhyNum);
261 printk("Access Status=0x%X\n", le16_to_cpu(pg0->AccessStatus));
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200262 printk("Device Info=0x%X\n", le32_to_cpu(pg0->DeviceInfo));
263 printk("Flags=0x%X\n", le16_to_cpu(pg0->Flags));
264 printk("Physical Port=0x%X\n", pg0->PhysicalPort);
265 printk("\n");
266}
267
268static void mptsas_print_expander_pg1(SasExpanderPage1_t *pg1)
269{
270 printk("---- SAS EXPANDER PAGE 1 ------------\n");
271
272 printk("Physical Port=0x%X\n", pg1->PhysicalPort);
Eric Moore024358e2005-10-21 20:56:36 +0200273 printk("PHY Identifier=0x%X\n", pg1->PhyIdentifier);
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200274 printk("Negotiated Link Rate=0x%X\n", pg1->NegotiatedLinkRate);
275 printk("Programmed Link Rate=0x%X\n", pg1->ProgrammedLinkRate);
276 printk("Hardware Link Rate=0x%X\n", pg1->HwLinkRate);
277 printk("Owner Device Handle=0x%X\n",
278 le16_to_cpu(pg1->OwnerDevHandle));
279 printk("Attached Device Handle=0x%X\n",
280 le16_to_cpu(pg1->AttachedDevHandle));
281}
282#else
283#define mptsas_print_phy_data(phy_data) do { } while (0)
284#define mptsas_print_phy_pg0(pg0) do { } while (0)
285#define mptsas_print_device_pg0(pg0) do { } while (0)
286#define mptsas_print_expander_pg1(pg1) do { } while (0)
287#endif
288
289static int
290mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
291{
292 ConfigExtendedPageHeader_t hdr;
293 CONFIGPARMS cfg;
294 SasIOUnitPage0_t *buffer;
295 dma_addr_t dma_handle;
296 int error, i;
297
298 hdr.PageVersion = MPI_SASIOUNITPAGE0_PAGEVERSION;
299 hdr.ExtPageLength = 0;
300 hdr.PageNumber = 0;
301 hdr.Reserved1 = 0;
302 hdr.Reserved2 = 0;
303 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
304 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
305
306 cfg.cfghdr.ehdr = &hdr;
307 cfg.physAddr = -1;
308 cfg.pageAddr = 0;
309 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
310 cfg.dir = 0; /* read */
311 cfg.timeout = 10;
312
313 error = mpt_config(ioc, &cfg);
314 if (error)
315 goto out;
316 if (!hdr.ExtPageLength) {
317 error = -ENXIO;
318 goto out;
319 }
320
321 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
322 &dma_handle);
323 if (!buffer) {
324 error = -ENOMEM;
325 goto out;
326 }
327
328 cfg.physAddr = dma_handle;
329 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
330
331 error = mpt_config(ioc, &cfg);
332 if (error)
333 goto out_free_consistent;
334
335 port_info->num_phys = buffer->NumPhys;
336 port_info->phy_info = kcalloc(port_info->num_phys,
337 sizeof(struct mptsas_phyinfo),GFP_KERNEL);
338 if (!port_info->phy_info) {
339 error = -ENOMEM;
340 goto out_free_consistent;
341 }
342
343 for (i = 0; i < port_info->num_phys; i++) {
344 mptsas_print_phy_data(&buffer->PhyData[i]);
345 port_info->phy_info[i].phy_id = i;
346 port_info->phy_info[i].port_id =
347 buffer->PhyData[i].Port;
348 port_info->phy_info[i].negotiated_link_rate =
349 buffer->PhyData[i].NegotiatedLinkRate;
350 }
351
352 out_free_consistent:
353 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
354 buffer, dma_handle);
355 out:
356 return error;
357}
358
359static int
360mptsas_sas_phy_pg0(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
361 u32 form, u32 form_specific)
362{
363 ConfigExtendedPageHeader_t hdr;
364 CONFIGPARMS cfg;
365 SasPhyPage0_t *buffer;
366 dma_addr_t dma_handle;
367 int error;
368
369 hdr.PageVersion = MPI_SASPHY0_PAGEVERSION;
370 hdr.ExtPageLength = 0;
371 hdr.PageNumber = 0;
372 hdr.Reserved1 = 0;
373 hdr.Reserved2 = 0;
374 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
375 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
376
377 cfg.cfghdr.ehdr = &hdr;
378 cfg.dir = 0; /* read */
379 cfg.timeout = 10;
380
381 /* Get Phy Pg 0 for each Phy. */
382 cfg.physAddr = -1;
383 cfg.pageAddr = form + form_specific;
384 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
385
386 error = mpt_config(ioc, &cfg);
387 if (error)
388 goto out;
389
390 if (!hdr.ExtPageLength) {
391 error = -ENXIO;
392 goto out;
393 }
394
395 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
396 &dma_handle);
397 if (!buffer) {
398 error = -ENOMEM;
399 goto out;
400 }
401
402 cfg.physAddr = dma_handle;
403 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
404
405 error = mpt_config(ioc, &cfg);
406 if (error)
407 goto out_free_consistent;
408
409 mptsas_print_phy_pg0(buffer);
410
411 phy_info->hw_link_rate = buffer->HwLinkRate;
412 phy_info->programmed_link_rate = buffer->ProgrammedLinkRate;
413 phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle);
414 phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle);
415
416 out_free_consistent:
417 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
418 buffer, dma_handle);
419 out:
420 return error;
421}
422
423static int
424mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info,
425 u32 form, u32 form_specific)
426{
427 ConfigExtendedPageHeader_t hdr;
428 CONFIGPARMS cfg;
429 SasDevicePage0_t *buffer;
430 dma_addr_t dma_handle;
431 __le64 sas_address;
432 int error;
433
434 hdr.PageVersion = MPI_SASDEVICE0_PAGEVERSION;
435 hdr.ExtPageLength = 0;
436 hdr.PageNumber = 0;
437 hdr.Reserved1 = 0;
438 hdr.Reserved2 = 0;
439 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
440 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE;
441
442 cfg.cfghdr.ehdr = &hdr;
443 cfg.pageAddr = form + form_specific;
444 cfg.physAddr = -1;
445 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
446 cfg.dir = 0; /* read */
447 cfg.timeout = 10;
448
449 error = mpt_config(ioc, &cfg);
450 if (error)
451 goto out;
452 if (!hdr.ExtPageLength) {
453 error = -ENXIO;
454 goto out;
455 }
456
457 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
458 &dma_handle);
459 if (!buffer) {
460 error = -ENOMEM;
461 goto out;
462 }
463
464 cfg.physAddr = dma_handle;
465 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
466
467 error = mpt_config(ioc, &cfg);
468 if (error)
469 goto out_free_consistent;
470
471 mptsas_print_device_pg0(buffer);
472
473 device_info->handle = le16_to_cpu(buffer->DevHandle);
474 device_info->phy_id = buffer->PhyNum;
475 device_info->port_id = buffer->PhysicalPort;
476 device_info->target = buffer->TargetID;
477 device_info->bus = buffer->Bus;
478 memcpy(&sas_address, &buffer->SASAddress, sizeof(__le64));
479 device_info->sas_address = le64_to_cpu(sas_address);
480 device_info->device_info =
481 le32_to_cpu(buffer->DeviceInfo);
482
483 out_free_consistent:
484 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
485 buffer, dma_handle);
486 out:
487 return error;
488}
489
490static int
491mptsas_sas_expander_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info,
492 u32 form, u32 form_specific)
493{
494 ConfigExtendedPageHeader_t hdr;
495 CONFIGPARMS cfg;
496 SasExpanderPage0_t *buffer;
497 dma_addr_t dma_handle;
498 int error;
499
500 hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION;
501 hdr.ExtPageLength = 0;
502 hdr.PageNumber = 0;
503 hdr.Reserved1 = 0;
504 hdr.Reserved2 = 0;
505 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
506 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
507
508 cfg.cfghdr.ehdr = &hdr;
509 cfg.physAddr = -1;
510 cfg.pageAddr = form + form_specific;
511 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
512 cfg.dir = 0; /* read */
513 cfg.timeout = 10;
514
515 error = mpt_config(ioc, &cfg);
516 if (error)
517 goto out;
518
519 if (!hdr.ExtPageLength) {
520 error = -ENXIO;
521 goto out;
522 }
523
524 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
525 &dma_handle);
526 if (!buffer) {
527 error = -ENOMEM;
528 goto out;
529 }
530
531 cfg.physAddr = dma_handle;
532 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
533
534 error = mpt_config(ioc, &cfg);
535 if (error)
536 goto out_free_consistent;
537
538 /* save config data */
539 port_info->num_phys = buffer->NumPhys;
540 port_info->handle = le16_to_cpu(buffer->DevHandle);
541 port_info->phy_info = kcalloc(port_info->num_phys,
542 sizeof(struct mptsas_phyinfo),GFP_KERNEL);
543 if (!port_info->phy_info) {
544 error = -ENOMEM;
545 goto out_free_consistent;
546 }
547
548 out_free_consistent:
549 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
550 buffer, dma_handle);
551 out:
552 return error;
553}
554
555static int
556mptsas_sas_expander_pg1(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
557 u32 form, u32 form_specific)
558{
559 ConfigExtendedPageHeader_t hdr;
560 CONFIGPARMS cfg;
561 SasExpanderPage1_t *buffer;
562 dma_addr_t dma_handle;
563 int error;
564
565 hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION;
566 hdr.ExtPageLength = 0;
567 hdr.PageNumber = 1;
568 hdr.Reserved1 = 0;
569 hdr.Reserved2 = 0;
570 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
571 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
572
573 cfg.cfghdr.ehdr = &hdr;
574 cfg.physAddr = -1;
575 cfg.pageAddr = form + form_specific;
576 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
577 cfg.dir = 0; /* read */
578 cfg.timeout = 10;
579
580 error = mpt_config(ioc, &cfg);
581 if (error)
582 goto out;
583
584 if (!hdr.ExtPageLength) {
585 error = -ENXIO;
586 goto out;
587 }
588
589 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
590 &dma_handle);
591 if (!buffer) {
592 error = -ENOMEM;
593 goto out;
594 }
595
596 cfg.physAddr = dma_handle;
597 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
598
599 error = mpt_config(ioc, &cfg);
600 if (error)
601 goto out_free_consistent;
602
603
604 mptsas_print_expander_pg1(buffer);
605
606 /* save config data */
Eric Moore024358e2005-10-21 20:56:36 +0200607 phy_info->phy_id = buffer->PhyIdentifier;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200608 phy_info->port_id = buffer->PhysicalPort;
609 phy_info->negotiated_link_rate = buffer->NegotiatedLinkRate;
610 phy_info->programmed_link_rate = buffer->ProgrammedLinkRate;
611 phy_info->hw_link_rate = buffer->HwLinkRate;
612 phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle);
613 phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle);
614
615
616 out_free_consistent:
617 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
618 buffer, dma_handle);
619 out:
620 return error;
621}
622
623static void
624mptsas_parse_device_info(struct sas_identify *identify,
625 struct mptsas_devinfo *device_info)
626{
627 u16 protocols;
628
629 identify->sas_address = device_info->sas_address;
630 identify->phy_identifier = device_info->phy_id;
631
632 /*
633 * Fill in Phy Initiator Port Protocol.
634 * Bits 6:3, more than one bit can be set, fall through cases.
635 */
636 protocols = device_info->device_info & 0x78;
637 identify->initiator_port_protocols = 0;
638 if (protocols & MPI_SAS_DEVICE_INFO_SSP_INITIATOR)
639 identify->initiator_port_protocols |= SAS_PROTOCOL_SSP;
640 if (protocols & MPI_SAS_DEVICE_INFO_STP_INITIATOR)
641 identify->initiator_port_protocols |= SAS_PROTOCOL_STP;
642 if (protocols & MPI_SAS_DEVICE_INFO_SMP_INITIATOR)
643 identify->initiator_port_protocols |= SAS_PROTOCOL_SMP;
644 if (protocols & MPI_SAS_DEVICE_INFO_SATA_HOST)
645 identify->initiator_port_protocols |= SAS_PROTOCOL_SATA;
646
647 /*
648 * Fill in Phy Target Port Protocol.
649 * Bits 10:7, more than one bit can be set, fall through cases.
650 */
651 protocols = device_info->device_info & 0x780;
652 identify->target_port_protocols = 0;
653 if (protocols & MPI_SAS_DEVICE_INFO_SSP_TARGET)
654 identify->target_port_protocols |= SAS_PROTOCOL_SSP;
655 if (protocols & MPI_SAS_DEVICE_INFO_STP_TARGET)
656 identify->target_port_protocols |= SAS_PROTOCOL_STP;
657 if (protocols & MPI_SAS_DEVICE_INFO_SMP_TARGET)
658 identify->target_port_protocols |= SAS_PROTOCOL_SMP;
659 if (protocols & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
660 identify->target_port_protocols |= SAS_PROTOCOL_SATA;
661
662 /*
663 * Fill in Attached device type.
664 */
665 switch (device_info->device_info &
666 MPI_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) {
667 case MPI_SAS_DEVICE_INFO_NO_DEVICE:
668 identify->device_type = SAS_PHY_UNUSED;
669 break;
670 case MPI_SAS_DEVICE_INFO_END_DEVICE:
671 identify->device_type = SAS_END_DEVICE;
672 break;
673 case MPI_SAS_DEVICE_INFO_EDGE_EXPANDER:
674 identify->device_type = SAS_EDGE_EXPANDER_DEVICE;
675 break;
676 case MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER:
677 identify->device_type = SAS_FANOUT_EXPANDER_DEVICE;
678 break;
679 }
680}
681
682static int mptsas_probe_one_phy(struct device *dev,
683 struct mptsas_phyinfo *phy_info, int index)
684{
685 struct sas_phy *port;
686 int error;
687
688 port = sas_phy_alloc(dev, index);
689 if (!port)
690 return -ENOMEM;
691
692 port->port_identifier = phy_info->port_id;
693 mptsas_parse_device_info(&port->identify, &phy_info->identify);
694
695 /*
696 * Set Negotiated link rate.
697 */
698 switch (phy_info->negotiated_link_rate) {
699 case MPI_SAS_IOUNIT0_RATE_PHY_DISABLED:
700 port->negotiated_linkrate = SAS_PHY_DISABLED;
701 break;
702 case MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION:
703 port->negotiated_linkrate = SAS_LINK_RATE_FAILED;
704 break;
705 case MPI_SAS_IOUNIT0_RATE_1_5:
706 port->negotiated_linkrate = SAS_LINK_RATE_1_5_GBPS;
707 break;
708 case MPI_SAS_IOUNIT0_RATE_3_0:
709 port->negotiated_linkrate = SAS_LINK_RATE_3_0_GBPS;
710 break;
711 case MPI_SAS_IOUNIT0_RATE_SATA_OOB_COMPLETE:
712 case MPI_SAS_IOUNIT0_RATE_UNKNOWN:
713 default:
714 port->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN;
715 break;
716 }
717
718 /*
719 * Set Max hardware link rate.
720 */
721 switch (phy_info->hw_link_rate & MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
722 case MPI_SAS_PHY0_HWRATE_MAX_RATE_1_5:
723 port->maximum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
724 break;
725 case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
726 port->maximum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
727 break;
728 default:
729 break;
730 }
731
732 /*
733 * Set Max programmed link rate.
734 */
735 switch (phy_info->programmed_link_rate &
736 MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
737 case MPI_SAS_PHY0_PRATE_MAX_RATE_1_5:
738 port->maximum_linkrate = SAS_LINK_RATE_1_5_GBPS;
739 break;
740 case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
741 port->maximum_linkrate = SAS_LINK_RATE_3_0_GBPS;
742 break;
743 default:
744 break;
745 }
746
747 /*
748 * Set Min hardware link rate.
749 */
750 switch (phy_info->hw_link_rate & MPI_SAS_PHY0_HWRATE_MIN_RATE_MASK) {
751 case MPI_SAS_PHY0_HWRATE_MIN_RATE_1_5:
752 port->minimum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
753 break;
754 case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
755 port->minimum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
756 break;
757 default:
758 break;
759 }
760
761 /*
762 * Set Min programmed link rate.
763 */
764 switch (phy_info->programmed_link_rate &
765 MPI_SAS_PHY0_PRATE_MIN_RATE_MASK) {
766 case MPI_SAS_PHY0_PRATE_MIN_RATE_1_5:
767 port->minimum_linkrate = SAS_LINK_RATE_1_5_GBPS;
768 break;
769 case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
770 port->minimum_linkrate = SAS_LINK_RATE_3_0_GBPS;
771 break;
772 default:
773 break;
774 }
775
776 error = sas_phy_add(port);
777 if (error) {
778 sas_phy_free(port);
779 return error;
780 }
781
782 if (phy_info->attached.handle) {
783 struct sas_rphy *rphy;
784
785 rphy = sas_rphy_alloc(port);
786 if (!rphy)
787 return 0; /* non-fatal: an rphy can be added later */
788
789 mptsas_parse_device_info(&rphy->identify, &phy_info->attached);
790 error = sas_rphy_add(rphy);
791 if (error) {
792 sas_rphy_free(rphy);
793 return error;
794 }
795
796 phy_info->rphy = rphy;
797 }
798
799 return 0;
800}
801
802static int
803mptsas_probe_hba_phys(MPT_ADAPTER *ioc, int *index)
804{
805 struct mptsas_portinfo *port_info;
806 u32 handle = 0xFFFF;
807 int error = -ENOMEM, i;
808
809 port_info = kmalloc(sizeof(*port_info), GFP_KERNEL);
810 if (!port_info)
811 goto out;
812 memset(port_info, 0, sizeof(*port_info));
813
814 error = mptsas_sas_io_unit_pg0(ioc, port_info);
815 if (error)
816 goto out_free_port_info;
817
818 list_add_tail(&port_info->list, &ioc->sas_topology);
819
820 for (i = 0; i < port_info->num_phys; i++) {
821 mptsas_sas_phy_pg0(ioc, &port_info->phy_info[i],
822 (MPI_SAS_PHY_PGAD_FORM_PHY_NUMBER <<
823 MPI_SAS_PHY_PGAD_FORM_SHIFT), i);
824
825 mptsas_sas_device_pg0(ioc, &port_info->phy_info[i].identify,
826 (MPI_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE <<
827 MPI_SAS_DEVICE_PGAD_FORM_SHIFT), handle);
Eric Moore024358e2005-10-21 20:56:36 +0200828 port_info->phy_info[i].identify.phy_id =
829 port_info->phy_info[i].phy_id;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200830 handle = port_info->phy_info[i].identify.handle;
831
832 if (port_info->phy_info[i].attached.handle) {
833 mptsas_sas_device_pg0(ioc,
834 &port_info->phy_info[i].attached,
835 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
836 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
837 port_info->phy_info[i].attached.handle);
838 }
839
840 mptsas_probe_one_phy(&ioc->sh->shost_gendev,
841 &port_info->phy_info[i], *index);
842 (*index)++;
843 }
844
845 return 0;
846
847 out_free_port_info:
848 kfree(port_info);
849 out:
850 return error;
851}
852
853static int
854mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle, int *index)
855{
856 struct mptsas_portinfo *port_info, *p;
857 int error = -ENOMEM, i, j;
858
859 port_info = kmalloc(sizeof(*port_info), GFP_KERNEL);
860 if (!port_info)
861 goto out;
862 memset(port_info, 0, sizeof(*port_info));
863
864 error = mptsas_sas_expander_pg0(ioc, port_info,
865 (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE <<
866 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), *handle);
867 if (error)
868 goto out_free_port_info;
869
870 *handle = port_info->handle;
871
872 list_add_tail(&port_info->list, &ioc->sas_topology);
873 for (i = 0; i < port_info->num_phys; i++) {
874 struct device *parent;
875
876 mptsas_sas_expander_pg1(ioc, &port_info->phy_info[i],
877 (MPI_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM <<
878 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), (i << 16) + *handle);
879
880 if (port_info->phy_info[i].identify.handle) {
881 mptsas_sas_device_pg0(ioc,
882 &port_info->phy_info[i].identify,
883 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
884 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
885 port_info->phy_info[i].identify.handle);
Eric Moore024358e2005-10-21 20:56:36 +0200886 port_info->phy_info[i].identify.phy_id =
887 port_info->phy_info[i].phy_id;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200888 }
889
890 if (port_info->phy_info[i].attached.handle) {
891 mptsas_sas_device_pg0(ioc,
892 &port_info->phy_info[i].attached,
893 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
894 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
895 port_info->phy_info[i].attached.handle);
896 }
897
898 /*
899 * If we find a parent port handle this expander is
900 * attached to another expander, else it hangs of the
901 * HBA phys.
902 */
903 parent = &ioc->sh->shost_gendev;
904 list_for_each_entry(p, &ioc->sas_topology, list) {
905 for (j = 0; j < p->num_phys; j++) {
906 if (port_info->phy_info[i].identify.handle ==
907 p->phy_info[j].attached.handle)
908 parent = &p->phy_info[j].rphy->dev;
909 }
910 }
911
912 mptsas_probe_one_phy(parent, &port_info->phy_info[i], *index);
913 (*index)++;
914 }
915
916 return 0;
917
918 out_free_port_info:
919 kfree(port_info);
920 out:
921 return error;
922}
923
924static void
925mptsas_scan_sas_topology(MPT_ADAPTER *ioc)
926{
927 u32 handle = 0xFFFF;
928 int index = 0;
929
930 mptsas_probe_hba_phys(ioc, &index);
931 while (!mptsas_probe_expander_phys(ioc, &handle, &index))
932 ;
933}
934
935static int
936mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
937{
938 struct Scsi_Host *sh;
939 MPT_SCSI_HOST *hd;
940 MPT_ADAPTER *ioc;
941 unsigned long flags;
942 int sz, ii;
943 int numSGE = 0;
944 int scale;
945 int ioc_cap;
946 u8 *mem;
947 int error=0;
948 int r;
949
950 r = mpt_attach(pdev,id);
951 if (r)
952 return r;
953
954 ioc = pci_get_drvdata(pdev);
955 ioc->DoneCtx = mptsasDoneCtx;
956 ioc->TaskCtx = mptsasTaskCtx;
957 ioc->InternalCtx = mptsasInternalCtx;
958
959 /* Added sanity check on readiness of the MPT adapter.
960 */
961 if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
962 printk(MYIOC_s_WARN_FMT
963 "Skipping because it's not operational!\n",
964 ioc->name);
965 return -ENODEV;
966 }
967
968 if (!ioc->active) {
969 printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
970 ioc->name);
971 return -ENODEV;
972 }
973
974 /* Sanity check - ensure at least 1 port is INITIATOR capable
975 */
976 ioc_cap = 0;
977 for (ii = 0; ii < ioc->facts.NumberOfPorts; ii++) {
978 if (ioc->pfacts[ii].ProtocolFlags &
979 MPI_PORTFACTS_PROTOCOL_INITIATOR)
980 ioc_cap++;
981 }
982
983 if (!ioc_cap) {
984 printk(MYIOC_s_WARN_FMT
985 "Skipping ioc=%p because SCSI Initiator mode "
986 "is NOT enabled!\n", ioc->name, ioc);
Moore, Eric Dean466544d2005-09-14 18:09:10 -0600987 return 0;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200988 }
989
990 sh = scsi_host_alloc(&mptsas_driver_template, sizeof(MPT_SCSI_HOST));
991 if (!sh) {
992 printk(MYIOC_s_WARN_FMT
993 "Unable to register controller with SCSI subsystem\n",
994 ioc->name);
995 return -1;
996 }
997
998 spin_lock_irqsave(&ioc->FreeQlock, flags);
999
1000 /* Attach the SCSI Host to the IOC structure
1001 */
1002 ioc->sh = sh;
1003
1004 sh->io_port = 0;
1005 sh->n_io_port = 0;
1006 sh->irq = 0;
1007
1008 /* set 16 byte cdb's */
1009 sh->max_cmd_len = 16;
1010
1011 sh->max_id = ioc->pfacts->MaxDevices + 1;
1012
1013 sh->transportt = mptsas_transport_template;
1014
1015 sh->max_lun = MPT_LAST_LUN + 1;
1016 sh->max_channel = 0;
1017 sh->this_id = ioc->pfacts[0].PortSCSIID;
1018
1019 /* Required entry.
1020 */
1021 sh->unique_id = ioc->id;
1022
1023 INIT_LIST_HEAD(&ioc->sas_topology);
1024
1025 /* Verify that we won't exceed the maximum
1026 * number of chain buffers
1027 * We can optimize: ZZ = req_sz/sizeof(SGE)
1028 * For 32bit SGE's:
1029 * numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
1030 * + (req_sz - 64)/sizeof(SGE)
1031 * A slightly different algorithm is required for
1032 * 64bit SGEs.
1033 */
1034 scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
1035 if (sizeof(dma_addr_t) == sizeof(u64)) {
1036 numSGE = (scale - 1) *
1037 (ioc->facts.MaxChainDepth-1) + scale +
1038 (ioc->req_sz - 60) / (sizeof(dma_addr_t) +
1039 sizeof(u32));
1040 } else {
1041 numSGE = 1 + (scale - 1) *
1042 (ioc->facts.MaxChainDepth-1) + scale +
1043 (ioc->req_sz - 64) / (sizeof(dma_addr_t) +
1044 sizeof(u32));
1045 }
1046
1047 if (numSGE < sh->sg_tablesize) {
1048 /* Reset this value */
1049 dprintk((MYIOC_s_INFO_FMT
1050 "Resetting sg_tablesize to %d from %d\n",
1051 ioc->name, numSGE, sh->sg_tablesize));
1052 sh->sg_tablesize = numSGE;
1053 }
1054
1055 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
1056
1057 hd = (MPT_SCSI_HOST *) sh->hostdata;
1058 hd->ioc = ioc;
1059
1060 /* SCSI needs scsi_cmnd lookup table!
1061 * (with size equal to req_depth*PtrSz!)
1062 */
1063 sz = ioc->req_depth * sizeof(void *);
1064 mem = kmalloc(sz, GFP_ATOMIC);
1065 if (mem == NULL) {
1066 error = -ENOMEM;
1067 goto mptsas_probe_failed;
1068 }
1069
1070 memset(mem, 0, sz);
1071 hd->ScsiLookup = (struct scsi_cmnd **) mem;
1072
1073 dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n",
1074 ioc->name, hd->ScsiLookup, sz));
1075
1076 /* Allocate memory for the device structures.
1077 * A non-Null pointer at an offset
1078 * indicates a device exists.
1079 * max_id = 1 + maximum id (hosts.h)
1080 */
1081 sz = sh->max_id * sizeof(void *);
1082 mem = kmalloc(sz, GFP_ATOMIC);
1083 if (mem == NULL) {
1084 error = -ENOMEM;
1085 goto mptsas_probe_failed;
1086 }
1087
1088 memset(mem, 0, sz);
1089 hd->Targets = (VirtDevice **) mem;
1090
1091 dprintk((KERN_INFO
1092 " Targets @ %p, sz=%d\n", hd->Targets, sz));
1093
1094 /* Clear the TM flags
1095 */
1096 hd->tmPending = 0;
1097 hd->tmState = TM_STATE_NONE;
1098 hd->resetPending = 0;
1099 hd->abortSCpnt = NULL;
1100
1101 /* Clear the pointer used to store
1102 * single-threaded commands, i.e., those
1103 * issued during a bus scan, dv and
1104 * configuration pages.
1105 */
1106 hd->cmdPtr = NULL;
1107
1108 /* Initialize this SCSI Hosts' timers
1109 * To use, set the timer expires field
1110 * and add_timer
1111 */
1112 init_timer(&hd->timer);
1113 hd->timer.data = (unsigned long) hd;
1114 hd->timer.function = mptscsih_timer_expired;
1115
1116 hd->mpt_pq_filter = mpt_pq_filter;
1117 ioc->sas_data.ptClear = mpt_pt_clear;
1118
1119 if (ioc->sas_data.ptClear==1) {
1120 mptbase_sas_persist_operation(
1121 ioc, MPI_SAS_OP_CLEAR_ALL_PERSISTENT);
1122 }
1123
1124 ddvprintk((MYIOC_s_INFO_FMT
1125 "mpt_pq_filter %x mpt_pq_filter %x\n",
1126 ioc->name,
1127 mpt_pq_filter,
1128 mpt_pq_filter));
1129
1130 init_waitqueue_head(&hd->scandv_waitq);
1131 hd->scandv_wait_done = 0;
1132 hd->last_queue_full = 0;
1133
1134 error = scsi_add_host(sh, &ioc->pcidev->dev);
1135 if (error) {
1136 dprintk((KERN_ERR MYNAM
1137 "scsi_add_host failed\n"));
1138 goto mptsas_probe_failed;
1139 }
1140
1141 mptsas_scan_sas_topology(ioc);
1142
1143 return 0;
1144
1145mptsas_probe_failed:
1146
1147 mptscsih_remove(pdev);
1148 return error;
1149}
1150
1151static void __devexit mptsas_remove(struct pci_dev *pdev)
1152{
1153 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1154 struct mptsas_portinfo *p, *n;
1155
1156 sas_remove_host(ioc->sh);
1157
1158 list_for_each_entry_safe(p, n, &ioc->sas_topology, list) {
1159 list_del(&p->list);
1160 kfree(p);
1161 }
1162
1163 mptscsih_remove(pdev);
1164}
1165
1166static struct pci_device_id mptsas_pci_table[] = {
1167 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1064,
1168 PCI_ANY_ID, PCI_ANY_ID },
1169 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1066,
1170 PCI_ANY_ID, PCI_ANY_ID },
1171 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1068,
1172 PCI_ANY_ID, PCI_ANY_ID },
1173 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1064E,
1174 PCI_ANY_ID, PCI_ANY_ID },
1175 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1066E,
1176 PCI_ANY_ID, PCI_ANY_ID },
1177 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1068E,
1178 PCI_ANY_ID, PCI_ANY_ID },
1179 {0} /* Terminating entry */
1180};
1181MODULE_DEVICE_TABLE(pci, mptsas_pci_table);
1182
1183
1184static struct pci_driver mptsas_driver = {
1185 .name = "mptsas",
1186 .id_table = mptsas_pci_table,
1187 .probe = mptsas_probe,
1188 .remove = __devexit_p(mptsas_remove),
1189 .shutdown = mptscsih_shutdown,
1190#ifdef CONFIG_PM
1191 .suspend = mptscsih_suspend,
1192 .resume = mptscsih_resume,
1193#endif
1194};
1195
1196static int __init
1197mptsas_init(void)
1198{
1199 show_mptmod_ver(my_NAME, my_VERSION);
1200
1201 mptsas_transport_template =
1202 sas_attach_transport(&mptsas_transport_functions);
1203 if (!mptsas_transport_template)
1204 return -ENODEV;
1205
1206 mptsasDoneCtx = mpt_register(mptscsih_io_done, MPTSAS_DRIVER);
1207 mptsasTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSAS_DRIVER);
1208 mptsasInternalCtx =
1209 mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER);
1210
1211 if (mpt_event_register(mptsasDoneCtx, mptscsih_event_process) == 0) {
1212 devtprintk((KERN_INFO MYNAM
1213 ": Registered for IOC event notifications\n"));
1214 }
1215
1216 if (mpt_reset_register(mptsasDoneCtx, mptscsih_ioc_reset) == 0) {
1217 dprintk((KERN_INFO MYNAM
1218 ": Registered for IOC reset notifications\n"));
1219 }
1220
1221 return pci_register_driver(&mptsas_driver);
1222}
1223
1224static void __exit
1225mptsas_exit(void)
1226{
1227 pci_unregister_driver(&mptsas_driver);
1228 sas_release_transport(mptsas_transport_template);
1229
1230 mpt_reset_deregister(mptsasDoneCtx);
1231 mpt_event_deregister(mptsasDoneCtx);
1232
1233 mpt_deregister(mptsasInternalCtx);
1234 mpt_deregister(mptsasTaskCtx);
1235 mpt_deregister(mptsasDoneCtx);
1236}
1237
1238module_init(mptsas_init);
1239module_exit(mptsas_exit);