linux/drivers/net/phy/sfp-bus.c
<<
>>
Prefs
   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
  11struct 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
  30int 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}
  80EXPORT_SYMBOL_GPL(sfp_parse_port);
  81
  82phy_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}
 119EXPORT_SYMBOL_GPL(sfp_parse_interface);
 120
 121void 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}
 209EXPORT_SYMBOL_GPL(sfp_parse_support);
 210
 211
 212static LIST_HEAD(sfp_buses);
 213static DEFINE_MUTEX(sfp_mutex);
 214
 215static const struct sfp_upstream_ops *sfp_get_upstream_ops(struct sfp_bus *bus)
 216{
 217        return bus->registered ? bus->upstream_ops : NULL;
 218}
 219
 220static 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
 251static 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
 260static void sfp_bus_put(struct sfp_bus *bus)
 261{
 262        kref_put_mutex(&bus->kref, sfp_bus_release, &sfp_mutex);
 263}
 264
 265static 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
 285static 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
 299int 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}
 305EXPORT_SYMBOL_GPL(sfp_get_module_info);
 306
 307int 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}
 314EXPORT_SYMBOL_GPL(sfp_get_module_eeprom);
 315
 316void sfp_upstream_start(struct sfp_bus *bus)
 317{
 318        if (bus->registered)
 319                bus->socket_ops->start(bus->sfp);
 320        bus->started = true;
 321}
 322EXPORT_SYMBOL_GPL(sfp_upstream_start);
 323
 324void sfp_upstream_stop(struct sfp_bus *bus)
 325{
 326        if (bus->registered)
 327                bus->socket_ops->stop(bus->sfp);
 328        bus->started = false;
 329}
 330EXPORT_SYMBOL_GPL(sfp_upstream_stop);
 331
 332struct 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}
 357EXPORT_SYMBOL_GPL(sfp_register_upstream);
 358
 359void 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}
 369EXPORT_SYMBOL_GPL(sfp_unregister_upstream);
 370
 371
 372/* Socket driver entry points */
 373int 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}
 386EXPORT_SYMBOL_GPL(sfp_add_phy);
 387
 388void 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}
 396EXPORT_SYMBOL_GPL(sfp_remove_phy);
 397
 398
 399void 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}
 406EXPORT_SYMBOL_GPL(sfp_link_up);
 407
 408void 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}
 415EXPORT_SYMBOL_GPL(sfp_link_down);
 416
 417int 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}
 427EXPORT_SYMBOL_GPL(sfp_module_insert);
 428
 429void 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}
 436EXPORT_SYMBOL_GPL(sfp_module_remove);
 437
 438struct 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}
 462EXPORT_SYMBOL_GPL(sfp_register_socket);
 463
 464void 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}
 475EXPORT_SYMBOL_GPL(sfp_unregister_socket);
 476