diff options
author | Dmitry Torokhov <dtor_core@ameritech.net> | 2005-10-30 18:00:14 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-10-30 20:37:17 -0500 |
commit | e812cb5226af32aec91bcbaa8365bd7f921b6ebb (patch) | |
tree | adb7ccb2a766f92dcb354dd20834ce3c023c04b9 /drivers/net/irda/smsc-ircc2.c | |
parent | 17fd47ab4d33e764216b87006d8118fa050b4c92 (diff) |
[PATCH] smsc-ircc2: PM cleanup - do not close device when suspending
smsc-ircc2 - avoid closing network device when suspending; just release
interrupt and disable DMA ourselves. Also make sure to reset chip when
resuming.
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Cc: Jean Tourrilhes <jt@bougret.hpl.hp.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/net/irda/smsc-ircc2.c')
-rw-r--r-- | drivers/net/irda/smsc-ircc2.c | 129 |
1 files changed, 85 insertions, 44 deletions
diff --git a/drivers/net/irda/smsc-ircc2.c b/drivers/net/irda/smsc-ircc2.c index bbac720cca63..140b7cdb1f7e 100644 --- a/drivers/net/irda/smsc-ircc2.c +++ b/drivers/net/irda/smsc-ircc2.c | |||
@@ -638,21 +638,14 @@ static void smsc_ircc_setup_qos(struct smsc_ircc_cb *self) | |||
638 | */ | 638 | */ |
639 | static void smsc_ircc_init_chip(struct smsc_ircc_cb *self) | 639 | static void smsc_ircc_init_chip(struct smsc_ircc_cb *self) |
640 | { | 640 | { |
641 | int iobase, ir_mode, ctrl, fast; | 641 | int iobase = self->io.fir_base; |
642 | |||
643 | IRDA_ASSERT(self != NULL, return;); | ||
644 | |||
645 | iobase = self->io.fir_base; | ||
646 | ir_mode = IRCC_CFGA_IRDA_SIR_A; | ||
647 | ctrl = 0; | ||
648 | fast = 0; | ||
649 | 642 | ||
650 | register_bank(iobase, 0); | 643 | register_bank(iobase, 0); |
651 | outb(IRCC_MASTER_RESET, iobase + IRCC_MASTER); | 644 | outb(IRCC_MASTER_RESET, iobase + IRCC_MASTER); |
652 | outb(0x00, iobase + IRCC_MASTER); | 645 | outb(0x00, iobase + IRCC_MASTER); |
653 | 646 | ||
654 | register_bank(iobase, 1); | 647 | register_bank(iobase, 1); |
655 | outb(((inb(iobase + IRCC_SCE_CFGA) & 0x87) | ir_mode), | 648 | outb(((inb(iobase + IRCC_SCE_CFGA) & 0x87) | IRCC_CFGA_IRDA_SIR_A), |
656 | iobase + IRCC_SCE_CFGA); | 649 | iobase + IRCC_SCE_CFGA); |
657 | 650 | ||
658 | #ifdef smsc_669 /* Uses pin 88/89 for Rx/Tx */ | 651 | #ifdef smsc_669 /* Uses pin 88/89 for Rx/Tx */ |
@@ -666,10 +659,10 @@ static void smsc_ircc_init_chip(struct smsc_ircc_cb *self) | |||
666 | outb(SMSC_IRCC2_FIFO_THRESHOLD, iobase + IRCC_FIFO_THRESHOLD); | 659 | outb(SMSC_IRCC2_FIFO_THRESHOLD, iobase + IRCC_FIFO_THRESHOLD); |
667 | 660 | ||
668 | register_bank(iobase, 4); | 661 | register_bank(iobase, 4); |
669 | outb((inb(iobase + IRCC_CONTROL) & 0x30) | ctrl, iobase + IRCC_CONTROL); | 662 | outb((inb(iobase + IRCC_CONTROL) & 0x30), iobase + IRCC_CONTROL); |
670 | 663 | ||
671 | register_bank(iobase, 0); | 664 | register_bank(iobase, 0); |
672 | outb(fast, iobase + IRCC_LCR_A); | 665 | outb(0, iobase + IRCC_LCR_A); |
673 | 666 | ||
674 | smsc_ircc_set_sir_speed(self, SMSC_IRCC2_C_IRDA_FALLBACK_SPEED); | 667 | smsc_ircc_set_sir_speed(self, SMSC_IRCC2_C_IRDA_FALLBACK_SPEED); |
675 | 668 | ||
@@ -1556,6 +1549,46 @@ static int ircc_is_receiving(struct smsc_ircc_cb *self) | |||
1556 | } | 1549 | } |
1557 | #endif /* unused */ | 1550 | #endif /* unused */ |
1558 | 1551 | ||
1552 | static int smsc_ircc_request_irq(struct smsc_ircc_cb *self) | ||
1553 | { | ||
1554 | int error; | ||
1555 | |||
1556 | error = request_irq(self->io.irq, smsc_ircc_interrupt, 0, | ||
1557 | self->netdev->name, self->netdev); | ||
1558 | if (error) | ||
1559 | IRDA_DEBUG(0, "%s(), unable to allocate irq=%d, err=%d\n", | ||
1560 | __FUNCTION__, self->io.irq, error); | ||
1561 | |||
1562 | return error; | ||
1563 | } | ||
1564 | |||
1565 | static void smsc_ircc_start_interrupts(struct smsc_ircc_cb *self) | ||
1566 | { | ||
1567 | unsigned long flags; | ||
1568 | |||
1569 | spin_lock_irqsave(&self->lock, flags); | ||
1570 | |||
1571 | self->io.speed = 0; | ||
1572 | smsc_ircc_change_speed(self, SMSC_IRCC2_C_IRDA_FALLBACK_SPEED); | ||
1573 | |||
1574 | spin_unlock_irqrestore(&self->lock, flags); | ||
1575 | } | ||
1576 | |||
1577 | static void smsc_ircc_stop_interrupts(struct smsc_ircc_cb *self) | ||
1578 | { | ||
1579 | int iobase = self->io.fir_base; | ||
1580 | unsigned long flags; | ||
1581 | |||
1582 | spin_lock_irqsave(&self->lock, flags); | ||
1583 | |||
1584 | register_bank(iobase, 0); | ||
1585 | outb(0, iobase + IRCC_IER); | ||
1586 | outb(IRCC_MASTER_RESET, iobase + IRCC_MASTER); | ||
1587 | outb(0x00, iobase + IRCC_MASTER); | ||
1588 | |||
1589 | spin_unlock_irqrestore(&self->lock, flags); | ||
1590 | } | ||
1591 | |||
1559 | 1592 | ||
1560 | /* | 1593 | /* |
1561 | * Function smsc_ircc_net_open (dev) | 1594 | * Function smsc_ircc_net_open (dev) |
@@ -1567,7 +1600,6 @@ static int smsc_ircc_net_open(struct net_device *dev) | |||
1567 | { | 1600 | { |
1568 | struct smsc_ircc_cb *self; | 1601 | struct smsc_ircc_cb *self; |
1569 | char hwname[16]; | 1602 | char hwname[16]; |
1570 | unsigned long flags; | ||
1571 | 1603 | ||
1572 | IRDA_DEBUG(1, "%s\n", __FUNCTION__); | 1604 | IRDA_DEBUG(1, "%s\n", __FUNCTION__); |
1573 | 1605 | ||
@@ -1575,6 +1607,11 @@ static int smsc_ircc_net_open(struct net_device *dev) | |||
1575 | self = netdev_priv(dev); | 1607 | self = netdev_priv(dev); |
1576 | IRDA_ASSERT(self != NULL, return 0;); | 1608 | IRDA_ASSERT(self != NULL, return 0;); |
1577 | 1609 | ||
1610 | if (self->io.suspended) { | ||
1611 | IRDA_DEBUG(0, "%s(), device is suspended\n", __FUNCTION__); | ||
1612 | return -EAGAIN; | ||
1613 | } | ||
1614 | |||
1578 | if (request_irq(self->io.irq, smsc_ircc_interrupt, 0, dev->name, | 1615 | if (request_irq(self->io.irq, smsc_ircc_interrupt, 0, dev->name, |
1579 | (void *) dev)) { | 1616 | (void *) dev)) { |
1580 | IRDA_DEBUG(0, "%s(), unable to allocate irq=%d\n", | 1617 | IRDA_DEBUG(0, "%s(), unable to allocate irq=%d\n", |
@@ -1582,11 +1619,7 @@ static int smsc_ircc_net_open(struct net_device *dev) | |||
1582 | return -EAGAIN; | 1619 | return -EAGAIN; |
1583 | } | 1620 | } |
1584 | 1621 | ||
1585 | spin_lock_irqsave(&self->lock, flags); | 1622 | smsc_ircc_start_interrupts(self); |
1586 | /*smsc_ircc_sir_start(self);*/ | ||
1587 | self->io.speed = 0; | ||
1588 | smsc_ircc_change_speed(self, SMSC_IRCC2_C_IRDA_FALLBACK_SPEED); | ||
1589 | spin_unlock_irqrestore(&self->lock, flags); | ||
1590 | 1623 | ||
1591 | /* Give self a hardware name */ | 1624 | /* Give self a hardware name */ |
1592 | /* It would be cool to offer the chip revision here - Jean II */ | 1625 | /* It would be cool to offer the chip revision here - Jean II */ |
@@ -1639,7 +1672,12 @@ static int smsc_ircc_net_close(struct net_device *dev) | |||
1639 | irlap_close(self->irlap); | 1672 | irlap_close(self->irlap); |
1640 | self->irlap = NULL; | 1673 | self->irlap = NULL; |
1641 | 1674 | ||
1642 | free_irq(self->io.irq, dev); | 1675 | smsc_ircc_stop_interrupts(self); |
1676 | |||
1677 | /* if we are called from smsc_ircc_resume we don't have IRQ reserved */ | ||
1678 | if (!self->io.suspended) | ||
1679 | free_irq(self->io.irq, dev); | ||
1680 | |||
1643 | disable_dma(self->io.dma); | 1681 | disable_dma(self->io.dma); |
1644 | free_dma(self->io.dma); | 1682 | free_dma(self->io.dma); |
1645 | 1683 | ||
@@ -1650,11 +1688,18 @@ static int smsc_ircc_suspend(struct device *dev, pm_message_t state) | |||
1650 | { | 1688 | { |
1651 | struct smsc_ircc_cb *self = dev_get_drvdata(dev); | 1689 | struct smsc_ircc_cb *self = dev_get_drvdata(dev); |
1652 | 1690 | ||
1653 | IRDA_MESSAGE("%s, Suspending\n", driver_name); | ||
1654 | |||
1655 | if (!self->io.suspended) { | 1691 | if (!self->io.suspended) { |
1656 | smsc_ircc_net_close(self->netdev); | 1692 | IRDA_DEBUG(1, "%s, Suspending\n", driver_name); |
1693 | |||
1694 | rtnl_lock(); | ||
1695 | if (netif_running(self->netdev)) { | ||
1696 | netif_device_detach(self->netdev); | ||
1697 | smsc_ircc_stop_interrupts(self); | ||
1698 | free_irq(self->io.irq, self->netdev); | ||
1699 | disable_dma(self->io.dma); | ||
1700 | } | ||
1657 | self->io.suspended = 1; | 1701 | self->io.suspended = 1; |
1702 | rtnl_unlock(); | ||
1658 | } | 1703 | } |
1659 | 1704 | ||
1660 | return 0; | 1705 | return 0; |
@@ -1665,11 +1710,25 @@ static int smsc_ircc_resume(struct device *dev) | |||
1665 | struct smsc_ircc_cb *self = dev_get_drvdata(dev); | 1710 | struct smsc_ircc_cb *self = dev_get_drvdata(dev); |
1666 | 1711 | ||
1667 | if (self->io.suspended) { | 1712 | if (self->io.suspended) { |
1668 | 1713 | IRDA_DEBUG(1, "%s, Waking up\n", driver_name); | |
1669 | smsc_ircc_net_open(self->netdev); | 1714 | |
1715 | rtnl_lock(); | ||
1716 | smsc_ircc_init_chip(self); | ||
1717 | if (netif_running(self->netdev)) { | ||
1718 | if (smsc_ircc_request_irq(self)) { | ||
1719 | /* | ||
1720 | * Don't fail resume process, just kill this | ||
1721 | * network interface | ||
1722 | */ | ||
1723 | unregister_netdevice(self->netdev); | ||
1724 | } else { | ||
1725 | enable_dma(self->io.dma); | ||
1726 | smsc_ircc_start_interrupts(self); | ||
1727 | netif_device_attach(self->netdev); | ||
1728 | } | ||
1729 | } | ||
1670 | self->io.suspended = 0; | 1730 | self->io.suspended = 0; |
1671 | 1731 | rtnl_unlock(); | |
1672 | IRDA_MESSAGE("%s, Waking up\n", driver_name); | ||
1673 | } | 1732 | } |
1674 | return 0; | 1733 | return 0; |
1675 | } | 1734 | } |
@@ -1682,9 +1741,6 @@ static int smsc_ircc_resume(struct device *dev) | |||
1682 | */ | 1741 | */ |
1683 | static int __exit smsc_ircc_close(struct smsc_ircc_cb *self) | 1742 | static int __exit smsc_ircc_close(struct smsc_ircc_cb *self) |
1684 | { | 1743 | { |
1685 | int iobase; | ||
1686 | unsigned long flags; | ||
1687 | |||
1688 | IRDA_DEBUG(1, "%s\n", __FUNCTION__); | 1744 | IRDA_DEBUG(1, "%s\n", __FUNCTION__); |
1689 | 1745 | ||
1690 | IRDA_ASSERT(self != NULL, return -1;); | 1746 | IRDA_ASSERT(self != NULL, return -1;); |
@@ -1694,22 +1750,7 @@ static int __exit smsc_ircc_close(struct smsc_ircc_cb *self) | |||
1694 | /* Remove netdevice */ | 1750 | /* Remove netdevice */ |
1695 | unregister_netdev(self->netdev); | 1751 | unregister_netdev(self->netdev); |
1696 | 1752 | ||
1697 | /* Make sure the irq handler is not exectuting */ | 1753 | smsc_ircc_stop_interrupts(self); |
1698 | spin_lock_irqsave(&self->lock, flags); | ||
1699 | |||
1700 | /* Stop interrupts */ | ||
1701 | iobase = self->io.fir_base; | ||
1702 | register_bank(iobase, 0); | ||
1703 | outb(0, iobase + IRCC_IER); | ||
1704 | outb(IRCC_MASTER_RESET, iobase + IRCC_MASTER); | ||
1705 | outb(0x00, iobase + IRCC_MASTER); | ||
1706 | #if 0 | ||
1707 | /* Reset to SIR mode */ | ||
1708 | register_bank(iobase, 1); | ||
1709 | outb(IRCC_CFGA_IRDA_SIR_A|IRCC_CFGA_TX_POLARITY, iobase + IRCC_SCE_CFGA); | ||
1710 | outb(IRCC_CFGB_IR, iobase + IRCC_SCE_CFGB); | ||
1711 | #endif | ||
1712 | spin_unlock_irqrestore(&self->lock, flags); | ||
1713 | 1754 | ||
1714 | /* Release the PORTS that this driver is using */ | 1755 | /* Release the PORTS that this driver is using */ |
1715 | IRDA_DEBUG(0, "%s(), releasing 0x%03x\n", __FUNCTION__, | 1756 | IRDA_DEBUG(0, "%s(), releasing 0x%03x\n", __FUNCTION__, |