@@ -2519,6 +2519,135 @@ static int mlxsw_sp_flash_device(struct net_device *dev,
2519
2519
return err ;
2520
2520
}
2521
2521
2522
+ #define MLXSW_SP_QSFP_I2C_ADDR 0x50
2523
+
2524
+ static int mlxsw_sp_query_module_eeprom (struct mlxsw_sp_port * mlxsw_sp_port ,
2525
+ u16 offset , u16 size , void * data ,
2526
+ unsigned int * p_read_size )
2527
+ {
2528
+ struct mlxsw_sp * mlxsw_sp = mlxsw_sp_port -> mlxsw_sp ;
2529
+ char eeprom_tmp [MLXSW_SP_REG_MCIA_EEPROM_SIZE ];
2530
+ char mcia_pl [MLXSW_REG_MCIA_LEN ];
2531
+ int status ;
2532
+ int err ;
2533
+
2534
+ size = min_t (u16 , size , MLXSW_SP_REG_MCIA_EEPROM_SIZE );
2535
+ mlxsw_reg_mcia_pack (mcia_pl , mlxsw_sp_port -> mapping .module ,
2536
+ 0 , 0 , offset , size , MLXSW_SP_QSFP_I2C_ADDR );
2537
+
2538
+ err = mlxsw_reg_query (mlxsw_sp -> core , MLXSW_REG (mcia ), mcia_pl );
2539
+ if (err )
2540
+ return err ;
2541
+
2542
+ status = mlxsw_reg_mcia_status_get (mcia_pl );
2543
+ if (status )
2544
+ return - EIO ;
2545
+
2546
+ mlxsw_reg_mcia_eeprom_memcpy_from (mcia_pl , eeprom_tmp );
2547
+ memcpy (data , eeprom_tmp , size );
2548
+ * p_read_size = size ;
2549
+
2550
+ return 0 ;
2551
+ }
2552
+
2553
+ enum mlxsw_sp_eeprom_module_info_rev_id {
2554
+ MLXSW_SP_EEPROM_MODULE_INFO_REV_ID_UNSPC = 0x00 ,
2555
+ MLXSW_SP_EEPROM_MODULE_INFO_REV_ID_8436 = 0x01 ,
2556
+ MLXSW_SP_EEPROM_MODULE_INFO_REV_ID_8636 = 0x03 ,
2557
+ };
2558
+
2559
+ enum mlxsw_sp_eeprom_module_info_id {
2560
+ MLXSW_SP_EEPROM_MODULE_INFO_ID_SFP = 0x03 ,
2561
+ MLXSW_SP_EEPROM_MODULE_INFO_ID_QSFP = 0x0C ,
2562
+ MLXSW_SP_EEPROM_MODULE_INFO_ID_QSFP_PLUS = 0x0D ,
2563
+ MLXSW_SP_EEPROM_MODULE_INFO_ID_QSFP28 = 0x11 ,
2564
+ };
2565
+
2566
+ enum mlxsw_sp_eeprom_module_info {
2567
+ MLXSW_SP_EEPROM_MODULE_INFO_ID ,
2568
+ MLXSW_SP_EEPROM_MODULE_INFO_REV_ID ,
2569
+ MLXSW_SP_EEPROM_MODULE_INFO_SIZE ,
2570
+ };
2571
+
2572
+ static int mlxsw_sp_get_module_info (struct net_device * netdev ,
2573
+ struct ethtool_modinfo * modinfo )
2574
+ {
2575
+ struct mlxsw_sp_port * mlxsw_sp_port = netdev_priv (netdev );
2576
+ u8 module_info [MLXSW_SP_EEPROM_MODULE_INFO_SIZE ];
2577
+ u8 module_rev_id , module_id ;
2578
+ unsigned int read_size ;
2579
+ int err ;
2580
+
2581
+ err = mlxsw_sp_query_module_eeprom (mlxsw_sp_port , 0 ,
2582
+ MLXSW_SP_EEPROM_MODULE_INFO_SIZE ,
2583
+ module_info , & read_size );
2584
+ if (err )
2585
+ return err ;
2586
+
2587
+ if (read_size < MLXSW_SP_EEPROM_MODULE_INFO_SIZE )
2588
+ return - EIO ;
2589
+
2590
+ module_rev_id = module_info [MLXSW_SP_EEPROM_MODULE_INFO_REV_ID ];
2591
+ module_id = module_info [MLXSW_SP_EEPROM_MODULE_INFO_ID ];
2592
+
2593
+ switch (module_id ) {
2594
+ case MLXSW_SP_EEPROM_MODULE_INFO_ID_QSFP :
2595
+ modinfo -> type = ETH_MODULE_SFF_8436 ;
2596
+ modinfo -> eeprom_len = ETH_MODULE_SFF_8436_LEN ;
2597
+ break ;
2598
+ case MLXSW_SP_EEPROM_MODULE_INFO_ID_QSFP_PLUS :
2599
+ case MLXSW_SP_EEPROM_MODULE_INFO_ID_QSFP28 :
2600
+ if (module_id == MLXSW_SP_EEPROM_MODULE_INFO_ID_QSFP28 ||
2601
+ module_rev_id >= MLXSW_SP_EEPROM_MODULE_INFO_REV_ID_8636 ) {
2602
+ modinfo -> type = ETH_MODULE_SFF_8636 ;
2603
+ modinfo -> eeprom_len = ETH_MODULE_SFF_8636_LEN ;
2604
+ } else {
2605
+ modinfo -> type = ETH_MODULE_SFF_8436 ;
2606
+ modinfo -> eeprom_len = ETH_MODULE_SFF_8436_LEN ;
2607
+ }
2608
+ break ;
2609
+ case MLXSW_SP_EEPROM_MODULE_INFO_ID_SFP :
2610
+ modinfo -> type = ETH_MODULE_SFF_8472 ;
2611
+ modinfo -> eeprom_len = ETH_MODULE_SFF_8472_LEN ;
2612
+ break ;
2613
+ default :
2614
+ return - EINVAL ;
2615
+ }
2616
+
2617
+ return 0 ;
2618
+ }
2619
+
2620
+ static int mlxsw_sp_get_module_eeprom (struct net_device * netdev ,
2621
+ struct ethtool_eeprom * ee ,
2622
+ u8 * data )
2623
+ {
2624
+ struct mlxsw_sp_port * mlxsw_sp_port = netdev_priv (netdev );
2625
+ int offset = ee -> offset ;
2626
+ unsigned int read_size ;
2627
+ int i = 0 ;
2628
+ int err ;
2629
+
2630
+ if (!ee -> len )
2631
+ return - EINVAL ;
2632
+
2633
+ memset (data , 0 , ee -> len );
2634
+
2635
+ while (i < ee -> len ) {
2636
+ err = mlxsw_sp_query_module_eeprom (mlxsw_sp_port , offset ,
2637
+ ee -> len - i , data + i ,
2638
+ & read_size );
2639
+ if (err ) {
2640
+ netdev_err (mlxsw_sp_port -> dev , "Eeprom query failed\n" );
2641
+ return err ;
2642
+ }
2643
+
2644
+ i += read_size ;
2645
+ offset += read_size ;
2646
+ }
2647
+
2648
+ return 0 ;
2649
+ }
2650
+
2522
2651
static const struct ethtool_ops mlxsw_sp_port_ethtool_ops = {
2523
2652
.get_drvinfo = mlxsw_sp_port_get_drvinfo ,
2524
2653
.get_link = ethtool_op_get_link ,
@@ -2531,6 +2660,8 @@ static const struct ethtool_ops mlxsw_sp_port_ethtool_ops = {
2531
2660
.get_link_ksettings = mlxsw_sp_port_get_link_ksettings ,
2532
2661
.set_link_ksettings = mlxsw_sp_port_set_link_ksettings ,
2533
2662
.flash_device = mlxsw_sp_flash_device ,
2663
+ .get_module_info = mlxsw_sp_get_module_info ,
2664
+ .get_module_eeprom = mlxsw_sp_get_module_eeprom ,
2534
2665
};
2535
2666
2536
2667
static int
0 commit comments