[kernel] update to 2.6.25.1 and refresh patches
[openwrt.git] / target / linux / ixp4xx / patches-2.6.25 / 202-npe_driver_switch_support.patch
1 Index: linux-2.6.25.1/drivers/net/arm/ixp4xx_eth.c
2 ===================================================================
3 --- linux-2.6.25.1.orig/drivers/net/arm/ixp4xx_eth.c
4 +++ linux-2.6.25.1/drivers/net/arm/ixp4xx_eth.c
5 @@ -165,14 +165,15 @@ struct port {
6         struct net_device *netdev;
7         struct napi_struct napi;
8         struct net_device_stats stat;
9 -       struct mii_if_info mii;
10 +       struct mii_if_info mii[IXP4XX_ETH_PHY_MAX_ADDR];
11         struct delayed_work mdio_thread;
12         struct eth_plat_info *plat;
13         buffer_t *rx_buff_tab[RX_DESCS], *tx_buff_tab[TX_DESCS];
14         struct desc *desc_tab;  /* coherent */
15         u32 desc_tab_phys;
16         int id;                 /* logical port ID */
17 -       u16 mii_bmcr;
18 +       u16 mii_bmcr[IXP4XX_ETH_PHY_MAX_ADDR];
19 +       int phy_count;
20  };
21  
22  /* NPE message structure */
23 @@ -316,12 +317,13 @@ static void mdio_write(struct net_device
24         spin_unlock_irqrestore(&mdio_lock, flags);
25  }
26  
27 -static void phy_reset(struct net_device *dev, int phy_id)
28 +static void phy_reset(struct net_device *dev, int idx)
29  {
30         struct port *port = netdev_priv(dev);
31 +       int phy_id = port->mii[idx].phy_id;
32         int cycles = 0;
33  
34 -       mdio_write(dev, phy_id, MII_BMCR, port->mii_bmcr | BMCR_RESET);
35 +       mdio_write(dev, phy_id, MII_BMCR, port->mii_bmcr[idx] | BMCR_RESET);
36  
37         while (cycles < MAX_MII_RESET_RETRIES) {
38                 if (!(mdio_read(dev, phy_id, MII_BMCR) & BMCR_RESET)) {
39 @@ -335,12 +337,12 @@ static void phy_reset(struct net_device 
40                 cycles++;
41         }
42  
43 -       printk(KERN_ERR "%s: MII reset failed\n", dev->name);
44 +       printk(KERN_ERR "%s: MII reset failed on PHY%2d\n", dev->name, phy_id);
45  }
46  
47 -static void eth_set_duplex(struct port *port)
48 +static void eth_set_duplex(struct port *port, int full_duplex)
49  {
50 -       if (port->mii.full_duplex)
51 +       if (full_duplex)
52                 __raw_writel(DEFAULT_TX_CNTRL0 & ~TX_CNTRL0_HALFDUPLEX,
53                              &port->regs->tx_control[0]);
54         else
55 @@ -348,7 +350,7 @@ static void eth_set_duplex(struct port *
56                              &port->regs->tx_control[0]);
57  }
58  
59 -
60 +#if 0
61  static void phy_check_media(struct port *port, int init)
62  {
63         if (mii_check_media(&port->mii, 1, init))
64 @@ -367,7 +369,63 @@ static void phy_check_media(struct port 
65                 }
66         }
67  }
68 +#else
69 +static void phy_update_link(struct net_device *dev, int link)
70 +{
71 +       int prev_link = netif_carrier_ok(dev);
72 +
73 +       if (!prev_link && link) {
74 +               printk(KERN_INFO "%s: link up\n", dev->name);
75 +               netif_carrier_on(dev);
76 +       } else if (prev_link && !link) {
77 +               printk(KERN_INFO "%s: link down\n", dev->name);
78 +               netif_carrier_off(dev);
79 +       }
80 +}
81 +
82 +static void phy_check_media(struct port *port, int init)
83 +{
84 +       struct net_device *dev = port->netdev;
85 +
86 +       if (port->phy_count == 1) {
87 +               struct mii_if_info *mii = &port->mii[0];
88 +
89 +               if (mii_check_media(mii, 1, init))
90 +                       eth_set_duplex(port, mii->full_duplex);
91 +
92 +               if (mii->force_media) /* mii_check_media() doesn't work */
93 +                       phy_update_link(dev, mii_link_ok(mii));
94 +       } else {
95 +               int cur_link = 0;
96 +               int i;
97 +
98 +               if (init)
99 +                       eth_set_duplex(port, 1);
100 +
101 +               for (i = 0; i < port->phy_count; i++)
102 +                       cur_link |= mii_link_ok(&port->mii[i]);
103 +
104 +               phy_update_link(dev, cur_link);
105 +       }
106 +}
107 +#endif
108 +
109 +static void phy_power_down(struct net_device *dev, int idx)
110 +{
111 +       struct port *port = netdev_priv(dev);
112 +       int phy_id = port->mii[idx].phy_id;
113 +
114 +       port->mii_bmcr[idx] = mdio_read(dev, phy_id, MII_BMCR) &
115 +                                               ~(BMCR_RESET | BMCR_PDOWN);
116 +       mdio_write(dev, phy_id, MII_BMCR, port->mii_bmcr[idx] | BMCR_PDOWN);
117 +}
118 +
119 +static void phy_power_up(struct net_device *dev, int idx)
120 +{
121 +       struct port *port = netdev_priv(dev);
122  
123 +       mdio_write(dev, port->mii[idx].phy_id, MII_BMCR, port->mii_bmcr[idx]);
124 +}
125  
126  static void mdio_thread(struct work_struct *work)
127  {
128 @@ -792,9 +850,12 @@ static int eth_ioctl(struct net_device *
129  
130         if (!netif_running(dev))
131                 return -EINVAL;
132 -       err = generic_mii_ioctl(&port->mii, if_mii(req), cmd, &duplex_chg);
133 +       if (port->phy_count != 1)
134 +               return -EOPNOTSUPP;
135 +
136 +       err = generic_mii_ioctl(&port->mii[0], if_mii(req), cmd, &duplex_chg);
137         if (duplex_chg)
138 -               eth_set_duplex(port);
139 +               eth_set_duplex(port, port->mii[0].full_duplex);
140         return err;
141  }
142  
143 @@ -947,7 +1008,8 @@ static int eth_open(struct net_device *d
144                 }
145         }
146  
147 -       mdio_write(dev, port->plat->phy, MII_BMCR, port->mii_bmcr);
148 +       for (i = 0; i < port->phy_count; i++)
149 +               phy_power_up(dev, i);
150  
151         memset(&msg, 0, sizeof(msg));
152         msg.cmd = NPE_VLAN_SETRXQOSENTRY;
153 @@ -1107,10 +1169,8 @@ static int eth_close(struct net_device *
154                 printk(KERN_CRIT "%s: unable to disable loopback\n",
155                        dev->name);
156  
157 -       port->mii_bmcr = mdio_read(dev, port->plat->phy, MII_BMCR) &
158 -               ~(BMCR_RESET | BMCR_PDOWN); /* may have been altered */
159 -       mdio_write(dev, port->plat->phy, MII_BMCR,
160 -                  port->mii_bmcr | BMCR_PDOWN);
161 +       for (i = 0; i < port->phy_count; i++)
162 +               phy_power_down(dev, i);
163  
164         if (!ports_open)
165                 qmgr_disable_irq(TXDONE_QUEUE);
166 @@ -1120,6 +1180,42 @@ static int eth_close(struct net_device *
167         return 0;
168  }
169  
170 +static void eth_add_phy(struct net_device *dev, int phy_id)
171 +{
172 +       struct port *port = netdev_priv(dev);
173 +       int i;
174 +
175 +       i = port->phy_count++;
176 +
177 +       port->mii[i].dev = dev;
178 +       port->mii[i].mdio_read = mdio_read;
179 +       port->mii[i].mdio_write = mdio_write;
180 +       port->mii[i].phy_id = phy_id;
181 +       port->mii[i].phy_id_mask = 0x1F;
182 +       port->mii[i].reg_num_mask = 0x1F;
183 +
184 +       printk(KERN_INFO "%s: MII PHY %i on %s\n", dev->name, phy_id,
185 +              npe_name(port->npe));
186 +
187 +       phy_reset(dev, i);
188 +       phy_power_down(dev, i);
189 +}
190 +
191 +static void eth_init_mii(struct net_device *dev)
192 +{
193 +       struct port *port = netdev_priv(dev);
194 +
195 +       if (port->plat->phy < IXP4XX_ETH_PHY_MAX_ADDR) {
196 +               eth_add_phy(dev, port->plat->phy);
197 +       } else {
198 +               int i;
199 +               for (i = 0; i < IXP4XX_ETH_PHY_MAX_ADDR; i++)
200 +                       if (port->plat->phy_mask & (1U << i))
201 +                               eth_add_phy(dev, i);
202 +       }
203 +
204 +}
205 +
206  static int __devinit eth_init_one(struct platform_device *pdev)
207  {
208         struct port *port;
209 @@ -1192,20 +1288,7 @@ static int __devinit eth_init_one(struct
210         __raw_writel(DEFAULT_CORE_CNTRL, &port->regs->core_control);
211         udelay(50);
212  
213 -       port->mii.dev = dev;
214 -       port->mii.mdio_read = mdio_read;
215 -       port->mii.mdio_write = mdio_write;
216 -       port->mii.phy_id = plat->phy;
217 -       port->mii.phy_id_mask = 0x1F;
218 -       port->mii.reg_num_mask = 0x1F;
219 -
220 -       printk(KERN_INFO "%s: MII PHY %i on %s\n", dev->name, plat->phy,
221 -              npe_name(port->npe));
222 -
223 -       phy_reset(dev, plat->phy);
224 -       port->mii_bmcr = mdio_read(dev, plat->phy, MII_BMCR) &
225 -               ~(BMCR_RESET | BMCR_PDOWN);
226 -       mdio_write(dev, plat->phy, MII_BMCR, port->mii_bmcr | BMCR_PDOWN);
227 +       eth_init_mii(dev);
228  
229         INIT_DELAYED_WORK(&port->mdio_thread, mdio_thread);
230         return 0;
231 Index: linux-2.6.25.1/include/asm-arm/arch-ixp4xx/platform.h
232 ===================================================================
233 --- linux-2.6.25.1.orig/include/asm-arm/arch-ixp4xx/platform.h
234 +++ linux-2.6.25.1/include/asm-arm/arch-ixp4xx/platform.h
235 @@ -95,12 +95,15 @@ struct sys_timer;
236  #define IXP4XX_ETH_NPEB                0x10
237  #define IXP4XX_ETH_NPEC                0x20
238  
239 +#define IXP4XX_ETH_PHY_MAX_ADDR        32
240 +
241  /* Information about built-in Ethernet MAC interfaces */
242  struct eth_plat_info {
243         u8 phy;         /* MII PHY ID, 0 - 31 */
244         u8 rxq;         /* configurable, currently 0 - 31 only */
245         u8 txreadyq;
246         u8 hwaddr[6];
247 +       u32 phy_mask;
248  };
249  
250  /* Information about built-in HSS (synchronous serial) interfaces */