On Thu, Nov 13, 2014 at 2:13 PM, Arnd Bergmann <arnd@xxxxxxxx> wrote: > On Thursday 13 November 2014 12:58:08 Andrew Bresticker wrote: >> + >> +static bool mdc_filter_fn(struct dma_chan *chan, void *fn_param) >> +{ >> + struct mdc_filter_data *data = fn_param; >> + struct mdc_chan *mchan; >> + >> + if (chan->device->dev->driver == &mdc_dma_driver.driver) { >> + mchan = to_mdc_chan(chan); >> + if (!(data->mask & BIT(mchan->chan_nr))) >> + return false; >> + mchan->periph = data->periph; >> + mchan->thread = data->thread; >> + return true; >> + } >> + return false; >> +} >> + >> +static struct dma_chan *mdc_of_xlate(struct of_phandle_args *dma_spec, >> + struct of_dma *ofdma) >> +{ >> + struct mdc_dma *mdma = ofdma->of_dma_data; >> + struct mdc_filter_data data; >> + >> + if (dma_spec->args_count != 3) >> + return NULL; >> + >> + data.periph = dma_spec->args[0]; >> + data.mask = dma_spec->args[1]; >> + data.thread = dma_spec->args[2]; >> + >> + return dma_request_channel(mdma->dma_dev.cap_mask, mdc_filter_fn, >> + &data); >> +} > > The filter function is broken if you ever have multiple instances > of the device. Better avoid calling dma_request_channel and scan > the channels that the device knows about. It seems unlikely that there would be multiple instances of this IP in a system, but it doesn't hurt to be safe. Perhaps instead of iterating through the list here I could extend struct mdc_filter_data to include a pointer to the struct dma_device corresponding to this instance of the MDC and compare based on that. >> + >> +#define PISTACHIO_CR_PERIPH_DMA_ROUTE(ch) (0x120 + 0x4 * ((ch) / 4)) >> +#define PISTACHIO_CR_PERIPH_DMA_ROUTE_SHIFT(ch) (8 * ((ch) % 4)) >> +#define PISTACHIO_CR_PERIPH_DMA_ROUTE_MASK 0x3f >> + >> +static void pistachio_mdc_enable_chan(struct mdc_chan *mchan) >> +{ >> + struct mdc_dma *mdma = mchan->mdma; >> + unsigned long flags; >> + >> + spin_lock_irqsave(&mdma->lock, flags); >> + regmap_update_bits(mdma->periph_regs, >> + PISTACHIO_CR_PERIPH_DMA_ROUTE(mchan->chan_nr), >> + PISTACHIO_CR_PERIPH_DMA_ROUTE_MASK << >> + PISTACHIO_CR_PERIPH_DMA_ROUTE_SHIFT(mchan->chan_nr), >> + mchan->periph << >> + PISTACHIO_CR_PERIPH_DMA_ROUTE_SHIFT(mchan->chan_nr)); >> + spin_unlock_irqrestore(&mdma->lock, flags); >> +} >> + >> +static void pistachio_mdc_disable_chan(struct mdc_chan *mchan) >> +{ >> + struct mdc_dma *mdma = mchan->mdma; >> + unsigned long flags; >> + >> + spin_lock_irqsave(&mdma->lock, flags); >> + regmap_update_bits(mdma->periph_regs, >> + PISTACHIO_CR_PERIPH_DMA_ROUTE(mchan->chan_nr), >> + PISTACHIO_CR_PERIPH_DMA_ROUTE_MASK << >> + PISTACHIO_CR_PERIPH_DMA_ROUTE_SHIFT(mchan->chan_nr), >> + 0); >> + spin_unlock_irqrestore(&mdma->lock, flags); >> +} > > Regmap has its own locking, no need to add another level. Ah, right. I'll drop the locking. -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html