diff options
-rw-r--r-- | drivers/net/Kconfig | 1 | ||||
-rw-r--r-- | drivers/net/r6040.c | 298 |
2 files changed, 145 insertions, 154 deletions
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 2decc597bda7..fe113d0e9456 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig | |||
@@ -1659,6 +1659,7 @@ config R6040 | |||
1659 | depends on NET_PCI && PCI | 1659 | depends on NET_PCI && PCI |
1660 | select CRC32 | 1660 | select CRC32 |
1661 | select MII | 1661 | select MII |
1662 | select PHYLIB | ||
1662 | help | 1663 | help |
1663 | This is a driver for the R6040 Fast Ethernet MACs found in the | 1664 | This is a driver for the R6040 Fast Ethernet MACs found in the |
1664 | the RDC R-321x System-on-chips. | 1665 | the RDC R-321x System-on-chips. |
diff --git a/drivers/net/r6040.c b/drivers/net/r6040.c index 9a251acf5ab8..6878511afc4e 100644 --- a/drivers/net/r6040.c +++ b/drivers/net/r6040.c | |||
@@ -44,6 +44,7 @@ | |||
44 | #include <linux/io.h> | 44 | #include <linux/io.h> |
45 | #include <linux/irq.h> | 45 | #include <linux/irq.h> |
46 | #include <linux/uaccess.h> | 46 | #include <linux/uaccess.h> |
47 | #include <linux/phy.h> | ||
47 | 48 | ||
48 | #include <asm/processor.h> | 49 | #include <asm/processor.h> |
49 | 50 | ||
@@ -179,7 +180,6 @@ struct r6040_descriptor { | |||
179 | 180 | ||
180 | struct r6040_private { | 181 | struct r6040_private { |
181 | spinlock_t lock; /* driver lock */ | 182 | spinlock_t lock; /* driver lock */ |
182 | struct timer_list timer; | ||
183 | struct pci_dev *pdev; | 183 | struct pci_dev *pdev; |
184 | struct r6040_descriptor *rx_insert_ptr; | 184 | struct r6040_descriptor *rx_insert_ptr; |
185 | struct r6040_descriptor *rx_remove_ptr; | 185 | struct r6040_descriptor *rx_remove_ptr; |
@@ -189,13 +189,15 @@ struct r6040_private { | |||
189 | struct r6040_descriptor *tx_ring; | 189 | struct r6040_descriptor *tx_ring; |
190 | dma_addr_t rx_ring_dma; | 190 | dma_addr_t rx_ring_dma; |
191 | dma_addr_t tx_ring_dma; | 191 | dma_addr_t tx_ring_dma; |
192 | u16 tx_free_desc, phy_addr, phy_mode; | 192 | u16 tx_free_desc, phy_addr; |
193 | u16 mcr0, mcr1; | 193 | u16 mcr0, mcr1; |
194 | u16 switch_sig; | ||
195 | struct net_device *dev; | 194 | struct net_device *dev; |
196 | struct mii_if_info mii_if; | 195 | struct mii_bus *mii_bus; |
197 | struct napi_struct napi; | 196 | struct napi_struct napi; |
198 | void __iomem *base; | 197 | void __iomem *base; |
198 | struct phy_device *phydev; | ||
199 | int old_link; | ||
200 | int old_duplex; | ||
199 | }; | 201 | }; |
200 | 202 | ||
201 | static char version[] __devinitdata = KERN_INFO DRV_NAME | 203 | static char version[] __devinitdata = KERN_INFO DRV_NAME |
@@ -238,20 +240,30 @@ static void r6040_phy_write(void __iomem *ioaddr, int phy_addr, int reg, u16 val | |||
238 | } | 240 | } |
239 | } | 241 | } |
240 | 242 | ||
241 | static int r6040_mdio_read(struct net_device *dev, int mii_id, int reg) | 243 | static int r6040_mdiobus_read(struct mii_bus *bus, int phy_addr, int reg) |
242 | { | 244 | { |
245 | struct net_device *dev = bus->priv; | ||
243 | struct r6040_private *lp = netdev_priv(dev); | 246 | struct r6040_private *lp = netdev_priv(dev); |
244 | void __iomem *ioaddr = lp->base; | 247 | void __iomem *ioaddr = lp->base; |
245 | 248 | ||
246 | return (r6040_phy_read(ioaddr, lp->phy_addr, reg)); | 249 | return r6040_phy_read(ioaddr, phy_addr, reg); |
247 | } | 250 | } |
248 | 251 | ||
249 | static void r6040_mdio_write(struct net_device *dev, int mii_id, int reg, int val) | 252 | static int r6040_mdiobus_write(struct mii_bus *bus, int phy_addr, |
253 | int reg, u16 value) | ||
250 | { | 254 | { |
255 | struct net_device *dev = bus->priv; | ||
251 | struct r6040_private *lp = netdev_priv(dev); | 256 | struct r6040_private *lp = netdev_priv(dev); |
252 | void __iomem *ioaddr = lp->base; | 257 | void __iomem *ioaddr = lp->base; |
253 | 258 | ||
254 | r6040_phy_write(ioaddr, lp->phy_addr, reg, val); | 259 | r6040_phy_write(ioaddr, phy_addr, reg, value); |
260 | |||
261 | return 0; | ||
262 | } | ||
263 | |||
264 | static int r6040_mdiobus_reset(struct mii_bus *bus) | ||
265 | { | ||
266 | return 0; | ||
255 | } | 267 | } |
256 | 268 | ||
257 | static void r6040_free_txbufs(struct net_device *dev) | 269 | static void r6040_free_txbufs(struct net_device *dev) |
@@ -408,10 +420,9 @@ static void r6040_tx_timeout(struct net_device *dev) | |||
408 | void __iomem *ioaddr = priv->base; | 420 | void __iomem *ioaddr = priv->base; |
409 | 421 | ||
410 | netdev_warn(dev, "transmit timed out, int enable %4.4x " | 422 | netdev_warn(dev, "transmit timed out, int enable %4.4x " |
411 | "status %4.4x, PHY status %4.4x\n", | 423 | "status %4.4x\n", |
412 | ioread16(ioaddr + MIER), | 424 | ioread16(ioaddr + MIER), |
413 | ioread16(ioaddr + MISR), | 425 | ioread16(ioaddr + MISR)); |
414 | r6040_mdio_read(dev, priv->mii_if.phy_id, MII_BMSR)); | ||
415 | 426 | ||
416 | dev->stats.tx_errors++; | 427 | dev->stats.tx_errors++; |
417 | 428 | ||
@@ -463,9 +474,6 @@ static int r6040_close(struct net_device *dev) | |||
463 | struct r6040_private *lp = netdev_priv(dev); | 474 | struct r6040_private *lp = netdev_priv(dev); |
464 | struct pci_dev *pdev = lp->pdev; | 475 | struct pci_dev *pdev = lp->pdev; |
465 | 476 | ||
466 | /* deleted timer */ | ||
467 | del_timer_sync(&lp->timer); | ||
468 | |||
469 | spin_lock_irq(&lp->lock); | 477 | spin_lock_irq(&lp->lock); |
470 | napi_disable(&lp->napi); | 478 | napi_disable(&lp->napi); |
471 | netif_stop_queue(dev); | 479 | netif_stop_queue(dev); |
@@ -495,64 +503,14 @@ static int r6040_close(struct net_device *dev) | |||
495 | return 0; | 503 | return 0; |
496 | } | 504 | } |
497 | 505 | ||
498 | /* Status of PHY CHIP */ | ||
499 | static int r6040_phy_mode_chk(struct net_device *dev) | ||
500 | { | ||
501 | struct r6040_private *lp = netdev_priv(dev); | ||
502 | void __iomem *ioaddr = lp->base; | ||
503 | int phy_dat; | ||
504 | |||
505 | /* PHY Link Status Check */ | ||
506 | phy_dat = r6040_phy_read(ioaddr, lp->phy_addr, 1); | ||
507 | if (!(phy_dat & 0x4)) | ||
508 | phy_dat = 0x8000; /* Link Failed, full duplex */ | ||
509 | |||
510 | /* PHY Chip Auto-Negotiation Status */ | ||
511 | phy_dat = r6040_phy_read(ioaddr, lp->phy_addr, 1); | ||
512 | if (phy_dat & 0x0020) { | ||
513 | /* Auto Negotiation Mode */ | ||
514 | phy_dat = r6040_phy_read(ioaddr, lp->phy_addr, 5); | ||
515 | phy_dat &= r6040_phy_read(ioaddr, lp->phy_addr, 4); | ||
516 | if (phy_dat & 0x140) | ||
517 | /* Force full duplex */ | ||
518 | phy_dat = 0x8000; | ||
519 | else | ||
520 | phy_dat = 0; | ||
521 | } else { | ||
522 | /* Force Mode */ | ||
523 | phy_dat = r6040_phy_read(ioaddr, lp->phy_addr, 0); | ||
524 | if (phy_dat & 0x100) | ||
525 | phy_dat = 0x8000; | ||
526 | else | ||
527 | phy_dat = 0x0000; | ||
528 | } | ||
529 | |||
530 | return phy_dat; | ||
531 | }; | ||
532 | |||
533 | static void r6040_set_carrier(struct mii_if_info *mii) | ||
534 | { | ||
535 | if (r6040_phy_mode_chk(mii->dev)) { | ||
536 | /* autoneg is off: Link is always assumed to be up */ | ||
537 | if (!netif_carrier_ok(mii->dev)) | ||
538 | netif_carrier_on(mii->dev); | ||
539 | } else | ||
540 | r6040_phy_mode_chk(mii->dev); | ||
541 | } | ||
542 | |||
543 | static int r6040_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) | 506 | static int r6040_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) |
544 | { | 507 | { |
545 | struct r6040_private *lp = netdev_priv(dev); | 508 | struct r6040_private *lp = netdev_priv(dev); |
546 | struct mii_ioctl_data *data = if_mii(rq); | ||
547 | int rc; | ||
548 | 509 | ||
549 | if (!netif_running(dev)) | 510 | if (!lp->phydev) |
550 | return -EINVAL; | 511 | return -EINVAL; |
551 | spin_lock_irq(&lp->lock); | 512 | |
552 | rc = generic_mii_ioctl(&lp->mii_if, data, cmd, NULL); | 513 | return phy_mii_ioctl(lp->phydev, if_mii(rq), cmd); |
553 | spin_unlock_irq(&lp->lock); | ||
554 | r6040_set_carrier(&lp->mii_if); | ||
555 | return rc; | ||
556 | } | 514 | } |
557 | 515 | ||
558 | static int r6040_rx(struct net_device *dev, int limit) | 516 | static int r6040_rx(struct net_device *dev, int limit) |
@@ -751,26 +709,6 @@ static int r6040_up(struct net_device *dev) | |||
751 | if (ret) | 709 | if (ret) |
752 | return ret; | 710 | return ret; |
753 | 711 | ||
754 | /* Read the PHY ID */ | ||
755 | lp->switch_sig = r6040_phy_read(ioaddr, 0, 2); | ||
756 | |||
757 | if (lp->switch_sig == ICPLUS_PHY_ID) { | ||
758 | r6040_phy_write(ioaddr, 29, 31, 0x175C); /* Enable registers */ | ||
759 | lp->phy_mode = 0x8000; | ||
760 | } else { | ||
761 | /* PHY Mode Check */ | ||
762 | r6040_phy_write(ioaddr, lp->phy_addr, 4, PHY_CAP); | ||
763 | r6040_phy_write(ioaddr, lp->phy_addr, 0, PHY_MODE); | ||
764 | |||
765 | if (PHY_MODE == 0x3100) | ||
766 | lp->phy_mode = r6040_phy_mode_chk(dev); | ||
767 | else | ||
768 | lp->phy_mode = (PHY_MODE & 0x0100) ? 0x8000:0x0; | ||
769 | } | ||
770 | |||
771 | /* Set duplex mode */ | ||
772 | lp->mcr0 |= lp->phy_mode; | ||
773 | |||
774 | /* improve performance (by RDC guys) */ | 712 | /* improve performance (by RDC guys) */ |
775 | r6040_phy_write(ioaddr, 30, 17, (r6040_phy_read(ioaddr, 30, 17) | 0x4000)); | 713 | r6040_phy_write(ioaddr, 30, 17, (r6040_phy_read(ioaddr, 30, 17) | 0x4000)); |
776 | r6040_phy_write(ioaddr, 30, 17, ~((~r6040_phy_read(ioaddr, 30, 17)) | 0x2000)); | 714 | r6040_phy_write(ioaddr, 30, 17, ~((~r6040_phy_read(ioaddr, 30, 17)) | 0x2000)); |
@@ -783,35 +721,6 @@ static int r6040_up(struct net_device *dev) | |||
783 | return 0; | 721 | return 0; |
784 | } | 722 | } |
785 | 723 | ||
786 | /* | ||
787 | A periodic timer routine | ||
788 | Polling PHY Chip Link Status | ||
789 | */ | ||
790 | static void r6040_timer(unsigned long data) | ||
791 | { | ||
792 | struct net_device *dev = (struct net_device *)data; | ||
793 | struct r6040_private *lp = netdev_priv(dev); | ||
794 | void __iomem *ioaddr = lp->base; | ||
795 | u16 phy_mode; | ||
796 | |||
797 | /* Polling PHY Chip Status */ | ||
798 | if (PHY_MODE == 0x3100) | ||
799 | phy_mode = r6040_phy_mode_chk(dev); | ||
800 | else | ||
801 | phy_mode = (PHY_MODE & 0x0100) ? 0x8000:0x0; | ||
802 | |||
803 | if (phy_mode != lp->phy_mode) { | ||
804 | lp->phy_mode = phy_mode; | ||
805 | lp->mcr0 = (lp->mcr0 & 0x7fff) | phy_mode; | ||
806 | iowrite16(lp->mcr0, ioaddr); | ||
807 | } | ||
808 | |||
809 | /* Timer active again */ | ||
810 | mod_timer(&lp->timer, round_jiffies(jiffies + HZ)); | ||
811 | |||
812 | /* Check media */ | ||
813 | mii_check_media(&lp->mii_if, 1, 1); | ||
814 | } | ||
815 | 724 | ||
816 | /* Read/set MAC address routines */ | 725 | /* Read/set MAC address routines */ |
817 | static void r6040_mac_address(struct net_device *dev) | 726 | static void r6040_mac_address(struct net_device *dev) |
@@ -873,10 +782,6 @@ static int r6040_open(struct net_device *dev) | |||
873 | napi_enable(&lp->napi); | 782 | napi_enable(&lp->napi); |
874 | netif_start_queue(dev); | 783 | netif_start_queue(dev); |
875 | 784 | ||
876 | /* set and active a timer process */ | ||
877 | setup_timer(&lp->timer, r6040_timer, (unsigned long) dev); | ||
878 | if (lp->switch_sig != ICPLUS_PHY_ID) | ||
879 | mod_timer(&lp->timer, jiffies + HZ); | ||
880 | return 0; | 785 | return 0; |
881 | } | 786 | } |
882 | 787 | ||
@@ -1015,40 +920,22 @@ static void netdev_get_drvinfo(struct net_device *dev, | |||
1015 | static int netdev_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) | 920 | static int netdev_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) |
1016 | { | 921 | { |
1017 | struct r6040_private *rp = netdev_priv(dev); | 922 | struct r6040_private *rp = netdev_priv(dev); |
1018 | int rc; | ||
1019 | |||
1020 | spin_lock_irq(&rp->lock); | ||
1021 | rc = mii_ethtool_gset(&rp->mii_if, cmd); | ||
1022 | spin_unlock_irq(&rp->lock); | ||
1023 | 923 | ||
1024 | return rc; | 924 | return phy_ethtool_gset(rp->phydev, cmd); |
1025 | } | 925 | } |
1026 | 926 | ||
1027 | static int netdev_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) | 927 | static int netdev_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) |
1028 | { | 928 | { |
1029 | struct r6040_private *rp = netdev_priv(dev); | 929 | struct r6040_private *rp = netdev_priv(dev); |
1030 | int rc; | ||
1031 | |||
1032 | spin_lock_irq(&rp->lock); | ||
1033 | rc = mii_ethtool_sset(&rp->mii_if, cmd); | ||
1034 | spin_unlock_irq(&rp->lock); | ||
1035 | r6040_set_carrier(&rp->mii_if); | ||
1036 | |||
1037 | return rc; | ||
1038 | } | ||
1039 | |||
1040 | static u32 netdev_get_link(struct net_device *dev) | ||
1041 | { | ||
1042 | struct r6040_private *rp = netdev_priv(dev); | ||
1043 | 930 | ||
1044 | return mii_link_ok(&rp->mii_if); | 931 | return phy_ethtool_sset(rp->phydev, cmd); |
1045 | } | 932 | } |
1046 | 933 | ||
1047 | static const struct ethtool_ops netdev_ethtool_ops = { | 934 | static const struct ethtool_ops netdev_ethtool_ops = { |
1048 | .get_drvinfo = netdev_get_drvinfo, | 935 | .get_drvinfo = netdev_get_drvinfo, |
1049 | .get_settings = netdev_get_settings, | 936 | .get_settings = netdev_get_settings, |
1050 | .set_settings = netdev_set_settings, | 937 | .set_settings = netdev_set_settings, |
1051 | .get_link = netdev_get_link, | 938 | .get_link = ethtool_op_get_link, |
1052 | }; | 939 | }; |
1053 | 940 | ||
1054 | static const struct net_device_ops r6040_netdev_ops = { | 941 | static const struct net_device_ops r6040_netdev_ops = { |
@@ -1067,6 +954,79 @@ static const struct net_device_ops r6040_netdev_ops = { | |||
1067 | #endif | 954 | #endif |
1068 | }; | 955 | }; |
1069 | 956 | ||
957 | static void r6040_adjust_link(struct net_device *dev) | ||
958 | { | ||
959 | struct r6040_private *lp = netdev_priv(dev); | ||
960 | struct phy_device *phydev = lp->phydev; | ||
961 | int status_changed = 0; | ||
962 | void __iomem *ioaddr = lp->base; | ||
963 | |||
964 | BUG_ON(!phydev); | ||
965 | |||
966 | if (lp->old_link != phydev->link) { | ||
967 | status_changed = 1; | ||
968 | lp->old_link = phydev->link; | ||
969 | } | ||
970 | |||
971 | /* reflect duplex change */ | ||
972 | if (phydev->link && (lp->old_duplex != phydev->duplex)) { | ||
973 | lp->mcr0 |= (phydev->duplex == DUPLEX_FULL ? 0x8000 : 0); | ||
974 | iowrite16(lp->mcr0, ioaddr); | ||
975 | |||
976 | status_changed = 1; | ||
977 | lp->old_duplex = phydev->duplex; | ||
978 | } | ||
979 | |||
980 | if (status_changed) { | ||
981 | pr_info("%s: link %s", dev->name, phydev->link ? | ||
982 | "UP" : "DOWN"); | ||
983 | if (phydev->link) | ||
984 | pr_cont(" - %d/%s", phydev->speed, | ||
985 | DUPLEX_FULL == phydev->duplex ? "full" : "half"); | ||
986 | pr_cont("\n"); | ||
987 | } | ||
988 | } | ||
989 | |||
990 | static int r6040_mii_probe(struct net_device *dev) | ||
991 | { | ||
992 | struct r6040_private *lp = netdev_priv(dev); | ||
993 | struct phy_device *phydev = NULL; | ||
994 | |||
995 | phydev = phy_find_first(lp->mii_bus); | ||
996 | if (!phydev) { | ||
997 | dev_err(&lp->pdev->dev, "no PHY found\n"); | ||
998 | return -ENODEV; | ||
999 | } | ||
1000 | |||
1001 | phydev = phy_connect(dev, dev_name(&phydev->dev), &r6040_adjust_link, | ||
1002 | 0, PHY_INTERFACE_MODE_MII); | ||
1003 | |||
1004 | if (IS_ERR(phydev)) { | ||
1005 | dev_err(&lp->pdev->dev, "could not attach to PHY\n"); | ||
1006 | return PTR_ERR(phydev); | ||
1007 | } | ||
1008 | |||
1009 | /* mask with MAC supported features */ | ||
1010 | phydev->supported &= (SUPPORTED_10baseT_Half | ||
1011 | | SUPPORTED_10baseT_Full | ||
1012 | | SUPPORTED_100baseT_Half | ||
1013 | | SUPPORTED_100baseT_Full | ||
1014 | | SUPPORTED_Autoneg | ||
1015 | | SUPPORTED_MII | ||
1016 | | SUPPORTED_TP); | ||
1017 | |||
1018 | phydev->advertising = phydev->supported; | ||
1019 | lp->phydev = phydev; | ||
1020 | lp->old_link = 0; | ||
1021 | lp->old_duplex = -1; | ||
1022 | |||
1023 | dev_info(&lp->pdev->dev, "attached PHY driver [%s] " | ||
1024 | "(mii_bus:phy_addr=%s)\n", | ||
1025 | phydev->drv->name, dev_name(&phydev->dev)); | ||
1026 | |||
1027 | return 0; | ||
1028 | } | ||
1029 | |||
1070 | static int __devinit r6040_init_one(struct pci_dev *pdev, | 1030 | static int __devinit r6040_init_one(struct pci_dev *pdev, |
1071 | const struct pci_device_id *ent) | 1031 | const struct pci_device_id *ent) |
1072 | { | 1032 | { |
@@ -1077,6 +1037,7 @@ static int __devinit r6040_init_one(struct pci_dev *pdev, | |||
1077 | static int card_idx = -1; | 1037 | static int card_idx = -1; |
1078 | int bar = 0; | 1038 | int bar = 0; |
1079 | u16 *adrp; | 1039 | u16 *adrp; |
1040 | int i; | ||
1080 | 1041 | ||
1081 | printk("%s\n", version); | 1042 | printk("%s\n", version); |
1082 | 1043 | ||
@@ -1163,7 +1124,6 @@ static int __devinit r6040_init_one(struct pci_dev *pdev, | |||
1163 | /* Init RDC private data */ | 1124 | /* Init RDC private data */ |
1164 | lp->mcr0 = 0x1002; | 1125 | lp->mcr0 = 0x1002; |
1165 | lp->phy_addr = phy_table[card_idx]; | 1126 | lp->phy_addr = phy_table[card_idx]; |
1166 | lp->switch_sig = 0; | ||
1167 | 1127 | ||
1168 | /* The RDC-specific entries in the device structure. */ | 1128 | /* The RDC-specific entries in the device structure. */ |
1169 | dev->netdev_ops = &r6040_netdev_ops; | 1129 | dev->netdev_ops = &r6040_netdev_ops; |
@@ -1171,28 +1131,54 @@ static int __devinit r6040_init_one(struct pci_dev *pdev, | |||
1171 | dev->watchdog_timeo = TX_TIMEOUT; | 1131 | dev->watchdog_timeo = TX_TIMEOUT; |
1172 | 1132 | ||
1173 | netif_napi_add(dev, &lp->napi, r6040_poll, 64); | 1133 | netif_napi_add(dev, &lp->napi, r6040_poll, 64); |
1174 | lp->mii_if.dev = dev; | 1134 | |
1175 | lp->mii_if.mdio_read = r6040_mdio_read; | 1135 | lp->mii_bus = mdiobus_alloc(); |
1176 | lp->mii_if.mdio_write = r6040_mdio_write; | 1136 | if (!lp->mii_bus) { |
1177 | lp->mii_if.phy_id = lp->phy_addr; | 1137 | dev_err(&pdev->dev, "mdiobus_alloc() failed\n"); |
1178 | lp->mii_if.phy_id_mask = 0x1f; | ||
1179 | lp->mii_if.reg_num_mask = 0x1f; | ||
1180 | |||
1181 | /* Check the vendor ID on the PHY, if 0xffff assume none attached */ | ||
1182 | if (r6040_phy_read(ioaddr, lp->phy_addr, 2) == 0xffff) { | ||
1183 | dev_err(&pdev->dev, "Failed to detect an attached PHY\n"); | ||
1184 | err = -ENODEV; | ||
1185 | goto err_out_unmap; | 1138 | goto err_out_unmap; |
1186 | } | 1139 | } |
1187 | 1140 | ||
1141 | lp->mii_bus->priv = dev; | ||
1142 | lp->mii_bus->read = r6040_mdiobus_read; | ||
1143 | lp->mii_bus->write = r6040_mdiobus_write; | ||
1144 | lp->mii_bus->reset = r6040_mdiobus_reset; | ||
1145 | lp->mii_bus->name = "r6040_eth_mii"; | ||
1146 | snprintf(lp->mii_bus->id, MII_BUS_ID_SIZE, "%x", card_idx); | ||
1147 | lp->mii_bus->irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL); | ||
1148 | if (!lp->mii_bus->irq) { | ||
1149 | dev_err(&pdev->dev, "mii_bus irq allocation failed\n"); | ||
1150 | goto err_out_mdio; | ||
1151 | } | ||
1152 | |||
1153 | for (i = 0; i < PHY_MAX_ADDR; i++) | ||
1154 | lp->mii_bus->irq[i] = PHY_POLL; | ||
1155 | |||
1156 | err = mdiobus_register(lp->mii_bus); | ||
1157 | if (err) { | ||
1158 | dev_err(&pdev->dev, "failed to register MII bus\n"); | ||
1159 | goto err_out_mdio_irq; | ||
1160 | } | ||
1161 | |||
1162 | err = r6040_mii_probe(dev); | ||
1163 | if (err) { | ||
1164 | dev_err(&pdev->dev, "failed to probe MII bus\n"); | ||
1165 | goto err_out_mdio_unregister; | ||
1166 | } | ||
1167 | |||
1188 | /* Register net device. After this dev->name assign */ | 1168 | /* Register net device. After this dev->name assign */ |
1189 | err = register_netdev(dev); | 1169 | err = register_netdev(dev); |
1190 | if (err) { | 1170 | if (err) { |
1191 | dev_err(&pdev->dev, "Failed to register net device\n"); | 1171 | dev_err(&pdev->dev, "Failed to register net device\n"); |
1192 | goto err_out_unmap; | 1172 | goto err_out_mdio_unregister; |
1193 | } | 1173 | } |
1194 | return 0; | 1174 | return 0; |
1195 | 1175 | ||
1176 | err_out_mdio_unregister: | ||
1177 | mdiobus_unregister(lp->mii_bus); | ||
1178 | err_out_mdio_irq: | ||
1179 | kfree(lp->mii_bus->irq); | ||
1180 | err_out_mdio: | ||
1181 | mdiobus_free(lp->mii_bus); | ||
1196 | err_out_unmap: | 1182 | err_out_unmap: |
1197 | pci_iounmap(pdev, ioaddr); | 1183 | pci_iounmap(pdev, ioaddr); |
1198 | err_out_free_res: | 1184 | err_out_free_res: |
@@ -1206,8 +1192,12 @@ err_out: | |||
1206 | static void __devexit r6040_remove_one(struct pci_dev *pdev) | 1192 | static void __devexit r6040_remove_one(struct pci_dev *pdev) |
1207 | { | 1193 | { |
1208 | struct net_device *dev = pci_get_drvdata(pdev); | 1194 | struct net_device *dev = pci_get_drvdata(pdev); |
1195 | struct r6040_private *lp = netdev_priv(dev); | ||
1209 | 1196 | ||
1210 | unregister_netdev(dev); | 1197 | unregister_netdev(dev); |
1198 | mdiobus_unregister(lp->mii_bus); | ||
1199 | kfree(lp->mii_bus->irq); | ||
1200 | mdiobus_free(lp->mii_bus); | ||
1211 | pci_release_regions(pdev); | 1201 | pci_release_regions(pdev); |
1212 | free_netdev(dev); | 1202 | free_netdev(dev); |
1213 | pci_disable_device(pdev); | 1203 | pci_disable_device(pdev); |