blob: 0e557a3a9d0627e97f7c6f44e3ee3c9a145c313b [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 */
Christoph Hellwigda4fa652005-10-19 20:01:42 +020086static int mptsasMgmtCtx = -1;
Christoph Hellwig0c33b272005-09-09 16:27:19 +020087
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
Christoph Hellwigb5141122005-10-28 22:07:41 +0200127
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");
Christoph Hellwigf9a2d2e2005-10-19 20:01:47 +0200170 printk("Invalid Dword Count=0x%x\n", pg1->InvalidDwordCount);
171 printk("Running Disparity Error Count=0x%x\n",
Christoph Hellwigb5141122005-10-28 22:07:41 +0200172 pg1->RunningDisparityErrorCount);
Christoph Hellwigf9a2d2e2005-10-19 20:01:47 +0200173 printk("Loss Dword Synch Count=0x%x\n", pg1->LossDwordSynchCount);
174 printk("PHY Reset Problem Count=0x%x\n", pg1->PhyResetProblemCount);
175 printk("\n");
Christoph Hellwigb5141122005-10-28 22:07:41 +0200176}
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);
Christoph Hellwigf9a2d2e2005-10-19 20:01:47 +0200191 /* 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));
Christoph Hellwigb5141122005-10-28 22:07:41 +0200196 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);
Christoph Hellwigf9a2d2e2005-10-19 20:01:47 +0200207 printk("PHY Identifier=0x%X\n", pg1->PhyIdentifier);
Christoph Hellwigb5141122005-10-28 22:07:41 +0200208 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
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200225/*
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 = {
Moore, Eric Deanf78496d2005-11-16 18:54:14 -0700280 .module = THIS_MODULE,
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200281 .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
Christoph Hellwigb5141122005-10-28 22:07:41 +0200303static inline MPT_ADAPTER *phy_to_ioc(struct sas_phy *phy)
304{
305 struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
306 return ((MPT_SCSI_HOST *)shost->hostdata)->ioc;
307}
308
309static int mptsas_get_linkerrors(struct sas_phy *phy)
310{
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;
317
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;
325
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;
332
333 error = mpt_config(ioc, &cfg);
334 if (error)
335 return error;
336 if (!hdr.ExtPageLength)
337 return -ENXIO;
338
339 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
340 &dma_handle);
341 if (!buffer)
342 return -ENOMEM;
343
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;
365}
366
Christoph Hellwigda4fa652005-10-19 20:01:42 +0200367static 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}
Christoph Hellwigb5141122005-10-28 22:07:41 +0200449
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200450static struct sas_function_template mptsas_transport_functions = {
Christoph Hellwigb5141122005-10-28 22:07:41 +0200451 .get_linkerrors = mptsas_get_linkerrors,
Christoph Hellwigda4fa652005-10-19 20:01:42 +0200452 .phy_reset = mptsas_phy_reset,
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200453};
454
455static struct scsi_transport_template *mptsas_transport_template;
456
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200457static 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 */
Eric Moore024358e2005-10-21 20:56:36 +0200775 phy_info->phy_id = buffer->PhyIdentifier;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200776 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,
Christoph Hellwigac01bbb2005-10-19 20:01:17 +0200851 struct mptsas_phyinfo *phy_info, int index, int local)
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200852{
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
Christoph Hellwigac01bbb2005-10-19 20:01:17 +0200944 if (local)
945 port->local_attached = 1;
946
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200947 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);
Eric Moore024358e2005-10-21 20:56:36 +0200999 port_info->phy_info[i].identify.phy_id =
1000 port_info->phy_info[i].phy_id;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001001 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,
Christoph Hellwigac01bbb2005-10-19 20:01:17 +02001012 &port_info->phy_info[i], *index, 1);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001013 (*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);
Eric Moore024358e2005-10-21 20:56:36 +02001057 port_info->phy_info[i].identify.phy_id =
1058 port_info->phy_info[i].phy_id;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001059 }
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
Christoph Hellwigac01bbb2005-10-19 20:01:17 +02001083 mptsas_probe_one_phy(parent, &port_info->phy_info[i],
1084 *index, 0);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001085 (*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);
1137 return -ENODEV;
1138 }
1139
1140 if (!ioc->active) {
1141 printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
1142 ioc->name);
1143 return -ENODEV;
1144 }
1145
1146 /* Sanity check - ensure at least 1 port is INITIATOR capable
1147 */
1148 ioc_cap = 0;
1149 for (ii = 0; ii < ioc->facts.NumberOfPorts; ii++) {
1150 if (ioc->pfacts[ii].ProtocolFlags &
1151 MPI_PORTFACTS_PROTOCOL_INITIATOR)
1152 ioc_cap++;
1153 }
1154
1155 if (!ioc_cap) {
1156 printk(MYIOC_s_WARN_FMT
1157 "Skipping ioc=%p because SCSI Initiator mode "
1158 "is NOT enabled!\n", ioc->name, ioc);
Moore, Eric Dean466544d2005-09-14 18:09:10 -06001159 return 0;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001160 }
1161
1162 sh = scsi_host_alloc(&mptsas_driver_template, sizeof(MPT_SCSI_HOST));
1163 if (!sh) {
1164 printk(MYIOC_s_WARN_FMT
1165 "Unable to register controller with SCSI subsystem\n",
1166 ioc->name);
1167 return -1;
1168 }
1169
1170 spin_lock_irqsave(&ioc->FreeQlock, flags);
1171
1172 /* Attach the SCSI Host to the IOC structure
1173 */
1174 ioc->sh = sh;
1175
1176 sh->io_port = 0;
1177 sh->n_io_port = 0;
1178 sh->irq = 0;
1179
1180 /* set 16 byte cdb's */
1181 sh->max_cmd_len = 16;
1182
1183 sh->max_id = ioc->pfacts->MaxDevices + 1;
1184
1185 sh->transportt = mptsas_transport_template;
1186
1187 sh->max_lun = MPT_LAST_LUN + 1;
1188 sh->max_channel = 0;
1189 sh->this_id = ioc->pfacts[0].PortSCSIID;
1190
1191 /* Required entry.
1192 */
1193 sh->unique_id = ioc->id;
1194
1195 INIT_LIST_HEAD(&ioc->sas_topology);
Christoph Hellwigda4fa652005-10-19 20:01:42 +02001196 init_MUTEX(&ioc->sas_mgmt.mutex);
1197 init_completion(&ioc->sas_mgmt.done);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001198
1199 /* Verify that we won't exceed the maximum
1200 * number of chain buffers
1201 * We can optimize: ZZ = req_sz/sizeof(SGE)
1202 * For 32bit SGE's:
1203 * numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
1204 * + (req_sz - 64)/sizeof(SGE)
1205 * A slightly different algorithm is required for
1206 * 64bit SGEs.
1207 */
1208 scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
1209 if (sizeof(dma_addr_t) == sizeof(u64)) {
1210 numSGE = (scale - 1) *
1211 (ioc->facts.MaxChainDepth-1) + scale +
1212 (ioc->req_sz - 60) / (sizeof(dma_addr_t) +
1213 sizeof(u32));
1214 } else {
1215 numSGE = 1 + (scale - 1) *
1216 (ioc->facts.MaxChainDepth-1) + scale +
1217 (ioc->req_sz - 64) / (sizeof(dma_addr_t) +
1218 sizeof(u32));
1219 }
1220
1221 if (numSGE < sh->sg_tablesize) {
1222 /* Reset this value */
1223 dprintk((MYIOC_s_INFO_FMT
1224 "Resetting sg_tablesize to %d from %d\n",
1225 ioc->name, numSGE, sh->sg_tablesize));
1226 sh->sg_tablesize = numSGE;
1227 }
1228
1229 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
1230
1231 hd = (MPT_SCSI_HOST *) sh->hostdata;
1232 hd->ioc = ioc;
1233
1234 /* SCSI needs scsi_cmnd lookup table!
1235 * (with size equal to req_depth*PtrSz!)
1236 */
1237 sz = ioc->req_depth * sizeof(void *);
1238 mem = kmalloc(sz, GFP_ATOMIC);
1239 if (mem == NULL) {
1240 error = -ENOMEM;
1241 goto mptsas_probe_failed;
1242 }
1243
1244 memset(mem, 0, sz);
1245 hd->ScsiLookup = (struct scsi_cmnd **) mem;
1246
1247 dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n",
1248 ioc->name, hd->ScsiLookup, sz));
1249
1250 /* Allocate memory for the device structures.
1251 * A non-Null pointer at an offset
1252 * indicates a device exists.
1253 * max_id = 1 + maximum id (hosts.h)
1254 */
1255 sz = sh->max_id * sizeof(void *);
1256 mem = kmalloc(sz, GFP_ATOMIC);
1257 if (mem == NULL) {
1258 error = -ENOMEM;
1259 goto mptsas_probe_failed;
1260 }
1261
1262 memset(mem, 0, sz);
1263 hd->Targets = (VirtDevice **) mem;
1264
1265 dprintk((KERN_INFO
1266 " Targets @ %p, sz=%d\n", hd->Targets, sz));
1267
1268 /* Clear the TM flags
1269 */
1270 hd->tmPending = 0;
1271 hd->tmState = TM_STATE_NONE;
1272 hd->resetPending = 0;
1273 hd->abortSCpnt = NULL;
1274
1275 /* Clear the pointer used to store
1276 * single-threaded commands, i.e., those
1277 * issued during a bus scan, dv and
1278 * configuration pages.
1279 */
1280 hd->cmdPtr = NULL;
1281
1282 /* Initialize this SCSI Hosts' timers
1283 * To use, set the timer expires field
1284 * and add_timer
1285 */
1286 init_timer(&hd->timer);
1287 hd->timer.data = (unsigned long) hd;
1288 hd->timer.function = mptscsih_timer_expired;
1289
1290 hd->mpt_pq_filter = mpt_pq_filter;
1291 ioc->sas_data.ptClear = mpt_pt_clear;
1292
1293 if (ioc->sas_data.ptClear==1) {
1294 mptbase_sas_persist_operation(
1295 ioc, MPI_SAS_OP_CLEAR_ALL_PERSISTENT);
1296 }
1297
1298 ddvprintk((MYIOC_s_INFO_FMT
1299 "mpt_pq_filter %x mpt_pq_filter %x\n",
1300 ioc->name,
1301 mpt_pq_filter,
1302 mpt_pq_filter));
1303
1304 init_waitqueue_head(&hd->scandv_waitq);
1305 hd->scandv_wait_done = 0;
1306 hd->last_queue_full = 0;
1307
1308 error = scsi_add_host(sh, &ioc->pcidev->dev);
1309 if (error) {
1310 dprintk((KERN_ERR MYNAM
1311 "scsi_add_host failed\n"));
1312 goto mptsas_probe_failed;
1313 }
1314
1315 mptsas_scan_sas_topology(ioc);
1316
1317 return 0;
1318
1319mptsas_probe_failed:
1320
1321 mptscsih_remove(pdev);
1322 return error;
1323}
1324
1325static void __devexit mptsas_remove(struct pci_dev *pdev)
1326{
1327 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1328 struct mptsas_portinfo *p, *n;
1329
1330 sas_remove_host(ioc->sh);
1331
1332 list_for_each_entry_safe(p, n, &ioc->sas_topology, list) {
1333 list_del(&p->list);
1334 kfree(p);
1335 }
1336
1337 mptscsih_remove(pdev);
1338}
1339
1340static struct pci_device_id mptsas_pci_table[] = {
1341 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1064,
1342 PCI_ANY_ID, PCI_ANY_ID },
1343 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1066,
1344 PCI_ANY_ID, PCI_ANY_ID },
1345 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1068,
1346 PCI_ANY_ID, PCI_ANY_ID },
1347 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1064E,
1348 PCI_ANY_ID, PCI_ANY_ID },
1349 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1066E,
1350 PCI_ANY_ID, PCI_ANY_ID },
1351 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1068E,
1352 PCI_ANY_ID, PCI_ANY_ID },
1353 {0} /* Terminating entry */
1354};
1355MODULE_DEVICE_TABLE(pci, mptsas_pci_table);
1356
1357
1358static struct pci_driver mptsas_driver = {
1359 .name = "mptsas",
1360 .id_table = mptsas_pci_table,
1361 .probe = mptsas_probe,
1362 .remove = __devexit_p(mptsas_remove),
1363 .shutdown = mptscsih_shutdown,
1364#ifdef CONFIG_PM
1365 .suspend = mptscsih_suspend,
1366 .resume = mptscsih_resume,
1367#endif
1368};
1369
1370static int __init
1371mptsas_init(void)
1372{
1373 show_mptmod_ver(my_NAME, my_VERSION);
1374
1375 mptsas_transport_template =
1376 sas_attach_transport(&mptsas_transport_functions);
1377 if (!mptsas_transport_template)
1378 return -ENODEV;
1379
1380 mptsasDoneCtx = mpt_register(mptscsih_io_done, MPTSAS_DRIVER);
1381 mptsasTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSAS_DRIVER);
1382 mptsasInternalCtx =
1383 mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER);
Christoph Hellwigda4fa652005-10-19 20:01:42 +02001384 mptsasMgmtCtx = mpt_register(mptsas_mgmt_done, MPTSAS_DRIVER);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001385
1386 if (mpt_event_register(mptsasDoneCtx, mptscsih_event_process) == 0) {
1387 devtprintk((KERN_INFO MYNAM
1388 ": Registered for IOC event notifications\n"));
1389 }
1390
1391 if (mpt_reset_register(mptsasDoneCtx, mptscsih_ioc_reset) == 0) {
1392 dprintk((KERN_INFO MYNAM
1393 ": Registered for IOC reset notifications\n"));
1394 }
1395
1396 return pci_register_driver(&mptsas_driver);
1397}
1398
1399static void __exit
1400mptsas_exit(void)
1401{
1402 pci_unregister_driver(&mptsas_driver);
1403 sas_release_transport(mptsas_transport_template);
1404
1405 mpt_reset_deregister(mptsasDoneCtx);
1406 mpt_event_deregister(mptsasDoneCtx);
1407
Christoph Hellwigda4fa652005-10-19 20:01:42 +02001408 mpt_deregister(mptsasMgmtCtx);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001409 mpt_deregister(mptsasInternalCtx);
1410 mpt_deregister(mptsasTaskCtx);
1411 mpt_deregister(mptsasDoneCtx);
1412}
1413
1414module_init(mptsas_init);
1415module_exit(mptsas_exit);