return 0;
}
+static void init_spi_share_data(struct ifpga_fme_hw *fme,
+ struct altera_spi_device *spi)
+{
+ struct ifpga_hw *hw = (struct ifpga_hw *)fme->parent;
+ opae_share_data *sd = NULL;
+
+ if (hw && hw->adapter && hw->adapter->shm.ptr) {
+ dev_info(NULL, "transfer share data to spi\n");
+ sd = (opae_share_data *)hw->adapter->shm.ptr;
+ spi->mutex = &sd->spi_mutex;
+ spi->dtb_sz_ptr = &sd->dtb_size;
+ spi->dtb = sd->dtb;
+ } else {
+ spi->mutex = NULL;
+ spi->dtb_sz_ptr = NULL;
+ spi->dtb = NULL;
+ }
+}
+
static int fme_spi_init(struct ifpga_feature *feature)
{
struct ifpga_fme_hw *fme = (struct ifpga_fme_hw *)feature->parent;
spi_master = altera_spi_alloc(feature->addr, TYPE_SPI);
if (!spi_master)
return -ENODEV;
+ init_spi_share_data(fme, spi_master);
altera_spi_init(spi_master);
goto spi_fail;
}
-
fme->max10_dev = max10;
/* SPI self test */
spi_master = altera_spi_alloc(feature->addr, TYPE_NIOS_SPI);
if (!spi_master)
return -ENODEV;
+ init_spi_share_data(fme, spi_master);
/**
* 1. wait A10 NIOS initial finished and
* release the SPI master to Host
*/
+ if (spi_master->mutex)
+ pthread_mutex_lock(spi_master->mutex);
+
ret = nios_spi_wait_init_done(spi_master);
if (ret != 0) {
dev_err(fme, "FME NIOS_SPI init fail\n");
if (nios_spi_check_error(spi_master))
dev_info(fme, "NIOS_SPI INIT done, but found some error\n");
+ if (spi_master->mutex)
+ pthread_mutex_unlock(spi_master->mutex);
+
/* 3. init the spi master*/
altera_spi_init(spi_master);
goto release_dev;
}
+ fme->max10_dev = max10;
+
max10->bus = hw->pci_data->bus;
fme_get_board_interface(fme);
- fme->max10_dev = max10;
mgr->sensor_list = &max10->opae_sensor_list;
/* SPI self test */
return 0;
}
+static void init_i2c_mutex(struct ifpga_fme_hw *fme)
+{
+ struct ifpga_hw *hw = (struct ifpga_hw *)fme->parent;
+ struct altera_i2c_dev *i2c_dev;
+ opae_share_data *sd = NULL;
+
+ if (fme->i2c_master) {
+ i2c_dev = (struct altera_i2c_dev *)fme->i2c_master;
+ if (hw && hw->adapter && hw->adapter->shm.ptr) {
+ dev_info(NULL, "use multi-process mutex in i2c\n");
+ sd = (opae_share_data *)hw->adapter->shm.ptr;
+ i2c_dev->mutex = &sd->i2c_mutex;
+ } else {
+ dev_info(NULL, "use multi-thread mutex in i2c\n");
+ i2c_dev->mutex = &i2c_dev->lock;
+ }
+ }
+}
+
static int fme_i2c_init(struct ifpga_feature *feature)
{
struct feature_fme_i2c *i2c;
if (!fme->i2c_master)
return -ENODEV;
+ init_i2c_mutex(fme);
+
/* MAC ROM self test */
i2c_mac_rom_test(fme->i2c_master);
'opae_eth_group.c',
]
+rtdep = dependency('librt', required: false)
+if not rtdep.found()
+ rtdep = cc.find_library('librt', required: false)
+endif
+if not rtdep.found()
+ build = false
+ reason = 'missing dependency, "librt"'
+ subdir_done()
+endif
+
+ext_deps += rtdep
+
base_lib = static_library('ifpga_rawdev_base', sources,
dependencies: static_rte_eal,
c_args: cflags)
* Copyright(c) 2010-2018 Intel Corporation
*/
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
#include "opae_hw_api.h"
#include "opae_debug.h"
#include "ifpga_api.h"
return NULL;
}
+static void opae_mutex_init(pthread_mutex_t *mutex)
+{
+ pthread_mutexattr_t mattr;
+
+ pthread_mutexattr_init(&mattr);
+ pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_RECURSIVE);
+ pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_SHARED);
+ pthread_mutexattr_setrobust(&mattr, PTHREAD_MUTEX_ROBUST);
+ pthread_mutexattr_setprotocol(&mattr, PTHREAD_PRIO_INHERIT);
+ pthread_mutex_init(mutex, &mattr);
+ pthread_mutexattr_destroy(&mattr);
+}
+
+static int opae_shm_open(char *shm_name, u32 size, int *new_shm)
+{
+ int shm_id;
+ int ret;
+
+ shm_id = shm_open(shm_name, O_CREAT | O_EXCL | O_RDWR, 0666);
+ if (shm_id == -1) {
+ if (errno == EEXIST) {
+ dev_info(NULL, "shared memory %s already exist\n",
+ shm_name);
+ shm_id = shm_open(shm_name, O_RDWR, 0666);
+ } else {
+ dev_err(NULL, "failed to create shared memory %s\n",
+ shm_name);
+ return -1;
+ }
+ } else {
+ *new_shm = 1;
+ ret = ftruncate(shm_id, size);
+ if (ret == -1) {
+ dev_err(NULL,
+ "failed to set shared memory size to %u\n",
+ size);
+ ret = shm_unlink(shm_name);
+ if (ret == -1) {
+ dev_err(NULL,
+ "failed to unlink shared memory %s\n",
+ shm_name);
+ }
+ return -1;
+ }
+ }
+
+ return shm_id;
+}
+
+static pthread_mutex_t *opae_adapter_mutex_open(struct opae_adapter *adapter)
+{
+ char shm_name[32];
+ void *ptr;
+ int shm_id;
+ int new_shm = 0;
+
+ if (!adapter->data)
+ return NULL;
+ adapter->lock = NULL;
+
+ snprintf(shm_name, sizeof(shm_name), "/mutex.IFPGA:%s", adapter->name);
+ shm_id = opae_shm_open(shm_name, sizeof(pthread_mutex_t), &new_shm);
+ if (shm_id == -1) {
+ dev_err(NULL, "failed to open shared memory %s\n", shm_name);
+ } else {
+ dev_info(NULL, "shared memory %s id is %d\n",
+ shm_name, shm_id);
+ ptr = mmap(NULL, sizeof(pthread_mutex_t),
+ PROT_READ | PROT_WRITE, MAP_SHARED,
+ shm_id, 0);
+ adapter->lock = (pthread_mutex_t *)ptr;
+ if (ptr) {
+ dev_info(NULL,
+ "shared memory %s address is %p\n",
+ shm_name, ptr);
+ if (new_shm)
+ opae_mutex_init(adapter->lock);
+ } else {
+ dev_err(NULL, "failed to map shared memory %s\n",
+ shm_name);
+ }
+ }
+
+ return adapter->lock;
+}
+
+static void opae_adapter_mutex_close(struct opae_adapter *adapter)
+{
+ char shm_name[32];
+ int ret;
+
+ if (!adapter->lock)
+ return;
+
+ snprintf(shm_name, sizeof(shm_name), "/mutex.IFPGA:%s", adapter->name);
+
+ ret = munmap(adapter->lock, sizeof(pthread_mutex_t));
+ if (ret == -1)
+ dev_err(NULL, "failed to unmap shared memory %s\n", shm_name);
+ else
+ adapter->lock = NULL;
+}
+
+/**
+ * opae_adapter_lock - lock this adapter
+ * @adapter: adapter to lock.
+ * @timeout: maximum time to wait for lock done
+ * -1 wait until the lock is available
+ * 0 do not wait and return immediately
+ * t positive time in second to wait
+ *
+ * Return: 0 on success, otherwise error code.
+ */
+int opae_adapter_lock(struct opae_adapter *adapter, int timeout)
+{
+ struct timespec t;
+ int ret = -EINVAL;
+
+ if (adapter && adapter->lock) {
+ if (timeout < 0) {
+ ret = pthread_mutex_lock(adapter->lock);
+ } else if (timeout == 0) {
+ ret = pthread_mutex_trylock(adapter->lock);
+ } else {
+ clock_gettime(CLOCK_REALTIME, &t);
+ t.tv_sec += timeout;
+ ret = pthread_mutex_timedlock(adapter->lock, &t);
+ }
+ }
+ return ret;
+}
+
+/**
+ * opae_adapter_unlock - unlock this adapter
+ * @adapter: adapter to unlock.
+ *
+ * Return: 0 on success, otherwise error code.
+ */
+int opae_adapter_unlock(struct opae_adapter *adapter)
+{
+ int ret = -EINVAL;
+
+ if (adapter && adapter->lock)
+ ret = pthread_mutex_unlock(adapter->lock);
+
+ return ret;
+}
+
+static void opae_adapter_shm_init(struct opae_adapter *adapter)
+{
+ opae_share_data *sd;
+
+ if (!adapter->shm.ptr)
+ return;
+
+ sd = (opae_share_data *)adapter->shm.ptr;
+ dev_info(NULL, "initialize shared memory\n");
+ opae_mutex_init(&sd->spi_mutex);
+ opae_mutex_init(&sd->i2c_mutex);
+ sd->ref_cnt = 0;
+ sd->dtb_size = SHM_BLK_SIZE;
+}
+
+static void *opae_adapter_shm_alloc(struct opae_adapter *adapter)
+{
+ char shm_name[32];
+ opae_share_data *sd;
+ u32 size = sizeof(opae_share_data);
+ int shm_id;
+ int new_shm = 0;
+
+ if (!adapter->data)
+ return NULL;
+
+ snprintf(shm_name, sizeof(shm_name), "/IFPGA:%s", adapter->name);
+ adapter->shm.ptr = NULL;
+
+ opae_adapter_lock(adapter, -1);
+ shm_id = opae_shm_open(shm_name, size, &new_shm);
+ if (shm_id == -1) {
+ dev_err(NULL, "failed to open shared memory %s\n", shm_name);
+ } else {
+ dev_info(NULL, "shared memory %s id is %d\n",
+ shm_name, shm_id);
+ adapter->shm.id = shm_id;
+ adapter->shm.size = size;
+ adapter->shm.ptr = mmap(NULL, size, PROT_READ | PROT_WRITE,
+ MAP_SHARED, shm_id, 0);
+ if (adapter->shm.ptr) {
+ dev_info(NULL,
+ "shared memory %s address is %p\n",
+ shm_name, adapter->shm.ptr);
+ if (new_shm)
+ opae_adapter_shm_init(adapter);
+ sd = (opae_share_data *)adapter->shm.ptr;
+ sd->ref_cnt++;
+ } else {
+ dev_err(NULL, "failed to map shared memory %s\n",
+ shm_name);
+ }
+ }
+ opae_adapter_unlock(adapter);
+
+ return adapter->shm.ptr;
+}
+
+static void opae_adapter_shm_free(struct opae_adapter *adapter)
+{
+ char shm_name[32];
+ opae_share_data *sd;
+ u32 ref_cnt;
+ int ret;
+
+ if (!adapter->shm.ptr)
+ return;
+
+ sd = (opae_share_data *)adapter->shm.ptr;
+ snprintf(shm_name, sizeof(shm_name), "/IFPGA:%s", adapter->name);
+
+ opae_adapter_lock(adapter, -1);
+ ref_cnt = --sd->ref_cnt;
+ ret = munmap(adapter->shm.ptr, adapter->shm.size);
+ if (ret == -1)
+ dev_err(NULL, "failed to unmap shared memory %s\n", shm_name);
+ else
+ adapter->shm.ptr = NULL;
+
+ if (ref_cnt == 0) {
+ dev_info(NULL, "unlink shared memory %s\n", shm_name);
+ ret = shm_unlink(shm_name);
+ if (ret == -1) {
+ dev_err(NULL, "failed to unlink shared memory %s\n",
+ shm_name);
+ }
+ }
+ opae_adapter_unlock(adapter);
+}
+
/**
* opae_adapter_init - init opae_adapter data structure
* @adapter: pointer of opae_adapter data structure
adapter->name = name;
adapter->ops = match_ops(adapter);
+ if (!opae_adapter_mutex_open(adapter))
+ return -ENOMEM;
+
+ if (!opae_adapter_shm_alloc(adapter))
+ return -ENOMEM;
+
return 0;
}
{
if (adapter && adapter->ops && adapter->ops->destroy)
adapter->ops->destroy(adapter);
+ opae_adapter_shm_free(adapter);
+ opae_adapter_mutex_close(adapter);
}
/**
#define opae_adapter_for_each_acc(adatper, acc) \
TAILQ_FOREACH(acc, &adapter->acc_list, node)
+#define SHM_PREFIX "/IFPGA:"
+#define SHM_BLK_SIZE 0x2000
+
+typedef struct {
+ union {
+ u8 byte[SHM_BLK_SIZE];
+ struct {
+ pthread_mutex_t spi_mutex;
+ pthread_mutex_t i2c_mutex;
+ u32 ref_cnt; /* reference count of shared memory */
+ u32 dtb_size; /* actual length of DTB data in byte */
+ };
+ };
+ u8 dtb[SHM_BLK_SIZE]; /* DTB data */
+} opae_share_data;
+
+typedef struct {
+ int id; /* shared memory id returned by shm_open */
+ u32 size; /* size of shared memory in byte */
+ void *ptr; /* start address of shared memory */
+} opae_share_memory;
+
struct opae_adapter {
const char *name;
struct opae_manager *mgr;
struct opae_accelerator_list acc_list;
struct opae_adapter_ops *ops;
void *data;
+ pthread_mutex_t *lock; /* multi-process mutex for IFPGA */
+ opae_share_memory shm;
};
/* OPAE Adapter APIs */
int opae_adapter_init(struct opae_adapter *adapter,
const char *name, void *data);
#define opae_adapter_free(adapter) opae_free(adapter)
-
+int opae_adapter_lock(struct opae_adapter *adapter, int timeout);
+int opae_adapter_unlock(struct opae_adapter *adapter);
int opae_adapter_enumerate(struct opae_adapter *adapter);
void opae_adapter_destroy(struct opae_adapter *adapter);
static inline struct opae_manager *
int i = 0;
int ret;
- pthread_mutex_lock(&dev->lock);
+ pthread_mutex_lock(dev->mutex);
if (flags & I2C_FLAG_ADDR16)
msgbuf[i++] = offset >> 8;
ret = i2c_transfer(dev, msg, 2);
exit:
- pthread_mutex_unlock(&dev->lock);
+ pthread_mutex_unlock(dev->mutex);
return ret;
}
int ret;
int i = 0;
- pthread_mutex_lock(&dev->lock);
+ pthread_mutex_lock(dev->mutex);
if (!dev->xfer) {
ret = -ENODEV;
opae_free(buf);
exit:
- pthread_mutex_unlock(&dev->lock);
+ pthread_mutex_unlock(dev->mutex);
return ret;
}
if (pthread_mutex_init(&dev->lock, NULL))
return NULL;
+ dev->mutex = &dev->lock;
altera_i2c_hardware_init(dev);
u8 *buf;
int (*xfer)(struct altera_i2c_dev *dev, struct i2c_msg *msg, int num);
pthread_mutex_t lock;
+ pthread_mutex_t *mutex; /* multi-process mutex from adapter */
};
/**
static int init_max10_device_table(struct intel_max10_device *max10)
{
+ struct altera_spi_device *spi = NULL;
struct max10_compatible_id *id;
struct fdt_header hdr;
char *fdt_root = NULL;
-
+ u32 dtb_magic = 0;
u32 dt_size, dt_addr, val;
- int ret;
-
- ret = max10_sys_read(max10, DT_AVAIL_REG, &val);
- if (ret) {
- dev_err(max10 "cannot read DT_AVAIL_REG\n");
- return ret;
- }
+ int ret = 0;
- if (!(val & DT_AVAIL)) {
- dev_err(max10 "DT not available\n");
+ spi = (struct altera_spi_device *)max10->spi_master;
+ if (!spi) {
+ dev_err(max10, "spi master is not set\n");
return -EINVAL;
}
+ if (spi->dtb)
+ dtb_magic = *(u32 *)spi->dtb;
+
+ if (dtb_magic != 0xEDFE0DD0) {
+ dev_info(max10, "read DTB from NOR flash\n");
+ ret = max10_sys_read(max10, DT_AVAIL_REG, &val);
+ if (ret) {
+ dev_err(max10 "cannot read DT_AVAIL_REG\n");
+ return ret;
+ }
- ret = max10_sys_read(max10, DT_BASE_ADDR_REG, &dt_addr);
- if (ret) {
- dev_info(max10 "cannot get base addr of device table\n");
- return ret;
- }
-
- ret = enable_nor_flash(max10, true);
- if (ret) {
- dev_err(max10 "fail to enable flash\n");
- return ret;
- }
+ if (!(val & DT_AVAIL)) {
+ dev_err(max10 "DT not available\n");
+ return -EINVAL;
+ }
- ret = altera_nor_flash_read(max10, dt_addr, &hdr, sizeof(hdr));
- if (ret) {
- dev_err(max10 "read fdt header fail\n");
- goto done;
- }
+ ret = max10_sys_read(max10, DT_BASE_ADDR_REG, &dt_addr);
+ if (ret) {
+ dev_info(max10 "cannot get base addr of device table\n");
+ return ret;
+ }
- ret = fdt_check_header(&hdr);
- if (ret) {
- dev_err(max10 "check fdt header fail\n");
- goto done;
- }
+ ret = enable_nor_flash(max10, true);
+ if (ret) {
+ dev_err(max10 "fail to enable flash\n");
+ return ret;
+ }
- dt_size = fdt_totalsize(&hdr);
- if (dt_size > DFT_MAX_SIZE) {
- dev_err(max10 "invalid device table size\n");
- ret = -EINVAL;
- goto done;
- }
+ ret = altera_nor_flash_read(max10, dt_addr, &hdr, sizeof(hdr));
+ if (ret) {
+ dev_err(max10 "read fdt header fail\n");
+ goto disable_nor_flash;
+ }
- fdt_root = opae_malloc(dt_size);
- if (!fdt_root) {
- ret = -ENOMEM;
- goto done;
- }
+ ret = fdt_check_header(&hdr);
+ if (ret) {
+ dev_err(max10 "check fdt header fail\n");
+ goto disable_nor_flash;
+ }
- ret = altera_nor_flash_read(max10, dt_addr, fdt_root, dt_size);
- if (ret) {
- dev_err(max10 "cannot read device table\n");
- goto done;
- }
+ dt_size = fdt_totalsize(&hdr);
+ if (dt_size > DFT_MAX_SIZE) {
+ dev_err(max10 "invalid device table size\n");
+ ret = -EINVAL;
+ goto disable_nor_flash;
+ }
- id = max10_match_compatible(fdt_root);
- if (!id) {
- dev_err(max10 "max10 compatible not found\n");
- ret = -ENODEV;
- goto done;
- }
+ fdt_root = opae_malloc(dt_size);
+ if (!fdt_root) {
+ ret = -ENOMEM;
+ goto disable_nor_flash;
+ }
- max10->flags |= MAX10_FLAGS_DEVICE_TABLE;
+ ret = altera_nor_flash_read(max10, dt_addr, fdt_root, dt_size);
+ if (ret) {
+ opae_free(fdt_root);
+ fdt_root = NULL;
+ dev_err(max10 "cannot read device table\n");
+ goto disable_nor_flash;
+ }
- max10->id = id;
- max10->fdt_root = fdt_root;
+ if (spi->dtb) {
+ if (*spi->dtb_sz_ptr < dt_size) {
+ dev_warn(max10,
+ "share memory for dtb is smaller than required %u\n",
+ dt_size);
+ } else {
+ *spi->dtb_sz_ptr = dt_size;
+ }
+ /* store dtb data into share memory */
+ memcpy(spi->dtb, fdt_root, *spi->dtb_sz_ptr);
+ }
-done:
- ret = enable_nor_flash(max10, false);
+disable_nor_flash:
+ enable_nor_flash(max10, false);
+ } else {
+ if (*spi->dtb_sz_ptr > 0) {
+ dev_info(max10, "read DTB from shared memory\n");
+ fdt_root = opae_malloc(*spi->dtb_sz_ptr);
+ if (fdt_root)
+ memcpy(fdt_root, spi->dtb, *spi->dtb_sz_ptr);
+ else
+ ret = -ENOMEM;
+ }
+ }
- if (ret && fdt_root)
- opae_free(fdt_root);
+ if (fdt_root) {
+ id = max10_match_compatible(fdt_root);
+ if (!id) {
+ dev_err(max10 "max10 compatible not found\n");
+ ret = -ENODEV;
+ } else {
+ max10->flags |= MAX10_FLAGS_DEVICE_TABLE;
+ max10->id = id;
+ max10->fdt_root = fdt_root;
+ }
+ }
return ret;
}
spi_dev->num_chipselect,
spi_dev->spi_param.clock_phase);
+ if (spi_dev->mutex)
+ pthread_mutex_lock(spi_dev->mutex);
/* clear */
spi_reg_write(spi_dev, ALTERA_SPI_CONTROL, 0);
spi_reg_write(spi_dev, ALTERA_SPI_STATUS, 0);
/* flush rxdata */
spi_flush_rx(spi_dev);
+ if (spi_dev->mutex)
+ pthread_mutex_unlock(spi_dev->mutex);
}
void altera_spi_release(struct altera_spi_device *dev)
int (*reg_read)(struct altera_spi_device *dev, u32 reg, u32 *val);
int (*reg_write)(struct altera_spi_device *dev, u32 reg,
u32 value);
+ /* below are data to be shared in multiple process */
+ pthread_mutex_t *mutex; /* to be passed to spi_transaction_dev */
+ unsigned int *dtb_sz_ptr; /* to be used in init_max10_device_table */
+ unsigned char *dtb; /* to be used in init_max10_device_table */
};
#define HEADER_LEN 8
int chipselect;
struct spi_tran_buffer *buffer;
pthread_mutex_t lock;
+ pthread_mutex_t *mutex; /* multi-process mutex from adapter */
};
struct spi_tran_header {
{
int ret;
- pthread_mutex_lock(&dev->lock);
+ pthread_mutex_lock(dev->mutex);
ret = do_transaction(dev, addr, size, data,
(size > SPI_REG_BYTES) ?
SPI_TRAN_SEQ_READ : SPI_TRAN_NON_SEQ_READ);
- pthread_mutex_unlock(&dev->lock);
+ pthread_mutex_unlock(dev->mutex);
return ret;
}
{
int ret;
- pthread_mutex_lock(&dev->lock);
+ pthread_mutex_lock(dev->mutex);
ret = do_transaction(dev, addr, size, data,
(size > SPI_REG_BYTES) ?
SPI_TRAN_SEQ_WRITE : SPI_TRAN_NON_SEQ_WRITE);
- pthread_mutex_unlock(&dev->lock);
+ pthread_mutex_unlock(dev->mutex);
return ret;
}
dev_err(spi_tran_dev, "fail to init mutex lock\n");
goto err;
}
+ if (dev->mutex) {
+ dev_info(NULL, "use multi-process mutex in spi\n");
+ spi_tran_dev->mutex = dev->mutex;
+ } else {
+ dev_info(NULL, "use multi-thread mutex in spi\n");
+ spi_tran_dev->mutex = &spi_tran_dev->lock;
+ }
return spi_tran_dev;