table: fix out of bounds write
[dpdk.git] / drivers / raw / ifpga / base / opae_hw_api.c
index d0e66d6..11c9887 100644 (file)
@@ -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,246 @@ 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;
+       sd->rsu_ctrl = 0;
+       sd->rsu_stat = 0;
+}
+
+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 +568,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;
 }
 
@@ -357,8 +607,12 @@ int opae_adapter_enumerate(struct opae_adapter *adapter)
  */
 void opae_adapter_destroy(struct opae_adapter *adapter)
 {
-       if (adapter && adapter->ops && adapter->ops->destroy)
-               adapter->ops->destroy(adapter);
+       if (adapter) {
+               if (adapter->ops && adapter->ops->destroy)
+                       adapter->ops->destroy(adapter);
+               opae_adapter_shm_free(adapter);
+               opae_adapter_mutex_close(adapter);
+       }
 }
 
 /**
@@ -583,11 +837,12 @@ int opae_manager_get_retimer_status(struct opae_manager *mgr,
  * Return: the pointer of the opae_sensor_info
  */
 struct opae_sensor_info *
-opae_mgr_get_sensor_by_id(unsigned int id)
+opae_mgr_get_sensor_by_id(struct opae_manager *mgr,
+               unsigned int id)
 {
        struct opae_sensor_info *sensor;
 
-       opae_mgr_for_each_sensor(sensor)
+       opae_mgr_for_each_sensor(mgr, sensor)
                if (sensor->id == id)
                        return sensor;
 
@@ -601,11 +856,12 @@ opae_mgr_get_sensor_by_id(unsigned int id)
  * Return: the pointer of the opae_sensor_info
  */
 struct opae_sensor_info *
-opae_mgr_get_sensor_by_name(const char *name)
+opae_mgr_get_sensor_by_name(struct opae_manager *mgr,
+               const char *name)
 {
        struct opae_sensor_info *sensor;
 
-       opae_mgr_for_each_sensor(sensor)
+       opae_mgr_for_each_sensor(mgr, sensor)
                if (!strcmp(sensor->name, name))
                        return sensor;
 
@@ -630,7 +886,7 @@ opae_mgr_get_sensor_value_by_name(struct opae_manager *mgr,
        if (!mgr)
                return -EINVAL;
 
-       sensor = opae_mgr_get_sensor_by_name(name);
+       sensor = opae_mgr_get_sensor_by_name(mgr, name);
        if (!sensor)
                return -ENODEV;
 
@@ -658,7 +914,7 @@ opae_mgr_get_sensor_value_by_id(struct opae_manager *mgr,
        if (!mgr)
                return -EINVAL;
 
-       sensor = opae_mgr_get_sensor_by_id(id);
+       sensor = opae_mgr_get_sensor_by_id(mgr, id);
        if (!sensor)
                return -ENODEV;
 
@@ -690,3 +946,98 @@ opae_mgr_get_sensor_value(struct opae_manager *mgr,
 
        return -ENOENT;
 }
+
+/**
+ * opae_manager_get_board_info - get board info
+ * sensor value
+ * @info: opae_board_info for the card
+ *
+ * Return: 0 on success, otherwise error code
+ */
+int
+opae_mgr_get_board_info(struct opae_manager *mgr,
+               struct opae_board_info **info)
+{
+       if (!mgr || !info)
+               return -EINVAL;
+
+       if (mgr->ops && mgr->ops->get_board_info)
+               return mgr->ops->get_board_info(mgr, info);
+
+       return -ENOENT;
+}
+
+/**
+ * opae_mgr_get_uuid -  get manager's UUID.
+ * @mgr: targeted manager
+ * @uuid: a pointer to UUID
+ *
+ * Return: 0 on success, otherwise error code.
+ */
+int opae_mgr_get_uuid(struct opae_manager *mgr, struct uuid *uuid)
+{
+       if (!mgr || !uuid)
+               return -EINVAL;
+
+       if (mgr->ops && mgr->ops->get_uuid)
+               return mgr->ops->get_uuid(mgr, uuid);
+
+       return -ENOENT;
+}
+
+/**
+ * opae_mgr_update_flash -  update image in flash.
+ * @mgr: targeted manager
+ * @image: name of image file
+ * @status: status of update
+ *
+ * Return: 0 on success, otherwise error code.
+ */
+int opae_mgr_update_flash(struct opae_manager *mgr, const char *image,
+       uint64_t *status)
+{
+       if (!mgr)
+               return -EINVAL;
+
+       if (mgr->ops && mgr->ops->update_flash)
+               return mgr->ops->update_flash(mgr, image, status);
+
+       return -ENOENT;
+}
+
+/**
+ * opae_stop_flash_update -  stop flash update.
+ * @mgr: targeted manager
+ * @force: make sure the update process is stopped
+ *
+ * Return: 0 on success, otherwise error code.
+ */
+int opae_mgr_stop_flash_update(struct opae_manager *mgr, int force)
+{
+       if (!mgr)
+               return -EINVAL;
+
+       if (mgr->ops && mgr->ops->stop_flash_update)
+               return mgr->ops->stop_flash_update(mgr, force);
+
+       return -ENOENT;
+}
+
+/**
+ * opae_mgr_reload -  reload FPGA.
+ * @mgr: targeted manager
+ * @type: FPGA type
+ * @page: reload from which page
+ *
+ * Return: 0 on success, otherwise error code.
+ */
+int opae_mgr_reload(struct opae_manager *mgr, int type, int page)
+{
+       if (!mgr)
+               return -EINVAL;
+
+       if (mgr->ops && mgr->ops->reload)
+               return mgr->ops->reload(mgr, type, page);
+
+       return -ENOENT;
+}