194 /*
195 * Allocate space to hold the callback args (for passing to the
196 * task queue). Note: If we are unable to allocate space for the
197 * the callback args here, then we just return. But we must ensure
198 * that we call ibmf_free_msg() to free up the message.
199 */
200 cb_args = (tavor_agent_handler_arg_t *)kmem_zalloc(
201 sizeof (tavor_agent_handler_arg_t), KM_NOSLEEP);
202 if (cb_args == NULL) {
203 ibmf_status = ibmf_free_msg(ibmf_handle, &msgp);
204 if (ibmf_status != IBMF_SUCCESS) {
205 TNF_PROBE_1(tavor_agent_request_cb_ibmf_free_msg_fail,
206 TAVOR_TNF_ERROR, "", tnf_uint, ibmf_status,
207 ibmf_status);
208 }
209 TNF_PROBE_0(tavor_agent_request_cb_kma_fail,
210 TAVOR_TNF_ERROR, "");
211 TAVOR_TNF_EXIT(tavor_agent_request_cb);
212 return;
213 }
214 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*cb_args))
215
216 /* Fill in the callback args */
217 cb_args->ahd_ibmfhdl = ibmf_handle;
218 cb_args->ahd_ibmfmsg = msgp;
219 cb_args->ahd_agentlist = args;
220
221 /*
222 * Dispatch the message to the task queue. Note: Just like above,
223 * if this request fails for any reason then make sure to free up
224 * the IBMF message and then return
225 */
226 status = ddi_taskq_dispatch(state->ts_taskq_agents,
227 tavor_agent_handle_req, cb_args, DDI_NOSLEEP);
228 if (status == DDI_FAILURE) {
229 kmem_free(cb_args, sizeof (tavor_agent_handler_arg_t));
230 ibmf_status = ibmf_free_msg(ibmf_handle, &msgp);
231 if (ibmf_status != IBMF_SUCCESS) {
232 TNF_PROBE_1(tavor_agent_request_cb_ibmf_free_msg_fail,
233 TAVOR_TNF_ERROR, "", tnf_uint, ibmf_status,
234 ibmf_status);
273 * information.
274 */
275 recv_msgbufp = &msgp->im_msgbufs_recv;
276 send_msgbufp = &msgp->im_msgbufs_send;
277 bcopy(recv_msgbufp, send_msgbufp, sizeof (ibmf_msg_bufs_t));
278
279 /*
280 * Check if the incoming packet is a special "Tavor Trap" MAD. If it
281 * is, then do the special handling. If it isn't, then simply pass it
282 * on to the firmware and forward the response back to the IBMF.
283 *
284 * Note: Tavor has a unique method for handling internally generated
285 * Traps. All internally detected/generated Trap messages are
286 * automatically received by the IBMF (as receive completions on QP0),
287 * which (because all Tavor Trap MADs have SLID == 0) detects it as a
288 * special "Tavor Trap" and forwards it here to the driver's SMA.
289 * It is then our responsibility here to fill in the Trap MAD's DLID
290 * for forwarding to the real Master SM (as programmed in the port's
291 * PortInfo.MasterSMLID field.)
292 */
293 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(msgp->im_local_addr))
294 if (TAVOR_IS_SPECIAL_TRAP_MAD(msgp)) {
295 msgp->im_local_addr.ia_remote_lid =
296 TAVOR_PORT_MASTERSMLID_GET(state, port - 1);
297 } else {
298 /*
299 * Post the command to the firmware (using the MAD_IFC
300 * command). Note: We also reuse the command that was passed
301 * in. We pass the pointer to the original MAD payload as if
302 * it were both the source of the incoming MAD as well as the
303 * destination for the response. This is acceptable and saves
304 * us the step of one additional copy. Note: If this command
305 * fails for any reason other than TAVOR_CMD_BAD_PKT, it
306 * probably indicates a serious problem.
307 */
308 status = tavor_mad_ifc_cmd_post(state, port,
309 TAVOR_CMD_SLEEP_NOSPIN,
310 (uint32_t *)recv_msgbufp->im_bufs_mad_hdr,
311 (uint32_t *)send_msgbufp->im_bufs_mad_hdr);
312 if (status != TAVOR_CMD_SUCCESS) {
313 if ((status != TAVOR_CMD_BAD_PKT) &&
627 static void
628 tavor_agent_mad_resp_handling(tavor_state_t *state, ibmf_msg_t *msgp,
629 uint_t port)
630 {
631 ib_mad_hdr_t *rmadhdrp = msgp->im_msgbufs_recv.im_bufs_mad_hdr;
632 ib_mad_hdr_t *smadhdrp = msgp->im_msgbufs_send.im_bufs_mad_hdr;
633 uint_t hop_count, hop_point;
634 uchar_t *resp, *ret_path;
635
636 resp = (uchar_t *)msgp->im_msgbufs_send.im_bufs_cl_data;
637
638 /*
639 * Handle directed route MADs as a special case. Tavor firmware
640 * does not update the "direction" bit, "hop pointer", "Return
641 * Path" or, in fact, any of the "directed route" parameters. So
642 * the responsibility falls on Tavor driver software to inspect the
643 * MADs and update those fields as appropriate (see section 14.2.2
644 * of the IBA specification, rev 1.1)
645 */
646 if (TAVOR_MAD_IS_DR(rmadhdrp)) {
647
648 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*((sm_dr_mad_hdr_t *)rmadhdrp)))
649 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*((sm_dr_mad_hdr_t *)smadhdrp)))
650
651 /*
652 * Set the "Direction" bit to one. This indicates that this
653 * is now directed route response
654 */
655 TAVOR_DRMAD_SET_DIRECTION(rmadhdrp);
656
657 /* Extract the "hop pointer" and "hop count" from the MAD */
658 hop_count = TAVOR_DRMAD_GET_HOPCOUNT(rmadhdrp);
659 hop_point = TAVOR_DRMAD_GET_HOPPOINTER(rmadhdrp);
660
661 /* Append the port we came in on to the "Return Path" */
662 if ((hop_count != 0) && ((hop_point == hop_count) ||
663 (hop_point == hop_count + 1))) {
664 ret_path = &resp[TAVOR_DRMAD_RETURN_PATH_OFFSET];
665 ret_path[hop_point] = port;
666 }
667
668 /* Then increment the "hop pointer" in the MAD */
669 hop_point++;
670 TAVOR_DRMAD_SET_HOPPOINTER(smadhdrp, hop_point);
|
194 /*
195 * Allocate space to hold the callback args (for passing to the
196 * task queue). Note: If we are unable to allocate space for the
197 * the callback args here, then we just return. But we must ensure
198 * that we call ibmf_free_msg() to free up the message.
199 */
200 cb_args = (tavor_agent_handler_arg_t *)kmem_zalloc(
201 sizeof (tavor_agent_handler_arg_t), KM_NOSLEEP);
202 if (cb_args == NULL) {
203 ibmf_status = ibmf_free_msg(ibmf_handle, &msgp);
204 if (ibmf_status != IBMF_SUCCESS) {
205 TNF_PROBE_1(tavor_agent_request_cb_ibmf_free_msg_fail,
206 TAVOR_TNF_ERROR, "", tnf_uint, ibmf_status,
207 ibmf_status);
208 }
209 TNF_PROBE_0(tavor_agent_request_cb_kma_fail,
210 TAVOR_TNF_ERROR, "");
211 TAVOR_TNF_EXIT(tavor_agent_request_cb);
212 return;
213 }
214
215 /* Fill in the callback args */
216 cb_args->ahd_ibmfhdl = ibmf_handle;
217 cb_args->ahd_ibmfmsg = msgp;
218 cb_args->ahd_agentlist = args;
219
220 /*
221 * Dispatch the message to the task queue. Note: Just like above,
222 * if this request fails for any reason then make sure to free up
223 * the IBMF message and then return
224 */
225 status = ddi_taskq_dispatch(state->ts_taskq_agents,
226 tavor_agent_handle_req, cb_args, DDI_NOSLEEP);
227 if (status == DDI_FAILURE) {
228 kmem_free(cb_args, sizeof (tavor_agent_handler_arg_t));
229 ibmf_status = ibmf_free_msg(ibmf_handle, &msgp);
230 if (ibmf_status != IBMF_SUCCESS) {
231 TNF_PROBE_1(tavor_agent_request_cb_ibmf_free_msg_fail,
232 TAVOR_TNF_ERROR, "", tnf_uint, ibmf_status,
233 ibmf_status);
272 * information.
273 */
274 recv_msgbufp = &msgp->im_msgbufs_recv;
275 send_msgbufp = &msgp->im_msgbufs_send;
276 bcopy(recv_msgbufp, send_msgbufp, sizeof (ibmf_msg_bufs_t));
277
278 /*
279 * Check if the incoming packet is a special "Tavor Trap" MAD. If it
280 * is, then do the special handling. If it isn't, then simply pass it
281 * on to the firmware and forward the response back to the IBMF.
282 *
283 * Note: Tavor has a unique method for handling internally generated
284 * Traps. All internally detected/generated Trap messages are
285 * automatically received by the IBMF (as receive completions on QP0),
286 * which (because all Tavor Trap MADs have SLID == 0) detects it as a
287 * special "Tavor Trap" and forwards it here to the driver's SMA.
288 * It is then our responsibility here to fill in the Trap MAD's DLID
289 * for forwarding to the real Master SM (as programmed in the port's
290 * PortInfo.MasterSMLID field.)
291 */
292 if (TAVOR_IS_SPECIAL_TRAP_MAD(msgp)) {
293 msgp->im_local_addr.ia_remote_lid =
294 TAVOR_PORT_MASTERSMLID_GET(state, port - 1);
295 } else {
296 /*
297 * Post the command to the firmware (using the MAD_IFC
298 * command). Note: We also reuse the command that was passed
299 * in. We pass the pointer to the original MAD payload as if
300 * it were both the source of the incoming MAD as well as the
301 * destination for the response. This is acceptable and saves
302 * us the step of one additional copy. Note: If this command
303 * fails for any reason other than TAVOR_CMD_BAD_PKT, it
304 * probably indicates a serious problem.
305 */
306 status = tavor_mad_ifc_cmd_post(state, port,
307 TAVOR_CMD_SLEEP_NOSPIN,
308 (uint32_t *)recv_msgbufp->im_bufs_mad_hdr,
309 (uint32_t *)send_msgbufp->im_bufs_mad_hdr);
310 if (status != TAVOR_CMD_SUCCESS) {
311 if ((status != TAVOR_CMD_BAD_PKT) &&
625 static void
626 tavor_agent_mad_resp_handling(tavor_state_t *state, ibmf_msg_t *msgp,
627 uint_t port)
628 {
629 ib_mad_hdr_t *rmadhdrp = msgp->im_msgbufs_recv.im_bufs_mad_hdr;
630 ib_mad_hdr_t *smadhdrp = msgp->im_msgbufs_send.im_bufs_mad_hdr;
631 uint_t hop_count, hop_point;
632 uchar_t *resp, *ret_path;
633
634 resp = (uchar_t *)msgp->im_msgbufs_send.im_bufs_cl_data;
635
636 /*
637 * Handle directed route MADs as a special case. Tavor firmware
638 * does not update the "direction" bit, "hop pointer", "Return
639 * Path" or, in fact, any of the "directed route" parameters. So
640 * the responsibility falls on Tavor driver software to inspect the
641 * MADs and update those fields as appropriate (see section 14.2.2
642 * of the IBA specification, rev 1.1)
643 */
644 if (TAVOR_MAD_IS_DR(rmadhdrp)) {
645 /*
646 * Set the "Direction" bit to one. This indicates that this
647 * is now directed route response
648 */
649 TAVOR_DRMAD_SET_DIRECTION(rmadhdrp);
650
651 /* Extract the "hop pointer" and "hop count" from the MAD */
652 hop_count = TAVOR_DRMAD_GET_HOPCOUNT(rmadhdrp);
653 hop_point = TAVOR_DRMAD_GET_HOPPOINTER(rmadhdrp);
654
655 /* Append the port we came in on to the "Return Path" */
656 if ((hop_count != 0) && ((hop_point == hop_count) ||
657 (hop_point == hop_count + 1))) {
658 ret_path = &resp[TAVOR_DRMAD_RETURN_PATH_OFFSET];
659 ret_path[hop_point] = port;
660 }
661
662 /* Then increment the "hop pointer" in the MAD */
663 hop_point++;
664 TAVOR_DRMAD_SET_HOPPOINTER(smadhdrp, hop_point);
|