163 hermon_agent_handler_arg_t *cb_args;
164 hermon_agent_list_t *curr;
165 hermon_state_t *state;
166 int status;
167
168 curr = (hermon_agent_list_t *)args;
169 state = curr->agl_state;
170
171 /*
172 * Allocate space to hold the callback args (for passing to the
173 * task queue). Note: If we are unable to allocate space for the
174 * the callback args here, then we just return. But we must ensure
175 * that we call ibmf_free_msg() to free up the message.
176 */
177 cb_args = (hermon_agent_handler_arg_t *)kmem_zalloc(
178 sizeof (hermon_agent_handler_arg_t), KM_NOSLEEP);
179 if (cb_args == NULL) {
180 (void) ibmf_free_msg(ibmf_handle, &msgp);
181 return;
182 }
183 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*cb_args))
184
185 /* Fill in the callback args */
186 cb_args->ahd_ibmfhdl = ibmf_handle;
187 cb_args->ahd_ibmfmsg = msgp;
188 cb_args->ahd_agentlist = args;
189
190 /*
191 * Dispatch the message to the task queue. Note: Just like above,
192 * if this request fails for any reason then make sure to free up
193 * the IBMF message and then return
194 */
195 status = ddi_taskq_dispatch(state->hs_taskq_agents,
196 hermon_agent_handle_req, cb_args, DDI_NOSLEEP);
197 if (status == DDI_FAILURE) {
198 kmem_free(cb_args, sizeof (hermon_agent_handler_arg_t));
199 (void) ibmf_free_msg(ibmf_handle, &msgp);
200 }
201 }
202
203 /*
309 */
310 static void
311 hermon_agent_handle_req(void *cb_args)
312 {
313 hermon_agent_handler_arg_t *agent_args;
314 hermon_agent_list_t *curr;
315 ibc_async_event_t event;
316 ibt_async_code_t type, code;
317 sm_portinfo_t curpinfo, tmadpinfo;
318 sm_portinfo_t *madpinfop;
319 hermon_state_t *state;
320 ibmf_handle_t ibmf_handle;
321 ibmf_msg_t *msgp;
322 ibmf_msg_bufs_t *recv_msgbufp;
323 ibmf_msg_bufs_t *send_msgbufp;
324 ib_mad_hdr_t *madhdrp;
325 ibmf_retrans_t retrans;
326 uint_t port;
327 int status;
328
329 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*((sm_portinfo_t *)madpinfop)))
330 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(curpinfo))
331 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(tmadpinfo))
332 /* Extract the necessary info from the callback args parameter */
333 agent_args = (hermon_agent_handler_arg_t *)cb_args;
334 ibmf_handle = agent_args->ahd_ibmfhdl;
335 msgp = agent_args->ahd_ibmfmsg;
336 curr = agent_args->ahd_agentlist;
337 state = curr->agl_state;
338 port = curr->agl_port;
339
340 /*
341 * Set the message send buffer pointers to the message receive buffer
342 * pointers to reuse the IBMF provided buffers for the sender
343 * information.
344 */
345 recv_msgbufp = &msgp->im_msgbufs_recv;
346 send_msgbufp = &msgp->im_msgbufs_send;
347 bcopy(recv_msgbufp, send_msgbufp, sizeof (ibmf_msg_bufs_t));
348
349 /*
350 * Check if the incoming packet is a special "Hermon Trap" MAD. If it
351 * is, then do the special handling. If it isn't, then simply pass it
352 * on to the firmware and forward the response back to the IBMF.
353 *
354 * Note: Hermon has a unique method for handling internally generated
355 * Traps. All internally detected/generated Trap messages are
356 * automatically received by the IBMF (as receive completions on QP0),
357 * which (because all Hermon Trap MADs have SLID == 0) detects it as a
358 * special "Hermon Trap" and forwards it here to the driver's SMA.
359 * It is then our responsibility here to fill in the Trap MAD's DLID
360 * for forwarding to the real Master SM (as programmed in the port's
361 * PortInfo.MasterSMLID field.)
362 */
363 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(msgp->im_local_addr))
364 if (HERMON_IS_SPECIAL_TRAP_MAD(msgp)) {
365 msgp->im_local_addr.ia_remote_lid =
366 hermon_get_smlid(state, port);
367 } else {
368 int isSMSet, isReregSuppd;
369 uint_t attr_id, method, mgmt_class;
370
371 madhdrp = recv_msgbufp->im_bufs_mad_hdr;
372 method = madhdrp->R_Method;
373 attr_id = b2h16(madhdrp->AttributeID);
374 mgmt_class = madhdrp->MgmtClass;
375
376 /*
377 * Is this a Subnet Manager MAD with SET method ? If so
378 * we will have to get the current portinfo to generate
379 * events based on what has changed in portinfo.
380 */
381 isSMSet = (((mgmt_class == MAD_MGMT_CLASS_SUBN_LID_ROUTED)||
382 (mgmt_class == MAD_MGMT_CLASS_SUBN_DIRECT_ROUTE)) &&
383 (method == MAD_METHOD_SET));
785 static void
786 hermon_agent_mad_resp_handling(hermon_state_t *state, ibmf_msg_t *msgp,
787 uint_t port)
788 {
789 ib_mad_hdr_t *rmadhdrp = msgp->im_msgbufs_recv.im_bufs_mad_hdr;
790 ib_mad_hdr_t *smadhdrp = msgp->im_msgbufs_send.im_bufs_mad_hdr;
791 uint_t hop_count, hop_point;
792 uchar_t *resp, *ret_path;
793
794 resp = (uchar_t *)msgp->im_msgbufs_send.im_bufs_cl_data;
795
796 /*
797 * Handle directed route MADs as a special case. Hermon firmware
798 * does not update the "direction" bit, "hop pointer", "Return
799 * Path" or, in fact, any of the "directed route" parameters. So
800 * the responsibility falls on Hermon driver software to inspect the
801 * MADs and update those fields as appropriate (see section 14.2.2
802 * of the IBA specification, rev 1.1)
803 */
804 if (HERMON_MAD_IS_DR(rmadhdrp)) {
805
806 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*((sm_dr_mad_hdr_t *)rmadhdrp)))
807 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*((sm_dr_mad_hdr_t *)smadhdrp)))
808
809 /*
810 * Set the "Direction" bit to one. This indicates that this
811 * is now directed route response
812 */
813 HERMON_DRMAD_SET_DIRECTION(rmadhdrp);
814
815 /* Extract the "hop pointer" and "hop count" from the MAD */
816 hop_count = HERMON_DRMAD_GET_HOPCOUNT(rmadhdrp);
817 hop_point = HERMON_DRMAD_GET_HOPPOINTER(rmadhdrp);
818
819 /* Append the port we came in on to the "Return Path" */
820 if ((hop_count != 0) && ((hop_point == hop_count) ||
821 (hop_point == hop_count + 1))) {
822 ret_path = &resp[HERMON_DRMAD_RETURN_PATH_OFFSET];
823 ret_path[hop_point] = (uchar_t)port;
824 }
825
826 /* Then increment the "hop pointer" in the MAD */
827 hop_point++;
828 HERMON_DRMAD_SET_HOPPOINTER(smadhdrp, (uint8_t)hop_point);
|
163 hermon_agent_handler_arg_t *cb_args;
164 hermon_agent_list_t *curr;
165 hermon_state_t *state;
166 int status;
167
168 curr = (hermon_agent_list_t *)args;
169 state = curr->agl_state;
170
171 /*
172 * Allocate space to hold the callback args (for passing to the
173 * task queue). Note: If we are unable to allocate space for the
174 * the callback args here, then we just return. But we must ensure
175 * that we call ibmf_free_msg() to free up the message.
176 */
177 cb_args = (hermon_agent_handler_arg_t *)kmem_zalloc(
178 sizeof (hermon_agent_handler_arg_t), KM_NOSLEEP);
179 if (cb_args == NULL) {
180 (void) ibmf_free_msg(ibmf_handle, &msgp);
181 return;
182 }
183
184 /* Fill in the callback args */
185 cb_args->ahd_ibmfhdl = ibmf_handle;
186 cb_args->ahd_ibmfmsg = msgp;
187 cb_args->ahd_agentlist = args;
188
189 /*
190 * Dispatch the message to the task queue. Note: Just like above,
191 * if this request fails for any reason then make sure to free up
192 * the IBMF message and then return
193 */
194 status = ddi_taskq_dispatch(state->hs_taskq_agents,
195 hermon_agent_handle_req, cb_args, DDI_NOSLEEP);
196 if (status == DDI_FAILURE) {
197 kmem_free(cb_args, sizeof (hermon_agent_handler_arg_t));
198 (void) ibmf_free_msg(ibmf_handle, &msgp);
199 }
200 }
201
202 /*
308 */
309 static void
310 hermon_agent_handle_req(void *cb_args)
311 {
312 hermon_agent_handler_arg_t *agent_args;
313 hermon_agent_list_t *curr;
314 ibc_async_event_t event;
315 ibt_async_code_t type, code;
316 sm_portinfo_t curpinfo, tmadpinfo;
317 sm_portinfo_t *madpinfop;
318 hermon_state_t *state;
319 ibmf_handle_t ibmf_handle;
320 ibmf_msg_t *msgp;
321 ibmf_msg_bufs_t *recv_msgbufp;
322 ibmf_msg_bufs_t *send_msgbufp;
323 ib_mad_hdr_t *madhdrp;
324 ibmf_retrans_t retrans;
325 uint_t port;
326 int status;
327
328 /* Extract the necessary info from the callback args parameter */
329 agent_args = (hermon_agent_handler_arg_t *)cb_args;
330 ibmf_handle = agent_args->ahd_ibmfhdl;
331 msgp = agent_args->ahd_ibmfmsg;
332 curr = agent_args->ahd_agentlist;
333 state = curr->agl_state;
334 port = curr->agl_port;
335
336 /*
337 * Set the message send buffer pointers to the message receive buffer
338 * pointers to reuse the IBMF provided buffers for the sender
339 * information.
340 */
341 recv_msgbufp = &msgp->im_msgbufs_recv;
342 send_msgbufp = &msgp->im_msgbufs_send;
343 bcopy(recv_msgbufp, send_msgbufp, sizeof (ibmf_msg_bufs_t));
344
345 /*
346 * Check if the incoming packet is a special "Hermon Trap" MAD. If it
347 * is, then do the special handling. If it isn't, then simply pass it
348 * on to the firmware and forward the response back to the IBMF.
349 *
350 * Note: Hermon has a unique method for handling internally generated
351 * Traps. All internally detected/generated Trap messages are
352 * automatically received by the IBMF (as receive completions on QP0),
353 * which (because all Hermon Trap MADs have SLID == 0) detects it as a
354 * special "Hermon Trap" and forwards it here to the driver's SMA.
355 * It is then our responsibility here to fill in the Trap MAD's DLID
356 * for forwarding to the real Master SM (as programmed in the port's
357 * PortInfo.MasterSMLID field.)
358 */
359 if (HERMON_IS_SPECIAL_TRAP_MAD(msgp)) {
360 msgp->im_local_addr.ia_remote_lid =
361 hermon_get_smlid(state, port);
362 } else {
363 int isSMSet, isReregSuppd;
364 uint_t attr_id, method, mgmt_class;
365
366 madhdrp = recv_msgbufp->im_bufs_mad_hdr;
367 method = madhdrp->R_Method;
368 attr_id = b2h16(madhdrp->AttributeID);
369 mgmt_class = madhdrp->MgmtClass;
370
371 /*
372 * Is this a Subnet Manager MAD with SET method ? If so
373 * we will have to get the current portinfo to generate
374 * events based on what has changed in portinfo.
375 */
376 isSMSet = (((mgmt_class == MAD_MGMT_CLASS_SUBN_LID_ROUTED)||
377 (mgmt_class == MAD_MGMT_CLASS_SUBN_DIRECT_ROUTE)) &&
378 (method == MAD_METHOD_SET));
780 static void
781 hermon_agent_mad_resp_handling(hermon_state_t *state, ibmf_msg_t *msgp,
782 uint_t port)
783 {
784 ib_mad_hdr_t *rmadhdrp = msgp->im_msgbufs_recv.im_bufs_mad_hdr;
785 ib_mad_hdr_t *smadhdrp = msgp->im_msgbufs_send.im_bufs_mad_hdr;
786 uint_t hop_count, hop_point;
787 uchar_t *resp, *ret_path;
788
789 resp = (uchar_t *)msgp->im_msgbufs_send.im_bufs_cl_data;
790
791 /*
792 * Handle directed route MADs as a special case. Hermon firmware
793 * does not update the "direction" bit, "hop pointer", "Return
794 * Path" or, in fact, any of the "directed route" parameters. So
795 * the responsibility falls on Hermon driver software to inspect the
796 * MADs and update those fields as appropriate (see section 14.2.2
797 * of the IBA specification, rev 1.1)
798 */
799 if (HERMON_MAD_IS_DR(rmadhdrp)) {
800 /*
801 * Set the "Direction" bit to one. This indicates that this
802 * is now directed route response
803 */
804 HERMON_DRMAD_SET_DIRECTION(rmadhdrp);
805
806 /* Extract the "hop pointer" and "hop count" from the MAD */
807 hop_count = HERMON_DRMAD_GET_HOPCOUNT(rmadhdrp);
808 hop_point = HERMON_DRMAD_GET_HOPPOINTER(rmadhdrp);
809
810 /* Append the port we came in on to the "Return Path" */
811 if ((hop_count != 0) && ((hop_point == hop_count) ||
812 (hop_point == hop_count + 1))) {
813 ret_path = &resp[HERMON_DRMAD_RETURN_PATH_OFFSET];
814 ret_path[hop_point] = (uchar_t)port;
815 }
816
817 /* Then increment the "hop pointer" in the MAD */
818 hop_point++;
819 HERMON_DRMAD_SET_HOPPOINTER(smadhdrp, (uint8_t)hop_point);
|