Commit bcbefabe authored by Federico Vaga's avatar Federico Vaga

drv: do not reload FPGA devices - VME Slave invalid

When we re-program the FPGA we are overwriting the very same VME Slave
that we are using to access the card. This makes the device driver
instance instable. For this reason the driver from now on will auto
remove the device instance after an FPGA configuration.
Signed-off-by: Federico Vaga's avatarFederico Vaga <federico.vaga@cern.ch>
parent 22541c1e
......@@ -869,6 +869,8 @@ int svec_fpga_exit(struct svec_dev *svec_dev)
if (!svec_fpga)
return 0;
/* this function must run before re-flashing */
BUG_ON(svec_dev->flags & SVEC_DEV_FLAGS_REPROGRAMMED);
svec_fpga_app_exit(svec_fpga);
svec_fmc_exit(svec_fpga);
svec_fpga_devices_exit(svec_fpga);
......
......@@ -64,19 +64,16 @@ static int svec_fw_load(struct svec_dev *svec_dev, const char *name)
mutex_lock(&svec_dev->mtx);
err = compat_svec_fw_load(svec_dev, name);
if (err)
goto out;
err = svec_fpga_init(svec_dev, SVEC_FUNC_NR);
if (err)
dev_warn(&svec_dev->vdev->dev,
"FPGA incorrectly programmed %d\n", err);
out:
mutex_unlock(&svec_dev->mtx);
return err;
}
static void remove_callback(struct device *dev)
{
vme_unregister_device(to_vme_dev(dev));
}
#define VBRIDGE_DBG_FW_BUF_LEN 128
static ssize_t svec_dbg_fw_write(struct file *file,
const char __user *buf,
......@@ -84,7 +81,7 @@ static ssize_t svec_dbg_fw_write(struct file *file,
{
struct svec_dev *svec_dev = file->private_data;
char buf_l[VBRIDGE_DBG_FW_BUF_LEN];
int err;
int err, ret;
if (VBRIDGE_DBG_FW_BUF_LEN < count) {
dev_err(&svec_dev->vdev->dev,
......@@ -98,7 +95,28 @@ static ssize_t svec_dbg_fw_write(struct file *file,
if (err)
return -EFAULT;
spin_lock(&svec_dev->lock);
svec_dev->flags |= SVEC_DEV_FLAGS_REPROGRAMMED;
spin_unlock(&svec_dev->lock);
err = svec_fw_load(svec_dev, buf_l);
if (err)
dev_err(&svec_dev->vdev->dev,
"FPGA Configuration failure %d\n", err);
/*
* Reprogramming the FPGA means replacing the VME slave. In other words
* the SVEC device that we used to re-flash the FPGA disappeard and so
* this driver instance must disapear as well.
*/
dev_warn(&svec_dev->vdev->dev, "VME Slave removed\n");
dev_warn(&svec_dev->vdev->dev, "Remove this device driver instance\n");
ret = device_schedule_callback(&svec_dev->vdev->dev, remove_callback);
if (ret) {
dev_err(&svec_dev->vdev->dev,
"Can't remove device driver instance %d\n", ret);
return ret;
}
return err ? err : count;
}
......@@ -516,6 +534,7 @@ static int svec_probe(struct device *dev, unsigned int ndev)
goto err;
}
spin_lock_init(&svec->lock);
mutex_init(&svec->mtx);
svec->vdev = vdev;
dev_set_drvdata(dev, svec);
......@@ -568,7 +587,13 @@ static int svec_remove(struct device *dev, unsigned int ndev)
fpga_mgr_free(svec->mgr);
dev_set_drvdata(dev, NULL);
vme_disable_device(svec->vdev);
if ((svec->flags & SVEC_DEV_FLAGS_REPROGRAMMED) == 0) {
/*
* If FPGA is REPROGRAMMED then there is
* no device to disable
*/
vme_disable_device(svec->vdev);
}
kfree(svec);
return 0;
......
......@@ -9,6 +9,7 @@
#include <linux/debugfs.h>
#include <linux/platform_device.h>
#include <linux/fmc.h>
#include <linux/spinlock.h>
#include <vmebus.h>
#include "svec-core-fpga.h"
......@@ -105,6 +106,7 @@ static inline struct svec_fpga *to_svec_fpga(struct device *_dev)
}
#define SVEC_DEV_FLAGS_REPROGRAMMED BIT(0)
/**
* struct svec_dev - SVEC instance
* It describes a SVEC device instance.
......@@ -129,6 +131,7 @@ struct svec_dev {
unsigned long flags;
struct svec_meta_id meta;
struct mutex mtx;
spinlock_t lock;
struct fpga_manager *mgr;
uint32_t bitstream_last_word;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment