Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc
Pull powerpc merge from Benjamin Herrenschmidt: "Here's the powerpc batch for this merge window. It is going to be a bit more nasty than usual as in touching things outside of arch/powerpc mostly due to the big iSeriesectomy :-) We finally got rid of the bugger (legacy iSeries support) which was a PITA to maintain and that nobody really used anymore. Here are some of the highlights: - Legacy iSeries is gone. Thanks Stephen ! There's still some bits and pieces remaining if you do a grep -ir series arch/powerpc but they are harmless and will be removed in the next few weeks hopefully. - The 'fadump' functionality (Firmware Assisted Dump) replaces the previous (equivalent) "pHyp assisted dump"... it's a rewrite of a mechanism to get the hypervisor to do crash dumps on pSeries, the new implementation hopefully being much more reliable. Thanks Mahesh Salgaonkar. - The "EEH" code (pSeries PCI error handling & recovery) got a big spring cleaning, motivated by the need to be able to implement a new backend for it on top of some new different type of firwmare. The work isn't complete yet, but a good chunk of the cleanups is there. Note that this adds a field to struct device_node which is not very nice and which Grant objects to. I will have a patch soon that moves that to a powerpc private data structure (hopefully before rc1) and we'll improve things further later on (hopefully getting rid of the need for that pointer completely). Thanks Gavin Shan. - I dug into our exception & interrupt handling code to improve the way we do lazy interrupt handling (and make it work properly with "edge" triggered interrupt sources), and while at it found & fixed a wagon of issues in those areas, including adding support for page fault retry & fatal signals on page faults. - Your usual random batch of small fixes & updates, including a bunch of new embedded boards, both Freescale and APM based ones, etc..." I fixed up some conflicts with the generalized irq-domain changes from Grant Likely, hopefully correctly. * 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc: (141 commits) powerpc/ps3: Do not adjust the wrapper load address powerpc: Remove the rest of the legacy iSeries include files powerpc: Remove the remaining CONFIG_PPC_ISERIES pieces init: Remove CONFIG_PPC_ISERIES powerpc: Remove FW_FEATURE ISERIES from arch code tty/hvc_vio: FW_FEATURE_ISERIES is no longer selectable powerpc/spufs: Fix double unlocks powerpc/5200: convert mpc5200 to use of_platform_populate() powerpc/mpc5200: add options to mpc5200_defconfig powerpc/mpc52xx: add a4m072 board support powerpc/mpc5200: update mpc5200_defconfig to fit for charon board Documentation/powerpc/mpc52xx.txt: Checkpatch cleanup powerpc/44x: Add additional device support for APM821xx SoC and Bluestone board powerpc/44x: Add support PCI-E for APM821xx SoC and Bluestone board MAINTAINERS: Update PowerPC 4xx tree powerpc/44x: The bug fixed support for APM821xx SoC and Bluestone board powerpc: document the FSL MPIC message register binding powerpc: add support for MPIC message register API powerpc/fsl: Added aliased MSIIR register address to MSI node in dts powerpc/85xx: mpc8548cds - add 36-bit dts ...
This commit is contained in:
@@ -560,6 +560,9 @@ static void data_enable_interrupts(struct fpga_device *priv)
|
||||
|
||||
/* flush the writes */
|
||||
fpga_read_reg(priv, 0, MMAP_REG_STATUS);
|
||||
fpga_read_reg(priv, 1, MMAP_REG_STATUS);
|
||||
fpga_read_reg(priv, 2, MMAP_REG_STATUS);
|
||||
fpga_read_reg(priv, 3, MMAP_REG_STATUS);
|
||||
|
||||
/* switch back to the external interrupt source */
|
||||
iowrite32be(0x3F, priv->regs + SYS_IRQ_SOURCE_CTL);
|
||||
@@ -591,8 +594,12 @@ static void data_dma_cb(void *data)
|
||||
list_move_tail(&priv->inflight->entry, &priv->used);
|
||||
priv->inflight = NULL;
|
||||
|
||||
/* clear the FPGA status and re-enable interrupts */
|
||||
data_enable_interrupts(priv);
|
||||
/*
|
||||
* If data dumping is still enabled, then clear the FPGA
|
||||
* status registers and re-enable FPGA interrupts
|
||||
*/
|
||||
if (priv->enabled)
|
||||
data_enable_interrupts(priv);
|
||||
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
|
||||
@@ -708,6 +715,15 @@ static irqreturn_t data_irq(int irq, void *dev_id)
|
||||
|
||||
spin_lock(&priv->lock);
|
||||
|
||||
/*
|
||||
* This is an error case that should never happen.
|
||||
*
|
||||
* If this driver has a bug and manages to re-enable interrupts while
|
||||
* a DMA is in progress, then we will hit this statement and should
|
||||
* start paying attention immediately.
|
||||
*/
|
||||
BUG_ON(priv->inflight != NULL);
|
||||
|
||||
/* hide the interrupt by switching the IRQ driver to GPIO */
|
||||
data_disable_interrupts(priv);
|
||||
|
||||
@@ -762,11 +778,15 @@ out:
|
||||
*/
|
||||
static int data_device_enable(struct fpga_device *priv)
|
||||
{
|
||||
bool enabled;
|
||||
u32 val;
|
||||
int ret;
|
||||
|
||||
/* multiple enables are safe: they do nothing */
|
||||
if (priv->enabled)
|
||||
spin_lock_irq(&priv->lock);
|
||||
enabled = priv->enabled;
|
||||
spin_unlock_irq(&priv->lock);
|
||||
if (enabled)
|
||||
return 0;
|
||||
|
||||
/* check that the FPGAs are programmed */
|
||||
@@ -797,6 +817,9 @@ static int data_device_enable(struct fpga_device *priv)
|
||||
goto out_error;
|
||||
}
|
||||
|
||||
/* prevent the FPGAs from generating interrupts */
|
||||
data_disable_interrupts(priv);
|
||||
|
||||
/* hookup the irq handler */
|
||||
ret = request_irq(priv->irq, data_irq, IRQF_SHARED, drv_name, priv);
|
||||
if (ret) {
|
||||
@@ -804,11 +827,13 @@ static int data_device_enable(struct fpga_device *priv)
|
||||
goto out_error;
|
||||
}
|
||||
|
||||
/* switch to the external FPGA IRQ line */
|
||||
data_enable_interrupts(priv);
|
||||
|
||||
/* success, we're enabled */
|
||||
/* allow the DMA callback to re-enable FPGA interrupts */
|
||||
spin_lock_irq(&priv->lock);
|
||||
priv->enabled = true;
|
||||
spin_unlock_irq(&priv->lock);
|
||||
|
||||
/* allow the FPGAs to generate interrupts */
|
||||
data_enable_interrupts(priv);
|
||||
return 0;
|
||||
|
||||
out_error:
|
||||
@@ -834,41 +859,40 @@ out_error:
|
||||
*/
|
||||
static int data_device_disable(struct fpga_device *priv)
|
||||
{
|
||||
int ret;
|
||||
spin_lock_irq(&priv->lock);
|
||||
|
||||
/* allow multiple disable */
|
||||
if (!priv->enabled)
|
||||
if (!priv->enabled) {
|
||||
spin_unlock_irq(&priv->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* switch to the internal GPIO IRQ line */
|
||||
/*
|
||||
* Mark the device disabled
|
||||
*
|
||||
* This stops DMA callbacks from re-enabling interrupts
|
||||
*/
|
||||
priv->enabled = false;
|
||||
|
||||
/* prevent the FPGAs from generating interrupts */
|
||||
data_disable_interrupts(priv);
|
||||
|
||||
/* wait until all ongoing DMA has finished */
|
||||
while (priv->inflight != NULL) {
|
||||
spin_unlock_irq(&priv->lock);
|
||||
wait_event(priv->wait, priv->inflight == NULL);
|
||||
spin_lock_irq(&priv->lock);
|
||||
}
|
||||
|
||||
spin_unlock_irq(&priv->lock);
|
||||
|
||||
/* unhook the irq handler */
|
||||
free_irq(priv->irq, priv);
|
||||
|
||||
/*
|
||||
* wait for all outstanding DMA to complete
|
||||
*
|
||||
* Device interrupts are disabled, therefore another buffer cannot
|
||||
* be marked inflight.
|
||||
*/
|
||||
ret = wait_event_interruptible(priv->wait, priv->inflight == NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* free the correlation table */
|
||||
sg_free_table(&priv->corl_table);
|
||||
priv->corl_nents = 0;
|
||||
|
||||
/*
|
||||
* We are taking the spinlock not to protect priv->enabled, but instead
|
||||
* to make sure that there are no readers in the process of altering
|
||||
* the free or used lists while we are setting this flag.
|
||||
*/
|
||||
spin_lock_irq(&priv->lock);
|
||||
priv->enabled = false;
|
||||
spin_unlock_irq(&priv->lock);
|
||||
|
||||
/* free all buffers: the free and used lists are not being changed */
|
||||
data_free_buffers(priv);
|
||||
return 0;
|
||||
@@ -896,15 +920,6 @@ static unsigned int list_num_entries(struct list_head *list)
|
||||
static int data_debug_show(struct seq_file *f, void *offset)
|
||||
{
|
||||
struct fpga_device *priv = f->private;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Lock the mutex first, so that we get an accurate value for enable
|
||||
* Lock the spinlock next, to get accurate list counts
|
||||
*/
|
||||
ret = mutex_lock_interruptible(&priv->mutex);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
spin_lock_irq(&priv->lock);
|
||||
|
||||
@@ -917,7 +932,6 @@ static int data_debug_show(struct seq_file *f, void *offset)
|
||||
seq_printf(f, "num_dropped: %d\n", priv->num_dropped);
|
||||
|
||||
spin_unlock_irq(&priv->lock);
|
||||
mutex_unlock(&priv->mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -970,7 +984,13 @@ static ssize_t data_en_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct fpga_device *priv = dev_get_drvdata(dev);
|
||||
return snprintf(buf, PAGE_SIZE, "%u\n", priv->enabled);
|
||||
int ret;
|
||||
|
||||
spin_lock_irq(&priv->lock);
|
||||
ret = snprintf(buf, PAGE_SIZE, "%u\n", priv->enabled);
|
||||
spin_unlock_irq(&priv->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t data_en_set(struct device *dev, struct device_attribute *attr,
|
||||
@@ -986,6 +1006,7 @@ static ssize_t data_en_set(struct device *dev, struct device_attribute *attr,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* protect against concurrent enable/disable */
|
||||
ret = mutex_lock_interruptible(&priv->mutex);
|
||||
if (ret)
|
||||
return ret;
|
||||
@@ -1079,6 +1100,7 @@ static ssize_t data_read(struct file *filp, char __user *ubuf, size_t count,
|
||||
struct fpga_reader *reader = filp->private_data;
|
||||
struct fpga_device *priv = reader->priv;
|
||||
struct list_head *used = &priv->used;
|
||||
bool drop_buffer = false;
|
||||
struct data_buf *dbuf;
|
||||
size_t avail;
|
||||
void *data;
|
||||
@@ -1166,10 +1188,12 @@ have_buffer:
|
||||
* One of two things has happened, the device is disabled, or the
|
||||
* device has been reconfigured underneath us. In either case, we
|
||||
* should just throw away the buffer.
|
||||
*
|
||||
* Lockdep complains if this is done under the spinlock, so we
|
||||
* handle it during the unlock path.
|
||||
*/
|
||||
if (!priv->enabled || dbuf->size != priv->bufsize) {
|
||||
videobuf_dma_unmap(priv->dev, &dbuf->vb);
|
||||
data_free_buffer(dbuf);
|
||||
drop_buffer = true;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
@@ -1178,6 +1202,12 @@ have_buffer:
|
||||
|
||||
out_unlock:
|
||||
spin_unlock_irq(&priv->lock);
|
||||
|
||||
if (drop_buffer) {
|
||||
videobuf_dma_unmap(priv->dev, &dbuf->vb);
|
||||
data_free_buffer(dbuf);
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user