Skip to content

Commit

Permalink
Adding nic_util to packman package
Browse files Browse the repository at this point in the history
Summary: Added Nic_util to packman package. Also made some changes in Nic_util debug code.

Differential Revision: D22386920

fbshipit-source-id: b704d811a9e654d433c30849a58516375f9e1c1d
  • Loading branch information
Rajan Kumar authored and facebook-github-bot committed Aug 21, 2020
1 parent ff1ba4e commit 8865126
Showing 1 changed file with 147 additions and 18 deletions.
165 changes: 147 additions & 18 deletions fboss/util/nic_util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@
#include <sysexits.h>
#include <unistd.h>

/*
* CLI:
* nic_util --nic_read_reg --reg_addr <register-address> [--verbose]
* nic_util --nic_write_reg --reg_addr <register-address> --reg_val <data-value> [--verbose]
*/
DEFINE_bool(nic_read_reg, false,
"Read register from NIC i210, use with --reg_addr");
DEFINE_int32(reg_addr, 0,
Expand All @@ -17,6 +22,11 @@ DEFINE_bool(nic_write_reg, false,
DEFINE_uint32(reg_val, 0,
"NIC i210 register value");

/*
* CLI:
* nic_util --nic_phy_read_reg --phy_reg_addr <register-address> [--phy_page <phy-page-id>] [--verbose]
* nic_util --nic_phy_write_reg --phy_reg_addr <register-address> --phy_reg_val <data-value> [--phy_page <phy-page-id>] [--verbose]
*/
DEFINE_bool(nic_phy_read_reg, false,
"Read register from NIC i210 PHY, use with --phy_reg_addr and --phy_page");
DEFINE_int32(phy_reg_addr, 0,
Expand All @@ -28,12 +38,47 @@ DEFINE_uint32(phy_reg_val, 0,
DEFINE_uint32(phy_page, -1,
"NIC i210 PHY Page id");

/*
* CLI:
* nic_util --nic_link_show_config
* nic_util --nic_link_show_status
*/
DEFINE_bool(nic_link_show_config, false,
"Read link config from NIC i210");
DEFINE_bool(nic_link_show_status, false,
"Read link status from NIC i210");

/*
* CLI:
* nic_util --nic_reset [--soft_reset | --phy_reset | --device_reset]
*/
DEFINE_bool(nic_reset, false,
"Reset the NIC i210, use with --soft_reset, --phy_reset and --device_reset");
DEFINE_bool(soft_reset, false,
"Software reset for NIC i210");
DEFINE_bool(phy_reset, false,
"Internal PHY reset for NIC i210");
DEFINE_bool(device_reset, false,
"Device reset for NIC i210");

/*
* CLI:
* Extra option: --verbose
*/
DEFINE_bool(verbose, false, "detailed prints");

/*
* Intel NIC I210 register definition
* For full list of register definition pl refer to I210 spec from Intel site:
* https://www.intel.com/content/www/us/en/design/products-and-solutions/networking-and-io/ethernet-controller-i210-i211/technical-library.html
*/
constexpr uint16_t kDeviceControlRegister = 0x0000;
constexpr uint16_t kDeviceStatusRegister = 0x0008;
constexpr uint16_t kExtendedDeviceControlRegister = 0x0018;
constexpr uint16_t kMdiControlRegister = 0x0020;
constexpr uint16_t kCopperSwitchControlRegister = 0x0034;
constexpr uint16_t kPcsConfigurationRegister = 0x4200;
constexpr uint16_t kPcsLinkStatusRegister = 0x420c;

/*
* map_info_s
Expand All @@ -45,6 +90,8 @@ struct nic_info_s {
unsigned char *mapAddr;
};

bool verbosePrint = false;

/*
* nicReadRegInternal
*
Expand Down Expand Up @@ -86,7 +133,9 @@ void nicWriteRegInternal(struct nic_info_s *pNic, uint32_t regAddr, uint32_t reg
bool nicShowReg(struct nic_info_s *pNic, uint32_t regAddr) {

unsigned char *ptr = pNic->mapAddr;
printf("Map address: 0x%lx\n", (unsigned long)ptr);
if (verbosePrint) {
printf("Map address: 0x%lx\n", (unsigned long)ptr);
}
unsigned int regVal = nicReadRegInternal(pNic, regAddr);
printf("Reg 0x%x = 0x%.8x\n", regAddr, regVal);
return true;
Expand All @@ -101,7 +150,9 @@ bool nicShowReg(struct nic_info_s *pNic, uint32_t regAddr) {
bool nicWriteReg(struct nic_info_s *pNic, uint32_t regAddr, uint32_t regVal) {

unsigned char *ptr = pNic->mapAddr;
printf("Map address: 0x%lx\n", (unsigned long)ptr);
if (verbosePrint) {
printf("Map address: 0x%lx\n", (unsigned long)ptr);
}
nicWriteRegInternal(pNic, regAddr, regVal);
regVal = nicReadRegInternal(pNic, regAddr);
printf("Reg 0x%x = 0x%.8x\n", regAddr, regVal);
Expand Down Expand Up @@ -149,7 +200,9 @@ bool nicPhyReadReg(
uint32_t mdioRegVal;

unsigned char *ptr = pNic->mapAddr;
printf("Map address: 0x%lx\n", (unsigned long)ptr);
if (verbosePrint) {
printf("Map address: 0x%lx\n", (unsigned long)ptr);
}

// NIC register 0x20 is MDIO control register
ptr += kMdiControlRegister;
Expand Down Expand Up @@ -202,7 +255,10 @@ bool nicPhyWriteReg(
uint32_t iteration=0, maxIterations=100;

unsigned char *ptr = pNic->mapAddr;
printf("Map address: 0x%lx\n", (unsigned long)ptr);
if (verbosePrint) {
printf("Map address: 0x%lx\n", (unsigned long)ptr);
}

// NIC register 0x20 is MDIO control register
ptr += kMdiControlRegister;

Expand Down Expand Up @@ -258,30 +314,30 @@ bool nicLinkShowConfig(struct nic_info_s *pNic) {
printf("Map address: 0x%lx\n", (unsigned long)ptr);
printf("i210 MAC Config:\n");
// Read Device Control Register
regVal = nicReadRegInternal(pNic, 0);
regVal = nicReadRegInternal(pNic, kDeviceControlRegister);
printf(" Set Link Up: %s\n", (regVal & 0x40) ? "Up" : "Down");
printf(" Link speed: %s\n", speedString[((regVal>>8) & 0x3)].c_str());
printf(" Duplex: %s\n", (regVal & 0x1) ? "Full" : "Half");
// Read Extended Device Control Register
regVal = nicReadRegInternal(pNic, 0x18);
regVal = nicReadRegInternal(pNic, kExtendedDeviceControlRegister);
printf(" Link Mode: %s\n", linkMode[((regVal>>22) & 0x3)].c_str());
printf(" Driver Loaded: %s\n", (regVal & 0x10000000) ? "Yes" : "No");

printf("i210 PCS Config:\n");
// Read PCS Configuration register
regVal = nicReadRegInternal(pNic, 0x4200);
regVal = nicReadRegInternal(pNic, kPcsConfigurationRegister);
printf(" PCS Enabled: %s\n", (regVal & 0x8) ? "Enabled" : "Disabled");

printf("i210 PHY Config:\n");

// Set Phy page 0
mdioRegVal = (1 << 26) | (22 << 16);
nicWriteRegInternal(pNic, 0x20, mdioRegVal);
nicWriteRegInternal(pNic, kMdiControlRegister, mdioRegVal);
mdioRegVal = waitForMdioCompletion(pNic);

// Read reg 0
mdioRegVal = (2 << 26) | (0 << 16);
nicWriteRegInternal(pNic, 0x20, mdioRegVal);
nicWriteRegInternal(pNic, kMdiControlRegister, mdioRegVal);
mdioRegVal = waitForMdioCompletion(pNic);

printf(" Power Down: %s\n", (mdioRegVal & 0x800) ? "Yes" : "No");
Expand Down Expand Up @@ -310,20 +366,20 @@ bool nicLinkShowStatus(struct nic_info_s *pNic) {
printf("Map address: 0x%lx\n", (unsigned long)ptr);
printf("i210 MAC Status:\n");
// Read Device Status Register
regVal = nicReadRegInternal(pNic, 0x8);
regVal = nicReadRegInternal(pNic, kDeviceStatusRegister);
printf(" Link: %s\n", (regVal & 0x2) ? "Up" : "Down");
printf(" Link speed: %s\n", speedString[((regVal>>6) & 0x3)].c_str());
printf(" Duplex: %s\n", (regVal & 0x1) ? "Full" : "Half");

// Read Copper switch control register
regVal = nicReadRegInternal(pNic, 0x34);
regVal = nicReadRegInternal(pNic, kCopperSwitchControlRegister);
printf(" PHY Signal: %s\n", (regVal & 0x400) ? "Detected" : "Not detected");
printf(" Serdes Signal: %s\n", (regVal & 0x200) ? "Detected" : "Not detected");
printf(" Phy power: %s\n", (regVal & 0x800) ? "Down" : "Up");

printf("i210 PCS Status:\n");
// Read PCS status register
regVal = nicReadRegInternal(pNic, 0x420C);
regVal = nicReadRegInternal(pNic, kPcsLinkStatusRegister);
printf(" PCS Link: %s\n", (regVal & 0x1) ? "Up" : "Down");
printf(" Link speed: %s\n", speedString[((regVal>>1) & 0x3)].c_str());
printf(" Duplex: %s\n", (regVal & 0x8) ? "Full" : "Half");
Expand All @@ -332,19 +388,19 @@ bool nicLinkShowStatus(struct nic_info_s *pNic) {

// Set Phy page 0
mdioRegVal = (1 << 26) | (22 << 16);
nicWriteRegInternal(pNic, 0x20, mdioRegVal);
nicWriteRegInternal(pNic, kMdiControlRegister, mdioRegVal);
mdioRegVal = waitForMdioCompletion(pNic);

// Read reg 1
mdioRegVal = (2 << 26) | (0x1 << 16);
nicWriteRegInternal(pNic, 0x20, mdioRegVal);
nicWriteRegInternal(pNic, kMdiControlRegister, mdioRegVal);
mdioRegVal = waitForMdioCompletion(pNic);
printf(" Link: %s\n", (mdioRegVal & 0x4) ? "Up" : "Down");
printf(" AN Status: %s\n", (mdioRegVal & 0x20) ? "Completed" : "Incomplete");

// Read reg 17
mdioRegVal = (2 << 26) | (0x11 << 16);
nicWriteRegInternal(pNic, 0x20, mdioRegVal);
nicWriteRegInternal(pNic, kMdiControlRegister, mdioRegVal);
mdioRegVal = waitForMdioCompletion(pNic);
printf(" Speed: %s\n", speedString[((mdioRegVal>>14) & 0x3)].c_str());
printf(" Duplex: %s\n", (mdioRegVal & 0x2000) ? "Full" : "Half");
Expand All @@ -353,6 +409,57 @@ bool nicLinkShowStatus(struct nic_info_s *pNic) {
return true;
}

/*
* nicReset
*
* Does the NIC I210 block reset for the following components:
* Soft reset
* Internal PHY reset
* Device reset
*/
bool nicReset(struct nic_info_s *pNic, bool softReset, bool phyReset, bool deviceReset) {

uint32_t regVal;
unsigned char *ptr = pNic->mapAddr;

printf("Map address: 0x%lx\n", (unsigned long)ptr);

// Read Device Control Register and do soft reset
regVal = nicReadRegInternal(pNic, kDeviceControlRegister);
if (softReset) {
// Soft reset bit 26 is self clear
regVal |= (1 << 26);
nicWriteRegInternal(pNic, kDeviceControlRegister, regVal);
printf("NIC: Soft Reset done\n");
}
usleep(1000000);

// Read Device Control Register and do PHY reset
regVal = nicReadRegInternal(pNic, kDeviceControlRegister);
if (phyReset) {
// Phy reset bit 31 is not self clear
regVal |= (1 << 31);
nicWriteRegInternal(pNic, kDeviceControlRegister, regVal);
usleep(1000000);
regVal &= ~(1 << 31);
nicWriteRegInternal(pNic, kDeviceControlRegister, regVal);
printf("NIC: Internal PHY Reset done\n");
}
usleep(1000000);

// Read Device Control Register and do Device reset
regVal = nicReadRegInternal(pNic, kDeviceControlRegister);
if (deviceReset) {
// Device reset bit 29 is self clear
regVal |= (1 << 29);
nicWriteRegInternal(pNic, kDeviceControlRegister, regVal);
printf("NIC: Device Reset done\n");
}
usleep(1000000);

return true;
}

/*
* This utility program provides the access CLI for Intel NIC i210
* which is used in most of the FBOSS platform. This NIC provides
Expand Down Expand Up @@ -386,6 +493,7 @@ int main(int argc, char* argv[]) {
nChars = sprintf(sysfsPath, "/sys/bus/pci/devices/0000:");
fscanf(fp, "%s", &sysfsPath[nChars]);
strcat(sysfsPath, "/resource0");
pclose(fp);

// Open the sysfs file to access the device
int fd = open(sysfsPath, O_RDWR | O_SYNC);
Expand All @@ -406,6 +514,11 @@ int main(int argc, char* argv[]) {
return EX_SOFTWARE;
}

// CLI: --verbose option
if (FLAGS_verbose) {
verbosePrint = true;
}

// CLI: nic_util --nic_read_reg --reg_addr <register-address>
if (FLAGS_nic_read_reg) {
printf("Calling nicShowReg with address 0x%x\n", FLAGS_reg_addr);
Expand All @@ -423,16 +536,26 @@ int main(int argc, char* argv[]) {
// CLI: nic_util --nic_phy_read_reg --phy_reg_addr <register-address>
// [--phy_page <phy-page-id>]
if (FLAGS_nic_phy_read_reg) {
printf("Calling nicPhyReadReg with address 0x%x (page %d)\n",
FLAGS_phy_reg_addr, FLAGS_phy_page);
if (FLAGS_phy_page>=0) {
printf("Calling nicPhyReadReg with address 0x%x (page %d)\n",
FLAGS_phy_reg_addr, FLAGS_phy_page);
} else {
printf("Calling nicPhyReadReg with address 0x%x\n",
FLAGS_phy_reg_addr);
}
nicPhyReadReg(&nicInfo, FLAGS_phy_reg_addr, FLAGS_phy_page);
}

// CLI: nic_util --nic_phy_write_reg --phy_reg_addr <register-address>
// --phy_reg_val <data-value> [--phy_page <phy-page-id>]
if (FLAGS_nic_phy_write_reg) {
printf("Calling nicPhyWriteReg with address 0x%x value 0x%x (page %d)\n",
if (FLAGS_phy_page>=0) {
printf("Calling nicPhyWriteReg with address 0x%x value 0x%x (page %d)\n",
FLAGS_phy_reg_addr, FLAGS_phy_reg_val, FLAGS_phy_page);
} else {
printf("Calling nicPhyWriteReg with address 0x%x value 0x%x\n",
FLAGS_phy_reg_addr, FLAGS_phy_reg_val);
}
nicPhyWriteReg(&nicInfo, FLAGS_phy_reg_addr, FLAGS_phy_reg_val, FLAGS_phy_page);
}

Expand All @@ -448,6 +571,12 @@ int main(int argc, char* argv[]) {
nicLinkShowStatus(&nicInfo);
}

// CLI: nic_util --nic_reset [--soft_reset | --phy_reset | --device_reset]
if (FLAGS_nic_reset) {
printf("Calling nicReset to reset the NIC I210\n");
nicReset(&nicInfo, FLAGS_soft_reset, FLAGS_phy_reset,FLAGS_device_reset);
}

munmap(nicInfo.mapAddr, 0x10000);
close(fd);
return EX_OK;
Expand Down

0 comments on commit 8865126

Please sign in to comment.