[Linux1394-cvslog] rev 674 - trunk
Brought to you by:
aeb,
bencollins
From: SVN U. <ben...@li...> - 2002-11-16 20:30:04
|
Author: bencollins Date: 2002-11-16 15:29:30 -0500 (Sat, 16 Nov 2002) New Revision: 674 Modified: trunk/hosts.h trunk/ieee1394_core.c trunk/ieee1394_core.h trunk/ohci1394.c trunk/pcilynx.c Log: Patch from Manfred for cycle master check Modified: trunk/ieee1394_core.c ============================================================================== --- trunk/ieee1394_core.c (original) +++ trunk/ieee1394_core.c 2002-11-16 15:29:31.000000000 -0500 @@ -378,6 +378,7 @@ /* selfid stage did not complete without error */ HPSB_NOTICE("Error in SelfID stage, resetting"); host->in_bus_reset = 0; + /* this should work from ohci1394 now... */ hpsb_reset_bus(host, LONG_RESET); return; } else { @@ -403,7 +404,6 @@ host->is_irm = 0; } - host->reset_retries = 0; if (isroot) { host->driver->devctl(host, ACT_CYCLE_MASTER, 1); host->is_cycmst = 1; @@ -411,6 +411,32 @@ atomic_inc(&host->generation); host->in_bus_reset = 0; highlevel_host_reset(host); + + /* check for common cycle master error */ + hpsb_check_cycle_master(host); +} + + +void hpsb_check_cycle_master(struct hpsb_host *host) +{ + HPSB_INFO("Checking for host IRM cycle master"); + + /* check if host is IRM and not ROOT */ + if (host->is_irm && !host->is_root) { + HPSB_NOTICE("Host IRM is not root, resetting"); + if (host->reset_retries++ < 4) { + /* selfid stage did not yield valid cycle master */ + hpsb_reset_bus(host, LONG_RESET_FORCE_ROOT); + } else { + host->reset_retries = 0; + HPSB_NOTICE("Stopping out-of-control reset loop"); + HPSB_NOTICE("Warning - Cycle Master not set correctly"); + } + return; + } + + host->reset_retries = 0; + HPSB_INFO("Valid cycle master found"); } @@ -1215,6 +1241,7 @@ EXPORT_SYMBOL(hpsb_bus_reset); EXPORT_SYMBOL(hpsb_selfid_received); EXPORT_SYMBOL(hpsb_selfid_complete); +EXPORT_SYMBOL(hpsb_check_cycle_master); EXPORT_SYMBOL(hpsb_packet_sent); EXPORT_SYMBOL(hpsb_packet_received); EXPORT_SYMBOL(ieee1394_register_chardev); Modified: trunk/ohci1394.c ============================================================================== --- trunk/ohci1394.c (original) +++ trunk/ohci1394.c 2002-11-16 15:29:31.000000000 -0500 @@ -38,6 +38,7 @@ * * Known bugs: * . devctl BUS_RESET arg confusion (reset type or root holdoff?) + * added LONG_RESET_ROOT and SHORT_RESET_ROOT for root holdoff --kk */ /* @@ -75,6 +76,10 @@ * . Updated to 2.4.x module scheme (PCI aswell) * . Removed procfs support since it trashes random mem * . Config ROM generation + * + * Manfred Weihs <we...@ic...> + * . Reworked code for initiating bus resets + * (long, short, with or without hold-off) */ #include <linux/config.h> @@ -158,10 +163,6 @@ "$Rev$ Ben Collins <bco...@de...>"; /* Module Parameters */ -MODULE_PARM(attempt_root,"i"); -MODULE_PARM_DESC(attempt_root, "Attempt to make the host root (default = 0)."); -static int attempt_root = 0; - MODULE_PARM(phys_dma,"i"); MODULE_PARM_DESC(phys_dma, "Enable physical dma (default = 1)."); static int phys_dma = 1; @@ -338,8 +339,6 @@ DBGMSG(ohci->id, "SelfID complete"); - hpsb_selfid_complete(host, phyid, isroot); - return; } @@ -843,12 +842,57 @@ struct ti_ohci *ohci = host->hostdata; int retval = 0; unsigned long flags; + int phy_reg; switch (cmd) { case RESET_BUS: - DBGMSG(ohci->id, "devctl: Bus reset requested%s", - attempt_root ? " and attempting to become root" : ""); - set_phy_reg_mask (ohci, 1, 0x40 | (attempt_root ? 0x80 : 0)); + switch (arg) { + case SHORT_RESET: + phy_reg = get_phy_reg(ohci, 5); + phy_reg |= 0x40; + set_phy_reg(ohci, 5, phy_reg); /* set ISBR */ + break; + case LONG_RESET: + phy_reg = get_phy_reg(ohci, 1); + phy_reg |= 0x40; + set_phy_reg(ohci, 1, phy_reg); /* set IBR */ + break; + case SHORT_RESET_NO_FORCE_ROOT: + phy_reg = get_phy_reg(ohci, 1); + if (phy_reg & 0x80) { + phy_reg &= ~0x80; + set_phy_reg(ohci, 1, phy_reg); /* clear RHB */ + } + + phy_reg = get_phy_reg(ohci, 5); + phy_reg |= 0x40; + set_phy_reg(ohci, 5, phy_reg); /* set ISBR */ + break; + case LONG_RESET_NO_FORCE_ROOT: + phy_reg = get_phy_reg(ohci, 1); + phy_reg &= ~0x80; + phy_reg |= 0x40; + set_phy_reg(ohci, 1, phy_reg); /* clear RHB, set IBR */ + break; + case SHORT_RESET_FORCE_ROOT: + phy_reg = get_phy_reg(ohci, 1); + if (!(phy_reg & 0x80)) { + phy_reg |= 0x80; + set_phy_reg(ohci, 1, phy_reg); /* set RHB */ + } + + phy_reg = get_phy_reg(ohci, 5); + phy_reg |= 0x40; + set_phy_reg(ohci, 5, phy_reg); /* set ISBR */ + break; + case LONG_RESET_FORCE_ROOT: + phy_reg = get_phy_reg(ohci, 1); + phy_reg |= 0xc0; + set_phy_reg(ohci, 1, phy_reg); /* set RHB and IBR */ + break; + default: + retval = -1; + } break; case GET_CYCLE_COUNTER: @@ -1754,7 +1798,7 @@ unsigned long flags; /* Read and clear the interrupt event register. Don't clear - * the busReset event, though, this is done when we get the + * the busReset event, though. This is done when we get the * selfIDComplete interrupt. */ spin_lock_irqsave(&ohci->event_lock, flags); event = reg_read(ohci, OHCI1394_IntEventClear); @@ -1839,9 +1883,7 @@ } spin_unlock_irqrestore(&ohci->event_lock, flags); if (!host->in_bus_reset) { - DBGMSG(ohci->id, "irq_handler: Bus reset requested%s", - (attempt_root) ? " and attempting to become root" - : ""); + DBGMSG(ohci->id, "irq_handler: Bus reset requested"); /* Subsystem call */ hpsb_bus_reset(ohci->host); @@ -1912,8 +1954,6 @@ event &= ~OHCI1394_isochTx; } if (event & OHCI1394_selfIDComplete) { - event &= ~OHCI1394_selfIDComplete; - if (host->in_bus_reset) { node_id = reg_read(ohci, OHCI1394_NodeID); @@ -1962,10 +2002,13 @@ DBGMSG(ohci->id, "PhyReqFilter=%08x%08x\n", reg_read(ohci,OHCI1394_PhyReqFilterHiSet), reg_read(ohci,OHCI1394_PhyReqFilterLoSet)); + + hpsb_selfid_complete(host, phyid, isroot) } else PRINT(KERN_ERR, ohci->id, "SelfID received outside of bus reset sequence"); + event &= ~OHCI1394_selfIDComplete; selfid_not_valid: } Modified: trunk/ieee1394_core.h ============================================================================== --- trunk/ieee1394_core.h (original) +++ trunk/ieee1394_core.h 2002-11-16 15:29:32.000000000 -0500 @@ -140,6 +140,12 @@ */ void hpsb_selfid_complete(struct hpsb_host *host, int phyid, int isroot); +/* + * Check bus reset results to find cycle master + */ +void hpsb_check_cycle_master(struct hpsb_host *host); + + /* * Notify core of sending a packet. Ackcode is the ack code returned for async * transmits or ACKX_SEND_ERROR if the transmission failed completely; ACKX_NONE Modified: trunk/hosts.h ============================================================================== --- trunk/hosts.h (original) +++ trunk/hosts.h 2002-11-16 15:29:32.000000000 -0500 @@ -134,7 +134,13 @@ /* Short (arbitrated) reset -- only available on 1394a capable IEEE 1394 capable controllers */ - SHORT_RESET + SHORT_RESET, + + /* Variants, that set force_root before issueing the bus reset */ + LONG_RESET_FORCE_ROOT, SHORT_RESET_FORCE_ROOT, + + /* Variants, that clear force_root before issueing the bus reset */ + LONG_RESET_NO_FORCE_ROOT, SHORT_RESET_NO_FORCE_ROOT }; struct hpsb_host_driver { Modified: trunk/pcilynx.c ============================================================================== --- trunk/pcilynx.c (original) +++ trunk/pcilynx.c 2002-11-16 15:29:32.000000000 -0500 @@ -19,6 +19,16 @@ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/* + * Contributions: + * + * Manfred Weihs <we...@ic...> + * reading bus info block (containing GUID) from serial + * eeprom via i2c and storing it in config ROM + * Reworked code for initiating bus resets + * (long, short, with or without hold-off) + */ + #include <linux/config.h> #include <linux/kernel.h> #include <linux/slab.h> @@ -450,7 +460,7 @@ if (host->in_bus_reset) return; /* in bus reset again */ - if (isroot) reg_set_bits(lynx, LINK_CONTROL, LINK_CONTROL_CYCMASTER); + if (isroot) reg_set_bits(lynx, LINK_CONTROL, LINK_CONTROL_CYCMASTER); //FIXME: I do not think, we need this here reg_set_bits(lynx, LINK_CONTROL, LINK_CONTROL_RCV_CMP_VALID | LINK_CONTROL_TX_ASYNC_EN | LINK_CONTROL_RX_ASYNC_EN | LINK_CONTROL_CYCTIMEREN); @@ -563,6 +573,7 @@ struct hpsb_packet *packet; LIST_HEAD(packet_list); unsigned long flags; + int phy_reg; switch (cmd) { case RESET_BUS: @@ -571,21 +582,140 @@ break; } - if (arg) { - arg = 3 << 6; - } else { - arg = 1 << 6; - } - - retval = get_phy_reg(lynx, 1); - arg |= (retval == -1 ? 63 : retval); - retval = 0; - - PRINT(KERN_INFO, lynx->id, "resetting bus on request"); + switch (arg) { + case SHORT_RESET: + if (lynx->phyic.reg_1394a) { + phy_reg = get_phy_reg(lynx, 5); + if (phy_reg == -1) { + PRINT(KERN_ERR, lynx->id, "cannot reset bus, because read phy reg failed"); + retval = -1; + break; + } + phy_reg |= 0x40; + + PRINT(KERN_INFO, lynx->id, "resetting bus (short bus reset) on request"); + + lynx->selfid_size = -1; + lynx->phy_reg0 = -1; + set_phy_reg(lynx, 5, phy_reg); /* set ISBR */ + break; + } else { + PRINT(KERN_INFO, lynx->id, "cannot do short bus reset, because of old phy"); + /* fall through to long bus reset */ + } + case LONG_RESET: + phy_reg = get_phy_reg(lynx, 1); + if (phy_reg == -1) { + PRINT(KERN_ERR, lynx->id, "cannot reset bus, because read phy reg failed"); + retval = -1; + break; + } + phy_reg |= 0x40; + + PRINT(KERN_INFO, lynx->id, "resetting bus (long bus reset) on request"); + + lynx->selfid_size = -1; + lynx->phy_reg0 = -1; + set_phy_reg(lynx, 1, phy_reg); /* clear RHB, set IBR */ + break; + case SHORT_RESET_NO_FORCE_ROOT: + if (lynx->phyic.reg_1394a) { + phy_reg = get_phy_reg(lynx, 1); + if (phy_reg == -1) { + PRINT(KERN_ERR, lynx->id, "cannot reset bus, because read phy reg failed"); + retval = -1; + break; + } + if (phy_reg & 0x80) { + phy_reg &= ~0x80; + set_phy_reg(lynx, 1, phy_reg); /* clear RHB */ + } + + phy_reg = get_phy_reg(lynx, 5); + if (phy_reg == -1) { + PRINT(KERN_ERR, lynx->id, "cannot reset bus, because read phy reg failed"); + retval = -1; + break; + } + phy_reg |= 0x40; + + PRINT(KERN_INFO, lynx->id, "resetting bus (short bus reset, no force_root) on request"); + + lynx->selfid_size = -1; + lynx->phy_reg0 = -1; + set_phy_reg(lynx, 5, phy_reg); /* set ISBR */ + break; + } else { + PRINT(KERN_INFO, lynx->id, "cannot do short bus reset, because of old phy"); + /* fall through to long bus reset */ + } + case LONG_RESET_NO_FORCE_ROOT: + phy_reg = get_phy_reg(lynx, 1); + if (phy_reg == -1) { + PRINT(KERN_ERR, lynx->id, "cannot reset bus, because read phy reg failed"); + retval = -1; + break; + } + phy_reg &= ~0x80; + phy_reg |= 0x40; + + PRINT(KERN_INFO, lynx->id, "resetting bus (long bus reset, no force_root) on request"); + + lynx->selfid_size = -1; + lynx->phy_reg0 = -1; + set_phy_reg(lynx, 1, phy_reg); /* clear RHB, set IBR */ + break; + case SHORT_RESET_FORCE_ROOT: + if (lynx->phyic.reg_1394a) { + phy_reg = get_phy_reg(lynx, 1); + if (phy_reg == -1) { + PRINT(KERN_ERR, lynx->id, "cannot reset bus, because read phy reg failed"); + retval = -1; + break; + } + if (!(phy_reg & 0x80)) { + phy_reg |= 0x80; + set_phy_reg(lynx, 1, phy_reg); /* set RHB */ + } + + phy_reg = get_phy_reg(lynx, 5); + if (phy_reg == -1) { + PRINT(KERN_ERR, lynx->id, "cannot reset bus, because read phy reg failed"); + retval = -1; + break; + } + phy_reg |= 0x40; + + PRINT(KERN_INFO, lynx->id, "resetting bus (short bus reset, force_root set) on request"); + + lynx->selfid_size = -1; + lynx->phy_reg0 = -1; + set_phy_reg(lynx, 5, phy_reg); /* set ISBR */ + break; + } else { + PRINT(KERN_INFO, lynx->id, "cannot do short bus reset, because of old phy"); + /* fall through to long bus reset */ + } + case LONG_RESET_FORCE_ROOT: + phy_reg = get_phy_reg(lynx, 1); + if (phy_reg == -1) { + PRINT(KERN_ERR, lynx->id, "cannot reset bus, because read phy reg failed"); + retval = -1; + break; + } + phy_reg |= 0xc0; + + PRINT(KERN_INFO, lynx->id, "resetting bus (long bus reset, force_root set) on request"); + + lynx->selfid_size = -1; + lynx->phy_reg0 = -1; + set_phy_reg(lynx, 1, phy_reg); /* set IBR and RHB */ + break; + default: + PRINT(KERN_ERR, lynx->id, "unknown argument for reset_bus command %d", arg); + retval = -1; + } - lynx->selfid_size = -1; - lynx->phy_reg0 = -1; - set_phy_reg(lynx, 1, arg); break; case GET_CYCLE_COUNTER: |