Example #1
0
/**
 * e100_run_diag - main test execution handler - checks mask of requests and calls the diag routines  
 * @dev: atapter's net device data struct
 * @test_info: array with test request mask also used to store test results
 *
 * RETURNS: updated flags field of struct ethtool_test
 */
u32
e100_run_diag(struct net_device *dev, u64 *test_info, u32 flags)
{
	struct e100_private* bdp = dev->priv;
	u8 test_result = 0;

	if (!e100_get_link_state(bdp)) {
		test_result = ETH_TEST_FL_FAILED;
		test_info[test_link] = true;
	}
	if (!e100_diag_eeprom(dev)) {
		test_result = ETH_TEST_FL_FAILED;
		test_info[test_eeprom] = true;
	}
	if (flags & ETH_TEST_FL_OFFLINE) {
		u8 fail_mask;
		if (netif_running(dev)) {
			spin_lock_bh(&dev->xmit_lock);
			e100_close(dev);
			spin_unlock_bh(&dev->xmit_lock);
		}
		if (e100_diag_selftest(dev)) {
			test_result = ETH_TEST_FL_FAILED;
			test_info[test_self_test] = true;
		}

		fail_mask = e100_diag_loopback(dev);
		if (fail_mask) {
			test_result = ETH_TEST_FL_FAILED;
			if (fail_mask & PHY_LOOPBACK)
				test_info[test_loopback_phy] = true;
			if (fail_mask & MAC_LOOPBACK)
				test_info[test_loopback_mac] = true;
		}

		test_info[cable_diag] = e100_cable_diag(bdp);
		/* Need hw init regardless of netif_running */
		e100_hw_init(bdp);
		if (netif_running(dev)) {
			e100_open(dev);
		}
	}
	else {
		test_info[test_self_test] = false;
		test_info[test_loopback_phy] = false;
		test_info[test_loopback_mac] = false;
		test_info[cable_diag] = false;
	}

	return flags | test_result;
}
Example #2
0
/* 
 * Procedure: e100_update_link_state
 * 
 * Description: This routine updates the link status of the adapter,
 * 		also considering netif_running
 *
 * Arguments:  bdp - Pointer to the e100_private structure for the board
 *		    
 *
 * Returns: true - If a link is found
 *		false - If there is no link
 *
 */
unsigned char
e100_update_link_state(struct e100_private *bdp)
{
	unsigned char link;

	/* Logical AND PHY link & netif_running */
	link = e100_get_link_state(bdp) && netif_running(bdp->device);

	if (link) {
		if (!netif_carrier_ok(bdp->device))
			netif_carrier_on(bdp->device);
	} else {
		if (netif_carrier_ok(bdp->device))
			netif_carrier_off(bdp->device);
	}

	return link;
}
Example #3
0
static int
e100_cable_diag(struct e100_private *bdp)
{	
	int saved_open_circut = 0xffff;
	int saved_short_circut = 0xffff;
	int saved_distance = 0xffff;
	int saved_same = 0;
	int cable_status = E100_CABLE_UNKNOWN;
	int i;
	
	/* If we have link, */	
	if (e100_get_link_state(bdp))
		return E100_CABLE_OK;
	
	if (bdp->rev_id < D102_REV_ID)
		return E100_CABLE_UNKNOWN;

	/* Disable MDI/MDI-X auto switching */
        e100_mdi_write(bdp, MII_NCONFIG, bdp->phy_addr,
		MDI_MDIX_RESET_ALL_MASK);
	/* Set to 100 Full as required by cable test */
	e100_mdi_write(bdp, MII_BMCR, bdp->phy_addr,
		BMCR_SPEED100 | BMCR_FULLDPLX);

	/* Test up to 100 times */
	for (i = 0; i < 100; i++) {
		u16 ctrl_reg;
		int distance, open_circut, short_circut, near_end;

		/* Enable and execute cable test */
		e100_mdi_write(bdp, HWI_CONTROL_REG, bdp->phy_addr,
			(HWI_TEST_ENABLE | HWI_TEST_EXECUTE));
		/* Wait for cable test finished */
		set_current_state(TASK_UNINTERRUPTIBLE);
		schedule_timeout(HZ/100 + 1);
		/* Read results */
		e100_mdi_read(bdp, HWI_CONTROL_REG, bdp->phy_addr, &ctrl_reg);
		distance = ctrl_reg & HWI_TEST_DISTANCE;
		open_circut = ctrl_reg & HWI_TEST_HIGHZ_PROBLEM;
		short_circut = ctrl_reg & HWI_TEST_LOWZ_PROBLEM;

		if ((distance == saved_distance) &&
	    	    (open_circut == saved_open_circut) &&
	    	    (short_circut == saved_short_circut)) 
			saved_same++;
		else {
			saved_same = 0;
			saved_distance = distance;
			saved_open_circut = open_circut;
			saved_short_circut = short_circut;
		}
		/* If results are the same 3 times */
		if (saved_same == 3) {
			near_end = ((distance * HWI_REGISTER_GRANULARITY) <
			       HWI_NEAR_END_BOUNDARY);
			if (open_circut)
				cable_status = (near_end) ? 
					E100_CABLE_OPEN_NEAR : E100_CABLE_OPEN_FAR;
			if (short_circut)
				cable_status = (near_end) ?
					E100_CABLE_SHORT_NEAR : E100_CABLE_SHORT_FAR;
			break;
		}
	}
	/* Reset cable test */
        e100_mdi_write(bdp, HWI_CONTROL_REG, bdp->phy_addr,					       HWI_RESET_ALL_MASK);
	return cable_status;
}