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