[dpdk-dev] [PATCH v2 4/4] raw/ifpga/base: enhance driver reliability in multi-process

Xu, Rosen rosen.xu at intel.com
Thu Oct 15 08:08:29 CEST 2020


Hi,

> -----Original Message-----
> From: Zhang, Tianfei <tianfei.zhang at intel.com>
> Sent: Monday, September 28, 2020 9:40
> To: dev at dpdk.org; Xu, Rosen <rosen.xu at intel.com>; Huang, Wei
> <wei.huang at intel.com>
> Cc: Zhang, Tianfei <tianfei.zhang at intel.com>
> Subject: [PATCH v2 4/4] raw/ifpga/base: enhance driver reliability in multi-
> process
> 
> From: Wei Huang <wei.huang at intel.com>
> 
> Current hardware protection is based on pthread mutex which work just for
> situation of multi-thread in one process. In multi-process environment,
> hardware state machine would be corrupted by concurrent access, that
> means original pthread mutex mechanism need be enhanced.
> 
> The major modifications in this patch are list below:
> 1. Create a mutex for adapter in shared memory named
> "mutex.IFPGA:domain:bus:dev.func" when device is probed.
> 2. Create a shared memory named "IFPGA:domain:bus:dev.func"
> during opae adapter is initializing. There is a reference count in shared
> memory. Shared memory will be destroyed once reference count turned to
> zero.
> 3. Two mutexs are created in shared memory and initialized with flag
> PTHREAD_PROCESS_SHARED. One for SPI and the other for I2C. They will be
> passed to SPI and I2C driver subsequently.
> 4. DTB data in flash will be cached in shared memory. Then
> MAX10 driver can read DTB from shared memory instead of flash. This avoid
> confliction of concurrent flash access between hardware and software.
> 
> Signed-off-by: Wei Huang <wei.huang at intel.com>
> Signed-off-by: Tianfei zhang <tianfei.zhang at intel.com>
> ---
> v2: fix typo in commit log. 'master' is not misspelled, it's used in original code.
> There will be a separate patch to clean up the language.
> ---
>  drivers/raw/ifpga/base/ifpga_fme.c            |  52 +++-
>  drivers/raw/ifpga/base/meson.build            |  12 +
>  drivers/raw/ifpga/base/opae_hw_api.c          | 250 ++++++++++++++++++
>  drivers/raw/ifpga/base/opae_hw_api.h          |  27 +-
>  drivers/raw/ifpga/base/opae_i2c.c             |   9 +-
>  drivers/raw/ifpga/base/opae_i2c.h             |   1 +
>  drivers/raw/ifpga/base/opae_intel_max10.c     | 152 ++++++-----
>  drivers/raw/ifpga/base/opae_spi.c             |   4 +
>  drivers/raw/ifpga/base/opae_spi.h             |   5 +
>  drivers/raw/ifpga/base/opae_spi_transaction.c |  15 +-
>  10 files changed, 456 insertions(+), 71 deletions(-)
> 
> diff --git a/drivers/raw/ifpga/base/ifpga_fme.c
> b/drivers/raw/ifpga/base/ifpga_fme.c
> index 9057087b5..540bb1110 100644
> --- a/drivers/raw/ifpga/base/ifpga_fme.c
> +++ b/drivers/raw/ifpga/base/ifpga_fme.c
> @@ -919,6 +919,25 @@ static int spi_self_checking(struct
> intel_max10_device *dev)
>  	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;
> @@ -935,6 +954,7 @@ static int fme_spi_init(struct ifpga_feature *feature)
>  	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);
> 
> @@ -945,7 +965,6 @@ static int fme_spi_init(struct ifpga_feature *feature)
>  		goto spi_fail;
>  	}
> 
> -
>  	fme->max10_dev = max10;
> 
>  	/* SPI self test */
> @@ -1084,11 +1103,15 @@ static int fme_nios_spi_init(struct ifpga_feature
> *feature)
>  	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"); @@ -1101,6
> +1124,9 @@ static int fme_nios_spi_init(struct ifpga_feature *feature)
>  	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);
> 
> @@ -1112,11 +1138,12 @@ static int fme_nios_spi_init(struct ifpga_feature
> *feature)
>  		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 */
> @@ -1178,6 +1205,25 @@ static int i2c_mac_rom_test(struct altera_i2c_dev
> *dev)
>  	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;
> @@ -1191,6 +1237,8 @@ static int fme_i2c_init(struct ifpga_feature *feature)
>  	if (!fme->i2c_master)
>  		return -ENODEV;
> 
> +	init_i2c_mutex(fme);
> +
>  	/* MAC ROM self test */
>  	i2c_mac_rom_test(fme->i2c_master);
> 
> diff --git a/drivers/raw/ifpga/base/meson.build
> b/drivers/raw/ifpga/base/meson.build
> index b13e13e89..da2d6e33c 100644
> --- a/drivers/raw/ifpga/base/meson.build
> +++ b/drivers/raw/ifpga/base/meson.build
> @@ -23,6 +23,18 @@ sources = [
>  	'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)
> diff --git a/drivers/raw/ifpga/base/opae_hw_api.c
> b/drivers/raw/ifpga/base/opae_hw_api.c
> index c969dfed3..600afdea1 100644
> --- a/drivers/raw/ifpga/base/opae_hw_api.c
> +++ b/drivers/raw/ifpga/base/opae_hw_api.c
> @@ -2,6 +2,10 @@
>   * 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"
> @@ -305,6 +309,244 @@ static struct opae_adapter_ops *match_ops(struct
> opae_adapter *adapter)
>  	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 @@ -324,6 +566,12
> @@ int opae_adapter_init(struct opae_adapter *adapter,
>  	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;
>  }
> 
> @@ -359,6 +607,8 @@ void opae_adapter_destroy(struct opae_adapter
> *adapter)  {
>  	if (adapter && adapter->ops && adapter->ops->destroy)
>  		adapter->ops->destroy(adapter);
> +	opae_adapter_shm_free(adapter);
> +	opae_adapter_mutex_close(adapter);
>  }
> 
>  /**
> diff --git a/drivers/raw/ifpga/base/opae_hw_api.h
> b/drivers/raw/ifpga/base/opae_hw_api.h
> index cf8ff93a6..e99ee4564 100644
> --- a/drivers/raw/ifpga/base/opae_hw_api.h
> +++ b/drivers/raw/ifpga/base/opae_hw_api.h
> @@ -265,12 +265,36 @@ TAILQ_HEAD(opae_accelerator_list,
> opae_accelerator);  #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 */
> @@ -280,7 +304,8 @@ void *opae_adapter_data_alloc(enum
> opae_adapter_type type);  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 * diff --git a/drivers/raw/ifpga/base/opae_i2c.c
> b/drivers/raw/ifpga/base/opae_i2c.c
> index 846d751f5..598eab574 100644
> --- a/drivers/raw/ifpga/base/opae_i2c.c
> +++ b/drivers/raw/ifpga/base/opae_i2c.c
> @@ -30,7 +30,7 @@ int i2c_read(struct altera_i2c_dev *dev, int flags,
> unsigned int slave_addr,
>  	int i = 0;
>  	int ret;
> 
> -	pthread_mutex_lock(&dev->lock);
> +	pthread_mutex_lock(dev->mutex);
> 
>  	if (flags & I2C_FLAG_ADDR16)
>  		msgbuf[i++] = offset >> 8;
> @@ -60,7 +60,7 @@ int i2c_read(struct altera_i2c_dev *dev, int flags,
> unsigned int slave_addr,
>  	ret = i2c_transfer(dev, msg, 2);
> 
>  exit:
> -	pthread_mutex_unlock(&dev->lock);
> +	pthread_mutex_unlock(dev->mutex);
>  	return ret;
>  }
> 
> @@ -72,7 +72,7 @@ int i2c_write(struct altera_i2c_dev *dev, int flags,
> unsigned int slave_addr,
>  	int ret;
>  	int i = 0;
> 
> -	pthread_mutex_lock(&dev->lock);
> +	pthread_mutex_lock(dev->mutex);
> 
>  	if (!dev->xfer) {
>  		ret = -ENODEV;
> @@ -100,7 +100,7 @@ int i2c_write(struct altera_i2c_dev *dev, int flags,
> unsigned int slave_addr,
> 
>  	opae_free(buf);
>  exit:
> -	pthread_mutex_unlock(&dev->lock);
> +	pthread_mutex_unlock(dev->mutex);
>  	return ret;
>  }
> 
> @@ -496,6 +496,7 @@ struct altera_i2c_dev *altera_i2c_probe(void *base)
> 
>  	if (pthread_mutex_init(&dev->lock, NULL))
>  		return NULL;
> +	dev->mutex = &dev->lock;
> 
>  	altera_i2c_hardware_init(dev);
> 
> diff --git a/drivers/raw/ifpga/base/opae_i2c.h
> b/drivers/raw/ifpga/base/opae_i2c.h
> index 266e127b7..4f6b0b28b 100644
> --- a/drivers/raw/ifpga/base/opae_i2c.h
> +++ b/drivers/raw/ifpga/base/opae_i2c.h
> @@ -94,6 +94,7 @@ struct altera_i2c_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 */
>  };
> 
>  /**
> diff --git a/drivers/raw/ifpga/base/opae_intel_max10.c
> b/drivers/raw/ifpga/base/opae_intel_max10.c
> index 8e23ca18a..1a526ea54 100644
> --- a/drivers/raw/ifpga/base/opae_intel_max10.c
> +++ b/drivers/raw/ifpga/base/opae_intel_max10.c
> @@ -138,84 +138,116 @@ static int enable_nor_flash(struct
> intel_max10_device *dev, bool on)
> 
>  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;
>  }
> diff --git a/drivers/raw/ifpga/base/opae_spi.c
> b/drivers/raw/ifpga/base/opae_spi.c
> index bfdc83e6c..9efeecb79 100644
> --- a/drivers/raw/ifpga/base/opae_spi.c
> +++ b/drivers/raw/ifpga/base/opae_spi.c
> @@ -285,11 +285,15 @@ void altera_spi_init(struct altera_spi_device
> *spi_dev)
>  			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) diff --git
> a/drivers/raw/ifpga/base/opae_spi.h b/drivers/raw/ifpga/base/opae_spi.h
> index 73a227673..af11656e4 100644
> --- a/drivers/raw/ifpga/base/opae_spi.h
> +++ b/drivers/raw/ifpga/base/opae_spi.h
> @@ -77,6 +77,10 @@ struct altera_spi_device {
>  	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
> @@ -103,6 +107,7 @@ struct spi_transaction_dev {
>  	int chipselect;
>  	struct spi_tran_buffer *buffer;
>  	pthread_mutex_t lock;
> +	pthread_mutex_t *mutex;  /* multi-process mutex from adapter */
>  };
> 
>  struct spi_tran_header {
> diff --git a/drivers/raw/ifpga/base/opae_spi_transaction.c
> b/drivers/raw/ifpga/base/opae_spi_transaction.c
> index d13d2fbc8..006cdb4c1 100644
> --- a/drivers/raw/ifpga/base/opae_spi_transaction.c
> +++ b/drivers/raw/ifpga/base/opae_spi_transaction.c
> @@ -434,11 +434,11 @@ int spi_transaction_read(struct
> spi_transaction_dev *dev, unsigned int addr,  {
>  	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;
>  }
> @@ -448,11 +448,11 @@ int spi_transaction_write(struct
> spi_transaction_dev *dev, unsigned int addr,  {
>  	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;
>  }
> @@ -479,6 +479,13 @@ struct spi_transaction_dev
> *spi_transaction_init(struct altera_spi_device *dev,
>  		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;
> 
> --
> 2.17.1

Acked-by: Rosen Xu <rosen.xu at intel.com>


More information about the dev mailing list