qlge: bugfix: Pad outbound frames smaller than 60 bytes.
[safe/jmp/linux-2.6] / drivers / ieee1394 / ohci1394.c
index 0690469..65c1429 100644 (file)
@@ -1723,6 +1723,8 @@ struct ohci_iso_xmit {
        struct dma_prog_region prog;
        struct ohci1394_iso_tasklet task;
        int task_active;
+       int last_cycle;
+       atomic_t skips;
 
        u32 ContextControlSet;
        u32 ContextControlClear;
@@ -1759,6 +1761,8 @@ static int ohci_iso_xmit_init(struct hpsb_iso *iso)
        iso->hostdata = xmit;
        xmit->ohci = iso->host->hostdata;
        xmit->task_active = 0;
+       xmit->last_cycle = -1;
+       atomic_set(&iso->skips, 0);
 
        dma_prog_region_init(&xmit->prog);
 
@@ -1856,6 +1860,26 @@ static void ohci_iso_xmit_task(unsigned long data)
                /* parse cycle */
                cycle = le32_to_cpu(cmd->output_last.status) & 0x1FFF;
 
+               if (xmit->last_cycle > -1) {
+                       int cycle_diff = cycle - xmit->last_cycle;
+                       int skip;
+
+                       /* unwrap */
+                       if (cycle_diff < 0) {
+                               cycle_diff += 8000;
+                               if (cycle_diff < 0)
+                                       PRINT(KERN_ERR, "bogus cycle diff %d\n",
+                                             cycle_diff);
+                       }
+
+                       skip = cycle_diff - 1;
+                       if (skip > 0) {
+                               DBGMSG("skipped %d cycles without packet loss", skip);
+                               atomic_add(skip, &iso->skips);
+                       }
+               }
+               xmit->last_cycle = cycle;
+
                /* tell the subsystem the packet has gone out */
                hpsb_iso_packet_sent(iso, cycle, event != 0x11);
 
@@ -1943,6 +1967,16 @@ static int ohci_iso_xmit_queue(struct hpsb_iso *iso, struct hpsb_iso_packet_info
        prev->output_last.branchAddress = cpu_to_le32(
                dma_prog_region_offset_to_bus(&xmit->prog, sizeof(struct iso_xmit_cmd) * next_i) | 3);
 
+       /*
+        * Link the skip address to this descriptor itself. This causes a
+        * context to skip a cycle whenever lost cycles or FIFO overruns occur,
+        * without dropping the data at that point the application should then
+        * decide whether this is an error condition or not. Some protocols
+        * can deal with this by dropping some rate-matching padding packets.
+        */
+       next->output_more_immediate.branchAddress =
+                       prev->output_last.branchAddress;
+
        /* disable interrupt, unless required by the IRQ interval */
        if (prev_i % iso->irq_interval) {
                prev->output_last.control &= cpu_to_le32(~(3 << 20)); /* no interrupt */
@@ -2939,7 +2973,7 @@ alloc_dma_trm_ctx(struct ti_ohci *ohci, struct dma_trm_ctx *d,
        return 0;
 }
 
-static void ohci_set_hw_config_rom(struct hpsb_host *host, quadlet_t *config_rom)
+static void ohci_set_hw_config_rom(struct hpsb_host *host, __be32 *config_rom)
 {
        struct ti_ohci *ohci = host->hostdata;
 
@@ -3165,15 +3199,16 @@ static int __devinit ohci1394_pci_probe(struct pci_dev *dev,
        /* Now enable LPS, which we need in order to start accessing
         * most of the registers.  In fact, on some cards (ALI M5251),
         * accessing registers in the SClk domain without LPS enabled
-        * will lock up the machine.  Wait 50msec to make sure we have
-        * full link enabled.  */
+        * will lock up the machine. */
        reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_LPS);
 
        /* Disable and clear interrupts */
        reg_write(ohci, OHCI1394_IntEventClear, 0xffffffff);
        reg_write(ohci, OHCI1394_IntMaskClear, 0xffffffff);
 
-       mdelay(50);
+       /* Flush MMIO writes and wait to make sure we have full link enabled. */
+       reg_read(ohci, OHCI1394_Version);
+       msleep(50);
 
        /* Determine the number of available IR and IT contexts. */
        ohci->nb_iso_rcv_ctx =
@@ -3199,8 +3234,9 @@ static int __devinit ohci1394_pci_probe(struct pci_dev *dev,
         * we need to get to that "no event", so enough should be initialized
         * by that point.
         */
-       if (request_irq(dev->irq, ohci_irq_handler, IRQF_SHARED,
-                        OHCI1394_DRIVER_NAME, ohci)) {
+       err = request_irq(dev->irq, ohci_irq_handler, IRQF_SHARED,
+                         OHCI1394_DRIVER_NAME, ohci);
+       if (err) {
                PRINT_G(KERN_ERR, "Failed to allocate interrupt %d", dev->irq);
                goto err;
        }
@@ -3347,6 +3383,7 @@ static int ohci1394_pci_suspend(struct pci_dev *dev, pm_message_t state)
        ohci_devctl(ohci->host, RESET_BUS, LONG_RESET_NO_FORCE_ROOT);
        ohci_soft_reset(ohci);
 
+       free_irq(dev->irq, ohci);
        err = pci_save_state(dev);
        if (err) {
                PRINT(KERN_ERR, "pci_save_state failed with %d", err);
@@ -3386,7 +3423,16 @@ static int ohci1394_pci_resume(struct pci_dev *dev)
        reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_LPS);
        reg_write(ohci, OHCI1394_IntEventClear, 0xffffffff);
        reg_write(ohci, OHCI1394_IntMaskClear, 0xffffffff);
-       mdelay(50);
+       reg_read(ohci, OHCI1394_Version);
+       msleep(50);
+
+       err = request_irq(dev->irq, ohci_irq_handler, IRQF_SHARED,
+                         OHCI1394_DRIVER_NAME, ohci);
+       if (err) {
+               PRINT_G(KERN_ERR, "Failed to allocate interrupt %d", dev->irq);
+               return err;
+       }
+
        ohci_initialize(ohci);
 
        hpsb_resume_host(ohci->host);