[openib-general] SM Receive Handling

Michael Arndt michael.arndt at informatik.tu-chemnitz.de
Fri Oct 27 02:56:01 PDT 2006


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);
} 





More information about the general mailing list