[kernel] update to 2.6.25.1 and refresh patches
[openwrt/svn-archive/archive.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 */