Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

sfp: add sfp-bus to bridge between network devices and sfp cages

Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Russell King and committed by
David S. Miller
ce0aa27f 9525ae83

+1097
+3
drivers/net/phy/Makefile
··· 38 38 obj-$(CONFIG_MDIO_THUNDER) += mdio-thunder.o 39 39 obj-$(CONFIG_MDIO_XGENE) += mdio-xgene.o 40 40 41 + sfp-obj-$(CONFIG_SFP) += sfp-bus.o 42 + obj-y += $(sfp-obj-y) $(sfp-obj-m) 43 + 41 44 obj-$(CONFIG_AMD_PHY) += amd.o 42 45 obj-$(CONFIG_AQUANTIA_PHY) += aquantia.o 43 46 obj-$(CONFIG_AT803X_PHY) += at803x.o
+157
drivers/net/phy/phylink.c
··· 21 21 #include <linux/spinlock.h> 22 22 #include <linux/workqueue.h> 23 23 24 + #include "sfp.h" 24 25 #include "swphy.h" 25 26 26 27 #define SUPPORTED_INTERFACES \ ··· 33 32 34 33 enum { 35 34 PHYLINK_DISABLE_STOPPED, 35 + PHYLINK_DISABLE_LINK, 36 36 }; 37 37 38 38 struct phylink { ··· 56 54 struct work_struct resolve; 57 55 58 56 bool mac_link_dropped; 57 + 58 + struct sfp_bus *sfp_bus; 59 59 }; 60 60 61 61 static inline void linkmode_zero(unsigned long *dst) ··· 470 466 queue_work(system_power_efficient_wq, &pl->resolve); 471 467 } 472 468 469 + static const struct sfp_upstream_ops sfp_phylink_ops; 470 + 471 + static int phylink_register_sfp(struct phylink *pl, struct device_node *np) 472 + { 473 + struct device_node *sfp_np; 474 + 475 + sfp_np = of_parse_phandle(np, "sfp", 0); 476 + if (!sfp_np) 477 + return 0; 478 + 479 + pl->sfp_bus = sfp_register_upstream(sfp_np, pl->netdev, pl, 480 + &sfp_phylink_ops); 481 + if (!pl->sfp_bus) 482 + return -ENOMEM; 483 + 484 + return 0; 485 + } 486 + 473 487 struct phylink *phylink_create(struct net_device *ndev, struct device_node *np, 474 488 phy_interface_t iface, const struct phylink_mac_ops *ops) 475 489 { ··· 529 507 } 530 508 } 531 509 510 + ret = phylink_register_sfp(pl, np); 511 + if (ret < 0) { 512 + kfree(pl); 513 + return ERR_PTR(ret); 514 + } 515 + 532 516 return pl; 533 517 } 534 518 EXPORT_SYMBOL_GPL(phylink_create); 535 519 536 520 void phylink_destroy(struct phylink *pl) 537 521 { 522 + if (pl->sfp_bus) 523 + sfp_unregister_upstream(pl->sfp_bus); 524 + 538 525 cancel_work_sync(&pl->resolve); 539 526 kfree(pl); 540 527 } ··· 737 706 clear_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state); 738 707 phylink_run_resolve(pl); 739 708 709 + if (pl->sfp_bus) 710 + sfp_upstream_start(pl->sfp_bus); 740 711 if (pl->phydev) 741 712 phy_start(pl->phydev); 742 713 } ··· 750 717 751 718 if (pl->phydev) 752 719 phy_stop(pl->phydev); 720 + if (pl->sfp_bus) 721 + sfp_upstream_stop(pl->sfp_bus); 753 722 754 723 set_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state); 755 724 flush_work(&pl->resolve); ··· 1200 1165 return ret; 1201 1166 } 1202 1167 EXPORT_SYMBOL_GPL(phylink_mii_ioctl); 1168 + 1169 + 1170 + 1171 + static int phylink_sfp_module_insert(void *upstream, 1172 + const struct sfp_eeprom_id *id) 1173 + { 1174 + struct phylink *pl = upstream; 1175 + __ETHTOOL_DECLARE_LINK_MODE_MASK(support) = { 0, }; 1176 + struct phylink_link_state config; 1177 + phy_interface_t iface; 1178 + int mode, ret = 0; 1179 + bool changed; 1180 + u8 port; 1181 + 1182 + sfp_parse_support(pl->sfp_bus, id, support); 1183 + port = sfp_parse_port(pl->sfp_bus, id, support); 1184 + iface = sfp_parse_interface(pl->sfp_bus, id); 1185 + 1186 + WARN_ON(!lockdep_rtnl_is_held()); 1187 + 1188 + switch (iface) { 1189 + case PHY_INTERFACE_MODE_SGMII: 1190 + mode = MLO_AN_SGMII; 1191 + break; 1192 + case PHY_INTERFACE_MODE_1000BASEX: 1193 + mode = MLO_AN_8023Z; 1194 + break; 1195 + default: 1196 + return -EINVAL; 1197 + } 1198 + 1199 + memset(&config, 0, sizeof(config)); 1200 + linkmode_copy(config.advertising, support); 1201 + config.interface = iface; 1202 + config.speed = SPEED_UNKNOWN; 1203 + config.duplex = DUPLEX_UNKNOWN; 1204 + config.pause = MLO_PAUSE_AN; 1205 + config.an_enabled = pl->link_config.an_enabled; 1206 + 1207 + /* Ignore errors if we're expecting a PHY to attach later */ 1208 + ret = phylink_validate(pl, support, &config); 1209 + if (ret) { 1210 + netdev_err(pl->netdev, "validation of %s/%s with support %*pb failed: %d\n", 1211 + phylink_an_mode_str(mode), phy_modes(config.interface), 1212 + __ETHTOOL_LINK_MODE_MASK_NBITS, support, ret); 1213 + return ret; 1214 + } 1215 + 1216 + netdev_dbg(pl->netdev, "requesting link mode %s/%s with support %*pb\n", 1217 + phylink_an_mode_str(mode), phy_modes(config.interface), 1218 + __ETHTOOL_LINK_MODE_MASK_NBITS, support); 1219 + 1220 + if (mode == MLO_AN_8023Z && pl->phydev) 1221 + return -EINVAL; 1222 + 1223 + changed = !bitmap_equal(pl->supported, support, 1224 + __ETHTOOL_LINK_MODE_MASK_NBITS); 1225 + if (changed) { 1226 + linkmode_copy(pl->supported, support); 1227 + linkmode_copy(pl->link_config.advertising, config.advertising); 1228 + } 1229 + 1230 + if (pl->link_an_mode != mode || 1231 + pl->link_config.interface != config.interface) { 1232 + pl->link_config.interface = config.interface; 1233 + pl->link_an_mode = mode; 1234 + 1235 + changed = true; 1236 + 1237 + netdev_info(pl->netdev, "switched to %s/%s link mode\n", 1238 + phylink_an_mode_str(mode), 1239 + phy_modes(config.interface)); 1240 + } 1241 + 1242 + pl->link_port = port; 1243 + 1244 + if (changed && !test_bit(PHYLINK_DISABLE_STOPPED, 1245 + &pl->phylink_disable_state)) 1246 + phylink_mac_config(pl, &pl->link_config); 1247 + 1248 + return ret; 1249 + } 1250 + 1251 + static void phylink_sfp_link_down(void *upstream) 1252 + { 1253 + struct phylink *pl = upstream; 1254 + 1255 + WARN_ON(!lockdep_rtnl_is_held()); 1256 + 1257 + set_bit(PHYLINK_DISABLE_LINK, &pl->phylink_disable_state); 1258 + flush_work(&pl->resolve); 1259 + 1260 + netif_carrier_off(pl->netdev); 1261 + } 1262 + 1263 + static void phylink_sfp_link_up(void *upstream) 1264 + { 1265 + struct phylink *pl = upstream; 1266 + 1267 + WARN_ON(!lockdep_rtnl_is_held()); 1268 + 1269 + clear_bit(PHYLINK_DISABLE_LINK, &pl->phylink_disable_state); 1270 + phylink_run_resolve(pl); 1271 + } 1272 + 1273 + static int phylink_sfp_connect_phy(void *upstream, struct phy_device *phy) 1274 + { 1275 + return phylink_connect_phy(upstream, phy); 1276 + } 1277 + 1278 + static void phylink_sfp_disconnect_phy(void *upstream) 1279 + { 1280 + phylink_disconnect_phy(upstream); 1281 + } 1282 + 1283 + static const struct sfp_upstream_ops sfp_phylink_ops = { 1284 + .module_insert = phylink_sfp_module_insert, 1285 + .link_up = phylink_sfp_link_up, 1286 + .link_down = phylink_sfp_link_down, 1287 + .connect_phy = phylink_sfp_connect_phy, 1288 + .disconnect_phy = phylink_sfp_disconnect_phy, 1289 + }; 1203 1290 1204 1291 MODULE_LICENSE("GPL");
+475
drivers/net/phy/sfp-bus.c
··· 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/rtnetlink.h> 7 + #include <linux/slab.h> 8 + 9 + #include "sfp.h" 10 + 11 + struct sfp_bus { 12 + struct kref kref; 13 + struct list_head node; 14 + struct device_node *device_node; 15 + 16 + const struct sfp_socket_ops *socket_ops; 17 + struct device *sfp_dev; 18 + struct sfp *sfp; 19 + 20 + const struct sfp_upstream_ops *upstream_ops; 21 + void *upstream; 22 + struct net_device *netdev; 23 + struct phy_device *phydev; 24 + 25 + bool registered; 26 + bool started; 27 + }; 28 + 29 + 30 + int sfp_parse_port(struct sfp_bus *bus, const struct sfp_eeprom_id *id, 31 + unsigned long *support) 32 + { 33 + int port; 34 + 35 + /* port is the physical connector, set this from the connector field. */ 36 + switch (id->base.connector) { 37 + case SFP_CONNECTOR_SC: 38 + case SFP_CONNECTOR_FIBERJACK: 39 + case SFP_CONNECTOR_LC: 40 + case SFP_CONNECTOR_MT_RJ: 41 + case SFP_CONNECTOR_MU: 42 + case SFP_CONNECTOR_OPTICAL_PIGTAIL: 43 + if (support) 44 + phylink_set(support, FIBRE); 45 + port = PORT_FIBRE; 46 + break; 47 + 48 + case SFP_CONNECTOR_RJ45: 49 + if (support) 50 + phylink_set(support, TP); 51 + port = PORT_TP; 52 + break; 53 + 54 + case SFP_CONNECTOR_UNSPEC: 55 + if (id->base.e1000_base_t) { 56 + if (support) 57 + phylink_set(support, TP); 58 + port = PORT_TP; 59 + break; 60 + } 61 + /* fallthrough */ 62 + case SFP_CONNECTOR_SG: /* guess */ 63 + case SFP_CONNECTOR_MPO_1X12: 64 + case SFP_CONNECTOR_MPO_2X16: 65 + case SFP_CONNECTOR_HSSDC_II: 66 + case SFP_CONNECTOR_COPPER_PIGTAIL: 67 + case SFP_CONNECTOR_NOSEPARATE: 68 + case SFP_CONNECTOR_MXC_2X16: 69 + port = PORT_OTHER; 70 + break; 71 + default: 72 + dev_warn(bus->sfp_dev, "SFP: unknown connector id 0x%02x\n", 73 + id->base.connector); 74 + port = PORT_OTHER; 75 + break; 76 + } 77 + 78 + return port; 79 + } 80 + EXPORT_SYMBOL_GPL(sfp_parse_port); 81 + 82 + phy_interface_t sfp_parse_interface(struct sfp_bus *bus, 83 + const struct sfp_eeprom_id *id) 84 + { 85 + phy_interface_t iface; 86 + 87 + /* Setting the serdes link mode is guesswork: there's no field in 88 + * the EEPROM which indicates what mode should be used. 89 + * 90 + * If the module wants 64b66b, then it must be >= 10G. 91 + * 92 + * If it's a gigabit-only fiber module, it probably does not have 93 + * a PHY, so switch to 802.3z negotiation mode. Otherwise, switch 94 + * to SGMII mode (which is required to support non-gigabit speeds). 95 + */ 96 + switch (id->base.encoding) { 97 + case SFP_ENCODING_8472_64B66B: 98 + iface = PHY_INTERFACE_MODE_10GKR; 99 + break; 100 + 101 + case SFP_ENCODING_8B10B: 102 + if (!id->base.e1000_base_t && 103 + !id->base.e100_base_lx && 104 + !id->base.e100_base_fx) 105 + iface = PHY_INTERFACE_MODE_1000BASEX; 106 + else 107 + iface = PHY_INTERFACE_MODE_SGMII; 108 + break; 109 + 110 + default: 111 + iface = PHY_INTERFACE_MODE_NA; 112 + dev_err(bus->sfp_dev, 113 + "SFP module encoding does not support 8b10b nor 64b66b\n"); 114 + break; 115 + } 116 + 117 + return iface; 118 + } 119 + EXPORT_SYMBOL_GPL(sfp_parse_interface); 120 + 121 + void sfp_parse_support(struct sfp_bus *bus, const struct sfp_eeprom_id *id, 122 + unsigned long *support) 123 + { 124 + phylink_set(support, Autoneg); 125 + phylink_set(support, Pause); 126 + phylink_set(support, Asym_Pause); 127 + 128 + /* Set ethtool support from the compliance fields. */ 129 + if (id->base.e10g_base_sr) 130 + phylink_set(support, 10000baseSR_Full); 131 + if (id->base.e10g_base_lr) 132 + phylink_set(support, 10000baseLR_Full); 133 + if (id->base.e10g_base_lrm) 134 + phylink_set(support, 10000baseLRM_Full); 135 + if (id->base.e10g_base_er) 136 + phylink_set(support, 10000baseER_Full); 137 + if (id->base.e1000_base_sx || 138 + id->base.e1000_base_lx || 139 + id->base.e1000_base_cx) 140 + phylink_set(support, 1000baseX_Full); 141 + if (id->base.e1000_base_t) { 142 + phylink_set(support, 1000baseT_Half); 143 + phylink_set(support, 1000baseT_Full); 144 + } 145 + 146 + switch (id->base.extended_cc) { 147 + case 0x00: /* Unspecified */ 148 + break; 149 + case 0x02: /* 100Gbase-SR4 or 25Gbase-SR */ 150 + phylink_set(support, 100000baseSR4_Full); 151 + phylink_set(support, 25000baseSR_Full); 152 + break; 153 + case 0x03: /* 100Gbase-LR4 or 25Gbase-LR */ 154 + case 0x04: /* 100Gbase-ER4 or 25Gbase-ER */ 155 + phylink_set(support, 100000baseLR4_ER4_Full); 156 + break; 157 + case 0x0b: /* 100Gbase-CR4 or 25Gbase-CR CA-L */ 158 + case 0x0c: /* 25Gbase-CR CA-S */ 159 + case 0x0d: /* 25Gbase-CR CA-N */ 160 + phylink_set(support, 100000baseCR4_Full); 161 + phylink_set(support, 25000baseCR_Full); 162 + break; 163 + default: 164 + dev_warn(bus->sfp_dev, 165 + "Unknown/unsupported extended compliance code: 0x%02x\n", 166 + id->base.extended_cc); 167 + break; 168 + } 169 + 170 + /* For fibre channel SFP, derive possible BaseX modes */ 171 + if (id->base.fc_speed_100 || 172 + id->base.fc_speed_200 || 173 + id->base.fc_speed_400) { 174 + if (id->base.br_nominal >= 31) 175 + phylink_set(support, 2500baseX_Full); 176 + if (id->base.br_nominal >= 12) 177 + phylink_set(support, 1000baseX_Full); 178 + } 179 + 180 + switch (id->base.connector) { 181 + case SFP_CONNECTOR_SC: 182 + case SFP_CONNECTOR_FIBERJACK: 183 + case SFP_CONNECTOR_LC: 184 + case SFP_CONNECTOR_MT_RJ: 185 + case SFP_CONNECTOR_MU: 186 + case SFP_CONNECTOR_OPTICAL_PIGTAIL: 187 + break; 188 + 189 + case SFP_CONNECTOR_UNSPEC: 190 + if (id->base.e1000_base_t) 191 + break; 192 + 193 + case SFP_CONNECTOR_SG: /* guess */ 194 + case SFP_CONNECTOR_MPO_1X12: 195 + case SFP_CONNECTOR_MPO_2X16: 196 + case SFP_CONNECTOR_HSSDC_II: 197 + case SFP_CONNECTOR_COPPER_PIGTAIL: 198 + case SFP_CONNECTOR_NOSEPARATE: 199 + case SFP_CONNECTOR_MXC_2X16: 200 + default: 201 + /* a guess at the supported link modes */ 202 + dev_warn(bus->sfp_dev, 203 + "Guessing link modes, please report...\n"); 204 + phylink_set(support, 1000baseT_Half); 205 + phylink_set(support, 1000baseT_Full); 206 + break; 207 + } 208 + } 209 + EXPORT_SYMBOL_GPL(sfp_parse_support); 210 + 211 + 212 + static LIST_HEAD(sfp_buses); 213 + static DEFINE_MUTEX(sfp_mutex); 214 + 215 + static const struct sfp_upstream_ops *sfp_get_upstream_ops(struct sfp_bus *bus) 216 + { 217 + return bus->registered ? bus->upstream_ops : NULL; 218 + } 219 + 220 + static struct sfp_bus *sfp_bus_get(struct device_node *np) 221 + { 222 + struct sfp_bus *sfp, *new, *found = NULL; 223 + 224 + new = kzalloc(sizeof(*new), GFP_KERNEL); 225 + 226 + mutex_lock(&sfp_mutex); 227 + 228 + list_for_each_entry(sfp, &sfp_buses, node) { 229 + if (sfp->device_node == np) { 230 + kref_get(&sfp->kref); 231 + found = sfp; 232 + break; 233 + } 234 + } 235 + 236 + if (!found && new) { 237 + kref_init(&new->kref); 238 + new->device_node = np; 239 + list_add(&new->node, &sfp_buses); 240 + found = new; 241 + new = NULL; 242 + } 243 + 244 + mutex_unlock(&sfp_mutex); 245 + 246 + kfree(new); 247 + 248 + return found; 249 + } 250 + 251 + static void sfp_bus_release(struct kref *kref) __releases(sfp_mutex) 252 + { 253 + struct sfp_bus *bus = container_of(kref, struct sfp_bus, kref); 254 + 255 + list_del(&bus->node); 256 + mutex_unlock(&sfp_mutex); 257 + kfree(bus); 258 + } 259 + 260 + static void sfp_bus_put(struct sfp_bus *bus) 261 + { 262 + kref_put_mutex(&bus->kref, sfp_bus_release, &sfp_mutex); 263 + } 264 + 265 + static int sfp_register_bus(struct sfp_bus *bus) 266 + { 267 + const struct sfp_upstream_ops *ops = bus->upstream_ops; 268 + int ret; 269 + 270 + if (ops) { 271 + if (ops->link_down) 272 + ops->link_down(bus->upstream); 273 + if (ops->connect_phy && bus->phydev) { 274 + ret = ops->connect_phy(bus->upstream, bus->phydev); 275 + if (ret) 276 + return ret; 277 + } 278 + } 279 + if (bus->started) 280 + bus->socket_ops->start(bus->sfp); 281 + bus->registered = true; 282 + return 0; 283 + } 284 + 285 + static void sfp_unregister_bus(struct sfp_bus *bus) 286 + { 287 + const struct sfp_upstream_ops *ops = bus->upstream_ops; 288 + 289 + if (bus->registered) { 290 + if (bus->started) 291 + bus->socket_ops->stop(bus->sfp); 292 + if (bus->phydev && ops && ops->disconnect_phy) 293 + ops->disconnect_phy(bus->upstream); 294 + } 295 + bus->registered = false; 296 + } 297 + 298 + 299 + int sfp_get_module_info(struct sfp_bus *bus, struct ethtool_modinfo *modinfo) 300 + { 301 + if (!bus->registered) 302 + return -ENOIOCTLCMD; 303 + return bus->socket_ops->module_info(bus->sfp, modinfo); 304 + } 305 + EXPORT_SYMBOL_GPL(sfp_get_module_info); 306 + 307 + int sfp_get_module_eeprom(struct sfp_bus *bus, struct ethtool_eeprom *ee, 308 + u8 *data) 309 + { 310 + if (!bus->registered) 311 + return -ENOIOCTLCMD; 312 + return bus->socket_ops->module_eeprom(bus->sfp, ee, data); 313 + } 314 + EXPORT_SYMBOL_GPL(sfp_get_module_eeprom); 315 + 316 + void sfp_upstream_start(struct sfp_bus *bus) 317 + { 318 + if (bus->registered) 319 + bus->socket_ops->start(bus->sfp); 320 + bus->started = true; 321 + } 322 + EXPORT_SYMBOL_GPL(sfp_upstream_start); 323 + 324 + void sfp_upstream_stop(struct sfp_bus *bus) 325 + { 326 + if (bus->registered) 327 + bus->socket_ops->stop(bus->sfp); 328 + bus->started = false; 329 + } 330 + EXPORT_SYMBOL_GPL(sfp_upstream_stop); 331 + 332 + struct sfp_bus *sfp_register_upstream(struct device_node *np, 333 + struct net_device *ndev, void *upstream, 334 + const struct sfp_upstream_ops *ops) 335 + { 336 + struct sfp_bus *bus = sfp_bus_get(np); 337 + int ret = 0; 338 + 339 + if (bus) { 340 + rtnl_lock(); 341 + bus->upstream_ops = ops; 342 + bus->upstream = upstream; 343 + bus->netdev = ndev; 344 + 345 + if (bus->sfp) 346 + ret = sfp_register_bus(bus); 347 + rtnl_unlock(); 348 + } 349 + 350 + if (ret) { 351 + sfp_bus_put(bus); 352 + bus = NULL; 353 + } 354 + 355 + return bus; 356 + } 357 + EXPORT_SYMBOL_GPL(sfp_register_upstream); 358 + 359 + void sfp_unregister_upstream(struct sfp_bus *bus) 360 + { 361 + rtnl_lock(); 362 + sfp_unregister_bus(bus); 363 + bus->upstream = NULL; 364 + bus->netdev = NULL; 365 + rtnl_unlock(); 366 + 367 + sfp_bus_put(bus); 368 + } 369 + EXPORT_SYMBOL_GPL(sfp_unregister_upstream); 370 + 371 + 372 + /* Socket driver entry points */ 373 + int sfp_add_phy(struct sfp_bus *bus, struct phy_device *phydev) 374 + { 375 + const struct sfp_upstream_ops *ops = sfp_get_upstream_ops(bus); 376 + int ret = 0; 377 + 378 + if (ops && ops->connect_phy) 379 + ret = ops->connect_phy(bus->upstream, phydev); 380 + 381 + if (ret == 0) 382 + bus->phydev = phydev; 383 + 384 + return ret; 385 + } 386 + EXPORT_SYMBOL_GPL(sfp_add_phy); 387 + 388 + void sfp_remove_phy(struct sfp_bus *bus) 389 + { 390 + const struct sfp_upstream_ops *ops = sfp_get_upstream_ops(bus); 391 + 392 + if (ops && ops->disconnect_phy) 393 + ops->disconnect_phy(bus->upstream); 394 + bus->phydev = NULL; 395 + } 396 + EXPORT_SYMBOL_GPL(sfp_remove_phy); 397 + 398 + 399 + void sfp_link_up(struct sfp_bus *bus) 400 + { 401 + const struct sfp_upstream_ops *ops = sfp_get_upstream_ops(bus); 402 + 403 + if (ops && ops->link_up) 404 + ops->link_up(bus->upstream); 405 + } 406 + EXPORT_SYMBOL_GPL(sfp_link_up); 407 + 408 + void sfp_link_down(struct sfp_bus *bus) 409 + { 410 + const struct sfp_upstream_ops *ops = sfp_get_upstream_ops(bus); 411 + 412 + if (ops && ops->link_down) 413 + ops->link_down(bus->upstream); 414 + } 415 + EXPORT_SYMBOL_GPL(sfp_link_down); 416 + 417 + int sfp_module_insert(struct sfp_bus *bus, const struct sfp_eeprom_id *id) 418 + { 419 + const struct sfp_upstream_ops *ops = sfp_get_upstream_ops(bus); 420 + int ret = 0; 421 + 422 + if (ops && ops->module_insert) 423 + ret = ops->module_insert(bus->upstream, id); 424 + 425 + return ret; 426 + } 427 + EXPORT_SYMBOL_GPL(sfp_module_insert); 428 + 429 + void sfp_module_remove(struct sfp_bus *bus) 430 + { 431 + const struct sfp_upstream_ops *ops = sfp_get_upstream_ops(bus); 432 + 433 + if (ops && ops->module_remove) 434 + ops->module_remove(bus->upstream); 435 + } 436 + EXPORT_SYMBOL_GPL(sfp_module_remove); 437 + 438 + struct sfp_bus *sfp_register_socket(struct device *dev, struct sfp *sfp, 439 + const struct sfp_socket_ops *ops) 440 + { 441 + struct sfp_bus *bus = sfp_bus_get(dev->of_node); 442 + int ret = 0; 443 + 444 + if (bus) { 445 + rtnl_lock(); 446 + bus->sfp_dev = dev; 447 + bus->sfp = sfp; 448 + bus->socket_ops = ops; 449 + 450 + if (bus->netdev) 451 + ret = sfp_register_bus(bus); 452 + rtnl_unlock(); 453 + } 454 + 455 + if (ret) { 456 + sfp_bus_put(bus); 457 + bus = NULL; 458 + } 459 + 460 + return bus; 461 + } 462 + EXPORT_SYMBOL_GPL(sfp_register_socket); 463 + 464 + void sfp_unregister_socket(struct sfp_bus *bus) 465 + { 466 + rtnl_lock(); 467 + sfp_unregister_bus(bus); 468 + bus->sfp_dev = NULL; 469 + bus->sfp = NULL; 470 + bus->socket_ops = NULL; 471 + rtnl_unlock(); 472 + 473 + sfp_bus_put(bus); 474 + } 475 + EXPORT_SYMBOL_GPL(sfp_unregister_socket);
+28
drivers/net/phy/sfp.h
··· 1 + #ifndef SFP_H 2 + #define SFP_H 3 + 4 + #include <linux/ethtool.h> 5 + #include <linux/sfp.h> 6 + 7 + struct sfp; 8 + 9 + struct sfp_socket_ops { 10 + void (*start)(struct sfp *sfp); 11 + void (*stop)(struct sfp *sfp); 12 + int (*module_info)(struct sfp *sfp, struct ethtool_modinfo *modinfo); 13 + int (*module_eeprom)(struct sfp *sfp, struct ethtool_eeprom *ee, 14 + u8 *data); 15 + }; 16 + 17 + int sfp_add_phy(struct sfp_bus *bus, struct phy_device *phydev); 18 + void sfp_remove_phy(struct sfp_bus *bus); 19 + void sfp_link_up(struct sfp_bus *bus); 20 + void sfp_link_down(struct sfp_bus *bus); 21 + int sfp_module_insert(struct sfp_bus *bus, const struct sfp_eeprom_id *id); 22 + void sfp_module_remove(struct sfp_bus *bus); 23 + int sfp_link_configure(struct sfp_bus *bus, const struct sfp_eeprom_id *id); 24 + struct sfp_bus *sfp_register_socket(struct device *dev, struct sfp *sfp, 25 + const struct sfp_socket_ops *ops); 26 + void sfp_unregister_socket(struct sfp_bus *bus); 27 + 28 + #endif
+434
include/linux/sfp.h
··· 1 + #ifndef LINUX_SFP_H 2 + #define LINUX_SFP_H 3 + 4 + #include <linux/phy.h> 5 + 6 + struct __packed sfp_eeprom_base { 7 + u8 phys_id; 8 + u8 phys_ext_id; 9 + u8 connector; 10 + #if defined __BIG_ENDIAN_BITFIELD 11 + u8 e10g_base_er:1; 12 + u8 e10g_base_lrm:1; 13 + u8 e10g_base_lr:1; 14 + u8 e10g_base_sr:1; 15 + u8 if_1x_sx:1; 16 + u8 if_1x_lx:1; 17 + u8 if_1x_copper_active:1; 18 + u8 if_1x_copper_passive:1; 19 + 20 + u8 escon_mmf_1310_led:1; 21 + u8 escon_smf_1310_laser:1; 22 + u8 sonet_oc192_short_reach:1; 23 + u8 sonet_reach_bit1:1; 24 + u8 sonet_reach_bit2:1; 25 + u8 sonet_oc48_long_reach:1; 26 + u8 sonet_oc48_intermediate_reach:1; 27 + u8 sonet_oc48_short_reach:1; 28 + 29 + u8 unallocated_5_7:1; 30 + u8 sonet_oc12_smf_long_reach:1; 31 + u8 sonet_oc12_smf_intermediate_reach:1; 32 + u8 sonet_oc12_short_reach:1; 33 + u8 unallocated_5_3:1; 34 + u8 sonet_oc3_smf_long_reach:1; 35 + u8 sonet_oc3_smf_intermediate_reach:1; 36 + u8 sonet_oc3_short_reach:1; 37 + 38 + u8 e_base_px:1; 39 + u8 e_base_bx10:1; 40 + u8 e100_base_fx:1; 41 + u8 e100_base_lx:1; 42 + u8 e1000_base_t:1; 43 + u8 e1000_base_cx:1; 44 + u8 e1000_base_lx:1; 45 + u8 e1000_base_sx:1; 46 + 47 + u8 fc_ll_v:1; 48 + u8 fc_ll_s:1; 49 + u8 fc_ll_i:1; 50 + u8 fc_ll_l:1; 51 + u8 fc_ll_m:1; 52 + u8 fc_tech_sa:1; 53 + u8 fc_tech_lc:1; 54 + u8 fc_tech_electrical_inter_enclosure:1; 55 + 56 + u8 fc_tech_electrical_intra_enclosure:1; 57 + u8 fc_tech_sn:1; 58 + u8 fc_tech_sl:1; 59 + u8 fc_tech_ll:1; 60 + u8 sfp_ct_active:1; 61 + u8 sfp_ct_passive:1; 62 + u8 unallocated_8_1:1; 63 + u8 unallocated_8_0:1; 64 + 65 + u8 fc_media_tw:1; 66 + u8 fc_media_tp:1; 67 + u8 fc_media_mi:1; 68 + u8 fc_media_tv:1; 69 + u8 fc_media_m6:1; 70 + u8 fc_media_m5:1; 71 + u8 unallocated_9_1:1; 72 + u8 fc_media_sm:1; 73 + 74 + u8 fc_speed_1200:1; 75 + u8 fc_speed_800:1; 76 + u8 fc_speed_1600:1; 77 + u8 fc_speed_400:1; 78 + u8 fc_speed_3200:1; 79 + u8 fc_speed_200:1; 80 + u8 unallocated_10_1:1; 81 + u8 fc_speed_100:1; 82 + #elif defined __LITTLE_ENDIAN_BITFIELD 83 + u8 if_1x_copper_passive:1; 84 + u8 if_1x_copper_active:1; 85 + u8 if_1x_lx:1; 86 + u8 if_1x_sx:1; 87 + u8 e10g_base_sr:1; 88 + u8 e10g_base_lr:1; 89 + u8 e10g_base_lrm:1; 90 + u8 e10g_base_er:1; 91 + 92 + u8 sonet_oc3_short_reach:1; 93 + u8 sonet_oc3_smf_intermediate_reach:1; 94 + u8 sonet_oc3_smf_long_reach:1; 95 + u8 unallocated_5_3:1; 96 + u8 sonet_oc12_short_reach:1; 97 + u8 sonet_oc12_smf_intermediate_reach:1; 98 + u8 sonet_oc12_smf_long_reach:1; 99 + u8 unallocated_5_7:1; 100 + 101 + u8 sonet_oc48_short_reach:1; 102 + u8 sonet_oc48_intermediate_reach:1; 103 + u8 sonet_oc48_long_reach:1; 104 + u8 sonet_reach_bit2:1; 105 + u8 sonet_reach_bit1:1; 106 + u8 sonet_oc192_short_reach:1; 107 + u8 escon_smf_1310_laser:1; 108 + u8 escon_mmf_1310_led:1; 109 + 110 + u8 e1000_base_sx:1; 111 + u8 e1000_base_lx:1; 112 + u8 e1000_base_cx:1; 113 + u8 e1000_base_t:1; 114 + u8 e100_base_lx:1; 115 + u8 e100_base_fx:1; 116 + u8 e_base_bx10:1; 117 + u8 e_base_px:1; 118 + 119 + u8 fc_tech_electrical_inter_enclosure:1; 120 + u8 fc_tech_lc:1; 121 + u8 fc_tech_sa:1; 122 + u8 fc_ll_m:1; 123 + u8 fc_ll_l:1; 124 + u8 fc_ll_i:1; 125 + u8 fc_ll_s:1; 126 + u8 fc_ll_v:1; 127 + 128 + u8 unallocated_8_0:1; 129 + u8 unallocated_8_1:1; 130 + u8 sfp_ct_passive:1; 131 + u8 sfp_ct_active:1; 132 + u8 fc_tech_ll:1; 133 + u8 fc_tech_sl:1; 134 + u8 fc_tech_sn:1; 135 + u8 fc_tech_electrical_intra_enclosure:1; 136 + 137 + u8 fc_media_sm:1; 138 + u8 unallocated_9_1:1; 139 + u8 fc_media_m5:1; 140 + u8 fc_media_m6:1; 141 + u8 fc_media_tv:1; 142 + u8 fc_media_mi:1; 143 + u8 fc_media_tp:1; 144 + u8 fc_media_tw:1; 145 + 146 + u8 fc_speed_100:1; 147 + u8 unallocated_10_1:1; 148 + u8 fc_speed_200:1; 149 + u8 fc_speed_3200:1; 150 + u8 fc_speed_400:1; 151 + u8 fc_speed_1600:1; 152 + u8 fc_speed_800:1; 153 + u8 fc_speed_1200:1; 154 + #else 155 + #error Unknown Endian 156 + #endif 157 + u8 encoding; 158 + u8 br_nominal; 159 + u8 rate_id; 160 + u8 link_len[6]; 161 + char vendor_name[16]; 162 + u8 extended_cc; 163 + char vendor_oui[3]; 164 + char vendor_pn[16]; 165 + char vendor_rev[4]; 166 + union { 167 + __be16 optical_wavelength; 168 + u8 cable_spec; 169 + }; 170 + u8 reserved62; 171 + u8 cc_base; 172 + }; 173 + 174 + struct __packed sfp_eeprom_ext { 175 + __be16 options; 176 + u8 br_max; 177 + u8 br_min; 178 + char vendor_sn[16]; 179 + char datecode[8]; 180 + u8 diagmon; 181 + u8 enhopts; 182 + u8 sff8472_compliance; 183 + u8 cc_ext; 184 + }; 185 + 186 + struct __packed sfp_eeprom_id { 187 + struct sfp_eeprom_base base; 188 + struct sfp_eeprom_ext ext; 189 + }; 190 + 191 + /* SFP EEPROM registers */ 192 + enum { 193 + SFP_PHYS_ID = 0x00, 194 + SFP_PHYS_EXT_ID = 0x01, 195 + SFP_CONNECTOR = 0x02, 196 + SFP_COMPLIANCE = 0x03, 197 + SFP_ENCODING = 0x0b, 198 + SFP_BR_NOMINAL = 0x0c, 199 + SFP_RATE_ID = 0x0d, 200 + SFP_LINK_LEN_SM_KM = 0x0e, 201 + SFP_LINK_LEN_SM_100M = 0x0f, 202 + SFP_LINK_LEN_50UM_OM2_10M = 0x10, 203 + SFP_LINK_LEN_62_5UM_OM1_10M = 0x11, 204 + SFP_LINK_LEN_COPPER_1M = 0x12, 205 + SFP_LINK_LEN_50UM_OM4_10M = 0x12, 206 + SFP_LINK_LEN_50UM_OM3_10M = 0x13, 207 + SFP_VENDOR_NAME = 0x14, 208 + SFP_VENDOR_OUI = 0x25, 209 + SFP_VENDOR_PN = 0x28, 210 + SFP_VENDOR_REV = 0x38, 211 + SFP_OPTICAL_WAVELENGTH_MSB = 0x3c, 212 + SFP_OPTICAL_WAVELENGTH_LSB = 0x3d, 213 + SFP_CABLE_SPEC = 0x3c, 214 + SFP_CC_BASE = 0x3f, 215 + SFP_OPTIONS = 0x40, /* 2 bytes, MSB, LSB */ 216 + SFP_BR_MAX = 0x42, 217 + SFP_BR_MIN = 0x43, 218 + SFP_VENDOR_SN = 0x44, 219 + SFP_DATECODE = 0x54, 220 + SFP_DIAGMON = 0x5c, 221 + SFP_ENHOPTS = 0x5d, 222 + SFP_SFF8472_COMPLIANCE = 0x5e, 223 + SFP_CC_EXT = 0x5f, 224 + 225 + SFP_PHYS_ID_SFP = 0x03, 226 + SFP_PHYS_EXT_ID_SFP = 0x04, 227 + SFP_CONNECTOR_UNSPEC = 0x00, 228 + /* codes 01-05 not supportable on SFP, but some modules have single SC */ 229 + SFP_CONNECTOR_SC = 0x01, 230 + SFP_CONNECTOR_FIBERJACK = 0x06, 231 + SFP_CONNECTOR_LC = 0x07, 232 + SFP_CONNECTOR_MT_RJ = 0x08, 233 + SFP_CONNECTOR_MU = 0x09, 234 + SFP_CONNECTOR_SG = 0x0a, 235 + SFP_CONNECTOR_OPTICAL_PIGTAIL = 0x0b, 236 + SFP_CONNECTOR_MPO_1X12 = 0x0c, 237 + SFP_CONNECTOR_MPO_2X16 = 0x0d, 238 + SFP_CONNECTOR_HSSDC_II = 0x20, 239 + SFP_CONNECTOR_COPPER_PIGTAIL = 0x21, 240 + SFP_CONNECTOR_RJ45 = 0x22, 241 + SFP_CONNECTOR_NOSEPARATE = 0x23, 242 + SFP_CONNECTOR_MXC_2X16 = 0x24, 243 + SFP_ENCODING_UNSPEC = 0x00, 244 + SFP_ENCODING_8B10B = 0x01, 245 + SFP_ENCODING_4B5B = 0x02, 246 + SFP_ENCODING_NRZ = 0x03, 247 + SFP_ENCODING_8472_MANCHESTER = 0x04, 248 + SFP_ENCODING_8472_SONET = 0x05, 249 + SFP_ENCODING_8472_64B66B = 0x06, 250 + SFP_ENCODING_256B257B = 0x07, 251 + SFP_ENCODING_PAM4 = 0x08, 252 + SFP_OPTIONS_HIGH_POWER_LEVEL = BIT(13), 253 + SFP_OPTIONS_PAGING_A2 = BIT(12), 254 + SFP_OPTIONS_RETIMER = BIT(11), 255 + SFP_OPTIONS_COOLED_XCVR = BIT(10), 256 + SFP_OPTIONS_POWER_DECL = BIT(9), 257 + SFP_OPTIONS_RX_LINEAR_OUT = BIT(8), 258 + SFP_OPTIONS_RX_DECISION_THRESH = BIT(7), 259 + SFP_OPTIONS_TUNABLE_TX = BIT(6), 260 + SFP_OPTIONS_RATE_SELECT = BIT(5), 261 + SFP_OPTIONS_TX_DISABLE = BIT(4), 262 + SFP_OPTIONS_TX_FAULT = BIT(3), 263 + SFP_OPTIONS_LOS_INVERTED = BIT(2), 264 + SFP_OPTIONS_LOS_NORMAL = BIT(1), 265 + SFP_DIAGMON_DDM = BIT(6), 266 + SFP_DIAGMON_INT_CAL = BIT(5), 267 + SFP_DIAGMON_EXT_CAL = BIT(4), 268 + SFP_DIAGMON_RXPWR_AVG = BIT(3), 269 + SFP_DIAGMON_ADDRMODE = BIT(2), 270 + SFP_ENHOPTS_ALARMWARN = BIT(7), 271 + SFP_ENHOPTS_SOFT_TX_DISABLE = BIT(6), 272 + SFP_ENHOPTS_SOFT_TX_FAULT = BIT(5), 273 + SFP_ENHOPTS_SOFT_RX_LOS = BIT(4), 274 + SFP_ENHOPTS_SOFT_RATE_SELECT = BIT(3), 275 + SFP_ENHOPTS_APP_SELECT_SFF8079 = BIT(2), 276 + SFP_ENHOPTS_SOFT_RATE_SFF8431 = BIT(1), 277 + SFP_SFF8472_COMPLIANCE_NONE = 0x00, 278 + SFP_SFF8472_COMPLIANCE_REV9_3 = 0x01, 279 + SFP_SFF8472_COMPLIANCE_REV9_5 = 0x02, 280 + SFP_SFF8472_COMPLIANCE_REV10_2 = 0x03, 281 + SFP_SFF8472_COMPLIANCE_REV10_4 = 0x04, 282 + SFP_SFF8472_COMPLIANCE_REV11_0 = 0x05, 283 + SFP_SFF8472_COMPLIANCE_REV11_3 = 0x06, 284 + SFP_SFF8472_COMPLIANCE_REV11_4 = 0x07, 285 + SFP_SFF8472_COMPLIANCE_REV12_0 = 0x08, 286 + }; 287 + 288 + /* SFP Diagnostics */ 289 + enum { 290 + /* Alarm and warnings stored MSB at lower address then LSB */ 291 + SFP_TEMP_HIGH_ALARM = 0x00, 292 + SFP_TEMP_LOW_ALARM = 0x02, 293 + SFP_TEMP_HIGH_WARN = 0x04, 294 + SFP_TEMP_LOW_WARN = 0x06, 295 + SFP_VOLT_HIGH_ALARM = 0x08, 296 + SFP_VOLT_LOW_ALARM = 0x0a, 297 + SFP_VOLT_HIGH_WARN = 0x0c, 298 + SFP_VOLT_LOW_WARN = 0x0e, 299 + SFP_BIAS_HIGH_ALARM = 0x10, 300 + SFP_BIAS_LOW_ALARM = 0x12, 301 + SFP_BIAS_HIGH_WARN = 0x14, 302 + SFP_BIAS_LOW_WARN = 0x16, 303 + SFP_TXPWR_HIGH_ALARM = 0x18, 304 + SFP_TXPWR_LOW_ALARM = 0x1a, 305 + SFP_TXPWR_HIGH_WARN = 0x1c, 306 + SFP_TXPWR_LOW_WARN = 0x1e, 307 + SFP_RXPWR_HIGH_ALARM = 0x20, 308 + SFP_RXPWR_LOW_ALARM = 0x22, 309 + SFP_RXPWR_HIGH_WARN = 0x24, 310 + SFP_RXPWR_LOW_WARN = 0x26, 311 + SFP_LASER_TEMP_HIGH_ALARM = 0x28, 312 + SFP_LASER_TEMP_LOW_ALARM = 0x2a, 313 + SFP_LASER_TEMP_HIGH_WARN = 0x2c, 314 + SFP_LASER_TEMP_LOW_WARN = 0x2e, 315 + SFP_TEC_CUR_HIGH_ALARM = 0x30, 316 + SFP_TEC_CUR_LOW_ALARM = 0x32, 317 + SFP_TEC_CUR_HIGH_WARN = 0x34, 318 + SFP_TEC_CUR_LOW_WARN = 0x36, 319 + SFP_CAL_RXPWR4 = 0x38, 320 + SFP_CAL_RXPWR3 = 0x3c, 321 + SFP_CAL_RXPWR2 = 0x40, 322 + SFP_CAL_RXPWR1 = 0x44, 323 + SFP_CAL_RXPWR0 = 0x48, 324 + SFP_CAL_TXI_SLOPE = 0x4c, 325 + SFP_CAL_TXI_OFFSET = 0x4e, 326 + SFP_CAL_TXPWR_SLOPE = 0x50, 327 + SFP_CAL_TXPWR_OFFSET = 0x52, 328 + SFP_CAL_T_SLOPE = 0x54, 329 + SFP_CAL_T_OFFSET = 0x56, 330 + SFP_CAL_V_SLOPE = 0x58, 331 + SFP_CAL_V_OFFSET = 0x5a, 332 + SFP_CHKSUM = 0x5f, 333 + 334 + SFP_TEMP = 0x60, 335 + SFP_VCC = 0x62, 336 + SFP_TX_BIAS = 0x64, 337 + SFP_TX_POWER = 0x66, 338 + SFP_RX_POWER = 0x68, 339 + SFP_LASER_TEMP = 0x6a, 340 + SFP_TEC_CUR = 0x6c, 341 + 342 + SFP_STATUS = 0x6e, 343 + SFP_ALARM = 0x70, 344 + 345 + SFP_EXT_STATUS = 0x76, 346 + SFP_VSL = 0x78, 347 + SFP_PAGE = 0x7f, 348 + }; 349 + 350 + struct device_node; 351 + struct ethtool_eeprom; 352 + struct ethtool_modinfo; 353 + struct net_device; 354 + struct sfp_bus; 355 + 356 + struct sfp_upstream_ops { 357 + int (*module_insert)(void *, const struct sfp_eeprom_id *id); 358 + void (*module_remove)(void *); 359 + void (*link_down)(void *); 360 + void (*link_up)(void *); 361 + int (*connect_phy)(void *, struct phy_device *); 362 + void (*disconnect_phy)(void *); 363 + }; 364 + 365 + #if IS_ENABLED(CONFIG_SFP) 366 + int sfp_parse_port(struct sfp_bus *bus, const struct sfp_eeprom_id *id, 367 + unsigned long *support); 368 + phy_interface_t sfp_parse_interface(struct sfp_bus *bus, 369 + const struct sfp_eeprom_id *id); 370 + void sfp_parse_support(struct sfp_bus *bus, const struct sfp_eeprom_id *id, 371 + unsigned long *support); 372 + 373 + int sfp_get_module_info(struct sfp_bus *bus, struct ethtool_modinfo *modinfo); 374 + int sfp_get_module_eeprom(struct sfp_bus *bus, struct ethtool_eeprom *ee, 375 + u8 *data); 376 + void sfp_upstream_start(struct sfp_bus *bus); 377 + void sfp_upstream_stop(struct sfp_bus *bus); 378 + struct sfp_bus *sfp_register_upstream(struct device_node *np, 379 + struct net_device *ndev, void *upstream, 380 + const struct sfp_upstream_ops *ops); 381 + void sfp_unregister_upstream(struct sfp_bus *bus); 382 + #else 383 + static inline int sfp_parse_port(struct sfp_bus *bus, 384 + const struct sfp_eeprom_id *id, 385 + unsigned long *support) 386 + { 387 + return PORT_OTHER; 388 + } 389 + 390 + static inline phy_interface_t sfp_parse_interface(struct sfp_bus *bus, 391 + const struct sfp_eeprom_id *id) 392 + { 393 + return PHY_INTERFACE_MODE_NA; 394 + } 395 + 396 + static inline void sfp_parse_support(struct sfp_bus *bus, 397 + const struct sfp_eeprom_id *id, 398 + unsigned long *support) 399 + { 400 + } 401 + 402 + static inline int sfp_get_module_info(struct sfp_bus *bus, 403 + struct ethtool_modinfo *modinfo) 404 + { 405 + return -EOPNOTSUPP; 406 + } 407 + 408 + static inline int sfp_get_module_eeprom(struct sfp_bus *bus, 409 + struct ethtool_eeprom *ee, u8 *data) 410 + { 411 + return -EOPNOTSUPP; 412 + } 413 + 414 + static inline void sfp_upstream_start(struct sfp_bus *bus) 415 + { 416 + } 417 + 418 + static inline void sfp_upstream_stop(struct sfp_bus *bus) 419 + { 420 + } 421 + 422 + static inline struct sfp_bus *sfp_register_upstream(struct device_node *np, 423 + struct net_device *ndev, void *upstream, 424 + const struct sfp_upstream_ops *ops) 425 + { 426 + return (struct sfp_bus *)-1; 427 + } 428 + 429 + static inline void sfp_unregister_upstream(struct sfp_bus *bus) 430 + { 431 + } 432 + #endif 433 + 434 + #endif