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 14 kB image not shown  

Quelle  wx_vf.c   Sprache: C

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

#include <linux/etherdevice.h>
#include <linux/pci.h>

#include "wx_type.h"
#include "wx_hw.h"
#include "wx_mbx.h"
#include "wx_vf.h"

static void wx_virt_clr_reg(struct wx *wx)
{
 u32 vfsrrctl, i;

 /* VRSRRCTL default values (BSIZEPACKET = 2048, BSIZEHEADER = 256) */
 vfsrrctl = WX_VXRXDCTL_HDRSZ(wx_hdr_sz(WX_RX_HDR_SIZE));
 vfsrrctl |= WX_VXRXDCTL_BUFSZ(wx_buf_sz(WX_RX_BUF_SIZE));

 /* clear all rxd ctl */
 for (i = 0; i < WX_VF_MAX_RING_NUMS; i++)
  wr32m(wx, WX_VXRXDCTL(i),
        WX_VXRXDCTL_HDRSZ_MASK | WX_VXRXDCTL_BUFSZ_MASK,
        vfsrrctl);

 rd32(wx, WX_VXSTATUS);
}

/**
 *  wx_init_hw_vf - virtual function hardware initialization
 *  @wx: pointer to hardware structure
 *
 *  Initialize the mac address
 **/

void wx_init_hw_vf(struct wx *wx)
{
 wx_get_mac_addr_vf(wx, wx->mac.addr);
}
EXPORT_SYMBOL(wx_init_hw_vf);

static int wx_mbx_write_and_read_reply(struct wx *wx, u32 *req_buf,
           u32 *resp_buf, u16 size)
{
 int ret;

 ret = wx_write_posted_mbx(wx, req_buf, size);
 if (ret)
  return ret;

 return wx_read_posted_mbx(wx, resp_buf, size);
}

/**
 *  wx_reset_hw_vf - Performs hardware reset
 *  @wx: pointer to hardware structure
 *
 *  Resets the hardware by resetting the transmit and receive units, masks and
 *  clears all interrupts.
 *
 *  Return: returns 0 on success, negative error code on failure
 **/

int wx_reset_hw_vf(struct wx *wx)
{
 struct wx_mbx_info *mbx = &wx->mbx;
 u32 msgbuf[4] = {WX_VF_RESET};
 u8 *addr = (u8 *)(&msgbuf[1]);
 u32 b4_buf[16] = {0};
 u32 timeout = 200;
 int ret;
 u32 i;

 /* Call wx stop to disable tx/rx and clear interrupts */
 wx_stop_adapter_vf(wx);

 /* reset the api version */
 wx->vfinfo->vf_api = wx_mbox_api_null;

 /* backup msix vectors */
 if (wx->b4_addr) {
  for (i = 0; i < 16; i++)
   b4_buf[i] = readl(wx->b4_addr + i * 4);
 }

 wr32m(wx, WX_VXCTRL, WX_VXCTRL_RST, WX_VXCTRL_RST);
 rd32(wx, WX_VXSTATUS);

 /* we cannot reset while the RSTI / RSTD bits are asserted */
 while (!wx_check_for_rst_vf(wx) && timeout) {
  timeout--;
  udelay(5);
 }

 /* restore msix vectors */
 if (wx->b4_addr) {
  for (i = 0; i < 16; i++)
   writel(b4_buf[i], wx->b4_addr + i * 4);
 }

 /* amlite: bme */
 if (wx->mac.type == wx_mac_aml || wx->mac.type == wx_mac_aml40)
  wr32(wx, WX_VX_PF_BME, WX_VF_BME_ENABLE);

 if (!timeout)
  return -EBUSY;

 /* Reset VF registers to initial values */
 wx_virt_clr_reg(wx);

 /* mailbox timeout can now become active */
 mbx->timeout = 2000;

 ret = wx_mbx_write_and_read_reply(wx, msgbuf, msgbuf,
       ARRAY_SIZE(msgbuf));
 if (ret)
  return ret;

 if (msgbuf[0] != (WX_VF_RESET | WX_VT_MSGTYPE_ACK) &&
     msgbuf[0] != (WX_VF_RESET | WX_VT_MSGTYPE_NACK))
  return -EINVAL;

 if (msgbuf[0] == (WX_VF_RESET | WX_VT_MSGTYPE_ACK))
  ether_addr_copy(wx->mac.perm_addr, addr);

 wx->mac.mc_filter_type = msgbuf[3];

 return 0;
}
EXPORT_SYMBOL(wx_reset_hw_vf);

/**
 *  wx_stop_adapter_vf - Generic stop Tx/Rx units
 *  @wx: pointer to hardware structure
 *
 *  Clears interrupts, disables transmit and receive units.
 **/

void wx_stop_adapter_vf(struct wx *wx)
{
 u32 reg_val;
 u16 i;

 /* Clear interrupt mask to stop from interrupts being generated */
 wr32(wx, WX_VXIMS, WX_VF_IRQ_CLEAR_MASK);

 /* Clear any pending interrupts, flush previous writes */
 wr32(wx, WX_VXICR, U32_MAX);

 /* Disable the transmit unit.  Each queue must be disabled. */
 for (i = 0; i < wx->mac.max_tx_queues; i++)
  wr32(wx, WX_VXTXDCTL(i), WX_VXTXDCTL_FLUSH);

 /* Disable the receive unit by stopping each queue */
 for (i = 0; i < wx->mac.max_rx_queues; i++) {
  reg_val = rd32(wx, WX_VXRXDCTL(i));
  reg_val &= ~WX_VXRXDCTL_ENABLE;
  wr32(wx, WX_VXRXDCTL(i), reg_val);
 }
 /* Clear packet split and pool config */
 wr32(wx, WX_VXMRQC, 0);

 /* flush all queues disables */
 rd32(wx, WX_VXSTATUS);
}
EXPORT_SYMBOL(wx_stop_adapter_vf);

/**
 *  wx_set_rar_vf - set device MAC address
 *  @wx: pointer to hardware structure
 *  @index: Receive address register to write
 *  @addr: Address to put into receive address register
 *  @enable_addr: set flag that address is active
 *
 *  Return: returns 0 on success, negative error code on failure
 **/

int wx_set_rar_vf(struct wx *wx, u32 index, u8 *addr, u32 enable_addr)
{
 u32 msgbuf[3] = {WX_VF_SET_MAC_ADDR};
 u8 *msg_addr = (u8 *)(&msgbuf[1]);
 int ret;

 memcpy(msg_addr, addr, ETH_ALEN);

 ret = wx_mbx_write_and_read_reply(wx, msgbuf, msgbuf,
       ARRAY_SIZE(msgbuf));
 if (ret)
  return ret;
 msgbuf[0] &= ~WX_VT_MSGTYPE_CTS;

 /* if nacked the address was rejected, use "perm_addr" */
 if (msgbuf[0] == (WX_VF_SET_MAC_ADDR | WX_VT_MSGTYPE_NACK)) {
  wx_get_mac_addr_vf(wx, wx->mac.addr);
  return -EINVAL;
 }

 return 0;
}
EXPORT_SYMBOL(wx_set_rar_vf);

/**
 *  wx_update_mc_addr_list_vf - Update Multicast addresses
 *  @wx: pointer to the HW structure
 *  @netdev: pointer to the net device structure
 *
 *  Updates the Multicast Table Array.
 *
 *  Return: returns 0 on success, negative error code on failure
 **/

int wx_update_mc_addr_list_vf(struct wx *wx, struct net_device *netdev)
{
 u32 msgbuf[WX_VXMAILBOX_SIZE] = {WX_VF_SET_MULTICAST};
 u16 *vector_l = (u16 *)&msgbuf[1];
 struct netdev_hw_addr *ha;
 u32 cnt, i;

 cnt = netdev_mc_count(netdev);
 if (cnt > 28)
  cnt = 28;
 msgbuf[0] |= cnt << WX_VT_MSGINFO_SHIFT;

 i = 0;
 netdev_for_each_mc_addr(ha, netdev) {
  if (i == cnt)
   break;
  if (is_link_local_ether_addr(ha->addr))
   continue;

  vector_l[i++] = wx_mta_vector(wx, ha->addr);
 }

 return wx_write_posted_mbx(wx, msgbuf, ARRAY_SIZE(msgbuf));
}
EXPORT_SYMBOL(wx_update_mc_addr_list_vf);

/**
 *  wx_update_xcast_mode_vf - Update Multicast mode
 *  @wx: pointer to the HW structure
 *  @xcast_mode: new multicast mode
 *
 *  Updates the Multicast Mode of VF.
 *
 *  Return: returns 0 on success, negative error code on failure
 **/

int wx_update_xcast_mode_vf(struct wx *wx, int xcast_mode)
{
 u32 msgbuf[2] = {WX_VF_UPDATE_XCAST_MODE, xcast_mode};
 int ret = 0;

 if (wx->vfinfo->vf_api < wx_mbox_api_13)
  return -EINVAL;

 ret = wx_mbx_write_and_read_reply(wx, msgbuf, msgbuf,
       ARRAY_SIZE(msgbuf));
 if (ret)
  return ret;

 msgbuf[0] &= ~WX_VT_MSGTYPE_CTS;
 if (msgbuf[0] == (WX_VF_UPDATE_XCAST_MODE | WX_VT_MSGTYPE_NACK))
  return -EINVAL;

 return 0;
}
EXPORT_SYMBOL(wx_update_xcast_mode_vf);

/**
 * wx_get_link_state_vf - Get VF link state from PF
 * @wx: pointer to the HW structure
 * @link_state: link state storage
 *
 * Return: return state of the operation error or success.
 **/

int wx_get_link_state_vf(struct wx *wx, u16 *link_state)
{
 u32 msgbuf[2] = {WX_VF_GET_LINK_STATE};
 int ret;

 ret = wx_mbx_write_and_read_reply(wx, msgbuf, msgbuf,
       ARRAY_SIZE(msgbuf));
 if (ret)
  return ret;

 if (msgbuf[0] & WX_VT_MSGTYPE_NACK)
  return -EINVAL;

 *link_state = msgbuf[1];

 return 0;
}
EXPORT_SYMBOL(wx_get_link_state_vf);

/**
 *  wx_set_vfta_vf - Set/Unset vlan filter table address
 *  @wx: pointer to the HW structure
 *  @vlan: 12 bit VLAN ID
 *  @vind: unused by VF drivers
 *  @vlan_on: if true then set bit, else clear bit
 *  @vlvf_bypass: boolean flag indicating updating default pool is okay
 *
 *  Turn on/off specified VLAN in the VLAN filter table.
 *
 *  Return: returns 0 on success, negative error code on failure
 **/

int wx_set_vfta_vf(struct wx *wx, u32 vlan, u32 vind, bool vlan_on,
     bool vlvf_bypass)
{
 u32 msgbuf[2] = {WX_VF_SET_VLAN, vlan};
 bool vlan_offload = false;
 int ret;

 /* Setting the 8 bit field MSG INFO to TRUE indicates "add" */
 msgbuf[0] |= vlan_on << WX_VT_MSGINFO_SHIFT;
 /* if vf vlan offload is disabled, allow to create vlan under pf port vlan */
 msgbuf[0] |= BIT(vlan_offload);

 ret = wx_mbx_write_and_read_reply(wx, msgbuf, msgbuf,
       ARRAY_SIZE(msgbuf));
 if (ret)
  return ret;

 if (msgbuf[0] & WX_VT_MSGTYPE_ACK)
  return 0;

 return msgbuf[0] & WX_VT_MSGTYPE_NACK;
}
EXPORT_SYMBOL(wx_set_vfta_vf);

void wx_get_mac_addr_vf(struct wx *wx, u8 *mac_addr)
{
 ether_addr_copy(mac_addr, wx->mac.perm_addr);
}
EXPORT_SYMBOL(wx_get_mac_addr_vf);

int wx_get_fw_version_vf(struct wx *wx)
{
 u32 msgbuf[2] = {WX_VF_GET_FW_VERSION};
 int ret;

 ret = wx_mbx_write_and_read_reply(wx, msgbuf, msgbuf,
       ARRAY_SIZE(msgbuf));
 if (ret)
  return ret;

 if (msgbuf[0] & WX_VT_MSGTYPE_NACK)
  return -EINVAL;
 snprintf(wx->eeprom_id, 32, "0x%08x", msgbuf[1]);

 return 0;
}
EXPORT_SYMBOL(wx_get_fw_version_vf);

int wx_set_uc_addr_vf(struct wx *wx, u32 index, u8 *addr)
{
 u32 msgbuf[3] = {WX_VF_SET_MACVLAN};
 u8 *msg_addr = (u8 *)(&msgbuf[1]);
 int ret;

 /* If index is one then this is the start of a new list and needs
 * indication to the PF so it can do it's own list management.
 * If it is zero then that tells the PF to just clear all of
 * this VF's macvlans and there is no new list.
 */

 msgbuf[0] |= index << WX_VT_MSGINFO_SHIFT;
 if (addr)
  memcpy(msg_addr, addr, 6);
 ret = wx_mbx_write_and_read_reply(wx, msgbuf, msgbuf,
       ARRAY_SIZE(msgbuf));
 if (ret)
  return ret;

 msgbuf[0] &= ~WX_VT_MSGTYPE_CTS;

 if (msgbuf[0] == (WX_VF_SET_MACVLAN | WX_VT_MSGTYPE_NACK))
  return -EINVAL;

 return 0;
}
EXPORT_SYMBOL(wx_set_uc_addr_vf);

/**
 *  wx_rlpml_set_vf - Set the maximum receive packet length
 *  @wx: pointer to the HW structure
 *  @max_size: value to assign to max frame size
 *
 *  Return: returns 0 on success, negative error code on failure
 **/

int wx_rlpml_set_vf(struct wx *wx, u16 max_size)
{
 u32 msgbuf[2] = {WX_VF_SET_LPE, max_size};
 int ret;

 ret = wx_mbx_write_and_read_reply(wx, msgbuf, msgbuf,
       ARRAY_SIZE(msgbuf));
 if (ret)
  return ret;
 if ((msgbuf[0] & WX_VF_SET_LPE) &&
     (msgbuf[0] & WX_VT_MSGTYPE_NACK))
  return -EINVAL;

 return 0;
}
EXPORT_SYMBOL(wx_rlpml_set_vf);

/**
 *  wx_negotiate_api_version - Negotiate supported API version
 *  @wx: pointer to the HW structure
 *  @api: integer containing requested API version
 *
 *  Return: returns 0 on success, negative error code on failure
 **/

int wx_negotiate_api_version(struct wx *wx, int api)
{
 u32 msgbuf[2] = {WX_VF_API_NEGOTIATE, api};
 int ret;

 ret = wx_mbx_write_and_read_reply(wx, msgbuf, msgbuf,
       ARRAY_SIZE(msgbuf));
 if (ret)
  return ret;

 msgbuf[0] &= ~WX_VT_MSGTYPE_CTS;

 /* Store value and return 0 on success */
 if (msgbuf[0] == (WX_VF_API_NEGOTIATE | WX_VT_MSGTYPE_NACK))
  return -EINVAL;
 wx->vfinfo->vf_api = api;

 return 0;
}
EXPORT_SYMBOL(wx_negotiate_api_version);

int wx_get_queues_vf(struct wx *wx, u32 *num_tcs, u32 *default_tc)
{
 u32 msgbuf[5] = {WX_VF_GET_QUEUES};
 int ret;

 /* do nothing if API doesn't support wx_get_queues */
 if (wx->vfinfo->vf_api < wx_mbox_api_13)
  return -EINVAL;

 /* Fetch queue configuration from the PF */
 ret = wx_mbx_write_and_read_reply(wx, msgbuf, msgbuf,
       ARRAY_SIZE(msgbuf));
 if (ret)
  return ret;
 msgbuf[0] &= ~WX_VT_MSGTYPE_CTS;

 /* if we didn't get an ACK there must have been
 * some sort of mailbox error so we should treat it
 * as such
 */

 if (msgbuf[0] != (WX_VF_GET_QUEUES | WX_VT_MSGTYPE_ACK))
  return -EINVAL;
 /* record and validate values from message */
 wx->mac.max_tx_queues = msgbuf[WX_VF_TX_QUEUES];
 if (wx->mac.max_tx_queues == 0 ||
     wx->mac.max_tx_queues > WX_VF_MAX_TX_QUEUES)
  wx->mac.max_tx_queues = WX_VF_MAX_TX_QUEUES;

 wx->mac.max_rx_queues = msgbuf[WX_VF_RX_QUEUES];
 if (wx->mac.max_rx_queues == 0 ||
     wx->mac.max_rx_queues > WX_VF_MAX_RX_QUEUES)
  wx->mac.max_rx_queues = WX_VF_MAX_RX_QUEUES;

 *num_tcs = msgbuf[WX_VF_TRANS_VLAN];
 /* in case of unknown state assume we cannot tag frames */
 if (*num_tcs > wx->mac.max_rx_queues)
  *num_tcs = 1;
 *default_tc = msgbuf[WX_VF_DEF_QUEUE];
 /* default to queue 0 on out-of-bounds queue number */
 if (*default_tc >= wx->mac.max_tx_queues)
  *default_tc = 0;

 return 0;
}
EXPORT_SYMBOL(wx_get_queues_vf);

static int wx_get_link_status_from_pf(struct wx *wx, u32 *msgbuf)
{
 u32 links_reg = msgbuf[1];

 if (msgbuf[1] & WX_PF_NOFITY_VF_NET_NOT_RUNNING)
  wx->notify_down = true;
 else
  wx->notify_down = false;

 if (wx->notify_down) {
  wx->link = false;
  wx->speed = SPEED_UNKNOWN;
  return 0;
 }

 wx->link = WX_PFLINK_STATUS(links_reg);
 wx->speed = WX_PFLINK_SPEED(links_reg);

 return 0;
}

static int wx_pf_ping_vf(struct wx *wx, u32 *msgbuf)
{
 if (!(msgbuf[0] & WX_VT_MSGTYPE_CTS))
  /* msg is not CTS, we need to do reset */
  return -EINVAL;

 return 0;
}

static struct wx_link_reg_fields wx_speed_lookup_vf[] = {
 {wx_mac_unknown},
 {wx_mac_sp, SPEED_10000, SPEED_1000, SPEED_100, SPEED_UNKNOWN, SPEED_UNKNOWN},
 {wx_mac_em, SPEED_1000,  SPEED_100, SPEED_10, SPEED_UNKNOWN, SPEED_UNKNOWN},
 {wx_mac_aml, SPEED_40000, SPEED_25000, SPEED_10000, SPEED_1000, SPEED_UNKNOWN},
 {wx_mac_aml40, SPEED_40000, SPEED_25000, SPEED_10000, SPEED_1000, SPEED_UNKNOWN},
};

static void wx_check_physical_link(struct wx *wx)
{
 u32 val, link_val;
 int ret;

 /* get link status from hw status reg
 * for SFP+ modules and DA cables, it can take up to 500usecs
 * before the link status is correct
 */

 if (wx->mac.type == wx_mac_em)
  ret = read_poll_timeout_atomic(rd32, val, val & GENMASK(4, 1),
            100, 500, false, wx, WX_VXSTATUS);
 else
  ret = read_poll_timeout_atomic(rd32, val, val & BIT(0), 100,
            500, false, wx, WX_VXSTATUS);
 if (ret) {
  wx->speed = SPEED_UNKNOWN;
  wx->link = false;
  return;
 }

 wx->link = true;
 link_val = WX_VXSTATUS_SPEED(val);

 if (link_val & BIT(0))
  wx->speed = wx_speed_lookup_vf[wx->mac.type].bit0_f;
 else if (link_val & BIT(1))
  wx->speed = wx_speed_lookup_vf[wx->mac.type].bit1_f;
 else if (link_val & BIT(2))
  wx->speed = wx_speed_lookup_vf[wx->mac.type].bit2_f;
 else if (link_val & BIT(3))
  wx->speed = wx_speed_lookup_vf[wx->mac.type].bit3_f;
 else
  wx->speed = SPEED_UNKNOWN;
}

int wx_check_mac_link_vf(struct wx *wx)
{
 struct wx_mbx_info *mbx = &wx->mbx;
 u32 msgbuf[2] = {0};
 int ret = 0;

 if (!mbx->timeout)
  goto out;

 wx_check_for_rst_vf(wx);
 if (!wx_check_for_msg_vf(wx))
  ret = wx_read_mbx_vf(wx, msgbuf, 2);
 if (ret)
  goto out;

 switch (msgbuf[0] & GENMASK(8, 0)) {
 case WX_PF_NOFITY_VF_LINK_STATUS | WX_PF_CONTROL_MSG:
  ret = wx_get_link_status_from_pf(wx, msgbuf);
  goto out;
 case WX_PF_CONTROL_MSG:
  ret = wx_pf_ping_vf(wx, msgbuf);
  goto out;
 case 0:
  if (msgbuf[0] & WX_VT_MSGTYPE_NACK) {
   /* msg is NACK, we must have lost CTS status */
   ret = -EBUSY;
   goto out;
  }
  /* no message, check link status */
  wx_check_physical_link(wx);
  goto out;
 default:
  break;
 }

 if (!(msgbuf[0] & WX_VT_MSGTYPE_CTS)) {
  /* msg is not CTS and is NACK we must have lost CTS status */
  if (msgbuf[0] & WX_VT_MSGTYPE_NACK)
   ret = -EBUSY;
  goto out;
 }

 /* the pf is talking, if we timed out in the past we reinit */
 if (!mbx->timeout) {
  ret = -EBUSY;
  goto out;
 }

out:
 return ret;
}

Messung V0.5
C=92 H=93 G=92

¤ Dauer der Verarbeitung: 0.7 Sekunden  ¤

*© 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.