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 | |
| 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>
| -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); |
