2.10. pl08x_irq

/*
 * issue pending() will start the next transfer
 * - it only need be loaded here
 * CAUTION the work queue function may run during the handler
 * CAUTION function callbacks may have interesting side effects
 */
static irqreturn_t pl08x_irq(int irq, void *dev)
{
	u32 mask = 0;
	u32 reg;
	unsigned long flags;
	int c;
	reg = readl(pd.base + PL08X_OS_ISR_ERR);
	mb();
	if (reg) {
		/*
		 * An error interrupt (on one or more channels)
		 */
		dev_err(&pd.dmac->dev,
			"%s - Error interrupt, register value 0x%08x\n",
				__func__, reg);
		/*
		 * Simply clear ALL PL08X error interrupts,1
		 * regardless of channel and cause
		 */
		writel(0x000000FF, pd.base + PL08X_OS_ICLR_ERR);
	}
	reg = readl(pd.base + PL08X_OS_ISR);
	mb();
	for (c = 0; c < MAX_DMA_CHANNELS; c++) {
		if ((1 << c) & reg) {
			struct pl08x_txd *entry = NULL;
			struct pl08x_txd *next;

			spin_lock_irqsave(&pd.chanwrap[c]->lock, flags);

			if (pd.chanwrap[c]->at) {
				/*
				 * Update last completed
				 */
				pd.chanwrap[c]->lc =
					(pd.chanwrap[c]->at->tx.cookie);
				/*
				 * Callback peripheral driver for p/m
				 * to signal completion
				 */
				if (pd.chanwrap[c]->at->tx.callback) {
					/*
					 * Pass channel number
					 */
					((struct pl08x_callback_param *)
						pd.chanwrap[c]->at->tx.callback_param)->act = c;
					pd.chanwrap[c]->at->tx.callback2(
						pd.chanwrap[c]->at->tx.callback_param);
				}
				/*
				 * Device callbacks should NOT clear
				 * the current transaction on the channel
				 */
				if (!pd.chanwrap[c]->at)
					BUG();

				/*
				 * Free the descriptor if it's not for a device
				 * using a circular buffer
				 */
				if (!(pd.chanwrap[c]->at->pcd->circular_buffer)) {
					list_add_tail(&pd.chanwrap[c]->at->txd_list,
						&pd.chanwrap[c]->release_list);
					pd.chanwrap[c]->at = NULL;
					if (pd.pool_ctr > PL08X_MAX_ALLOCS) {
						schedule_work(&pd.dwork);
					}
				}
				/*
				 * else descriptor for circular
				 * buffers only freed when
				 * client has disabled dma
				 */
			}
			/*
			 * If descriptor queued, set it up
			 */
			if (!list_empty(&pd.chanwrap[c]->desc_list)) {
				list_for_each_entry_safe(entry,
				next, &pd.chanwrap[c]->desc_list, txd_list) {
					list_del_init(&entry->txd_list);
					pd.chanwrap[c]->at = entry;
					break;
				}
			}

			spin_unlock_irqrestore(&pd.chanwrap[c]->lock, flags);

			mask |= (1 << c);
		}
	}
	/*
	 * Clear only the terminal interrupts on channels we processed
	 */
	writel(mask, pd.base + PL08X_OS_ICLR_TC);
	mb();

	return mask ? IRQ_HANDLED : IRQ_NONE;
}
        

1

如果发现有任何错误,就退出

实际上此处很多种错误,而目前的此版本的驱动,暂时没加入更多的判断,仅仅是报错而已

2

此处,真正去调用你之前挂载的callback函数,在callback函数里面,常见要做的事情就是清除你设备的DMA enable位,然后调用complete去使得completion变量完成,使得你驱动得以继续执行