phy: convert swphy register generation to tabular form
authorRussell King <rmk+kernel@arm.linux.org.uk>
Thu, 23 Jun 2016 13:50:10 +0000 (14:50 +0100)
committerDavid S. Miller <davem@davemloft.net>
Mon, 27 Jun 2016 14:40:57 +0000 (10:40 -0400)
Convert the swphy register generation to tabular form which allows us
to eliminate multiple switch() statements.  This results in a smaller
object code size, more efficient, and easier to add support for faster
speeds.

Before:

Idx Name          Size      VMA       LMA       File off  Algn
  0 .text         00000164  00000000  00000000  00000034  2**2

   text    data     bss     dec     hex filename
    388       0       0     388     184 swphy.o

After:

Idx Name          Size      VMA       LMA       File off  Algn
  0 .text         000000fc  00000000  00000000  00000034  2**2
  5 .rodata       00000028  00000000  00000000  00000138  2**2

   text    data     bss     dec     hex filename
    324       0       0     324     144 swphy.o

Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/phy/swphy.c

index 0551a79..c88a194 100644 (file)
 
 #include "swphy.h"
 
+struct swmii_regs {
+       u16 bmcr;
+       u16 bmsr;
+       u16 lpa;
+       u16 lpagb;
+};
+
+enum {
+       SWMII_SPEED_10 = 0,
+       SWMII_SPEED_100,
+       SWMII_SPEED_1000,
+       SWMII_DUPLEX_HALF = 0,
+       SWMII_DUPLEX_FULL,
+};
+
+/*
+ * These two tables get bitwise-anded together to produce the final result.
+ * This means the speed table must contain both duplex settings, and the
+ * duplex table must contain all speed settings.
+ */
+static const struct swmii_regs speed[] = {
+       [SWMII_SPEED_10] = {
+               .bmcr  = BMCR_FULLDPLX,
+               .lpa   = LPA_10FULL | LPA_10HALF,
+       },
+       [SWMII_SPEED_100] = {
+               .bmcr  = BMCR_FULLDPLX | BMCR_SPEED100,
+               .bmsr  = BMSR_100FULL | BMSR_100HALF,
+               .lpa   = LPA_100FULL | LPA_100HALF,
+       },
+       [SWMII_SPEED_1000] = {
+               .bmcr  = BMCR_FULLDPLX | BMCR_SPEED1000,
+               .bmsr  = BMSR_ESTATEN,
+               .lpagb = LPA_1000FULL | LPA_1000HALF,
+       },
+};
+
+static const struct swmii_regs duplex[] = {
+       [SWMII_DUPLEX_HALF] = {
+               .bmcr  = ~BMCR_FULLDPLX,
+               .bmsr  = BMSR_ESTATEN | BMSR_100HALF,
+               .lpa   = LPA_10HALF | LPA_100HALF,
+               .lpagb = LPA_1000HALF,
+       },
+       [SWMII_DUPLEX_FULL] = {
+               .bmcr  = ~0,
+               .bmsr  = BMSR_ESTATEN | BMSR_100FULL,
+               .lpa   = LPA_10FULL | LPA_100FULL,
+               .lpagb = LPA_1000FULL,
+       },
+};
+
+static int swphy_decode_speed(int speed)
+{
+       switch (speed) {
+       case 1000:
+               return SWMII_SPEED_1000;
+       case 100:
+               return SWMII_SPEED_100;
+       case 10:
+               return SWMII_SPEED_10;
+       default:
+               return -EINVAL;
+       }
+}
+
 /**
  * swphy_update_regs - update MII register array with fixed phy state
  * @regs: array of 32 registers to update
  */
 int swphy_update_regs(u16 *regs, const struct fixed_phy_status *state)
 {
+       int speed_index, duplex_index;
        u16 bmsr = BMSR_ANEGCAPABLE;
        u16 bmcr = 0;
        u16 lpagb = 0;
        u16 lpa = 0;
 
-       if (state->duplex) {
-               switch (state->speed) {
-               case 1000:
-                       bmsr |= BMSR_ESTATEN;
-                       break;
-               case 100:
-                       bmsr |= BMSR_100FULL;
-                       break;
-               case 10:
-                       bmsr |= BMSR_10FULL;
-                       break;
-               default:
-                       break;
-               }
-       } else {
-               switch (state->speed) {
-               case 1000:
-                       bmsr |= BMSR_ESTATEN;
-                       break;
-               case 100:
-                       bmsr |= BMSR_100HALF;
-                       break;
-               case 10:
-                       bmsr |= BMSR_10HALF;
-                       break;
-               default:
-                       break;
-               }
+       speed_index = swphy_decode_speed(state->speed);
+       if (speed_index < 0) {
+               pr_warn("swphy: unknown speed\n");
+               return -EINVAL;
        }
 
+       duplex_index = state->duplex ? SWMII_DUPLEX_FULL : SWMII_DUPLEX_HALF;
+
+       bmsr |= speed[speed_index].bmsr & duplex[duplex_index].bmsr;
+
        if (state->link) {
                bmsr |= BMSR_LSTATUS | BMSR_ANEGCOMPLETE;
 
-               if (state->duplex) {
-                       bmcr |= BMCR_FULLDPLX;
-
-                       switch (state->speed) {
-                       case 1000:
-                               bmcr |= BMCR_SPEED1000;
-                               lpagb |= LPA_1000FULL;
-                               break;
-                       case 100:
-                               bmcr |= BMCR_SPEED100;
-                               lpa |= LPA_100FULL;
-                               break;
-                       case 10:
-                               lpa |= LPA_10FULL;
-                               break;
-                       default:
-                               pr_warn("swphy: unknown speed\n");
-                               return -EINVAL;
-                       }
-               } else {
-                       switch (state->speed) {
-                       case 1000:
-                               bmcr |= BMCR_SPEED1000;
-                               lpagb |= LPA_1000HALF;
-                               break;
-                       case 100:
-                               bmcr |= BMCR_SPEED100;
-                               lpa |= LPA_100HALF;
-                               break;
-                       case 10:
-                               lpa |= LPA_10HALF;
-                               break;
-                       default:
-                               pr_warn("swphy: unknown speed\n");
-                               return -EINVAL;
-                       }
-               }
+               bmcr  |= speed[speed_index].bmcr  & duplex[duplex_index].bmcr;
+               lpa   |= speed[speed_index].lpa   & duplex[duplex_index].lpa;
+               lpagb |= speed[speed_index].lpagb & duplex[duplex_index].lpagb;
 
                if (state->pause)
                        lpa |= LPA_PAUSE_CAP;