@@ -234,6 +234,7 @@ struct sfp {
234
234
enum mdio_i2c_proto mdio_protocol ;
235
235
struct phy_device * mod_phy ;
236
236
const struct sff_data * type ;
237
+ size_t i2c_max_block_size ;
237
238
size_t i2c_block_size ;
238
239
u32 max_power_mW ;
239
240
@@ -691,14 +692,71 @@ static int sfp_i2c_write(struct sfp *sfp, bool a2, u8 dev_addr, void *buf,
691
692
return ret == ARRAY_SIZE (msgs ) ? len : 0 ;
692
693
}
693
694
694
- static int sfp_i2c_configure (struct sfp * sfp , struct i2c_adapter * i2c )
695
+ static int sfp_smbus_byte_read (struct sfp * sfp , bool a2 , u8 dev_addr ,
696
+ void * buf , size_t len )
695
697
{
696
- if (!i2c_check_functionality (i2c , I2C_FUNC_I2C ))
697
- return - EINVAL ;
698
+ union i2c_smbus_data smbus_data ;
699
+ u8 bus_addr = a2 ? 0x51 : 0x50 ;
700
+ u8 * data = buf ;
701
+ int ret ;
702
+
703
+ while (len ) {
704
+ ret = i2c_smbus_xfer (sfp -> i2c , bus_addr , 0 ,
705
+ I2C_SMBUS_READ , dev_addr ,
706
+ I2C_SMBUS_BYTE_DATA , & smbus_data );
707
+ if (ret < 0 )
708
+ return ret ;
709
+
710
+ * data = smbus_data .byte ;
711
+
712
+ len -- ;
713
+ data ++ ;
714
+ dev_addr ++ ;
715
+ }
716
+
717
+ return data - (u8 * )buf ;
718
+ }
719
+
720
+ static int sfp_smbus_byte_write (struct sfp * sfp , bool a2 , u8 dev_addr ,
721
+ void * buf , size_t len )
722
+ {
723
+ union i2c_smbus_data smbus_data ;
724
+ u8 bus_addr = a2 ? 0x51 : 0x50 ;
725
+ u8 * data = buf ;
726
+ int ret ;
698
727
728
+ while (len ) {
729
+ smbus_data .byte = * data ;
730
+ ret = i2c_smbus_xfer (sfp -> i2c , bus_addr , 0 ,
731
+ I2C_SMBUS_WRITE , dev_addr ,
732
+ I2C_SMBUS_BYTE_DATA , & smbus_data );
733
+ if (ret )
734
+ return ret ;
735
+
736
+ len -- ;
737
+ data ++ ;
738
+ dev_addr ++ ;
739
+ }
740
+
741
+ return 0 ;
742
+ }
743
+
744
+ static int sfp_i2c_configure (struct sfp * sfp , struct i2c_adapter * i2c )
745
+ {
699
746
sfp -> i2c = i2c ;
700
- sfp -> read = sfp_i2c_read ;
701
- sfp -> write = sfp_i2c_write ;
747
+
748
+ if (i2c_check_functionality (i2c , I2C_FUNC_I2C )) {
749
+ sfp -> read = sfp_i2c_read ;
750
+ sfp -> write = sfp_i2c_write ;
751
+ sfp -> i2c_max_block_size = SFP_EEPROM_BLOCK_SIZE ;
752
+ } else if (i2c_check_functionality (i2c , I2C_FUNC_SMBUS_BYTE_DATA )) {
753
+ sfp -> read = sfp_smbus_byte_read ;
754
+ sfp -> write = sfp_smbus_byte_write ;
755
+ sfp -> i2c_max_block_size = 1 ;
756
+ } else {
757
+ sfp -> i2c = NULL ;
758
+ return - EINVAL ;
759
+ }
702
760
703
761
return 0 ;
704
762
}
@@ -1594,7 +1652,7 @@ static void sfp_hwmon_probe(struct work_struct *work)
1594
1652
*/
1595
1653
if (sfp -> i2c_block_size < 2 ) {
1596
1654
dev_info (sfp -> dev ,
1597
- "skipping hwmon device registration due to broken EEPROM \n" );
1655
+ "skipping hwmon device registration\n" );
1598
1656
dev_info (sfp -> dev ,
1599
1657
"diagnostic EEPROM area cannot be read atomically to guarantee data coherency\n" );
1600
1658
return ;
@@ -2201,7 +2259,7 @@ static int sfp_sm_mod_probe(struct sfp *sfp, bool report)
2201
2259
u8 check ;
2202
2260
int ret ;
2203
2261
2204
- sfp -> i2c_block_size = SFP_EEPROM_BLOCK_SIZE ;
2262
+ sfp -> i2c_block_size = sfp -> i2c_max_block_size ;
2205
2263
2206
2264
ret = sfp_read (sfp , false, 0 , & id .base , sizeof (id .base ));
2207
2265
if (ret < 0 ) {
@@ -2941,7 +2999,6 @@ static struct sfp *sfp_alloc(struct device *dev)
2941
2999
return ERR_PTR (- ENOMEM );
2942
3000
2943
3001
sfp -> dev = dev ;
2944
- sfp -> i2c_block_size = SFP_EEPROM_BLOCK_SIZE ;
2945
3002
2946
3003
mutex_init (& sfp -> sm_mutex );
2947
3004
mutex_init (& sfp -> st_mutex );
@@ -3115,6 +3172,15 @@ static int sfp_probe(struct platform_device *pdev)
3115
3172
if (!sfp -> sfp_bus )
3116
3173
return - ENOMEM ;
3117
3174
3175
+ if (sfp -> i2c_max_block_size < 2 )
3176
+ dev_warn (sfp -> dev ,
3177
+ "Please note:\n"
3178
+ "This SFP cage is accessed via an SMBus only capable of single byte\n"
3179
+ "transactions. Some features are disabled, other may be unreliable or\n"
3180
+ "sporadically fail. Use with caution. There is nothing that the kernel\n"
3181
+ "or community can do to fix it, the kernel will try best efforts. Please\n"
3182
+ "verify any problems on hardware that supports multi-byte I2C transactions.\n" );
3183
+
3118
3184
sfp_debugfs_init (sfp );
3119
3185
3120
3186
return 0 ;
0 commit comments