in devices/tsi721.c [2160:2347]
static int tsi721_open_inb_mbox(struct rio_mport *mport, void *dev_id,
int mbox, int entries)
{
struct tsi721_device *priv = mport->priv;
int ch = mbox + 4;
int i;
u64 *free_ptr;
int rc = 0;
if ((entries < TSI721_IMSGD_MIN_RING_SIZE) ||
(entries > TSI721_IMSGD_RING_SIZE) ||
(!is_power_of_2(entries)) || mbox >= RIO_MAX_MBOX) {
rc = -EINVAL;
goto out;
}
if ((mbox_sel & (1 << mbox)) == 0) {
rc = -ENODEV;
goto out;
}
/* Initialize IB Messaging Ring */
priv->imsg_ring[mbox].dev_id = dev_id;
priv->imsg_ring[mbox].size = entries;
priv->imsg_ring[mbox].rx_slot = 0;
priv->imsg_ring[mbox].desc_rdptr = 0;
priv->imsg_ring[mbox].fq_wrptr = 0;
for (i = 0; i < priv->imsg_ring[mbox].size; i++)
priv->imsg_ring[mbox].imq_base[i] = NULL;
spin_lock_init(&priv->imsg_ring[mbox].lock);
/* Allocate buffers for incoming messages */
priv->imsg_ring[mbox].buf_base =
dma_alloc_coherent(&priv->pdev->dev,
entries * TSI721_MSG_BUFFER_SIZE,
&priv->imsg_ring[mbox].buf_phys,
GFP_KERNEL);
if (priv->imsg_ring[mbox].buf_base == NULL) {
tsi_err(&priv->pdev->dev,
"Failed to allocate buffers for IB MBOX%d", mbox);
rc = -ENOMEM;
goto out;
}
/* Allocate memory for circular free list */
priv->imsg_ring[mbox].imfq_base =
dma_alloc_coherent(&priv->pdev->dev,
entries * 8,
&priv->imsg_ring[mbox].imfq_phys,
GFP_KERNEL);
if (priv->imsg_ring[mbox].imfq_base == NULL) {
tsi_err(&priv->pdev->dev,
"Failed to allocate free queue for IB MBOX%d", mbox);
rc = -ENOMEM;
goto out_buf;
}
/* Allocate memory for Inbound message descriptors */
priv->imsg_ring[mbox].imd_base =
dma_alloc_coherent(&priv->pdev->dev,
entries * sizeof(struct tsi721_imsg_desc),
&priv->imsg_ring[mbox].imd_phys, GFP_KERNEL);
if (priv->imsg_ring[mbox].imd_base == NULL) {
tsi_err(&priv->pdev->dev,
"Failed to allocate descriptor memory for IB MBOX%d",
mbox);
rc = -ENOMEM;
goto out_dma;
}
/* Fill free buffer pointer list */
free_ptr = priv->imsg_ring[mbox].imfq_base;
for (i = 0; i < entries; i++)
free_ptr[i] = cpu_to_le64(
(u64)(priv->imsg_ring[mbox].buf_phys) +
i * 0x1000);
mb();
/*
* For mapping of inbound SRIO Messages into appropriate queues we need
* to set Inbound Device ID register in the messaging engine. We do it
* once when first inbound mailbox is requested.
*/
if (!(priv->flags & TSI721_IMSGID_SET)) {
iowrite32((u32)priv->mport.host_deviceid,
priv->regs + TSI721_IB_DEVID);
priv->flags |= TSI721_IMSGID_SET;
}
/*
* Configure Inbound Messaging channel (ch = mbox + 4)
*/
/* Setup Inbound Message free queue */
iowrite32(((u64)priv->imsg_ring[mbox].imfq_phys >> 32),
priv->regs + TSI721_IBDMAC_FQBH(ch));
iowrite32(((u64)priv->imsg_ring[mbox].imfq_phys &
TSI721_IBDMAC_FQBL_MASK),
priv->regs+TSI721_IBDMAC_FQBL(ch));
iowrite32(TSI721_DMAC_DSSZ_SIZE(entries),
priv->regs + TSI721_IBDMAC_FQSZ(ch));
/* Setup Inbound Message descriptor queue */
iowrite32(((u64)priv->imsg_ring[mbox].imd_phys >> 32),
priv->regs + TSI721_IBDMAC_DQBH(ch));
iowrite32(((u32)priv->imsg_ring[mbox].imd_phys &
(u32)TSI721_IBDMAC_DQBL_MASK),
priv->regs+TSI721_IBDMAC_DQBL(ch));
iowrite32(TSI721_DMAC_DSSZ_SIZE(entries),
priv->regs + TSI721_IBDMAC_DQSZ(ch));
/* Enable interrupts */
#ifdef CONFIG_PCI_MSI
if (priv->flags & TSI721_USING_MSIX) {
int idx = TSI721_VECT_IMB0_RCV + mbox;
/* Request interrupt service if we are in MSI-X mode */
rc = request_irq(priv->msix[idx].vector, tsi721_imsg_msix, 0,
priv->msix[idx].irq_name, (void *)priv);
if (rc) {
tsi_debug(IMSG, &priv->pdev->dev,
"Unable to get MSI-X IRQ for IBOX%d-DONE",
mbox);
goto out_desc;
}
idx = TSI721_VECT_IMB0_INT + mbox;
rc = request_irq(priv->msix[idx].vector, tsi721_imsg_msix, 0,
priv->msix[idx].irq_name, (void *)priv);
if (rc) {
tsi_debug(IMSG, &priv->pdev->dev,
"Unable to get MSI-X IRQ for IBOX%d-INT", mbox);
free_irq(
priv->msix[TSI721_VECT_IMB0_RCV + mbox].vector,
(void *)priv);
goto out_desc;
}
}
#endif /* CONFIG_PCI_MSI */
tsi721_imsg_interrupt_enable(priv, ch, TSI721_IBDMAC_INT_ALL);
/* Initialize Inbound Message Engine */
iowrite32(TSI721_IBDMAC_CTL_INIT, priv->regs + TSI721_IBDMAC_CTL(ch));
ioread32(priv->regs + TSI721_IBDMAC_CTL(ch));
udelay(10);
priv->imsg_ring[mbox].fq_wrptr = entries - 1;
iowrite32(entries - 1, priv->regs + TSI721_IBDMAC_FQWP(ch));
priv->imsg_init[mbox] = 1;
return 0;
#ifdef CONFIG_PCI_MSI
out_desc:
dma_free_coherent(&priv->pdev->dev,
priv->imsg_ring[mbox].size * sizeof(struct tsi721_imsg_desc),
priv->imsg_ring[mbox].imd_base,
priv->imsg_ring[mbox].imd_phys);
priv->imsg_ring[mbox].imd_base = NULL;
#endif /* CONFIG_PCI_MSI */
out_dma:
dma_free_coherent(&priv->pdev->dev,
priv->imsg_ring[mbox].size * 8,
priv->imsg_ring[mbox].imfq_base,
priv->imsg_ring[mbox].imfq_phys);
priv->imsg_ring[mbox].imfq_base = NULL;
out_buf:
dma_free_coherent(&priv->pdev->dev,
priv->imsg_ring[mbox].size * TSI721_MSG_BUFFER_SIZE,
priv->imsg_ring[mbox].buf_base,
priv->imsg_ring[mbox].buf_phys);
priv->imsg_ring[mbox].buf_base = NULL;
out:
return rc;
}