Intel unsupported sfp: различия между версиями
Материал из noname.com.ua
Перейти к навигацииПерейти к поискуSirmax (обсуждение | вклад) (→x520) |
Sirmax (обсуждение | вклад) |
||
(не показано 6 промежуточных версий этого же участника) | |||
Строка 25: | Строка 25: | ||
Тут нужно указать список если более чем одна карта (или порт?) |
Тут нужно указать список если более чем одна карта (или порт?) |
||
− | + | =<code>x520 Unlocker</code>= |
|
В теории это нужно что бы установить карту там, где драйвер не имеет опции отключения проверки. |
В теории это нужно что бы установить карту там, где драйвер не имеет опции отключения проверки. |
||
<BR> |
<BR> |
||
Строка 44: | Строка 44: | ||
Все манипуляции проводить только с 1 битом, например если было значение <code>fe</code> |
Все манипуляции проводить только с 1 битом, например если было значение <code>fe</code> |
||
<BR> |
<BR> |
||
− | ( Бинарное <code>11111110</code> ) то записать следует <code>ff</code>( Бинарное <code>11111111</code> |
+ | ( Бинарное <code>11111110</code> ) то записать следует <code>ff</code>( Бинарное <code>11111111</code> ) |
<PRE> |
<PRE> |
||
ethtool -E enp1s0 magic 0x10fb8086 offset 0x58 value 0xff |
ethtool -E enp1s0 magic 0x10fb8086 offset 0x58 value 0xff |
||
Строка 136: | Строка 136: | ||
}} |
}} |
||
− | + | =<code>xl710</code>= |
|
* https://github.com/bibigon812/xl710-unlocker |
* https://github.com/bibigon812/xl710-unlocker |
||
<PRE> |
<PRE> |
||
Строка 151: | Строка 151: | ||
+ | ==<code>Makefile</code>== |
||
− | |||
{{#spoiler:show=Makefile| |
{{#spoiler:show=Makefile| |
||
<PRE> |
<PRE> |
||
Строка 165: | Строка 165: | ||
</PRE> |
</PRE> |
||
}} |
}} |
||
− | {{#spoiler:show=1| |
||
+ | ==<code>syscalls.h</code>== |
||
− | <PRE> |
||
+ | {{#spoiler:show=syscalls.h| |
||
− | </PRE> |
||
− | }} |
||
− | <BR> |
||
− | {{#spoiler:show=1| |
||
<PRE> |
<PRE> |
||
+ | #ifndef SYSCALLS_H |
||
+ | |||
+ | #define ETHTOOL_GEEPROM 0x0000000b /* Get EEPROM data */ |
||
+ | #define ETHTOOL_SEEPROM 0x0000000c /* Set EEPROM data. */ |
||
+ | |||
+ | #define I40E_NVM_TRANS_SHIFT 8 |
||
+ | #define I40E_NVM_TRANS_MASK (0xf << I40E_NVM_TRANS_SHIFT) |
||
+ | #define I40E_NVM_CON 0x0 |
||
+ | #define I40E_NVM_SNT 0x1 |
||
+ | #define I40E_NVM_LCB 0x2 |
||
+ | #define I40E_NVM_SA (I40E_NVM_SNT | I40E_NVM_LCB) |
||
+ | #define I40E_NVM_ERA 0x4 |
||
+ | #define I40E_NVM_CSUM 0x8 |
||
+ | #define I40E_NVM_EXEC 0xf |
||
+ | |||
+ | struct ethtool_eeprom { |
||
+ | uint32_t cmd; |
||
+ | uint32_t magic; |
||
+ | uint32_t offset; |
||
+ | uint32_t len; |
||
+ | uint8_t data[0]; |
||
+ | }; |
||
+ | |||
+ | #endif |
||
</PRE> |
</PRE> |
||
}} |
}} |
||
+ | |||
− | {{#spoiler:show=1| |
||
+ | ==<code>xl710_unlock.c</code>== |
||
+ | {{#spoiler:show=xl710_unlock.c| |
||
<PRE> |
<PRE> |
||
+ | #include <stdint.h> |
||
+ | #include <stdlib.h> |
||
+ | #include <stdio.h> |
||
+ | #include <string.h> |
||
+ | #include <net/if.h> |
||
+ | #include <sys/ioctl.h> |
||
+ | #include <linux/sockios.h> |
||
+ | #include <unistd.h> |
||
+ | #include "syscalls.h" |
||
+ | |||
+ | |||
+ | void die( const char *reason ) { |
||
+ | perror( reason ); |
||
+ | exit( EXIT_FAILURE ); |
||
+ | } |
||
+ | |||
+ | void print_usage( void ) |
||
+ | { |
||
+ | printf( "xl710_unlock\n" ); |
||
+ | printf( " -n <device_name>, required\n" ); |
||
+ | printf( " -i <device_id>, default: 0x1572\n" ); |
||
+ | printf( " -p lock/unlock\n" ); |
||
+ | |||
+ | exit( EXIT_FAILURE ); |
||
+ | } |
||
+ | |||
+ | int main(int argc, char *const *argv) { |
||
+ | /* Parse arguments */ |
||
+ | char *c_devid = "0x1572"; |
||
+ | char *c_devname = NULL; |
||
+ | int patching = 0; |
||
+ | |||
+ | int c; |
||
+ | |||
+ | while( ( c = getopt( argc, argv, "i:n:h?" ) ) != -1 ) |
||
+ | { |
||
+ | switch( c ) |
||
+ | { |
||
+ | case 'i': |
||
+ | c_devid = optarg; |
||
+ | break; |
||
+ | case 'n': |
||
+ | c_devname = optarg; |
||
+ | break; |
||
+ | case 'h': |
||
+ | case '?': |
||
+ | default: |
||
+ | print_usage(); |
||
+ | break; |
||
+ | } |
||
+ | } |
||
+ | |||
+ | if( c_devname == NULL ) print_usage(); |
||
+ | |||
+ | int mod = 0; |
||
+ | uint16_t length = 0x02; |
||
+ | int fd; |
||
+ | struct ifreq ifr; |
||
+ | struct ethtool_eeprom *eeprom; |
||
+ | |||
+ | const int devid = strtol( c_devid, 0, 0 ); |
||
+ | const char *ethDev = c_devname; |
||
+ | |||
+ | fd = socket( AF_INET, SOCK_DGRAM, 0 ); |
||
+ | if( fd == -1 ) die( "socket" ); |
||
+ | |||
+ | eeprom = calloc( 1, sizeof( *eeprom ) + ( length << 1 ) ); |
||
+ | if( !eeprom ) die( "calloc" ); |
||
+ | |||
+ | eeprom->cmd = ETHTOOL_GEEPROM; |
||
+ | eeprom->magic = (devid << 16) | (I40E_NVM_SA << I40E_NVM_TRANS_SHIFT) | mod; |
||
+ | eeprom->len = length; |
||
+ | memset(&ifr, 0, sizeof(ifr)); |
||
+ | strcpy(ifr.ifr_name, ethDev); |
||
+ | |||
+ | /* |
||
+ | Get offset to EMP SR |
||
+ | offset 0x48 |
||
+ | length 0x2 |
||
+ | */ |
||
+ | eeprom->offset = 0x48 << 1; |
||
+ | |||
+ | ifr.ifr_data = (void*)eeprom; |
||
+ | if (ioctl(fd, SIOCETHTOOL, &ifr) == -1) die("ioctl"); |
||
+ | |||
+ | uint16_t emp_offset = *(uint16_t*)(eeprom+1); |
||
+ | printf("EMP SR offset: 0x%04x\n", emp_offset); |
||
+ | |||
+ | /* |
||
+ | Get offset to PHY Capabilities 0 |
||
+ | emp_offset + 0x19 |
||
+ | length 0x2 |
||
+ | */ |
||
+ | uint16_t cap_offset = 0x19; |
||
+ | |||
+ | eeprom->offset = (emp_offset + cap_offset) << 1; |
||
+ | |||
+ | ifr.ifr_data = (void*)eeprom; |
||
+ | if (ioctl(fd, SIOCETHTOOL, &ifr) == -1) die("ioctl"); |
||
+ | |||
+ | uint16_t phy_offset = *(uint16_t*)(eeprom+1) + emp_offset + cap_offset; |
||
+ | printf("PHY offset: 0x%04x\n", phy_offset); |
||
+ | |||
+ | /* |
||
+ | Get PHY data size |
||
+ | offset phy_offset |
||
+ | */ |
||
+ | eeprom->offset = phy_offset << 1; |
||
+ | |||
+ | ifr.ifr_data = (void*)eeprom; |
||
+ | if( ioctl( fd, SIOCETHTOOL, &ifr ) == -1 ) die( "ioctl" ); |
||
+ | |||
+ | uint16_t phy_cap_size = *(uint16_t*)(eeprom + 1); |
||
+ | printf("PHY data struct size: 0x%04x\n", phy_cap_size); |
||
+ | |||
+ | /* |
||
+ | Get misc0 |
||
+ | */ |
||
+ | |||
+ | uint16_t misc_offset = 0x8; |
||
+ | |||
+ | int i; |
||
+ | uint16_t misc0 = 0x0; |
||
+ | int change_count = 0; |
||
+ | |||
+ | for( i = 0; i < 4; ++i) |
||
+ | { |
||
+ | eeprom->offset = (phy_offset + misc_offset + (phy_cap_size + 1) * i) << 1; |
||
+ | |||
+ | ifr.ifr_data = (void*)eeprom; |
||
+ | if( ioctl( fd, SIOCETHTOOL, &ifr ) == -1 ) die( "ioctl" ); |
||
+ | |||
+ | uint16_t misc = *(uint16_t*)(eeprom + 1); |
||
+ | printf( "MISC: 0x%04x", misc); |
||
+ | |||
+ | if( misc & 0x0800 ) printf( " <- locked\n" ); |
||
+ | else printf( " <- unlocked\n" ); |
||
+ | |||
+ | if( misc != misc0 ) |
||
+ | { |
||
+ | ++change_count; |
||
+ | misc0 = misc; |
||
+ | } |
||
+ | } |
||
+ | |||
+ | if( change_count > 1 ) die( "Different MISC's values" ); |
||
+ | |||
+ | /* |
||
+ | Patching |
||
+ | */ |
||
+ | |||
+ | printf( "Ready to fix it? [y/N]: " ); |
||
+ | char choice = getchar(); |
||
+ | switch( choice ) |
||
+ | { |
||
+ | case 'y': |
||
+ | case 'Y': |
||
+ | patching = 1; |
||
+ | break; |
||
+ | default: |
||
+ | patching = 0; |
||
+ | } |
||
+ | |||
+ | if( patching ) |
||
+ | { |
||
+ | for( i = 0; i < 4; ++i) |
||
+ | { |
||
+ | eeprom->cmd = ETHTOOL_SEEPROM; |
||
+ | eeprom->offset = (phy_offset + misc_offset + (phy_cap_size + 1) * i) << 1; |
||
+ | |||
+ | *(uint16_t*)(eeprom + 1) = misc0 ^ 0x0800; |
||
+ | ifr.ifr_data = (void*)eeprom; |
||
+ | if (ioctl(fd, SIOCETHTOOL, &ifr) == -1) die("write"); |
||
+ | |||
+ | sleep(1); |
||
+ | } |
||
+ | |||
+ | // update checksum |
||
+ | eeprom->cmd = ETHTOOL_SEEPROM; |
||
+ | eeprom->magic = (devid << 16) | ((I40E_NVM_CSUM|I40E_NVM_SA) << I40E_NVM_TRANS_SHIFT) | mod; |
||
+ | eeprom->len = 2; |
||
+ | eeprom->offset = 0; |
||
+ | |||
+ | memset(&ifr, 0, sizeof(ifr)); |
||
+ | strcpy(ifr.ifr_name, ethDev); |
||
+ | ifr.ifr_data = (void*)eeprom; |
||
+ | if (ioctl(fd, SIOCETHTOOL, &ifr) == -1) die("checksum"); |
||
+ | } |
||
+ | |||
+ | return 0; |
||
+ | } |
||
</PRE> |
</PRE> |
||
}} |
}} |
Текущая версия на 11:17, 25 февраля 2024
Ошибка ixgbe failed to load because an unsupported SFP+ module type was detected
x520
- файл
/etc/default/grub.d/60_custom.cfg
GRUB_CMDLINE_LINUX="$GRUB_CMDLINE_LINUX ixgbe.allow_unsupported_sfp=1"
Или если более чем одна карта - ixgbe.allow_unsupported_sfp=1,1,1,1
- Запустить
update-grub
- Файл
/etc/modprobe.d/ixgbe.conf
options ixgbe allow_unsupported_sfp=1,1,1,1
Тут нужно указать список если более чем одна карта (или порт?)
x520 Unlocker
В теории это нужно что бы установить карту там, где драйвер не имеет опции отключения проверки.
Последний бит должен быть установлен 1 (в примере уже установлен, в обоих случаях )
ethtool -e enp3s0f1 offset 0x58 length 1 Offset Values ------ ------ 0x0058: fd
ethtool -e enp7s0f0 offset 0x58 length 1 Offset Values ------ ------ 0x0058: ff
Все манипуляции проводить только с 1 битом, например если было значение fe
( Бинарное 11111110
) то записать следует ff
( Бинарное 11111111
)
ethtool -E enp1s0 magic 0x10fb8086 offset 0x58 value 0xff
Магическое значение можно посмотреть так:
lspci -nn | grep 82599 03:00.0 Ethernet controller [0200]: Intel Corporation 82599ES 10-Gigabit SFI/SFP+ Network Connection [8086:10fb] (rev 01) 03:00.1 Ethernet controller [0200]: Intel Corporation 82599ES 10-Gigabit SFI/SFP+ Network Connection [8086:10fb] (rev 01)
[8086:10fb]
--> 0x 10fb 8086
Что бы не возиться руками все те же манипуляции можно сделать скриптом
xl710
# ./xl710_unlock -n enp4s0f0 EMP SR offset: 0x67a8 PHY offset: 0x68f6 PHY data struct size: 0x000c MISC: 0x6b0c <- locked MISC: 0x6b0c <- locked MISC: 0x6b0c <- locked MISC: 0x6b0c <- locked Ready to fix it? [y/N]: y