aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/firewire/ohci.c
diff options
context:
space:
mode:
authorClemens Ladisch <clemens@ladisch.de>2011-01-10 11:21:35 -0500
committerStefan Richter <stefanr@s5r6.in-berlin.de>2011-01-23 06:31:00 -0500
commitf117a3e3004381ccadadc5156178c283815ca393 (patch)
treeafc150347ea9a50aec8ca7b4677d0267547d183b /drivers/firewire/ohci.c
parent6044565af458e7fa6e748bff437ecc49dea88d79 (diff)
firewire: ohci: log dead DMA contexts
When a DMA context goes into the dead state (and the controller thus stops working correctly), logging this error and the controller's error code might be helpful for debugging. Signed-off-by: Clemens Ladisch <clemens@ladisch.de> Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
Diffstat (limited to 'drivers/firewire/ohci.c')
-rw-r--r--drivers/firewire/ohci.c59
1 files changed, 55 insertions, 4 deletions
diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c
index bd3c61b6dd8d..c7394361afcb 100644
--- a/drivers/firewire/ohci.c
+++ b/drivers/firewire/ohci.c
@@ -208,9 +208,11 @@ struct fw_ohci {
208 struct context at_request_ctx; 208 struct context at_request_ctx;
209 struct context at_response_ctx; 209 struct context at_response_ctx;
210 210
211 u32 it_context_support;
211 u32 it_context_mask; /* unoccupied IT contexts */ 212 u32 it_context_mask; /* unoccupied IT contexts */
212 struct iso_context *it_context_list; 213 struct iso_context *it_context_list;
213 u64 ir_context_channels; /* unoccupied channels */ 214 u64 ir_context_channels; /* unoccupied channels */
215 u32 ir_context_support;
214 u32 ir_context_mask; /* unoccupied IR contexts */ 216 u32 ir_context_mask; /* unoccupied IR contexts */
215 struct iso_context *ir_context_list; 217 struct iso_context *ir_context_list;
216 u64 mc_channels; /* channels in use by the multichannel IR context */ 218 u64 mc_channels; /* channels in use by the multichannel IR context */
@@ -338,7 +340,7 @@ static void log_irqs(u32 evt)
338 !(evt & OHCI1394_busReset)) 340 !(evt & OHCI1394_busReset))
339 return; 341 return;
340 342
341 fw_notify("IRQ %08x%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", evt, 343 fw_notify("IRQ %08x%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", evt,
342 evt & OHCI1394_selfIDComplete ? " selfID" : "", 344 evt & OHCI1394_selfIDComplete ? " selfID" : "",
343 evt & OHCI1394_RQPkt ? " AR_req" : "", 345 evt & OHCI1394_RQPkt ? " AR_req" : "",
344 evt & OHCI1394_RSPkt ? " AR_resp" : "", 346 evt & OHCI1394_RSPkt ? " AR_resp" : "",
@@ -351,6 +353,7 @@ static void log_irqs(u32 evt)
351 evt & OHCI1394_cycle64Seconds ? " cycle64Seconds" : "", 353 evt & OHCI1394_cycle64Seconds ? " cycle64Seconds" : "",
352 evt & OHCI1394_cycleInconsistent ? " cycleInconsistent" : "", 354 evt & OHCI1394_cycleInconsistent ? " cycleInconsistent" : "",
353 evt & OHCI1394_regAccessFail ? " regAccessFail" : "", 355 evt & OHCI1394_regAccessFail ? " regAccessFail" : "",
356 evt & OHCI1394_unrecoverableError ? " unrecoverableError" : "",
354 evt & OHCI1394_busReset ? " busReset" : "", 357 evt & OHCI1394_busReset ? " busReset" : "",
355 evt & ~(OHCI1394_selfIDComplete | OHCI1394_RQPkt | 358 evt & ~(OHCI1394_selfIDComplete | OHCI1394_RQPkt |
356 OHCI1394_RSPkt | OHCI1394_reqTxComplete | 359 OHCI1394_RSPkt | OHCI1394_reqTxComplete |
@@ -1590,6 +1593,47 @@ static void at_context_transmit(struct context *ctx, struct fw_packet *packet)
1590 1593
1591} 1594}
1592 1595
1596static void detect_dead_context(struct fw_ohci *ohci,
1597 const char *name, unsigned int regs)
1598{
1599 u32 ctl;
1600
1601 ctl = reg_read(ohci, CONTROL_SET(regs));
1602 if (ctl & CONTEXT_DEAD) {
1603#ifdef CONFIG_FIREWIRE_OHCI_DEBUG
1604 fw_error("DMA context %s has stopped, error code: %s\n",
1605 name, evts[ctl & 0x1f]);
1606#else
1607 fw_error("DMA context %s has stopped, error code: %#x\n",
1608 name, ctl & 0x1f);
1609#endif
1610 }
1611}
1612
1613static void handle_dead_contexts(struct fw_ohci *ohci)
1614{
1615 unsigned int i;
1616 char name[8];
1617
1618 detect_dead_context(ohci, "ATReq", OHCI1394_AsReqTrContextBase);
1619 detect_dead_context(ohci, "ATRsp", OHCI1394_AsRspTrContextBase);
1620 detect_dead_context(ohci, "ARReq", OHCI1394_AsReqRcvContextBase);
1621 detect_dead_context(ohci, "ARRsp", OHCI1394_AsRspRcvContextBase);
1622 for (i = 0; i < 32; ++i) {
1623 if (!(ohci->it_context_support & (1 << i)))
1624 continue;
1625 sprintf(name, "IT%u", i);
1626 detect_dead_context(ohci, name, OHCI1394_IsoXmitContextBase(i));
1627 }
1628 for (i = 0; i < 32; ++i) {
1629 if (!(ohci->ir_context_support & (1 << i)))
1630 continue;
1631 sprintf(name, "IR%u", i);
1632 detect_dead_context(ohci, name, OHCI1394_IsoRcvContextBase(i));
1633 }
1634 /* TODO: maybe try to flush and restart the dead contexts */
1635}
1636
1593static u32 cycle_timer_ticks(u32 cycle_timer) 1637static u32 cycle_timer_ticks(u32 cycle_timer)
1594{ 1638{
1595 u32 ticks; 1639 u32 ticks;
@@ -1904,6 +1948,9 @@ static irqreturn_t irq_handler(int irq, void *data)
1904 fw_notify("isochronous cycle inconsistent\n"); 1948 fw_notify("isochronous cycle inconsistent\n");
1905 } 1949 }
1906 1950
1951 if (unlikely(event & OHCI1394_unrecoverableError))
1952 handle_dead_contexts(ohci);
1953
1907 if (event & OHCI1394_cycle64Seconds) { 1954 if (event & OHCI1394_cycle64Seconds) {
1908 spin_lock(&ohci->lock); 1955 spin_lock(&ohci->lock);
1909 update_bus_time(ohci); 1956 update_bus_time(ohci);
@@ -2141,7 +2188,9 @@ static int ohci_enable(struct fw_card *card,
2141 OHCI1394_selfIDComplete | 2188 OHCI1394_selfIDComplete |
2142 OHCI1394_regAccessFail | 2189 OHCI1394_regAccessFail |
2143 OHCI1394_cycle64Seconds | 2190 OHCI1394_cycle64Seconds |
2144 OHCI1394_cycleInconsistent | OHCI1394_cycleTooLong | 2191 OHCI1394_cycleInconsistent |
2192 OHCI1394_unrecoverableError |
2193 OHCI1394_cycleTooLong |
2145 OHCI1394_masterIntEnable; 2194 OHCI1394_masterIntEnable;
2146 if (param_debug & OHCI_PARAM_DEBUG_BUSRESETS) 2195 if (param_debug & OHCI_PARAM_DEBUG_BUSRESETS)
2147 irqs |= OHCI1394_busReset; 2196 irqs |= OHCI1394_busReset;
@@ -3207,15 +3256,17 @@ static int __devinit pci_probe(struct pci_dev *dev,
3207 3256
3208 reg_write(ohci, OHCI1394_IsoRecvIntMaskSet, ~0); 3257 reg_write(ohci, OHCI1394_IsoRecvIntMaskSet, ~0);
3209 ohci->ir_context_channels = ~0ULL; 3258 ohci->ir_context_channels = ~0ULL;
3210 ohci->ir_context_mask = reg_read(ohci, OHCI1394_IsoRecvIntMaskSet); 3259 ohci->ir_context_support = reg_read(ohci, OHCI1394_IsoRecvIntMaskSet);
3211 reg_write(ohci, OHCI1394_IsoRecvIntMaskClear, ~0); 3260 reg_write(ohci, OHCI1394_IsoRecvIntMaskClear, ~0);
3261 ohci->ir_context_mask = ohci->ir_context_support;
3212 ohci->n_ir = hweight32(ohci->ir_context_mask); 3262 ohci->n_ir = hweight32(ohci->ir_context_mask);
3213 size = sizeof(struct iso_context) * ohci->n_ir; 3263 size = sizeof(struct iso_context) * ohci->n_ir;
3214 ohci->ir_context_list = kzalloc(size, GFP_KERNEL); 3264 ohci->ir_context_list = kzalloc(size, GFP_KERNEL);
3215 3265
3216 reg_write(ohci, OHCI1394_IsoXmitIntMaskSet, ~0); 3266 reg_write(ohci, OHCI1394_IsoXmitIntMaskSet, ~0);
3217 ohci->it_context_mask = reg_read(ohci, OHCI1394_IsoXmitIntMaskSet); 3267 ohci->it_context_support = reg_read(ohci, OHCI1394_IsoXmitIntMaskSet);
3218 reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, ~0); 3268 reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, ~0);
3269 ohci->it_context_mask = ohci->it_context_support;
3219 ohci->n_it = hweight32(ohci->it_context_mask); 3270 ohci->n_it = hweight32(ohci->it_context_mask);
3220 size = sizeof(struct iso_context) * ohci->n_it; 3271 size = sizeof(struct iso_context) * ohci->n_it;
3221 ohci->it_context_list = kzalloc(size, GFP_KERNEL); 3272 ohci->it_context_list = kzalloc(size, GFP_KERNEL);