1#include <linux/export.h>
2#include <linux/kref.h>
3#include <linux/list.h>
4#include <linux/mutex.h>
5#include <linux/phylink.h>
6#include <linux/property.h>
7#include <linux/rtnetlink.h>
8#include <linux/slab.h>
9
10#include "sfp.h"
11
12struct sfp_quirk {
13 const char *vendor;
14 const char *part;
15 void (*modes)(const struct sfp_eeprom_id *id, unsigned long *modes);
16};
17
18
19
20
21struct sfp_bus {
22
23 struct kref kref;
24 struct list_head node;
25 struct fwnode_handle *fwnode;
26
27 const struct sfp_socket_ops *socket_ops;
28 struct device *sfp_dev;
29 struct sfp *sfp;
30 const struct sfp_quirk *sfp_quirk;
31
32 const struct sfp_upstream_ops *upstream_ops;
33 void *upstream;
34 struct phy_device *phydev;
35
36 bool registered;
37 bool started;
38};
39
40static void sfp_quirk_2500basex(const struct sfp_eeprom_id *id,
41 unsigned long *modes)
42{
43 phylink_set(modes, 2500baseX_Full);
44}
45
46static const struct sfp_quirk sfp_quirks[] = {
47 {
48
49
50 .vendor = "ALCATELLUCENT",
51 .part = "G010SP",
52 .modes = sfp_quirk_2500basex,
53 }, {
54
55
56 .vendor = "ALCATELLUCENT",
57 .part = "3FE46541AA",
58 .modes = sfp_quirk_2500basex,
59 }, {
60
61
62 .vendor = "HUAWEI",
63 .part = "MA5671A",
64 .modes = sfp_quirk_2500basex,
65 },
66};
67
68static size_t sfp_strlen(const char *str, size_t maxlen)
69{
70 size_t size, i;
71
72
73 for (i = 0, size = 0; i < maxlen; i++)
74 if (str[i] != ' ')
75 size = i + 1;
76
77 return size;
78}
79
80static bool sfp_match(const char *qs, const char *str, size_t len)
81{
82 if (!qs)
83 return true;
84 if (strlen(qs) != len)
85 return false;
86 return !strncmp(qs, str, len);
87}
88
89static const struct sfp_quirk *sfp_lookup_quirk(const struct sfp_eeprom_id *id)
90{
91 const struct sfp_quirk *q;
92 unsigned int i;
93 size_t vs, ps;
94
95 vs = sfp_strlen(id->base.vendor_name, ARRAY_SIZE(id->base.vendor_name));
96 ps = sfp_strlen(id->base.vendor_pn, ARRAY_SIZE(id->base.vendor_pn));
97
98 for (i = 0, q = sfp_quirks; i < ARRAY_SIZE(sfp_quirks); i++, q++)
99 if (sfp_match(q->vendor, id->base.vendor_name, vs) &&
100 sfp_match(q->part, id->base.vendor_pn, ps))
101 return q;
102
103 return NULL;
104}
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120int sfp_parse_port(struct sfp_bus *bus, const struct sfp_eeprom_id *id,
121 unsigned long *support)
122{
123 int port;
124
125
126 switch (id->base.connector) {
127 case SFF8024_CONNECTOR_SC:
128 case SFF8024_CONNECTOR_FIBERJACK:
129 case SFF8024_CONNECTOR_LC:
130 case SFF8024_CONNECTOR_MT_RJ:
131 case SFF8024_CONNECTOR_MU:
132 case SFF8024_CONNECTOR_OPTICAL_PIGTAIL:
133 case SFF8024_CONNECTOR_MPO_1X12:
134 case SFF8024_CONNECTOR_MPO_2X16:
135 port = PORT_FIBRE;
136 break;
137
138 case SFF8024_CONNECTOR_RJ45:
139 port = PORT_TP;
140 break;
141
142 case SFF8024_CONNECTOR_COPPER_PIGTAIL:
143 port = PORT_DA;
144 break;
145
146 case SFF8024_CONNECTOR_UNSPEC:
147 if (id->base.e1000_base_t) {
148 port = PORT_TP;
149 break;
150 }
151
152 case SFF8024_CONNECTOR_SG:
153 case SFF8024_CONNECTOR_HSSDC_II:
154 case SFF8024_CONNECTOR_NOSEPARATE:
155 case SFF8024_CONNECTOR_MXC_2X16:
156 port = PORT_OTHER;
157 break;
158 default:
159 dev_warn(bus->sfp_dev, "SFP: unknown connector id 0x%02x\n",
160 id->base.connector);
161 port = PORT_OTHER;
162 break;
163 }
164
165 if (support) {
166 switch (port) {
167 case PORT_FIBRE:
168 phylink_set(support, FIBRE);
169 break;
170
171 case PORT_TP:
172 phylink_set(support, TP);
173 break;
174 }
175 }
176
177 return port;
178}
179EXPORT_SYMBOL_GPL(sfp_parse_port);
180
181
182
183
184
185
186
187
188
189bool sfp_may_have_phy(struct sfp_bus *bus, const struct sfp_eeprom_id *id)
190{
191 if (id->base.e1000_base_t)
192 return true;
193
194 if (id->base.phys_id != SFF8024_ID_DWDM_SFP) {
195 switch (id->base.extended_cc) {
196 case SFF8024_ECC_10GBASE_T_SFI:
197 case SFF8024_ECC_10GBASE_T_SR:
198 case SFF8024_ECC_5GBASE_T:
199 case SFF8024_ECC_2_5GBASE_T:
200 return true;
201 }
202 }
203
204 return false;
205}
206EXPORT_SYMBOL_GPL(sfp_may_have_phy);
207
208
209
210
211
212
213
214
215
216
217void sfp_parse_support(struct sfp_bus *bus, const struct sfp_eeprom_id *id,
218 unsigned long *support)
219{
220 unsigned int br_min, br_nom, br_max;
221 __ETHTOOL_DECLARE_LINK_MODE_MASK(modes) = { 0, };
222
223
224 br_min = br_nom = br_max = 0;
225 if (id->base.br_nominal) {
226 if (id->base.br_nominal != 255) {
227 br_nom = id->base.br_nominal * 100;
228 br_min = br_nom - id->base.br_nominal * id->ext.br_min;
229 br_max = br_nom + id->base.br_nominal * id->ext.br_max;
230 } else if (id->ext.br_max) {
231 br_nom = 250 * id->ext.br_max;
232 br_max = br_nom + br_nom * id->ext.br_min / 100;
233 br_min = br_nom - br_nom * id->ext.br_min / 100;
234 }
235
236
237
238
239
240 if (br_min == br_max && id->base.sfp_ct_passive)
241 br_min = 0;
242 }
243
244
245 if (id->base.e10g_base_sr)
246 phylink_set(modes, 10000baseSR_Full);
247 if (id->base.e10g_base_lr)
248 phylink_set(modes, 10000baseLR_Full);
249 if (id->base.e10g_base_lrm)
250 phylink_set(modes, 10000baseLRM_Full);
251 if (id->base.e10g_base_er)
252 phylink_set(modes, 10000baseER_Full);
253 if (id->base.e1000_base_sx ||
254 id->base.e1000_base_lx ||
255 id->base.e1000_base_cx)
256 phylink_set(modes, 1000baseX_Full);
257 if (id->base.e1000_base_t) {
258 phylink_set(modes, 1000baseT_Half);
259 phylink_set(modes, 1000baseT_Full);
260 }
261
262
263 if ((id->base.e_base_px || id->base.e_base_bx10) &&
264 br_min <= 1300 && br_max >= 1200)
265 phylink_set(modes, 1000baseX_Full);
266
267
268
269
270 if ((id->base.sfp_ct_passive || id->base.sfp_ct_active) && br_nom) {
271
272 if (br_min <= 12000 && br_max >= 10300)
273 phylink_set(modes, 10000baseCR_Full);
274 if (br_min <= 3200 && br_max >= 3100)
275 phylink_set(modes, 2500baseX_Full);
276 if (br_min <= 1300 && br_max >= 1200)
277 phylink_set(modes, 1000baseX_Full);
278 }
279 if (id->base.sfp_ct_passive) {
280 if (id->base.passive.sff8431_app_e)
281 phylink_set(modes, 10000baseCR_Full);
282 }
283 if (id->base.sfp_ct_active) {
284 if (id->base.active.sff8431_app_e ||
285 id->base.active.sff8431_lim) {
286 phylink_set(modes, 10000baseCR_Full);
287 }
288 }
289
290 switch (id->base.extended_cc) {
291 case SFF8024_ECC_UNSPEC:
292 break;
293 case SFF8024_ECC_100GBASE_SR4_25GBASE_SR:
294 phylink_set(modes, 100000baseSR4_Full);
295 phylink_set(modes, 25000baseSR_Full);
296 break;
297 case SFF8024_ECC_100GBASE_LR4_25GBASE_LR:
298 case SFF8024_ECC_100GBASE_ER4_25GBASE_ER:
299 phylink_set(modes, 100000baseLR4_ER4_Full);
300 break;
301 case SFF8024_ECC_100GBASE_CR4:
302 phylink_set(modes, 100000baseCR4_Full);
303
304 case SFF8024_ECC_25GBASE_CR_S:
305 case SFF8024_ECC_25GBASE_CR_N:
306 phylink_set(modes, 25000baseCR_Full);
307 break;
308 case SFF8024_ECC_10GBASE_T_SFI:
309 case SFF8024_ECC_10GBASE_T_SR:
310 phylink_set(modes, 10000baseT_Full);
311 break;
312 case SFF8024_ECC_5GBASE_T:
313 phylink_set(modes, 5000baseT_Full);
314 break;
315 case SFF8024_ECC_2_5GBASE_T:
316 phylink_set(modes, 2500baseT_Full);
317 break;
318 default:
319 dev_warn(bus->sfp_dev,
320 "Unknown/unsupported extended compliance code: 0x%02x\n",
321 id->base.extended_cc);
322 break;
323 }
324
325
326 if (id->base.fc_speed_100 ||
327 id->base.fc_speed_200 ||
328 id->base.fc_speed_400) {
329 if (id->base.br_nominal >= 31)
330 phylink_set(modes, 2500baseX_Full);
331 if (id->base.br_nominal >= 12)
332 phylink_set(modes, 1000baseX_Full);
333 }
334
335
336
337
338
339
340 if (bitmap_empty(modes, __ETHTOOL_LINK_MODE_MASK_NBITS)) {
341
342 if (id->base.encoding == SFF8024_ENCODING_8B10B && br_nom &&
343 br_min <= 1300 && br_max >= 1200)
344 phylink_set(modes, 1000baseX_Full);
345 }
346
347 if (bus->sfp_quirk)
348 bus->sfp_quirk->modes(id, modes);
349
350 bitmap_or(support, support, modes, __ETHTOOL_LINK_MODE_MASK_NBITS);
351
352 phylink_set(support, Autoneg);
353 phylink_set(support, Pause);
354 phylink_set(support, Asym_Pause);
355}
356EXPORT_SYMBOL_GPL(sfp_parse_support);
357
358
359
360
361
362
363
364
365
366phy_interface_t sfp_select_interface(struct sfp_bus *bus,
367 unsigned long *link_modes)
368{
369 if (phylink_test(link_modes, 10000baseCR_Full) ||
370 phylink_test(link_modes, 10000baseSR_Full) ||
371 phylink_test(link_modes, 10000baseLR_Full) ||
372 phylink_test(link_modes, 10000baseLRM_Full) ||
373 phylink_test(link_modes, 10000baseER_Full) ||
374 phylink_test(link_modes, 10000baseT_Full))
375 return PHY_INTERFACE_MODE_10GKR;
376
377 if (phylink_test(link_modes, 2500baseX_Full))
378 return PHY_INTERFACE_MODE_2500BASEX;
379
380 if (phylink_test(link_modes, 1000baseT_Half) ||
381 phylink_test(link_modes, 1000baseT_Full))
382 return PHY_INTERFACE_MODE_SGMII;
383
384 if (phylink_test(link_modes, 1000baseX_Full))
385 return PHY_INTERFACE_MODE_1000BASEX;
386
387 dev_warn(bus->sfp_dev, "Unable to ascertain link mode\n");
388
389 return PHY_INTERFACE_MODE_NA;
390}
391EXPORT_SYMBOL_GPL(sfp_select_interface);
392
393static LIST_HEAD(sfp_buses);
394static DEFINE_MUTEX(sfp_mutex);
395
396static const struct sfp_upstream_ops *sfp_get_upstream_ops(struct sfp_bus *bus)
397{
398 return bus->registered ? bus->upstream_ops : NULL;
399}
400
401static struct sfp_bus *sfp_bus_get(struct fwnode_handle *fwnode)
402{
403 struct sfp_bus *sfp, *new, *found = NULL;
404
405 new = kzalloc(sizeof(*new), GFP_KERNEL);
406
407 mutex_lock(&sfp_mutex);
408
409 list_for_each_entry(sfp, &sfp_buses, node) {
410 if (sfp->fwnode == fwnode) {
411 kref_get(&sfp->kref);
412 found = sfp;
413 break;
414 }
415 }
416
417 if (!found && new) {
418 kref_init(&new->kref);
419 new->fwnode = fwnode;
420 list_add(&new->node, &sfp_buses);
421 found = new;
422 new = NULL;
423 }
424
425 mutex_unlock(&sfp_mutex);
426
427 kfree(new);
428
429 return found;
430}
431
432static void sfp_bus_release(struct kref *kref)
433{
434 struct sfp_bus *bus = container_of(kref, struct sfp_bus, kref);
435
436 list_del(&bus->node);
437 mutex_unlock(&sfp_mutex);
438 kfree(bus);
439}
440
441
442
443
444
445
446
447
448void sfp_bus_put(struct sfp_bus *bus)
449{
450 if (bus)
451 kref_put_mutex(&bus->kref, sfp_bus_release, &sfp_mutex);
452}
453EXPORT_SYMBOL_GPL(sfp_bus_put);
454
455static int sfp_register_bus(struct sfp_bus *bus)
456{
457 const struct sfp_upstream_ops *ops = bus->upstream_ops;
458 int ret;
459
460 if (ops) {
461 if (ops->link_down)
462 ops->link_down(bus->upstream);
463 if (ops->connect_phy && bus->phydev) {
464 ret = ops->connect_phy(bus->upstream, bus->phydev);
465 if (ret)
466 return ret;
467 }
468 }
469 bus->registered = true;
470 bus->socket_ops->attach(bus->sfp);
471 if (bus->started)
472 bus->socket_ops->start(bus->sfp);
473 bus->upstream_ops->attach(bus->upstream, bus);
474 return 0;
475}
476
477static void sfp_unregister_bus(struct sfp_bus *bus)
478{
479 const struct sfp_upstream_ops *ops = bus->upstream_ops;
480
481 if (bus->registered) {
482 bus->upstream_ops->detach(bus->upstream, bus);
483 if (bus->started)
484 bus->socket_ops->stop(bus->sfp);
485 bus->socket_ops->detach(bus->sfp);
486 if (bus->phydev && ops && ops->disconnect_phy)
487 ops->disconnect_phy(bus->upstream);
488 }
489 bus->registered = false;
490}
491
492
493
494
495
496
497
498
499
500
501
502int sfp_get_module_info(struct sfp_bus *bus, struct ethtool_modinfo *modinfo)
503{
504 return bus->socket_ops->module_info(bus->sfp, modinfo);
505}
506EXPORT_SYMBOL_GPL(sfp_get_module_info);
507
508
509
510
511
512
513
514
515
516
517
518
519int sfp_get_module_eeprom(struct sfp_bus *bus, struct ethtool_eeprom *ee,
520 u8 *data)
521{
522 return bus->socket_ops->module_eeprom(bus->sfp, ee, data);
523}
524EXPORT_SYMBOL_GPL(sfp_get_module_eeprom);
525
526
527
528
529
530
531
532
533
534
535void sfp_upstream_start(struct sfp_bus *bus)
536{
537 if (bus->registered)
538 bus->socket_ops->start(bus->sfp);
539 bus->started = true;
540}
541EXPORT_SYMBOL_GPL(sfp_upstream_start);
542
543
544
545
546
547
548
549
550
551
552void sfp_upstream_stop(struct sfp_bus *bus)
553{
554 if (bus->registered)
555 bus->socket_ops->stop(bus->sfp);
556 bus->started = false;
557}
558EXPORT_SYMBOL_GPL(sfp_upstream_stop);
559
560static void sfp_upstream_clear(struct sfp_bus *bus)
561{
562 bus->upstream_ops = NULL;
563 bus->upstream = NULL;
564}
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584struct sfp_bus *sfp_bus_find_fwnode(struct fwnode_handle *fwnode)
585{
586 struct fwnode_reference_args ref;
587 struct sfp_bus *bus;
588 int ret;
589
590 ret = fwnode_property_get_reference_args(fwnode, "sfp", NULL,
591 0, 0, &ref);
592 if (ret == -ENOENT)
593 return NULL;
594 else if (ret < 0)
595 return ERR_PTR(ret);
596
597 bus = sfp_bus_get(ref.fwnode);
598 fwnode_handle_put(ref.fwnode);
599 if (!bus)
600 return ERR_PTR(-ENOMEM);
601
602 return bus;
603}
604EXPORT_SYMBOL_GPL(sfp_bus_find_fwnode);
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626int sfp_bus_add_upstream(struct sfp_bus *bus, void *upstream,
627 const struct sfp_upstream_ops *ops)
628{
629 int ret;
630
631
632 if (!bus)
633 return 0;
634
635 rtnl_lock();
636 kref_get(&bus->kref);
637 bus->upstream_ops = ops;
638 bus->upstream = upstream;
639
640 if (bus->sfp) {
641 ret = sfp_register_bus(bus);
642 if (ret)
643 sfp_upstream_clear(bus);
644 } else {
645 ret = 0;
646 }
647 rtnl_unlock();
648
649 if (ret)
650 sfp_bus_put(bus);
651
652 return ret;
653}
654EXPORT_SYMBOL_GPL(sfp_bus_add_upstream);
655
656
657
658
659
660
661
662
663void sfp_bus_del_upstream(struct sfp_bus *bus)
664{
665 if (bus) {
666 rtnl_lock();
667 if (bus->sfp)
668 sfp_unregister_bus(bus);
669 sfp_upstream_clear(bus);
670 rtnl_unlock();
671
672 sfp_bus_put(bus);
673 }
674}
675EXPORT_SYMBOL_GPL(sfp_bus_del_upstream);
676
677
678int sfp_add_phy(struct sfp_bus *bus, struct phy_device *phydev)
679{
680 const struct sfp_upstream_ops *ops = sfp_get_upstream_ops(bus);
681 int ret = 0;
682
683 if (ops && ops->connect_phy)
684 ret = ops->connect_phy(bus->upstream, phydev);
685
686 if (ret == 0)
687 bus->phydev = phydev;
688
689 return ret;
690}
691EXPORT_SYMBOL_GPL(sfp_add_phy);
692
693void sfp_remove_phy(struct sfp_bus *bus)
694{
695 const struct sfp_upstream_ops *ops = sfp_get_upstream_ops(bus);
696
697 if (ops && ops->disconnect_phy)
698 ops->disconnect_phy(bus->upstream);
699 bus->phydev = NULL;
700}
701EXPORT_SYMBOL_GPL(sfp_remove_phy);
702
703void sfp_link_up(struct sfp_bus *bus)
704{
705 const struct sfp_upstream_ops *ops = sfp_get_upstream_ops(bus);
706
707 if (ops && ops->link_up)
708 ops->link_up(bus->upstream);
709}
710EXPORT_SYMBOL_GPL(sfp_link_up);
711
712void sfp_link_down(struct sfp_bus *bus)
713{
714 const struct sfp_upstream_ops *ops = sfp_get_upstream_ops(bus);
715
716 if (ops && ops->link_down)
717 ops->link_down(bus->upstream);
718}
719EXPORT_SYMBOL_GPL(sfp_link_down);
720
721int sfp_module_insert(struct sfp_bus *bus, const struct sfp_eeprom_id *id)
722{
723 const struct sfp_upstream_ops *ops = sfp_get_upstream_ops(bus);
724 int ret = 0;
725
726 bus->sfp_quirk = sfp_lookup_quirk(id);
727
728 if (ops && ops->module_insert)
729 ret = ops->module_insert(bus->upstream, id);
730
731 return ret;
732}
733EXPORT_SYMBOL_GPL(sfp_module_insert);
734
735void sfp_module_remove(struct sfp_bus *bus)
736{
737 const struct sfp_upstream_ops *ops = sfp_get_upstream_ops(bus);
738
739 if (ops && ops->module_remove)
740 ops->module_remove(bus->upstream);
741
742 bus->sfp_quirk = NULL;
743}
744EXPORT_SYMBOL_GPL(sfp_module_remove);
745
746int sfp_module_start(struct sfp_bus *bus)
747{
748 const struct sfp_upstream_ops *ops = sfp_get_upstream_ops(bus);
749 int ret = 0;
750
751 if (ops && ops->module_start)
752 ret = ops->module_start(bus->upstream);
753
754 return ret;
755}
756EXPORT_SYMBOL_GPL(sfp_module_start);
757
758void sfp_module_stop(struct sfp_bus *bus)
759{
760 const struct sfp_upstream_ops *ops = sfp_get_upstream_ops(bus);
761
762 if (ops && ops->module_stop)
763 ops->module_stop(bus->upstream);
764}
765EXPORT_SYMBOL_GPL(sfp_module_stop);
766
767static void sfp_socket_clear(struct sfp_bus *bus)
768{
769 bus->sfp_dev = NULL;
770 bus->sfp = NULL;
771 bus->socket_ops = NULL;
772}
773
774struct sfp_bus *sfp_register_socket(struct device *dev, struct sfp *sfp,
775 const struct sfp_socket_ops *ops)
776{
777 struct sfp_bus *bus = sfp_bus_get(dev->fwnode);
778 int ret = 0;
779
780 if (bus) {
781 rtnl_lock();
782 bus->sfp_dev = dev;
783 bus->sfp = sfp;
784 bus->socket_ops = ops;
785
786 if (bus->upstream_ops) {
787 ret = sfp_register_bus(bus);
788 if (ret)
789 sfp_socket_clear(bus);
790 }
791 rtnl_unlock();
792 }
793
794 if (ret) {
795 sfp_bus_put(bus);
796 bus = NULL;
797 }
798
799 return bus;
800}
801EXPORT_SYMBOL_GPL(sfp_register_socket);
802
803void sfp_unregister_socket(struct sfp_bus *bus)
804{
805 rtnl_lock();
806 if (bus->upstream_ops)
807 sfp_unregister_bus(bus);
808 sfp_socket_clear(bus);
809 rtnl_unlock();
810
811 sfp_bus_put(bus);
812}
813EXPORT_SYMBOL_GPL(sfp_unregister_socket);
814