Skip to content

Commit 601ad04

Browse files
committed
Merge branch 'mlxsw-speed-up-transceiver-module-eeprom-dump'
Petr Machata says: ==================== mlxsw: Speed up transceiver module EEPROM dump Ido Schimmel writes: Old firmware versions could only read up to 48 bytes from a transceiver module's EEPROM in one go. Newer versions can read up to 128 bytes, resulting in fewer transactions. Query support for the new capability during driver initialization and if supported, read up to 128 bytes in one go. This is going to be especially useful for upcoming transceiver module firmware flashing support. Before: # perf stat -e devlink:devlink_hwmsg -- ethtool -m swp11 page 0x1 offset 128 length 128 i2c 0x50 [...] Performance counter stats for 'ethtool -m swp11 page 0x1 offset 128 length 128 i2c 0x50': 3 devlink:devlink_hwmsg After: # perf stat -e devlink:devlink_hwmsg -- ethtool -m swp11 page 0x1 offset 128 length 128 i2c 0x50 [...] Performance counter stats for 'ethtool -m swp11 page 0x1 offset 128 length 128 i2c 0x50': 1 devlink:devlink_hwmsg Patches #1-#4 are preparations / cleanups. Patch #5 adds support for the new read size. ==================== Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
2 parents c1b0b61 + 1f4aea1 commit 601ad04

File tree

2 files changed

+112
-26
lines changed

2 files changed

+112
-26
lines changed

drivers/net/ethernet/mellanox/mlxsw/core_env.c

Lines changed: 34 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ struct mlxsw_env {
3232
const struct mlxsw_bus_info *bus_info;
3333
u8 max_module_count; /* Maximum number of modules per-slot. */
3434
u8 num_of_slots; /* Including the main board. */
35+
u8 max_eeprom_len; /* Maximum module EEPROM transaction length. */
3536
struct mutex line_cards_lock; /* Protects line cards. */
3637
struct mlxsw_env_line_card *line_cards[];
3738
};
@@ -111,7 +112,7 @@ mlxsw_env_validate_cable_ident(struct mlxsw_core *core, u8 slot_index, int id,
111112
if (err)
112113
return err;
113114

114-
mlxsw_reg_mcia_pack(mcia_pl, slot_index, id, 0,
115+
mlxsw_reg_mcia_pack(mcia_pl, slot_index, id,
115116
MLXSW_REG_MCIA_PAGE0_LO_OFF, 0, 1,
116117
MLXSW_REG_MCIA_I2C_ADDR_LOW);
117118
err = mlxsw_reg_query(core, MLXSW_REG(mcia), mcia_pl);
@@ -146,18 +147,15 @@ mlxsw_env_query_module_eeprom(struct mlxsw_core *mlxsw_core, u8 slot_index,
146147
int module, u16 offset, u16 size, void *data,
147148
bool qsfp, unsigned int *p_read_size)
148149
{
150+
struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core);
149151
char mcia_pl[MLXSW_REG_MCIA_LEN];
150152
char *eeprom_tmp;
151153
u16 i2c_addr;
152154
u8 page = 0;
153155
int status;
154156
int err;
155157

156-
/* MCIA register accepts buffer size <= 48. Page of size 128 should be
157-
* read by chunks of size 48, 48, 32. Align the size of the last chunk
158-
* to avoid reading after the end of the page.
159-
*/
160-
size = min_t(u16, size, MLXSW_REG_MCIA_EEPROM_SIZE);
158+
size = min_t(u16, size, mlxsw_env->max_eeprom_len);
161159

162160
if (offset < MLXSW_REG_MCIA_EEPROM_PAGE_LENGTH &&
163161
offset + size > MLXSW_REG_MCIA_EEPROM_PAGE_LENGTH)
@@ -188,7 +186,7 @@ mlxsw_env_query_module_eeprom(struct mlxsw_core *mlxsw_core, u8 slot_index,
188186
}
189187
}
190188

191-
mlxsw_reg_mcia_pack(mcia_pl, slot_index, module, 0, page, offset, size,
189+
mlxsw_reg_mcia_pack(mcia_pl, slot_index, module, page, offset, size,
192190
i2c_addr);
193191

194192
err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(mcia), mcia_pl);
@@ -266,12 +264,12 @@ mlxsw_env_module_temp_thresholds_get(struct mlxsw_core *core, u8 slot_index,
266264
page = MLXSW_REG_MCIA_TH_PAGE_CMIS_NUM;
267265
else
268266
page = MLXSW_REG_MCIA_TH_PAGE_NUM;
269-
mlxsw_reg_mcia_pack(mcia_pl, slot_index, module, 0, page,
267+
mlxsw_reg_mcia_pack(mcia_pl, slot_index, module, page,
270268
MLXSW_REG_MCIA_TH_PAGE_OFF + off,
271269
MLXSW_REG_MCIA_TH_ITEM_SIZE,
272270
MLXSW_REG_MCIA_I2C_ADDR_LOW);
273271
} else {
274-
mlxsw_reg_mcia_pack(mcia_pl, slot_index, module, 0,
272+
mlxsw_reg_mcia_pack(mcia_pl, slot_index, module,
275273
MLXSW_REG_MCIA_PAGE0_LO,
276274
off, MLXSW_REG_MCIA_TH_ITEM_SIZE,
277275
MLXSW_REG_MCIA_I2C_ADDR_HIGH);
@@ -489,9 +487,9 @@ mlxsw_env_get_module_eeprom_by_page(struct mlxsw_core *mlxsw_core,
489487
u8 size;
490488

491489
size = min_t(u8, page->length - bytes_read,
492-
MLXSW_REG_MCIA_EEPROM_SIZE);
490+
mlxsw_env->max_eeprom_len);
493491

494-
mlxsw_reg_mcia_pack(mcia_pl, slot_index, module, 0, page->page,
492+
mlxsw_reg_mcia_pack(mcia_pl, slot_index, module, page->page,
495493
device_addr + bytes_read, size,
496494
page->i2c_address);
497495
mlxsw_reg_mcia_bank_number_set(mcia_pl, page->bank);
@@ -1359,6 +1357,26 @@ static struct mlxsw_linecards_event_ops mlxsw_env_event_ops = {
13591357
.got_inactive = mlxsw_env_got_inactive,
13601358
};
13611359

1360+
static int mlxsw_env_max_module_eeprom_len_query(struct mlxsw_env *mlxsw_env)
1361+
{
1362+
char mcam_pl[MLXSW_REG_MCAM_LEN];
1363+
bool mcia_128b_supported;
1364+
int err;
1365+
1366+
mlxsw_reg_mcam_pack(mcam_pl,
1367+
MLXSW_REG_MCAM_FEATURE_GROUP_ENHANCED_FEATURES);
1368+
err = mlxsw_reg_query(mlxsw_env->core, MLXSW_REG(mcam), mcam_pl);
1369+
if (err)
1370+
return err;
1371+
1372+
mlxsw_reg_mcam_unpack(mcam_pl, MLXSW_REG_MCAM_MCIA_128B,
1373+
&mcia_128b_supported);
1374+
1375+
mlxsw_env->max_eeprom_len = mcia_128b_supported ? 128 : 48;
1376+
1377+
return 0;
1378+
}
1379+
13621380
int mlxsw_env_init(struct mlxsw_core *mlxsw_core,
13631381
const struct mlxsw_bus_info *bus_info,
13641382
struct mlxsw_env **p_env)
@@ -1427,10 +1445,15 @@ int mlxsw_env_init(struct mlxsw_core *mlxsw_core,
14271445
if (err)
14281446
goto err_type_set;
14291447

1448+
err = mlxsw_env_max_module_eeprom_len_query(env);
1449+
if (err)
1450+
goto err_eeprom_len_query;
1451+
14301452
env->line_cards[0]->active = true;
14311453

14321454
return 0;
14331455

1456+
err_eeprom_len_query:
14341457
err_type_set:
14351458
mlxsw_env_module_event_disable(env, 0);
14361459
err_mlxsw_env_module_event_enable:

drivers/net/ethernet/mellanox/mlxsw/reg.h

Lines changed: 78 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9640,18 +9640,10 @@ static inline void mlxsw_reg_mtbr_temp_unpack(char *payload, int rec_ind,
96409640
*/
96419641

96429642
#define MLXSW_REG_MCIA_ID 0x9014
9643-
#define MLXSW_REG_MCIA_LEN 0x40
9643+
#define MLXSW_REG_MCIA_LEN 0x94
96449644

96459645
MLXSW_REG_DEFINE(mcia, MLXSW_REG_MCIA_ID, MLXSW_REG_MCIA_LEN);
96469646

9647-
/* reg_mcia_l
9648-
* Lock bit. Setting this bit will lock the access to the specific
9649-
* cable. Used for updating a full page in a cable EPROM. Any access
9650-
* other then subsequence writes will fail while the port is locked.
9651-
* Access: RW
9652-
*/
9653-
MLXSW_ITEM32(reg, mcia, l, 0x00, 31, 1);
9654-
96559647
/* reg_mcia_module
96569648
* Module number.
96579649
* Access: Index
@@ -9716,7 +9708,6 @@ MLXSW_ITEM32(reg, mcia, size, 0x08, 0, 16);
97169708

97179709
#define MLXSW_REG_MCIA_EEPROM_PAGE_LENGTH 256
97189710
#define MLXSW_REG_MCIA_EEPROM_UP_PAGE_LENGTH 128
9719-
#define MLXSW_REG_MCIA_EEPROM_SIZE 48
97209711
#define MLXSW_REG_MCIA_I2C_ADDR_LOW 0x50
97219712
#define MLXSW_REG_MCIA_I2C_ADDR_HIGH 0x51
97229713
#define MLXSW_REG_MCIA_PAGE0_LO_OFF 0xa0
@@ -9753,7 +9744,7 @@ enum mlxsw_reg_mcia_eeprom_module_info {
97539744
* Bytes to read/write.
97549745
* Access: RW
97559746
*/
9756-
MLXSW_ITEM_BUF(reg, mcia, eeprom, 0x10, MLXSW_REG_MCIA_EEPROM_SIZE);
9747+
MLXSW_ITEM_BUF(reg, mcia, eeprom, 0x10, 128);
97579748

97589749
/* This is used to access the optional upper pages (1-3) in the QSFP+
97599750
* memory map. Page 1 is available on offset 256 through 383, page 2 -
@@ -9764,14 +9755,12 @@ MLXSW_ITEM_BUF(reg, mcia, eeprom, 0x10, MLXSW_REG_MCIA_EEPROM_SIZE);
97649755
MLXSW_REG_MCIA_EEPROM_UP_PAGE_LENGTH + 1)
97659756

97669757
static inline void mlxsw_reg_mcia_pack(char *payload, u8 slot_index, u8 module,
9767-
u8 lock, u8 page_number,
9768-
u16 device_addr, u8 size,
9758+
u8 page_number, u16 device_addr, u8 size,
97699759
u8 i2c_device_addr)
97709760
{
97719761
MLXSW_REG_ZERO(mcia, payload);
97729762
mlxsw_reg_mcia_slot_set(payload, slot_index);
97739763
mlxsw_reg_mcia_module_set(payload, module);
9774-
mlxsw_reg_mcia_l_set(payload, lock);
97759764
mlxsw_reg_mcia_page_number_set(payload, page_number);
97769765
mlxsw_reg_mcia_device_address_set(payload, device_addr);
97779766
mlxsw_reg_mcia_size_set(payload, size);
@@ -10581,6 +10570,79 @@ static inline void mlxsw_reg_mcda_pack(char *payload, u32 update_handle,
1058110570
mlxsw_reg_mcda_data_set(payload, i, *(u32 *) &data[i * 4]);
1058210571
}
1058310572

10573+
/* MCAM - Management Capabilities Mask Register
10574+
* --------------------------------------------
10575+
* Reports the device supported management features.
10576+
*/
10577+
#define MLXSW_REG_MCAM_ID 0x907F
10578+
#define MLXSW_REG_MCAM_LEN 0x48
10579+
10580+
MLXSW_REG_DEFINE(mcam, MLXSW_REG_MCAM_ID, MLXSW_REG_MCAM_LEN);
10581+
10582+
enum mlxsw_reg_mcam_feature_group {
10583+
/* Enhanced features. */
10584+
MLXSW_REG_MCAM_FEATURE_GROUP_ENHANCED_FEATURES,
10585+
};
10586+
10587+
/* reg_mcam_feature_group
10588+
* Feature list mask index.
10589+
* Access: Index
10590+
*/
10591+
MLXSW_ITEM32(reg, mcam, feature_group, 0x00, 16, 8);
10592+
10593+
enum mlxsw_reg_mcam_mng_feature_cap_mask_bits {
10594+
/* If set, MCIA supports 128 bytes payloads. Otherwise, 48 bytes. */
10595+
MLXSW_REG_MCAM_MCIA_128B = 34,
10596+
};
10597+
10598+
#define MLXSW_REG_BYTES_PER_DWORD 0x4
10599+
10600+
/* reg_mcam_mng_feature_cap_mask
10601+
* Supported port's enhanced features.
10602+
* Based on feature_group index.
10603+
* When bit is set, the feature is supported in the device.
10604+
* Access: RO
10605+
*/
10606+
#define MLXSW_REG_MCAM_MNG_FEATURE_CAP_MASK_DWORD(_dw_num, _offset) \
10607+
MLXSW_ITEM_BIT_ARRAY(reg, mcam, mng_feature_cap_mask_dw##_dw_num, \
10608+
_offset, MLXSW_REG_BYTES_PER_DWORD, 1)
10609+
10610+
/* The access to the bits in the field 'mng_feature_cap_mask' is not same to
10611+
* other mask fields in other registers. In most of the cases bit #0 is the
10612+
* first one in the last dword. In MCAM register, the first dword contains bits
10613+
* #0-#31 and so on, so the access to the bits is simpler using bit array per
10614+
* dword. Declare each dword of 'mng_feature_cap_mask' field separately.
10615+
*/
10616+
MLXSW_REG_MCAM_MNG_FEATURE_CAP_MASK_DWORD(0, 0x28);
10617+
MLXSW_REG_MCAM_MNG_FEATURE_CAP_MASK_DWORD(1, 0x2C);
10618+
MLXSW_REG_MCAM_MNG_FEATURE_CAP_MASK_DWORD(2, 0x30);
10619+
MLXSW_REG_MCAM_MNG_FEATURE_CAP_MASK_DWORD(3, 0x34);
10620+
10621+
static inline void
10622+
mlxsw_reg_mcam_pack(char *payload, enum mlxsw_reg_mcam_feature_group feat_group)
10623+
{
10624+
MLXSW_REG_ZERO(mcam, payload);
10625+
mlxsw_reg_mcam_feature_group_set(payload, feat_group);
10626+
}
10627+
10628+
static inline void
10629+
mlxsw_reg_mcam_unpack(char *payload,
10630+
enum mlxsw_reg_mcam_mng_feature_cap_mask_bits bit,
10631+
bool *p_mng_feature_cap_val)
10632+
{
10633+
int offset = bit % (MLXSW_REG_BYTES_PER_DWORD * BITS_PER_BYTE);
10634+
int dword = bit / (MLXSW_REG_BYTES_PER_DWORD * BITS_PER_BYTE);
10635+
u8 (*getters[])(const char *, u16) = {
10636+
mlxsw_reg_mcam_mng_feature_cap_mask_dw0_get,
10637+
mlxsw_reg_mcam_mng_feature_cap_mask_dw1_get,
10638+
mlxsw_reg_mcam_mng_feature_cap_mask_dw2_get,
10639+
mlxsw_reg_mcam_mng_feature_cap_mask_dw3_get,
10640+
};
10641+
10642+
if (!WARN_ON_ONCE(dword >= ARRAY_SIZE(getters)))
10643+
*p_mng_feature_cap_val = getters[dword](payload, offset);
10644+
}
10645+
1058410646
/* MPSC - Monitoring Packet Sampling Configuration Register
1058510647
* --------------------------------------------------------
1058610648
* MPSC Register is used to configure the Packet Sampling mechanism.
@@ -12974,10 +13036,11 @@ static const struct mlxsw_reg_info *mlxsw_reg_infos[] = {
1297413036
MLXSW_REG(mcion),
1297513037
MLXSW_REG(mtpps),
1297613038
MLXSW_REG(mtutc),
12977-
MLXSW_REG(mpsc),
1297813039
MLXSW_REG(mcqi),
1297913040
MLXSW_REG(mcc),
1298013041
MLXSW_REG(mcda),
13042+
MLXSW_REG(mcam),
13043+
MLXSW_REG(mpsc),
1298113044
MLXSW_REG(mgpc),
1298213045
MLXSW_REG(mprs),
1298313046
MLXSW_REG(mogcr),

0 commit comments

Comments
 (0)