root/drivers/net/phy/sfp-bus.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. sfp_parse_port
  2. sfp_parse_support
  3. sfp_select_interface
  4. sfp_get_upstream_ops
  5. sfp_bus_get
  6. sfp_bus_release
  7. sfp_bus_put
  8. sfp_register_bus
  9. sfp_unregister_bus
  10. sfp_get_module_info
  11. sfp_get_module_eeprom
  12. sfp_upstream_start
  13. sfp_upstream_stop
  14. sfp_upstream_clear
  15. sfp_register_upstream
  16. sfp_unregister_upstream
  17. sfp_add_phy
  18. sfp_remove_phy
  19. sfp_link_up
  20. sfp_link_down
  21. sfp_module_insert
  22. sfp_module_remove
  23. sfp_socket_clear
  24. sfp_register_socket
  25. sfp_unregister_socket

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 #include <linux/export.h>
   3 #include <linux/kref.h>
   4 #include <linux/list.h>
   5 #include <linux/mutex.h>
   6 #include <linux/phylink.h>
   7 #include <linux/rtnetlink.h>
   8 #include <linux/slab.h>
   9 
  10 #include "sfp.h"
  11 
  12 /**
  13  * struct sfp_bus - internal representation of a sfp bus
  14  */
  15 struct sfp_bus {
  16         /* private: */
  17         struct kref kref;
  18         struct list_head node;
  19         struct fwnode_handle *fwnode;
  20 
  21         const struct sfp_socket_ops *socket_ops;
  22         struct device *sfp_dev;
  23         struct sfp *sfp;
  24 
  25         const struct sfp_upstream_ops *upstream_ops;
  26         void *upstream;
  27         struct phy_device *phydev;
  28 
  29         bool registered;
  30         bool started;
  31 };
  32 
  33 /**
  34  * sfp_parse_port() - Parse the EEPROM base ID, setting the port type
  35  * @bus: a pointer to the &struct sfp_bus structure for the sfp module
  36  * @id: a pointer to the module's &struct sfp_eeprom_id
  37  * @support: optional pointer to an array of unsigned long for the
  38  *   ethtool support mask
  39  *
  40  * Parse the EEPROM identification given in @id, and return one of
  41  * %PORT_TP, %PORT_FIBRE or %PORT_OTHER. If @support is non-%NULL,
  42  * also set the ethtool %ETHTOOL_LINK_MODE_xxx_BIT corresponding with
  43  * the connector type.
  44  *
  45  * If the port type is not known, returns %PORT_OTHER.
  46  */
  47 int sfp_parse_port(struct sfp_bus *bus, const struct sfp_eeprom_id *id,
  48                    unsigned long *support)
  49 {
  50         int port;
  51 
  52         /* port is the physical connector, set this from the connector field. */
  53         switch (id->base.connector) {
  54         case SFP_CONNECTOR_SC:
  55         case SFP_CONNECTOR_FIBERJACK:
  56         case SFP_CONNECTOR_LC:
  57         case SFP_CONNECTOR_MT_RJ:
  58         case SFP_CONNECTOR_MU:
  59         case SFP_CONNECTOR_OPTICAL_PIGTAIL:
  60                 port = PORT_FIBRE;
  61                 break;
  62 
  63         case SFP_CONNECTOR_RJ45:
  64                 port = PORT_TP;
  65                 break;
  66 
  67         case SFP_CONNECTOR_COPPER_PIGTAIL:
  68                 port = PORT_DA;
  69                 break;
  70 
  71         case SFP_CONNECTOR_UNSPEC:
  72                 if (id->base.e1000_base_t) {
  73                         port = PORT_TP;
  74                         break;
  75                 }
  76                 /* fallthrough */
  77         case SFP_CONNECTOR_SG: /* guess */
  78         case SFP_CONNECTOR_MPO_1X12:
  79         case SFP_CONNECTOR_MPO_2X16:
  80         case SFP_CONNECTOR_HSSDC_II:
  81         case SFP_CONNECTOR_NOSEPARATE:
  82         case SFP_CONNECTOR_MXC_2X16:
  83                 port = PORT_OTHER;
  84                 break;
  85         default:
  86                 dev_warn(bus->sfp_dev, "SFP: unknown connector id 0x%02x\n",
  87                          id->base.connector);
  88                 port = PORT_OTHER;
  89                 break;
  90         }
  91 
  92         if (support) {
  93                 switch (port) {
  94                 case PORT_FIBRE:
  95                         phylink_set(support, FIBRE);
  96                         break;
  97 
  98                 case PORT_TP:
  99                         phylink_set(support, TP);
 100                         break;
 101                 }
 102         }
 103 
 104         return port;
 105 }
 106 EXPORT_SYMBOL_GPL(sfp_parse_port);
 107 
 108 /**
 109  * sfp_parse_support() - Parse the eeprom id for supported link modes
 110  * @bus: a pointer to the &struct sfp_bus structure for the sfp module
 111  * @id: a pointer to the module's &struct sfp_eeprom_id
 112  * @support: pointer to an array of unsigned long for the ethtool support mask
 113  *
 114  * Parse the EEPROM identification information and derive the supported
 115  * ethtool link modes for the module.
 116  */
 117 void sfp_parse_support(struct sfp_bus *bus, const struct sfp_eeprom_id *id,
 118                        unsigned long *support)
 119 {
 120         unsigned int br_min, br_nom, br_max;
 121         __ETHTOOL_DECLARE_LINK_MODE_MASK(modes) = { 0, };
 122 
 123         /* Decode the bitrate information to MBd */
 124         br_min = br_nom = br_max = 0;
 125         if (id->base.br_nominal) {
 126                 if (id->base.br_nominal != 255) {
 127                         br_nom = id->base.br_nominal * 100;
 128                         br_min = br_nom - id->base.br_nominal * id->ext.br_min;
 129                         br_max = br_nom + id->base.br_nominal * id->ext.br_max;
 130                 } else if (id->ext.br_max) {
 131                         br_nom = 250 * id->ext.br_max;
 132                         br_max = br_nom + br_nom * id->ext.br_min / 100;
 133                         br_min = br_nom - br_nom * id->ext.br_min / 100;
 134                 }
 135 
 136                 /* When using passive cables, in case neither BR,min nor BR,max
 137                  * are specified, set br_min to 0 as the nominal value is then
 138                  * used as the maximum.
 139                  */
 140                 if (br_min == br_max && id->base.sfp_ct_passive)
 141                         br_min = 0;
 142         }
 143 
 144         /* Set ethtool support from the compliance fields. */
 145         if (id->base.e10g_base_sr)
 146                 phylink_set(modes, 10000baseSR_Full);
 147         if (id->base.e10g_base_lr)
 148                 phylink_set(modes, 10000baseLR_Full);
 149         if (id->base.e10g_base_lrm)
 150                 phylink_set(modes, 10000baseLRM_Full);
 151         if (id->base.e10g_base_er)
 152                 phylink_set(modes, 10000baseER_Full);
 153         if (id->base.e1000_base_sx ||
 154             id->base.e1000_base_lx ||
 155             id->base.e1000_base_cx)
 156                 phylink_set(modes, 1000baseX_Full);
 157         if (id->base.e1000_base_t) {
 158                 phylink_set(modes, 1000baseT_Half);
 159                 phylink_set(modes, 1000baseT_Full);
 160         }
 161 
 162         /* 1000Base-PX or 1000Base-BX10 */
 163         if ((id->base.e_base_px || id->base.e_base_bx10) &&
 164             br_min <= 1300 && br_max >= 1200)
 165                 phylink_set(modes, 1000baseX_Full);
 166 
 167         /* For active or passive cables, select the link modes
 168          * based on the bit rates and the cable compliance bytes.
 169          */
 170         if ((id->base.sfp_ct_passive || id->base.sfp_ct_active) && br_nom) {
 171                 /* This may look odd, but some manufacturers use 12000MBd */
 172                 if (br_min <= 12000 && br_max >= 10300)
 173                         phylink_set(modes, 10000baseCR_Full);
 174                 if (br_min <= 3200 && br_max >= 3100)
 175                         phylink_set(modes, 2500baseX_Full);
 176                 if (br_min <= 1300 && br_max >= 1200)
 177                         phylink_set(modes, 1000baseX_Full);
 178         }
 179         if (id->base.sfp_ct_passive) {
 180                 if (id->base.passive.sff8431_app_e)
 181                         phylink_set(modes, 10000baseCR_Full);
 182         }
 183         if (id->base.sfp_ct_active) {
 184                 if (id->base.active.sff8431_app_e ||
 185                     id->base.active.sff8431_lim) {
 186                         phylink_set(modes, 10000baseCR_Full);
 187                 }
 188         }
 189 
 190         switch (id->base.extended_cc) {
 191         case 0x00: /* Unspecified */
 192                 break;
 193         case 0x02: /* 100Gbase-SR4 or 25Gbase-SR */
 194                 phylink_set(modes, 100000baseSR4_Full);
 195                 phylink_set(modes, 25000baseSR_Full);
 196                 break;
 197         case 0x03: /* 100Gbase-LR4 or 25Gbase-LR */
 198         case 0x04: /* 100Gbase-ER4 or 25Gbase-ER */
 199                 phylink_set(modes, 100000baseLR4_ER4_Full);
 200                 break;
 201         case 0x0b: /* 100Gbase-CR4 or 25Gbase-CR CA-L */
 202         case 0x0c: /* 25Gbase-CR CA-S */
 203         case 0x0d: /* 25Gbase-CR CA-N */
 204                 phylink_set(modes, 100000baseCR4_Full);
 205                 phylink_set(modes, 25000baseCR_Full);
 206                 break;
 207         default:
 208                 dev_warn(bus->sfp_dev,
 209                          "Unknown/unsupported extended compliance code: 0x%02x\n",
 210                          id->base.extended_cc);
 211                 break;
 212         }
 213 
 214         /* For fibre channel SFP, derive possible BaseX modes */
 215         if (id->base.fc_speed_100 ||
 216             id->base.fc_speed_200 ||
 217             id->base.fc_speed_400) {
 218                 if (id->base.br_nominal >= 31)
 219                         phylink_set(modes, 2500baseX_Full);
 220                 if (id->base.br_nominal >= 12)
 221                         phylink_set(modes, 1000baseX_Full);
 222         }
 223 
 224         /* If we haven't discovered any modes that this module supports, try
 225          * the encoding and bitrate to determine supported modes. Some BiDi
 226          * modules (eg, 1310nm/1550nm) are not 1000BASE-BX compliant due to
 227          * the differing wavelengths, so do not set any transceiver bits.
 228          */
 229         if (bitmap_empty(modes, __ETHTOOL_LINK_MODE_MASK_NBITS)) {
 230                 /* If the encoding and bit rate allows 1000baseX */
 231                 if (id->base.encoding == SFP_ENCODING_8B10B && br_nom &&
 232                     br_min <= 1300 && br_max >= 1200)
 233                         phylink_set(modes, 1000baseX_Full);
 234         }
 235 
 236         bitmap_or(support, support, modes, __ETHTOOL_LINK_MODE_MASK_NBITS);
 237 
 238         phylink_set(support, Autoneg);
 239         phylink_set(support, Pause);
 240         phylink_set(support, Asym_Pause);
 241 }
 242 EXPORT_SYMBOL_GPL(sfp_parse_support);
 243 
 244 /**
 245  * sfp_select_interface() - Select appropriate phy_interface_t mode
 246  * @bus: a pointer to the &struct sfp_bus structure for the sfp module
 247  * @id: a pointer to the module's &struct sfp_eeprom_id
 248  * @link_modes: ethtool link modes mask
 249  *
 250  * Derive the phy_interface_t mode for the information found in the
 251  * module's identifying EEPROM and the link modes mask. There is no
 252  * standard or defined way to derive this information, so we decide
 253  * based upon the link mode mask.
 254  */
 255 phy_interface_t sfp_select_interface(struct sfp_bus *bus,
 256                                      const struct sfp_eeprom_id *id,
 257                                      unsigned long *link_modes)
 258 {
 259         if (phylink_test(link_modes, 10000baseCR_Full) ||
 260             phylink_test(link_modes, 10000baseSR_Full) ||
 261             phylink_test(link_modes, 10000baseLR_Full) ||
 262             phylink_test(link_modes, 10000baseLRM_Full) ||
 263             phylink_test(link_modes, 10000baseER_Full))
 264                 return PHY_INTERFACE_MODE_10GKR;
 265 
 266         if (phylink_test(link_modes, 2500baseX_Full))
 267                 return PHY_INTERFACE_MODE_2500BASEX;
 268 
 269         if (id->base.e1000_base_t ||
 270             id->base.e100_base_lx ||
 271             id->base.e100_base_fx)
 272                 return PHY_INTERFACE_MODE_SGMII;
 273 
 274         if (phylink_test(link_modes, 1000baseX_Full))
 275                 return PHY_INTERFACE_MODE_1000BASEX;
 276 
 277         dev_warn(bus->sfp_dev, "Unable to ascertain link mode\n");
 278 
 279         return PHY_INTERFACE_MODE_NA;
 280 }
 281 EXPORT_SYMBOL_GPL(sfp_select_interface);
 282 
 283 static LIST_HEAD(sfp_buses);
 284 static DEFINE_MUTEX(sfp_mutex);
 285 
 286 static const struct sfp_upstream_ops *sfp_get_upstream_ops(struct sfp_bus *bus)
 287 {
 288         return bus->registered ? bus->upstream_ops : NULL;
 289 }
 290 
 291 static struct sfp_bus *sfp_bus_get(struct fwnode_handle *fwnode)
 292 {
 293         struct sfp_bus *sfp, *new, *found = NULL;
 294 
 295         new = kzalloc(sizeof(*new), GFP_KERNEL);
 296 
 297         mutex_lock(&sfp_mutex);
 298 
 299         list_for_each_entry(sfp, &sfp_buses, node) {
 300                 if (sfp->fwnode == fwnode) {
 301                         kref_get(&sfp->kref);
 302                         found = sfp;
 303                         break;
 304                 }
 305         }
 306 
 307         if (!found && new) {
 308                 kref_init(&new->kref);
 309                 new->fwnode = fwnode;
 310                 list_add(&new->node, &sfp_buses);
 311                 found = new;
 312                 new = NULL;
 313         }
 314 
 315         mutex_unlock(&sfp_mutex);
 316 
 317         kfree(new);
 318 
 319         return found;
 320 }
 321 
 322 static void sfp_bus_release(struct kref *kref)
 323 {
 324         struct sfp_bus *bus = container_of(kref, struct sfp_bus, kref);
 325 
 326         list_del(&bus->node);
 327         mutex_unlock(&sfp_mutex);
 328         kfree(bus);
 329 }
 330 
 331 static void sfp_bus_put(struct sfp_bus *bus)
 332 {
 333         kref_put_mutex(&bus->kref, sfp_bus_release, &sfp_mutex);
 334 }
 335 
 336 static int sfp_register_bus(struct sfp_bus *bus)
 337 {
 338         const struct sfp_upstream_ops *ops = bus->upstream_ops;
 339         int ret;
 340 
 341         if (ops) {
 342                 if (ops->link_down)
 343                         ops->link_down(bus->upstream);
 344                 if (ops->connect_phy && bus->phydev) {
 345                         ret = ops->connect_phy(bus->upstream, bus->phydev);
 346                         if (ret)
 347                                 return ret;
 348                 }
 349         }
 350         bus->socket_ops->attach(bus->sfp);
 351         if (bus->started)
 352                 bus->socket_ops->start(bus->sfp);
 353         bus->upstream_ops->attach(bus->upstream, bus);
 354         bus->registered = true;
 355         return 0;
 356 }
 357 
 358 static void sfp_unregister_bus(struct sfp_bus *bus)
 359 {
 360         const struct sfp_upstream_ops *ops = bus->upstream_ops;
 361 
 362         if (bus->registered) {
 363                 bus->upstream_ops->detach(bus->upstream, bus);
 364                 if (bus->started)
 365                         bus->socket_ops->stop(bus->sfp);
 366                 bus->socket_ops->detach(bus->sfp);
 367                 if (bus->phydev && ops && ops->disconnect_phy)
 368                         ops->disconnect_phy(bus->upstream);
 369         }
 370         bus->registered = false;
 371 }
 372 
 373 /**
 374  * sfp_get_module_info() - Get the ethtool_modinfo for a SFP module
 375  * @bus: a pointer to the &struct sfp_bus structure for the sfp module
 376  * @modinfo: a &struct ethtool_modinfo
 377  *
 378  * Fill in the type and eeprom_len parameters in @modinfo for a module on
 379  * the sfp bus specified by @bus.
 380  *
 381  * Returns 0 on success or a negative errno number.
 382  */
 383 int sfp_get_module_info(struct sfp_bus *bus, struct ethtool_modinfo *modinfo)
 384 {
 385         return bus->socket_ops->module_info(bus->sfp, modinfo);
 386 }
 387 EXPORT_SYMBOL_GPL(sfp_get_module_info);
 388 
 389 /**
 390  * sfp_get_module_eeprom() - Read the SFP module EEPROM
 391  * @bus: a pointer to the &struct sfp_bus structure for the sfp module
 392  * @ee: a &struct ethtool_eeprom
 393  * @data: buffer to contain the EEPROM data (must be at least @ee->len bytes)
 394  *
 395  * Read the EEPROM as specified by the supplied @ee. See the documentation
 396  * for &struct ethtool_eeprom for the region to be read.
 397  *
 398  * Returns 0 on success or a negative errno number.
 399  */
 400 int sfp_get_module_eeprom(struct sfp_bus *bus, struct ethtool_eeprom *ee,
 401                           u8 *data)
 402 {
 403         return bus->socket_ops->module_eeprom(bus->sfp, ee, data);
 404 }
 405 EXPORT_SYMBOL_GPL(sfp_get_module_eeprom);
 406 
 407 /**
 408  * sfp_upstream_start() - Inform the SFP that the network device is up
 409  * @bus: a pointer to the &struct sfp_bus structure for the sfp module
 410  *
 411  * Inform the SFP socket that the network device is now up, so that the
 412  * module can be enabled by allowing TX_DISABLE to be deasserted. This
 413  * should be called from the network device driver's &struct net_device_ops
 414  * ndo_open() method.
 415  */
 416 void sfp_upstream_start(struct sfp_bus *bus)
 417 {
 418         if (bus->registered)
 419                 bus->socket_ops->start(bus->sfp);
 420         bus->started = true;
 421 }
 422 EXPORT_SYMBOL_GPL(sfp_upstream_start);
 423 
 424 /**
 425  * sfp_upstream_stop() - Inform the SFP that the network device is down
 426  * @bus: a pointer to the &struct sfp_bus structure for the sfp module
 427  *
 428  * Inform the SFP socket that the network device is now up, so that the
 429  * module can be disabled by asserting TX_DISABLE, disabling the laser
 430  * in optical modules. This should be called from the network device
 431  * driver's &struct net_device_ops ndo_stop() method.
 432  */
 433 void sfp_upstream_stop(struct sfp_bus *bus)
 434 {
 435         if (bus->registered)
 436                 bus->socket_ops->stop(bus->sfp);
 437         bus->started = false;
 438 }
 439 EXPORT_SYMBOL_GPL(sfp_upstream_stop);
 440 
 441 static void sfp_upstream_clear(struct sfp_bus *bus)
 442 {
 443         bus->upstream_ops = NULL;
 444         bus->upstream = NULL;
 445 }
 446 
 447 /**
 448  * sfp_register_upstream() - Register the neighbouring device
 449  * @fwnode: firmware node for the SFP bus
 450  * @upstream: the upstream private data
 451  * @ops: the upstream's &struct sfp_upstream_ops
 452  *
 453  * Register the upstream device (eg, PHY) with the SFP bus. MAC drivers
 454  * should use phylink, which will call this function for them. Returns
 455  * a pointer to the allocated &struct sfp_bus.
 456  *
 457  * On error, returns %NULL.
 458  */
 459 struct sfp_bus *sfp_register_upstream(struct fwnode_handle *fwnode,
 460                                       void *upstream,
 461                                       const struct sfp_upstream_ops *ops)
 462 {
 463         struct sfp_bus *bus = sfp_bus_get(fwnode);
 464         int ret = 0;
 465 
 466         if (bus) {
 467                 rtnl_lock();
 468                 bus->upstream_ops = ops;
 469                 bus->upstream = upstream;
 470 
 471                 if (bus->sfp) {
 472                         ret = sfp_register_bus(bus);
 473                         if (ret)
 474                                 sfp_upstream_clear(bus);
 475                 }
 476                 rtnl_unlock();
 477         }
 478 
 479         if (ret) {
 480                 sfp_bus_put(bus);
 481                 bus = NULL;
 482         }
 483 
 484         return bus;
 485 }
 486 EXPORT_SYMBOL_GPL(sfp_register_upstream);
 487 
 488 /**
 489  * sfp_unregister_upstream() - Unregister sfp bus
 490  * @bus: a pointer to the &struct sfp_bus structure for the sfp module
 491  *
 492  * Unregister a previously registered upstream connection for the SFP
 493  * module. @bus is returned from sfp_register_upstream().
 494  */
 495 void sfp_unregister_upstream(struct sfp_bus *bus)
 496 {
 497         rtnl_lock();
 498         if (bus->sfp)
 499                 sfp_unregister_bus(bus);
 500         sfp_upstream_clear(bus);
 501         rtnl_unlock();
 502 
 503         sfp_bus_put(bus);
 504 }
 505 EXPORT_SYMBOL_GPL(sfp_unregister_upstream);
 506 
 507 /* Socket driver entry points */
 508 int sfp_add_phy(struct sfp_bus *bus, struct phy_device *phydev)
 509 {
 510         const struct sfp_upstream_ops *ops = sfp_get_upstream_ops(bus);
 511         int ret = 0;
 512 
 513         if (ops && ops->connect_phy)
 514                 ret = ops->connect_phy(bus->upstream, phydev);
 515 
 516         if (ret == 0)
 517                 bus->phydev = phydev;
 518 
 519         return ret;
 520 }
 521 EXPORT_SYMBOL_GPL(sfp_add_phy);
 522 
 523 void sfp_remove_phy(struct sfp_bus *bus)
 524 {
 525         const struct sfp_upstream_ops *ops = sfp_get_upstream_ops(bus);
 526 
 527         if (ops && ops->disconnect_phy)
 528                 ops->disconnect_phy(bus->upstream);
 529         bus->phydev = NULL;
 530 }
 531 EXPORT_SYMBOL_GPL(sfp_remove_phy);
 532 
 533 void sfp_link_up(struct sfp_bus *bus)
 534 {
 535         const struct sfp_upstream_ops *ops = sfp_get_upstream_ops(bus);
 536 
 537         if (ops && ops->link_up)
 538                 ops->link_up(bus->upstream);
 539 }
 540 EXPORT_SYMBOL_GPL(sfp_link_up);
 541 
 542 void sfp_link_down(struct sfp_bus *bus)
 543 {
 544         const struct sfp_upstream_ops *ops = sfp_get_upstream_ops(bus);
 545 
 546         if (ops && ops->link_down)
 547                 ops->link_down(bus->upstream);
 548 }
 549 EXPORT_SYMBOL_GPL(sfp_link_down);
 550 
 551 int sfp_module_insert(struct sfp_bus *bus, const struct sfp_eeprom_id *id)
 552 {
 553         const struct sfp_upstream_ops *ops = sfp_get_upstream_ops(bus);
 554         int ret = 0;
 555 
 556         if (ops && ops->module_insert)
 557                 ret = ops->module_insert(bus->upstream, id);
 558 
 559         return ret;
 560 }
 561 EXPORT_SYMBOL_GPL(sfp_module_insert);
 562 
 563 void sfp_module_remove(struct sfp_bus *bus)
 564 {
 565         const struct sfp_upstream_ops *ops = sfp_get_upstream_ops(bus);
 566 
 567         if (ops && ops->module_remove)
 568                 ops->module_remove(bus->upstream);
 569 }
 570 EXPORT_SYMBOL_GPL(sfp_module_remove);
 571 
 572 static void sfp_socket_clear(struct sfp_bus *bus)
 573 {
 574         bus->sfp_dev = NULL;
 575         bus->sfp = NULL;
 576         bus->socket_ops = NULL;
 577 }
 578 
 579 struct sfp_bus *sfp_register_socket(struct device *dev, struct sfp *sfp,
 580                                     const struct sfp_socket_ops *ops)
 581 {
 582         struct sfp_bus *bus = sfp_bus_get(dev->fwnode);
 583         int ret = 0;
 584 
 585         if (bus) {
 586                 rtnl_lock();
 587                 bus->sfp_dev = dev;
 588                 bus->sfp = sfp;
 589                 bus->socket_ops = ops;
 590 
 591                 if (bus->upstream_ops) {
 592                         ret = sfp_register_bus(bus);
 593                         if (ret)
 594                                 sfp_socket_clear(bus);
 595                 }
 596                 rtnl_unlock();
 597         }
 598 
 599         if (ret) {
 600                 sfp_bus_put(bus);
 601                 bus = NULL;
 602         }
 603 
 604         return bus;
 605 }
 606 EXPORT_SYMBOL_GPL(sfp_register_socket);
 607 
 608 void sfp_unregister_socket(struct sfp_bus *bus)
 609 {
 610         rtnl_lock();
 611         if (bus->upstream_ops)
 612                 sfp_unregister_bus(bus);
 613         sfp_socket_clear(bus);
 614         rtnl_unlock();
 615 
 616         sfp_bus_put(bus);
 617 }
 618 EXPORT_SYMBOL_GPL(sfp_unregister_socket);

/* [<][>][^][v][top][bottom][index][help] */