diff options
author | Moni Shoua <monis@voltaire.com> | 2009-01-28 17:54:35 -0500 |
---|---|---|
committer | Roland Dreier <rolandd@cisco.com> | 2009-01-28 17:54:35 -0500 |
commit | f0f6f346a1edaec23b990c25f53478669e56fa70 (patch) | |
tree | 874c70fae081386ca3408c358f14de231edf68ce /drivers/infiniband | |
parent | f3b8436ad9a8ad36b3c9fa1fe030c7f38e5d3d0b (diff) |
IB/mlx4: Fix dispatch of IB_EVENT_LID_CHANGE event
When snooping a PortInfo MAD, its client_reregister bit is checked.
If the bit is ON then a CLIENT_REREGISTER event is dispatched,
otherwise a LID_CHANGE event is dispatched. This way of decision
ignores the cases where the MAD changes the LID along with an
instruction to reregister (so a necessary LID_CHANGE event won't be
dispatched) or the MAD is neither of these (and an unnecessary
LID_CHANGE event will be dispatched).
This causes problems at least with IPoIB, which will do a "light"
flush on reregister, rather than the "heavy" flush required due to a
LID change.
Fix this by dispatching a CLIENT_REREGISTER event if the
client_reregister bit is set, but also compare the LID in the MAD to
the current LID. If and only if they are not identical then a
LID_CHANGE event is dispatched.
Signed-off-by: Moni Shoua <monis@voltaire.com>
Signed-off-by: Jack Morgenstein <jackm@dev.mellanox.co.il>
Signed-off-by: Yossi Etigin <yosefe@voltaire.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband')
-rw-r--r-- | drivers/infiniband/hw/mlx4/mad.c | 27 |
1 files changed, 20 insertions, 7 deletions
diff --git a/drivers/infiniband/hw/mlx4/mad.c b/drivers/infiniband/hw/mlx4/mad.c index 606f1e2ef284..19e68ab66168 100644 --- a/drivers/infiniband/hw/mlx4/mad.c +++ b/drivers/infiniband/hw/mlx4/mad.c | |||
@@ -147,7 +147,8 @@ static void update_sm_ah(struct mlx4_ib_dev *dev, u8 port_num, u16 lid, u8 sl) | |||
147 | * Snoop SM MADs for port info and P_Key table sets, so we can | 147 | * Snoop SM MADs for port info and P_Key table sets, so we can |
148 | * synthesize LID change and P_Key change events. | 148 | * synthesize LID change and P_Key change events. |
149 | */ | 149 | */ |
150 | static void smp_snoop(struct ib_device *ibdev, u8 port_num, struct ib_mad *mad) | 150 | static void smp_snoop(struct ib_device *ibdev, u8 port_num, struct ib_mad *mad, |
151 | u16 prev_lid) | ||
151 | { | 152 | { |
152 | struct ib_event event; | 153 | struct ib_event event; |
153 | 154 | ||
@@ -157,6 +158,7 @@ static void smp_snoop(struct ib_device *ibdev, u8 port_num, struct ib_mad *mad) | |||
157 | if (mad->mad_hdr.attr_id == IB_SMP_ATTR_PORT_INFO) { | 158 | if (mad->mad_hdr.attr_id == IB_SMP_ATTR_PORT_INFO) { |
158 | struct ib_port_info *pinfo = | 159 | struct ib_port_info *pinfo = |
159 | (struct ib_port_info *) ((struct ib_smp *) mad)->data; | 160 | (struct ib_port_info *) ((struct ib_smp *) mad)->data; |
161 | u16 lid = be16_to_cpu(pinfo->lid); | ||
160 | 162 | ||
161 | update_sm_ah(to_mdev(ibdev), port_num, | 163 | update_sm_ah(to_mdev(ibdev), port_num, |
162 | be16_to_cpu(pinfo->sm_lid), | 164 | be16_to_cpu(pinfo->sm_lid), |
@@ -165,12 +167,15 @@ static void smp_snoop(struct ib_device *ibdev, u8 port_num, struct ib_mad *mad) | |||
165 | event.device = ibdev; | 167 | event.device = ibdev; |
166 | event.element.port_num = port_num; | 168 | event.element.port_num = port_num; |
167 | 169 | ||
168 | if (pinfo->clientrereg_resv_subnetto & 0x80) | 170 | if (pinfo->clientrereg_resv_subnetto & 0x80) { |
169 | event.event = IB_EVENT_CLIENT_REREGISTER; | 171 | event.event = IB_EVENT_CLIENT_REREGISTER; |
170 | else | 172 | ib_dispatch_event(&event); |
171 | event.event = IB_EVENT_LID_CHANGE; | 173 | } |
172 | 174 | ||
173 | ib_dispatch_event(&event); | 175 | if (prev_lid != lid) { |
176 | event.event = IB_EVENT_LID_CHANGE; | ||
177 | ib_dispatch_event(&event); | ||
178 | } | ||
174 | } | 179 | } |
175 | 180 | ||
176 | if (mad->mad_hdr.attr_id == IB_SMP_ATTR_PKEY_TABLE) { | 181 | if (mad->mad_hdr.attr_id == IB_SMP_ATTR_PKEY_TABLE) { |
@@ -228,8 +233,9 @@ int mlx4_ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, | |||
228 | struct ib_wc *in_wc, struct ib_grh *in_grh, | 233 | struct ib_wc *in_wc, struct ib_grh *in_grh, |
229 | struct ib_mad *in_mad, struct ib_mad *out_mad) | 234 | struct ib_mad *in_mad, struct ib_mad *out_mad) |
230 | { | 235 | { |
231 | u16 slid; | 236 | u16 slid, prev_lid = 0; |
232 | int err; | 237 | int err; |
238 | struct ib_port_attr pattr; | ||
233 | 239 | ||
234 | slid = in_wc ? in_wc->slid : be16_to_cpu(IB_LID_PERMISSIVE); | 240 | slid = in_wc ? in_wc->slid : be16_to_cpu(IB_LID_PERMISSIVE); |
235 | 241 | ||
@@ -263,6 +269,13 @@ int mlx4_ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, | |||
263 | } else | 269 | } else |
264 | return IB_MAD_RESULT_SUCCESS; | 270 | return IB_MAD_RESULT_SUCCESS; |
265 | 271 | ||
272 | if ((in_mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_LID_ROUTED || | ||
273 | in_mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) && | ||
274 | in_mad->mad_hdr.method == IB_MGMT_METHOD_SET && | ||
275 | in_mad->mad_hdr.attr_id == IB_SMP_ATTR_PORT_INFO && | ||
276 | !ib_query_port(ibdev, port_num, &pattr)) | ||
277 | prev_lid = pattr.lid; | ||
278 | |||
266 | err = mlx4_MAD_IFC(to_mdev(ibdev), | 279 | err = mlx4_MAD_IFC(to_mdev(ibdev), |
267 | mad_flags & IB_MAD_IGNORE_MKEY, | 280 | mad_flags & IB_MAD_IGNORE_MKEY, |
268 | mad_flags & IB_MAD_IGNORE_BKEY, | 281 | mad_flags & IB_MAD_IGNORE_BKEY, |
@@ -271,7 +284,7 @@ int mlx4_ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, | |||
271 | return IB_MAD_RESULT_FAILURE; | 284 | return IB_MAD_RESULT_FAILURE; |
272 | 285 | ||
273 | if (!out_mad->mad_hdr.status) { | 286 | if (!out_mad->mad_hdr.status) { |
274 | smp_snoop(ibdev, port_num, in_mad); | 287 | smp_snoop(ibdev, port_num, in_mad, prev_lid); |
275 | node_desc_override(ibdev, out_mad); | 288 | node_desc_override(ibdev, out_mad); |
276 | } | 289 | } |
277 | 290 | ||