diff options
author | Mike Marciniszyn <mike.marciniszyn@qlogic.com> | 2011-01-10 20:42:19 -0500 |
---|---|---|
committer | Roland Dreier <rolandd@cisco.com> | 2011-01-10 20:42:19 -0500 |
commit | 3c9e5f4d657170c2fbc3d382d2daae3820713a6c (patch) | |
tree | 5d3417d0d69c1d6610d1c6ab5ea597ed2242e4cb /drivers/infiniband | |
parent | a377acd15188cf11e47a67af5feea098cd8b25d2 (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.c | 45 |
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); |