drivers/soc/ixp4xx/ixp4xx-qmgr.c

Source file repositories/reference/linux-study-clean/drivers/soc/ixp4xx/ixp4xx-qmgr.c

File Facts

System
Linux kernel
Corpus path
drivers/soc/ixp4xx/ixp4xx-qmgr.c
Extension
.c
Size
11972 bytes
Lines
488
Domain
Driver Families
Bucket
drivers/soc
Inferred role
Driver Families: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (stat & BIT(src & 3)) {
			irq_handlers[i](irq_pdevs[i]);
			ret = IRQ_HANDLED;
		}
	}
	return ret;
}


static irqreturn_t qmgr_irq2_a0(int irq, void *pdev)
{
	int i, ret = 0;
	u32 req_bitmap;

	/* ACK - it may clear any bits so don't rely on it */
	__raw_writel(0xFFFFFFFF, &qmgr_regs->irqstat[1]);

	req_bitmap = __raw_readl(&qmgr_regs->irqen[1]) &
		     __raw_readl(&qmgr_regs->statne_h);
	while (req_bitmap) {
		i = __fls(req_bitmap); /* number of the last "high" queue */
		req_bitmap &= ~BIT(i);
		irq_handlers[HALF_QUEUES + i](irq_pdevs[HALF_QUEUES + i]);
		ret = IRQ_HANDLED;
	}
	return ret;
}


static irqreturn_t qmgr_irq(int irq, void *pdev)
{
	int i, half = (irq == qmgr_irq_1 ? 0 : 1);
	u32 req_bitmap = __raw_readl(&qmgr_regs->irqstat[half]);

	if (!req_bitmap)
		return 0;
	__raw_writel(req_bitmap, &qmgr_regs->irqstat[half]); /* ACK */

	while (req_bitmap) {
		i = __fls(req_bitmap); /* number of the last queue */
		req_bitmap &= ~BIT(i);
		i += half * HALF_QUEUES;
		irq_handlers[i](irq_pdevs[i]);
	}
	return IRQ_HANDLED;
}


void qmgr_enable_irq(unsigned int queue)
{
	unsigned long flags;
	int half = queue / 32;
	u32 mask = 1 << (queue & (HALF_QUEUES - 1));

	spin_lock_irqsave(&qmgr_lock, flags);
	__raw_writel(__raw_readl(&qmgr_regs->irqen[half]) | mask,
		     &qmgr_regs->irqen[half]);
	spin_unlock_irqrestore(&qmgr_lock, flags);
}

void qmgr_disable_irq(unsigned int queue)
{
	unsigned long flags;
	int half = queue / 32;
	u32 mask = 1 << (queue & (HALF_QUEUES - 1));

	spin_lock_irqsave(&qmgr_lock, flags);
	__raw_writel(__raw_readl(&qmgr_regs->irqen[half]) & ~mask,
		     &qmgr_regs->irqen[half]);
	__raw_writel(mask, &qmgr_regs->irqstat[half]); /* clear */
	spin_unlock_irqrestore(&qmgr_lock, flags);
}

static inline void shift_mask(u32 *mask)
{
	mask[3] = mask[3] << 1 | mask[2] >> 31;
	mask[2] = mask[2] << 1 | mask[1] >> 31;
	mask[1] = mask[1] << 1 | mask[0] >> 31;
	mask[0] <<= 1;
}

#if DEBUG_QMGR
int qmgr_request_queue(unsigned int queue, unsigned int len /* dwords */,
		       unsigned int nearly_empty_watermark,
		       unsigned int nearly_full_watermark,
		       const char *desc_format, const char* name)
#else
int __qmgr_request_queue(unsigned int queue, unsigned int len /* dwords */,
			 unsigned int nearly_empty_watermark,
			 unsigned int nearly_full_watermark)

Annotation

Implementation Notes