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