void mlx5_pci_vsc_init(struct mlx5_core_dev *dev)
{ if (!mlx5_core_is_pf(dev)) return;
dev->vsc_addr = pci_find_capability(dev->pdev,
PCI_CAP_ID_VNDR); if (!dev->vsc_addr)
mlx5_core_warn(dev, "Failed to get valid vendor specific ID\n");
}
int mlx5_vsc_gw_lock(struct mlx5_core_dev *dev)
{
u32 counter = 0; int retries = 0;
u32 lock_val; int ret;
pci_cfg_access_lock(dev->pdev); do { if (retries > VSC_MAX_RETRIES) {
ret = -EBUSY; goto pci_unlock;
} if (pci_channel_offline(dev->pdev)) {
ret = -EACCES; goto pci_unlock;
}
/* Check if semaphore is already locked */
ret = vsc_read(dev, VSC_SEMAPHORE_OFFSET, &lock_val); if (ret) goto pci_unlock;
if (lock_val) {
retries++;
usleep_range(1000, 2000); continue;
}
/* Read and write counter value, if written value is * the same, semaphore was acquired successfully.
*/
ret = vsc_read(dev, VSC_COUNTER_OFFSET, &counter); if (ret) goto pci_unlock;
ret = vsc_write(dev, VSC_SEMAPHORE_OFFSET, counter); if (ret) goto pci_unlock;
ret = vsc_read(dev, VSC_SEMAPHORE_OFFSET, &lock_val); if (ret) goto pci_unlock;
int mlx5_vsc_gw_unlock(struct mlx5_core_dev *dev)
{ int ret;
ret = vsc_write(dev, VSC_SEMAPHORE_OFFSET, MLX5_VSC_UNLOCK);
pci_cfg_access_unlock(dev->pdev); return ret;
}
int mlx5_vsc_gw_set_space(struct mlx5_core_dev *dev, u16 space,
u32 *ret_space_size)
{ int ret;
u32 val = 0;
if (!mlx5_vsc_accessible(dev)) return -EINVAL;
if (ret_space_size)
*ret_space_size = 0;
/* Get a unique val */
ret = vsc_read(dev, VSC_CTRL_OFFSET, &val); if (ret) goto out;
/* Try to modify the lock */
val = MLX5_MERGE(val, space, VSC_SPACE_BIT_OFFS, VSC_SPACE_BIT_LEN);
ret = vsc_write(dev, VSC_CTRL_OFFSET, val); if (ret) goto out;
/* Verify lock was modified */
ret = vsc_read(dev, VSC_CTRL_OFFSET, &val); if (ret) goto out;
if (MLX5_EXTRACT(val, VSC_STATUS_BIT_OFFS, VSC_STATUS_BIT_LEN) == 0) return -EINVAL;
/* Get space max address if indicated by size valid bit */ if (ret_space_size &&
MLX5_EXTRACT(val, VSC_SIZE_VLD_BIT_OFFS, VSC_SIZE_VLD_BIT_LEN)) {
ret = vsc_read(dev, VSC_ADDR_OFFSET, &val); if (ret) {
mlx5_core_warn(dev, "Failed to get max space size\n"); goto out;
}
*ret_space_size = MLX5_EXTRACT(val, VSC_ADDR_BIT_OFFS,
VSC_ADDR_BIT_LEN);
} return 0;
out: return ret;
}
staticint mlx5_vsc_wait_on_flag(struct mlx5_core_dev *dev, u8 expected_val)
{ int retries = 0;
u32 flag; int ret;
do { if (retries > VSC_MAX_RETRIES) return -EBUSY;
ret = vsc_read(dev, VSC_ADDR_OFFSET, &flag); if (ret) return ret;
flag = MLX5_EXTRACT(flag, VSC_FLAG_BIT_OFFS, VSC_FLAG_BIT_LEN);
retries++;
if ((retries & 0xf) == 0)
usleep_range(1000, 2000);
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.