mirror of
https://github.com/corundum/corundum.git
synced 2025-01-16 08:12:53 +08:00
Accept interface name and PCIe BDF when connecting to device
This commit is contained in:
parent
23f635f273
commit
eba32ce8a5
@ -347,13 +347,13 @@ int file_type_from_ext(const char *file_name)
|
|||||||
return FILE_TYPE_BIN;
|
return FILE_TYPE_BIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
int pcie_hot_reset(const char *pcie_port_path)
|
int pcie_hot_reset(const char *pci_port_path)
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
char path[PATH_MAX+32];
|
char path[PATH_MAX+32];
|
||||||
char buf[32];
|
char buf[32];
|
||||||
|
|
||||||
snprintf(path, sizeof(path), "%s/config", pcie_port_path);
|
snprintf(path, sizeof(path), "%s/config", pci_port_path);
|
||||||
|
|
||||||
fd = open(path, O_RDWR);
|
fd = open(path, O_RDWR);
|
||||||
|
|
||||||
@ -381,14 +381,14 @@ int pcie_hot_reset(const char *pcie_port_path)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int pcie_disable_fatal_err(const char *pcie_port_path)
|
int pcie_disable_fatal_err(const char *pci_port_path)
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
char path[PATH_MAX+32];
|
char path[PATH_MAX+32];
|
||||||
char buf[32];
|
char buf[32];
|
||||||
int offset;
|
int offset;
|
||||||
|
|
||||||
snprintf(path, sizeof(path), "%s/config", pcie_port_path);
|
snprintf(path, sizeof(path), "%s/config", pci_port_path);
|
||||||
|
|
||||||
fd = open(path, O_RDWR);
|
fd = open(path, O_RDWR);
|
||||||
|
|
||||||
@ -451,8 +451,8 @@ int main(int argc, char *argv[])
|
|||||||
FILE *write_file = NULL;
|
FILE *write_file = NULL;
|
||||||
|
|
||||||
char path[PATH_MAX+32];
|
char path[PATH_MAX+32];
|
||||||
char device_path[PATH_MAX];
|
char pci_device_path[PATH_MAX];
|
||||||
char port_path[PATH_MAX];
|
char pci_port_path[PATH_MAX];
|
||||||
char *ptr;
|
char *ptr;
|
||||||
|
|
||||||
int slot = -1;
|
int slot = -1;
|
||||||
@ -526,47 +526,24 @@ int main(int argc, char *argv[])
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// determine sysfs path of PCIe device
|
if (!dev->pci_device_path[0])
|
||||||
// first, try to find via miscdevice
|
|
||||||
ptr = strrchr(device, '/');
|
|
||||||
ptr = ptr ? ptr+1 : device;
|
|
||||||
|
|
||||||
snprintf(path, sizeof(path), "/sys/class/misc/%s/device", ptr);
|
|
||||||
|
|
||||||
if (!realpath(path, device_path))
|
|
||||||
{
|
{
|
||||||
// that failed, perhaps it was a PCIe resource
|
fprintf(stderr, "Failed to determine PCIe device path\n");
|
||||||
strcpy(path, device);
|
|
||||||
ptr = strrchr(path, '/');
|
|
||||||
if (ptr)
|
|
||||||
*ptr = 0;
|
|
||||||
|
|
||||||
if (!realpath(path, device_path))
|
|
||||||
{
|
|
||||||
perror("failed to determine device path");
|
|
||||||
ret = -1;
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// PCIe device will have a config space, so check for that
|
|
||||||
snprintf(path, sizeof(path), "%s/config", device_path);
|
|
||||||
|
|
||||||
if (access(path, F_OK))
|
|
||||||
{
|
|
||||||
perror("failed to determine device path");
|
|
||||||
ret = -1;
|
ret = -1;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// snprintf(device_path, sizeof(device_path), dev->device_path)
|
||||||
|
snprintf(pci_device_path, sizeof(pci_device_path), "%s", dev->pci_device_path);
|
||||||
|
|
||||||
// determine sysfs path of upstream port
|
// determine sysfs path of upstream port
|
||||||
strcpy(port_path, device_path);
|
snprintf(pci_port_path, sizeof(pci_port_path), "%s", pci_device_path);
|
||||||
ptr = strrchr(port_path, '/');
|
ptr = strrchr(pci_port_path, '/');
|
||||||
if (ptr)
|
if (ptr)
|
||||||
*ptr = 0;
|
*ptr = 0;
|
||||||
|
|
||||||
printf("PCIe ID (device): %s\n", strrchr(device_path, '/')+1);
|
printf("PCIe ID (device): %s\n", strrchr(pci_device_path, '/')+1);
|
||||||
printf("PCIe ID (upstream port): %s\n", strrchr(port_path, '/')+1);
|
printf("PCIe ID (upstream port): %s\n", strrchr(pci_port_path, '/')+1);
|
||||||
|
|
||||||
uint32_t flash_format = 0;
|
uint32_t flash_format = 0;
|
||||||
const char *fpga_part = get_fpga_part(dev->fpga_id);
|
const char *fpga_part = get_fpga_part(dev->fpga_id);
|
||||||
@ -1216,27 +1193,23 @@ skip_flash:
|
|||||||
|
|
||||||
// disable fatal error reporting on port (to prevent IPMI-triggered reboot)
|
// disable fatal error reporting on port (to prevent IPMI-triggered reboot)
|
||||||
printf("Disabling PCIe fatal error reporting on port...\n");
|
printf("Disabling PCIe fatal error reporting on port...\n");
|
||||||
pcie_disable_fatal_err(port_path);
|
pcie_disable_fatal_err(pci_port_path);
|
||||||
|
|
||||||
// disconnect from device
|
// disconnect from device
|
||||||
mqnic_close(dev);
|
mqnic_close(dev);
|
||||||
dev = NULL;
|
dev = NULL;
|
||||||
|
|
||||||
// attempt to disconnect driver
|
// attempt to disconnect driver
|
||||||
ptr = strrchr(device_path, '/');
|
snprintf(path, sizeof(path), "%s/driver/unbind", pci_device_path);
|
||||||
if (ptr)
|
|
||||||
{
|
|
||||||
snprintf(path, sizeof(path), "%s/driver/unbind", device_path);
|
|
||||||
|
|
||||||
if (access(path, F_OK) == 0)
|
if (access(path, F_OK) == 0)
|
||||||
{
|
{
|
||||||
printf("Unbinding driver...\n");
|
printf("Unbinding driver...\n");
|
||||||
write_str_to_file(path, ptr+1);
|
write_str_to_file(path, ptr+1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
printf("No driver bound\n");
|
printf("No driver bound\n");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sleep(1);
|
sleep(1);
|
||||||
@ -1245,7 +1218,7 @@ skip_flash:
|
|||||||
if (action_boot)
|
if (action_boot)
|
||||||
{
|
{
|
||||||
// reconnect directly to device
|
// reconnect directly to device
|
||||||
snprintf(path, sizeof(path), "%s/resource0", device_path);
|
snprintf(path, sizeof(path), "%s/resource0", pci_device_path);
|
||||||
dev = mqnic_open(path);
|
dev = mqnic_open(path);
|
||||||
|
|
||||||
if (!dev)
|
if (!dev)
|
||||||
@ -1269,7 +1242,7 @@ skip_flash:
|
|||||||
// remove PCIe device
|
// remove PCIe device
|
||||||
printf("Removing device...\n");
|
printf("Removing device...\n");
|
||||||
|
|
||||||
snprintf(path, sizeof(path), "%s/remove", device_path);
|
snprintf(path, sizeof(path), "%s/remove", pci_device_path);
|
||||||
|
|
||||||
if (write_1_to_file(path))
|
if (write_1_to_file(path))
|
||||||
{
|
{
|
||||||
@ -1289,13 +1262,13 @@ skip_flash:
|
|||||||
for (int tries = 5; tries > 0; tries--)
|
for (int tries = 5; tries > 0; tries--)
|
||||||
{
|
{
|
||||||
printf("Performing hot reset on upstream port...\n");
|
printf("Performing hot reset on upstream port...\n");
|
||||||
pcie_hot_reset(port_path);
|
pcie_hot_reset(pci_port_path);
|
||||||
|
|
||||||
sleep(2);
|
sleep(2);
|
||||||
|
|
||||||
printf("Rescanning on upstream port...\n");
|
printf("Rescanning on upstream port...\n");
|
||||||
|
|
||||||
snprintf(path, sizeof(path), "%s/rescan", port_path);
|
snprintf(path, sizeof(path), "%s/rescan", pci_port_path);
|
||||||
|
|
||||||
if (write_1_to_file(path))
|
if (write_1_to_file(path))
|
||||||
{
|
{
|
||||||
@ -1305,7 +1278,7 @@ skip_flash:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// PCIe device will have a config space, so check for that
|
// PCIe device will have a config space, so check for that
|
||||||
snprintf(path, sizeof(path), "%s/config", device_path);
|
snprintf(path, sizeof(path), "%s/config", pci_device_path);
|
||||||
|
|
||||||
if (access(path, F_OK) == 0)
|
if (access(path, F_OK) == 0)
|
||||||
{
|
{
|
||||||
|
160
utils/mqnic.c
160
utils/mqnic.c
@ -33,8 +33,10 @@ either expressed or implied, of The Regents of the University of California.
|
|||||||
|
|
||||||
#include "mqnic.h"
|
#include "mqnic.h"
|
||||||
|
|
||||||
|
#include <dirent.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
#include <stdarg.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -43,18 +45,29 @@ either expressed or implied, of The Regents of the University of California.
|
|||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
struct mqnic *mqnic_open(const char *dev_name)
|
static int mqnic_try_open(struct mqnic *dev, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
struct mqnic *dev = calloc(1, sizeof(struct mqnic));
|
va_list ap;
|
||||||
|
char path[PATH_MAX+32];
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
char *ptr;
|
||||||
|
|
||||||
if (!dev)
|
va_start(ap, fmt);
|
||||||
{
|
vsnprintf(dev->device_path, sizeof(dev->device_path), fmt, ap);
|
||||||
perror("memory allocation failed");
|
va_end(ap);
|
||||||
goto fail_alloc;
|
|
||||||
}
|
|
||||||
|
|
||||||
dev->fd = open(dev_name, O_RDWR);
|
dev->pci_device_path[0] = 0;
|
||||||
|
|
||||||
|
if (access(dev->device_path, W_OK))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (stat(dev->device_path, &st))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (S_ISDIR(st.st_mode))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
dev->fd = open(dev->device_path, O_RDWR);
|
||||||
|
|
||||||
if (dev->fd < 0)
|
if (dev->fd < 0)
|
||||||
{
|
{
|
||||||
@ -82,6 +95,35 @@ struct mqnic *mqnic_open(const char *dev_name)
|
|||||||
dev->regs_size = info.regs_size;
|
dev->regs_size = info.regs_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// determine sysfs path of PCIe device
|
||||||
|
// first, try to find via miscdevice
|
||||||
|
ptr = strrchr(dev->device_path, '/');
|
||||||
|
ptr = ptr ? ptr+1 : dev->device_path;
|
||||||
|
|
||||||
|
snprintf(path, sizeof(path), "/sys/class/misc/%s/device", ptr);
|
||||||
|
|
||||||
|
if (!realpath(path, dev->pci_device_path))
|
||||||
|
{
|
||||||
|
// that failed, perhaps it was a PCIe resource
|
||||||
|
snprintf(path, sizeof(path), "%s", dev->device_path);
|
||||||
|
ptr = strrchr(path, '/');
|
||||||
|
if (ptr)
|
||||||
|
*ptr = 0;
|
||||||
|
|
||||||
|
if (!realpath(path, dev->pci_device_path))
|
||||||
|
dev->pci_device_path[0] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// PCIe device will have a config space, so check for that
|
||||||
|
if (dev->pci_device_path[0])
|
||||||
|
{
|
||||||
|
snprintf(path, sizeof(path), "%s/config", dev->pci_device_path);
|
||||||
|
|
||||||
|
if (access(path, F_OK))
|
||||||
|
dev->pci_device_path[0] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// map registers
|
||||||
dev->regs = (volatile uint8_t *)mmap(NULL, dev->regs_size, PROT_READ | PROT_WRITE, MAP_SHARED, dev->fd, 0);
|
dev->regs = (volatile uint8_t *)mmap(NULL, dev->regs_size, PROT_READ | PROT_WRITE, MAP_SHARED, dev->fd, 0);
|
||||||
if (dev->regs == MAP_FAILED)
|
if (dev->regs == MAP_FAILED)
|
||||||
{
|
{
|
||||||
@ -89,20 +131,12 @@ struct mqnic *mqnic_open(const char *dev_name)
|
|||||||
goto fail_mmap_regs;
|
goto fail_mmap_regs;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mqnic_reg_read32(dev->regs, 4) == 0xffffffff)
|
if (dev->pci_device_path[0] && mqnic_reg_read32(dev->regs, 4) == 0xffffffff)
|
||||||
{
|
{
|
||||||
// if we were given a PCIe resource, then we may need to enable the device
|
// if we were given a PCIe resource, then we may need to enable the device
|
||||||
char path[PATH_MAX+32];
|
snprintf(path, sizeof(path), "%s/enable", dev->pci_device_path);
|
||||||
char *ptr;
|
|
||||||
|
|
||||||
strcpy(path, dev_name);
|
if (access(path, W_OK) == 0)
|
||||||
ptr = strrchr(path, '/');
|
|
||||||
if (ptr)
|
|
||||||
{
|
|
||||||
strcpy(++ptr, "enable");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (access(path, F_OK) == 0)
|
|
||||||
{
|
{
|
||||||
FILE *fp = fopen(path, "w");
|
FILE *fp = fopen(path, "w");
|
||||||
|
|
||||||
@ -137,6 +171,85 @@ struct mqnic *mqnic_open(const char *dev_name)
|
|||||||
goto fail_enum;
|
goto fail_enum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
fail_enum:
|
||||||
|
if (dev->rb_list)
|
||||||
|
free_reg_block_list(dev->rb_list);
|
||||||
|
fail_reset:
|
||||||
|
munmap((void *)dev->regs, dev->regs_size);
|
||||||
|
fail_mmap_regs:
|
||||||
|
fail_ioctl:
|
||||||
|
fail_fstat:
|
||||||
|
close(dev->fd);
|
||||||
|
fail_open:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mqnic_try_open_if_name(struct mqnic *dev, const char *if_name)
|
||||||
|
{
|
||||||
|
DIR *folder;
|
||||||
|
struct dirent *entry;
|
||||||
|
char path[PATH_MAX];
|
||||||
|
|
||||||
|
snprintf(path, sizeof(path), "/sys/class/net/%s/device/misc/", if_name);
|
||||||
|
|
||||||
|
folder = opendir(path);
|
||||||
|
if (!folder)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
while ((entry = readdir(folder)))
|
||||||
|
{
|
||||||
|
if (entry->d_name[0] != '.')
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!entry)
|
||||||
|
{
|
||||||
|
closedir(folder);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(path, sizeof(path), "/dev/%s", entry->d_name);
|
||||||
|
|
||||||
|
closedir(folder);
|
||||||
|
|
||||||
|
return mqnic_try_open(dev, "%s", path);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct mqnic *mqnic_open(const char *dev_name)
|
||||||
|
{
|
||||||
|
struct mqnic *dev = calloc(1, sizeof(struct mqnic));
|
||||||
|
|
||||||
|
if (!dev)
|
||||||
|
{
|
||||||
|
perror("memory allocation failed");
|
||||||
|
goto fail_alloc;
|
||||||
|
}
|
||||||
|
|
||||||
|
// absolute path
|
||||||
|
if (mqnic_try_open(dev, "%s", dev_name) == 0)
|
||||||
|
goto open;
|
||||||
|
|
||||||
|
// network interface
|
||||||
|
if (mqnic_try_open_if_name(dev, dev_name) == 0)
|
||||||
|
goto open;
|
||||||
|
|
||||||
|
// PCIe sysfs path
|
||||||
|
if (mqnic_try_open(dev, "%s/resource0", dev_name) == 0)
|
||||||
|
goto open;
|
||||||
|
|
||||||
|
// PCIe BDF (dddd:xx:yy.z)
|
||||||
|
if (mqnic_try_open(dev, "/sys/bus/pci/devices/%s/resource0", dev_name) == 0)
|
||||||
|
goto open;
|
||||||
|
|
||||||
|
// PCIe BDF (xx:yy.z)
|
||||||
|
if (mqnic_try_open(dev, "/sys/bus/pci/devices/0000:%s/resource0", dev_name) == 0)
|
||||||
|
goto open;
|
||||||
|
|
||||||
|
goto fail_open;
|
||||||
|
|
||||||
|
open:
|
||||||
dev->fpga_id = mqnic_reg_read32(dev->fw_id_rb->regs, MQNIC_RB_FW_ID_REG_FPGA_ID);
|
dev->fpga_id = mqnic_reg_read32(dev->fw_id_rb->regs, MQNIC_RB_FW_ID_REG_FPGA_ID);
|
||||||
dev->fw_id = mqnic_reg_read32(dev->fw_id_rb->regs, MQNIC_RB_FW_ID_REG_FW_ID);
|
dev->fw_id = mqnic_reg_read32(dev->fw_id_rb->regs, MQNIC_RB_FW_ID_REG_FW_ID);
|
||||||
dev->fw_ver = mqnic_reg_read32(dev->fw_id_rb->regs, MQNIC_RB_FW_ID_REG_FW_VER);
|
dev->fw_ver = mqnic_reg_read32(dev->fw_id_rb->regs, MQNIC_RB_FW_ID_REG_FW_VER);
|
||||||
@ -186,15 +299,6 @@ struct mqnic *mqnic_open(const char *dev_name)
|
|||||||
skip_interface:
|
skip_interface:
|
||||||
return dev;
|
return dev;
|
||||||
|
|
||||||
fail:
|
|
||||||
fail_enum:
|
|
||||||
fail_reset:
|
|
||||||
mqnic_close(dev);
|
|
||||||
return NULL;
|
|
||||||
fail_mmap_regs:
|
|
||||||
fail_ioctl:
|
|
||||||
fail_fstat:
|
|
||||||
close(dev->fd);
|
|
||||||
fail_open:
|
fail_open:
|
||||||
free(dev);
|
free(dev);
|
||||||
fail_alloc:
|
fail_alloc:
|
||||||
|
@ -34,6 +34,7 @@ either expressed or implied, of The Regents of the University of California.
|
|||||||
#ifndef MQNIC_H
|
#ifndef MQNIC_H
|
||||||
#define MQNIC_H
|
#define MQNIC_H
|
||||||
|
|
||||||
|
#include <limits.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
@ -152,6 +153,9 @@ struct mqnic {
|
|||||||
char build_date_str[32];
|
char build_date_str[32];
|
||||||
|
|
||||||
struct mqnic_if *interfaces[MQNIC_MAX_IF];
|
struct mqnic_if *interfaces[MQNIC_MAX_IF];
|
||||||
|
|
||||||
|
char device_path[PATH_MAX];
|
||||||
|
char pci_device_path[PATH_MAX];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mqnic *mqnic_open(const char *dev_name);
|
struct mqnic *mqnic_open(const char *dev_name);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user