Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Linux/drivers/net/ethernet/wangxun/libwx/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 9 kB image not shown  

Quelle  wx_mbx.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) 2015 - 2025 Beijing WangXun Technology Co., Ltd. */

#include <linux/pci.h>
#include "wx_type.h"
#include "wx_mbx.h"

/**
 *  wx_obtain_mbx_lock_pf - obtain mailbox lock
 *  @wx: pointer to the HW structure
 *  @vf: the VF index
 *
 *  Return: return 0 on success and -EBUSY on failure
 **/

static int wx_obtain_mbx_lock_pf(struct wx *wx, u16 vf)
{
 int count = 5;
 u32 mailbox;

 while (count--) {
  /* Take ownership of the buffer */
  wr32(wx, WX_PXMAILBOX(vf), WX_PXMAILBOX_PFU);

  /* reserve mailbox for vf use */
  mailbox = rd32(wx, WX_PXMAILBOX(vf));
  if (mailbox & WX_PXMAILBOX_PFU)
   return 0;
  else if (count)
   udelay(10);
 }
 wx_err(wx, "Failed to obtain mailbox lock for PF%d", vf);

 return -EBUSY;
}

static int wx_check_for_bit_pf(struct wx *wx, u32 mask, int index)
{
 u32 mbvficr = rd32(wx, WX_MBVFICR(index));

 if (!(mbvficr & mask))
  return -EBUSY;
 wr32(wx, WX_MBVFICR(index), mask);

 return 0;
}

/**
 *  wx_check_for_ack_pf - checks to see if the VF has acked
 *  @wx: pointer to the HW structure
 *  @vf: the VF index
 *
 *  Return: return 0 if the VF has set the status bit or else -EBUSY
 **/

int wx_check_for_ack_pf(struct wx *wx, u16 vf)
{
 u32 index = vf / 16, vf_bit = vf % 16;

 return wx_check_for_bit_pf(wx,
       FIELD_PREP(WX_MBVFICR_VFACK_MASK,
           BIT(vf_bit)),
       index);
}

/**
 *  wx_check_for_msg_pf - checks to see if the VF has sent mail
 *  @wx: pointer to the HW structure
 *  @vf: the VF index
 *
 *  Return: return 0 if the VF has got req bit or else -EBUSY
 **/

int wx_check_for_msg_pf(struct wx *wx, u16 vf)
{
 u32 index = vf / 16, vf_bit = vf % 16;

 return wx_check_for_bit_pf(wx,
       FIELD_PREP(WX_MBVFICR_VFREQ_MASK,
           BIT(vf_bit)),
       index);
}

/**
 *  wx_write_mbx_pf - Places a message in the mailbox
 *  @wx: pointer to the HW structure
 *  @msg: The message buffer
 *  @size: Length of buffer
 *  @vf: the VF index
 *
 *  Return: return 0 on success and -EINVAL/-EBUSY on failure
 **/

int wx_write_mbx_pf(struct wx *wx, u32 *msg, u16 size, u16 vf)
{
 struct wx_mbx_info *mbx = &wx->mbx;
 int ret, i;

 /* mbx->size is up to 15 */
 if (size > mbx->size) {
  wx_err(wx, "Invalid mailbox message size %d", size);
  return -EINVAL;
 }

 /* lock the mailbox to prevent pf/vf race condition */
 ret = wx_obtain_mbx_lock_pf(wx, vf);
 if (ret)
  return ret;

 /* flush msg and acks as we are overwriting the message buffer */
 wx_check_for_msg_pf(wx, vf);
 wx_check_for_ack_pf(wx, vf);

 /* copy the caller specified message to the mailbox memory buffer */
 for (i = 0; i < size; i++)
  wr32a(wx, WX_PXMBMEM(vf), i, msg[i]);

 /* Interrupt VF to tell it a message has been sent and release buffer */
 /* set mirrored mailbox flags */
 wr32a(wx, WX_PXMBMEM(vf), WX_VXMAILBOX_SIZE, WX_PXMAILBOX_STS);
 wr32(wx, WX_PXMAILBOX(vf), WX_PXMAILBOX_STS);

 return 0;
}

/**
 *  wx_read_mbx_pf - Read a message from the mailbox
 *  @wx: pointer to the HW structure
 *  @msg: The message buffer
 *  @size: Length of buffer
 *  @vf: the VF index
 *
 *  Return: return 0 on success and -EBUSY on failure
 **/

int wx_read_mbx_pf(struct wx *wx, u32 *msg, u16 size, u16 vf)
{
 struct wx_mbx_info *mbx = &wx->mbx;
 int ret;
 u16 i;

 /* limit read to size of mailbox and mbx->size is up to 15 */
 if (size > mbx->size)
  size = mbx->size;

 /* lock the mailbox to prevent pf/vf race condition */
 ret = wx_obtain_mbx_lock_pf(wx, vf);
 if (ret)
  return ret;

 for (i = 0; i < size; i++)
  msg[i] = rd32a(wx, WX_PXMBMEM(vf), i);

 /* Acknowledge the message and release buffer */
 /* set mirrored mailbox flags */
 wr32a(wx, WX_PXMBMEM(vf), WX_VXMAILBOX_SIZE, WX_PXMAILBOX_ACK);
 wr32(wx, WX_PXMAILBOX(vf), WX_PXMAILBOX_ACK);

 return 0;
}

/**
 *  wx_check_for_rst_pf - checks to see if the VF has reset
 *  @wx: pointer to the HW structure
 *  @vf: the VF index
 *
 *  Return: return 0 on success and -EBUSY on failure
 **/

int wx_check_for_rst_pf(struct wx *wx, u16 vf)
{
 u32 reg_offset = WX_VF_REG_OFFSET(vf);
 u32 vf_shift = WX_VF_IND_SHIFT(vf);
 u32 vflre = 0;

 vflre = rd32(wx, WX_VFLRE(reg_offset));
 if (!(vflre & BIT(vf_shift)))
  return -EBUSY;
 wr32(wx, WX_VFLREC(reg_offset), BIT(vf_shift));

 return 0;
}

static u32 wx_read_v2p_mailbox(struct wx *wx)
{
 u32 mailbox = rd32(wx, WX_VXMAILBOX);

 mailbox |= wx->mbx.mailbox;
 wx->mbx.mailbox |= mailbox & WX_VXMAILBOX_R2C_BITS;

 return mailbox;
}

static u32 wx_mailbox_get_lock_vf(struct wx *wx)
{
 wr32(wx, WX_VXMAILBOX, WX_VXMAILBOX_VFU);
 return wx_read_v2p_mailbox(wx);
}

/**
 *  wx_obtain_mbx_lock_vf - obtain mailbox lock
 *  @wx: pointer to the HW structure
 *
 *  Return: return 0 on success and -EBUSY on failure
 **/

static int wx_obtain_mbx_lock_vf(struct wx *wx)
{
 int count = 5, ret;
 u32 mailbox;

 ret = readx_poll_timeout_atomic(wx_mailbox_get_lock_vf, wx, mailbox,
     (mailbox & WX_VXMAILBOX_VFU),
     1, count);
 if (ret)
  wx_err(wx, "Failed to obtain mailbox lock for VF.\n");

 return ret;
}

static int wx_check_for_bit_vf(struct wx *wx, u32 mask)
{
 u32 mailbox = wx_read_v2p_mailbox(wx);

 wx->mbx.mailbox &= ~mask;

 return (mailbox & mask ? 0 : -EBUSY);
}

/**
 *  wx_check_for_ack_vf - checks to see if the PF has ACK'd
 *  @wx: pointer to the HW structure
 *
 *  Return: return 0 if the PF has set the status bit or else -EBUSY
 **/

static int wx_check_for_ack_vf(struct wx *wx)
{
 /* read clear the pf ack bit */
 return wx_check_for_bit_vf(wx, WX_VXMAILBOX_PFACK);
}

/**
 *  wx_check_for_msg_vf - checks to see if the PF has sent mail
 *  @wx: pointer to the HW structure
 *
 *  Return: return 0 if the PF has got req bit or else -EBUSY
 **/

int wx_check_for_msg_vf(struct wx *wx)
{
 /* read clear the pf sts bit */
 return wx_check_for_bit_vf(wx, WX_VXMAILBOX_PFSTS);
}

/**
 *  wx_check_for_rst_vf - checks to see if the PF has reset
 *  @wx: pointer to the HW structure
 *
 *  Return: return 0 if the PF has set the reset done and -EBUSY on failure
 **/

int wx_check_for_rst_vf(struct wx *wx)
{
 /* read clear the pf reset done bit */
 return wx_check_for_bit_vf(wx,
       WX_VXMAILBOX_RSTD |
       WX_VXMAILBOX_RSTI);
}

/**
 *  wx_poll_for_msg - Wait for message notification
 *  @wx: pointer to the HW structure
 *
 *  Return: return 0 if the VF has successfully received a message notification
 **/

static int wx_poll_for_msg(struct wx *wx)
{
 struct wx_mbx_info *mbx = &wx->mbx;
 u32 val;

 return readx_poll_timeout_atomic(wx_check_for_msg_vf, wx, val,
      (val == 0), mbx->udelay, mbx->timeout);
}

/**
 *  wx_poll_for_ack - Wait for message acknowledgment
 *  @wx: pointer to the HW structure
 *
 *  Return: return 0 if the VF has successfully received a message ack
 **/

static int wx_poll_for_ack(struct wx *wx)
{
 struct wx_mbx_info *mbx = &wx->mbx;
 u32 val;

 return readx_poll_timeout_atomic(wx_check_for_ack_vf, wx, val,
      (val == 0), mbx->udelay, mbx->timeout);
}

/**
 *  wx_read_posted_mbx - Wait for message notification and receive message
 *  @wx: pointer to the HW structure
 *  @msg: The message buffer
 *  @size: Length of buffer
 *
 *  Return: returns 0 if it successfully received a message notification and
 *  copied it into the receive buffer.
 **/

int wx_read_posted_mbx(struct wx *wx, u32 *msg, u16 size)
{
 int ret;

 ret = wx_poll_for_msg(wx);
 /* if ack received read message, otherwise we timed out */
 if (ret)
  return ret;

 return wx_read_mbx_vf(wx, msg, size);
}

/**
 *  wx_write_posted_mbx - Write a message to the mailbox, wait for ack
 *  @wx: pointer to the HW structure
 *  @msg: The message buffer
 *  @size: Length of buffer
 *
 *  Return: returns 0 if it successfully copied message into the buffer and
 *  received an ack to that message within delay * timeout period
 **/

int wx_write_posted_mbx(struct wx *wx, u32 *msg, u16 size)
{
 int ret;

 /* send msg */
 ret = wx_write_mbx_vf(wx, msg, size);
 /* if msg sent wait until we receive an ack */
 if (ret)
  return ret;

 return wx_poll_for_ack(wx);
}

/**
 *  wx_write_mbx_vf - Write a message to the mailbox
 *  @wx: pointer to the HW structure
 *  @msg: The message buffer
 *  @size: Length of buffer
 *
 *  Return: returns 0 if it successfully copied message into the buffer
 **/

int wx_write_mbx_vf(struct wx *wx, u32 *msg, u16 size)
{
 struct wx_mbx_info *mbx = &wx->mbx;
 int ret, i;

 /* mbx->size is up to 15 */
 if (size > mbx->size) {
  wx_err(wx, "Invalid mailbox message size %d", size);
  return -EINVAL;
 }

 /* lock the mailbox to prevent pf/vf race condition */
 ret = wx_obtain_mbx_lock_vf(wx);
 if (ret)
  return ret;

 /* flush msg and acks as we are overwriting the message buffer */
 wx_check_for_msg_vf(wx);
 wx_check_for_ack_vf(wx);

 /* copy the caller specified message to the mailbox memory buffer */
 for (i = 0; i < size; i++)
  wr32a(wx, WX_VXMBMEM, i, msg[i]);

 /* Drop VFU and interrupt the PF to tell it a message has been sent */
 wr32(wx, WX_VXMAILBOX, WX_VXMAILBOX_REQ);

 return 0;
}

/**
 *  wx_read_mbx_vf - Reads a message from the inbox intended for vf
 *  @wx: pointer to the HW structure
 *  @msg: The message buffer
 *  @size: Length of buffer
 *
 *  Return: returns 0 if it successfully copied message into the buffer
 **/

int wx_read_mbx_vf(struct wx *wx, u32 *msg, u16 size)
{
 struct wx_mbx_info *mbx = &wx->mbx;
 int ret, i;

 /* limit read to size of mailbox and mbx->size is up to 15 */
 if (size > mbx->size)
  size = mbx->size;

 /* lock the mailbox to prevent pf/vf race condition */
 ret = wx_obtain_mbx_lock_vf(wx);
 if (ret)
  return ret;

 /* copy the message from the mailbox memory buffer */
 for (i = 0; i < size; i++)
  msg[i] = rd32a(wx, WX_VXMBMEM, i);

 /* Acknowledge receipt and release mailbox, then we're done */
 wr32(wx, WX_VXMAILBOX, WX_VXMAILBOX_ACK);

 return 0;
}

int wx_init_mbx_params_vf(struct wx *wx)
{
 wx->vfinfo = kzalloc(sizeof(struct vf_data_storage),
        GFP_KERNEL);
 if (!wx->vfinfo)
  return -ENOMEM;

 /* Initialize mailbox parameters */
 wx->mbx.size = WX_VXMAILBOX_SIZE;
 wx->mbx.mailbox = WX_VXMAILBOX;
 wx->mbx.udelay = 10;
 wx->mbx.timeout = 1000;

 return 0;
}
EXPORT_SYMBOL(wx_init_mbx_params_vf);

Messung V0.5
C=96 H=93 G=94

¤ Dauer der Verarbeitung: 0.25 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.