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

Merge branch 'sfp-infra'

Russell King says:

====================
Initial SFP support patches

Please review and merge this initial patch set, which is part of a
larger set previously posted adding SFP support to phy and mvneta.

This initial set are focused on cleaning up and reorganising the
fixed-phy code to allow the core software-phy code to be re-used.

These are based on net-next.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>

+222 -126
+4
drivers/net/phy/Kconfig
··· 12 12 13 13 if PHYLIB 14 14 15 + config SWPHY 16 + bool 17 + 15 18 comment "MII PHY device drivers" 16 19 17 20 config AQUANTIA_PHY ··· 162 159 config FIXED_PHY 163 160 tristate "Driver for MDIO Bus/PHY emulation with fixed speed/link PHYs" 164 161 depends on PHYLIB 162 + select SWPHY 165 163 ---help--- 166 164 Adds the platform "fixed" MDIO Bus to cover the boards that use 167 165 PHYs that are not connected to the real MDIO bus.
+2 -1
drivers/net/phy/Makefile
··· 1 1 # Makefile for Linux PHY drivers 2 2 3 - libphy-objs := phy.o phy_device.o mdio_bus.o mdio_device.o 3 + libphy-y := phy.o phy_device.o mdio_bus.o mdio_device.o 4 + libphy-$(CONFIG_SWPHY) += swphy.o 4 5 5 6 obj-$(CONFIG_PHYLIB) += libphy.o 6 7 obj-$(CONFIG_AQUANTIA_PHY) += aquantia.o
+28 -125
drivers/net/phy/fixed_phy.c
··· 23 23 #include <linux/slab.h> 24 24 #include <linux/of.h> 25 25 #include <linux/gpio.h> 26 + #include <linux/seqlock.h> 26 27 27 - #define MII_REGS_NUM 29 28 + #include "swphy.h" 28 29 29 30 struct fixed_mdio_bus { 30 31 struct mii_bus *mii_bus; ··· 34 33 35 34 struct fixed_phy { 36 35 int addr; 37 - u16 regs[MII_REGS_NUM]; 38 36 struct phy_device *phydev; 37 + seqcount_t seqcount; 39 38 struct fixed_phy_status status; 40 39 int (*link_update)(struct net_device *, struct fixed_phy_status *); 41 40 struct list_head node; ··· 47 46 .phys = LIST_HEAD_INIT(platform_fmb.phys), 48 47 }; 49 48 50 - static int fixed_phy_update_regs(struct fixed_phy *fp) 49 + static void fixed_phy_update(struct fixed_phy *fp) 51 50 { 52 - u16 bmsr = BMSR_ANEGCAPABLE; 53 - u16 bmcr = 0; 54 - u16 lpagb = 0; 55 - u16 lpa = 0; 56 - 57 51 if (gpio_is_valid(fp->link_gpio)) 58 52 fp->status.link = !!gpio_get_value_cansleep(fp->link_gpio); 59 - 60 - if (fp->status.duplex) { 61 - switch (fp->status.speed) { 62 - case 1000: 63 - bmsr |= BMSR_ESTATEN; 64 - break; 65 - case 100: 66 - bmsr |= BMSR_100FULL; 67 - break; 68 - case 10: 69 - bmsr |= BMSR_10FULL; 70 - break; 71 - default: 72 - break; 73 - } 74 - } else { 75 - switch (fp->status.speed) { 76 - case 1000: 77 - bmsr |= BMSR_ESTATEN; 78 - break; 79 - case 100: 80 - bmsr |= BMSR_100HALF; 81 - break; 82 - case 10: 83 - bmsr |= BMSR_10HALF; 84 - break; 85 - default: 86 - break; 87 - } 88 - } 89 - 90 - if (fp->status.link) { 91 - bmsr |= BMSR_LSTATUS | BMSR_ANEGCOMPLETE; 92 - 93 - if (fp->status.duplex) { 94 - bmcr |= BMCR_FULLDPLX; 95 - 96 - switch (fp->status.speed) { 97 - case 1000: 98 - bmcr |= BMCR_SPEED1000; 99 - lpagb |= LPA_1000FULL; 100 - break; 101 - case 100: 102 - bmcr |= BMCR_SPEED100; 103 - lpa |= LPA_100FULL; 104 - break; 105 - case 10: 106 - lpa |= LPA_10FULL; 107 - break; 108 - default: 109 - pr_warn("fixed phy: unknown speed\n"); 110 - return -EINVAL; 111 - } 112 - } else { 113 - switch (fp->status.speed) { 114 - case 1000: 115 - bmcr |= BMCR_SPEED1000; 116 - lpagb |= LPA_1000HALF; 117 - break; 118 - case 100: 119 - bmcr |= BMCR_SPEED100; 120 - lpa |= LPA_100HALF; 121 - break; 122 - case 10: 123 - lpa |= LPA_10HALF; 124 - break; 125 - default: 126 - pr_warn("fixed phy: unknown speed\n"); 127 - return -EINVAL; 128 - } 129 - } 130 - 131 - if (fp->status.pause) 132 - lpa |= LPA_PAUSE_CAP; 133 - 134 - if (fp->status.asym_pause) 135 - lpa |= LPA_PAUSE_ASYM; 136 - } 137 - 138 - fp->regs[MII_PHYSID1] = 0; 139 - fp->regs[MII_PHYSID2] = 0; 140 - 141 - fp->regs[MII_BMSR] = bmsr; 142 - fp->regs[MII_BMCR] = bmcr; 143 - fp->regs[MII_LPA] = lpa; 144 - fp->regs[MII_STAT1000] = lpagb; 145 - 146 - return 0; 147 53 } 148 54 149 55 static int fixed_mdio_read(struct mii_bus *bus, int phy_addr, int reg_num) ··· 58 150 struct fixed_mdio_bus *fmb = bus->priv; 59 151 struct fixed_phy *fp; 60 152 61 - if (reg_num >= MII_REGS_NUM) 62 - return -1; 63 - 64 - /* We do not support emulating Clause 45 over Clause 22 register reads 65 - * return an error instead of bogus data. 66 - */ 67 - switch (reg_num) { 68 - case MII_MMD_CTRL: 69 - case MII_MMD_DATA: 70 - return -1; 71 - default: 72 - break; 73 - } 74 - 75 153 list_for_each_entry(fp, &fmb->phys, node) { 76 154 if (fp->addr == phy_addr) { 77 - /* Issue callback if user registered it. */ 78 - if (fp->link_update) { 79 - fp->link_update(fp->phydev->attached_dev, 80 - &fp->status); 81 - fixed_phy_update_regs(fp); 82 - } 83 - return fp->regs[reg_num]; 155 + struct fixed_phy_status state; 156 + int s; 157 + 158 + do { 159 + s = read_seqcount_begin(&fp->seqcount); 160 + /* Issue callback if user registered it. */ 161 + if (fp->link_update) { 162 + fp->link_update(fp->phydev->attached_dev, 163 + &fp->status); 164 + fixed_phy_update(fp); 165 + } 166 + state = fp->status; 167 + } while (read_seqcount_retry(&fp->seqcount, s)); 168 + 169 + return swphy_read_reg(reg_num, &state); 84 170 } 85 171 } 86 172 ··· 126 224 127 225 list_for_each_entry(fp, &fmb->phys, node) { 128 226 if (fp->addr == phydev->mdio.addr) { 227 + write_seqcount_begin(&fp->seqcount); 129 228 #define _UPD(x) if (changed->x) \ 130 229 fp->status.x = status->x 131 230 _UPD(link); ··· 135 232 _UPD(pause); 136 233 _UPD(asym_pause); 137 234 #undef _UPD 138 - fixed_phy_update_regs(fp); 235 + fixed_phy_update(fp); 236 + write_seqcount_end(&fp->seqcount); 139 237 return 0; 140 238 } 141 239 } ··· 153 249 struct fixed_mdio_bus *fmb = &platform_fmb; 154 250 struct fixed_phy *fp; 155 251 252 + ret = swphy_validate_state(status); 253 + if (ret < 0) 254 + return ret; 255 + 156 256 fp = kzalloc(sizeof(*fp), GFP_KERNEL); 157 257 if (!fp) 158 258 return -ENOMEM; 159 259 160 - memset(fp->regs, 0xFF, sizeof(fp->regs[0]) * MII_REGS_NUM); 260 + seqcount_init(&fp->seqcount); 161 261 162 262 if (irq != PHY_POLL) 163 263 fmb->mii_bus->irq[phy_addr] = irq; ··· 177 269 goto err_regs; 178 270 } 179 271 180 - ret = fixed_phy_update_regs(fp); 181 - if (ret) 182 - goto err_gpio; 272 + fixed_phy_update(fp); 183 273 184 274 list_add_tail(&fp->node, &fmb->phys); 185 275 186 276 return 0; 187 277 188 - err_gpio: 189 - if (gpio_is_valid(fp->link_gpio)) 190 - gpio_free(fp->link_gpio); 191 278 err_regs: 192 279 kfree(fp); 193 280 return ret;
+179
drivers/net/phy/swphy.c
··· 1 + /* 2 + * Software PHY emulation 3 + * 4 + * Code taken from fixed_phy.c by Russell King <rmk+kernel@arm.linux.org.uk> 5 + * 6 + * Author: Vitaly Bordug <vbordug@ru.mvista.com> 7 + * Anton Vorontsov <avorontsov@ru.mvista.com> 8 + * 9 + * Copyright (c) 2006-2007 MontaVista Software, Inc. 10 + * 11 + * This program is free software; you can redistribute it and/or modify it 12 + * under the terms of the GNU General Public License as published by the 13 + * Free Software Foundation; either version 2 of the License, or (at your 14 + * option) any later version. 15 + */ 16 + #include <linux/export.h> 17 + #include <linux/mii.h> 18 + #include <linux/phy.h> 19 + #include <linux/phy_fixed.h> 20 + 21 + #include "swphy.h" 22 + 23 + #define MII_REGS_NUM 29 24 + 25 + struct swmii_regs { 26 + u16 bmcr; 27 + u16 bmsr; 28 + u16 lpa; 29 + u16 lpagb; 30 + }; 31 + 32 + enum { 33 + SWMII_SPEED_10 = 0, 34 + SWMII_SPEED_100, 35 + SWMII_SPEED_1000, 36 + SWMII_DUPLEX_HALF = 0, 37 + SWMII_DUPLEX_FULL, 38 + }; 39 + 40 + /* 41 + * These two tables get bitwise-anded together to produce the final result. 42 + * This means the speed table must contain both duplex settings, and the 43 + * duplex table must contain all speed settings. 44 + */ 45 + static const struct swmii_regs speed[] = { 46 + [SWMII_SPEED_10] = { 47 + .bmcr = BMCR_FULLDPLX, 48 + .lpa = LPA_10FULL | LPA_10HALF, 49 + }, 50 + [SWMII_SPEED_100] = { 51 + .bmcr = BMCR_FULLDPLX | BMCR_SPEED100, 52 + .bmsr = BMSR_100FULL | BMSR_100HALF, 53 + .lpa = LPA_100FULL | LPA_100HALF, 54 + }, 55 + [SWMII_SPEED_1000] = { 56 + .bmcr = BMCR_FULLDPLX | BMCR_SPEED1000, 57 + .bmsr = BMSR_ESTATEN, 58 + .lpagb = LPA_1000FULL | LPA_1000HALF, 59 + }, 60 + }; 61 + 62 + static const struct swmii_regs duplex[] = { 63 + [SWMII_DUPLEX_HALF] = { 64 + .bmcr = ~BMCR_FULLDPLX, 65 + .bmsr = BMSR_ESTATEN | BMSR_100HALF, 66 + .lpa = LPA_10HALF | LPA_100HALF, 67 + .lpagb = LPA_1000HALF, 68 + }, 69 + [SWMII_DUPLEX_FULL] = { 70 + .bmcr = ~0, 71 + .bmsr = BMSR_ESTATEN | BMSR_100FULL, 72 + .lpa = LPA_10FULL | LPA_100FULL, 73 + .lpagb = LPA_1000FULL, 74 + }, 75 + }; 76 + 77 + static int swphy_decode_speed(int speed) 78 + { 79 + switch (speed) { 80 + case 1000: 81 + return SWMII_SPEED_1000; 82 + case 100: 83 + return SWMII_SPEED_100; 84 + case 10: 85 + return SWMII_SPEED_10; 86 + default: 87 + return -EINVAL; 88 + } 89 + } 90 + 91 + /** 92 + * swphy_validate_state - validate the software phy status 93 + * @state: software phy status 94 + * 95 + * This checks that we can represent the state stored in @state can be 96 + * represented in the emulated MII registers. Returns 0 if it can, 97 + * otherwise returns -EINVAL. 98 + */ 99 + int swphy_validate_state(const struct fixed_phy_status *state) 100 + { 101 + int err; 102 + 103 + if (state->link) { 104 + err = swphy_decode_speed(state->speed); 105 + if (err < 0) { 106 + pr_warn("swphy: unknown speed\n"); 107 + return -EINVAL; 108 + } 109 + } 110 + return 0; 111 + } 112 + EXPORT_SYMBOL_GPL(swphy_validate_state); 113 + 114 + /** 115 + * swphy_read_reg - return a MII register from the fixed phy state 116 + * @reg: MII register 117 + * @state: fixed phy status 118 + * 119 + * Return the MII @reg register generated from the fixed phy state @state. 120 + */ 121 + int swphy_read_reg(int reg, const struct fixed_phy_status *state) 122 + { 123 + int speed_index, duplex_index; 124 + u16 bmsr = BMSR_ANEGCAPABLE; 125 + u16 bmcr = 0; 126 + u16 lpagb = 0; 127 + u16 lpa = 0; 128 + 129 + if (reg > MII_REGS_NUM) 130 + return -1; 131 + 132 + speed_index = swphy_decode_speed(state->speed); 133 + if (WARN_ON(speed_index < 0)) 134 + return 0; 135 + 136 + duplex_index = state->duplex ? SWMII_DUPLEX_FULL : SWMII_DUPLEX_HALF; 137 + 138 + bmsr |= speed[speed_index].bmsr & duplex[duplex_index].bmsr; 139 + 140 + if (state->link) { 141 + bmsr |= BMSR_LSTATUS | BMSR_ANEGCOMPLETE; 142 + 143 + bmcr |= speed[speed_index].bmcr & duplex[duplex_index].bmcr; 144 + lpa |= speed[speed_index].lpa & duplex[duplex_index].lpa; 145 + lpagb |= speed[speed_index].lpagb & duplex[duplex_index].lpagb; 146 + 147 + if (state->pause) 148 + lpa |= LPA_PAUSE_CAP; 149 + 150 + if (state->asym_pause) 151 + lpa |= LPA_PAUSE_ASYM; 152 + } 153 + 154 + switch (reg) { 155 + case MII_BMCR: 156 + return bmcr; 157 + case MII_BMSR: 158 + return bmsr; 159 + case MII_PHYSID1: 160 + case MII_PHYSID2: 161 + return 0; 162 + case MII_LPA: 163 + return lpa; 164 + case MII_STAT1000: 165 + return lpagb; 166 + 167 + /* 168 + * We do not support emulating Clause 45 over Clause 22 register 169 + * reads. Return an error instead of bogus data. 170 + */ 171 + case MII_MMD_CTRL: 172 + case MII_MMD_DATA: 173 + return -1; 174 + 175 + default: 176 + return 0xffff; 177 + } 178 + } 179 + EXPORT_SYMBOL_GPL(swphy_read_reg);
+9
drivers/net/phy/swphy.h
··· 1 + #ifndef SWPHY_H 2 + #define SWPHY_H 3 + 4 + struct fixed_phy_status; 5 + 6 + int swphy_validate_state(const struct fixed_phy_status *state); 7 + int swphy_read_reg(int reg, const struct fixed_phy_status *state); 8 + 9 + #endif