diff options
Diffstat (limited to 'drivers/net/ethernet/davicom/dm9000.c')
-rw-r--r-- | drivers/net/ethernet/davicom/dm9000.c | 66 |
1 files changed, 40 insertions, 26 deletions
diff --git a/drivers/net/ethernet/davicom/dm9000.c b/drivers/net/ethernet/davicom/dm9000.c index 8c4b93be333b..13723c96d1a2 100644 --- a/drivers/net/ethernet/davicom/dm9000.c +++ b/drivers/net/ethernet/davicom/dm9000.c | |||
@@ -109,6 +109,7 @@ typedef struct board_info { | |||
109 | u8 imr_all; | 109 | u8 imr_all; |
110 | 110 | ||
111 | unsigned int flags; | 111 | unsigned int flags; |
112 | unsigned int in_timeout:1; | ||
112 | unsigned int in_suspend:1; | 113 | unsigned int in_suspend:1; |
113 | unsigned int wake_supported:1; | 114 | unsigned int wake_supported:1; |
114 | 115 | ||
@@ -187,13 +188,13 @@ dm9000_reset(board_info_t *db) | |||
187 | * The essential point is that we have to do a double reset, and the | 188 | * The essential point is that we have to do a double reset, and the |
188 | * instruction is to set LBK into MAC internal loopback mode. | 189 | * instruction is to set LBK into MAC internal loopback mode. |
189 | */ | 190 | */ |
190 | iow(db, DM9000_NCR, 0x03); | 191 | iow(db, DM9000_NCR, NCR_RST | NCR_MAC_LBK); |
191 | udelay(100); /* Application note says at least 20 us */ | 192 | udelay(100); /* Application note says at least 20 us */ |
192 | if (ior(db, DM9000_NCR) & 1) | 193 | if (ior(db, DM9000_NCR) & 1) |
193 | dev_err(db->dev, "dm9000 did not respond to first reset\n"); | 194 | dev_err(db->dev, "dm9000 did not respond to first reset\n"); |
194 | 195 | ||
195 | iow(db, DM9000_NCR, 0); | 196 | iow(db, DM9000_NCR, 0); |
196 | iow(db, DM9000_NCR, 0x03); | 197 | iow(db, DM9000_NCR, NCR_RST | NCR_MAC_LBK); |
197 | udelay(100); | 198 | udelay(100); |
198 | if (ior(db, DM9000_NCR) & 1) | 199 | if (ior(db, DM9000_NCR) & 1) |
199 | dev_err(db->dev, "dm9000 did not respond to second reset\n"); | 200 | dev_err(db->dev, "dm9000 did not respond to second reset\n"); |
@@ -273,7 +274,7 @@ static void dm9000_dumpblk_32bit(void __iomem *reg, int count) | |||
273 | */ | 274 | */ |
274 | static void dm9000_msleep(board_info_t *db, unsigned int ms) | 275 | static void dm9000_msleep(board_info_t *db, unsigned int ms) |
275 | { | 276 | { |
276 | if (db->in_suspend) | 277 | if (db->in_suspend || db->in_timeout) |
277 | mdelay(ms); | 278 | mdelay(ms); |
278 | else | 279 | else |
279 | msleep(ms); | 280 | msleep(ms); |
@@ -334,7 +335,8 @@ dm9000_phy_write(struct net_device *dev, | |||
334 | unsigned long reg_save; | 335 | unsigned long reg_save; |
335 | 336 | ||
336 | dm9000_dbg(db, 5, "phy_write[%02x] = %04x\n", reg, value); | 337 | dm9000_dbg(db, 5, "phy_write[%02x] = %04x\n", reg, value); |
337 | mutex_lock(&db->addr_lock); | 338 | if (!db->in_timeout) |
339 | mutex_lock(&db->addr_lock); | ||
338 | 340 | ||
339 | spin_lock_irqsave(&db->lock, flags); | 341 | spin_lock_irqsave(&db->lock, flags); |
340 | 342 | ||
@@ -365,7 +367,8 @@ dm9000_phy_write(struct net_device *dev, | |||
365 | writeb(reg_save, db->io_addr); | 367 | writeb(reg_save, db->io_addr); |
366 | 368 | ||
367 | spin_unlock_irqrestore(&db->lock, flags); | 369 | spin_unlock_irqrestore(&db->lock, flags); |
368 | mutex_unlock(&db->addr_lock); | 370 | if (!db->in_timeout) |
371 | mutex_unlock(&db->addr_lock); | ||
369 | } | 372 | } |
370 | 373 | ||
371 | /* dm9000_set_io | 374 | /* dm9000_set_io |
@@ -882,6 +885,18 @@ dm9000_hash_table(struct net_device *dev) | |||
882 | spin_unlock_irqrestore(&db->lock, flags); | 885 | spin_unlock_irqrestore(&db->lock, flags); |
883 | } | 886 | } |
884 | 887 | ||
888 | static void | ||
889 | dm9000_mask_interrupts(board_info_t *db) | ||
890 | { | ||
891 | iow(db, DM9000_IMR, IMR_PAR); | ||
892 | } | ||
893 | |||
894 | static void | ||
895 | dm9000_unmask_interrupts(board_info_t *db) | ||
896 | { | ||
897 | iow(db, DM9000_IMR, db->imr_all); | ||
898 | } | ||
899 | |||
885 | /* | 900 | /* |
886 | * Initialize dm9000 board | 901 | * Initialize dm9000 board |
887 | */ | 902 | */ |
@@ -894,6 +909,9 @@ dm9000_init_dm9000(struct net_device *dev) | |||
894 | 909 | ||
895 | dm9000_dbg(db, 1, "entering %s\n", __func__); | 910 | dm9000_dbg(db, 1, "entering %s\n", __func__); |
896 | 911 | ||
912 | dm9000_reset(db); | ||
913 | dm9000_mask_interrupts(db); | ||
914 | |||
897 | /* I/O mode */ | 915 | /* I/O mode */ |
898 | db->io_mode = ior(db, DM9000_ISR) >> 6; /* ISR bit7:6 keeps I/O mode */ | 916 | db->io_mode = ior(db, DM9000_ISR) >> 6; /* ISR bit7:6 keeps I/O mode */ |
899 | 917 | ||
@@ -941,9 +959,6 @@ dm9000_init_dm9000(struct net_device *dev) | |||
941 | 959 | ||
942 | db->imr_all = imr; | 960 | db->imr_all = imr; |
943 | 961 | ||
944 | /* Enable TX/RX interrupt mask */ | ||
945 | iow(db, DM9000_IMR, imr); | ||
946 | |||
947 | /* Init Driver variable */ | 962 | /* Init Driver variable */ |
948 | db->tx_pkt_cnt = 0; | 963 | db->tx_pkt_cnt = 0; |
949 | db->queue_pkt_len = 0; | 964 | db->queue_pkt_len = 0; |
@@ -959,17 +974,19 @@ static void dm9000_timeout(struct net_device *dev) | |||
959 | 974 | ||
960 | /* Save previous register address */ | 975 | /* Save previous register address */ |
961 | spin_lock_irqsave(&db->lock, flags); | 976 | spin_lock_irqsave(&db->lock, flags); |
977 | db->in_timeout = 1; | ||
962 | reg_save = readb(db->io_addr); | 978 | reg_save = readb(db->io_addr); |
963 | 979 | ||
964 | netif_stop_queue(dev); | 980 | netif_stop_queue(dev); |
965 | dm9000_reset(db); | ||
966 | dm9000_init_dm9000(dev); | 981 | dm9000_init_dm9000(dev); |
982 | dm9000_unmask_interrupts(db); | ||
967 | /* We can accept TX packets again */ | 983 | /* We can accept TX packets again */ |
968 | dev->trans_start = jiffies; /* prevent tx timeout */ | 984 | dev->trans_start = jiffies; /* prevent tx timeout */ |
969 | netif_wake_queue(dev); | 985 | netif_wake_queue(dev); |
970 | 986 | ||
971 | /* Restore previous register address */ | 987 | /* Restore previous register address */ |
972 | writeb(reg_save, db->io_addr); | 988 | writeb(reg_save, db->io_addr); |
989 | db->in_timeout = 0; | ||
973 | spin_unlock_irqrestore(&db->lock, flags); | 990 | spin_unlock_irqrestore(&db->lock, flags); |
974 | } | 991 | } |
975 | 992 | ||
@@ -1093,7 +1110,6 @@ dm9000_rx(struct net_device *dev) | |||
1093 | if (rxbyte & DM9000_PKT_ERR) { | 1110 | if (rxbyte & DM9000_PKT_ERR) { |
1094 | dev_warn(db->dev, "status check fail: %d\n", rxbyte); | 1111 | dev_warn(db->dev, "status check fail: %d\n", rxbyte); |
1095 | iow(db, DM9000_RCR, 0x00); /* Stop Device */ | 1112 | iow(db, DM9000_RCR, 0x00); /* Stop Device */ |
1096 | iow(db, DM9000_ISR, IMR_PAR); /* Stop INT request */ | ||
1097 | return; | 1113 | return; |
1098 | } | 1114 | } |
1099 | 1115 | ||
@@ -1193,9 +1209,7 @@ static irqreturn_t dm9000_interrupt(int irq, void *dev_id) | |||
1193 | /* Save previous register address */ | 1209 | /* Save previous register address */ |
1194 | reg_save = readb(db->io_addr); | 1210 | reg_save = readb(db->io_addr); |
1195 | 1211 | ||
1196 | /* Disable all interrupts */ | 1212 | dm9000_mask_interrupts(db); |
1197 | iow(db, DM9000_IMR, IMR_PAR); | ||
1198 | |||
1199 | /* Got DM9000 interrupt status */ | 1213 | /* Got DM9000 interrupt status */ |
1200 | int_status = ior(db, DM9000_ISR); /* Got ISR */ | 1214 | int_status = ior(db, DM9000_ISR); /* Got ISR */ |
1201 | iow(db, DM9000_ISR, int_status); /* Clear ISR status */ | 1215 | iow(db, DM9000_ISR, int_status); /* Clear ISR status */ |
@@ -1218,9 +1232,7 @@ static irqreturn_t dm9000_interrupt(int irq, void *dev_id) | |||
1218 | } | 1232 | } |
1219 | } | 1233 | } |
1220 | 1234 | ||
1221 | /* Re-enable interrupt mask */ | 1235 | dm9000_unmask_interrupts(db); |
1222 | iow(db, DM9000_IMR, db->imr_all); | ||
1223 | |||
1224 | /* Restore previous register address */ | 1236 | /* Restore previous register address */ |
1225 | writeb(reg_save, db->io_addr); | 1237 | writeb(reg_save, db->io_addr); |
1226 | 1238 | ||
@@ -1292,6 +1304,9 @@ dm9000_open(struct net_device *dev) | |||
1292 | * may work, and tell the user that this is a problem */ | 1304 | * may work, and tell the user that this is a problem */ |
1293 | 1305 | ||
1294 | if (irqflags == IRQF_TRIGGER_NONE) | 1306 | if (irqflags == IRQF_TRIGGER_NONE) |
1307 | irqflags = irq_get_trigger_type(dev->irq); | ||
1308 | |||
1309 | if (irqflags == IRQF_TRIGGER_NONE) | ||
1295 | dev_warn(db->dev, "WARNING: no IRQ resource flags set.\n"); | 1310 | dev_warn(db->dev, "WARNING: no IRQ resource flags set.\n"); |
1296 | 1311 | ||
1297 | irqflags |= IRQF_SHARED; | 1312 | irqflags |= IRQF_SHARED; |
@@ -1301,11 +1316,14 @@ dm9000_open(struct net_device *dev) | |||
1301 | mdelay(1); /* delay needs by DM9000B */ | 1316 | mdelay(1); /* delay needs by DM9000B */ |
1302 | 1317 | ||
1303 | /* Initialize DM9000 board */ | 1318 | /* Initialize DM9000 board */ |
1304 | dm9000_reset(db); | ||
1305 | dm9000_init_dm9000(dev); | 1319 | dm9000_init_dm9000(dev); |
1306 | 1320 | ||
1307 | if (request_irq(dev->irq, dm9000_interrupt, irqflags, dev->name, dev)) | 1321 | if (request_irq(dev->irq, dm9000_interrupt, irqflags, dev->name, dev)) |
1308 | return -EAGAIN; | 1322 | return -EAGAIN; |
1323 | /* Now that we have an interrupt handler hooked up we can unmask | ||
1324 | * our interrupts | ||
1325 | */ | ||
1326 | dm9000_unmask_interrupts(db); | ||
1309 | 1327 | ||
1310 | /* Init driver variable */ | 1328 | /* Init driver variable */ |
1311 | db->dbug_cnt = 0; | 1329 | db->dbug_cnt = 0; |
@@ -1313,7 +1331,8 @@ dm9000_open(struct net_device *dev) | |||
1313 | mii_check_media(&db->mii, netif_msg_link(db), 1); | 1331 | mii_check_media(&db->mii, netif_msg_link(db), 1); |
1314 | netif_start_queue(dev); | 1332 | netif_start_queue(dev); |
1315 | 1333 | ||
1316 | dm9000_schedule_poll(db); | 1334 | /* Poll initial link status */ |
1335 | schedule_delayed_work(&db->phy_poll, 1); | ||
1317 | 1336 | ||
1318 | return 0; | 1337 | return 0; |
1319 | } | 1338 | } |
@@ -1326,7 +1345,7 @@ dm9000_shutdown(struct net_device *dev) | |||
1326 | /* RESET device */ | 1345 | /* RESET device */ |
1327 | dm9000_phy_write(dev, 0, MII_BMCR, BMCR_RESET); /* PHY RESET */ | 1346 | dm9000_phy_write(dev, 0, MII_BMCR, BMCR_RESET); /* PHY RESET */ |
1328 | iow(db, DM9000_GPR, 0x01); /* Power-Down PHY */ | 1347 | iow(db, DM9000_GPR, 0x01); /* Power-Down PHY */ |
1329 | iow(db, DM9000_IMR, IMR_PAR); /* Disable all interrupt */ | 1348 | dm9000_mask_interrupts(db); |
1330 | iow(db, DM9000_RCR, 0x00); /* Disable RX */ | 1349 | iow(db, DM9000_RCR, 0x00); /* Disable RX */ |
1331 | } | 1350 | } |
1332 | 1351 | ||
@@ -1547,12 +1566,7 @@ dm9000_probe(struct platform_device *pdev) | |||
1547 | db->flags |= DM9000_PLATF_SIMPLE_PHY; | 1566 | db->flags |= DM9000_PLATF_SIMPLE_PHY; |
1548 | #endif | 1567 | #endif |
1549 | 1568 | ||
1550 | /* Fixing bug on dm9000_probe, takeover dm9000_reset(db), | 1569 | dm9000_reset(db); |
1551 | * Need 'NCR_MAC_LBK' bit to indeed stable our DM9000 fifo | ||
1552 | * while probe stage. | ||
1553 | */ | ||
1554 | |||
1555 | iow(db, DM9000_NCR, NCR_MAC_LBK | NCR_RST); | ||
1556 | 1570 | ||
1557 | /* try multiple times, DM9000 sometimes gets the read wrong */ | 1571 | /* try multiple times, DM9000 sometimes gets the read wrong */ |
1558 | for (i = 0; i < 8; i++) { | 1572 | for (i = 0; i < 8; i++) { |
@@ -1695,8 +1709,8 @@ dm9000_drv_resume(struct device *dev) | |||
1695 | /* reset if we were not in wake mode to ensure if | 1709 | /* reset if we were not in wake mode to ensure if |
1696 | * the device was powered off it is in a known state */ | 1710 | * the device was powered off it is in a known state */ |
1697 | if (!db->wake_state) { | 1711 | if (!db->wake_state) { |
1698 | dm9000_reset(db); | ||
1699 | dm9000_init_dm9000(ndev); | 1712 | dm9000_init_dm9000(ndev); |
1713 | dm9000_unmask_interrupts(db); | ||
1700 | } | 1714 | } |
1701 | 1715 | ||
1702 | netif_device_attach(ndev); | 1716 | netif_device_attach(ndev); |