blob: e0a8bb8ba7d8f15bfdd3214a63f035884295129b [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 = {
280 .proc_name = "mptsas",
281 .proc_info = mptscsih_proc_info,
282 .name = "MPT SPI Host",
283 .info = mptscsih_info,
284 .queuecommand = mptscsih_qcmd,
285 .slave_alloc = mptsas_slave_alloc,
286 .slave_configure = mptscsih_slave_configure,
287 .slave_destroy = mptscsih_slave_destroy,
288 .change_queue_depth = mptscsih_change_queue_depth,
289 .eh_abort_handler = mptscsih_abort,
290 .eh_device_reset_handler = mptscsih_dev_reset,
291 .eh_bus_reset_handler = mptscsih_bus_reset,
292 .eh_host_reset_handler = mptscsih_host_reset,
293 .bios_param = mptscsih_bios_param,
294 .can_queue = MPT_FC_CAN_QUEUE,
295 .this_id = -1,
296 .sg_tablesize = MPT_SCSI_SG_DEPTH,
297 .max_sectors = 8192,
298 .cmd_per_lun = 7,
299 .use_clustering = ENABLE_CLUSTERING,
300};
301
Christoph Hellwigb5141122005-10-28 22:07:41 +0200302static inline MPT_ADAPTER *phy_to_ioc(struct sas_phy *phy)
303{
304 struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
305 return ((MPT_SCSI_HOST *)shost->hostdata)->ioc;
306}
307
308static int mptsas_get_linkerrors(struct sas_phy *phy)
309{
310 MPT_ADAPTER *ioc = phy_to_ioc(phy);
311 ConfigExtendedPageHeader_t hdr;
312 CONFIGPARMS cfg;
313 SasPhyPage1_t *buffer;
314 dma_addr_t dma_handle;
315 int error;
316
317 hdr.PageVersion = MPI_SASPHY1_PAGEVERSION;
318 hdr.ExtPageLength = 0;
319 hdr.PageNumber = 1 /* page number 1*/;
320 hdr.Reserved1 = 0;
321 hdr.Reserved2 = 0;
322 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
323 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
324
325 cfg.cfghdr.ehdr = &hdr;
326 cfg.physAddr = -1;
327 cfg.pageAddr = phy->identify.phy_identifier;
328 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
329 cfg.dir = 0; /* read */
330 cfg.timeout = 10;
331
332 error = mpt_config(ioc, &cfg);
333 if (error)
334 return error;
335 if (!hdr.ExtPageLength)
336 return -ENXIO;
337
338 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
339 &dma_handle);
340 if (!buffer)
341 return -ENOMEM;
342
343 cfg.physAddr = dma_handle;
344 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
345
346 error = mpt_config(ioc, &cfg);
347 if (error)
348 goto out_free_consistent;
349
350 mptsas_print_phy_pg1(buffer);
351
352 phy->invalid_dword_count = le32_to_cpu(buffer->InvalidDwordCount);
353 phy->running_disparity_error_count =
354 le32_to_cpu(buffer->RunningDisparityErrorCount);
355 phy->loss_of_dword_sync_count =
356 le32_to_cpu(buffer->LossDwordSynchCount);
357 phy->phy_reset_problem_count =
358 le32_to_cpu(buffer->PhyResetProblemCount);
359
360 out_free_consistent:
361 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
362 buffer, dma_handle);
363 return error;
364}
365
Christoph Hellwigda4fa652005-10-19 20:01:42 +0200366static int mptsas_mgmt_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req,
367 MPT_FRAME_HDR *reply)
368{
369 ioc->sas_mgmt.status |= MPT_SAS_MGMT_STATUS_COMMAND_GOOD;
370 if (reply != NULL) {
371 ioc->sas_mgmt.status |= MPT_SAS_MGMT_STATUS_RF_VALID;
372 memcpy(ioc->sas_mgmt.reply, reply,
373 min(ioc->reply_sz, 4 * reply->u.reply.MsgLength));
374 }
375 complete(&ioc->sas_mgmt.done);
376 return 1;
377}
378
379static int mptsas_phy_reset(struct sas_phy *phy, int hard_reset)
380{
381 MPT_ADAPTER *ioc = phy_to_ioc(phy);
382 SasIoUnitControlRequest_t *req;
383 SasIoUnitControlReply_t *reply;
384 MPT_FRAME_HDR *mf;
385 MPIHeader_t *hdr;
386 unsigned long timeleft;
387 int error = -ERESTARTSYS;
388
389 /* not implemented for expanders */
390 if (phy->identify.target_port_protocols & SAS_PROTOCOL_SMP)
391 return -ENXIO;
392
393 if (down_interruptible(&ioc->sas_mgmt.mutex))
394 goto out;
395
396 mf = mpt_get_msg_frame(mptsasMgmtCtx, ioc);
397 if (!mf) {
398 error = -ENOMEM;
399 goto out_unlock;
400 }
401
402 hdr = (MPIHeader_t *) mf;
403 req = (SasIoUnitControlRequest_t *)mf;
404 memset(req, 0, sizeof(SasIoUnitControlRequest_t));
405 req->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL;
406 req->MsgContext = hdr->MsgContext;
407 req->Operation = hard_reset ?
408 MPI_SAS_OP_PHY_HARD_RESET : MPI_SAS_OP_PHY_LINK_RESET;
409 req->PhyNum = phy->identify.phy_identifier;
410
411 mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf);
412
413 timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done,
414 10 * HZ);
415 if (!timeleft) {
416 /* On timeout reset the board */
417 mpt_free_msg_frame(ioc, mf);
418 mpt_HardResetHandler(ioc, CAN_SLEEP);
419 error = -ETIMEDOUT;
420 goto out_unlock;
421 }
422
423 /* a reply frame is expected */
424 if ((ioc->sas_mgmt.status &
425 MPT_IOCTL_STATUS_RF_VALID) == 0) {
426 error = -ENXIO;
427 goto out_unlock;
428 }
429
430 /* process the completed Reply Message Frame */
431 reply = (SasIoUnitControlReply_t *)ioc->sas_mgmt.reply;
432 if (reply->IOCStatus != MPI_IOCSTATUS_SUCCESS) {
433 printk("%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",
434 __FUNCTION__,
435 reply->IOCStatus,
436 reply->IOCLogInfo);
437 error = -ENXIO;
438 goto out_unlock;
439 }
440
441 error = 0;
442
443 out_unlock:
444 up(&ioc->sas_mgmt.mutex);
445 out:
446 return error;
447}
Christoph Hellwigb5141122005-10-28 22:07:41 +0200448
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200449static struct sas_function_template mptsas_transport_functions = {
Christoph Hellwigb5141122005-10-28 22:07:41 +0200450 .get_linkerrors = mptsas_get_linkerrors,
Christoph Hellwigda4fa652005-10-19 20:01:42 +0200451 .phy_reset = mptsas_phy_reset,
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200452};
453
454static struct scsi_transport_template *mptsas_transport_template;
455
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200456static int
457mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
458{
459 ConfigExtendedPageHeader_t hdr;
460 CONFIGPARMS cfg;
461 SasIOUnitPage0_t *buffer;
462 dma_addr_t dma_handle;
463 int error, i;
464
465 hdr.PageVersion = MPI_SASIOUNITPAGE0_PAGEVERSION;
466 hdr.ExtPageLength = 0;
467 hdr.PageNumber = 0;
468 hdr.Reserved1 = 0;
469 hdr.Reserved2 = 0;
470 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
471 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
472
473 cfg.cfghdr.ehdr = &hdr;
474 cfg.physAddr = -1;
475 cfg.pageAddr = 0;
476 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
477 cfg.dir = 0; /* read */
478 cfg.timeout = 10;
479
480 error = mpt_config(ioc, &cfg);
481 if (error)
482 goto out;
483 if (!hdr.ExtPageLength) {
484 error = -ENXIO;
485 goto out;
486 }
487
488 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
489 &dma_handle);
490 if (!buffer) {
491 error = -ENOMEM;
492 goto out;
493 }
494
495 cfg.physAddr = dma_handle;
496 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
497
498 error = mpt_config(ioc, &cfg);
499 if (error)
500 goto out_free_consistent;
501
502 port_info->num_phys = buffer->NumPhys;
503 port_info->phy_info = kcalloc(port_info->num_phys,
504 sizeof(struct mptsas_phyinfo),GFP_KERNEL);
505 if (!port_info->phy_info) {
506 error = -ENOMEM;
507 goto out_free_consistent;
508 }
509
510 for (i = 0; i < port_info->num_phys; i++) {
511 mptsas_print_phy_data(&buffer->PhyData[i]);
512 port_info->phy_info[i].phy_id = i;
513 port_info->phy_info[i].port_id =
514 buffer->PhyData[i].Port;
515 port_info->phy_info[i].negotiated_link_rate =
516 buffer->PhyData[i].NegotiatedLinkRate;
517 }
518
519 out_free_consistent:
520 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
521 buffer, dma_handle);
522 out:
523 return error;
524}
525
526static int
527mptsas_sas_phy_pg0(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
528 u32 form, u32 form_specific)
529{
530 ConfigExtendedPageHeader_t hdr;
531 CONFIGPARMS cfg;
532 SasPhyPage0_t *buffer;
533 dma_addr_t dma_handle;
534 int error;
535
536 hdr.PageVersion = MPI_SASPHY0_PAGEVERSION;
537 hdr.ExtPageLength = 0;
538 hdr.PageNumber = 0;
539 hdr.Reserved1 = 0;
540 hdr.Reserved2 = 0;
541 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
542 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
543
544 cfg.cfghdr.ehdr = &hdr;
545 cfg.dir = 0; /* read */
546 cfg.timeout = 10;
547
548 /* Get Phy Pg 0 for each Phy. */
549 cfg.physAddr = -1;
550 cfg.pageAddr = form + form_specific;
551 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
552
553 error = mpt_config(ioc, &cfg);
554 if (error)
555 goto out;
556
557 if (!hdr.ExtPageLength) {
558 error = -ENXIO;
559 goto out;
560 }
561
562 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
563 &dma_handle);
564 if (!buffer) {
565 error = -ENOMEM;
566 goto out;
567 }
568
569 cfg.physAddr = dma_handle;
570 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
571
572 error = mpt_config(ioc, &cfg);
573 if (error)
574 goto out_free_consistent;
575
576 mptsas_print_phy_pg0(buffer);
577
578 phy_info->hw_link_rate = buffer->HwLinkRate;
579 phy_info->programmed_link_rate = buffer->ProgrammedLinkRate;
580 phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle);
581 phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle);
582
583 out_free_consistent:
584 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
585 buffer, dma_handle);
586 out:
587 return error;
588}
589
590static int
591mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info,
592 u32 form, u32 form_specific)
593{
594 ConfigExtendedPageHeader_t hdr;
595 CONFIGPARMS cfg;
596 SasDevicePage0_t *buffer;
597 dma_addr_t dma_handle;
598 __le64 sas_address;
599 int error;
600
601 hdr.PageVersion = MPI_SASDEVICE0_PAGEVERSION;
602 hdr.ExtPageLength = 0;
603 hdr.PageNumber = 0;
604 hdr.Reserved1 = 0;
605 hdr.Reserved2 = 0;
606 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
607 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE;
608
609 cfg.cfghdr.ehdr = &hdr;
610 cfg.pageAddr = form + form_specific;
611 cfg.physAddr = -1;
612 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
613 cfg.dir = 0; /* read */
614 cfg.timeout = 10;
615
616 error = mpt_config(ioc, &cfg);
617 if (error)
618 goto out;
619 if (!hdr.ExtPageLength) {
620 error = -ENXIO;
621 goto out;
622 }
623
624 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
625 &dma_handle);
626 if (!buffer) {
627 error = -ENOMEM;
628 goto out;
629 }
630
631 cfg.physAddr = dma_handle;
632 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
633
634 error = mpt_config(ioc, &cfg);
635 if (error)
636 goto out_free_consistent;
637
638 mptsas_print_device_pg0(buffer);
639
640 device_info->handle = le16_to_cpu(buffer->DevHandle);
641 device_info->phy_id = buffer->PhyNum;
642 device_info->port_id = buffer->PhysicalPort;
643 device_info->target = buffer->TargetID;
644 device_info->bus = buffer->Bus;
645 memcpy(&sas_address, &buffer->SASAddress, sizeof(__le64));
646 device_info->sas_address = le64_to_cpu(sas_address);
647 device_info->device_info =
648 le32_to_cpu(buffer->DeviceInfo);
649
650 out_free_consistent:
651 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
652 buffer, dma_handle);
653 out:
654 return error;
655}
656
657static int
658mptsas_sas_expander_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info,
659 u32 form, u32 form_specific)
660{
661 ConfigExtendedPageHeader_t hdr;
662 CONFIGPARMS cfg;
663 SasExpanderPage0_t *buffer;
664 dma_addr_t dma_handle;
665 int error;
666
667 hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION;
668 hdr.ExtPageLength = 0;
669 hdr.PageNumber = 0;
670 hdr.Reserved1 = 0;
671 hdr.Reserved2 = 0;
672 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
673 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
674
675 cfg.cfghdr.ehdr = &hdr;
676 cfg.physAddr = -1;
677 cfg.pageAddr = form + form_specific;
678 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
679 cfg.dir = 0; /* read */
680 cfg.timeout = 10;
681
682 error = mpt_config(ioc, &cfg);
683 if (error)
684 goto out;
685
686 if (!hdr.ExtPageLength) {
687 error = -ENXIO;
688 goto out;
689 }
690
691 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
692 &dma_handle);
693 if (!buffer) {
694 error = -ENOMEM;
695 goto out;
696 }
697
698 cfg.physAddr = dma_handle;
699 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
700
701 error = mpt_config(ioc, &cfg);
702 if (error)
703 goto out_free_consistent;
704
705 /* save config data */
706 port_info->num_phys = buffer->NumPhys;
707 port_info->handle = le16_to_cpu(buffer->DevHandle);
708 port_info->phy_info = kcalloc(port_info->num_phys,
709 sizeof(struct mptsas_phyinfo),GFP_KERNEL);
710 if (!port_info->phy_info) {
711 error = -ENOMEM;
712 goto out_free_consistent;
713 }
714
715 out_free_consistent:
716 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
717 buffer, dma_handle);
718 out:
719 return error;
720}
721
722static int
723mptsas_sas_expander_pg1(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
724 u32 form, u32 form_specific)
725{
726 ConfigExtendedPageHeader_t hdr;
727 CONFIGPARMS cfg;
728 SasExpanderPage1_t *buffer;
729 dma_addr_t dma_handle;
730 int error;
731
732 hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION;
733 hdr.ExtPageLength = 0;
734 hdr.PageNumber = 1;
735 hdr.Reserved1 = 0;
736 hdr.Reserved2 = 0;
737 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
738 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
739
740 cfg.cfghdr.ehdr = &hdr;
741 cfg.physAddr = -1;
742 cfg.pageAddr = form + form_specific;
743 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
744 cfg.dir = 0; /* read */
745 cfg.timeout = 10;
746
747 error = mpt_config(ioc, &cfg);
748 if (error)
749 goto out;
750
751 if (!hdr.ExtPageLength) {
752 error = -ENXIO;
753 goto out;
754 }
755
756 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
757 &dma_handle);
758 if (!buffer) {
759 error = -ENOMEM;
760 goto out;
761 }
762
763 cfg.physAddr = dma_handle;
764 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
765
766 error = mpt_config(ioc, &cfg);
767 if (error)
768 goto out_free_consistent;
769
770
771 mptsas_print_expander_pg1(buffer);
772
773 /* save config data */
Eric Moore024358e2005-10-21 20:56:36 +0200774 phy_info->phy_id = buffer->PhyIdentifier;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200775 phy_info->port_id = buffer->PhysicalPort;
776 phy_info->negotiated_link_rate = buffer->NegotiatedLinkRate;
777 phy_info->programmed_link_rate = buffer->ProgrammedLinkRate;
778 phy_info->hw_link_rate = buffer->HwLinkRate;
779 phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle);
780 phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle);
781
782
783 out_free_consistent:
784 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
785 buffer, dma_handle);
786 out:
787 return error;
788}
789
790static void
791mptsas_parse_device_info(struct sas_identify *identify,
792 struct mptsas_devinfo *device_info)
793{
794 u16 protocols;
795
796 identify->sas_address = device_info->sas_address;
797 identify->phy_identifier = device_info->phy_id;
798
799 /*
800 * Fill in Phy Initiator Port Protocol.
801 * Bits 6:3, more than one bit can be set, fall through cases.
802 */
803 protocols = device_info->device_info & 0x78;
804 identify->initiator_port_protocols = 0;
805 if (protocols & MPI_SAS_DEVICE_INFO_SSP_INITIATOR)
806 identify->initiator_port_protocols |= SAS_PROTOCOL_SSP;
807 if (protocols & MPI_SAS_DEVICE_INFO_STP_INITIATOR)
808 identify->initiator_port_protocols |= SAS_PROTOCOL_STP;
809 if (protocols & MPI_SAS_DEVICE_INFO_SMP_INITIATOR)
810 identify->initiator_port_protocols |= SAS_PROTOCOL_SMP;
811 if (protocols & MPI_SAS_DEVICE_INFO_SATA_HOST)
812 identify->initiator_port_protocols |= SAS_PROTOCOL_SATA;
813
814 /*
815 * Fill in Phy Target Port Protocol.
816 * Bits 10:7, more than one bit can be set, fall through cases.
817 */
818 protocols = device_info->device_info & 0x780;
819 identify->target_port_protocols = 0;
820 if (protocols & MPI_SAS_DEVICE_INFO_SSP_TARGET)
821 identify->target_port_protocols |= SAS_PROTOCOL_SSP;
822 if (protocols & MPI_SAS_DEVICE_INFO_STP_TARGET)
823 identify->target_port_protocols |= SAS_PROTOCOL_STP;
824 if (protocols & MPI_SAS_DEVICE_INFO_SMP_TARGET)
825 identify->target_port_protocols |= SAS_PROTOCOL_SMP;
826 if (protocols & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
827 identify->target_port_protocols |= SAS_PROTOCOL_SATA;
828
829 /*
830 * Fill in Attached device type.
831 */
832 switch (device_info->device_info &
833 MPI_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) {
834 case MPI_SAS_DEVICE_INFO_NO_DEVICE:
835 identify->device_type = SAS_PHY_UNUSED;
836 break;
837 case MPI_SAS_DEVICE_INFO_END_DEVICE:
838 identify->device_type = SAS_END_DEVICE;
839 break;
840 case MPI_SAS_DEVICE_INFO_EDGE_EXPANDER:
841 identify->device_type = SAS_EDGE_EXPANDER_DEVICE;
842 break;
843 case MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER:
844 identify->device_type = SAS_FANOUT_EXPANDER_DEVICE;
845 break;
846 }
847}
848
849static int mptsas_probe_one_phy(struct device *dev,
Christoph Hellwigac01bbb2005-10-19 20:01:17 +0200850 struct mptsas_phyinfo *phy_info, int index, int local)
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200851{
852 struct sas_phy *port;
853 int error;
854
855 port = sas_phy_alloc(dev, index);
856 if (!port)
857 return -ENOMEM;
858
859 port->port_identifier = phy_info->port_id;
860 mptsas_parse_device_info(&port->identify, &phy_info->identify);
861
862 /*
863 * Set Negotiated link rate.
864 */
865 switch (phy_info->negotiated_link_rate) {
866 case MPI_SAS_IOUNIT0_RATE_PHY_DISABLED:
867 port->negotiated_linkrate = SAS_PHY_DISABLED;
868 break;
869 case MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION:
870 port->negotiated_linkrate = SAS_LINK_RATE_FAILED;
871 break;
872 case MPI_SAS_IOUNIT0_RATE_1_5:
873 port->negotiated_linkrate = SAS_LINK_RATE_1_5_GBPS;
874 break;
875 case MPI_SAS_IOUNIT0_RATE_3_0:
876 port->negotiated_linkrate = SAS_LINK_RATE_3_0_GBPS;
877 break;
878 case MPI_SAS_IOUNIT0_RATE_SATA_OOB_COMPLETE:
879 case MPI_SAS_IOUNIT0_RATE_UNKNOWN:
880 default:
881 port->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN;
882 break;
883 }
884
885 /*
886 * Set Max hardware link rate.
887 */
888 switch (phy_info->hw_link_rate & MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
889 case MPI_SAS_PHY0_HWRATE_MAX_RATE_1_5:
890 port->maximum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
891 break;
892 case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
893 port->maximum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
894 break;
895 default:
896 break;
897 }
898
899 /*
900 * Set Max programmed link rate.
901 */
902 switch (phy_info->programmed_link_rate &
903 MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
904 case MPI_SAS_PHY0_PRATE_MAX_RATE_1_5:
905 port->maximum_linkrate = SAS_LINK_RATE_1_5_GBPS;
906 break;
907 case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
908 port->maximum_linkrate = SAS_LINK_RATE_3_0_GBPS;
909 break;
910 default:
911 break;
912 }
913
914 /*
915 * Set Min hardware link rate.
916 */
917 switch (phy_info->hw_link_rate & MPI_SAS_PHY0_HWRATE_MIN_RATE_MASK) {
918 case MPI_SAS_PHY0_HWRATE_MIN_RATE_1_5:
919 port->minimum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
920 break;
921 case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
922 port->minimum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
923 break;
924 default:
925 break;
926 }
927
928 /*
929 * Set Min programmed link rate.
930 */
931 switch (phy_info->programmed_link_rate &
932 MPI_SAS_PHY0_PRATE_MIN_RATE_MASK) {
933 case MPI_SAS_PHY0_PRATE_MIN_RATE_1_5:
934 port->minimum_linkrate = SAS_LINK_RATE_1_5_GBPS;
935 break;
936 case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
937 port->minimum_linkrate = SAS_LINK_RATE_3_0_GBPS;
938 break;
939 default:
940 break;
941 }
942
Christoph Hellwigac01bbb2005-10-19 20:01:17 +0200943 if (local)
944 port->local_attached = 1;
945
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200946 error = sas_phy_add(port);
947 if (error) {
948 sas_phy_free(port);
949 return error;
950 }
951
952 if (phy_info->attached.handle) {
953 struct sas_rphy *rphy;
954
955 rphy = sas_rphy_alloc(port);
956 if (!rphy)
957 return 0; /* non-fatal: an rphy can be added later */
958
959 mptsas_parse_device_info(&rphy->identify, &phy_info->attached);
960 error = sas_rphy_add(rphy);
961 if (error) {
962 sas_rphy_free(rphy);
963 return error;
964 }
965
966 phy_info->rphy = rphy;
967 }
968
969 return 0;
970}
971
972static int
973mptsas_probe_hba_phys(MPT_ADAPTER *ioc, int *index)
974{
975 struct mptsas_portinfo *port_info;
976 u32 handle = 0xFFFF;
977 int error = -ENOMEM, i;
978
979 port_info = kmalloc(sizeof(*port_info), GFP_KERNEL);
980 if (!port_info)
981 goto out;
982 memset(port_info, 0, sizeof(*port_info));
983
984 error = mptsas_sas_io_unit_pg0(ioc, port_info);
985 if (error)
986 goto out_free_port_info;
987
988 list_add_tail(&port_info->list, &ioc->sas_topology);
989
990 for (i = 0; i < port_info->num_phys; i++) {
991 mptsas_sas_phy_pg0(ioc, &port_info->phy_info[i],
992 (MPI_SAS_PHY_PGAD_FORM_PHY_NUMBER <<
993 MPI_SAS_PHY_PGAD_FORM_SHIFT), i);
994
995 mptsas_sas_device_pg0(ioc, &port_info->phy_info[i].identify,
996 (MPI_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE <<
997 MPI_SAS_DEVICE_PGAD_FORM_SHIFT), handle);
Eric Moore024358e2005-10-21 20:56:36 +0200998 port_info->phy_info[i].identify.phy_id =
999 port_info->phy_info[i].phy_id;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001000 handle = port_info->phy_info[i].identify.handle;
1001
1002 if (port_info->phy_info[i].attached.handle) {
1003 mptsas_sas_device_pg0(ioc,
1004 &port_info->phy_info[i].attached,
1005 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
1006 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
1007 port_info->phy_info[i].attached.handle);
1008 }
1009
1010 mptsas_probe_one_phy(&ioc->sh->shost_gendev,
Christoph Hellwigac01bbb2005-10-19 20:01:17 +02001011 &port_info->phy_info[i], *index, 1);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001012 (*index)++;
1013 }
1014
1015 return 0;
1016
1017 out_free_port_info:
1018 kfree(port_info);
1019 out:
1020 return error;
1021}
1022
1023static int
1024mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle, int *index)
1025{
1026 struct mptsas_portinfo *port_info, *p;
1027 int error = -ENOMEM, i, j;
1028
1029 port_info = kmalloc(sizeof(*port_info), GFP_KERNEL);
1030 if (!port_info)
1031 goto out;
1032 memset(port_info, 0, sizeof(*port_info));
1033
1034 error = mptsas_sas_expander_pg0(ioc, port_info,
1035 (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE <<
1036 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), *handle);
1037 if (error)
1038 goto out_free_port_info;
1039
1040 *handle = port_info->handle;
1041
1042 list_add_tail(&port_info->list, &ioc->sas_topology);
1043 for (i = 0; i < port_info->num_phys; i++) {
1044 struct device *parent;
1045
1046 mptsas_sas_expander_pg1(ioc, &port_info->phy_info[i],
1047 (MPI_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM <<
1048 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), (i << 16) + *handle);
1049
1050 if (port_info->phy_info[i].identify.handle) {
1051 mptsas_sas_device_pg0(ioc,
1052 &port_info->phy_info[i].identify,
1053 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
1054 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
1055 port_info->phy_info[i].identify.handle);
Eric Moore024358e2005-10-21 20:56:36 +02001056 port_info->phy_info[i].identify.phy_id =
1057 port_info->phy_info[i].phy_id;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001058 }
1059
1060 if (port_info->phy_info[i].attached.handle) {
1061 mptsas_sas_device_pg0(ioc,
1062 &port_info->phy_info[i].attached,
1063 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
1064 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
1065 port_info->phy_info[i].attached.handle);
1066 }
1067
1068 /*
1069 * If we find a parent port handle this expander is
1070 * attached to another expander, else it hangs of the
1071 * HBA phys.
1072 */
1073 parent = &ioc->sh->shost_gendev;
1074 list_for_each_entry(p, &ioc->sas_topology, list) {
1075 for (j = 0; j < p->num_phys; j++) {
1076 if (port_info->phy_info[i].identify.handle ==
1077 p->phy_info[j].attached.handle)
1078 parent = &p->phy_info[j].rphy->dev;
1079 }
1080 }
1081
Christoph Hellwigac01bbb2005-10-19 20:01:17 +02001082 mptsas_probe_one_phy(parent, &port_info->phy_info[i],
1083 *index, 0);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001084 (*index)++;
1085 }
1086
1087 return 0;
1088
1089 out_free_port_info:
1090 kfree(port_info);
1091 out:
1092 return error;
1093}
1094
1095static void
1096mptsas_scan_sas_topology(MPT_ADAPTER *ioc)
1097{
1098 u32 handle = 0xFFFF;
1099 int index = 0;
1100
1101 mptsas_probe_hba_phys(ioc, &index);
1102 while (!mptsas_probe_expander_phys(ioc, &handle, &index))
1103 ;
1104}
1105
1106static int
1107mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
1108{
1109 struct Scsi_Host *sh;
1110 MPT_SCSI_HOST *hd;
1111 MPT_ADAPTER *ioc;
1112 unsigned long flags;
1113 int sz, ii;
1114 int numSGE = 0;
1115 int scale;
1116 int ioc_cap;
1117 u8 *mem;
1118 int error=0;
1119 int r;
1120
1121 r = mpt_attach(pdev,id);
1122 if (r)
1123 return r;
1124
1125 ioc = pci_get_drvdata(pdev);
1126 ioc->DoneCtx = mptsasDoneCtx;
1127 ioc->TaskCtx = mptsasTaskCtx;
1128 ioc->InternalCtx = mptsasInternalCtx;
1129
1130 /* Added sanity check on readiness of the MPT adapter.
1131 */
1132 if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
1133 printk(MYIOC_s_WARN_FMT
1134 "Skipping because it's not operational!\n",
1135 ioc->name);
1136 return -ENODEV;
1137 }
1138
1139 if (!ioc->active) {
1140 printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
1141 ioc->name);
1142 return -ENODEV;
1143 }
1144
1145 /* Sanity check - ensure at least 1 port is INITIATOR capable
1146 */
1147 ioc_cap = 0;
1148 for (ii = 0; ii < ioc->facts.NumberOfPorts; ii++) {
1149 if (ioc->pfacts[ii].ProtocolFlags &
1150 MPI_PORTFACTS_PROTOCOL_INITIATOR)
1151 ioc_cap++;
1152 }
1153
1154 if (!ioc_cap) {
1155 printk(MYIOC_s_WARN_FMT
1156 "Skipping ioc=%p because SCSI Initiator mode "
1157 "is NOT enabled!\n", ioc->name, ioc);
Moore, Eric Dean466544d2005-09-14 18:09:10 -06001158 return 0;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001159 }
1160
1161 sh = scsi_host_alloc(&mptsas_driver_template, sizeof(MPT_SCSI_HOST));
1162 if (!sh) {
1163 printk(MYIOC_s_WARN_FMT
1164 "Unable to register controller with SCSI subsystem\n",
1165 ioc->name);
1166 return -1;
1167 }
1168
1169 spin_lock_irqsave(&ioc->FreeQlock, flags);
1170
1171 /* Attach the SCSI Host to the IOC structure
1172 */
1173 ioc->sh = sh;
1174
1175 sh->io_port = 0;
1176 sh->n_io_port = 0;
1177 sh->irq = 0;
1178
1179 /* set 16 byte cdb's */
1180 sh->max_cmd_len = 16;
1181
1182 sh->max_id = ioc->pfacts->MaxDevices + 1;
1183
1184 sh->transportt = mptsas_transport_template;
1185
1186 sh->max_lun = MPT_LAST_LUN + 1;
1187 sh->max_channel = 0;
1188 sh->this_id = ioc->pfacts[0].PortSCSIID;
1189
1190 /* Required entry.
1191 */
1192 sh->unique_id = ioc->id;
1193
1194 INIT_LIST_HEAD(&ioc->sas_topology);
Christoph Hellwigda4fa652005-10-19 20:01:42 +02001195 init_MUTEX(&ioc->sas_mgmt.mutex);
1196 init_completion(&ioc->sas_mgmt.done);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001197
1198 /* Verify that we won't exceed the maximum
1199 * number of chain buffers
1200 * We can optimize: ZZ = req_sz/sizeof(SGE)
1201 * For 32bit SGE's:
1202 * numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
1203 * + (req_sz - 64)/sizeof(SGE)
1204 * A slightly different algorithm is required for
1205 * 64bit SGEs.
1206 */
1207 scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
1208 if (sizeof(dma_addr_t) == sizeof(u64)) {
1209 numSGE = (scale - 1) *
1210 (ioc->facts.MaxChainDepth-1) + scale +
1211 (ioc->req_sz - 60) / (sizeof(dma_addr_t) +
1212 sizeof(u32));
1213 } else {
1214 numSGE = 1 + (scale - 1) *
1215 (ioc->facts.MaxChainDepth-1) + scale +
1216 (ioc->req_sz - 64) / (sizeof(dma_addr_t) +
1217 sizeof(u32));
1218 }
1219
1220 if (numSGE < sh->sg_tablesize) {
1221 /* Reset this value */
1222 dprintk((MYIOC_s_INFO_FMT
1223 "Resetting sg_tablesize to %d from %d\n",
1224 ioc->name, numSGE, sh->sg_tablesize));
1225 sh->sg_tablesize = numSGE;
1226 }
1227
1228 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
1229
1230 hd = (MPT_SCSI_HOST *) sh->hostdata;
1231 hd->ioc = ioc;
1232
1233 /* SCSI needs scsi_cmnd lookup table!
1234 * (with size equal to req_depth*PtrSz!)
1235 */
1236 sz = ioc->req_depth * sizeof(void *);
1237 mem = kmalloc(sz, GFP_ATOMIC);
1238 if (mem == NULL) {
1239 error = -ENOMEM;
1240 goto mptsas_probe_failed;
1241 }
1242
1243 memset(mem, 0, sz);
1244 hd->ScsiLookup = (struct scsi_cmnd **) mem;
1245
1246 dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n",
1247 ioc->name, hd->ScsiLookup, sz));
1248
1249 /* Allocate memory for the device structures.
1250 * A non-Null pointer at an offset
1251 * indicates a device exists.
1252 * max_id = 1 + maximum id (hosts.h)
1253 */
1254 sz = sh->max_id * sizeof(void *);
1255 mem = kmalloc(sz, GFP_ATOMIC);
1256 if (mem == NULL) {
1257 error = -ENOMEM;
1258 goto mptsas_probe_failed;
1259 }
1260
1261 memset(mem, 0, sz);
1262 hd->Targets = (VirtDevice **) mem;
1263
1264 dprintk((KERN_INFO
1265 " Targets @ %p, sz=%d\n", hd->Targets, sz));
1266
1267 /* Clear the TM flags
1268 */
1269 hd->tmPending = 0;
1270 hd->tmState = TM_STATE_NONE;
1271 hd->resetPending = 0;
1272 hd->abortSCpnt = NULL;
1273
1274 /* Clear the pointer used to store
1275 * single-threaded commands, i.e., those
1276 * issued during a bus scan, dv and
1277 * configuration pages.
1278 */
1279 hd->cmdPtr = NULL;
1280
1281 /* Initialize this SCSI Hosts' timers
1282 * To use, set the timer expires field
1283 * and add_timer
1284 */
1285 init_timer(&hd->timer);
1286 hd->timer.data = (unsigned long) hd;
1287 hd->timer.function = mptscsih_timer_expired;
1288
1289 hd->mpt_pq_filter = mpt_pq_filter;
1290 ioc->sas_data.ptClear = mpt_pt_clear;
1291
1292 if (ioc->sas_data.ptClear==1) {
1293 mptbase_sas_persist_operation(
1294 ioc, MPI_SAS_OP_CLEAR_ALL_PERSISTENT);
1295 }
1296
1297 ddvprintk((MYIOC_s_INFO_FMT
1298 "mpt_pq_filter %x mpt_pq_filter %x\n",
1299 ioc->name,
1300 mpt_pq_filter,
1301 mpt_pq_filter));
1302
1303 init_waitqueue_head(&hd->scandv_waitq);
1304 hd->scandv_wait_done = 0;
1305 hd->last_queue_full = 0;
1306
1307 error = scsi_add_host(sh, &ioc->pcidev->dev);
1308 if (error) {
1309 dprintk((KERN_ERR MYNAM
1310 "scsi_add_host failed\n"));
1311 goto mptsas_probe_failed;
1312 }
1313
1314 mptsas_scan_sas_topology(ioc);
1315
1316 return 0;
1317
1318mptsas_probe_failed:
1319
1320 mptscsih_remove(pdev);
1321 return error;
1322}
1323
1324static void __devexit mptsas_remove(struct pci_dev *pdev)
1325{
1326 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1327 struct mptsas_portinfo *p, *n;
1328
1329 sas_remove_host(ioc->sh);
1330
1331 list_for_each_entry_safe(p, n, &ioc->sas_topology, list) {
1332 list_del(&p->list);
1333 kfree(p);
1334 }
1335
1336 mptscsih_remove(pdev);
1337}
1338
1339static struct pci_device_id mptsas_pci_table[] = {
1340 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1064,
1341 PCI_ANY_ID, PCI_ANY_ID },
1342 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1066,
1343 PCI_ANY_ID, PCI_ANY_ID },
1344 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1068,
1345 PCI_ANY_ID, PCI_ANY_ID },
1346 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1064E,
1347 PCI_ANY_ID, PCI_ANY_ID },
1348 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1066E,
1349 PCI_ANY_ID, PCI_ANY_ID },
1350 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1068E,
1351 PCI_ANY_ID, PCI_ANY_ID },
1352 {0} /* Terminating entry */
1353};
1354MODULE_DEVICE_TABLE(pci, mptsas_pci_table);
1355
1356
1357static struct pci_driver mptsas_driver = {
1358 .name = "mptsas",
1359 .id_table = mptsas_pci_table,
1360 .probe = mptsas_probe,
1361 .remove = __devexit_p(mptsas_remove),
1362 .shutdown = mptscsih_shutdown,
1363#ifdef CONFIG_PM
1364 .suspend = mptscsih_suspend,
1365 .resume = mptscsih_resume,
1366#endif
1367};
1368
1369static int __init
1370mptsas_init(void)
1371{
1372 show_mptmod_ver(my_NAME, my_VERSION);
1373
1374 mptsas_transport_template =
1375 sas_attach_transport(&mptsas_transport_functions);
1376 if (!mptsas_transport_template)
1377 return -ENODEV;
1378
1379 mptsasDoneCtx = mpt_register(mptscsih_io_done, MPTSAS_DRIVER);
1380 mptsasTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSAS_DRIVER);
1381 mptsasInternalCtx =
1382 mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER);
Christoph Hellwigda4fa652005-10-19 20:01:42 +02001383 mptsasMgmtCtx = mpt_register(mptsas_mgmt_done, MPTSAS_DRIVER);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001384
1385 if (mpt_event_register(mptsasDoneCtx, mptscsih_event_process) == 0) {
1386 devtprintk((KERN_INFO MYNAM
1387 ": Registered for IOC event notifications\n"));
1388 }
1389
1390 if (mpt_reset_register(mptsasDoneCtx, mptscsih_ioc_reset) == 0) {
1391 dprintk((KERN_INFO MYNAM
1392 ": Registered for IOC reset notifications\n"));
1393 }
1394
1395 return pci_register_driver(&mptsas_driver);
1396}
1397
1398static void __exit
1399mptsas_exit(void)
1400{
1401 pci_unregister_driver(&mptsas_driver);
1402 sas_release_transport(mptsas_transport_template);
1403
1404 mpt_reset_deregister(mptsasDoneCtx);
1405 mpt_event_deregister(mptsasDoneCtx);
1406
Christoph Hellwigda4fa652005-10-19 20:01:42 +02001407 mpt_deregister(mptsasMgmtCtx);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001408 mpt_deregister(mptsasInternalCtx);
1409 mpt_deregister(mptsasTaskCtx);
1410 mpt_deregister(mptsasDoneCtx);
1411}
1412
1413module_init(mptsas_init);
1414module_exit(mptsas_exit);