0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045 #include <linux/module.h>
0046 #include <linux/kernel.h>
0047 #include <linux/init.h>
0048 #include <linux/errno.h>
0049 #include <linux/sched.h>
0050 #include <linux/workqueue.h>
0051 #include <linux/delay.h>
0052 #include <linux/pci.h>
0053
0054 #include <scsi/scsi.h>
0055 #include <scsi/scsi_cmnd.h>
0056 #include <scsi/scsi_device.h>
0057 #include <scsi/scsi_host.h>
0058 #include <scsi/scsi_transport_sas.h>
0059 #include <scsi/scsi_dbg.h>
0060
0061 #include "mpt3sas_base.h"
0062
0063
0064
0065
0066
0067
0068
0069 static inline u8
0070 _transport_get_port_id_by_sas_phy(struct sas_phy *phy)
0071 {
0072 u8 port_id = 0xFF;
0073 struct hba_port *port = phy->hostdata;
0074
0075 if (port)
0076 port_id = port->port_id;
0077
0078 return port_id;
0079 }
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091 static struct _sas_node *
0092 _transport_sas_node_find_by_sas_address(struct MPT3SAS_ADAPTER *ioc,
0093 u64 sas_address, struct hba_port *port)
0094 {
0095 if (ioc->sas_hba.sas_address == sas_address)
0096 return &ioc->sas_hba;
0097 else
0098 return mpt3sas_scsih_expander_find_by_sas_address(ioc,
0099 sas_address, port);
0100 }
0101
0102
0103
0104
0105
0106
0107
0108
0109 static u8
0110 _transport_get_port_id_by_rphy(struct MPT3SAS_ADAPTER *ioc,
0111 struct sas_rphy *rphy)
0112 {
0113 struct _sas_node *sas_expander;
0114 struct _sas_device *sas_device;
0115 unsigned long flags;
0116 u8 port_id = 0xFF;
0117
0118 if (!rphy)
0119 return port_id;
0120
0121 if (rphy->identify.device_type == SAS_EDGE_EXPANDER_DEVICE ||
0122 rphy->identify.device_type == SAS_FANOUT_EXPANDER_DEVICE) {
0123 spin_lock_irqsave(&ioc->sas_node_lock, flags);
0124 list_for_each_entry(sas_expander,
0125 &ioc->sas_expander_list, list) {
0126 if (sas_expander->rphy == rphy) {
0127 port_id = sas_expander->port->port_id;
0128 break;
0129 }
0130 }
0131 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
0132 } else if (rphy->identify.device_type == SAS_END_DEVICE) {
0133 spin_lock_irqsave(&ioc->sas_device_lock, flags);
0134 sas_device = __mpt3sas_get_sdev_by_rphy(ioc, rphy);
0135 if (sas_device) {
0136 port_id = sas_device->port->port_id;
0137 sas_device_put(sas_device);
0138 }
0139 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
0140 }
0141
0142 return port_id;
0143 }
0144
0145
0146
0147
0148
0149
0150
0151 static enum sas_linkrate
0152 _transport_convert_phy_link_rate(u8 link_rate)
0153 {
0154 enum sas_linkrate rc;
0155
0156 switch (link_rate) {
0157 case MPI2_SAS_NEG_LINK_RATE_1_5:
0158 rc = SAS_LINK_RATE_1_5_GBPS;
0159 break;
0160 case MPI2_SAS_NEG_LINK_RATE_3_0:
0161 rc = SAS_LINK_RATE_3_0_GBPS;
0162 break;
0163 case MPI2_SAS_NEG_LINK_RATE_6_0:
0164 rc = SAS_LINK_RATE_6_0_GBPS;
0165 break;
0166 case MPI25_SAS_NEG_LINK_RATE_12_0:
0167 rc = SAS_LINK_RATE_12_0_GBPS;
0168 break;
0169 case MPI2_SAS_NEG_LINK_RATE_PHY_DISABLED:
0170 rc = SAS_PHY_DISABLED;
0171 break;
0172 case MPI2_SAS_NEG_LINK_RATE_NEGOTIATION_FAILED:
0173 rc = SAS_LINK_RATE_FAILED;
0174 break;
0175 case MPI2_SAS_NEG_LINK_RATE_PORT_SELECTOR:
0176 rc = SAS_SATA_PORT_SELECTOR;
0177 break;
0178 case MPI2_SAS_NEG_LINK_RATE_SMP_RESET_IN_PROGRESS:
0179 rc = SAS_PHY_RESET_IN_PROGRESS;
0180 break;
0181
0182 default:
0183 case MPI2_SAS_NEG_LINK_RATE_SATA_OOB_COMPLETE:
0184 case MPI2_SAS_NEG_LINK_RATE_UNKNOWN_LINK_RATE:
0185 rc = SAS_LINK_RATE_UNKNOWN;
0186 break;
0187 }
0188 return rc;
0189 }
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201 static int
0202 _transport_set_identify(struct MPT3SAS_ADAPTER *ioc, u16 handle,
0203 struct sas_identify *identify)
0204 {
0205 Mpi2SasDevicePage0_t sas_device_pg0;
0206 Mpi2ConfigReply_t mpi_reply;
0207 u32 device_info;
0208 u32 ioc_status;
0209
0210 if (ioc->shost_recovery || ioc->pci_error_recovery) {
0211 ioc_info(ioc, "%s: host reset in progress!\n", __func__);
0212 return -EFAULT;
0213 }
0214
0215 if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
0216 MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) {
0217 ioc_err(ioc, "failure at %s:%d/%s()!\n",
0218 __FILE__, __LINE__, __func__);
0219 return -ENXIO;
0220 }
0221
0222 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
0223 MPI2_IOCSTATUS_MASK;
0224 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
0225 ioc_err(ioc, "handle(0x%04x), ioc_status(0x%04x) failure at %s:%d/%s()!\n",
0226 handle, ioc_status, __FILE__, __LINE__, __func__);
0227 return -EIO;
0228 }
0229
0230 memset(identify, 0, sizeof(struct sas_identify));
0231 device_info = le32_to_cpu(sas_device_pg0.DeviceInfo);
0232
0233
0234 identify->sas_address = le64_to_cpu(sas_device_pg0.SASAddress);
0235
0236
0237 identify->phy_identifier = sas_device_pg0.PhyNum;
0238
0239
0240 switch (device_info & MPI2_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) {
0241 case MPI2_SAS_DEVICE_INFO_NO_DEVICE:
0242 identify->device_type = SAS_PHY_UNUSED;
0243 break;
0244 case MPI2_SAS_DEVICE_INFO_END_DEVICE:
0245 identify->device_type = SAS_END_DEVICE;
0246 break;
0247 case MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER:
0248 identify->device_type = SAS_EDGE_EXPANDER_DEVICE;
0249 break;
0250 case MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER:
0251 identify->device_type = SAS_FANOUT_EXPANDER_DEVICE;
0252 break;
0253 }
0254
0255
0256 if (device_info & MPI2_SAS_DEVICE_INFO_SSP_INITIATOR)
0257 identify->initiator_port_protocols |= SAS_PROTOCOL_SSP;
0258 if (device_info & MPI2_SAS_DEVICE_INFO_STP_INITIATOR)
0259 identify->initiator_port_protocols |= SAS_PROTOCOL_STP;
0260 if (device_info & MPI2_SAS_DEVICE_INFO_SMP_INITIATOR)
0261 identify->initiator_port_protocols |= SAS_PROTOCOL_SMP;
0262 if (device_info & MPI2_SAS_DEVICE_INFO_SATA_HOST)
0263 identify->initiator_port_protocols |= SAS_PROTOCOL_SATA;
0264
0265
0266 if (device_info & MPI2_SAS_DEVICE_INFO_SSP_TARGET)
0267 identify->target_port_protocols |= SAS_PROTOCOL_SSP;
0268 if (device_info & MPI2_SAS_DEVICE_INFO_STP_TARGET)
0269 identify->target_port_protocols |= SAS_PROTOCOL_STP;
0270 if (device_info & MPI2_SAS_DEVICE_INFO_SMP_TARGET)
0271 identify->target_port_protocols |= SAS_PROTOCOL_SMP;
0272 if (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE)
0273 identify->target_port_protocols |= SAS_PROTOCOL_SATA;
0274
0275 return 0;
0276 }
0277
0278
0279
0280
0281
0282
0283
0284
0285
0286
0287
0288
0289
0290
0291 u8
0292 mpt3sas_transport_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
0293 u32 reply)
0294 {
0295 MPI2DefaultReply_t *mpi_reply;
0296
0297 mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply);
0298 if (ioc->transport_cmds.status == MPT3_CMD_NOT_USED)
0299 return 1;
0300 if (ioc->transport_cmds.smid != smid)
0301 return 1;
0302 ioc->transport_cmds.status |= MPT3_CMD_COMPLETE;
0303 if (mpi_reply) {
0304 memcpy(ioc->transport_cmds.reply, mpi_reply,
0305 mpi_reply->MsgLength*4);
0306 ioc->transport_cmds.status |= MPT3_CMD_REPLY_VALID;
0307 }
0308 ioc->transport_cmds.status &= ~MPT3_CMD_PENDING;
0309 complete(&ioc->transport_cmds.done);
0310 return 1;
0311 }
0312
0313
0314 struct rep_manu_request {
0315 u8 smp_frame_type;
0316 u8 function;
0317 u8 reserved;
0318 u8 request_length;
0319 };
0320
0321
0322 struct rep_manu_reply {
0323 u8 smp_frame_type;
0324 u8 function;
0325 u8 function_result;
0326 u8 response_length;
0327 u16 expander_change_count;
0328 u8 reserved0[2];
0329 u8 sas_format;
0330 u8 reserved2[3];
0331 u8 vendor_id[SAS_EXPANDER_VENDOR_ID_LEN];
0332 u8 product_id[SAS_EXPANDER_PRODUCT_ID_LEN];
0333 u8 product_rev[SAS_EXPANDER_PRODUCT_REV_LEN];
0334 u8 component_vendor_id[SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN];
0335 u16 component_id;
0336 u8 component_revision_id;
0337 u8 reserved3;
0338 u8 vendor_specific[8];
0339 };
0340
0341
0342
0343
0344
0345
0346
0347
0348
0349
0350
0351
0352 static int
0353 _transport_expander_report_manufacture(struct MPT3SAS_ADAPTER *ioc,
0354 u64 sas_address, struct sas_expander_device *edev, u8 port_id)
0355 {
0356 Mpi2SmpPassthroughRequest_t *mpi_request;
0357 Mpi2SmpPassthroughReply_t *mpi_reply;
0358 struct rep_manu_reply *manufacture_reply;
0359 struct rep_manu_request *manufacture_request;
0360 int rc;
0361 u16 smid;
0362 void *psge;
0363 u8 issue_reset = 0;
0364 void *data_out = NULL;
0365 dma_addr_t data_out_dma;
0366 dma_addr_t data_in_dma;
0367 size_t data_in_sz;
0368 size_t data_out_sz;
0369
0370 if (ioc->shost_recovery || ioc->pci_error_recovery) {
0371 ioc_info(ioc, "%s: host reset in progress!\n", __func__);
0372 return -EFAULT;
0373 }
0374
0375 mutex_lock(&ioc->transport_cmds.mutex);
0376
0377 if (ioc->transport_cmds.status != MPT3_CMD_NOT_USED) {
0378 ioc_err(ioc, "%s: transport_cmds in use\n", __func__);
0379 rc = -EAGAIN;
0380 goto out;
0381 }
0382 ioc->transport_cmds.status = MPT3_CMD_PENDING;
0383
0384 rc = mpt3sas_wait_for_ioc(ioc, IOC_OPERATIONAL_WAIT_COUNT);
0385 if (rc)
0386 goto out;
0387
0388 smid = mpt3sas_base_get_smid(ioc, ioc->transport_cb_idx);
0389 if (!smid) {
0390 ioc_err(ioc, "%s: failed obtaining a smid\n", __func__);
0391 rc = -EAGAIN;
0392 goto out;
0393 }
0394
0395 rc = 0;
0396 mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
0397 ioc->transport_cmds.smid = smid;
0398
0399 data_out_sz = sizeof(struct rep_manu_request);
0400 data_in_sz = sizeof(struct rep_manu_reply);
0401 data_out = dma_alloc_coherent(&ioc->pdev->dev, data_out_sz + data_in_sz,
0402 &data_out_dma, GFP_KERNEL);
0403 if (!data_out) {
0404 pr_err("failure at %s:%d/%s()!\n", __FILE__,
0405 __LINE__, __func__);
0406 rc = -ENOMEM;
0407 mpt3sas_base_free_smid(ioc, smid);
0408 goto out;
0409 }
0410
0411 data_in_dma = data_out_dma + sizeof(struct rep_manu_request);
0412
0413 manufacture_request = data_out;
0414 manufacture_request->smp_frame_type = 0x40;
0415 manufacture_request->function = 1;
0416 manufacture_request->reserved = 0;
0417 manufacture_request->request_length = 0;
0418
0419 memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t));
0420 mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
0421 mpi_request->PhysicalPort = port_id;
0422 mpi_request->SASAddress = cpu_to_le64(sas_address);
0423 mpi_request->RequestDataLength = cpu_to_le16(data_out_sz);
0424 psge = &mpi_request->SGL;
0425
0426 ioc->build_sg(ioc, psge, data_out_dma, data_out_sz, data_in_dma,
0427 data_in_sz);
0428
0429 dtransportprintk(ioc,
0430 ioc_info(ioc, "report_manufacture - send to sas_addr(0x%016llx)\n",
0431 (u64)sas_address));
0432 init_completion(&ioc->transport_cmds.done);
0433 ioc->put_smid_default(ioc, smid);
0434 wait_for_completion_timeout(&ioc->transport_cmds.done, 10*HZ);
0435
0436 if (!(ioc->transport_cmds.status & MPT3_CMD_COMPLETE)) {
0437 ioc_err(ioc, "%s: timeout\n", __func__);
0438 _debug_dump_mf(mpi_request,
0439 sizeof(Mpi2SmpPassthroughRequest_t)/4);
0440 if (!(ioc->transport_cmds.status & MPT3_CMD_RESET))
0441 issue_reset = 1;
0442 goto issue_host_reset;
0443 }
0444
0445 dtransportprintk(ioc, ioc_info(ioc, "report_manufacture - complete\n"));
0446
0447 if (ioc->transport_cmds.status & MPT3_CMD_REPLY_VALID) {
0448 u8 *tmp;
0449
0450 mpi_reply = ioc->transport_cmds.reply;
0451
0452 dtransportprintk(ioc,
0453 ioc_info(ioc, "report_manufacture - reply data transfer size(%d)\n",
0454 le16_to_cpu(mpi_reply->ResponseDataLength)));
0455
0456 if (le16_to_cpu(mpi_reply->ResponseDataLength) !=
0457 sizeof(struct rep_manu_reply))
0458 goto out;
0459
0460 manufacture_reply = data_out + sizeof(struct rep_manu_request);
0461 strncpy(edev->vendor_id, manufacture_reply->vendor_id,
0462 SAS_EXPANDER_VENDOR_ID_LEN);
0463 strncpy(edev->product_id, manufacture_reply->product_id,
0464 SAS_EXPANDER_PRODUCT_ID_LEN);
0465 strncpy(edev->product_rev, manufacture_reply->product_rev,
0466 SAS_EXPANDER_PRODUCT_REV_LEN);
0467 edev->level = manufacture_reply->sas_format & 1;
0468 if (edev->level) {
0469 strncpy(edev->component_vendor_id,
0470 manufacture_reply->component_vendor_id,
0471 SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN);
0472 tmp = (u8 *)&manufacture_reply->component_id;
0473 edev->component_id = tmp[0] << 8 | tmp[1];
0474 edev->component_revision_id =
0475 manufacture_reply->component_revision_id;
0476 }
0477 } else
0478 dtransportprintk(ioc,
0479 ioc_info(ioc, "report_manufacture - no reply\n"));
0480
0481 issue_host_reset:
0482 if (issue_reset)
0483 mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER);
0484 out:
0485 ioc->transport_cmds.status = MPT3_CMD_NOT_USED;
0486 if (data_out)
0487 dma_free_coherent(&ioc->pdev->dev, data_out_sz + data_in_sz,
0488 data_out, data_out_dma);
0489
0490 mutex_unlock(&ioc->transport_cmds.mutex);
0491 return rc;
0492 }
0493
0494
0495
0496
0497
0498
0499
0500 static void
0501 _transport_delete_port(struct MPT3SAS_ADAPTER *ioc,
0502 struct _sas_port *mpt3sas_port)
0503 {
0504 u64 sas_address = mpt3sas_port->remote_identify.sas_address;
0505 struct hba_port *port = mpt3sas_port->hba_port;
0506 enum sas_device_type device_type =
0507 mpt3sas_port->remote_identify.device_type;
0508
0509 dev_printk(KERN_INFO, &mpt3sas_port->port->dev,
0510 "remove: sas_addr(0x%016llx)\n",
0511 (unsigned long long) sas_address);
0512
0513 ioc->logging_level |= MPT_DEBUG_TRANSPORT;
0514 if (device_type == SAS_END_DEVICE)
0515 mpt3sas_device_remove_by_sas_address(ioc,
0516 sas_address, port);
0517 else if (device_type == SAS_EDGE_EXPANDER_DEVICE ||
0518 device_type == SAS_FANOUT_EXPANDER_DEVICE)
0519 mpt3sas_expander_remove(ioc, sas_address, port);
0520 ioc->logging_level &= ~MPT_DEBUG_TRANSPORT;
0521 }
0522
0523
0524
0525
0526
0527
0528
0529 static void
0530 _transport_delete_phy(struct MPT3SAS_ADAPTER *ioc,
0531 struct _sas_port *mpt3sas_port, struct _sas_phy *mpt3sas_phy)
0532 {
0533 u64 sas_address = mpt3sas_port->remote_identify.sas_address;
0534
0535 dev_printk(KERN_INFO, &mpt3sas_phy->phy->dev,
0536 "remove: sas_addr(0x%016llx), phy(%d)\n",
0537 (unsigned long long) sas_address, mpt3sas_phy->phy_id);
0538
0539 list_del(&mpt3sas_phy->port_siblings);
0540 mpt3sas_port->num_phys--;
0541 sas_port_delete_phy(mpt3sas_port->port, mpt3sas_phy->phy);
0542 mpt3sas_phy->phy_belongs_to_port = 0;
0543 }
0544
0545
0546
0547
0548
0549
0550
0551 static void
0552 _transport_add_phy(struct MPT3SAS_ADAPTER *ioc, struct _sas_port *mpt3sas_port,
0553 struct _sas_phy *mpt3sas_phy)
0554 {
0555 u64 sas_address = mpt3sas_port->remote_identify.sas_address;
0556
0557 dev_printk(KERN_INFO, &mpt3sas_phy->phy->dev,
0558 "add: sas_addr(0x%016llx), phy(%d)\n", (unsigned long long)
0559 sas_address, mpt3sas_phy->phy_id);
0560
0561 list_add_tail(&mpt3sas_phy->port_siblings, &mpt3sas_port->phy_list);
0562 mpt3sas_port->num_phys++;
0563 sas_port_add_phy(mpt3sas_port->port, mpt3sas_phy->phy);
0564 mpt3sas_phy->phy_belongs_to_port = 1;
0565 }
0566
0567
0568
0569
0570
0571
0572
0573
0574
0575 void
0576 mpt3sas_transport_add_phy_to_an_existing_port(struct MPT3SAS_ADAPTER *ioc,
0577 struct _sas_node *sas_node, struct _sas_phy *mpt3sas_phy,
0578 u64 sas_address, struct hba_port *port)
0579 {
0580 struct _sas_port *mpt3sas_port;
0581 struct _sas_phy *phy_srch;
0582
0583 if (mpt3sas_phy->phy_belongs_to_port == 1)
0584 return;
0585
0586 if (!port)
0587 return;
0588
0589 list_for_each_entry(mpt3sas_port, &sas_node->sas_port_list,
0590 port_list) {
0591 if (mpt3sas_port->remote_identify.sas_address !=
0592 sas_address)
0593 continue;
0594 if (mpt3sas_port->hba_port != port)
0595 continue;
0596 list_for_each_entry(phy_srch, &mpt3sas_port->phy_list,
0597 port_siblings) {
0598 if (phy_srch == mpt3sas_phy)
0599 return;
0600 }
0601 _transport_add_phy(ioc, mpt3sas_port, mpt3sas_phy);
0602 return;
0603 }
0604
0605 }
0606
0607
0608
0609
0610
0611
0612
0613 void
0614 mpt3sas_transport_del_phy_from_an_existing_port(struct MPT3SAS_ADAPTER *ioc,
0615 struct _sas_node *sas_node, struct _sas_phy *mpt3sas_phy)
0616 {
0617 struct _sas_port *mpt3sas_port, *next;
0618 struct _sas_phy *phy_srch;
0619
0620 if (mpt3sas_phy->phy_belongs_to_port == 0)
0621 return;
0622
0623 list_for_each_entry_safe(mpt3sas_port, next, &sas_node->sas_port_list,
0624 port_list) {
0625 list_for_each_entry(phy_srch, &mpt3sas_port->phy_list,
0626 port_siblings) {
0627 if (phy_srch != mpt3sas_phy)
0628 continue;
0629
0630
0631
0632
0633
0634 if (mpt3sas_port->num_phys == 1 && !ioc->shost_recovery)
0635 _transport_delete_port(ioc, mpt3sas_port);
0636 else
0637 _transport_delete_phy(ioc, mpt3sas_port,
0638 mpt3sas_phy);
0639 return;
0640 }
0641 }
0642 }
0643
0644
0645
0646
0647
0648
0649
0650
0651
0652
0653 static void
0654 _transport_sanity_check(struct MPT3SAS_ADAPTER *ioc, struct _sas_node *sas_node,
0655 u64 sas_address, struct hba_port *port)
0656 {
0657 int i;
0658
0659 for (i = 0; i < sas_node->num_phys; i++) {
0660 if (sas_node->phy[i].remote_identify.sas_address != sas_address)
0661 continue;
0662 if (sas_node->phy[i].port != port)
0663 continue;
0664 if (sas_node->phy[i].phy_belongs_to_port == 1)
0665 mpt3sas_transport_del_phy_from_an_existing_port(ioc,
0666 sas_node, &sas_node->phy[i]);
0667 }
0668 }
0669
0670
0671
0672
0673
0674
0675
0676
0677
0678
0679
0680
0681
0682 struct _sas_port *
0683 mpt3sas_transport_port_add(struct MPT3SAS_ADAPTER *ioc, u16 handle,
0684 u64 sas_address, struct hba_port *hba_port)
0685 {
0686 struct _sas_phy *mpt3sas_phy, *next;
0687 struct _sas_port *mpt3sas_port;
0688 unsigned long flags;
0689 struct _sas_node *sas_node;
0690 struct sas_rphy *rphy;
0691 struct _sas_device *sas_device = NULL;
0692 int i;
0693 struct sas_port *port;
0694 struct virtual_phy *vphy = NULL;
0695
0696 if (!hba_port) {
0697 ioc_err(ioc, "failure at %s:%d/%s()!\n",
0698 __FILE__, __LINE__, __func__);
0699 return NULL;
0700 }
0701
0702 mpt3sas_port = kzalloc(sizeof(struct _sas_port),
0703 GFP_KERNEL);
0704 if (!mpt3sas_port) {
0705 ioc_err(ioc, "failure at %s:%d/%s()!\n",
0706 __FILE__, __LINE__, __func__);
0707 return NULL;
0708 }
0709
0710 INIT_LIST_HEAD(&mpt3sas_port->port_list);
0711 INIT_LIST_HEAD(&mpt3sas_port->phy_list);
0712 spin_lock_irqsave(&ioc->sas_node_lock, flags);
0713 sas_node = _transport_sas_node_find_by_sas_address(ioc,
0714 sas_address, hba_port);
0715 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
0716
0717 if (!sas_node) {
0718 ioc_err(ioc, "%s: Could not find parent sas_address(0x%016llx)!\n",
0719 __func__, (u64)sas_address);
0720 goto out_fail;
0721 }
0722
0723 if ((_transport_set_identify(ioc, handle,
0724 &mpt3sas_port->remote_identify))) {
0725 ioc_err(ioc, "failure at %s:%d/%s()!\n",
0726 __FILE__, __LINE__, __func__);
0727 goto out_fail;
0728 }
0729
0730 if (mpt3sas_port->remote_identify.device_type == SAS_PHY_UNUSED) {
0731 ioc_err(ioc, "failure at %s:%d/%s()!\n",
0732 __FILE__, __LINE__, __func__);
0733 goto out_fail;
0734 }
0735
0736 mpt3sas_port->hba_port = hba_port;
0737 _transport_sanity_check(ioc, sas_node,
0738 mpt3sas_port->remote_identify.sas_address, hba_port);
0739
0740 for (i = 0; i < sas_node->num_phys; i++) {
0741 if (sas_node->phy[i].remote_identify.sas_address !=
0742 mpt3sas_port->remote_identify.sas_address)
0743 continue;
0744 if (sas_node->phy[i].port != hba_port)
0745 continue;
0746 list_add_tail(&sas_node->phy[i].port_siblings,
0747 &mpt3sas_port->phy_list);
0748 mpt3sas_port->num_phys++;
0749 if (sas_node->handle <= ioc->sas_hba.num_phys) {
0750 if (!sas_node->phy[i].hba_vphy) {
0751 hba_port->phy_mask |= (1 << i);
0752 continue;
0753 }
0754
0755 vphy = mpt3sas_get_vphy_by_phy(ioc, hba_port, i);
0756 if (!vphy) {
0757 ioc_err(ioc, "failure at %s:%d/%s()!\n",
0758 __FILE__, __LINE__, __func__);
0759 goto out_fail;
0760 }
0761 }
0762 }
0763
0764 if (!mpt3sas_port->num_phys) {
0765 ioc_err(ioc, "failure at %s:%d/%s()!\n",
0766 __FILE__, __LINE__, __func__);
0767 goto out_fail;
0768 }
0769
0770 if (mpt3sas_port->remote_identify.device_type == SAS_END_DEVICE) {
0771 sas_device = mpt3sas_get_sdev_by_addr(ioc,
0772 mpt3sas_port->remote_identify.sas_address,
0773 mpt3sas_port->hba_port);
0774 if (!sas_device) {
0775 ioc_err(ioc, "failure at %s:%d/%s()!\n",
0776 __FILE__, __LINE__, __func__);
0777 goto out_fail;
0778 }
0779 sas_device->pend_sas_rphy_add = 1;
0780 }
0781
0782 if (!sas_node->parent_dev) {
0783 ioc_err(ioc, "failure at %s:%d/%s()!\n",
0784 __FILE__, __LINE__, __func__);
0785 goto out_fail;
0786 }
0787 port = sas_port_alloc_num(sas_node->parent_dev);
0788 if ((sas_port_add(port))) {
0789 ioc_err(ioc, "failure at %s:%d/%s()!\n",
0790 __FILE__, __LINE__, __func__);
0791 goto out_fail;
0792 }
0793
0794 list_for_each_entry(mpt3sas_phy, &mpt3sas_port->phy_list,
0795 port_siblings) {
0796 if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
0797 dev_printk(KERN_INFO, &port->dev,
0798 "add: handle(0x%04x), sas_addr(0x%016llx), phy(%d)\n",
0799 handle, (unsigned long long)
0800 mpt3sas_port->remote_identify.sas_address,
0801 mpt3sas_phy->phy_id);
0802 sas_port_add_phy(port, mpt3sas_phy->phy);
0803 mpt3sas_phy->phy_belongs_to_port = 1;
0804 mpt3sas_phy->port = hba_port;
0805 }
0806
0807 mpt3sas_port->port = port;
0808 if (mpt3sas_port->remote_identify.device_type == SAS_END_DEVICE) {
0809 rphy = sas_end_device_alloc(port);
0810 sas_device->rphy = rphy;
0811 if (sas_node->handle <= ioc->sas_hba.num_phys) {
0812 if (!vphy)
0813 hba_port->sas_address =
0814 sas_device->sas_address;
0815 else
0816 vphy->sas_address =
0817 sas_device->sas_address;
0818 }
0819 } else {
0820 rphy = sas_expander_alloc(port,
0821 mpt3sas_port->remote_identify.device_type);
0822 if (sas_node->handle <= ioc->sas_hba.num_phys)
0823 hba_port->sas_address =
0824 mpt3sas_port->remote_identify.sas_address;
0825 }
0826
0827 rphy->identify = mpt3sas_port->remote_identify;
0828
0829 if ((sas_rphy_add(rphy))) {
0830 ioc_err(ioc, "failure at %s:%d/%s()!\n",
0831 __FILE__, __LINE__, __func__);
0832 }
0833
0834 if (mpt3sas_port->remote_identify.device_type == SAS_END_DEVICE) {
0835 sas_device->pend_sas_rphy_add = 0;
0836 sas_device_put(sas_device);
0837 }
0838
0839 dev_info(&rphy->dev,
0840 "add: handle(0x%04x), sas_addr(0x%016llx)\n", handle,
0841 (unsigned long long)mpt3sas_port->remote_identify.sas_address);
0842
0843 mpt3sas_port->rphy = rphy;
0844 spin_lock_irqsave(&ioc->sas_node_lock, flags);
0845 list_add_tail(&mpt3sas_port->port_list, &sas_node->sas_port_list);
0846 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
0847
0848
0849 if (mpt3sas_port->remote_identify.device_type ==
0850 MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER ||
0851 mpt3sas_port->remote_identify.device_type ==
0852 MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER)
0853 _transport_expander_report_manufacture(ioc,
0854 mpt3sas_port->remote_identify.sas_address,
0855 rphy_to_expander_device(rphy), hba_port->port_id);
0856 return mpt3sas_port;
0857
0858 out_fail:
0859 list_for_each_entry_safe(mpt3sas_phy, next, &mpt3sas_port->phy_list,
0860 port_siblings)
0861 list_del(&mpt3sas_phy->port_siblings);
0862 kfree(mpt3sas_port);
0863 return NULL;
0864 }
0865
0866
0867
0868
0869
0870
0871
0872
0873
0874
0875
0876
0877 void
0878 mpt3sas_transport_port_remove(struct MPT3SAS_ADAPTER *ioc, u64 sas_address,
0879 u64 sas_address_parent, struct hba_port *port)
0880 {
0881 int i;
0882 unsigned long flags;
0883 struct _sas_port *mpt3sas_port, *next;
0884 struct _sas_node *sas_node;
0885 u8 found = 0;
0886 struct _sas_phy *mpt3sas_phy, *next_phy;
0887 struct hba_port *hba_port_next, *hba_port = NULL;
0888 struct virtual_phy *vphy, *vphy_next = NULL;
0889
0890 if (!port)
0891 return;
0892
0893 spin_lock_irqsave(&ioc->sas_node_lock, flags);
0894 sas_node = _transport_sas_node_find_by_sas_address(ioc,
0895 sas_address_parent, port);
0896 if (!sas_node) {
0897 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
0898 return;
0899 }
0900 list_for_each_entry_safe(mpt3sas_port, next, &sas_node->sas_port_list,
0901 port_list) {
0902 if (mpt3sas_port->remote_identify.sas_address != sas_address)
0903 continue;
0904 if (mpt3sas_port->hba_port != port)
0905 continue;
0906 found = 1;
0907 list_del(&mpt3sas_port->port_list);
0908 goto out;
0909 }
0910 out:
0911 if (!found) {
0912 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
0913 return;
0914 }
0915
0916 if (sas_node->handle <= ioc->sas_hba.num_phys &&
0917 (ioc->multipath_on_hba)) {
0918 if (port->vphys_mask) {
0919 list_for_each_entry_safe(vphy, vphy_next,
0920 &port->vphys_list, list) {
0921 if (vphy->sas_address != sas_address)
0922 continue;
0923 ioc_info(ioc,
0924 "remove vphy entry: %p of port:%p,from %d port's vphys list\n",
0925 vphy, port, port->port_id);
0926 port->vphys_mask &= ~vphy->phy_mask;
0927 list_del(&vphy->list);
0928 kfree(vphy);
0929 }
0930 }
0931
0932 list_for_each_entry_safe(hba_port, hba_port_next,
0933 &ioc->port_table_list, list) {
0934 if (hba_port != port)
0935 continue;
0936
0937
0938
0939
0940
0941
0942
0943
0944
0945
0946 if ((hba_port->sas_address == sas_address ||
0947 !hba_port->sas_address) && !hba_port->vphys_mask) {
0948 ioc_info(ioc,
0949 "remove hba_port entry: %p port: %d from hba_port list\n",
0950 hba_port, hba_port->port_id);
0951 list_del(&hba_port->list);
0952 kfree(hba_port);
0953 } else if (hba_port->sas_address == sas_address &&
0954 hba_port->vphys_mask) {
0955
0956
0957
0958
0959
0960
0961
0962 ioc_info(ioc,
0963 "clearing sas_address from hba_port entry: %p port: %d from hba_port list\n",
0964 hba_port, hba_port->port_id);
0965 port->sas_address = 0;
0966 }
0967 break;
0968 }
0969 }
0970
0971 for (i = 0; i < sas_node->num_phys; i++) {
0972 if (sas_node->phy[i].remote_identify.sas_address == sas_address)
0973 memset(&sas_node->phy[i].remote_identify, 0 ,
0974 sizeof(struct sas_identify));
0975 }
0976
0977 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
0978
0979 list_for_each_entry_safe(mpt3sas_phy, next_phy,
0980 &mpt3sas_port->phy_list, port_siblings) {
0981 if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
0982 dev_printk(KERN_INFO, &mpt3sas_port->port->dev,
0983 "remove: sas_addr(0x%016llx), phy(%d)\n",
0984 (unsigned long long)
0985 mpt3sas_port->remote_identify.sas_address,
0986 mpt3sas_phy->phy_id);
0987 mpt3sas_phy->phy_belongs_to_port = 0;
0988 if (!ioc->remove_host)
0989 sas_port_delete_phy(mpt3sas_port->port,
0990 mpt3sas_phy->phy);
0991 list_del(&mpt3sas_phy->port_siblings);
0992 }
0993 if (!ioc->remove_host)
0994 sas_port_delete(mpt3sas_port->port);
0995 ioc_info(ioc, "%s: removed: sas_addr(0x%016llx)\n",
0996 __func__, (unsigned long long)sas_address);
0997 kfree(mpt3sas_port);
0998 }
0999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009 int
1010 mpt3sas_transport_add_host_phy(struct MPT3SAS_ADAPTER *ioc, struct _sas_phy
1011 *mpt3sas_phy, Mpi2SasPhyPage0_t phy_pg0, struct device *parent_dev)
1012 {
1013 struct sas_phy *phy;
1014 int phy_index = mpt3sas_phy->phy_id;
1015
1016
1017 INIT_LIST_HEAD(&mpt3sas_phy->port_siblings);
1018 phy = sas_phy_alloc(parent_dev, phy_index);
1019 if (!phy) {
1020 ioc_err(ioc, "failure at %s:%d/%s()!\n",
1021 __FILE__, __LINE__, __func__);
1022 return -1;
1023 }
1024 if ((_transport_set_identify(ioc, mpt3sas_phy->handle,
1025 &mpt3sas_phy->identify))) {
1026 ioc_err(ioc, "failure at %s:%d/%s()!\n",
1027 __FILE__, __LINE__, __func__);
1028 sas_phy_free(phy);
1029 return -1;
1030 }
1031 phy->identify = mpt3sas_phy->identify;
1032 mpt3sas_phy->attached_handle = le16_to_cpu(phy_pg0.AttachedDevHandle);
1033 if (mpt3sas_phy->attached_handle)
1034 _transport_set_identify(ioc, mpt3sas_phy->attached_handle,
1035 &mpt3sas_phy->remote_identify);
1036 phy->identify.phy_identifier = mpt3sas_phy->phy_id;
1037 phy->negotiated_linkrate = _transport_convert_phy_link_rate(
1038 phy_pg0.NegotiatedLinkRate & MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL);
1039 phy->minimum_linkrate_hw = _transport_convert_phy_link_rate(
1040 phy_pg0.HwLinkRate & MPI2_SAS_HWRATE_MIN_RATE_MASK);
1041 phy->maximum_linkrate_hw = _transport_convert_phy_link_rate(
1042 phy_pg0.HwLinkRate >> 4);
1043 phy->minimum_linkrate = _transport_convert_phy_link_rate(
1044 phy_pg0.ProgrammedLinkRate & MPI2_SAS_PRATE_MIN_RATE_MASK);
1045 phy->maximum_linkrate = _transport_convert_phy_link_rate(
1046 phy_pg0.ProgrammedLinkRate >> 4);
1047 phy->hostdata = mpt3sas_phy->port;
1048
1049 if ((sas_phy_add(phy))) {
1050 ioc_err(ioc, "failure at %s:%d/%s()!\n",
1051 __FILE__, __LINE__, __func__);
1052 sas_phy_free(phy);
1053 return -1;
1054 }
1055 if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
1056 dev_printk(KERN_INFO, &phy->dev,
1057 "add: handle(0x%04x), sas_addr(0x%016llx)\n"
1058 "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n",
1059 mpt3sas_phy->handle, (unsigned long long)
1060 mpt3sas_phy->identify.sas_address,
1061 mpt3sas_phy->attached_handle,
1062 (unsigned long long)
1063 mpt3sas_phy->remote_identify.sas_address);
1064 mpt3sas_phy->phy = phy;
1065 return 0;
1066 }
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078 int
1079 mpt3sas_transport_add_expander_phy(struct MPT3SAS_ADAPTER *ioc, struct _sas_phy
1080 *mpt3sas_phy, Mpi2ExpanderPage1_t expander_pg1,
1081 struct device *parent_dev)
1082 {
1083 struct sas_phy *phy;
1084 int phy_index = mpt3sas_phy->phy_id;
1085
1086 INIT_LIST_HEAD(&mpt3sas_phy->port_siblings);
1087 phy = sas_phy_alloc(parent_dev, phy_index);
1088 if (!phy) {
1089 ioc_err(ioc, "failure at %s:%d/%s()!\n",
1090 __FILE__, __LINE__, __func__);
1091 return -1;
1092 }
1093 if ((_transport_set_identify(ioc, mpt3sas_phy->handle,
1094 &mpt3sas_phy->identify))) {
1095 ioc_err(ioc, "failure at %s:%d/%s()!\n",
1096 __FILE__, __LINE__, __func__);
1097 sas_phy_free(phy);
1098 return -1;
1099 }
1100 phy->identify = mpt3sas_phy->identify;
1101 mpt3sas_phy->attached_handle =
1102 le16_to_cpu(expander_pg1.AttachedDevHandle);
1103 if (mpt3sas_phy->attached_handle)
1104 _transport_set_identify(ioc, mpt3sas_phy->attached_handle,
1105 &mpt3sas_phy->remote_identify);
1106 phy->identify.phy_identifier = mpt3sas_phy->phy_id;
1107 phy->negotiated_linkrate = _transport_convert_phy_link_rate(
1108 expander_pg1.NegotiatedLinkRate &
1109 MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL);
1110 phy->minimum_linkrate_hw = _transport_convert_phy_link_rate(
1111 expander_pg1.HwLinkRate & MPI2_SAS_HWRATE_MIN_RATE_MASK);
1112 phy->maximum_linkrate_hw = _transport_convert_phy_link_rate(
1113 expander_pg1.HwLinkRate >> 4);
1114 phy->minimum_linkrate = _transport_convert_phy_link_rate(
1115 expander_pg1.ProgrammedLinkRate & MPI2_SAS_PRATE_MIN_RATE_MASK);
1116 phy->maximum_linkrate = _transport_convert_phy_link_rate(
1117 expander_pg1.ProgrammedLinkRate >> 4);
1118 phy->hostdata = mpt3sas_phy->port;
1119
1120 if ((sas_phy_add(phy))) {
1121 ioc_err(ioc, "failure at %s:%d/%s()!\n",
1122 __FILE__, __LINE__, __func__);
1123 sas_phy_free(phy);
1124 return -1;
1125 }
1126 if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
1127 dev_printk(KERN_INFO, &phy->dev,
1128 "add: handle(0x%04x), sas_addr(0x%016llx)\n"
1129 "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n",
1130 mpt3sas_phy->handle, (unsigned long long)
1131 mpt3sas_phy->identify.sas_address,
1132 mpt3sas_phy->attached_handle,
1133 (unsigned long long)
1134 mpt3sas_phy->remote_identify.sas_address);
1135 mpt3sas_phy->phy = phy;
1136 return 0;
1137 }
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150 void
1151 mpt3sas_transport_update_links(struct MPT3SAS_ADAPTER *ioc,
1152 u64 sas_address, u16 handle, u8 phy_number, u8 link_rate,
1153 struct hba_port *port)
1154 {
1155 unsigned long flags;
1156 struct _sas_node *sas_node;
1157 struct _sas_phy *mpt3sas_phy;
1158 struct hba_port *hba_port = NULL;
1159
1160 if (ioc->shost_recovery || ioc->pci_error_recovery)
1161 return;
1162
1163 spin_lock_irqsave(&ioc->sas_node_lock, flags);
1164 sas_node = _transport_sas_node_find_by_sas_address(ioc,
1165 sas_address, port);
1166 if (!sas_node) {
1167 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1168 return;
1169 }
1170
1171 mpt3sas_phy = &sas_node->phy[phy_number];
1172 mpt3sas_phy->attached_handle = handle;
1173 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1174 if (handle && (link_rate >= MPI2_SAS_NEG_LINK_RATE_1_5)) {
1175 _transport_set_identify(ioc, handle,
1176 &mpt3sas_phy->remote_identify);
1177 if ((sas_node->handle <= ioc->sas_hba.num_phys) &&
1178 (ioc->multipath_on_hba)) {
1179 list_for_each_entry(hba_port,
1180 &ioc->port_table_list, list) {
1181 if (hba_port->sas_address == sas_address &&
1182 hba_port == port)
1183 hba_port->phy_mask |=
1184 (1 << mpt3sas_phy->phy_id);
1185 }
1186 }
1187 mpt3sas_transport_add_phy_to_an_existing_port(ioc, sas_node,
1188 mpt3sas_phy, mpt3sas_phy->remote_identify.sas_address,
1189 port);
1190 } else
1191 memset(&mpt3sas_phy->remote_identify, 0 , sizeof(struct
1192 sas_identify));
1193
1194 if (mpt3sas_phy->phy)
1195 mpt3sas_phy->phy->negotiated_linkrate =
1196 _transport_convert_phy_link_rate(link_rate);
1197
1198 if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
1199 dev_printk(KERN_INFO, &mpt3sas_phy->phy->dev,
1200 "refresh: parent sas_addr(0x%016llx),\n"
1201 "\tlink_rate(0x%02x), phy(%d)\n"
1202 "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n",
1203 (unsigned long long)sas_address,
1204 link_rate, phy_number, handle, (unsigned long long)
1205 mpt3sas_phy->remote_identify.sas_address);
1206 }
1207
1208 static inline void *
1209 phy_to_ioc(struct sas_phy *phy)
1210 {
1211 struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
1212 return shost_priv(shost);
1213 }
1214
1215 static inline void *
1216 rphy_to_ioc(struct sas_rphy *rphy)
1217 {
1218 struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent);
1219 return shost_priv(shost);
1220 }
1221
1222
1223 struct phy_error_log_request {
1224 u8 smp_frame_type;
1225 u8 function;
1226 u8 allocated_response_length;
1227 u8 request_length;
1228 u8 reserved_1[5];
1229 u8 phy_identifier;
1230 u8 reserved_2[2];
1231 };
1232
1233
1234 struct phy_error_log_reply {
1235 u8 smp_frame_type;
1236 u8 function;
1237 u8 function_result;
1238 u8 response_length;
1239 __be16 expander_change_count;
1240 u8 reserved_1[3];
1241 u8 phy_identifier;
1242 u8 reserved_2[2];
1243 __be32 invalid_dword;
1244 __be32 running_disparity_error;
1245 __be32 loss_of_dword_sync;
1246 __be32 phy_reset_problem;
1247 };
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257 static int
1258 _transport_get_expander_phy_error_log(struct MPT3SAS_ADAPTER *ioc,
1259 struct sas_phy *phy)
1260 {
1261 Mpi2SmpPassthroughRequest_t *mpi_request;
1262 Mpi2SmpPassthroughReply_t *mpi_reply;
1263 struct phy_error_log_request *phy_error_log_request;
1264 struct phy_error_log_reply *phy_error_log_reply;
1265 int rc;
1266 u16 smid;
1267 void *psge;
1268 u8 issue_reset = 0;
1269 void *data_out = NULL;
1270 dma_addr_t data_out_dma;
1271 u32 sz;
1272
1273 if (ioc->shost_recovery || ioc->pci_error_recovery) {
1274 ioc_info(ioc, "%s: host reset in progress!\n", __func__);
1275 return -EFAULT;
1276 }
1277
1278 mutex_lock(&ioc->transport_cmds.mutex);
1279
1280 if (ioc->transport_cmds.status != MPT3_CMD_NOT_USED) {
1281 ioc_err(ioc, "%s: transport_cmds in use\n", __func__);
1282 rc = -EAGAIN;
1283 goto out;
1284 }
1285 ioc->transport_cmds.status = MPT3_CMD_PENDING;
1286
1287 rc = mpt3sas_wait_for_ioc(ioc, IOC_OPERATIONAL_WAIT_COUNT);
1288 if (rc)
1289 goto out;
1290
1291 smid = mpt3sas_base_get_smid(ioc, ioc->transport_cb_idx);
1292 if (!smid) {
1293 ioc_err(ioc, "%s: failed obtaining a smid\n", __func__);
1294 rc = -EAGAIN;
1295 goto out;
1296 }
1297
1298 mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
1299 ioc->transport_cmds.smid = smid;
1300
1301 sz = sizeof(struct phy_error_log_request) +
1302 sizeof(struct phy_error_log_reply);
1303 data_out = dma_alloc_coherent(&ioc->pdev->dev, sz, &data_out_dma,
1304 GFP_KERNEL);
1305 if (!data_out) {
1306 pr_err("failure at %s:%d/%s()!\n", __FILE__,
1307 __LINE__, __func__);
1308 rc = -ENOMEM;
1309 mpt3sas_base_free_smid(ioc, smid);
1310 goto out;
1311 }
1312
1313 rc = -EINVAL;
1314 memset(data_out, 0, sz);
1315 phy_error_log_request = data_out;
1316 phy_error_log_request->smp_frame_type = 0x40;
1317 phy_error_log_request->function = 0x11;
1318 phy_error_log_request->request_length = 2;
1319 phy_error_log_request->allocated_response_length = 0;
1320 phy_error_log_request->phy_identifier = phy->number;
1321
1322 memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t));
1323 mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
1324 mpi_request->PhysicalPort = _transport_get_port_id_by_sas_phy(phy);
1325 mpi_request->VF_ID = 0;
1326 mpi_request->VP_ID = 0;
1327 mpi_request->SASAddress = cpu_to_le64(phy->identify.sas_address);
1328 mpi_request->RequestDataLength =
1329 cpu_to_le16(sizeof(struct phy_error_log_request));
1330 psge = &mpi_request->SGL;
1331
1332 ioc->build_sg(ioc, psge, data_out_dma,
1333 sizeof(struct phy_error_log_request),
1334 data_out_dma + sizeof(struct phy_error_log_request),
1335 sizeof(struct phy_error_log_reply));
1336
1337 dtransportprintk(ioc,
1338 ioc_info(ioc, "phy_error_log - send to sas_addr(0x%016llx), phy(%d)\n",
1339 (u64)phy->identify.sas_address,
1340 phy->number));
1341 init_completion(&ioc->transport_cmds.done);
1342 ioc->put_smid_default(ioc, smid);
1343 wait_for_completion_timeout(&ioc->transport_cmds.done, 10*HZ);
1344
1345 if (!(ioc->transport_cmds.status & MPT3_CMD_COMPLETE)) {
1346 ioc_err(ioc, "%s: timeout\n", __func__);
1347 _debug_dump_mf(mpi_request,
1348 sizeof(Mpi2SmpPassthroughRequest_t)/4);
1349 if (!(ioc->transport_cmds.status & MPT3_CMD_RESET))
1350 issue_reset = 1;
1351 goto issue_host_reset;
1352 }
1353
1354 dtransportprintk(ioc, ioc_info(ioc, "phy_error_log - complete\n"));
1355
1356 if (ioc->transport_cmds.status & MPT3_CMD_REPLY_VALID) {
1357
1358 mpi_reply = ioc->transport_cmds.reply;
1359
1360 dtransportprintk(ioc,
1361 ioc_info(ioc, "phy_error_log - reply data transfer size(%d)\n",
1362 le16_to_cpu(mpi_reply->ResponseDataLength)));
1363
1364 if (le16_to_cpu(mpi_reply->ResponseDataLength) !=
1365 sizeof(struct phy_error_log_reply))
1366 goto out;
1367
1368 phy_error_log_reply = data_out +
1369 sizeof(struct phy_error_log_request);
1370
1371 dtransportprintk(ioc,
1372 ioc_info(ioc, "phy_error_log - function_result(%d)\n",
1373 phy_error_log_reply->function_result));
1374
1375 phy->invalid_dword_count =
1376 be32_to_cpu(phy_error_log_reply->invalid_dword);
1377 phy->running_disparity_error_count =
1378 be32_to_cpu(phy_error_log_reply->running_disparity_error);
1379 phy->loss_of_dword_sync_count =
1380 be32_to_cpu(phy_error_log_reply->loss_of_dword_sync);
1381 phy->phy_reset_problem_count =
1382 be32_to_cpu(phy_error_log_reply->phy_reset_problem);
1383 rc = 0;
1384 } else
1385 dtransportprintk(ioc,
1386 ioc_info(ioc, "phy_error_log - no reply\n"));
1387
1388 issue_host_reset:
1389 if (issue_reset)
1390 mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER);
1391 out:
1392 ioc->transport_cmds.status = MPT3_CMD_NOT_USED;
1393 if (data_out)
1394 dma_free_coherent(&ioc->pdev->dev, sz, data_out, data_out_dma);
1395
1396 mutex_unlock(&ioc->transport_cmds.mutex);
1397 return rc;
1398 }
1399
1400
1401
1402
1403
1404
1405
1406
1407 static int
1408 _transport_get_linkerrors(struct sas_phy *phy)
1409 {
1410 struct MPT3SAS_ADAPTER *ioc = phy_to_ioc(phy);
1411 unsigned long flags;
1412 Mpi2ConfigReply_t mpi_reply;
1413 Mpi2SasPhyPage1_t phy_pg1;
1414 struct hba_port *port = phy->hostdata;
1415 int port_id = port->port_id;
1416
1417 spin_lock_irqsave(&ioc->sas_node_lock, flags);
1418 if (_transport_sas_node_find_by_sas_address(ioc,
1419 phy->identify.sas_address,
1420 mpt3sas_get_port_by_id(ioc, port_id, 0)) == NULL) {
1421 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1422 return -EINVAL;
1423 }
1424 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1425
1426 if (phy->identify.sas_address != ioc->sas_hba.sas_address)
1427 return _transport_get_expander_phy_error_log(ioc, phy);
1428
1429
1430 if ((mpt3sas_config_get_phy_pg1(ioc, &mpi_reply, &phy_pg1,
1431 phy->number))) {
1432 ioc_err(ioc, "failure at %s:%d/%s()!\n",
1433 __FILE__, __LINE__, __func__);
1434 return -ENXIO;
1435 }
1436
1437 if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo)
1438 ioc_info(ioc, "phy(%d), ioc_status (0x%04x), loginfo(0x%08x)\n",
1439 phy->number,
1440 le16_to_cpu(mpi_reply.IOCStatus),
1441 le32_to_cpu(mpi_reply.IOCLogInfo));
1442
1443 phy->invalid_dword_count = le32_to_cpu(phy_pg1.InvalidDwordCount);
1444 phy->running_disparity_error_count =
1445 le32_to_cpu(phy_pg1.RunningDisparityErrorCount);
1446 phy->loss_of_dword_sync_count =
1447 le32_to_cpu(phy_pg1.LossDwordSynchCount);
1448 phy->phy_reset_problem_count =
1449 le32_to_cpu(phy_pg1.PhyResetProblemCount);
1450 return 0;
1451 }
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461 static int
1462 _transport_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier)
1463 {
1464 struct MPT3SAS_ADAPTER *ioc = rphy_to_ioc(rphy);
1465 struct _sas_device *sas_device;
1466 unsigned long flags;
1467 int rc;
1468
1469 spin_lock_irqsave(&ioc->sas_device_lock, flags);
1470 sas_device = __mpt3sas_get_sdev_by_rphy(ioc, rphy);
1471 if (sas_device) {
1472 *identifier = sas_device->enclosure_logical_id;
1473 rc = 0;
1474 sas_device_put(sas_device);
1475 } else {
1476 *identifier = 0;
1477 rc = -ENXIO;
1478 }
1479
1480 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
1481 return rc;
1482 }
1483
1484
1485
1486
1487
1488
1489
1490 static int
1491 _transport_get_bay_identifier(struct sas_rphy *rphy)
1492 {
1493 struct MPT3SAS_ADAPTER *ioc = rphy_to_ioc(rphy);
1494 struct _sas_device *sas_device;
1495 unsigned long flags;
1496 int rc;
1497
1498 spin_lock_irqsave(&ioc->sas_device_lock, flags);
1499 sas_device = __mpt3sas_get_sdev_by_rphy(ioc, rphy);
1500 if (sas_device) {
1501 rc = sas_device->slot;
1502 sas_device_put(sas_device);
1503 } else {
1504 rc = -ENXIO;
1505 }
1506 spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
1507 return rc;
1508 }
1509
1510
1511 struct phy_control_request {
1512 u8 smp_frame_type;
1513 u8 function;
1514 u8 allocated_response_length;
1515 u8 request_length;
1516 u16 expander_change_count;
1517 u8 reserved_1[3];
1518 u8 phy_identifier;
1519 u8 phy_operation;
1520 u8 reserved_2[13];
1521 u64 attached_device_name;
1522 u8 programmed_min_physical_link_rate;
1523 u8 programmed_max_physical_link_rate;
1524 u8 reserved_3[6];
1525 };
1526
1527
1528 struct phy_control_reply {
1529 u8 smp_frame_type;
1530 u8 function;
1531 u8 function_result;
1532 u8 response_length;
1533 };
1534
1535 #define SMP_PHY_CONTROL_LINK_RESET (0x01)
1536 #define SMP_PHY_CONTROL_HARD_RESET (0x02)
1537 #define SMP_PHY_CONTROL_DISABLE (0x03)
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548 static int
1549 _transport_expander_phy_control(struct MPT3SAS_ADAPTER *ioc,
1550 struct sas_phy *phy, u8 phy_operation)
1551 {
1552 Mpi2SmpPassthroughRequest_t *mpi_request;
1553 Mpi2SmpPassthroughReply_t *mpi_reply;
1554 struct phy_control_request *phy_control_request;
1555 struct phy_control_reply *phy_control_reply;
1556 int rc;
1557 u16 smid;
1558 void *psge;
1559 u8 issue_reset = 0;
1560 void *data_out = NULL;
1561 dma_addr_t data_out_dma;
1562 u32 sz;
1563
1564 if (ioc->shost_recovery || ioc->pci_error_recovery) {
1565 ioc_info(ioc, "%s: host reset in progress!\n", __func__);
1566 return -EFAULT;
1567 }
1568
1569 mutex_lock(&ioc->transport_cmds.mutex);
1570
1571 if (ioc->transport_cmds.status != MPT3_CMD_NOT_USED) {
1572 ioc_err(ioc, "%s: transport_cmds in use\n", __func__);
1573 rc = -EAGAIN;
1574 goto out;
1575 }
1576 ioc->transport_cmds.status = MPT3_CMD_PENDING;
1577
1578 rc = mpt3sas_wait_for_ioc(ioc, IOC_OPERATIONAL_WAIT_COUNT);
1579 if (rc)
1580 goto out;
1581
1582 smid = mpt3sas_base_get_smid(ioc, ioc->transport_cb_idx);
1583 if (!smid) {
1584 ioc_err(ioc, "%s: failed obtaining a smid\n", __func__);
1585 rc = -EAGAIN;
1586 goto out;
1587 }
1588
1589 mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
1590 ioc->transport_cmds.smid = smid;
1591
1592 sz = sizeof(struct phy_control_request) +
1593 sizeof(struct phy_control_reply);
1594 data_out = dma_alloc_coherent(&ioc->pdev->dev, sz, &data_out_dma,
1595 GFP_KERNEL);
1596 if (!data_out) {
1597 pr_err("failure at %s:%d/%s()!\n", __FILE__,
1598 __LINE__, __func__);
1599 rc = -ENOMEM;
1600 mpt3sas_base_free_smid(ioc, smid);
1601 goto out;
1602 }
1603
1604 rc = -EINVAL;
1605 memset(data_out, 0, sz);
1606 phy_control_request = data_out;
1607 phy_control_request->smp_frame_type = 0x40;
1608 phy_control_request->function = 0x91;
1609 phy_control_request->request_length = 9;
1610 phy_control_request->allocated_response_length = 0;
1611 phy_control_request->phy_identifier = phy->number;
1612 phy_control_request->phy_operation = phy_operation;
1613 phy_control_request->programmed_min_physical_link_rate =
1614 phy->minimum_linkrate << 4;
1615 phy_control_request->programmed_max_physical_link_rate =
1616 phy->maximum_linkrate << 4;
1617
1618 memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t));
1619 mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
1620 mpi_request->PhysicalPort = _transport_get_port_id_by_sas_phy(phy);
1621 mpi_request->VF_ID = 0;
1622 mpi_request->VP_ID = 0;
1623 mpi_request->SASAddress = cpu_to_le64(phy->identify.sas_address);
1624 mpi_request->RequestDataLength =
1625 cpu_to_le16(sizeof(struct phy_error_log_request));
1626 psge = &mpi_request->SGL;
1627
1628 ioc->build_sg(ioc, psge, data_out_dma,
1629 sizeof(struct phy_control_request),
1630 data_out_dma + sizeof(struct phy_control_request),
1631 sizeof(struct phy_control_reply));
1632
1633 dtransportprintk(ioc,
1634 ioc_info(ioc, "phy_control - send to sas_addr(0x%016llx), phy(%d), opcode(%d)\n",
1635 (u64)phy->identify.sas_address,
1636 phy->number, phy_operation));
1637 init_completion(&ioc->transport_cmds.done);
1638 ioc->put_smid_default(ioc, smid);
1639 wait_for_completion_timeout(&ioc->transport_cmds.done, 10*HZ);
1640
1641 if (!(ioc->transport_cmds.status & MPT3_CMD_COMPLETE)) {
1642 ioc_err(ioc, "%s: timeout\n", __func__);
1643 _debug_dump_mf(mpi_request,
1644 sizeof(Mpi2SmpPassthroughRequest_t)/4);
1645 if (!(ioc->transport_cmds.status & MPT3_CMD_RESET))
1646 issue_reset = 1;
1647 goto issue_host_reset;
1648 }
1649
1650 dtransportprintk(ioc, ioc_info(ioc, "phy_control - complete\n"));
1651
1652 if (ioc->transport_cmds.status & MPT3_CMD_REPLY_VALID) {
1653
1654 mpi_reply = ioc->transport_cmds.reply;
1655
1656 dtransportprintk(ioc,
1657 ioc_info(ioc, "phy_control - reply data transfer size(%d)\n",
1658 le16_to_cpu(mpi_reply->ResponseDataLength)));
1659
1660 if (le16_to_cpu(mpi_reply->ResponseDataLength) !=
1661 sizeof(struct phy_control_reply))
1662 goto out;
1663
1664 phy_control_reply = data_out +
1665 sizeof(struct phy_control_request);
1666
1667 dtransportprintk(ioc,
1668 ioc_info(ioc, "phy_control - function_result(%d)\n",
1669 phy_control_reply->function_result));
1670
1671 rc = 0;
1672 } else
1673 dtransportprintk(ioc,
1674 ioc_info(ioc, "phy_control - no reply\n"));
1675
1676 issue_host_reset:
1677 if (issue_reset)
1678 mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER);
1679 out:
1680 ioc->transport_cmds.status = MPT3_CMD_NOT_USED;
1681 if (data_out)
1682 dma_free_coherent(&ioc->pdev->dev, sz, data_out,
1683 data_out_dma);
1684
1685 mutex_unlock(&ioc->transport_cmds.mutex);
1686 return rc;
1687 }
1688
1689
1690
1691
1692
1693
1694
1695
1696 static int
1697 _transport_phy_reset(struct sas_phy *phy, int hard_reset)
1698 {
1699 struct MPT3SAS_ADAPTER *ioc = phy_to_ioc(phy);
1700 Mpi2SasIoUnitControlReply_t mpi_reply;
1701 Mpi2SasIoUnitControlRequest_t mpi_request;
1702 struct hba_port *port = phy->hostdata;
1703 int port_id = port->port_id;
1704 unsigned long flags;
1705
1706 spin_lock_irqsave(&ioc->sas_node_lock, flags);
1707 if (_transport_sas_node_find_by_sas_address(ioc,
1708 phy->identify.sas_address,
1709 mpt3sas_get_port_by_id(ioc, port_id, 0)) == NULL) {
1710 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1711 return -EINVAL;
1712 }
1713 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1714
1715
1716 if (phy->identify.sas_address != ioc->sas_hba.sas_address)
1717 return _transport_expander_phy_control(ioc, phy,
1718 (hard_reset == 1) ? SMP_PHY_CONTROL_HARD_RESET :
1719 SMP_PHY_CONTROL_LINK_RESET);
1720
1721
1722 memset(&mpi_request, 0, sizeof(Mpi2SasIoUnitControlRequest_t));
1723 mpi_request.Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL;
1724 mpi_request.Operation = hard_reset ?
1725 MPI2_SAS_OP_PHY_HARD_RESET : MPI2_SAS_OP_PHY_LINK_RESET;
1726 mpi_request.PhyNum = phy->number;
1727
1728 if ((mpt3sas_base_sas_iounit_control(ioc, &mpi_reply, &mpi_request))) {
1729 ioc_err(ioc, "failure at %s:%d/%s()!\n",
1730 __FILE__, __LINE__, __func__);
1731 return -ENXIO;
1732 }
1733
1734 if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo)
1735 ioc_info(ioc, "phy(%d), ioc_status(0x%04x), loginfo(0x%08x)\n",
1736 phy->number, le16_to_cpu(mpi_reply.IOCStatus),
1737 le32_to_cpu(mpi_reply.IOCLogInfo));
1738
1739 return 0;
1740 }
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750 static int
1751 _transport_phy_enable(struct sas_phy *phy, int enable)
1752 {
1753 struct MPT3SAS_ADAPTER *ioc = phy_to_ioc(phy);
1754 Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL;
1755 Mpi2SasIOUnitPage0_t *sas_iounit_pg0 = NULL;
1756 Mpi2ConfigReply_t mpi_reply;
1757 u16 ioc_status;
1758 u16 sz;
1759 int rc = 0;
1760 unsigned long flags;
1761 int i, discovery_active;
1762 struct hba_port *port = phy->hostdata;
1763 int port_id = port->port_id;
1764
1765 spin_lock_irqsave(&ioc->sas_node_lock, flags);
1766 if (_transport_sas_node_find_by_sas_address(ioc,
1767 phy->identify.sas_address,
1768 mpt3sas_get_port_by_id(ioc, port_id, 0)) == NULL) {
1769 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1770 return -EINVAL;
1771 }
1772 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1773
1774
1775 if (phy->identify.sas_address != ioc->sas_hba.sas_address)
1776 return _transport_expander_phy_control(ioc, phy,
1777 (enable == 1) ? SMP_PHY_CONTROL_LINK_RESET :
1778 SMP_PHY_CONTROL_DISABLE);
1779
1780
1781
1782
1783 sz = offsetof(Mpi2SasIOUnitPage0_t, PhyData) + (ioc->sas_hba.num_phys *
1784 sizeof(Mpi2SasIOUnit0PhyData_t));
1785 sas_iounit_pg0 = kzalloc(sz, GFP_KERNEL);
1786 if (!sas_iounit_pg0) {
1787 ioc_err(ioc, "failure at %s:%d/%s()!\n",
1788 __FILE__, __LINE__, __func__);
1789 rc = -ENOMEM;
1790 goto out;
1791 }
1792 if ((mpt3sas_config_get_sas_iounit_pg0(ioc, &mpi_reply,
1793 sas_iounit_pg0, sz))) {
1794 ioc_err(ioc, "failure at %s:%d/%s()!\n",
1795 __FILE__, __LINE__, __func__);
1796 rc = -ENXIO;
1797 goto out;
1798 }
1799 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1800 MPI2_IOCSTATUS_MASK;
1801 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1802 ioc_err(ioc, "failure at %s:%d/%s()!\n",
1803 __FILE__, __LINE__, __func__);
1804 rc = -EIO;
1805 goto out;
1806 }
1807
1808
1809 for (i = 0, discovery_active = 0; i < ioc->sas_hba.num_phys ; i++) {
1810 if (sas_iounit_pg0->PhyData[i].PortFlags &
1811 MPI2_SASIOUNIT0_PORTFLAGS_DISCOVERY_IN_PROGRESS) {
1812 ioc_err(ioc, "discovery is active on port = %d, phy = %d: unable to enable/disable phys, try again later!\n",
1813 sas_iounit_pg0->PhyData[i].Port, i);
1814 discovery_active = 1;
1815 }
1816 }
1817
1818 if (discovery_active) {
1819 rc = -EAGAIN;
1820 goto out;
1821 }
1822
1823
1824 sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (ioc->sas_hba.num_phys *
1825 sizeof(Mpi2SasIOUnit1PhyData_t));
1826 sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL);
1827 if (!sas_iounit_pg1) {
1828 ioc_err(ioc, "failure at %s:%d/%s()!\n",
1829 __FILE__, __LINE__, __func__);
1830 rc = -ENOMEM;
1831 goto out;
1832 }
1833 if ((mpt3sas_config_get_sas_iounit_pg1(ioc, &mpi_reply,
1834 sas_iounit_pg1, sz))) {
1835 ioc_err(ioc, "failure at %s:%d/%s()!\n",
1836 __FILE__, __LINE__, __func__);
1837 rc = -ENXIO;
1838 goto out;
1839 }
1840 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1841 MPI2_IOCSTATUS_MASK;
1842 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1843 ioc_err(ioc, "failure at %s:%d/%s()!\n",
1844 __FILE__, __LINE__, __func__);
1845 rc = -EIO;
1846 goto out;
1847 }
1848
1849
1850 for (i = 0; i < ioc->sas_hba.num_phys ; i++) {
1851 sas_iounit_pg1->PhyData[i].Port =
1852 sas_iounit_pg0->PhyData[i].Port;
1853 sas_iounit_pg1->PhyData[i].PortFlags =
1854 (sas_iounit_pg0->PhyData[i].PortFlags &
1855 MPI2_SASIOUNIT0_PORTFLAGS_AUTO_PORT_CONFIG);
1856 sas_iounit_pg1->PhyData[i].PhyFlags =
1857 (sas_iounit_pg0->PhyData[i].PhyFlags &
1858 (MPI2_SASIOUNIT0_PHYFLAGS_ZONING_ENABLED +
1859 MPI2_SASIOUNIT0_PHYFLAGS_PHY_DISABLED));
1860 }
1861
1862 if (enable)
1863 sas_iounit_pg1->PhyData[phy->number].PhyFlags
1864 &= ~MPI2_SASIOUNIT1_PHYFLAGS_PHY_DISABLE;
1865 else
1866 sas_iounit_pg1->PhyData[phy->number].PhyFlags
1867 |= MPI2_SASIOUNIT1_PHYFLAGS_PHY_DISABLE;
1868
1869 mpt3sas_config_set_sas_iounit_pg1(ioc, &mpi_reply, sas_iounit_pg1, sz);
1870
1871
1872 if (enable)
1873 _transport_phy_reset(phy, 0);
1874
1875 out:
1876 kfree(sas_iounit_pg1);
1877 kfree(sas_iounit_pg0);
1878 return rc;
1879 }
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890 static int
1891 _transport_phy_speed(struct sas_phy *phy, struct sas_phy_linkrates *rates)
1892 {
1893 struct MPT3SAS_ADAPTER *ioc = phy_to_ioc(phy);
1894 Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL;
1895 Mpi2SasPhyPage0_t phy_pg0;
1896 Mpi2ConfigReply_t mpi_reply;
1897 u16 ioc_status;
1898 u16 sz;
1899 int i;
1900 int rc = 0;
1901 unsigned long flags;
1902 struct hba_port *port = phy->hostdata;
1903 int port_id = port->port_id;
1904
1905 spin_lock_irqsave(&ioc->sas_node_lock, flags);
1906 if (_transport_sas_node_find_by_sas_address(ioc,
1907 phy->identify.sas_address,
1908 mpt3sas_get_port_by_id(ioc, port_id, 0)) == NULL) {
1909 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1910 return -EINVAL;
1911 }
1912 spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
1913
1914 if (!rates->minimum_linkrate)
1915 rates->minimum_linkrate = phy->minimum_linkrate;
1916 else if (rates->minimum_linkrate < phy->minimum_linkrate_hw)
1917 rates->minimum_linkrate = phy->minimum_linkrate_hw;
1918
1919 if (!rates->maximum_linkrate)
1920 rates->maximum_linkrate = phy->maximum_linkrate;
1921 else if (rates->maximum_linkrate > phy->maximum_linkrate_hw)
1922 rates->maximum_linkrate = phy->maximum_linkrate_hw;
1923
1924
1925 if (phy->identify.sas_address != ioc->sas_hba.sas_address) {
1926 phy->minimum_linkrate = rates->minimum_linkrate;
1927 phy->maximum_linkrate = rates->maximum_linkrate;
1928 return _transport_expander_phy_control(ioc, phy,
1929 SMP_PHY_CONTROL_LINK_RESET);
1930 }
1931
1932
1933
1934
1935 sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (ioc->sas_hba.num_phys *
1936 sizeof(Mpi2SasIOUnit1PhyData_t));
1937 sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL);
1938 if (!sas_iounit_pg1) {
1939 ioc_err(ioc, "failure at %s:%d/%s()!\n",
1940 __FILE__, __LINE__, __func__);
1941 rc = -ENOMEM;
1942 goto out;
1943 }
1944 if ((mpt3sas_config_get_sas_iounit_pg1(ioc, &mpi_reply,
1945 sas_iounit_pg1, sz))) {
1946 ioc_err(ioc, "failure at %s:%d/%s()!\n",
1947 __FILE__, __LINE__, __func__);
1948 rc = -ENXIO;
1949 goto out;
1950 }
1951 ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
1952 MPI2_IOCSTATUS_MASK;
1953 if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
1954 ioc_err(ioc, "failure at %s:%d/%s()!\n",
1955 __FILE__, __LINE__, __func__);
1956 rc = -EIO;
1957 goto out;
1958 }
1959
1960 for (i = 0; i < ioc->sas_hba.num_phys; i++) {
1961 if (phy->number != i) {
1962 sas_iounit_pg1->PhyData[i].MaxMinLinkRate =
1963 (ioc->sas_hba.phy[i].phy->minimum_linkrate +
1964 (ioc->sas_hba.phy[i].phy->maximum_linkrate << 4));
1965 } else {
1966 sas_iounit_pg1->PhyData[i].MaxMinLinkRate =
1967 (rates->minimum_linkrate +
1968 (rates->maximum_linkrate << 4));
1969 }
1970 }
1971
1972 if (mpt3sas_config_set_sas_iounit_pg1(ioc, &mpi_reply, sas_iounit_pg1,
1973 sz)) {
1974 ioc_err(ioc, "failure at %s:%d/%s()!\n",
1975 __FILE__, __LINE__, __func__);
1976 rc = -ENXIO;
1977 goto out;
1978 }
1979
1980
1981 _transport_phy_reset(phy, 0);
1982
1983
1984 if (!mpt3sas_config_get_phy_pg0(ioc, &mpi_reply, &phy_pg0,
1985 phy->number)) {
1986 phy->minimum_linkrate = _transport_convert_phy_link_rate(
1987 phy_pg0.ProgrammedLinkRate & MPI2_SAS_PRATE_MIN_RATE_MASK);
1988 phy->maximum_linkrate = _transport_convert_phy_link_rate(
1989 phy_pg0.ProgrammedLinkRate >> 4);
1990 phy->negotiated_linkrate = _transport_convert_phy_link_rate(
1991 phy_pg0.NegotiatedLinkRate &
1992 MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL);
1993 }
1994
1995 out:
1996 kfree(sas_iounit_pg1);
1997 return rc;
1998 }
1999
2000 static int
2001 _transport_map_smp_buffer(struct device *dev, struct bsg_buffer *buf,
2002 dma_addr_t *dma_addr, size_t *dma_len, void **p)
2003 {
2004
2005 if (buf->sg_cnt > 1) {
2006 *p = dma_alloc_coherent(dev, buf->payload_len, dma_addr,
2007 GFP_KERNEL);
2008 if (!*p)
2009 return -ENOMEM;
2010 *dma_len = buf->payload_len;
2011 } else {
2012 if (!dma_map_sg(dev, buf->sg_list, 1, DMA_BIDIRECTIONAL))
2013 return -ENOMEM;
2014 *dma_addr = sg_dma_address(buf->sg_list);
2015 *dma_len = sg_dma_len(buf->sg_list);
2016 *p = NULL;
2017 }
2018
2019 return 0;
2020 }
2021
2022 static void
2023 _transport_unmap_smp_buffer(struct device *dev, struct bsg_buffer *buf,
2024 dma_addr_t dma_addr, void *p)
2025 {
2026 if (p)
2027 dma_free_coherent(dev, buf->payload_len, p, dma_addr);
2028 else
2029 dma_unmap_sg(dev, buf->sg_list, 1, DMA_BIDIRECTIONAL);
2030 }
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042 static void
2043 _transport_smp_handler(struct bsg_job *job, struct Scsi_Host *shost,
2044 struct sas_rphy *rphy)
2045 {
2046 struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
2047 Mpi2SmpPassthroughRequest_t *mpi_request;
2048 Mpi2SmpPassthroughReply_t *mpi_reply;
2049 int rc;
2050 u16 smid;
2051 void *psge;
2052 dma_addr_t dma_addr_in;
2053 dma_addr_t dma_addr_out;
2054 void *addr_in = NULL;
2055 void *addr_out = NULL;
2056 size_t dma_len_in;
2057 size_t dma_len_out;
2058 unsigned int reslen = 0;
2059
2060 if (ioc->shost_recovery || ioc->pci_error_recovery) {
2061 ioc_info(ioc, "%s: host reset in progress!\n", __func__);
2062 rc = -EFAULT;
2063 goto job_done;
2064 }
2065
2066 rc = mutex_lock_interruptible(&ioc->transport_cmds.mutex);
2067 if (rc)
2068 goto job_done;
2069
2070 if (ioc->transport_cmds.status != MPT3_CMD_NOT_USED) {
2071 ioc_err(ioc, "%s: transport_cmds in use\n",
2072 __func__);
2073 rc = -EAGAIN;
2074 goto out;
2075 }
2076 ioc->transport_cmds.status = MPT3_CMD_PENDING;
2077
2078 rc = _transport_map_smp_buffer(&ioc->pdev->dev, &job->request_payload,
2079 &dma_addr_out, &dma_len_out, &addr_out);
2080 if (rc)
2081 goto out;
2082 if (addr_out) {
2083 sg_copy_to_buffer(job->request_payload.sg_list,
2084 job->request_payload.sg_cnt, addr_out,
2085 job->request_payload.payload_len);
2086 }
2087
2088 rc = _transport_map_smp_buffer(&ioc->pdev->dev, &job->reply_payload,
2089 &dma_addr_in, &dma_len_in, &addr_in);
2090 if (rc)
2091 goto unmap_out;
2092
2093 rc = mpt3sas_wait_for_ioc(ioc, IOC_OPERATIONAL_WAIT_COUNT);
2094 if (rc)
2095 goto unmap_in;
2096
2097 smid = mpt3sas_base_get_smid(ioc, ioc->transport_cb_idx);
2098 if (!smid) {
2099 ioc_err(ioc, "%s: failed obtaining a smid\n", __func__);
2100 rc = -EAGAIN;
2101 goto unmap_in;
2102 }
2103
2104 rc = 0;
2105 mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
2106 ioc->transport_cmds.smid = smid;
2107
2108 memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t));
2109 mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
2110 mpi_request->PhysicalPort = _transport_get_port_id_by_rphy(ioc, rphy);
2111 mpi_request->SASAddress = (rphy) ?
2112 cpu_to_le64(rphy->identify.sas_address) :
2113 cpu_to_le64(ioc->sas_hba.sas_address);
2114 mpi_request->RequestDataLength = cpu_to_le16(dma_len_out - 4);
2115 psge = &mpi_request->SGL;
2116
2117 ioc->build_sg(ioc, psge, dma_addr_out, dma_len_out - 4, dma_addr_in,
2118 dma_len_in - 4);
2119
2120 dtransportprintk(ioc,
2121 ioc_info(ioc, "%s: sending smp request\n", __func__));
2122
2123 init_completion(&ioc->transport_cmds.done);
2124 ioc->put_smid_default(ioc, smid);
2125 wait_for_completion_timeout(&ioc->transport_cmds.done, 10*HZ);
2126
2127 if (!(ioc->transport_cmds.status & MPT3_CMD_COMPLETE)) {
2128 ioc_err(ioc, "%s: timeout\n", __func__);
2129 _debug_dump_mf(mpi_request,
2130 sizeof(Mpi2SmpPassthroughRequest_t)/4);
2131 if (!(ioc->transport_cmds.status & MPT3_CMD_RESET)) {
2132 mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER);
2133 rc = -ETIMEDOUT;
2134 goto unmap_in;
2135 }
2136 }
2137
2138 dtransportprintk(ioc, ioc_info(ioc, "%s - complete\n", __func__));
2139
2140 if (!(ioc->transport_cmds.status & MPT3_CMD_REPLY_VALID)) {
2141 dtransportprintk(ioc,
2142 ioc_info(ioc, "%s: no reply\n", __func__));
2143 rc = -ENXIO;
2144 goto unmap_in;
2145 }
2146
2147 mpi_reply = ioc->transport_cmds.reply;
2148
2149 dtransportprintk(ioc,
2150 ioc_info(ioc, "%s: reply data transfer size(%d)\n",
2151 __func__,
2152 le16_to_cpu(mpi_reply->ResponseDataLength)));
2153
2154 memcpy(job->reply, mpi_reply, sizeof(*mpi_reply));
2155 job->reply_len = sizeof(*mpi_reply);
2156 reslen = le16_to_cpu(mpi_reply->ResponseDataLength);
2157
2158 if (addr_in) {
2159 sg_copy_to_buffer(job->reply_payload.sg_list,
2160 job->reply_payload.sg_cnt, addr_in,
2161 job->reply_payload.payload_len);
2162 }
2163
2164 rc = 0;
2165 unmap_in:
2166 _transport_unmap_smp_buffer(&ioc->pdev->dev, &job->reply_payload,
2167 dma_addr_in, addr_in);
2168 unmap_out:
2169 _transport_unmap_smp_buffer(&ioc->pdev->dev, &job->request_payload,
2170 dma_addr_out, addr_out);
2171 out:
2172 ioc->transport_cmds.status = MPT3_CMD_NOT_USED;
2173 mutex_unlock(&ioc->transport_cmds.mutex);
2174 job_done:
2175 bsg_job_done(job, rc, reslen);
2176 }
2177
2178 struct sas_function_template mpt3sas_transport_functions = {
2179 .get_linkerrors = _transport_get_linkerrors,
2180 .get_enclosure_identifier = _transport_get_enclosure_identifier,
2181 .get_bay_identifier = _transport_get_bay_identifier,
2182 .phy_reset = _transport_phy_reset,
2183 .phy_enable = _transport_phy_enable,
2184 .set_phy_speed = _transport_phy_speed,
2185 .smp_handler = _transport_smp_handler,
2186 };
2187
2188 struct scsi_transport_template *mpt3sas_transport_template;