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