diff options
author | Moni Shoua <monis@Voltaire.COM> | 2009-01-28 18:15:56 -0500 |
---|---|---|
committer | Roland Dreier <rolandd@cisco.com> | 2009-01-28 18:15:56 -0500 |
commit | 270b8b85134c299799dddec624ceeb5671330131 (patch) | |
tree | a558f73a67af4cf9bb4f4e27cf7cd0eaa27ee2b4 /drivers/infiniband | |
parent | f3b8436ad9a8ad36b3c9fa1fe030c7f38e5d3d0b (diff) |
IB/mthca: 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/mthca/mthca_mad.c | 25 |
1 files changed, 19 insertions, 6 deletions
diff --git a/drivers/infiniband/hw/mthca/mthca_mad.c b/drivers/infiniband/hw/mthca/mthca_mad.c index 640449582aba..5648659ff0b0 100644 --- a/drivers/infiniband/hw/mthca/mthca_mad.c +++ b/drivers/infiniband/hw/mthca/mthca_mad.c | |||
@@ -104,7 +104,8 @@ static void update_sm_ah(struct mthca_dev *dev, | |||
104 | */ | 104 | */ |
105 | static void smp_snoop(struct ib_device *ibdev, | 105 | static void smp_snoop(struct ib_device *ibdev, |
106 | u8 port_num, | 106 | u8 port_num, |
107 | struct ib_mad *mad) | 107 | struct ib_mad *mad, |
108 | u16 prev_lid) | ||
108 | { | 109 | { |
109 | struct ib_event event; | 110 | struct ib_event event; |
110 | 111 | ||
@@ -114,6 +115,7 @@ static void smp_snoop(struct ib_device *ibdev, | |||
114 | if (mad->mad_hdr.attr_id == IB_SMP_ATTR_PORT_INFO) { | 115 | if (mad->mad_hdr.attr_id == IB_SMP_ATTR_PORT_INFO) { |
115 | struct ib_port_info *pinfo = | 116 | struct ib_port_info *pinfo = |
116 | (struct ib_port_info *) ((struct ib_smp *) mad)->data; | 117 | (struct ib_port_info *) ((struct ib_smp *) mad)->data; |
118 | u16 lid = be16_to_cpu(pinfo->lid); | ||
117 | 119 | ||
118 | mthca_update_rate(to_mdev(ibdev), port_num); | 120 | mthca_update_rate(to_mdev(ibdev), port_num); |
119 | update_sm_ah(to_mdev(ibdev), port_num, | 121 | update_sm_ah(to_mdev(ibdev), port_num, |
@@ -123,12 +125,15 @@ static void smp_snoop(struct ib_device *ibdev, | |||
123 | event.device = ibdev; | 125 | event.device = ibdev; |
124 | event.element.port_num = port_num; | 126 | event.element.port_num = port_num; |
125 | 127 | ||
126 | if (pinfo->clientrereg_resv_subnetto & 0x80) | 128 | if (pinfo->clientrereg_resv_subnetto & 0x80) { |
127 | event.event = IB_EVENT_CLIENT_REREGISTER; | 129 | event.event = IB_EVENT_CLIENT_REREGISTER; |
128 | else | 130 | ib_dispatch_event(&event); |
129 | event.event = IB_EVENT_LID_CHANGE; | 131 | } |
130 | 132 | ||
131 | ib_dispatch_event(&event); | 133 | if (prev_lid != lid) { |
134 | event.event = IB_EVENT_LID_CHANGE; | ||
135 | ib_dispatch_event(&event); | ||
136 | } | ||
132 | } | 137 | } |
133 | 138 | ||
134 | if (mad->mad_hdr.attr_id == IB_SMP_ATTR_PKEY_TABLE) { | 139 | if (mad->mad_hdr.attr_id == IB_SMP_ATTR_PKEY_TABLE) { |
@@ -196,6 +201,8 @@ int mthca_process_mad(struct ib_device *ibdev, | |||
196 | int err; | 201 | int err; |
197 | u8 status; | 202 | u8 status; |
198 | u16 slid = in_wc ? in_wc->slid : be16_to_cpu(IB_LID_PERMISSIVE); | 203 | u16 slid = in_wc ? in_wc->slid : be16_to_cpu(IB_LID_PERMISSIVE); |
204 | u16 prev_lid = 0; | ||
205 | struct ib_port_attr pattr; | ||
199 | 206 | ||
200 | /* Forward locally generated traps to the SM */ | 207 | /* Forward locally generated traps to the SM */ |
201 | if (in_mad->mad_hdr.method == IB_MGMT_METHOD_TRAP && | 208 | if (in_mad->mad_hdr.method == IB_MGMT_METHOD_TRAP && |
@@ -233,6 +240,12 @@ int mthca_process_mad(struct ib_device *ibdev, | |||
233 | return IB_MAD_RESULT_SUCCESS; | 240 | return IB_MAD_RESULT_SUCCESS; |
234 | } else | 241 | } else |
235 | return IB_MAD_RESULT_SUCCESS; | 242 | return IB_MAD_RESULT_SUCCESS; |
243 | if ((in_mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_LID_ROUTED || | ||
244 | in_mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) && | ||
245 | in_mad->mad_hdr.method == IB_MGMT_METHOD_SET && | ||
246 | in_mad->mad_hdr.attr_id == IB_SMP_ATTR_PORT_INFO && | ||
247 | !ib_query_port(ibdev, port_num, &pattr)) | ||
248 | prev_lid = pattr.lid; | ||
236 | 249 | ||
237 | err = mthca_MAD_IFC(to_mdev(ibdev), | 250 | err = mthca_MAD_IFC(to_mdev(ibdev), |
238 | mad_flags & IB_MAD_IGNORE_MKEY, | 251 | mad_flags & IB_MAD_IGNORE_MKEY, |
@@ -252,7 +265,7 @@ int mthca_process_mad(struct ib_device *ibdev, | |||
252 | } | 265 | } |
253 | 266 | ||
254 | if (!out_mad->mad_hdr.status) { | 267 | if (!out_mad->mad_hdr.status) { |
255 | smp_snoop(ibdev, port_num, in_mad); | 268 | smp_snoop(ibdev, port_num, in_mad, prev_lid); |
256 | node_desc_override(ibdev, out_mad); | 269 | node_desc_override(ibdev, out_mad); |
257 | } | 270 | } |
258 | 271 | ||