2 * Copyright (c) 2013-2017, Mellanox Technologies, Ltd. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS `AS IS' AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 #include <dev/mlx5/driver.h>
29 #include <dev/mlx5/device.h>
30 #include <dev/mlx5/mlx5_core/mlx5_core.h>
32 struct mlx5_ifc_vsc_space_bits {
38 struct mlx5_ifc_vsc_addr_bits {
44 int mlx5_vsc_lock(struct mlx5_core_dev *mdev)
46 device_t dev = mdev->pdev->dev.bsddev;
47 int vsc_addr = mdev->vsc_addr;
53 mlx5_core_warn(mdev, "Unable to acquire vsc lock, vsc_addr not initialized\n");
58 if (retries > MLX5_VSC_MAX_RETRIES)
61 if (pci_read_config(dev, vsc_addr + MLX5_VSC_SEMA_OFFSET, 4)) {
64 * The PRM suggests random 0 - 10ms to prevent multiple
65 * waiters on the same interval in order to avoid starvation
67 DELAY((random() % 11) * 1000);
71 counter = pci_read_config(dev, vsc_addr + MLX5_VSC_COUNTER_OFFSET, 4);
72 pci_write_config(dev, vsc_addr + MLX5_VSC_SEMA_OFFSET, counter, 4);
73 lock_val = pci_read_config(dev, vsc_addr + MLX5_VSC_SEMA_OFFSET, 4);
75 if (lock_val == counter)
84 void mlx5_vsc_unlock(struct mlx5_core_dev *mdev)
86 device_t dev = mdev->pdev->dev.bsddev;
87 int vsc_addr = mdev->vsc_addr;
90 mlx5_core_warn(mdev, "Unable to release vsc lock, vsc_addr not initialized\n");
94 pci_write_config(dev, vsc_addr + MLX5_VSC_SEMA_OFFSET, 0, 4);
97 static int mlx5_vsc_wait_on_flag(struct mlx5_core_dev *mdev, u32 expected)
99 device_t dev = mdev->pdev->dev.bsddev;
100 int vsc_addr = mdev->vsc_addr;
105 if (retries > MLX5_VSC_MAX_RETRIES)
108 flag = pci_read_config(dev, vsc_addr + MLX5_VSC_ADDR_OFFSET, 4);
109 if (expected == MLX5_VSC_GET(vsc_addr, &flag, flag))
119 int mlx5_vsc_set_space(struct mlx5_core_dev *mdev, u16 space)
121 device_t dev = mdev->pdev->dev.bsddev;
122 int vsc_addr = mdev->vsc_addr;
126 mlx5_core_warn(mdev, "Unable to set vsc space, vsc_addr not initialized\n");
130 MLX5_VSC_SET(vsc_space, &vsc_space, space, space);
131 pci_write_config(dev, vsc_addr + MLX5_VSC_SPACE_OFFSET, vsc_space, 4);
132 vsc_space = pci_read_config(dev, vsc_addr + MLX5_VSC_SPACE_OFFSET, 4);
134 if (MLX5_VSC_GET(vsc_space, &vsc_space, status) != MLX5_VSC_SPACE_SUPPORTED) {
135 mlx5_core_warn(mdev, "Space 0x%x is not supported.\n", space);
142 int mlx5_vsc_write(struct mlx5_core_dev *mdev, u32 addr, u32 *data)
144 device_t dev = mdev->pdev->dev.bsddev;
145 int vsc_addr = mdev->vsc_addr;
150 mlx5_core_warn(mdev, "Unable to call vsc write, vsc_addr not initialized\n");
154 MLX5_VSC_SET(vsc_addr, &in, address, addr);
155 MLX5_VSC_SET(vsc_addr, &in, flag, 1);
156 pci_write_config(dev, vsc_addr + MLX5_VSC_DATA_OFFSET, *data, 4);
157 pci_write_config(dev, vsc_addr + MLX5_VSC_ADDR_OFFSET, in, 4);
159 err = mlx5_vsc_wait_on_flag(mdev, 0);
161 mlx5_core_warn(mdev, "Failed waiting for write flag!\n");
166 int mlx5_vsc_read(struct mlx5_core_dev *mdev, u32 addr, u32 *data)
168 device_t dev = mdev->pdev->dev.bsddev;
169 int vsc_addr = mdev->vsc_addr;
174 mlx5_core_warn(mdev, "Unable to call vsc read, vsc_addr not initialized\n");
178 MLX5_VSC_SET(vsc_addr, &in, address, addr);
179 pci_write_config(dev, vsc_addr + MLX5_VSC_ADDR_OFFSET, in, 4);
181 err = mlx5_vsc_wait_on_flag(mdev, 1);
183 mlx5_core_warn(mdev, "Failed waiting for read complete flag!\n");
187 *data = pci_read_config(dev, vsc_addr + MLX5_VSC_DATA_OFFSET, 4);
192 int mlx5_vsc_find_cap(struct mlx5_core_dev *mdev)
194 int *capreg = &mdev->vsc_addr;
197 err = pci_find_cap(mdev->pdev->dev.bsddev, PCIY_VENDOR, capreg);