Root/target/linux/rdc/patches-2.6.32/014-r6040_phylib_support.patch

1--- a/drivers/net/r6040.c
2+++ b/drivers/net/r6040.c
3@@ -45,6 +45,7 @@
4 #include <linux/io.h>
5 #include <linux/irq.h>
6 #include <linux/uaccess.h>
7+#include <linux/phy.h>
8 
9 #include <asm/processor.h>
10 
11@@ -180,7 +181,6 @@ struct r6040_descriptor {
12 
13 struct r6040_private {
14     spinlock_t lock; /* driver lock */
15- struct timer_list timer;
16     struct pci_dev *pdev;
17     struct r6040_descriptor *rx_insert_ptr;
18     struct r6040_descriptor *rx_remove_ptr;
19@@ -190,13 +190,15 @@ struct r6040_private {
20     struct r6040_descriptor *tx_ring;
21     dma_addr_t rx_ring_dma;
22     dma_addr_t tx_ring_dma;
23- u16 tx_free_desc, phy_addr, phy_mode;
24+ u16 tx_free_desc, phy_addr;
25     u16 mcr0, mcr1;
26- u16 switch_sig;
27     struct net_device *dev;
28- struct mii_if_info mii_if;
29+ struct mii_bus *mii_bus;
30     struct napi_struct napi;
31     void __iomem *base;
32+ struct phy_device *phydev;
33+ int old_link;
34+ int old_duplex;
35 };
36 
37 static char version[] __devinitdata = KERN_INFO DRV_NAME
38@@ -239,20 +241,29 @@ static void r6040_phy_write(void __iomem
39     }
40 }
41 
42-static int r6040_mdio_read(struct net_device *dev, int mii_id, int reg)
43+static int r6040_mdiobus_read(struct mii_bus *bus, int phy_addr, int reg)
44 {
45+ struct net_device *dev = bus->priv;
46     struct r6040_private *lp = netdev_priv(dev);
47     void __iomem *ioaddr = lp->base;
48 
49- return (r6040_phy_read(ioaddr, lp->phy_addr, reg));
50+ return r6040_phy_read(ioaddr, phy_addr, reg);
51 }
52 
53-static void r6040_mdio_write(struct net_device *dev, int mii_id, int reg, int val)
54+static int r6040_mdiobus_write(struct mii_bus *bus, int phy_addr, int reg, u16 value)
55 {
56+ struct net_device *dev = bus->priv;
57     struct r6040_private *lp = netdev_priv(dev);
58     void __iomem *ioaddr = lp->base;
59 
60- r6040_phy_write(ioaddr, lp->phy_addr, reg, val);
61+ r6040_phy_write(ioaddr, phy_addr, reg, value);
62+
63+ return 0;
64+}
65+
66+static int r6040_mdiobus_reset(struct mii_bus *bus)
67+{
68+ return 0;
69 }
70 
71 static void r6040_free_txbufs(struct net_device *dev)
72@@ -409,10 +420,9 @@ static void r6040_tx_timeout(struct net_
73     void __iomem *ioaddr = priv->base;
74 
75     printk(KERN_WARNING "%s: transmit timed out, int enable %4.4x "
76- "status %4.4x, PHY status %4.4x\n",
77+ "status %4.4x\n",
78         dev->name, ioread16(ioaddr + MIER),
79- ioread16(ioaddr + MISR),
80- r6040_mdio_read(dev, priv->mii_if.phy_id, MII_BMSR));
81+ ioread16(ioaddr + MISR));
82 
83     dev->stats.tx_errors++;
84 
85@@ -464,9 +474,6 @@ static int r6040_close(struct net_device
86     struct r6040_private *lp = netdev_priv(dev);
87     struct pci_dev *pdev = lp->pdev;
88 
89- /* deleted timer */
90- del_timer_sync(&lp->timer);
91-
92     spin_lock_irq(&lp->lock);
93     napi_disable(&lp->napi);
94     netif_stop_queue(dev);
95@@ -496,64 +503,14 @@ static int r6040_close(struct net_device
96     return 0;
97 }
98 
99-/* Status of PHY CHIP */
100-static int r6040_phy_mode_chk(struct net_device *dev)
101-{
102- struct r6040_private *lp = netdev_priv(dev);
103- void __iomem *ioaddr = lp->base;
104- int phy_dat;
105-
106- /* PHY Link Status Check */
107- phy_dat = r6040_phy_read(ioaddr, lp->phy_addr, 1);
108- if (!(phy_dat & 0x4))
109- phy_dat = 0x8000; /* Link Failed, full duplex */
110-
111- /* PHY Chip Auto-Negotiation Status */
112- phy_dat = r6040_phy_read(ioaddr, lp->phy_addr, 1);
113- if (phy_dat & 0x0020) {
114- /* Auto Negotiation Mode */
115- phy_dat = r6040_phy_read(ioaddr, lp->phy_addr, 5);
116- phy_dat &= r6040_phy_read(ioaddr, lp->phy_addr, 4);
117- if (phy_dat & 0x140)
118- /* Force full duplex */
119- phy_dat = 0x8000;
120- else
121- phy_dat = 0;
122- } else {
123- /* Force Mode */
124- phy_dat = r6040_phy_read(ioaddr, lp->phy_addr, 0);
125- if (phy_dat & 0x100)
126- phy_dat = 0x8000;
127- else
128- phy_dat = 0x0000;
129- }
130-
131- return phy_dat;
132-};
133-
134-static void r6040_set_carrier(struct mii_if_info *mii)
135-{
136- if (r6040_phy_mode_chk(mii->dev)) {
137- /* autoneg is off: Link is always assumed to be up */
138- if (!netif_carrier_ok(mii->dev))
139- netif_carrier_on(mii->dev);
140- } else
141- r6040_phy_mode_chk(mii->dev);
142-}
143-
144 static int r6040_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
145 {
146     struct r6040_private *lp = netdev_priv(dev);
147- struct mii_ioctl_data *data = if_mii(rq);
148- int rc;
149 
150- if (!netif_running(dev))
151+ if (!lp->phydev)
152         return -EINVAL;
153- spin_lock_irq(&lp->lock);
154- rc = generic_mii_ioctl(&lp->mii_if, data, cmd, NULL);
155- spin_unlock_irq(&lp->lock);
156- r6040_set_carrier(&lp->mii_if);
157- return rc;
158+
159+ return phy_mii_ioctl(lp->phydev, if_mii(rq), cmd);
160 }
161 
162 static int r6040_rx(struct net_device *dev, int limit)
163@@ -752,26 +709,6 @@ static int r6040_up(struct net_device *d
164     if (ret)
165         return ret;
166 
167- /* Read the PHY ID */
168- lp->switch_sig = r6040_phy_read(ioaddr, 0, 2);
169-
170- if (lp->switch_sig == ICPLUS_PHY_ID) {
171- r6040_phy_write(ioaddr, 29, 31, 0x175C); /* Enable registers */
172- lp->phy_mode = 0x8000;
173- } else {
174- /* PHY Mode Check */
175- r6040_phy_write(ioaddr, lp->phy_addr, 4, PHY_CAP);
176- r6040_phy_write(ioaddr, lp->phy_addr, 0, PHY_MODE);
177-
178- if (PHY_MODE == 0x3100)
179- lp->phy_mode = r6040_phy_mode_chk(dev);
180- else
181- lp->phy_mode = (PHY_MODE & 0x0100) ? 0x8000:0x0;
182- }
183-
184- /* Set duplex mode */
185- lp->mcr0 |= lp->phy_mode;
186-
187     /* improve performance (by RDC guys) */
188     r6040_phy_write(ioaddr, 30, 17, (r6040_phy_read(ioaddr, 30, 17) | 0x4000));
189     r6040_phy_write(ioaddr, 30, 17, ~((~r6040_phy_read(ioaddr, 30, 17)) | 0x2000));
190@@ -784,35 +721,6 @@ static int r6040_up(struct net_device *d
191     return 0;
192 }
193 
194-/*
195- A periodic timer routine
196- Polling PHY Chip Link Status
197-*/
198-static void r6040_timer(unsigned long data)
199-{
200- struct net_device *dev = (struct net_device *)data;
201- struct r6040_private *lp = netdev_priv(dev);
202- void __iomem *ioaddr = lp->base;
203- u16 phy_mode;
204-
205- /* Polling PHY Chip Status */
206- if (PHY_MODE == 0x3100)
207- phy_mode = r6040_phy_mode_chk(dev);
208- else
209- phy_mode = (PHY_MODE & 0x0100) ? 0x8000:0x0;
210-
211- if (phy_mode != lp->phy_mode) {
212- lp->phy_mode = phy_mode;
213- lp->mcr0 = (lp->mcr0 & 0x7fff) | phy_mode;
214- iowrite16(lp->mcr0, ioaddr);
215- }
216-
217- /* Timer active again */
218- mod_timer(&lp->timer, round_jiffies(jiffies + HZ));
219-
220- /* Check media */
221- mii_check_media(&lp->mii_if, 1, 1);
222-}
223 
224 /* Read/set MAC address routines */
225 static void r6040_mac_address(struct net_device *dev)
226@@ -874,10 +782,6 @@ static int r6040_open(struct net_device
227     napi_enable(&lp->napi);
228     netif_start_queue(dev);
229 
230- /* set and active a timer process */
231- setup_timer(&lp->timer, r6040_timer, (unsigned long) dev);
232- if (lp->switch_sig != ICPLUS_PHY_ID)
233- mod_timer(&lp->timer, jiffies + HZ);
234     return 0;
235 }
236 
237@@ -1018,40 +922,22 @@ static void netdev_get_drvinfo(struct ne
238 static int netdev_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
239 {
240     struct r6040_private *rp = netdev_priv(dev);
241- int rc;
242-
243- spin_lock_irq(&rp->lock);
244- rc = mii_ethtool_gset(&rp->mii_if, cmd);
245- spin_unlock_irq(&rp->lock);
246 
247- return rc;
248+ return phy_ethtool_gset(rp->phydev, cmd);
249 }
250 
251 static int netdev_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
252 {
253     struct r6040_private *rp = netdev_priv(dev);
254- int rc;
255-
256- spin_lock_irq(&rp->lock);
257- rc = mii_ethtool_sset(&rp->mii_if, cmd);
258- spin_unlock_irq(&rp->lock);
259- r6040_set_carrier(&rp->mii_if);
260-
261- return rc;
262-}
263-
264-static u32 netdev_get_link(struct net_device *dev)
265-{
266- struct r6040_private *rp = netdev_priv(dev);
267 
268- return mii_link_ok(&rp->mii_if);
269+ return phy_ethtool_sset(rp->phydev, cmd);
270 }
271 
272 static const struct ethtool_ops netdev_ethtool_ops = {
273     .get_drvinfo = netdev_get_drvinfo,
274     .get_settings = netdev_get_settings,
275     .set_settings = netdev_set_settings,
276- .get_link = netdev_get_link,
277+ .get_link = ethtool_op_get_link,
278 };
279 
280 static const struct net_device_ops r6040_netdev_ops = {
281@@ -1070,6 +956,86 @@ static const struct net_device_ops r6040
282 #endif
283 };
284 
285+static void r6040_adjust_link(struct net_device *dev)
286+{
287+ struct r6040_private *lp = netdev_priv(dev);
288+ struct phy_device *phydev = lp->phydev;
289+ int status_changed = 0;
290+ void __iomem *ioaddr = lp->base;
291+
292+ BUG_ON (!phydev);
293+
294+ if (lp->old_link != phydev->link) {
295+ status_changed = 1;
296+ lp->old_link = phydev->link;
297+ }
298+
299+ /* reflect duplex change */
300+ if (phydev->link && (lp->old_duplex != phydev->duplex)) {
301+ lp->mcr0 |= (phydev->duplex == DUPLEX_FULL ? 0x8000 : 0);
302+ iowrite16(lp->mcr0, ioaddr);
303+
304+ status_changed = 1;
305+ lp->old_duplex = phydev->duplex;
306+ }
307+
308+ if (status_changed) {
309+ pr_info("%s: link %s", dev->name, phydev->link ?
310+ "UP" : "DOWN");
311+ if (phydev->link)
312+ pr_cont(" - %d/%s", phydev->speed,
313+ DUPLEX_FULL == phydev->duplex ? "full" : "half");
314+ pr_cont("\n");
315+ }
316+}
317+
318+static int r6040_mii_probe(struct net_device *dev)
319+{
320+ struct r6040_private *lp = netdev_priv(dev);
321+ struct phy_device *phydev = NULL;
322+ int phy_addr;
323+
324+ for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) {
325+ if (lp->mii_bus->phy_map[phy_addr]) {
326+ phydev = lp->mii_bus->phy_map[phy_addr];
327+ break;
328+ }
329+ }
330+
331+ if (!phydev) {
332+ printk(KERN_ERR DRV_NAME "no PHY found\n");
333+ return -ENODEV;
334+ }
335+
336+ phydev = phy_connect(dev, dev_name(&phydev->dev), &r6040_adjust_link,
337+ 0, PHY_INTERFACE_MODE_MII);
338+
339+ if (IS_ERR(phydev)) {
340+ printk(KERN_ERR DRV_NAME "could not attach to PHY\n");
341+ return PTR_ERR(phydev);
342+ }
343+
344+ /* mask with MAC supported features */
345+ phydev->supported &= (SUPPORTED_10baseT_Half
346+ | SUPPORTED_10baseT_Full
347+ | SUPPORTED_100baseT_Half
348+ | SUPPORTED_100baseT_Full
349+ | SUPPORTED_Autoneg
350+ | SUPPORTED_MII
351+ | SUPPORTED_TP);
352+
353+ phydev->advertising = phydev->supported;
354+ lp->phydev = phydev;
355+ lp->old_link = 0;
356+ lp->old_duplex = -1;
357+
358+ printk(KERN_INFO "%s: attached PHY driver [%s] "
359+ "(mii_bus:phy_addr=%s)\n", dev->name,
360+ phydev->drv->name, dev_name(&phydev->dev));
361+
362+ return 0;
363+}
364+
365 static int __devinit r6040_init_one(struct pci_dev *pdev,
366                      const struct pci_device_id *ent)
367 {
368@@ -1080,6 +1046,7 @@ static int __devinit r6040_init_one(stru
369     static int card_idx = -1;
370     int bar = 0;
371     u16 *adrp;
372+ int i;
373 
374     printk("%s\n", version);
375 
376@@ -1167,7 +1134,6 @@ static int __devinit r6040_init_one(stru
377     /* Init RDC private data */
378     lp->mcr0 = 0x1002;
379     lp->phy_addr = phy_table[card_idx];
380- lp->switch_sig = 0;
381 
382     /* The RDC-specific entries in the device structure. */
383     dev->netdev_ops = &r6040_netdev_ops;
384@@ -1175,28 +1141,61 @@ static int __devinit r6040_init_one(stru
385     dev->watchdog_timeo = TX_TIMEOUT;
386 
387     netif_napi_add(dev, &lp->napi, r6040_poll, 64);
388- lp->mii_if.dev = dev;
389- lp->mii_if.mdio_read = r6040_mdio_read;
390- lp->mii_if.mdio_write = r6040_mdio_write;
391- lp->mii_if.phy_id = lp->phy_addr;
392- lp->mii_if.phy_id_mask = 0x1f;
393- lp->mii_if.reg_num_mask = 0x1f;
394+
395+ lp->mii_bus = mdiobus_alloc();
396+ if (!lp->mii_bus) {
397+ printk(KERN_ERR DRV_NAME ": mdiobus_alloc failed\n");
398+ goto err_out_unmap;
399+ }
400+
401+ lp->mii_bus->priv = dev;
402+ lp->mii_bus->read = r6040_mdiobus_read;
403+ lp->mii_bus->write = r6040_mdiobus_write;
404+ lp->mii_bus->reset = r6040_mdiobus_reset;
405+ lp->mii_bus->name = "r6040_eth_mii";
406+ snprintf(lp->mii_bus->id, MII_BUS_ID_SIZE, "%x", card_idx);
407+ lp->mii_bus->irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL);
408+ if (!lp->mii_bus->irq) {
409+ printk(KERN_ERR DRV_NAME ": allocation failed\n");
410+ goto err_out_mdio;
411+ }
412+
413+ for (i = 0; i < PHY_MAX_ADDR; i++)
414+ lp->mii_bus->irq[i] = PHY_POLL;
415+
416+ err = mdiobus_register(lp->mii_bus);
417+ if (err) {
418+ printk(KERN_ERR DRV_NAME ": failed to register MII bus\n");
419+ goto err_out_mdio_irq;
420+ }
421+
422+ err = r6040_mii_probe(dev);
423+ if (err) {
424+ printk(KERN_ERR DRV_NAME ": failed to probe MII bus\n");
425+ goto err_out_mdio_unregister;
426+ }
427 
428     /* Check the vendor ID on the PHY, if 0xffff assume none attached */
429     if (r6040_phy_read(ioaddr, lp->phy_addr, 2) == 0xffff) {
430         printk(KERN_ERR DRV_NAME ": Failed to detect an attached PHY\n");
431         err = -ENODEV;
432- goto err_out_unmap;
433+ goto err_out_mdio_unregister;
434     }
435 
436     /* Register net device. After this dev->name assign */
437     err = register_netdev(dev);
438     if (err) {
439         printk(KERN_ERR DRV_NAME ": Failed to register net device\n");
440- goto err_out_unmap;
441+ goto err_out_mdio_unregister;
442     }
443     return 0;
444 
445+err_out_mdio_unregister:
446+ mdiobus_unregister(lp->mii_bus);
447+err_out_mdio_irq:
448+ kfree(lp->mii_bus->irq);
449+err_out_mdio:
450+ mdiobus_free(lp->mii_bus);
451 err_out_unmap:
452     pci_iounmap(pdev, ioaddr);
453 err_out_free_res:
454@@ -1210,8 +1209,12 @@ err_out:
455 static void __devexit r6040_remove_one(struct pci_dev *pdev)
456 {
457     struct net_device *dev = pci_get_drvdata(pdev);
458+ struct r6040_private *lp = netdev_priv(dev);
459 
460     unregister_netdev(dev);
461+ mdiobus_unregister(lp->mii_bus);
462+ kfree(lp->mii_bus->irq);
463+ mdiobus_free(lp->mii_bus);
464     pci_release_regions(pdev);
465     free_netdev(dev);
466     pci_disable_device(pdev);
467

Archive Download this file



interactive