printk(level "%s: fw-host%d: " fmt "\n" , OHCI1394_DRIVER_NAME, ohci->host->id , ## args)
static char version[] __devinitdata =
- "$Rev: 1223 $ Ben Collins <bcollins@debian.org>";
+ "$Rev: 1250 $ Ben Collins <bcollins@debian.org>";
/* Module Parameters */
static int phys_dma = 1;
/* Put some defaults to these undefined bus options */
buf = reg_read(ohci, OHCI1394_BusOptions);
- buf |= 0xE0000000; /* Enable IRMC, CMC and ISC */
+ buf |= 0x60000000; /* Enable CMC and ISC */
+ if (!hpsb_disable_irm)
+ buf |= 0x80000000; /* Enable IRMC */
buf &= ~0x00ff0000; /* XXX: Set cyc_clk_acc to zero for now */
buf &= ~0x18000000; /* Disable PMC and BMC */
reg_write(ohci, OHCI1394_BusOptions, buf);
reg_write(ohci, OHCI1394_LinkControlClear, 0xffffffff);
/* Enable cycle timer and cycle master and set the IRM
- * contender bit in our self ID packets. */
- reg_write(ohci, OHCI1394_LinkControlSet, OHCI1394_LinkControl_CycleTimerEnable |
+ * contender bit in our self ID packets if appropriate. */
+ reg_write(ohci, OHCI1394_LinkControlSet,
+ OHCI1394_LinkControl_CycleTimerEnable |
OHCI1394_LinkControl_CycleMaster);
- set_phy_reg_mask(ohci, 4, 0xc0);
+ set_phy_reg_mask(ohci, 4, PHY_04_LCTRL |
+ (hpsb_disable_irm ? 0 : PHY_04_CONTENDER));
/* Set up self-id dma buffer */
reg_write(ohci, OHCI1394_SelfIDBuffer, ohci->selfid_buf_bus);
/* Now get our max packet size */
ohci->max_packet_size =
1<<(((reg_read(ohci, OHCI1394_BusOptions)>>12)&0xf)+1);
-
- if (ohci->max_packet_size < 512) {
- HPSB_ERR("warning: Invalid max packet size of %d, setting to 512",
- ohci->max_packet_size);
- ohci->max_packet_size = 512;
- }
/* Don't accept phy packets into AR request context */
reg_write(ohci, OHCI1394_LinkControlClear, 0x00000400);
/* Initialize AT dma */
initialize_dma_trm_ctx(&ohci->at_req_context);
initialize_dma_trm_ctx(&ohci->at_resp_context);
+
+ /* Initialize IR Legacy DMA channel mask */
+ ohci->ir_legacy_channels = 0;
/*
* Accept AT requests from all nodes. This probably
case ISO_LISTEN_CHANNEL:
{
u64 mask;
+ struct dma_rcv_ctx *d = &ohci->ir_legacy_context;
+ int ir_legacy_active;
if (arg<0 || arg>63) {
PRINT(KERN_ERR,
return -EFAULT;
}
- /* activate the legacy IR context */
- if (ohci->ir_legacy_context.ohci == NULL) {
- if (alloc_dma_rcv_ctx(ohci, &ohci->ir_legacy_context,
- DMA_CTX_ISO, 0, IR_NUM_DESC,
- IR_BUF_SIZE, IR_SPLIT_BUF_SIZE,
- OHCI1394_IsoRcvContextBase) < 0) {
- PRINT(KERN_ERR, "%s: failed to allocate an IR context",
- __FUNCTION__);
- return -ENOMEM;
- }
- ohci->ir_legacy_channels = 0;
- initialize_dma_rcv_ctx(&ohci->ir_legacy_context, 1);
-
- DBGMSG("ISO receive legacy context activated");
- }
-
mask = (u64)0x1<<arg;
spin_lock_irqsave(&ohci->IR_channel_lock, flags);
return -EFAULT;
}
+ ir_legacy_active = ohci->ir_legacy_channels;
+
ohci->ISO_channel_usage |= mask;
ohci->ir_legacy_channels |= mask;
+ spin_unlock_irqrestore(&ohci->IR_channel_lock, flags);
+
+ if (!ir_legacy_active) {
+ if (ohci1394_register_iso_tasklet(ohci,
+ &ohci->ir_legacy_tasklet) < 0) {
+ PRINT(KERN_ERR, "No IR DMA context available");
+ return -EBUSY;
+ }
+
+ /* the IR context can be assigned to any DMA context
+ * by ohci1394_register_iso_tasklet */
+ d->ctx = ohci->ir_legacy_tasklet.context;
+ d->ctrlSet = OHCI1394_IsoRcvContextControlSet +
+ 32*d->ctx;
+ d->ctrlClear = OHCI1394_IsoRcvContextControlClear +
+ 32*d->ctx;
+ d->cmdPtr = OHCI1394_IsoRcvCommandPtr + 32*d->ctx;
+ d->ctxtMatch = OHCI1394_IsoRcvContextMatch + 32*d->ctx;
+
+ initialize_dma_rcv_ctx(&ohci->ir_legacy_context, 1);
+
+ PRINT(KERN_ERR, "IR legacy activated");
+ }
+
+ spin_lock_irqsave(&ohci->IR_channel_lock, flags);
+
if (arg>31)
reg_write(ohci, OHCI1394_IRMultiChanMaskHiSet,
1<<(arg-32));
if (ohci->ir_legacy_channels == 0) {
stop_dma_rcv_ctx(&ohci->ir_legacy_context);
- free_dma_rcv_ctx(&ohci->ir_legacy_context);
- DBGMSG("ISO receive legacy context deactivated");
+ DBGMSG("ISO legacy receive context stopped");
}
+
break;
}
default:
OHCI_ISO_RECEIVE,
ohci_iso_recv_task, (unsigned long) iso);
- if (ohci1394_register_iso_tasklet(recv->ohci, &recv->task) < 0)
+ if (ohci1394_register_iso_tasklet(recv->ohci, &recv->task) < 0) {
+ ret = -EBUSY;
goto err;
+ }
recv->task_active = 1;
ohci1394_init_iso_tasklet(&xmit->task, OHCI_ISO_TRANSMIT,
ohci_iso_xmit_task, (unsigned long) iso);
- if (ohci1394_register_iso_tasklet(xmit->ohci, &xmit->task) < 0)
+ if (ohci1394_register_iso_tasklet(xmit->ohci, &xmit->task) < 0) {
+ ret = -EBUSY;
goto err;
+ }
xmit->task_active = 1;
idx = (idx + d->num_desc - 1 ) % d->num_desc;
d->prg_cpu[idx]->branchAddress |= le32_to_cpu(0x00000001);
+ /* To avoid a race, ensure 1394 interface hardware sees the inserted
+ * context program descriptors before it sees the wakeup bit set. */
+ wmb();
+
/* wake up the dma context if necessary */
if (!(reg_read(ohci, d->ctrlSet) & 0x400)) {
PRINT(KERN_INFO,
(cond_le32_to_cpu(d->spb[length/4-1], ohci->no_swap_incoming)>>16)&0x1f,
(cond_le32_to_cpu(d->spb[length/4-1], ohci->no_swap_incoming)>>21)&0x3,
tcode, length, d->ctx,
- (cond_le32_to_cpu(d->spb[length/4-1], ohci->no_swap_incoming)>>10)&0x3f);
+ (cond_le32_to_cpu(d->spb[0], ohci->no_swap_incoming)>>10)&0x3f);
ack = (((cond_le32_to_cpu(d->spb[length/4-1], ohci->no_swap_incoming)>>16)&0x1f)
== 0x11) ? 1 : 0;
d->ctx);
else
DBGMSG("Packet sent to node %d tcode=0x%X tLabel="
- "0x%02X ack=0x%X spd=%d dataLength=%d ctx=%d",
+ "%d ack=0x%X spd=%d dataLength=%d ctx=%d",
(le32_to_cpu(d->prg_cpu[d->sent_ind]->data[1])>>16)&0x3f,
(le32_to_cpu(d->prg_cpu[d->sent_ind]->data[0])>>4)&0xf,
(le32_to_cpu(d->prg_cpu[d->sent_ind]->data[0])>>10)&0x3f,
d->ctx);
else
DBGMSG("Packet sent to node %d tcode=0x%X tLabel="
- "0x%02X ack=0x%X spd=%d data=0x%08X ctx=%d",
+ "%d ack=0x%X spd=%d data=0x%08X ctx=%d",
(le32_to_cpu(d->prg_cpu[d->sent_ind]->data[1])
>>16)&0x3f,
(le32_to_cpu(d->prg_cpu[d->sent_ind]->data[0])
kfree(d->prg_cpu);
kfree(d->prg_bus);
}
- if (d->spb) kfree(d->spb);
+ kfree(d->spb);
/* Mark this context as freed. */
d->ohci = NULL;
enum context_type type, int ctx, int num_desc,
int buf_size, int split_buf_size, int context_base)
{
- int i;
+ int i, len;
+ static int num_allocs;
+ static char pool_name[20];
d->ohci = ohci;
d->type = type;
free_dma_rcv_ctx(d);
return -ENOMEM;
}
-
- d->prg_pool = pci_pool_create("ohci1394 rcv prg", ohci->dev,
+
+ len = sprintf(pool_name, "ohci1394_rcv_prg");
+ sprintf(pool_name+len, "%d", num_allocs);
+ d->prg_pool = pci_pool_create(pool_name, ohci->dev,
sizeof(struct dma_cmd), 4, 0);
+ if(d->prg_pool == NULL)
+ {
+ PRINT(KERN_ERR, "pci_pool_create failed for %s", pool_name);
+ free_dma_rcv_ctx(d);
+ return -ENOMEM;
+ }
+ num_allocs++;
+
OHCI_DMA_ALLOC("dma_rcv prg pool");
for (i=0; i<d->num_desc; i++) {
ohci1394_init_iso_tasklet(&ohci->ir_legacy_tasklet,
OHCI_ISO_MULTICHANNEL_RECEIVE,
dma_rcv_tasklet, (unsigned long) d);
- if (ohci1394_register_iso_tasklet(ohci,
- &ohci->ir_legacy_tasklet) < 0) {
- PRINT(KERN_ERR, "No IR DMA context available");
- free_dma_rcv_ctx(d);
- return -EBUSY;
- }
-
- /* the IR context can be assigned to any DMA context
- * by ohci1394_register_iso_tasklet */
- d->ctx = ohci->ir_legacy_tasklet.context;
- d->ctrlSet = OHCI1394_IsoRcvContextControlSet + 32*d->ctx;
- d->ctrlClear = OHCI1394_IsoRcvContextControlClear + 32*d->ctx;
- d->cmdPtr = OHCI1394_IsoRcvCommandPtr + 32*d->ctx;
- d->ctxtMatch = OHCI1394_IsoRcvContextMatch + 32*d->ctx;
} else {
d->ctrlSet = context_base + OHCI1394_ContextControlSet;
d->ctrlClear = context_base + OHCI1394_ContextControlClear;
enum context_type type, int ctx, int num_desc,
int context_base)
{
- int i;
+ int i, len;
+ static char pool_name[20];
+ static int num_allocs=0;
d->ohci = ohci;
d->type = type;
memset(d->prg_cpu, 0, d->num_desc * sizeof(struct at_dma_prg*));
memset(d->prg_bus, 0, d->num_desc * sizeof(dma_addr_t));
- d->prg_pool = pci_pool_create("ohci1394 trm prg", ohci->dev,
+ len = sprintf(pool_name, "ohci1394_trm_prg");
+ sprintf(pool_name+len, "%d", num_allocs);
+ d->prg_pool = pci_pool_create(pool_name, ohci->dev,
sizeof(struct at_dma_prg), 4, 0);
+ if (d->prg_pool == NULL) {
+ PRINT(KERN_ERR, "pci_pool_create failed for %s", pool_name);
+ free_dma_trm_ctx(d);
+ return -ENOMEM;
+ }
+ num_allocs++;
+
OHCI_DMA_ALLOC("dma_rcv prg pool");
for (i = 0; i < d->num_desc; i++) {
ohci->ISO_channel_usage = 0;
spin_lock_init(&ohci->IR_channel_lock);
- /* the IR DMA context is allocated on-demand; mark it inactive */
- ohci->ir_legacy_context.ohci = NULL;
+ /* Allocate the IR DMA context right here so we don't have
+ * to do it in interrupt path - note that this doesn't
+ * waste much memory and avoids the jugglery required to
+ * allocate it in IRQ path. */
+ if (alloc_dma_rcv_ctx(ohci, &ohci->ir_legacy_context,
+ DMA_CTX_ISO, 0, IR_NUM_DESC,
+ IR_BUF_SIZE, IR_SPLIT_BUF_SIZE,
+ OHCI1394_IsoRcvContextBase) < 0) {
+ FAIL(-ENOMEM, "Cannot allocate IR Legacy DMA context");
+ }
- /* same for the IT DMA context */
+ /* We hopefully don't have to pre-allocate IT DMA like we did
+ * for IR DMA above. Allocate it on-demand and mark inactive. */
ohci->it_legacy_context.ohci = NULL;
if (request_irq(dev->irq, ohci_irq_handler, SA_SHIRQ,
/* Free IT dma */
free_dma_trm_ctx(&ohci->it_legacy_context);
+ /* Free IR legacy dma */
+ free_dma_rcv_ctx(&ohci->ir_legacy_context);
+
+
case OHCI_INIT_HAVE_SELFID_BUFFER:
pci_free_consistent(ohci->dev, OHCI1394_SI_DMA_BUF_SIZE,
ohci->selfid_buf_cpu,
}
-static int ohci1394_pci_suspend (struct pci_dev *pdev, u32 state)
+static int ohci1394_pci_suspend (struct pci_dev *pdev, pm_message_t state)
{
#ifdef CONFIG_PMAC_PBOOK
{
static int __init ohci1394_init(void)
{
- return pci_module_init(&ohci1394_pci_driver);
+ return pci_register_driver(&ohci1394_pci_driver);
}
module_init(ohci1394_init);