]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/firewire/fw-ohci.c
PCI: include linux/pm_wakeup.h for device_set_wakeup_capable
[linux-2.6-omap-h63xx.git] / drivers / firewire / fw-ohci.c
index b564b1aae52f9c277b1353babcb433dc13aa6cd8..4f02c55f13e15131b95bc615e540e2931ad63d96 100644 (file)
@@ -178,9 +178,10 @@ struct fw_ohci {
        struct tasklet_struct bus_reset_tasklet;
        int node_id;
        int generation;
-       int request_generation;
+       int request_generation; /* for timestamping incoming requests */
        u32 bus_seconds;
        bool old_uninorth;
+       bool bus_reset_packet_quirk;
 
        /*
         * Spinlock for accessing fw_ohci data.  Never call out of
@@ -240,24 +241,32 @@ static char ohci_driver_name[] = KBUILD_MODNAME;
 
 #ifdef CONFIG_FIREWIRE_OHCI_DEBUG
 
-#define OHCI_PARAM_DEBUG_IRQS          1
+#define OHCI_PARAM_DEBUG_AT_AR         1
 #define OHCI_PARAM_DEBUG_SELFIDS       2
-#define OHCI_PARAM_DEBUG_AT_AR         4
+#define OHCI_PARAM_DEBUG_IRQS          4
+#define OHCI_PARAM_DEBUG_BUSRESETS     8 /* only effective before chip init */
 
 static int param_debug;
 module_param_named(debug, param_debug, int, 0644);
 MODULE_PARM_DESC(debug, "Verbose logging (default = 0"
-       ", IRQs = "             __stringify(OHCI_PARAM_DEBUG_IRQS)
-       ", self-IDs = "         __stringify(OHCI_PARAM_DEBUG_SELFIDS)
        ", AT/AR events = "     __stringify(OHCI_PARAM_DEBUG_AT_AR)
+       ", self-IDs = "         __stringify(OHCI_PARAM_DEBUG_SELFIDS)
+       ", IRQs = "             __stringify(OHCI_PARAM_DEBUG_IRQS)
+       ", busReset events = "  __stringify(OHCI_PARAM_DEBUG_BUSRESETS)
        ", or a combination, or all = -1)");
 
 static void log_irqs(u32 evt)
 {
-       if (likely(!(param_debug & OHCI_PARAM_DEBUG_IRQS)))
+       if (likely(!(param_debug &
+                       (OHCI_PARAM_DEBUG_IRQS | OHCI_PARAM_DEBUG_BUSRESETS))))
                return;
 
-       printk(KERN_DEBUG KBUILD_MODNAME ": IRQ %08x%s%s%s%s%s%s%s%s%s%s%s\n",
+       if (!(param_debug & OHCI_PARAM_DEBUG_IRQS) &&
+           !(evt & OHCI1394_busReset))
+               return;
+
+       printk(KERN_DEBUG KBUILD_MODNAME ": IRQ "
+              "%08x%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
               evt,
               evt & OHCI1394_selfIDComplete    ? " selfID"             : "",
               evt & OHCI1394_RQPkt             ? " AR_req"             : "",
@@ -269,11 +278,14 @@ static void log_irqs(u32 evt)
               evt & OHCI1394_postedWriteErr    ? " postedWriteErr"     : "",
               evt & OHCI1394_cycleTooLong      ? " cycleTooLong"       : "",
               evt & OHCI1394_cycle64Seconds    ? " cycle64Seconds"     : "",
+              evt & OHCI1394_regAccessFail     ? " regAccessFail"      : "",
+              evt & OHCI1394_busReset          ? " busReset"           : "",
               evt & ~(OHCI1394_selfIDComplete | OHCI1394_RQPkt |
                       OHCI1394_RSPkt | OHCI1394_reqTxComplete |
                       OHCI1394_respTxComplete | OHCI1394_isochRx |
                       OHCI1394_isochTx | OHCI1394_postedWriteErr |
-                      OHCI1394_cycleTooLong | OHCI1394_cycle64Seconds)
+                      OHCI1394_cycleTooLong | OHCI1394_cycle64Seconds |
+                      OHCI1394_regAccessFail | OHCI1394_busReset)
                                                ? " ?"                  : "");
 }
 
@@ -291,13 +303,13 @@ static char _p(u32 *s, int shift)
        return port[*s >> shift & 3];
 }
 
-static void log_selfids(int generation, int self_id_count, u32 *s)
+static void log_selfids(int node_id, int generation, int self_id_count, u32 *s)
 {
        if (likely(!(param_debug & OHCI_PARAM_DEBUG_SELFIDS)))
                return;
 
-       printk(KERN_DEBUG KBUILD_MODNAME ": %d selfIDs, generation %d\n",
-              self_id_count, generation);
+       printk(KERN_DEBUG KBUILD_MODNAME ": %d selfIDs, generation %d, "
+              "local node ID %04x\n", self_id_count, generation, node_id);
 
        for (; self_id_count--; ++s)
                if ((*s & 1 << 23) == 0)
@@ -360,6 +372,12 @@ static void log_ar_at_event(char dir, int speed, u32 *header, int evt)
        if (unlikely(evt >= ARRAY_SIZE(evts)))
                        evt = 0x1f;
 
+       if (evt == OHCI1394_evt_bus_reset) {
+               printk(KERN_DEBUG "A%c evt_bus_reset, generation %d\n",
+                      dir, (header[2] >> 16) & 0xff);
+               return;
+       }
+
        if (header[0] == ~header[1]) {
                printk(KERN_DEBUG "A%c %s, %s, %08x\n",
                       dir, evts[evt], phys[header[0] >> 30 & 0x3],
@@ -406,7 +424,7 @@ static void log_ar_at_event(char dir, int speed, u32 *header, int evt)
 #else
 
 #define log_irqs(evt)
-#define log_selfids(generation, self_id_count, sid)
+#define log_selfids(node_id, generation, self_id_count, sid)
 #define log_ar_at_event(dir, speed, header, evt)
 
 #endif /* CONFIG_FIREWIRE_OHCI_DEBUG */
@@ -494,6 +512,7 @@ static __le32 *handle_ar_packet(struct ar_context *ctx, __le32 *buffer)
        struct fw_ohci *ohci = ctx->ohci;
        struct fw_packet p;
        u32 status, length, tcode;
+       int evt;
 
        p.header[0] = cond_le32_to_cpu(buffer[0]);
        p.header[1] = cond_le32_to_cpu(buffer[1]);
@@ -536,13 +555,14 @@ static __le32 *handle_ar_packet(struct ar_context *ctx, __le32 *buffer)
        /* FIXME: What to do about evt_* errors? */
        length = (p.header_length + p.payload_length + 3) / 4;
        status = cond_le32_to_cpu(buffer[length]);
+       evt    = (status >> 16) & 0x1f;
 
-       p.ack        = ((status >> 16) & 0x1f) - 16;
+       p.ack        = evt - 16;
        p.speed      = (status >> 21) & 0x7;
        p.timestamp  = status & 0xffff;
        p.generation = ohci->request_generation;
 
-       log_ar_at_event('R', p.speed, p.header, status >> 16 & 0x1f);
+       log_ar_at_event('R', p.speed, p.header, evt);
 
        /*
         * The OHCI bus reset handler synthesizes a phy packet with
@@ -552,14 +572,19 @@ static __le32 *handle_ar_packet(struct ar_context *ctx, __le32 *buffer)
         * generation.  We only need this for requests; for responses
         * we use the unique tlabel for finding the matching
         * request.
+        *
+        * Alas some chips sometimes emit bus reset packets with a
+        * wrong generation.  We set the correct generation for these
+        * at a slightly incorrect time (in bus_reset_tasklet).
         */
-
-       if (p.ack + 16 == 0x09)
-               ohci->request_generation = (p.header[2] >> 16) & 0xff;
-       else if (ctx == &ohci->ar_request_ctx)
+       if (evt == OHCI1394_evt_bus_reset) {
+               if (!ohci->bus_reset_packet_quirk)
+                       ohci->request_generation = (p.header[2] >> 16) & 0xff;
+       } else if (ctx == &ohci->ar_request_ctx) {
                fw_core_handle_request(&ohci->card, &p);
-       else
+       } else {
                fw_core_handle_response(&ohci->card, &p);
+       }
 
        return buffer + length + 1;
 }
@@ -946,8 +971,19 @@ at_context_queue_packet(struct context *ctx, struct fw_packet *packet)
                                     DESCRIPTOR_IRQ_ALWAYS |
                                     DESCRIPTOR_BRANCH_ALWAYS);
 
-       /* FIXME: Document how the locking works. */
-       if (ohci->generation != packet->generation) {
+       /*
+        * If the controller and packet generations don't match, we need to
+        * bail out and try again.  If IntEvent.busReset is set, the AT context
+        * is halted, so appending to the context and trying to run it is
+        * futile.  Most controllers do the right thing and just flush the AT
+        * queue (per section 7.2.3.2 of the OHCI 1.1 specification), but
+        * some controllers (like a JMicron JMB381 PCI-e) misbehave and wind
+        * up stalling out.  So we just bail out in software and try again
+        * later, and everyone is happy.
+        * FIXME: Document how the locking works.
+        */
+       if (ohci->generation != packet->generation ||
+           reg_read(ohci, OHCI1394_IntEventSet) & OHCI1394_busReset) {
                if (packet->payload_length > 0)
                        dma_unmap_single(ohci->card.device, payload_bus,
                                         packet->payload_length, DMA_TO_DEVICE);
@@ -1255,6 +1291,9 @@ static void bus_reset_tasklet(unsigned long data)
        context_stop(&ohci->at_response_ctx);
        reg_write(ohci, OHCI1394_IntEventClear, OHCI1394_busReset);
 
+       if (ohci->bus_reset_packet_quirk)
+               ohci->request_generation = generation;
+
        /*
         * This next bit is unrelated to the AT context stuff but we
         * have to do it under the spinlock also.  If a new config rom
@@ -1296,7 +1335,8 @@ static void bus_reset_tasklet(unsigned long data)
                dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE,
                                  free_rom, free_rom_bus);
 
-       log_selfids(generation, self_id_count, ohci->self_id_buffer);
+       log_selfids(ohci->node_id, generation,
+                   self_id_count, ohci->self_id_buffer);
 
        fw_core_handle_bus_reset(&ohci->card, ohci->node_id, generation,
                                 self_id_count, ohci->self_id_buffer);
@@ -1313,7 +1353,8 @@ static irqreturn_t irq_handler(int irq, void *data)
        if (!event || !~event)
                return IRQ_NONE;
 
-       reg_write(ohci, OHCI1394_IntEventClear, event);
+       /* busReset must not be cleared yet, see OHCI 1.1 clause 7.2.3.2 */
+       reg_write(ohci, OHCI1394_IntEventClear, event & ~OHCI1394_busReset);
        log_irqs(event);
 
        if (event & OHCI1394_selfIDComplete)
@@ -1349,6 +1390,10 @@ static irqreturn_t irq_handler(int irq, void *data)
                iso_event &= ~(1 << i);
        }
 
+       if (unlikely(event & OHCI1394_regAccessFail))
+               fw_error("Register access failure - "
+                        "please notify linux1394-devel@lists.sf.net\n");
+
        if (unlikely(event & OHCI1394_postedWriteErr))
                fw_error("PCI posted write error\n");
 
@@ -1388,6 +1433,8 @@ static int ohci_enable(struct fw_card *card, u32 *config_rom, size_t length)
 {
        struct fw_ohci *ohci = fw_ohci(card);
        struct pci_dev *dev = to_pci_dev(card->device);
+       u32 lps;
+       int i;
 
        if (software_reset(ohci)) {
                fw_error("Failed to reset ohci card.\n");
@@ -1399,13 +1446,24 @@ static int ohci_enable(struct fw_card *card, u32 *config_rom, size_t length)
         * 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.
+        * full link enabled.  However, with some cards (well, at least
+        * a JMicron PCIe card), we have to try again sometimes.
         */
        reg_write(ohci, OHCI1394_HCControlSet,
                  OHCI1394_HCControl_LPS |
                  OHCI1394_HCControl_postedWriteEnable);
        flush_writes(ohci);
-       msleep(50);
+
+       for (lps = 0, i = 0; !lps && i < 3; i++) {
+               msleep(50);
+               lps = reg_read(ohci, OHCI1394_HCControlSet) &
+                     OHCI1394_HCControl_LPS;
+       }
+
+       if (!lps) {
+               fw_error("Failed to set Link Power Status\n");
+               return -EIO;
+       }
 
        reg_write(ohci, OHCI1394_HCControlClear,
                  OHCI1394_HCControl_noByteSwapData);
@@ -1433,7 +1491,10 @@ static int ohci_enable(struct fw_card *card, u32 *config_rom, size_t length)
                  OHCI1394_reqTxComplete | OHCI1394_respTxComplete |
                  OHCI1394_isochRx | OHCI1394_isochTx |
                  OHCI1394_postedWriteErr | OHCI1394_cycleTooLong |
-                 OHCI1394_cycle64Seconds | OHCI1394_masterIntEnable);
+                 OHCI1394_cycle64Seconds | OHCI1394_regAccessFail |
+                 OHCI1394_masterIntEnable);
+       if (param_debug & OHCI_PARAM_DEBUG_BUSRESETS)
+               reg_write(ohci, OHCI1394_IntMaskSet, OHCI1394_busReset);
 
        /* Activate link_on bit and contender bit in our self ID packets.*/
        if (ohci_update_phy_reg(card, 4, 0,
@@ -2284,8 +2345,6 @@ pci_probe(struct pci_dev *dev, const struct pci_device_id *ent)
        int err;
        size_t size;
 
-       ohci_pmac_on(dev);
-
        ohci = kzalloc(sizeof(*ohci), GFP_KERNEL);
        if (ohci == NULL) {
                fw_error("Could not malloc fw_ohci data.\n");
@@ -2294,6 +2353,8 @@ pci_probe(struct pci_dev *dev, const struct pci_device_id *ent)
 
        fw_card_initialize(&ohci->card, &ohci_driver, &dev->dev);
 
+       ohci_pmac_on(dev);
+
        err = pci_enable_device(dev);
        if (err) {
                fw_error("Failed to enable OHCI hardware.\n");
@@ -2308,6 +2369,8 @@ pci_probe(struct pci_dev *dev, const struct pci_device_id *ent)
        ohci->old_uninorth = dev->vendor == PCI_VENDOR_ID_APPLE &&
                             dev->device == PCI_DEVICE_ID_APPLE_UNI_N_FW;
 #endif
+       ohci->bus_reset_packet_quirk = dev->vendor == PCI_VENDOR_ID_TI;
+
        spin_lock_init(&ohci->lock);
 
        tasklet_init(&ohci->bus_reset_tasklet,
@@ -2395,6 +2458,7 @@ pci_probe(struct pci_dev *dev, const struct pci_device_id *ent)
        pci_disable_device(dev);
  fail_free:
        kfree(&ohci->card);
+       ohci_pmac_off(dev);
 
        return err;
 }