aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/hw/mthca
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/infiniband/hw/mthca')
-rw-r--r--drivers/infiniband/hw/mthca/mthca_mad.c25
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 */
105static void smp_snoop(struct ib_device *ibdev, 105static 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