Commit 3c9e5f4d authored by Mike Marciniszyn's avatar Mike Marciniszyn Committed by Roland Dreier

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: default avatarMike Marciniszyn <mike.marciniszyn@qlogic.com>
Signed-off-by: default avatarRoland Dreier <rolandd@cisco.com>
parent a377acd1
...@@ -668,8 +668,8 @@ static int subn_set_portinfo(struct ib_smp *smp, struct ib_device *ibdev, ...@@ -668,8 +668,8 @@ static int subn_set_portinfo(struct ib_smp *smp, struct ib_device *ibdev,
lid = be16_to_cpu(pip->lid); lid = be16_to_cpu(pip->lid);
/* Must be a valid unicast LID address. */ /* Must be a valid unicast LID address. */
if (lid == 0 || lid >= QIB_MULTICAST_LID_BASE) if (lid == 0 || lid >= QIB_MULTICAST_LID_BASE)
goto err; smp->status |= IB_SMP_INVALID_FIELD;
if (ppd->lid != lid || ppd->lmc != (pip->mkeyprot_resv_lmc & 7)) { else if (ppd->lid != lid || ppd->lmc != (pip->mkeyprot_resv_lmc & 7)) {
if (ppd->lid != lid) if (ppd->lid != lid)
qib_set_uevent_bits(ppd, _QIB_EVENT_LID_CHANGE_BIT); qib_set_uevent_bits(ppd, _QIB_EVENT_LID_CHANGE_BIT);
if (ppd->lmc != (pip->mkeyprot_resv_lmc & 7)) 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,8 +683,8 @@ static int subn_set_portinfo(struct ib_smp *smp, struct ib_device *ibdev,
msl = pip->neighbormtu_mastersmsl & 0xF; msl = pip->neighbormtu_mastersmsl & 0xF;
/* Must be a valid unicast LID address. */ /* Must be a valid unicast LID address. */
if (smlid == 0 || smlid >= QIB_MULTICAST_LID_BASE) if (smlid == 0 || smlid >= QIB_MULTICAST_LID_BASE)
goto err; smp->status |= IB_SMP_INVALID_FIELD;
if (smlid != ibp->sm_lid || msl != ibp->sm_sl) { else if (smlid != ibp->sm_lid || msl != ibp->sm_sl) {
spin_lock_irqsave(&ibp->lock, flags); spin_lock_irqsave(&ibp->lock, flags);
if (ibp->sm_ah) { if (ibp->sm_ah) {
if (smlid != ibp->sm_lid) if (smlid != ibp->sm_lid)
...@@ -707,8 +707,9 @@ static int subn_set_portinfo(struct ib_smp *smp, struct ib_device *ibdev, ...@@ -707,8 +707,9 @@ static int subn_set_portinfo(struct ib_smp *smp, struct ib_device *ibdev,
if (lwe == 0xFF) if (lwe == 0xFF)
lwe = ppd->link_width_supported; lwe = ppd->link_width_supported;
else if (lwe >= 16 || (lwe & ~ppd->link_width_supported)) else if (lwe >= 16 || (lwe & ~ppd->link_width_supported))
goto err; smp->status |= IB_SMP_INVALID_FIELD;
set_link_width_enabled(ppd, lwe); else if (lwe != ppd->link_width_enabled)
set_link_width_enabled(ppd, lwe);
} }
lse = pip->linkspeedactive_enabled & 0xF; lse = pip->linkspeedactive_enabled & 0xF;
...@@ -721,8 +722,9 @@ static int subn_set_portinfo(struct ib_smp *smp, struct ib_device *ibdev, ...@@ -721,8 +722,9 @@ static int subn_set_portinfo(struct ib_smp *smp, struct ib_device *ibdev,
if (lse == 15) if (lse == 15)
lse = ppd->link_speed_supported; lse = ppd->link_speed_supported;
else if (lse >= 8 || (lse & ~ppd->link_speed_supported)) else if (lse >= 8 || (lse & ~ppd->link_speed_supported))
goto err; smp->status |= IB_SMP_INVALID_FIELD;
set_link_speed_enabled(ppd, lse); else if (lse != ppd->link_speed_enabled)
set_link_speed_enabled(ppd, lse);
} }
/* Set link down default state. */ /* Set link down default state. */
...@@ -738,7 +740,7 @@ static int subn_set_portinfo(struct ib_smp *smp, struct ib_device *ibdev, ...@@ -738,7 +740,7 @@ static int subn_set_portinfo(struct ib_smp *smp, struct ib_device *ibdev,
IB_LINKINITCMD_POLL); IB_LINKINITCMD_POLL);
break; break;
default: default:
goto err; smp->status |= IB_SMP_INVALID_FIELD;
} }
ibp->mkeyprot = pip->mkeyprot_resv_lmc >> 6; 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,15 +750,17 @@ static int subn_set_portinfo(struct ib_smp *smp, struct ib_device *ibdev,
mtu = ib_mtu_enum_to_int((pip->neighbormtu_mastersmsl >> 4) & 0xF); mtu = ib_mtu_enum_to_int((pip->neighbormtu_mastersmsl >> 4) & 0xF);
if (mtu == -1) if (mtu == -1)
goto err; smp->status |= IB_SMP_INVALID_FIELD;
qib_set_mtu(ppd, mtu); else
qib_set_mtu(ppd, mtu);
/* Set operational VLs */ /* Set operational VLs */
vls = (pip->operationalvl_pei_peo_fpi_fpo >> 4) & 0xF; vls = (pip->operationalvl_pei_peo_fpi_fpo >> 4) & 0xF;
if (vls) { if (vls) {
if (vls > ppd->vls_supported) if (vls > ppd->vls_supported)
goto err; smp->status |= IB_SMP_INVALID_FIELD;
(void) dd->f_set_ib_cfg(ppd, QIB_IB_CFG_OP_VLS, vls); else
(void) dd->f_set_ib_cfg(ppd, QIB_IB_CFG_OP_VLS, vls);
} }
if (pip->mkey_violations == 0) if (pip->mkey_violations == 0)
...@@ -770,10 +774,10 @@ static int subn_set_portinfo(struct ib_smp *smp, struct ib_device *ibdev, ...@@ -770,10 +774,10 @@ static int subn_set_portinfo(struct ib_smp *smp, struct ib_device *ibdev,
ore = pip->localphyerrors_overrunerrors; ore = pip->localphyerrors_overrunerrors;
if (set_phyerrthreshold(ppd, (ore >> 4) & 0xF)) if (set_phyerrthreshold(ppd, (ore >> 4) & 0xF))
goto err; smp->status |= IB_SMP_INVALID_FIELD;
if (set_overrunthreshold(ppd, (ore & 0xF))) if (set_overrunthreshold(ppd, (ore & 0xF)))
goto err; smp->status |= IB_SMP_INVALID_FIELD;
ibp->subnet_timeout = pip->clientrereg_resv_subnetto & 0x1F; ibp->subnet_timeout = pip->clientrereg_resv_subnetto & 0x1F;
...@@ -792,7 +796,7 @@ static int subn_set_portinfo(struct ib_smp *smp, struct ib_device *ibdev, ...@@ -792,7 +796,7 @@ static int subn_set_portinfo(struct ib_smp *smp, struct ib_device *ibdev,
state = pip->linkspeed_portstate & 0xF; state = pip->linkspeed_portstate & 0xF;
lstate = (pip->portphysstate_linkdown >> 4) & 0xF; lstate = (pip->portphysstate_linkdown >> 4) & 0xF;
if (lstate && !(state == IB_PORT_DOWN || state == IB_PORT_NOP)) if (lstate && !(state == IB_PORT_DOWN || state == IB_PORT_NOP))
goto err; smp->status |= IB_SMP_INVALID_FIELD;
/* /*
* Only state changes of DOWN, ARM, and ACTIVE are valid * 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,8 +816,10 @@ static int subn_set_portinfo(struct ib_smp *smp, struct ib_device *ibdev,
lstate = QIB_IB_LINKDOWN; lstate = QIB_IB_LINKDOWN;
else if (lstate == 3) else if (lstate == 3)
lstate = QIB_IB_LINKDOWN_DISABLE; lstate = QIB_IB_LINKDOWN_DISABLE;
else else {
goto err; smp->status |= IB_SMP_INVALID_FIELD;
break;
}
spin_lock_irqsave(&ppd->lflags_lock, flags); spin_lock_irqsave(&ppd->lflags_lock, flags);
ppd->lflags &= ~QIBL_LINKV; ppd->lflags &= ~QIBL_LINKV;
spin_unlock_irqrestore(&ppd->lflags_lock, flags); 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,8 +841,7 @@ static int subn_set_portinfo(struct ib_smp *smp, struct ib_device *ibdev,
qib_set_linkstate(ppd, QIB_IB_LINKACTIVE); qib_set_linkstate(ppd, QIB_IB_LINKACTIVE);
break; break;
default: default:
/* XXX We have already partially updated our state! */ smp->status |= IB_SMP_INVALID_FIELD;
goto err;
} }
ret = subn_get_portinfo(smp, ibdev, port); ret = subn_get_portinfo(smp, ibdev, port);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment