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