Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git] / drivers / ieee1394 / ohci1394.c
index 88438b5..8f1292c 100644 (file)
@@ -94,7 +94,6 @@
 #include <linux/pci.h>
 #include <linux/fs.h>
 #include <linux/poll.h>
-#include <linux/irq.h>
 #include <asm/byteorder.h>
 #include <asm/atomic.h>
 #include <asm/uaccess.h>
 
 #include <asm/pgtable.h>
 #include <asm/page.h>
+#include <asm/irq.h>
 #include <linux/sched.h>
 #include <linux/types.h>
 #include <linux/vmalloc.h>
@@ -161,9 +161,6 @@ printk(level "%s: " fmt "\n" , OHCI1394_DRIVER_NAME , ## args)
 #define PRINT(level, fmt, args...) \
 printk(level "%s: fw-host%d: " fmt "\n" , OHCI1394_DRIVER_NAME, ohci->host->id , ## args)
 
-static char version[] __devinitdata =
-       "$Rev: 1203 $ Ben Collins <bcollins@debian.org>";
-
 /* Module Parameters */
 static int phys_dma = 1;
 module_param(phys_dma, int, 0644);
@@ -478,11 +475,14 @@ static void ohci_initialize(struct ti_ohci *ohci)
        int num_ports, i;
 
        spin_lock_init(&ohci->phy_reg_lock);
-       spin_lock_init(&ohci->event_lock);
 
        /* 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;
+       else
+               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);
@@ -497,10 +497,16 @@ static void ohci_initialize(struct ti_ohci *ohci)
        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);
+       i = get_phy_reg(ohci, 4) | PHY_04_LCTRL;
+       if (hpsb_disable_irm)
+               i &= ~PHY_04_CONTENDER;
+       else
+               i |= PHY_04_CONTENDER;
+       set_phy_reg(ohci, 4, i);
 
        /* Set up self-id dma buffer */
        reg_write(ohci, OHCI1394_SelfIDBuffer, ohci->selfid_buf_bus);
@@ -515,7 +521,7 @@ static void ohci_initialize(struct ti_ohci *ohci)
        /* Now get our max packet size */
        ohci->max_packet_size =
                1<<(((reg_read(ohci, OHCI1394_BusOptions)>>12)&0xf)+1);
-
+               
        /* Don't accept phy packets into AR request context */
        reg_write(ohci, OHCI1394_LinkControlClear, 0x00000400);
 
@@ -534,13 +540,23 @@ static void ohci_initialize(struct ti_ohci *ohci)
        /* 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
-        * will have to be controlled from the subsystem
-        * on a per node basis.
-        */
-       reg_write(ohci,OHCI1394_AsReqFilterHiSet, 0x80000000);
+       /* Accept AR requests from all nodes */
+       reg_write(ohci, OHCI1394_AsReqFilterHiSet, 0x80000000);
+
+       /* Set the address range of the physical response unit.
+        * Most controllers do not implement it as a writable register though.
+        * They will keep a hardwired offset of 0x00010000 and show 0x0 as
+        * register content.
+        * To actually enable physical responses is the job of our interrupt
+        * handler which programs the physical request filter. */
+       reg_write(ohci, OHCI1394_PhyUpperBound, 0x01000000);
+
+       DBGMSG("physUpperBoundOffset=%08x",
+              reg_read(ohci, OHCI1394_PhyUpperBound));
 
        /* Specify AT retries */
        reg_write(ohci, OHCI1394_ATRetries,
@@ -563,6 +579,7 @@ static void ohci_initialize(struct ti_ohci *ohci)
                  OHCI1394_reqTxComplete |
                  OHCI1394_isochRx |
                  OHCI1394_isochTx |
+                 OHCI1394_postedWriteErr |
                  OHCI1394_cycleInconsistent);
 
        /* Enable link */
@@ -575,12 +592,13 @@ static void ohci_initialize(struct ti_ohci *ohci)
        sprintf (irq_buf, "%s", __irq_itoa(ohci->dev->irq));
 #endif
        PRINT(KERN_INFO, "OHCI-1394 %d.%d (PCI): IRQ=[%s]  "
-             "MMIO=[%lx-%lx]  Max Packet=[%d]",
+             "MMIO=[%lx-%lx]  Max Packet=[%d]  IR/IT contexts=[%d/%d]",
              ((((buf) >> 16) & 0xf) + (((buf) >> 20) & 0xf) * 10),
              ((((buf) >> 4) & 0xf) + ((buf) & 0xf) * 10), irq_buf,
              pci_resource_start(ohci->dev, 0),
              pci_resource_start(ohci->dev, 0) + OHCI1394_REGISTER_SIZE - 1,
-             ohci->max_packet_size);
+             ohci->max_packet_size,
+             ohci->nb_iso_rcv_ctx, ohci->nb_iso_xmit_ctx);
 
        /* Check all of our ports to make sure that if anything is
         * connected, we enable that port. */
@@ -1023,6 +1041,8 @@ static int ohci_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg)
        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,
@@ -1031,22 +1051,6 @@ static int ohci_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg)
                        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);
@@ -1059,9 +1063,38 @@ static int ohci_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg)
                        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);
+
+                       if (printk_ratelimit())
+                               DBGMSG("IR legacy activated");
+               }
+
+                spin_lock_irqsave(&ohci->IR_channel_lock, flags);
+
                if (arg>31)
                        reg_write(ohci, OHCI1394_IRMultiChanMaskHiSet,
                                  1<<(arg-32));
@@ -1111,9 +1144,9 @@ static int ohci_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg)
 
                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:
@@ -1283,8 +1316,10 @@ static int ohci_iso_recv_init(struct hpsb_iso *iso)
                                                       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;
 
@@ -1543,6 +1578,10 @@ static void ohci_iso_recv_release_block(struct ohci_iso_recv *recv, int block)
 
        struct dma_cmd *next = &recv->block[next_i];
        struct dma_cmd *prev = &recv->block[prev_i];
+       
+       /* ignore out-of-range requests */
+       if ((block < 0) || (block > recv->nblocks))
+               return;
 
        /* 'next' becomes the new end of the DMA chain,
           so disable branch and enable interrupt */
@@ -1570,19 +1609,8 @@ static void ohci_iso_recv_release_block(struct ohci_iso_recv *recv, int block)
 static void ohci_iso_recv_bufferfill_release(struct ohci_iso_recv *recv,
                                             struct hpsb_iso_packet_info *info)
 {
-       int len;
-
        /* release the memory where the packet was */
-       len = info->len;
-
-       /* add the wasted space for padding to 4 bytes */
-       if (len % 4)
-               len += 4 - (len % 4);
-
-       /* add 8 bytes for the OHCI DMA data format overhead */
-       len += 8;
-
-       recv->released_bytes += len;
+       recv->released_bytes += info->total_len;
 
        /* have we released enough memory for one block? */
        while (recv->released_bytes > recv->buf_stride) {
@@ -1614,7 +1642,7 @@ static void ohci_iso_recv_bufferfill_parse(struct hpsb_iso *iso, struct ohci_iso
                /* note: packet layout is as shown in section 10.6.1.1 of the OHCI spec */
 
                unsigned int offset;
-               unsigned short len, cycle;
+               unsigned short len, cycle, total_len;
                unsigned char channel, tag, sy;
 
                unsigned char *p = iso->data_buf.kvirt;
@@ -1665,9 +1693,11 @@ static void ohci_iso_recv_bufferfill_parse(struct hpsb_iso *iso, struct ohci_iso
                /* advance to xferStatus/timeStamp */
                recv->dma_offset += len;
 
+               total_len = len + 8; /* 8 bytes header+trailer in OHCI packet */
                /* payload is padded to 4 bytes */
                if (len % 4) {
                        recv->dma_offset += 4 - (len%4);
+                       total_len += 4 - (len%4);
                }
 
                /* check for wrap-around */
@@ -1701,7 +1731,7 @@ static void ohci_iso_recv_bufferfill_parse(struct hpsb_iso *iso, struct ohci_iso
                        recv->dma_offset -= recv->buf_stride*recv->nblocks;
                }
 
-               hpsb_iso_packet_received(iso, offset, len, cycle, channel, tag, sy);
+               hpsb_iso_packet_received(iso, offset, len, total_len, cycle, channel, tag, sy);
        }
 
        if (wake)
@@ -1827,7 +1857,8 @@ static void ohci_iso_recv_packetperbuf_task(struct hpsb_iso *iso, struct ohci_is
                        tag = hdr[5] >> 6;
                        sy = hdr[4] & 0xF;
 
-                       hpsb_iso_packet_received(iso, offset, packet_len, cycle, channel, tag, sy);
+                       hpsb_iso_packet_received(iso, offset, packet_len,
+                                       recv->buf_stride, cycle, channel, tag, sy);
                }
 
                /* reset the DMA descriptor */
@@ -1909,8 +1940,10 @@ static int ohci_iso_xmit_init(struct hpsb_iso *iso)
        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;
 
@@ -2256,8 +2289,9 @@ static void ohci_schedule_iso_tasklets(struct ti_ohci *ohci,
 {
        struct ohci1394_iso_tasklet *t;
        unsigned long mask;
+       unsigned long flags;
 
-       spin_lock(&ohci->iso_tasklet_list_lock);
+       spin_lock_irqsave(&ohci->iso_tasklet_list_lock, flags);
 
        list_for_each_entry(t, &ohci->iso_tasklet_list, link) {
                mask = 1 << t->context;
@@ -2268,8 +2302,7 @@ static void ohci_schedule_iso_tasklets(struct ti_ohci *ohci,
                        tasklet_schedule(&t->tasklet);
        }
 
-       spin_unlock(&ohci->iso_tasklet_list_lock);
-
+       spin_unlock_irqrestore(&ohci->iso_tasklet_list_lock, flags);
 }
 
 static irqreturn_t ohci_irq_handler(int irq, void *dev_id,
@@ -2349,7 +2382,10 @@ static irqreturn_t ohci_irq_handler(int irq, void *dev_id,
 
                event &= ~OHCI1394_unrecoverableError;
        }
-
+       if (event & OHCI1394_postedWriteErr) {
+               PRINT(KERN_ERR, "physical posted write error");
+               /* no recovery strategy yet, had to involve protocol drivers */
+       }
        if (event & OHCI1394_cycleInconsistent) {
                /* We subscribe to the cycleInconsistent event only to
                 * clear the corresponding event bit... otherwise,
@@ -2357,7 +2393,6 @@ static irqreturn_t ohci_irq_handler(int irq, void *dev_id,
                DBGMSG("OHCI1394_cycleInconsistent");
                event &= ~OHCI1394_cycleInconsistent;
        }
-
        if (event & OHCI1394_busReset) {
                /* The busReset event bit can't be cleared during the
                 * selfID phase, so we disable busReset interrupts, to
@@ -2401,7 +2436,6 @@ static irqreturn_t ohci_irq_handler(int irq, void *dev_id,
                }
                event &= ~OHCI1394_busReset;
        }
-
        if (event & OHCI1394_reqTxComplete) {
                struct dma_trm_ctx *d = &ohci->at_req_context;
                DBGMSG("Got reqTxComplete interrupt "
@@ -2489,26 +2523,20 @@ static irqreturn_t ohci_irq_handler(int irq, void *dev_id,
                        reg_write(ohci, OHCI1394_IntMaskSet, OHCI1394_busReset);
                        spin_unlock_irqrestore(&ohci->event_lock, flags);
 
-                       /* Accept Physical requests from all nodes. */
-                       reg_write(ohci,OHCI1394_AsReqFilterHiSet, 0xffffffff);
-                       reg_write(ohci,OHCI1394_AsReqFilterLoSet, 0xffffffff);
-
                        /* Turn on phys dma reception.
                         *
                         * TODO: Enable some sort of filtering management.
                         */
                        if (phys_dma) {
-                               reg_write(ohci,OHCI1394_PhyReqFilterHiSet, 0xffffffff);
-                               reg_write(ohci,OHCI1394_PhyReqFilterLoSet, 0xffffffff);
-                               reg_write(ohci,OHCI1394_PhyUpperBound, 0xffff0000);
-                       } else {
-                               reg_write(ohci,OHCI1394_PhyReqFilterHiSet, 0x00000000);
-                               reg_write(ohci,OHCI1394_PhyReqFilterLoSet, 0x00000000);
+                               reg_write(ohci, OHCI1394_PhyReqFilterHiSet,
+                                         0xffffffff);
+                               reg_write(ohci, OHCI1394_PhyReqFilterLoSet,
+                                         0xffffffff);
                        }
 
                        DBGMSG("PhyReqFilter=%08x%08x",
-                              reg_read(ohci,OHCI1394_PhyReqFilterHiSet),
-                              reg_read(ohci,OHCI1394_PhyReqFilterLoSet));
+                              reg_read(ohci, OHCI1394_PhyReqFilterHiSet),
+                              reg_read(ohci, OHCI1394_PhyReqFilterLoSet));
 
                        hpsb_selfid_complete(host, phyid, isroot);
                } else
@@ -2539,6 +2567,10 @@ static void insert_dma_buffer(struct dma_rcv_ctx *d, int idx)
        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,
@@ -2700,7 +2732,7 @@ static void dma_rcv_tasklet (unsigned long data)
                                (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;
@@ -2763,7 +2795,7 @@ static void dma_trm_tasklet (unsigned long data)
                                       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,
@@ -2772,7 +2804,7 @@ static void dma_trm_tasklet (unsigned long data)
                                       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])
@@ -2902,7 +2934,7 @@ static void free_dma_rcv_ctx(struct dma_rcv_ctx *d)
                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;
@@ -2913,7 +2945,9 @@ alloc_dma_rcv_ctx(struct ti_ohci *ohci, struct dma_rcv_ctx *d,
                  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;
@@ -2927,39 +2961,44 @@ alloc_dma_rcv_ctx(struct ti_ohci *ohci, struct dma_rcv_ctx *d,
        d->ctrlClear = 0;
        d->cmdPtr = 0;
 
-       d->buf_cpu = kmalloc(d->num_desc * sizeof(quadlet_t*), GFP_KERNEL);
-       d->buf_bus = kmalloc(d->num_desc * sizeof(dma_addr_t), GFP_KERNEL);
+       d->buf_cpu = kzalloc(d->num_desc * sizeof(*d->buf_cpu), GFP_ATOMIC);
+       d->buf_bus = kzalloc(d->num_desc * sizeof(*d->buf_bus), GFP_ATOMIC);
 
        if (d->buf_cpu == NULL || d->buf_bus == NULL) {
                PRINT(KERN_ERR, "Failed to allocate dma buffer");
                free_dma_rcv_ctx(d);
                return -ENOMEM;
        }
-       memset(d->buf_cpu, 0, d->num_desc * sizeof(quadlet_t*));
-       memset(d->buf_bus, 0, d->num_desc * sizeof(dma_addr_t));
 
-       d->prg_cpu = kmalloc(d->num_desc * sizeof(struct dma_cmd*),
-                            GFP_KERNEL);
-       d->prg_bus = kmalloc(d->num_desc * sizeof(dma_addr_t), GFP_KERNEL);
+       d->prg_cpu = kzalloc(d->num_desc * sizeof(*d->prg_cpu), GFP_ATOMIC);
+       d->prg_bus = kzalloc(d->num_desc * sizeof(*d->prg_bus), GFP_ATOMIC);
 
        if (d->prg_cpu == NULL || d->prg_bus == NULL) {
                PRINT(KERN_ERR, "Failed to allocate dma prg");
                free_dma_rcv_ctx(d);
                return -ENOMEM;
        }
-       memset(d->prg_cpu, 0, d->num_desc * sizeof(struct dma_cmd*));
-       memset(d->prg_bus, 0, d->num_desc * sizeof(dma_addr_t));
 
-       d->spb = kmalloc(d->split_buf_size, GFP_KERNEL);
+       d->spb = kmalloc(d->split_buf_size, GFP_ATOMIC);
 
        if (d->spb == NULL) {
                PRINT(KERN_ERR, "Failed to allocate split buffer");
                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++) {
@@ -2996,20 +3035,6 @@ alloc_dma_rcv_ctx(struct ti_ohci *ohci, struct dma_rcv_ctx *d,
                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;
@@ -3052,7 +3077,9 @@ alloc_dma_trm_ctx(struct ti_ohci *ohci, struct dma_trm_ctx *d,
                  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;
@@ -3062,20 +3089,26 @@ alloc_dma_trm_ctx(struct ti_ohci *ohci, struct dma_trm_ctx *d,
        d->ctrlClear = 0;
        d->cmdPtr = 0;
 
-       d->prg_cpu = kmalloc(d->num_desc * sizeof(struct at_dma_prg*),
-                            GFP_KERNEL);
-       d->prg_bus = kmalloc(d->num_desc * sizeof(dma_addr_t), GFP_KERNEL);
+       d->prg_cpu = kzalloc(d->num_desc * sizeof(*d->prg_cpu), GFP_KERNEL);
+       d->prg_bus = kzalloc(d->num_desc * sizeof(*d->prg_bus), GFP_KERNEL);
 
        if (d->prg_cpu == NULL || d->prg_bus == NULL) {
                PRINT(KERN_ERR, "Failed to allocate at dma prg");
                free_dma_trm_ctx(d);
                return -ENOMEM;
        }
-       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++) {
@@ -3161,8 +3194,6 @@ static struct hpsb_host_driver ohci1394_driver = {
        .hw_csr_reg =           ohci_hw_csr_reg,
 };
 
-\f
-
 /***********************************
  * PCI Driver Interface functions  *
  ***********************************/
@@ -3177,15 +3208,10 @@ do {                                            \
 static int __devinit ohci1394_pci_probe(struct pci_dev *dev,
                                        const struct pci_device_id *ent)
 {
-       static int version_printed = 0;
-
        struct hpsb_host *host;
        struct ti_ohci *ohci;   /* shortcut to currently handled device */
        unsigned long ohci_base;
 
-       if (version_printed++ == 0)
-               PRINT_G(KERN_INFO, "%s", version);
-
         if (pci_enable_device(dev))
                FAIL(-ENXIO, "Failed to enable OHCI hardware");
         pci_set_master(dev);
@@ -3236,8 +3262,8 @@ static int __devinit ohci1394_pci_probe(struct pci_dev *dev,
         * fail to report the right length.  Anyway, the ohci spec
         * clearly says it's 2kb, so this shouldn't be a problem. */
        ohci_base = pci_resource_start(dev, 0);
-       if (pci_resource_len(dev, 0) != OHCI1394_REGISTER_SIZE)
-               PRINT(KERN_WARNING, "Unexpected PCI resource length of %lx!",
+       if (pci_resource_len(dev, 0) < OHCI1394_REGISTER_SIZE)
+               PRINT(KERN_WARNING, "PCI resource length of %lx too small!",
                      pci_resource_len(dev, 0));
 
        /* Seems PCMCIA handles this internally. Not sure why. Seems
@@ -3329,13 +3355,8 @@ static int __devinit ohci1394_pci_probe(struct pci_dev *dev,
        /* Determine the number of available IR and IT contexts. */
        ohci->nb_iso_rcv_ctx =
                get_nb_iso_ctx(ohci, OHCI1394_IsoRecvIntMaskSet);
-       DBGMSG("%d iso receive contexts available",
-              ohci->nb_iso_rcv_ctx);
-
        ohci->nb_iso_xmit_ctx =
                get_nb_iso_ctx(ohci, OHCI1394_IsoXmitIntMaskSet);
-       DBGMSG("%d iso transmit contexts available",
-              ohci->nb_iso_xmit_ctx);
 
        /* Set the usage bits for non-existent contexts so they can't
         * be allocated */
@@ -3347,12 +3368,28 @@ static int __devinit ohci1394_pci_probe(struct pci_dev *dev,
        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;
+       spin_lock_init(&ohci->event_lock);
 
+       /*
+        * interrupts are disabled, all right, but... due to SA_SHIRQ we
+        * might get called anyway.  We'll see no event, of course, but
+        * we need to get to that "no event", so enough should be initialized
+        * by that point.
+        */
        if (request_irq(dev->irq, ohci_irq_handler, SA_SHIRQ,
                         OHCI1394_DRIVER_NAME, ohci))
                FAIL(-ENOMEM, "Failed to allocate shared interrupt %d", dev->irq);
@@ -3439,6 +3476,10 @@ static void ohci1394_pci_remove(struct pci_dev *pdev)
                /* 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,
@@ -3487,8 +3528,8 @@ static void ohci1394_pci_remove(struct pci_dev *pdev)
 
 static int ohci1394_pci_resume (struct pci_dev *pdev)
 {
-#ifdef CONFIG_PMAC_PBOOK
-       {
+#ifdef CONFIG_PPC_PMAC
+       if (machine_is(powermac)) {
                struct device_node *of_node;
 
                /* Re-enable 1394 */
@@ -3496,18 +3537,19 @@ static int ohci1394_pci_resume (struct pci_dev *pdev)
                if (of_node)
                        pmac_call_feature (PMAC_FTR_1394_ENABLE, of_node, 0, 1);
        }
-#endif
+#endif /* CONFIG_PPC_PMAC */
 
+       pci_restore_state(pdev);
        pci_enable_device(pdev);
 
        return 0;
 }
 
 
-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
-       {
+#ifdef CONFIG_PPC_PMAC
+       if (machine_is(powermac)) {
                struct device_node *of_node;
 
                /* Disable 1394 */
@@ -3517,6 +3559,8 @@ static int ohci1394_pci_suspend (struct pci_dev *pdev, u32 state)
        }
 #endif
 
+       pci_save_state(pdev);
+
        return 0;
 }
 
@@ -3546,8 +3590,6 @@ static struct pci_driver ohci1394_pci_driver = {
        .suspend =      ohci1394_pci_suspend,
 };
 
-\f
-
 /***********************************
  * OHCI1394 Video Interface        *
  ***********************************/
@@ -3654,7 +3696,6 @@ EXPORT_SYMBOL(ohci1394_init_iso_tasklet);
 EXPORT_SYMBOL(ohci1394_register_iso_tasklet);
 EXPORT_SYMBOL(ohci1394_unregister_iso_tasklet);
 
-
 /***********************************
  * General module initialization   *
  ***********************************/
@@ -3670,7 +3711,7 @@ static void __exit ohci1394_cleanup (void)
 
 static int __init ohci1394_init(void)
 {
-       return pci_module_init(&ohci1394_pci_driver);
+       return pci_register_driver(&ohci1394_pci_driver);
 }
 
 module_init(ohci1394_init);