aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband
diff options
context:
space:
mode:
authorMoni Shoua <monis@voltaire.com>2009-01-28 17:54:35 -0500
committerRoland Dreier <rolandd@cisco.com>2009-01-28 17:54:35 -0500
commitf0f6f346a1edaec23b990c25f53478669e56fa70 (patch)
tree874c70fae081386ca3408c358f14de231edf68ce /drivers/infiniband
parentf3b8436ad9a8ad36b3c9fa1fe030c7f38e5d3d0b (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.c27
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 */
150static void smp_snoop(struct ib_device *ibdev, u8 port_num, struct ib_mad *mad) 150static 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