[RFC] pl08x: don't use dma_slave_config direction argument
Russell King - ARM Linux
linux at arm.linux.org.uk
Thu May 17 10:30:35 EDT 2012
Linus,
Is there any reason you can see not to do this?
I ultimately need to kill off the passing of struct pl08x_dma_chan to
these functions, because that's preventing me moving the struct into
drivers/dma - which I need to in order to convert amba-pl08x.c to use
virt-dma.c.
The only use of pl08x_dma_chan in the functions below is for the debug
prints, which I suggest we just kill off - or we could change them to
be cd->bus_id, which is the same thing anyway.
diff --git a/arch/arm/mach-realview/core.c b/arch/arm/mach-realview/core.c
index 45868bb..30efe77 100644
--- a/arch/arm/mach-realview/core.c
+++ b/arch/arm/mach-realview/core.c
...
+/* State of the big DMA mux */
+static u32 current_mux;
+static u32 mux_users;
+static DEFINE_SPINLOCK(current_mux_lock);
+
+static int pl081_get_signal(struct pl08x_dma_chan *ch, const struct pl08x_channel_data *cd)
+{
+ unsigned long flags;
+ u32 val;
+
+ spin_lock_irqsave(¤t_mux_lock, flags);
+ /*
+ * We're on the same mux so fine, go ahead!
+ */
+ if (cd->muxval == current_mux) {
+ mux_users ++;
+ spin_unlock_irqrestore(¤t_mux_lock, flags);
+ /* We still have to write it since it may be OFF by default */
+ val = readl(__io_address(REALVIEW_SYS_DMAPSR));
+ val &= 0xFFFFFFFCU;
+ val |= current_mux;
+ writel(val, __io_address(REALVIEW_SYS_DMAPSR));
+ return cd->min_signal;
+ }
+ /*
+ * If we're not on the same mux and there are already
+ * users on the other mux setting, tough luck, the client
+ * can come back and retry or give up and fall back to
+ * PIO mode.
+ */
+ if (mux_users) {
+ spin_unlock_irqrestore(¤t_mux_lock, flags);
+ return -EBUSY;
+ }
+
+ /* Switch mux setting */
+ current_mux = cd->muxval;
+
+ val = readl(__io_address(REALVIEW_SYS_DMAPSR));
+ val &= 0xFFFFFFFCU;
+ val |= cd->muxval;
+ writel(val, __io_address(REALVIEW_SYS_DMAPSR));
+
+ pr_info("%s: muxing in %s in bank %d writing value "
+ "%08x to register %08x\n",
+ __func__, ch->name, cd->muxval,
+ val, REALVIEW_SYS_DMAPSR);
+
+ spin_unlock_irqrestore(¤t_mux_lock, flags);
+
+ return cd->min_signal;
+}
+
+static void pl081_put_signal(struct pl08x_dma_chan *ch, int signal)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(¤t_mux_lock, flags);
+ mux_users--;
+ spin_unlock_irqrestore(¤t_mux_lock, flags);
+}
...
diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c
index 6bbd74e..5570894 100644
--- a/arch/arm/mach-versatile/core.c
+++ b/arch/arm/mach-versatile/core.c
...
+/* This is a lock for the above muxing array */
+static DEFINE_SPINLOCK(muxlock);
+
+static int pl080_get_signal(struct pl08x_dma_chan *ch, const struct pl08x_channel_data *cd)
+{
+ pr_debug("requesting DMA signal on channel %s\n", ch->name);
+
+ /*
+ * The AB926EJ-S is simple - only static assignments
+ * so the channel is already muxed in and ready to go.
+ */
+ if (machine_is_versatile_ab())
+ return cd->min_signal;
+
+ /* The PB926EJ-S is hairier */
+ if (machine_is_versatile_pb()) {
+ unsigned long flags;
+ int i;
+
+ if (cd->min_signal > ARRAY_SIZE(pl080_muxtab) ||
+ cd->max_signal > ARRAY_SIZE(pl080_muxtab) ||
+ (cd->max_signal < cd->min_signal)) {
+ pr_err("%s: illegal muxing constraints for %s\n",
+ __func__, ch->name);
+ return -EINVAL;
+ }
+ /* Try to find a signal to use */
+ spin_lock_irqsave(&muxlock, flags);
+ for (i = cd->min_signal; i <= cd->max_signal; i++) {
+ if (!pl080_muxtab[i].user) {
+ u32 val;
+
+ pl080_muxtab[i].user = ch;
+ /* If the channels need to be muxed in, mux them! */
+ if (pl080_muxtab[i].ctrlreg) {
+ val = readl(__io_address(pl080_muxtab[i].ctrlreg));
+ val &= 0xFFFFFF60U;
+ val |= 0x80; /* Turn on muxing */
+ val |= cd->muxval; /* Mux in the right peripheral */
+ writel(val, __io_address(pl080_muxtab[i].ctrlreg));
+ pr_debug("%s: muxing in %s at channel %d writing value "
+ "%08x to register %08x\n",
+ __func__, ch->name, i,
+ val, pl080_muxtab[i].ctrlreg);
+ }
+ spin_unlock_irqrestore(&muxlock, flags);
+ return pl080_muxtab[i].id;
+ }
+ }
+ spin_unlock_irqrestore(&muxlock, flags);
+ }
+
+ return -EBUSY;
+}
+
+static void pl080_put_signal(struct pl08x_dma_chan *ch, int signal)
+{
+ unsigned long flags;
+ int i;
+
+ pr_debug("releasing DMA signal on channel %s\n", ch->name);
+
+ spin_lock_irqsave(&muxlock, flags);
+ for (i = 0; i < ARRAY_SIZE(pl080_muxtab); i++) {
+ if (pl080_muxtab[i].id == signal) {
+ WARN_ON(pl080_muxtab[i].user != ch);
+ pl080_muxtab[i].user = NULL;
+
+ if (pl080_muxtab[i].ctrlreg) {
+ u32 val;
+
+ val = readl(__io_address(pl080_muxtab[i].ctrlreg));
+ val &= 0xFFFFFF60U; /* Disable, select no channel */
+ writel(val, __io_address(pl080_muxtab[i].ctrlreg));
+ pr_debug("%s: muxing out %s at channel %d writing value "
+ "%08x to register %08x\n",
+ __func__, ch->name, i,
+ val, pl080_muxtab[i].ctrlreg);
+ }
+ spin_unlock_irqrestore(&muxlock, flags);
+ return;
+ }
+ }
+ spin_unlock_irqrestore(&muxlock, flags);
+ pr_debug("%s: unable to release muxing on channel %s\n",
+ __func__, ch->name);
+}
...
diff --git a/drivers/dma/amba-pl08x.c b/drivers/dma/amba-pl08x.c
index e62dd87..afe4640 100644
--- a/drivers/dma/amba-pl08x.c
+++ b/drivers/dma/amba-pl08x.c
@@ -947,7 +947,7 @@ static int prep_phy_channel(struct pl08x_dma_chan *plchan,
* Can the platform allow us to use this channel?
*/
if (plchan->slave && pl08x->pd->get_signal) {
- ret = pl08x->pd->get_signal(plchan);
+ ret = pl08x->pd->get_signal(plchan, plchan->cd);
if (ret < 0) {
dev_dbg(&pl08x->adev->dev,
"unable to use physical channel %d for transfer on %s due to platform restrictions\n",
@@ -982,7 +982,7 @@ static void release_phy_channel(struct pl08x_dma_chan *plchan)
struct pl08x_driver_data *pl08x = plchan->host;
if ((plchan->phychan->signal >= 0) && pl08x->pd->put_signal) {
- pl08x->pd->put_signal(plchan);
+ pl08x->pd->put_signal(plchan, plchan->phychan->signal);
plchan->phychan->signal = -1;
}
pl08x_put_phy_channel(pl08x, plchan->phychan);
diff --git a/include/linux/amba/pl08x.h b/include/linux/amba/pl08x.h
index 9331b68..f7312f8 100644
--- a/include/linux/amba/pl08x.h
+++ b/include/linux/amba/pl08x.h
@@ -147,8 +147,8 @@ struct pl08x_platform_data {
const struct pl08x_channel_data *slave_channels;
unsigned int num_slave_channels;
struct pl08x_channel_data memcpy_channel;
- int (*get_signal)(struct pl08x_dma_chan *);
- void (*put_signal)(struct pl08x_dma_chan *);
+ int (*get_signal)(struct pl08x_dma_chan *, const struct pl08x_channel_data *);
+ void (*put_signal)(struct pl08x_dma_chan *, int);
u8 lli_buses;
u8 mem_buses;
};
More information about the linux-arm-kernel
mailing list