static ssize_t set_phy_flash_cfg(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct efx_nic *efx = pci_get_drvdata(to_pci_dev(dev)); enum efx_phy_mode old_mode, new_mode; int err; rtnl_lock(); old_mode = efx->phy_mode; if (count == 0 || *buf == '0') new_mode = old_mode & ~PHY_MODE_SPECIAL; else new_mode = PHY_MODE_SPECIAL; if (old_mode == new_mode) { err = 0; } else if (efx->state != STATE_RUNNING || netif_running(efx->net_dev)) { err = -EBUSY; } else { /* Reset the PHY, reconfigure the MAC and enable/disable * MAC stats accordingly. */ efx->phy_mode = new_mode; if (new_mode & PHY_MODE_SPECIAL) falcon_stop_nic_stats(efx); err = sfe4001_poweron(efx); if (!err) err = efx_reconfigure_port(efx); if (!(new_mode & PHY_MODE_SPECIAL)) falcon_start_nic_stats(efx); } rtnl_unlock(); return err ? err : count; }
/* This board uses an I2C expander to provider power to the PHY, which needs to * be turned on before the PHY can be used. * Context: Process context, rtnl lock held */ static int sfe4001_init(struct efx_nic *efx) { struct falcon_board *board = falcon_board(efx); int rc; #if defined(CONFIG_SENSORS_LM90) || defined(CONFIG_SENSORS_LM90_MODULE) board->hwmon_client = i2c_new_device(&board->i2c_adap, &sfe4001_hwmon_info); #else board->hwmon_client = i2c_new_dummy(&board->i2c_adap, sfe4001_hwmon_info.addr); #endif if (!board->hwmon_client) return -EIO; /* Raise board/PHY high limit from 85 to 90 degrees Celsius */ rc = i2c_smbus_write_byte_data(board->hwmon_client, MAX664X_REG_WLHO, 90); if (rc) goto fail_hwmon; board->ioexp_client = i2c_new_dummy(&board->i2c_adap, PCA9539); if (!board->ioexp_client) { rc = -EIO; goto fail_hwmon; } if (efx->phy_mode & PHY_MODE_SPECIAL) { /* PHY won't generate a 156.25 MHz clock and MAC stats fetch * will fail. */ falcon_stop_nic_stats(efx); } rc = sfe4001_poweron(efx); if (rc) goto fail_ioexp; rc = device_create_file(&efx->pci_dev->dev, &dev_attr_phy_flash_cfg); if (rc) goto fail_on; EFX_INFO(efx, "PHY is powered on\n"); return 0; fail_on: sfe4001_poweroff(efx); fail_ioexp: i2c_unregister_device(board->ioexp_client); fail_hwmon: i2c_unregister_device(board->hwmon_client); return rc; }