aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband
diff options
context:
space:
mode:
authorMike Marciniszyn <mike.marciniszyn@qlogic.com>2011-01-10 20:42:19 -0500
committerRoland Dreier <rolandd@cisco.com>2011-01-10 20:42:19 -0500
commit3c9e5f4d657170c2fbc3d382d2daae3820713a6c (patch)
tree5d3417d0d69c1d6610d1c6ab5ea597ed2242e4cb /drivers/infiniband
parenta377acd15188cf11e47a67af5feea098cd8b25d2 (diff)
IB/qib: Set port physical state even if other fields are invalid
The IBTA vol. 1 release 1.2.1 spec. says: C14-24.2.1: If PortInfo:Portstate=Down, then a SubnSet(PortInfo) shall make any changes it specifies to PortInfo:PortPhysicalState; any other result is vendor-dependent. The patch changes the error handling so that the reply says there are invalid fields but still attempts to set fields that are in range including PortInfo:PortPhysicalState. Signed-off-by: Mike Marciniszyn <mike.marciniszyn@qlogic.com> Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband')
-rw-r--r--drivers/infiniband/hw/qib/qib_mad.c45
1 files changed, 25 insertions, 20 deletions
diff --git a/drivers/infiniband/hw/qib/qib_mad.c b/drivers/infiniband/hw/qib/qib_mad.c
index 94b0d1f3a8f0..5ad224e4a38b 100644
--- a/drivers/infiniband/hw/qib/qib_mad.c
+++ b/drivers/infiniband/hw/qib/qib_mad.c
@@ -668,8 +668,8 @@ static int subn_set_portinfo(struct ib_smp *smp, struct ib_device *ibdev,
668 lid = be16_to_cpu(pip->lid); 668 lid = be16_to_cpu(pip->lid);
669 /* Must be a valid unicast LID address. */ 669 /* Must be a valid unicast LID address. */
670 if (lid == 0 || lid >= QIB_MULTICAST_LID_BASE) 670 if (lid == 0 || lid >= QIB_MULTICAST_LID_BASE)
671 goto err; 671 smp->status |= IB_SMP_INVALID_FIELD;
672 if (ppd->lid != lid || ppd->lmc != (pip->mkeyprot_resv_lmc & 7)) { 672 else if (ppd->lid != lid || ppd->lmc != (pip->mkeyprot_resv_lmc & 7)) {
673 if (ppd->lid != lid) 673 if (ppd->lid != lid)
674 qib_set_uevent_bits(ppd, _QIB_EVENT_LID_CHANGE_BIT); 674 qib_set_uevent_bits(ppd, _QIB_EVENT_LID_CHANGE_BIT);
675 if (ppd->lmc != (pip->mkeyprot_resv_lmc & 7)) 675 if (ppd->lmc != (pip->mkeyprot_resv_lmc & 7))
@@ -683,8 +683,8 @@ static int subn_set_portinfo(struct ib_smp *smp, struct ib_device *ibdev,
683 msl = pip->neighbormtu_mastersmsl & 0xF; 683 msl = pip->neighbormtu_mastersmsl & 0xF;
684 /* Must be a valid unicast LID address. */ 684 /* Must be a valid unicast LID address. */
685 if (smlid == 0 || smlid >= QIB_MULTICAST_LID_BASE) 685 if (smlid == 0 || smlid >= QIB_MULTICAST_LID_BASE)
686 goto err; 686 smp->status |= IB_SMP_INVALID_FIELD;
687 if (smlid != ibp->sm_lid || msl != ibp->sm_sl) { 687 else if (smlid != ibp->sm_lid || msl != ibp->sm_sl) {
688 spin_lock_irqsave(&ibp->lock, flags); 688 spin_lock_irqsave(&ibp->lock, flags);
689 if (ibp->sm_ah) { 689 if (ibp->sm_ah) {
690 if (smlid != ibp->sm_lid) 690 if (smlid != ibp->sm_lid)
@@ -707,8 +707,9 @@ static int subn_set_portinfo(struct ib_smp *smp, struct ib_device *ibdev,
707 if (lwe == 0xFF) 707 if (lwe == 0xFF)
708 lwe = ppd->link_width_supported; 708 lwe = ppd->link_width_supported;
709 else if (lwe >= 16 || (lwe & ~ppd->link_width_supported)) 709 else if (lwe >= 16 || (lwe & ~ppd->link_width_supported))
710 goto err; 710 smp->status |= IB_SMP_INVALID_FIELD;
711 set_link_width_enabled(ppd, lwe); 711 else if (lwe != ppd->link_width_enabled)
712 set_link_width_enabled(ppd, lwe);
712 } 713 }
713 714
714 lse = pip->linkspeedactive_enabled & 0xF; 715 lse = pip->linkspeedactive_enabled & 0xF;
@@ -721,8 +722,9 @@ static int subn_set_portinfo(struct ib_smp *smp, struct ib_device *ibdev,
721 if (lse == 15) 722 if (lse == 15)
722 lse = ppd->link_speed_supported; 723 lse = ppd->link_speed_supported;
723 else if (lse >= 8 || (lse & ~ppd->link_speed_supported)) 724 else if (lse >= 8 || (lse & ~ppd->link_speed_supported))
724 goto err; 725 smp->status |= IB_SMP_INVALID_FIELD;
725 set_link_speed_enabled(ppd, lse); 726 else if (lse != ppd->link_speed_enabled)
727 set_link_speed_enabled(ppd, lse);
726 } 728 }
727 729
728 /* Set link down default state. */ 730 /* Set link down default state. */
@@ -738,7 +740,7 @@ static int subn_set_portinfo(struct ib_smp *smp, struct ib_device *ibdev,
738 IB_LINKINITCMD_POLL); 740 IB_LINKINITCMD_POLL);
739 break; 741 break;
740 default: 742 default:
741 goto err; 743 smp->status |= IB_SMP_INVALID_FIELD;
742 } 744 }
743 745
744 ibp->mkeyprot = pip->mkeyprot_resv_lmc >> 6; 746 ibp->mkeyprot = pip->mkeyprot_resv_lmc >> 6;
@@ -748,15 +750,17 @@ static int subn_set_portinfo(struct ib_smp *smp, struct ib_device *ibdev,
748 750
749 mtu = ib_mtu_enum_to_int((pip->neighbormtu_mastersmsl >> 4) & 0xF); 751 mtu = ib_mtu_enum_to_int((pip->neighbormtu_mastersmsl >> 4) & 0xF);
750 if (mtu == -1) 752 if (mtu == -1)
751 goto err; 753 smp->status |= IB_SMP_INVALID_FIELD;
752 qib_set_mtu(ppd, mtu); 754 else
755 qib_set_mtu(ppd, mtu);
753 756
754 /* Set operational VLs */ 757 /* Set operational VLs */
755 vls = (pip->operationalvl_pei_peo_fpi_fpo >> 4) & 0xF; 758 vls = (pip->operationalvl_pei_peo_fpi_fpo >> 4) & 0xF;
756 if (vls) { 759 if (vls) {
757 if (vls > ppd->vls_supported) 760 if (vls > ppd->vls_supported)
758 goto err; 761 smp->status |= IB_SMP_INVALID_FIELD;
759 (void) dd->f_set_ib_cfg(ppd, QIB_IB_CFG_OP_VLS, vls); 762 else
763 (void) dd->f_set_ib_cfg(ppd, QIB_IB_CFG_OP_VLS, vls);
760 } 764 }
761 765
762 if (pip->mkey_violations == 0) 766 if (pip->mkey_violations == 0)
@@ -770,10 +774,10 @@ static int subn_set_portinfo(struct ib_smp *smp, struct ib_device *ibdev,
770 774
771 ore = pip->localphyerrors_overrunerrors; 775 ore = pip->localphyerrors_overrunerrors;
772 if (set_phyerrthreshold(ppd, (ore >> 4) & 0xF)) 776 if (set_phyerrthreshold(ppd, (ore >> 4) & 0xF))
773 goto err; 777 smp->status |= IB_SMP_INVALID_FIELD;
774 778
775 if (set_overrunthreshold(ppd, (ore & 0xF))) 779 if (set_overrunthreshold(ppd, (ore & 0xF)))
776 goto err; 780 smp->status |= IB_SMP_INVALID_FIELD;
777 781
778 ibp->subnet_timeout = pip->clientrereg_resv_subnetto & 0x1F; 782 ibp->subnet_timeout = pip->clientrereg_resv_subnetto & 0x1F;
779 783
@@ -792,7 +796,7 @@ static int subn_set_portinfo(struct ib_smp *smp, struct ib_device *ibdev,
792 state = pip->linkspeed_portstate & 0xF; 796 state = pip->linkspeed_portstate & 0xF;
793 lstate = (pip->portphysstate_linkdown >> 4) & 0xF; 797 lstate = (pip->portphysstate_linkdown >> 4) & 0xF;
794 if (lstate && !(state == IB_PORT_DOWN || state == IB_PORT_NOP)) 798 if (lstate && !(state == IB_PORT_DOWN || state == IB_PORT_NOP))
795 goto err; 799 smp->status |= IB_SMP_INVALID_FIELD;
796 800
797 /* 801 /*
798 * Only state changes of DOWN, ARM, and ACTIVE are valid 802 * Only state changes of DOWN, ARM, and ACTIVE are valid
@@ -812,8 +816,10 @@ static int subn_set_portinfo(struct ib_smp *smp, struct ib_device *ibdev,
812 lstate = QIB_IB_LINKDOWN; 816 lstate = QIB_IB_LINKDOWN;
813 else if (lstate == 3) 817 else if (lstate == 3)
814 lstate = QIB_IB_LINKDOWN_DISABLE; 818 lstate = QIB_IB_LINKDOWN_DISABLE;
815 else 819 else {
816 goto err; 820 smp->status |= IB_SMP_INVALID_FIELD;
821 break;
822 }
817 spin_lock_irqsave(&ppd->lflags_lock, flags); 823 spin_lock_irqsave(&ppd->lflags_lock, flags);
818 ppd->lflags &= ~QIBL_LINKV; 824 ppd->lflags &= ~QIBL_LINKV;
819 spin_unlock_irqrestore(&ppd->lflags_lock, flags); 825 spin_unlock_irqrestore(&ppd->lflags_lock, flags);
@@ -835,8 +841,7 @@ static int subn_set_portinfo(struct ib_smp *smp, struct ib_device *ibdev,
835 qib_set_linkstate(ppd, QIB_IB_LINKACTIVE); 841 qib_set_linkstate(ppd, QIB_IB_LINKACTIVE);
836 break; 842 break;
837 default: 843 default:
838 /* XXX We have already partially updated our state! */ 844 smp->status |= IB_SMP_INVALID_FIELD;
839 goto err;
840 } 845 }
841 846
842 ret = subn_get_portinfo(smp, ibdev, port); 847 ret = subn_get_portinfo(smp, ibdev, port);