[openib-general] SM Receive Handling
Hal Rosenstock
halr at voltaire.com
Fri Oct 27 08:59:23 PDT 2006
Hi Michael,
The SM registers several MAD agents (for SM and SA traffic) and in mad.c this causes an agent to be found based on the high 32 bits of the transaction ID if it is a response (unsolicited messages are handled differently). This causes ib_mad_complete_recv to be invoked which handles RMPP, does the response matching, etc. before calling back the receive handler registered.
-- Hal
________________________________
From: openib-general-bounces at openib.org on behalf of Michael Arndt
Sent: Fri 10/27/2006 5:56 AM
To: openib-general at openib.org
Subject: [openib-general] SM Receive Handling
Hi,
I have a question about the way the SM is informed when a SMP is received.
If I look at the sources and go from the bottom up I stop at the
'ib_mad_recv_done_handler' (core/mad.c). At this point the SMI is processing
the packet and notice if the SMP has to be handled by the SM or SMA. In this
case the function jumps to the label 'local' at line 1860 (see code
attachment). I would really like if someone can explain the steps are taking
between the labels 'local' and 'out'. The reason is, that I can't see were
the __osm_sm_mad_ctrl_rcv_callback (which is the function the SM register to
handle received MADs, right?) is informed, in any way (Message, JobQueue,
Interrupt)?
Thanks Michael
static void ib_mad_recv_done_handler(struct ib_mad_port_private *port_priv,
struct ib_wc *wc)
{
struct ib_mad_qp_info *qp_info;
struct ib_mad_private_header *mad_priv_hdr;
struct ib_mad_private *recv, *response;
struct ib_mad_list_head *mad_list;
struct ib_mad_agent_private *mad_agent;
response = kmem_cache_alloc(ib_mad_cache, GFP_KERNEL);
if (!response)
printk(KERN_ERR PFX "ib_mad_recv_done_handler no memory "
"for response buffer\n");
mad_list = (struct ib_mad_list_head *)(unsigned long)wc->wr_id;
qp_info = mad_list->mad_queue->qp_info;
dequeue_mad(mad_list);
mad_priv_hdr = container_of(mad_list, struct ib_mad_private_header,
mad_list);
recv = container_of(mad_priv_hdr, struct ib_mad_private, header);
dma_unmap_single(port_priv->device->dma_device,
pci_unmap_addr(&recv->header, mapping),
sizeof(struct ib_mad_private) -
sizeof(struct ib_mad_private_header),
DMA_FROM_DEVICE);
/* Setup MAD receive work completion from "normal" work completion */
recv->header.wc = *wc;
recv->header.recv_wc.wc = &recv->header.wc;
recv->header.recv_wc.mad_len = sizeof(struct ib_mad);
recv->header.recv_wc.recv_buf.mad = &recv->mad.mad;
recv->header.recv_wc.recv_buf.grh = &recv->grh;
if (atomic_read(&qp_info->snoop_count))
snoop_recv(qp_info, &recv->header.recv_wc, IB_MAD_SNOOP_RECVS);
/* Validate MAD */
if (!validate_mad(&recv->mad.mad, qp_info->qp->qp_num))
goto out;
if (recv->mad.mad.mad_hdr.mgmt_class ==
IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) {
if (!smi_handle_dr_smp_recv(&recv->mad.smp,
port_priv->device->node_type,
port_priv->port_num,
port_priv->device->phys_port_cnt))
goto out;
if (!smi_check_forward_dr_smp(&recv->mad.smp))
goto local;
if (!smi_handle_dr_smp_send(&recv->mad.smp,
port_priv->device->node_type,
port_priv->port_num))
goto out;
if (!smi_check_local_smp(&recv->mad.smp, port_priv->device))
goto out;
}
local:
/* Give driver "right of first refusal" on incoming MAD */
if (port_priv->device->process_mad) {
int ret;
if (!response) {
printk(KERN_ERR PFX "No memory for response MAD\n");
/*
* Is it better to assume that
* it wouldn't be processed ?
*/
goto out;
}
ret = port_priv->device->process_mad(port_priv->device, 0,
port_priv->port_num,
wc, &recv->grh,
&recv->mad.mad,
&response->mad.mad);
if (ret & IB_MAD_RESULT_SUCCESS) {
if (ret & IB_MAD_RESULT_CONSUMED)
goto out;
if (ret & IB_MAD_RESULT_REPLY) {
agent_send_response(&response->mad.mad,
&recv->grh, wc,
port_priv->device,
port_priv->port_num,
qp_info->qp->qp_num);
goto out;
}
}
}
mad_agent = find_mad_agent(port_priv, &recv->mad.mad);
if (mad_agent) {
ib_mad_complete_recv(mad_agent, &recv->header.recv_wc);
/*
* recv is freed up in error cases in ib_mad_complete_recv
* or via recv_handler in ib_mad_complete_recv()
*/
recv = NULL;
}
out:
/* Post another receive request for this QP */
if (response) {
ib_mad_post_receive_mads(qp_info, response);
if (recv)
kmem_cache_free(ib_mad_cache, recv);
} else
ib_mad_post_receive_mads(qp_info, recv);
}
_______________________________________________
openib-general mailing list
openib-general at openib.org
http://openib.org/mailman/listinfo/openib-general
To unsubscribe, please visit http://openib.org/mailman/listinfo/openib-general
More information about the general
mailing list