vserver 2.0 rc7
[linux-2.6.git] / drivers / ieee1394 / ohci1394.c
index 7c3f6e7..36e25ac 100644 (file)
@@ -162,7 +162,7 @@ printk(level "%s: " fmt "\n" , OHCI1394_DRIVER_NAME , ## args)
 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;
@@ -482,7 +482,9 @@ static void ohci_initialize(struct ti_ohci *ohci)
 
        /* 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);
@@ -497,10 +499,12 @@ 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);
+       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);
@@ -515,12 +519,6 @@ 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);
-
-       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);
@@ -540,6 +538,9 @@ 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
@@ -1029,6 +1030,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,
@@ -1037,22 +1040,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);
@@ -1065,9 +1052,37 @@ 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);
+
+                       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));
@@ -1117,9 +1132,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:
@@ -1289,8 +1304,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;
 
@@ -1915,8 +1932,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;
 
@@ -2545,6 +2564,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,
@@ -2706,7 +2729,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;
@@ -2769,7 +2792,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,
@@ -2778,7 +2801,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])
@@ -2908,7 +2931,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;
@@ -2919,7 +2942,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;
@@ -2963,9 +2988,19 @@ alloc_dma_rcv_ctx(struct ti_ohci *ohci, struct dma_rcv_ctx *d,
                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++) {
@@ -3002,20 +3037,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;
@@ -3058,7 +3079,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;
@@ -3080,8 +3103,17 @@ alloc_dma_trm_ctx(struct ti_ohci *ohci, struct dma_trm_ctx *d,
        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++) {
@@ -3353,10 +3385,19 @@ 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;
 
        if (request_irq(dev->irq, ohci_irq_handler, SA_SHIRQ,
@@ -3445,6 +3486,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,
@@ -3510,7 +3555,7 @@ static int ohci1394_pci_resume (struct pci_dev *pdev)
 }
 
 
-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
        {
@@ -3676,7 +3721,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);