1010
1111#include "sfp.h"
1212
13+ struct sfp_quirk {
14+ const char * vendor ;
15+ const char * part ;
16+ void (* modes )(const struct sfp_eeprom_id * id , unsigned long * modes );
17+ };
18+
1319/**
1420 * struct sfp_bus - internal representation of a sfp bus
1521 */
@@ -22,6 +28,7 @@ struct sfp_bus {
2228 const struct sfp_socket_ops * socket_ops ;
2329 struct device * sfp_dev ;
2430 struct sfp * sfp ;
31+ const struct sfp_quirk * sfp_quirk ;
2532
2633 const struct sfp_upstream_ops * upstream_ops ;
2734 void * upstream ;
@@ -31,6 +38,46 @@ struct sfp_bus {
3138 bool started ;
3239};
3340
41+ static const struct sfp_quirk sfp_quirks [] = {
42+ };
43+
44+ static size_t sfp_strlen (const char * str , size_t maxlen )
45+ {
46+ size_t size , i ;
47+
48+ /* Trailing characters should be filled with space chars */
49+ for (i = 0 , size = 0 ; i < maxlen ; i ++ )
50+ if (str [i ] != ' ' )
51+ size = i + 1 ;
52+
53+ return size ;
54+ }
55+
56+ static bool sfp_match (const char * qs , const char * str , size_t len )
57+ {
58+ if (!qs )
59+ return true;
60+ if (strlen (qs ) != len )
61+ return false;
62+ return !strncmp (qs , str , len );
63+ }
64+
65+ static const struct sfp_quirk * sfp_lookup_quirk (const struct sfp_eeprom_id * id )
66+ {
67+ const struct sfp_quirk * q ;
68+ unsigned int i ;
69+ size_t vs , ps ;
70+
71+ vs = sfp_strlen (id -> base .vendor_name , ARRAY_SIZE (id -> base .vendor_name ));
72+ ps = sfp_strlen (id -> base .vendor_pn , ARRAY_SIZE (id -> base .vendor_pn ));
73+
74+ for (i = 0 , q = sfp_quirks ; i < ARRAY_SIZE (sfp_quirks ); i ++ , q ++ )
75+ if (sfp_match (q -> vendor , id -> base .vendor_name , vs ) &&
76+ sfp_match (q -> part , id -> base .vendor_pn , ps ))
77+ return q ;
78+
79+ return NULL ;
80+ }
3481/**
3582 * sfp_parse_port() - Parse the EEPROM base ID, setting the port type
3683 * @bus: a pointer to the &struct sfp_bus structure for the sfp module
@@ -234,6 +281,9 @@ void sfp_parse_support(struct sfp_bus *bus, const struct sfp_eeprom_id *id,
234281 phylink_set (modes , 1000b aseX_Full );
235282 }
236283
284+ if (bus -> sfp_quirk )
285+ bus -> sfp_quirk -> modes (id , modes );
286+
237287 bitmap_or (support , support , modes , __ETHTOOL_LINK_MODE_MASK_NBITS );
238288
239289 phylink_set (support , Autoneg );
@@ -610,6 +660,8 @@ int sfp_module_insert(struct sfp_bus *bus, const struct sfp_eeprom_id *id)
610660 const struct sfp_upstream_ops * ops = sfp_get_upstream_ops (bus );
611661 int ret = 0 ;
612662
663+ bus -> sfp_quirk = sfp_lookup_quirk (id );
664+
613665 if (ops && ops -> module_insert )
614666 ret = ops -> module_insert (bus -> upstream , id );
615667
@@ -623,6 +675,8 @@ void sfp_module_remove(struct sfp_bus *bus)
623675
624676 if (ops && ops -> module_remove )
625677 ops -> module_remove (bus -> upstream );
678+
679+ bus -> sfp_quirk = NULL ;
626680}
627681EXPORT_SYMBOL_GPL (sfp_module_remove );
628682
0 commit comments