aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/mpt2sas/mpt2sas_transport.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/mpt2sas/mpt2sas_transport.c')
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_transport.c89
1 files changed, 87 insertions, 2 deletions
diff --git a/drivers/scsi/mpt2sas/mpt2sas_transport.c b/drivers/scsi/mpt2sas/mpt2sas_transport.c
index bd7ca2b49f8..2727c3b6510 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_transport.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_transport.c
@@ -2,7 +2,7 @@
2 * SAS Transport Layer for MPT (Message Passing Technology) based controllers 2 * SAS Transport Layer for MPT (Message Passing Technology) based controllers
3 * 3 *
4 * This code is based on drivers/scsi/mpt2sas/mpt2_transport.c 4 * This code is based on drivers/scsi/mpt2sas/mpt2_transport.c
5 * Copyright (C) 2007-2009 LSI Corporation 5 * Copyright (C) 2007-2010 LSI Corporation
6 * (mailto:DL-MPTFusionLinux@lsi.com) 6 * (mailto:DL-MPTFusionLinux@lsi.com)
7 * 7 *
8 * This program is free software; you can redistribute it and/or 8 * This program is free software; you can redistribute it and/or
@@ -465,6 +465,85 @@ _transport_expander_report_manufacture(struct MPT2SAS_ADAPTER *ioc,
465 return rc; 465 return rc;
466} 466}
467 467
468
469/**
470 * _transport_delete_duplicate_port - (see below description)
471 * @ioc: per adapter object
472 * @sas_node: sas node object (either expander or sas host)
473 * @sas_address: sas address of device being added
474 * @phy_num: phy number
475 *
476 * This function is called when attempting to add a new port that is claiming
477 * the same phy resources already in use by another port. If we don't release
478 * the claimed phy resources, the sas transport layer will hang from the BUG
479 * in sas_port_add_phy.
480 *
481 * The reason we would hit this issue is becuase someone is changing the
482 * sas address of a device on the fly, meanwhile controller firmware sends
483 * EVENTs out of order when removing the previous instance of the device.
484 */
485static void
486_transport_delete_duplicate_port(struct MPT2SAS_ADAPTER *ioc,
487 struct _sas_node *sas_node, u64 sas_address, int phy_num)
488{
489 struct _sas_port *mpt2sas_port, *mpt2sas_port_duplicate;
490 struct _sas_phy *mpt2sas_phy;
491
492 printk(MPT2SAS_ERR_FMT "new device located at sas_addr(0x%016llx), "
493 "phy_id(%d)\n", ioc->name, (unsigned long long)sas_address,
494 phy_num);
495
496 mpt2sas_port_duplicate = NULL;
497 list_for_each_entry(mpt2sas_port, &sas_node->sas_port_list, port_list) {
498 dev_printk(KERN_ERR, &mpt2sas_port->port->dev,
499 "existing device at sas_addr(0x%016llx), num_phys(%d)\n",
500 (unsigned long long)
501 mpt2sas_port->remote_identify.sas_address,
502 mpt2sas_port->num_phys);
503 list_for_each_entry(mpt2sas_phy, &mpt2sas_port->phy_list,
504 port_siblings) {
505 dev_printk(KERN_ERR, &mpt2sas_phy->phy->dev,
506 "phy_number(%d)\n", mpt2sas_phy->phy_id);
507 if (mpt2sas_phy->phy_id == phy_num)
508 mpt2sas_port_duplicate = mpt2sas_port;
509 }
510 }
511
512 if (!mpt2sas_port_duplicate)
513 return;
514
515 dev_printk(KERN_ERR, &mpt2sas_port_duplicate->port->dev,
516 "deleting duplicate device at sas_addr(0x%016llx), phy(%d)!!!!\n",
517 (unsigned long long)
518 mpt2sas_port_duplicate->remote_identify.sas_address, phy_num);
519 ioc->logging_level |= MPT_DEBUG_TRANSPORT;
520 mpt2sas_transport_port_remove(ioc,
521 mpt2sas_port_duplicate->remote_identify.sas_address,
522 sas_node->sas_address);
523 ioc->logging_level &= ~MPT_DEBUG_TRANSPORT;
524}
525
526/**
527 * _transport_sanity_check - sanity check when adding a new port
528 * @ioc: per adapter object
529 * @sas_node: sas node object (either expander or sas host)
530 * @sas_address: sas address of device being added
531 *
532 * See the explanation above from _transport_delete_duplicate_port
533 */
534static void
535_transport_sanity_check(struct MPT2SAS_ADAPTER *ioc, struct _sas_node *sas_node,
536 u64 sas_address)
537{
538 int i;
539
540 for (i = 0; i < sas_node->num_phys; i++)
541 if (sas_node->phy[i].remote_identify.sas_address == sas_address)
542 if (sas_node->phy[i].phy_belongs_to_port)
543 _transport_delete_duplicate_port(ioc, sas_node,
544 sas_address, i);
545}
546
468/** 547/**
469 * mpt2sas_transport_port_add - insert port to the list 548 * mpt2sas_transport_port_add - insert port to the list
470 * @ioc: per adapter object 549 * @ioc: per adapter object
@@ -522,6 +601,9 @@ mpt2sas_transport_port_add(struct MPT2SAS_ADAPTER *ioc, u16 handle,
522 goto out_fail; 601 goto out_fail;
523 } 602 }
524 603
604 _transport_sanity_check(ioc, sas_node,
605 mpt2sas_port->remote_identify.sas_address);
606
525 for (i = 0; i < sas_node->num_phys; i++) { 607 for (i = 0; i < sas_node->num_phys; i++) {
526 if (sas_node->phy[i].remote_identify.sas_address != 608 if (sas_node->phy[i].remote_identify.sas_address !=
527 mpt2sas_port->remote_identify.sas_address) 609 mpt2sas_port->remote_identify.sas_address)
@@ -553,6 +635,7 @@ mpt2sas_transport_port_add(struct MPT2SAS_ADAPTER *ioc, u16 handle,
553 mpt2sas_port->remote_identify.sas_address, 635 mpt2sas_port->remote_identify.sas_address,
554 mpt2sas_phy->phy_id); 636 mpt2sas_phy->phy_id);
555 sas_port_add_phy(port, mpt2sas_phy->phy); 637 sas_port_add_phy(port, mpt2sas_phy->phy);
638 mpt2sas_phy->phy_belongs_to_port = 1;
556 } 639 }
557 640
558 mpt2sas_port->port = port; 641 mpt2sas_port->port = port;
@@ -651,6 +734,7 @@ mpt2sas_transport_port_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address,
651 (unsigned long long) 734 (unsigned long long)
652 mpt2sas_port->remote_identify.sas_address, 735 mpt2sas_port->remote_identify.sas_address,
653 mpt2sas_phy->phy_id); 736 mpt2sas_phy->phy_id);
737 mpt2sas_phy->phy_belongs_to_port = 0;
654 sas_port_delete_phy(mpt2sas_port->port, mpt2sas_phy->phy); 738 sas_port_delete_phy(mpt2sas_port->port, mpt2sas_phy->phy);
655 list_del(&mpt2sas_phy->port_siblings); 739 list_del(&mpt2sas_phy->port_siblings);
656 } 740 }
@@ -1341,7 +1425,8 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
1341 memcpy(req->sense, mpi_reply, sizeof(*mpi_reply)); 1425 memcpy(req->sense, mpi_reply, sizeof(*mpi_reply));
1342 req->sense_len = sizeof(*mpi_reply); 1426 req->sense_len = sizeof(*mpi_reply);
1343 req->resid_len = 0; 1427 req->resid_len = 0;
1344 rsp->resid_len -= mpi_reply->ResponseDataLength; 1428 rsp->resid_len -=
1429 le16_to_cpu(mpi_reply->ResponseDataLength);
1345 } else { 1430 } else {
1346 dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT 1431 dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT
1347 "%s - no reply\n", ioc->name, __func__)); 1432 "%s - no reply\n", ioc->name, __func__));