diff options
Diffstat (limited to 'drivers')
253 files changed, 12908 insertions, 9502 deletions
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 27c8d56111c2..29e71bddd6ff 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c | |||
@@ -679,24 +679,20 @@ static void ahci_save_initial_config(struct pci_dev *pdev, | |||
679 | 679 | ||
680 | /* cross check port_map and cap.n_ports */ | 680 | /* cross check port_map and cap.n_ports */ |
681 | if (port_map) { | 681 | if (port_map) { |
682 | u32 tmp_port_map = port_map; | 682 | int map_ports = 0; |
683 | int n_ports = ahci_nr_ports(cap); | ||
684 | 683 | ||
685 | for (i = 0; i < AHCI_MAX_PORTS && n_ports; i++) { | 684 | for (i = 0; i < AHCI_MAX_PORTS; i++) |
686 | if (tmp_port_map & (1 << i)) { | 685 | if (port_map & (1 << i)) |
687 | n_ports--; | 686 | map_ports++; |
688 | tmp_port_map &= ~(1 << i); | ||
689 | } | ||
690 | } | ||
691 | 687 | ||
692 | /* If n_ports and port_map are inconsistent, whine and | 688 | /* If PI has more ports than n_ports, whine, clear |
693 | * clear port_map and let it be generated from n_ports. | 689 | * port_map and let it be generated from n_ports. |
694 | */ | 690 | */ |
695 | if (n_ports || tmp_port_map) { | 691 | if (map_ports > ahci_nr_ports(cap)) { |
696 | dev_printk(KERN_WARNING, &pdev->dev, | 692 | dev_printk(KERN_WARNING, &pdev->dev, |
697 | "nr_ports (%u) and implemented port map " | 693 | "implemented port map (0x%x) contains more " |
698 | "(0x%x) don't match, using nr_ports\n", | 694 | "ports than nr_ports (%u), using nr_ports\n", |
699 | ahci_nr_ports(cap), port_map); | 695 | port_map, ahci_nr_ports(cap)); |
700 | port_map = 0; | 696 | port_map = 0; |
701 | } | 697 | } |
702 | } | 698 | } |
@@ -2201,7 +2197,7 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
2201 | struct device *dev = &pdev->dev; | 2197 | struct device *dev = &pdev->dev; |
2202 | struct ahci_host_priv *hpriv; | 2198 | struct ahci_host_priv *hpriv; |
2203 | struct ata_host *host; | 2199 | struct ata_host *host; |
2204 | int i, rc; | 2200 | int n_ports, i, rc; |
2205 | 2201 | ||
2206 | VPRINTK("ENTER\n"); | 2202 | VPRINTK("ENTER\n"); |
2207 | 2203 | ||
@@ -2255,7 +2251,14 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
2255 | if (hpriv->cap & HOST_CAP_PMP) | 2251 | if (hpriv->cap & HOST_CAP_PMP) |
2256 | pi.flags |= ATA_FLAG_PMP; | 2252 | pi.flags |= ATA_FLAG_PMP; |
2257 | 2253 | ||
2258 | host = ata_host_alloc_pinfo(&pdev->dev, ppi, fls(hpriv->port_map)); | 2254 | /* CAP.NP sometimes indicate the index of the last enabled |
2255 | * port, at other times, that of the last possible port, so | ||
2256 | * determining the maximum port number requires looking at | ||
2257 | * both CAP.NP and port_map. | ||
2258 | */ | ||
2259 | n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map)); | ||
2260 | |||
2261 | host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports); | ||
2259 | if (!host) | 2262 | if (!host) |
2260 | return -ENOMEM; | 2263 | return -ENOMEM; |
2261 | host->iomap = pcim_iomap_table(pdev); | 2264 | host->iomap = pcim_iomap_table(pdev); |
diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index 4b99ed0c59bb..9c2515f67de5 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c | |||
@@ -1603,7 +1603,8 @@ static void piix_iocfg_bit18_quirk(struct pci_dev *pdev) | |||
1603 | * Zero on success, or -ERRNO value. | 1603 | * Zero on success, or -ERRNO value. |
1604 | */ | 1604 | */ |
1605 | 1605 | ||
1606 | static int piix_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | 1606 | static int __devinit piix_init_one(struct pci_dev *pdev, |
1607 | const struct pci_device_id *ent) | ||
1607 | { | 1608 | { |
1608 | static int printed_version; | 1609 | static int printed_version; |
1609 | struct device *dev = &pdev->dev; | 1610 | struct device *dev = &pdev->dev; |
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 361cf50cbdea..3011919f3ec8 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c | |||
@@ -4154,8 +4154,6 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { | |||
4154 | /* NCQ is broken */ | 4154 | /* NCQ is broken */ |
4155 | { "Maxtor *", "BANC*", ATA_HORKAGE_NONCQ }, | 4155 | { "Maxtor *", "BANC*", ATA_HORKAGE_NONCQ }, |
4156 | { "Maxtor 7V300F0", "VA111630", ATA_HORKAGE_NONCQ }, | 4156 | { "Maxtor 7V300F0", "VA111630", ATA_HORKAGE_NONCQ }, |
4157 | { "HITACHI HDS7250SASUN500G*", NULL, ATA_HORKAGE_NONCQ }, | ||
4158 | { "HITACHI HDS7225SBSUN250G*", NULL, ATA_HORKAGE_NONCQ }, | ||
4159 | { "ST380817AS", "3.42", ATA_HORKAGE_NONCQ }, | 4157 | { "ST380817AS", "3.42", ATA_HORKAGE_NONCQ }, |
4160 | { "ST3160023AS", "3.42", ATA_HORKAGE_NONCQ }, | 4158 | { "ST3160023AS", "3.42", ATA_HORKAGE_NONCQ }, |
4161 | 4159 | ||
diff --git a/drivers/ata/pata_of_platform.c b/drivers/ata/pata_of_platform.c index 938f48a807eb..408da30594c4 100644 --- a/drivers/ata/pata_of_platform.c +++ b/drivers/ata/pata_of_platform.c | |||
@@ -12,7 +12,7 @@ | |||
12 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/of_platform.h> | 14 | #include <linux/of_platform.h> |
15 | #include <linux/pata_platform.h> | 15 | #include <linux/ata_platform.h> |
16 | 16 | ||
17 | static int __devinit pata_of_platform_probe(struct of_device *ofdev, | 17 | static int __devinit pata_of_platform_probe(struct of_device *ofdev, |
18 | const struct of_device_id *match) | 18 | const struct of_device_id *match) |
diff --git a/drivers/ata/pata_platform.c b/drivers/ata/pata_platform.c index 224bb6c2030a..aad7adc6ea56 100644 --- a/drivers/ata/pata_platform.c +++ b/drivers/ata/pata_platform.c | |||
@@ -19,7 +19,7 @@ | |||
19 | #include <linux/ata.h> | 19 | #include <linux/ata.h> |
20 | #include <linux/libata.h> | 20 | #include <linux/libata.h> |
21 | #include <linux/platform_device.h> | 21 | #include <linux/platform_device.h> |
22 | #include <linux/pata_platform.h> | 22 | #include <linux/ata_platform.h> |
23 | 23 | ||
24 | #define DRV_NAME "pata_platform" | 24 | #define DRV_NAME "pata_platform" |
25 | #define DRV_VERSION "1.2" | 25 | #define DRV_VERSION "1.2" |
diff --git a/drivers/ata/sata_fsl.c b/drivers/ata/sata_fsl.c index 922d7b2efba8..efcb66b6ccef 100644 --- a/drivers/ata/sata_fsl.c +++ b/drivers/ata/sata_fsl.c | |||
@@ -355,8 +355,8 @@ static unsigned int sata_fsl_fill_sg(struct ata_queued_cmd *qc, void *cmd_desc, | |||
355 | ata_port_printk(qc->ap, KERN_ERR, | 355 | ata_port_printk(qc->ap, KERN_ERR, |
356 | "s/g len unaligned : 0x%x\n", sg_len); | 356 | "s/g len unaligned : 0x%x\n", sg_len); |
357 | 357 | ||
358 | if ((num_prde == (SATA_FSL_MAX_PRD_DIRECT - 1)) && | 358 | if (num_prde == (SATA_FSL_MAX_PRD_DIRECT - 1) && |
359 | (qc->n_iter + 1 != qc->n_elem)) { | 359 | sg_next(sg) != NULL) { |
360 | VPRINTK("setting indirect prde\n"); | 360 | VPRINTK("setting indirect prde\n"); |
361 | prd_ptr_to_indirect_ext = prd; | 361 | prd_ptr_to_indirect_ext = prd; |
362 | prd->dba = cpu_to_le32(indirect_ext_segment_paddr); | 362 | prd->dba = cpu_to_le32(indirect_ext_segment_paddr); |
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index 3c1b5c9027db..080b8362f8d6 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c | |||
@@ -69,8 +69,11 @@ | |||
69 | #include <linux/blkdev.h> | 69 | #include <linux/blkdev.h> |
70 | #include <linux/delay.h> | 70 | #include <linux/delay.h> |
71 | #include <linux/interrupt.h> | 71 | #include <linux/interrupt.h> |
72 | #include <linux/dmapool.h> | ||
72 | #include <linux/dma-mapping.h> | 73 | #include <linux/dma-mapping.h> |
73 | #include <linux/device.h> | 74 | #include <linux/device.h> |
75 | #include <linux/platform_device.h> | ||
76 | #include <linux/ata_platform.h> | ||
74 | #include <scsi/scsi_host.h> | 77 | #include <scsi/scsi_host.h> |
75 | #include <scsi/scsi_cmnd.h> | 78 | #include <scsi/scsi_cmnd.h> |
76 | #include <scsi/scsi_device.h> | 79 | #include <scsi/scsi_device.h> |
@@ -179,6 +182,8 @@ enum { | |||
179 | 182 | ||
180 | HC_MAIN_IRQ_CAUSE_OFS = 0x1d60, | 183 | HC_MAIN_IRQ_CAUSE_OFS = 0x1d60, |
181 | HC_MAIN_IRQ_MASK_OFS = 0x1d64, | 184 | HC_MAIN_IRQ_MASK_OFS = 0x1d64, |
185 | HC_SOC_MAIN_IRQ_CAUSE_OFS = 0x20020, | ||
186 | HC_SOC_MAIN_IRQ_MASK_OFS = 0x20024, | ||
182 | PORT0_ERR = (1 << 0), /* shift by port # */ | 187 | PORT0_ERR = (1 << 0), /* shift by port # */ |
183 | PORT0_DONE = (1 << 1), /* shift by port # */ | 188 | PORT0_DONE = (1 << 1), /* shift by port # */ |
184 | HC0_IRQ_PEND = 0x1ff, /* bits 0-8 = HC0's ports */ | 189 | HC0_IRQ_PEND = 0x1ff, /* bits 0-8 = HC0's ports */ |
@@ -194,11 +199,13 @@ enum { | |||
194 | TWSI_INT = (1 << 24), | 199 | TWSI_INT = (1 << 24), |
195 | HC_MAIN_RSVD = (0x7f << 25), /* bits 31-25 */ | 200 | HC_MAIN_RSVD = (0x7f << 25), /* bits 31-25 */ |
196 | HC_MAIN_RSVD_5 = (0x1fff << 19), /* bits 31-19 */ | 201 | HC_MAIN_RSVD_5 = (0x1fff << 19), /* bits 31-19 */ |
202 | HC_MAIN_RSVD_SOC = (0x3fffffb << 6), /* bits 31-9, 7-6 */ | ||
197 | HC_MAIN_MASKED_IRQS = (TRAN_LO_DONE | TRAN_HI_DONE | | 203 | HC_MAIN_MASKED_IRQS = (TRAN_LO_DONE | TRAN_HI_DONE | |
198 | PORTS_0_7_COAL_DONE | GPIO_INT | TWSI_INT | | 204 | PORTS_0_7_COAL_DONE | GPIO_INT | TWSI_INT | |
199 | HC_MAIN_RSVD), | 205 | HC_MAIN_RSVD), |
200 | HC_MAIN_MASKED_IRQS_5 = (PORTS_0_3_COAL_DONE | PORTS_4_7_COAL_DONE | | 206 | HC_MAIN_MASKED_IRQS_5 = (PORTS_0_3_COAL_DONE | PORTS_4_7_COAL_DONE | |
201 | HC_MAIN_RSVD_5), | 207 | HC_MAIN_RSVD_5), |
208 | HC_MAIN_MASKED_IRQS_SOC = (PORTS_0_3_COAL_DONE | HC_MAIN_RSVD_SOC), | ||
202 | 209 | ||
203 | /* SATAHC registers */ | 210 | /* SATAHC registers */ |
204 | HC_CFG_OFS = 0, | 211 | HC_CFG_OFS = 0, |
@@ -368,6 +375,7 @@ enum chip_type { | |||
368 | chip_608x, | 375 | chip_608x, |
369 | chip_6042, | 376 | chip_6042, |
370 | chip_7042, | 377 | chip_7042, |
378 | chip_soc, | ||
371 | }; | 379 | }; |
372 | 380 | ||
373 | /* Command ReQuest Block: 32B */ | 381 | /* Command ReQuest Block: 32B */ |
@@ -424,6 +432,10 @@ struct mv_host_priv { | |||
424 | u32 hp_flags; | 432 | u32 hp_flags; |
425 | struct mv_port_signal signal[8]; | 433 | struct mv_port_signal signal[8]; |
426 | const struct mv_hw_ops *ops; | 434 | const struct mv_hw_ops *ops; |
435 | int n_ports; | ||
436 | void __iomem *base; | ||
437 | void __iomem *main_cause_reg_addr; | ||
438 | void __iomem *main_mask_reg_addr; | ||
427 | u32 irq_cause_ofs; | 439 | u32 irq_cause_ofs; |
428 | u32 irq_mask_ofs; | 440 | u32 irq_mask_ofs; |
429 | u32 unmask_all_irqs; | 441 | u32 unmask_all_irqs; |
@@ -482,6 +494,15 @@ static void mv6_read_preamp(struct mv_host_priv *hpriv, int idx, | |||
482 | static int mv6_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio, | 494 | static int mv6_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio, |
483 | unsigned int n_hc); | 495 | unsigned int n_hc); |
484 | static void mv6_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio); | 496 | static void mv6_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio); |
497 | static void mv_soc_enable_leds(struct mv_host_priv *hpriv, | ||
498 | void __iomem *mmio); | ||
499 | static void mv_soc_read_preamp(struct mv_host_priv *hpriv, int idx, | ||
500 | void __iomem *mmio); | ||
501 | static int mv_soc_reset_hc(struct mv_host_priv *hpriv, | ||
502 | void __iomem *mmio, unsigned int n_hc); | ||
503 | static void mv_soc_reset_flash(struct mv_host_priv *hpriv, | ||
504 | void __iomem *mmio); | ||
505 | static void mv_soc_reset_bus(struct ata_host *host, void __iomem *mmio); | ||
485 | static void mv_reset_pci_bus(struct ata_host *host, void __iomem *mmio); | 506 | static void mv_reset_pci_bus(struct ata_host *host, void __iomem *mmio); |
486 | static void mv_channel_reset(struct mv_host_priv *hpriv, void __iomem *mmio, | 507 | static void mv_channel_reset(struct mv_host_priv *hpriv, void __iomem *mmio, |
487 | unsigned int port_no); | 508 | unsigned int port_no); |
@@ -661,6 +682,12 @@ static const struct ata_port_info mv_port_info[] = { | |||
661 | .udma_mask = ATA_UDMA6, | 682 | .udma_mask = ATA_UDMA6, |
662 | .port_ops = &mv_iie_ops, | 683 | .port_ops = &mv_iie_ops, |
663 | }, | 684 | }, |
685 | { /* chip_soc */ | ||
686 | .flags = MV_COMMON_FLAGS | MV_FLAG_SOC, | ||
687 | .pio_mask = 0x1f, /* pio0-4 */ | ||
688 | .udma_mask = ATA_UDMA6, | ||
689 | .port_ops = &mv_iie_ops, | ||
690 | }, | ||
664 | }; | 691 | }; |
665 | 692 | ||
666 | static const struct pci_device_id mv_pci_tbl[] = { | 693 | static const struct pci_device_id mv_pci_tbl[] = { |
@@ -711,6 +738,15 @@ static const struct mv_hw_ops mv6xxx_ops = { | |||
711 | .reset_bus = mv_reset_pci_bus, | 738 | .reset_bus = mv_reset_pci_bus, |
712 | }; | 739 | }; |
713 | 740 | ||
741 | static const struct mv_hw_ops mv_soc_ops = { | ||
742 | .phy_errata = mv6_phy_errata, | ||
743 | .enable_leds = mv_soc_enable_leds, | ||
744 | .read_preamp = mv_soc_read_preamp, | ||
745 | .reset_hc = mv_soc_reset_hc, | ||
746 | .reset_flash = mv_soc_reset_flash, | ||
747 | .reset_bus = mv_soc_reset_bus, | ||
748 | }; | ||
749 | |||
714 | /* | 750 | /* |
715 | * Functions | 751 | * Functions |
716 | */ | 752 | */ |
@@ -749,9 +785,15 @@ static inline void __iomem *mv_port_base(void __iomem *base, unsigned int port) | |||
749 | (mv_hardport_from_port(port) * MV_PORT_REG_SZ); | 785 | (mv_hardport_from_port(port) * MV_PORT_REG_SZ); |
750 | } | 786 | } |
751 | 787 | ||
788 | static inline void __iomem *mv_host_base(struct ata_host *host) | ||
789 | { | ||
790 | struct mv_host_priv *hpriv = host->private_data; | ||
791 | return hpriv->base; | ||
792 | } | ||
793 | |||
752 | static inline void __iomem *mv_ap_base(struct ata_port *ap) | 794 | static inline void __iomem *mv_ap_base(struct ata_port *ap) |
753 | { | 795 | { |
754 | return mv_port_base(ap->host->iomap[MV_PRIMARY_BAR], ap->port_no); | 796 | return mv_port_base(mv_host_base(ap->host), ap->port_no); |
755 | } | 797 | } |
756 | 798 | ||
757 | static inline int mv_get_hc_count(unsigned long port_flags) | 799 | static inline int mv_get_hc_count(unsigned long port_flags) |
@@ -1649,16 +1691,21 @@ static void mv_intr_edma(struct ata_port *ap) | |||
1649 | */ | 1691 | */ |
1650 | static void mv_host_intr(struct ata_host *host, u32 relevant, unsigned int hc) | 1692 | static void mv_host_intr(struct ata_host *host, u32 relevant, unsigned int hc) |
1651 | { | 1693 | { |
1652 | void __iomem *mmio = host->iomap[MV_PRIMARY_BAR]; | 1694 | struct mv_host_priv *hpriv = host->private_data; |
1695 | void __iomem *mmio = hpriv->base; | ||
1653 | void __iomem *hc_mmio = mv_hc_base(mmio, hc); | 1696 | void __iomem *hc_mmio = mv_hc_base(mmio, hc); |
1654 | u32 hc_irq_cause; | 1697 | u32 hc_irq_cause; |
1655 | int port, port0; | 1698 | int port, port0, last_port; |
1656 | 1699 | ||
1657 | if (hc == 0) | 1700 | if (hc == 0) |
1658 | port0 = 0; | 1701 | port0 = 0; |
1659 | else | 1702 | else |
1660 | port0 = MV_PORTS_PER_HC; | 1703 | port0 = MV_PORTS_PER_HC; |
1661 | 1704 | ||
1705 | if (HAS_PCI(host)) | ||
1706 | last_port = port0 + MV_PORTS_PER_HC; | ||
1707 | else | ||
1708 | last_port = port0 + hpriv->n_ports; | ||
1662 | /* we'll need the HC success int register in most cases */ | 1709 | /* we'll need the HC success int register in most cases */ |
1663 | hc_irq_cause = readl(hc_mmio + HC_IRQ_CAUSE_OFS); | 1710 | hc_irq_cause = readl(hc_mmio + HC_IRQ_CAUSE_OFS); |
1664 | if (!hc_irq_cause) | 1711 | if (!hc_irq_cause) |
@@ -1669,7 +1716,7 @@ static void mv_host_intr(struct ata_host *host, u32 relevant, unsigned int hc) | |||
1669 | VPRINTK("ENTER, hc%u relevant=0x%08x HC IRQ cause=0x%08x\n", | 1716 | VPRINTK("ENTER, hc%u relevant=0x%08x HC IRQ cause=0x%08x\n", |
1670 | hc, relevant, hc_irq_cause); | 1717 | hc, relevant, hc_irq_cause); |
1671 | 1718 | ||
1672 | for (port = port0; port < port0 + MV_PORTS_PER_HC; port++) { | 1719 | for (port = port0; port < port0 + last_port; port++) { |
1673 | struct ata_port *ap = host->ports[port]; | 1720 | struct ata_port *ap = host->ports[port]; |
1674 | struct mv_port_priv *pp = ap->private_data; | 1721 | struct mv_port_priv *pp = ap->private_data; |
1675 | int have_err_bits, hard_port, shift; | 1722 | int have_err_bits, hard_port, shift; |
@@ -1764,13 +1811,15 @@ static void mv_pci_error(struct ata_host *host, void __iomem *mmio) | |||
1764 | static irqreturn_t mv_interrupt(int irq, void *dev_instance) | 1811 | static irqreturn_t mv_interrupt(int irq, void *dev_instance) |
1765 | { | 1812 | { |
1766 | struct ata_host *host = dev_instance; | 1813 | struct ata_host *host = dev_instance; |
1814 | struct mv_host_priv *hpriv = host->private_data; | ||
1767 | unsigned int hc, handled = 0, n_hcs; | 1815 | unsigned int hc, handled = 0, n_hcs; |
1768 | void __iomem *mmio = host->iomap[MV_PRIMARY_BAR]; | 1816 | void __iomem *mmio = hpriv->base; |
1769 | u32 irq_stat, irq_mask; | 1817 | u32 irq_stat, irq_mask; |
1770 | 1818 | ||
1771 | spin_lock(&host->lock); | 1819 | spin_lock(&host->lock); |
1772 | irq_stat = readl(mmio + HC_MAIN_IRQ_CAUSE_OFS); | 1820 | |
1773 | irq_mask = readl(mmio + HC_MAIN_IRQ_MASK_OFS); | 1821 | irq_stat = readl(hpriv->main_cause_reg_addr); |
1822 | irq_mask = readl(hpriv->main_mask_reg_addr); | ||
1774 | 1823 | ||
1775 | /* check the cases where we either have nothing pending or have read | 1824 | /* check the cases where we either have nothing pending or have read |
1776 | * a bogus register value which can indicate HW removal or PCI fault | 1825 | * a bogus register value which can indicate HW removal or PCI fault |
@@ -1827,7 +1876,8 @@ static unsigned int mv5_scr_offset(unsigned int sc_reg_in) | |||
1827 | 1876 | ||
1828 | static int mv5_scr_read(struct ata_port *ap, unsigned int sc_reg_in, u32 *val) | 1877 | static int mv5_scr_read(struct ata_port *ap, unsigned int sc_reg_in, u32 *val) |
1829 | { | 1878 | { |
1830 | void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR]; | 1879 | struct mv_host_priv *hpriv = ap->host->private_data; |
1880 | void __iomem *mmio = hpriv->base; | ||
1831 | void __iomem *addr = mv5_phy_base(mmio, ap->port_no); | 1881 | void __iomem *addr = mv5_phy_base(mmio, ap->port_no); |
1832 | unsigned int ofs = mv5_scr_offset(sc_reg_in); | 1882 | unsigned int ofs = mv5_scr_offset(sc_reg_in); |
1833 | 1883 | ||
@@ -1840,7 +1890,8 @@ static int mv5_scr_read(struct ata_port *ap, unsigned int sc_reg_in, u32 *val) | |||
1840 | 1890 | ||
1841 | static int mv5_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val) | 1891 | static int mv5_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val) |
1842 | { | 1892 | { |
1843 | void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR]; | 1893 | struct mv_host_priv *hpriv = ap->host->private_data; |
1894 | void __iomem *mmio = hpriv->base; | ||
1844 | void __iomem *addr = mv5_phy_base(mmio, ap->port_no); | 1895 | void __iomem *addr = mv5_phy_base(mmio, ap->port_no); |
1845 | unsigned int ofs = mv5_scr_offset(sc_reg_in); | 1896 | unsigned int ofs = mv5_scr_offset(sc_reg_in); |
1846 | 1897 | ||
@@ -2178,6 +2229,93 @@ static void mv6_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio, | |||
2178 | writel(m2, port_mmio + PHY_MODE2); | 2229 | writel(m2, port_mmio + PHY_MODE2); |
2179 | } | 2230 | } |
2180 | 2231 | ||
2232 | /* TODO: use the generic LED interface to configure the SATA Presence */ | ||
2233 | /* & Acitivy LEDs on the board */ | ||
2234 | static void mv_soc_enable_leds(struct mv_host_priv *hpriv, | ||
2235 | void __iomem *mmio) | ||
2236 | { | ||
2237 | return; | ||
2238 | } | ||
2239 | |||
2240 | static void mv_soc_read_preamp(struct mv_host_priv *hpriv, int idx, | ||
2241 | void __iomem *mmio) | ||
2242 | { | ||
2243 | void __iomem *port_mmio; | ||
2244 | u32 tmp; | ||
2245 | |||
2246 | port_mmio = mv_port_base(mmio, idx); | ||
2247 | tmp = readl(port_mmio + PHY_MODE2); | ||
2248 | |||
2249 | hpriv->signal[idx].amps = tmp & 0x700; /* bits 10:8 */ | ||
2250 | hpriv->signal[idx].pre = tmp & 0xe0; /* bits 7:5 */ | ||
2251 | } | ||
2252 | |||
2253 | #undef ZERO | ||
2254 | #define ZERO(reg) writel(0, port_mmio + (reg)) | ||
2255 | static void mv_soc_reset_hc_port(struct mv_host_priv *hpriv, | ||
2256 | void __iomem *mmio, unsigned int port) | ||
2257 | { | ||
2258 | void __iomem *port_mmio = mv_port_base(mmio, port); | ||
2259 | |||
2260 | writelfl(EDMA_DS, port_mmio + EDMA_CMD_OFS); | ||
2261 | |||
2262 | mv_channel_reset(hpriv, mmio, port); | ||
2263 | |||
2264 | ZERO(0x028); /* command */ | ||
2265 | writel(0x101f, port_mmio + EDMA_CFG_OFS); | ||
2266 | ZERO(0x004); /* timer */ | ||
2267 | ZERO(0x008); /* irq err cause */ | ||
2268 | ZERO(0x00c); /* irq err mask */ | ||
2269 | ZERO(0x010); /* rq bah */ | ||
2270 | ZERO(0x014); /* rq inp */ | ||
2271 | ZERO(0x018); /* rq outp */ | ||
2272 | ZERO(0x01c); /* respq bah */ | ||
2273 | ZERO(0x024); /* respq outp */ | ||
2274 | ZERO(0x020); /* respq inp */ | ||
2275 | ZERO(0x02c); /* test control */ | ||
2276 | writel(0xbc, port_mmio + EDMA_IORDY_TMOUT); | ||
2277 | } | ||
2278 | |||
2279 | #undef ZERO | ||
2280 | |||
2281 | #define ZERO(reg) writel(0, hc_mmio + (reg)) | ||
2282 | static void mv_soc_reset_one_hc(struct mv_host_priv *hpriv, | ||
2283 | void __iomem *mmio) | ||
2284 | { | ||
2285 | void __iomem *hc_mmio = mv_hc_base(mmio, 0); | ||
2286 | |||
2287 | ZERO(0x00c); | ||
2288 | ZERO(0x010); | ||
2289 | ZERO(0x014); | ||
2290 | |||
2291 | } | ||
2292 | |||
2293 | #undef ZERO | ||
2294 | |||
2295 | static int mv_soc_reset_hc(struct mv_host_priv *hpriv, | ||
2296 | void __iomem *mmio, unsigned int n_hc) | ||
2297 | { | ||
2298 | unsigned int port; | ||
2299 | |||
2300 | for (port = 0; port < hpriv->n_ports; port++) | ||
2301 | mv_soc_reset_hc_port(hpriv, mmio, port); | ||
2302 | |||
2303 | mv_soc_reset_one_hc(hpriv, mmio); | ||
2304 | |||
2305 | return 0; | ||
2306 | } | ||
2307 | |||
2308 | static void mv_soc_reset_flash(struct mv_host_priv *hpriv, | ||
2309 | void __iomem *mmio) | ||
2310 | { | ||
2311 | return; | ||
2312 | } | ||
2313 | |||
2314 | static void mv_soc_reset_bus(struct ata_host *host, void __iomem *mmio) | ||
2315 | { | ||
2316 | return; | ||
2317 | } | ||
2318 | |||
2181 | static void mv_channel_reset(struct mv_host_priv *hpriv, void __iomem *mmio, | 2319 | static void mv_channel_reset(struct mv_host_priv *hpriv, void __iomem *mmio, |
2182 | unsigned int port_no) | 2320 | unsigned int port_no) |
2183 | { | 2321 | { |
@@ -2342,7 +2480,7 @@ static int mv_hardreset(struct ata_link *link, unsigned int *class, | |||
2342 | { | 2480 | { |
2343 | struct ata_port *ap = link->ap; | 2481 | struct ata_port *ap = link->ap; |
2344 | struct mv_host_priv *hpriv = ap->host->private_data; | 2482 | struct mv_host_priv *hpriv = ap->host->private_data; |
2345 | void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR]; | 2483 | void __iomem *mmio = hpriv->base; |
2346 | 2484 | ||
2347 | mv_stop_dma(ap); | 2485 | mv_stop_dma(ap); |
2348 | 2486 | ||
@@ -2383,7 +2521,7 @@ static void mv_error_handler(struct ata_port *ap) | |||
2383 | 2521 | ||
2384 | static void mv_eh_freeze(struct ata_port *ap) | 2522 | static void mv_eh_freeze(struct ata_port *ap) |
2385 | { | 2523 | { |
2386 | void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR]; | 2524 | struct mv_host_priv *hpriv = ap->host->private_data; |
2387 | unsigned int hc = (ap->port_no > 3) ? 1 : 0; | 2525 | unsigned int hc = (ap->port_no > 3) ? 1 : 0; |
2388 | u32 tmp, mask; | 2526 | u32 tmp, mask; |
2389 | unsigned int shift; | 2527 | unsigned int shift; |
@@ -2397,13 +2535,14 @@ static void mv_eh_freeze(struct ata_port *ap) | |||
2397 | mask = 0x3 << shift; | 2535 | mask = 0x3 << shift; |
2398 | 2536 | ||
2399 | /* disable assertion of portN err, done events */ | 2537 | /* disable assertion of portN err, done events */ |
2400 | tmp = readl(mmio + HC_MAIN_IRQ_MASK_OFS); | 2538 | tmp = readl(hpriv->main_mask_reg_addr); |
2401 | writelfl(tmp & ~mask, mmio + HC_MAIN_IRQ_MASK_OFS); | 2539 | writelfl(tmp & ~mask, hpriv->main_mask_reg_addr); |
2402 | } | 2540 | } |
2403 | 2541 | ||
2404 | static void mv_eh_thaw(struct ata_port *ap) | 2542 | static void mv_eh_thaw(struct ata_port *ap) |
2405 | { | 2543 | { |
2406 | void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR]; | 2544 | struct mv_host_priv *hpriv = ap->host->private_data; |
2545 | void __iomem *mmio = hpriv->base; | ||
2407 | unsigned int hc = (ap->port_no > 3) ? 1 : 0; | 2546 | unsigned int hc = (ap->port_no > 3) ? 1 : 0; |
2408 | void __iomem *hc_mmio = mv_hc_base(mmio, hc); | 2547 | void __iomem *hc_mmio = mv_hc_base(mmio, hc); |
2409 | void __iomem *port_mmio = mv_ap_base(ap); | 2548 | void __iomem *port_mmio = mv_ap_base(ap); |
@@ -2430,8 +2569,8 @@ static void mv_eh_thaw(struct ata_port *ap) | |||
2430 | writel(hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS); | 2569 | writel(hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS); |
2431 | 2570 | ||
2432 | /* enable assertion of portN err, done events */ | 2571 | /* enable assertion of portN err, done events */ |
2433 | tmp = readl(mmio + HC_MAIN_IRQ_MASK_OFS); | 2572 | tmp = readl(hpriv->main_mask_reg_addr); |
2434 | writelfl(tmp | mask, mmio + HC_MAIN_IRQ_MASK_OFS); | 2573 | writelfl(tmp | mask, hpriv->main_mask_reg_addr); |
2435 | } | 2574 | } |
2436 | 2575 | ||
2437 | /** | 2576 | /** |
@@ -2598,9 +2737,13 @@ static int mv_chip_id(struct ata_host *host, unsigned int board_idx) | |||
2598 | break; | 2737 | break; |
2599 | } | 2738 | } |
2600 | break; | 2739 | break; |
2740 | case chip_soc: | ||
2741 | hpriv->ops = &mv_soc_ops; | ||
2742 | hp_flags |= MV_HP_ERRATA_60X1C0; | ||
2743 | break; | ||
2601 | 2744 | ||
2602 | default: | 2745 | default: |
2603 | dev_printk(KERN_ERR, &pdev->dev, | 2746 | dev_printk(KERN_ERR, host->dev, |
2604 | "BUG: invalid board index %u\n", board_idx); | 2747 | "BUG: invalid board index %u\n", board_idx); |
2605 | return 1; | 2748 | return 1; |
2606 | } | 2749 | } |
@@ -2633,15 +2776,25 @@ static int mv_chip_id(struct ata_host *host, unsigned int board_idx) | |||
2633 | static int mv_init_host(struct ata_host *host, unsigned int board_idx) | 2776 | static int mv_init_host(struct ata_host *host, unsigned int board_idx) |
2634 | { | 2777 | { |
2635 | int rc = 0, n_hc, port, hc; | 2778 | int rc = 0, n_hc, port, hc; |
2636 | void __iomem *mmio = host->iomap[MV_PRIMARY_BAR]; | ||
2637 | struct mv_host_priv *hpriv = host->private_data; | 2779 | struct mv_host_priv *hpriv = host->private_data; |
2638 | 2780 | void __iomem *mmio = hpriv->base; | |
2639 | /* global interrupt mask */ | ||
2640 | writel(0, mmio + HC_MAIN_IRQ_MASK_OFS); | ||
2641 | 2781 | ||
2642 | rc = mv_chip_id(host, board_idx); | 2782 | rc = mv_chip_id(host, board_idx); |
2643 | if (rc) | 2783 | if (rc) |
2644 | goto done; | 2784 | goto done; |
2785 | |||
2786 | if (HAS_PCI(host)) { | ||
2787 | hpriv->main_cause_reg_addr = hpriv->base + | ||
2788 | HC_MAIN_IRQ_CAUSE_OFS; | ||
2789 | hpriv->main_mask_reg_addr = hpriv->base + HC_MAIN_IRQ_MASK_OFS; | ||
2790 | } else { | ||
2791 | hpriv->main_cause_reg_addr = hpriv->base + | ||
2792 | HC_SOC_MAIN_IRQ_CAUSE_OFS; | ||
2793 | hpriv->main_mask_reg_addr = hpriv->base + | ||
2794 | HC_SOC_MAIN_IRQ_MASK_OFS; | ||
2795 | } | ||
2796 | /* global interrupt mask */ | ||
2797 | writel(0, hpriv->main_mask_reg_addr); | ||
2645 | 2798 | ||
2646 | n_hc = mv_get_hc_count(host->ports[0]->flags); | 2799 | n_hc = mv_get_hc_count(host->ports[0]->flags); |
2647 | 2800 | ||
@@ -2672,13 +2825,15 @@ static int mv_init_host(struct ata_host *host, unsigned int board_idx) | |||
2672 | for (port = 0; port < host->n_ports; port++) { | 2825 | for (port = 0; port < host->n_ports; port++) { |
2673 | struct ata_port *ap = host->ports[port]; | 2826 | struct ata_port *ap = host->ports[port]; |
2674 | void __iomem *port_mmio = mv_port_base(mmio, port); | 2827 | void __iomem *port_mmio = mv_port_base(mmio, port); |
2675 | unsigned int offset = port_mmio - mmio; | ||
2676 | 2828 | ||
2677 | mv_port_init(&ap->ioaddr, port_mmio); | 2829 | mv_port_init(&ap->ioaddr, port_mmio); |
2678 | 2830 | ||
2679 | #ifdef CONFIG_PCI | 2831 | #ifdef CONFIG_PCI |
2680 | ata_port_pbar_desc(ap, MV_PRIMARY_BAR, -1, "mmio"); | 2832 | if (HAS_PCI(host)) { |
2681 | ata_port_pbar_desc(ap, MV_PRIMARY_BAR, offset, "port"); | 2833 | unsigned int offset = port_mmio - mmio; |
2834 | ata_port_pbar_desc(ap, MV_PRIMARY_BAR, -1, "mmio"); | ||
2835 | ata_port_pbar_desc(ap, MV_PRIMARY_BAR, offset, "port"); | ||
2836 | } | ||
2682 | #endif | 2837 | #endif |
2683 | } | 2838 | } |
2684 | 2839 | ||
@@ -2694,35 +2849,141 @@ static int mv_init_host(struct ata_host *host, unsigned int board_idx) | |||
2694 | writelfl(0, hc_mmio + HC_IRQ_CAUSE_OFS); | 2849 | writelfl(0, hc_mmio + HC_IRQ_CAUSE_OFS); |
2695 | } | 2850 | } |
2696 | 2851 | ||
2697 | /* Clear any currently outstanding host interrupt conditions */ | 2852 | if (HAS_PCI(host)) { |
2698 | writelfl(0, mmio + hpriv->irq_cause_ofs); | 2853 | /* Clear any currently outstanding host interrupt conditions */ |
2854 | writelfl(0, mmio + hpriv->irq_cause_ofs); | ||
2699 | 2855 | ||
2700 | /* and unmask interrupt generation for host regs */ | 2856 | /* and unmask interrupt generation for host regs */ |
2701 | writelfl(hpriv->unmask_all_irqs, mmio + hpriv->irq_mask_ofs); | 2857 | writelfl(hpriv->unmask_all_irqs, mmio + hpriv->irq_mask_ofs); |
2858 | if (IS_GEN_I(hpriv)) | ||
2859 | writelfl(~HC_MAIN_MASKED_IRQS_5, | ||
2860 | hpriv->main_mask_reg_addr); | ||
2861 | else | ||
2862 | writelfl(~HC_MAIN_MASKED_IRQS, | ||
2863 | hpriv->main_mask_reg_addr); | ||
2864 | |||
2865 | VPRINTK("HC MAIN IRQ cause/mask=0x%08x/0x%08x " | ||
2866 | "PCI int cause/mask=0x%08x/0x%08x\n", | ||
2867 | readl(hpriv->main_cause_reg_addr), | ||
2868 | readl(hpriv->main_mask_reg_addr), | ||
2869 | readl(mmio + hpriv->irq_cause_ofs), | ||
2870 | readl(mmio + hpriv->irq_mask_ofs)); | ||
2871 | } else { | ||
2872 | writelfl(~HC_MAIN_MASKED_IRQS_SOC, | ||
2873 | hpriv->main_mask_reg_addr); | ||
2874 | VPRINTK("HC MAIN IRQ cause/mask=0x%08x/0x%08x\n", | ||
2875 | readl(hpriv->main_cause_reg_addr), | ||
2876 | readl(hpriv->main_mask_reg_addr)); | ||
2877 | } | ||
2878 | done: | ||
2879 | return rc; | ||
2880 | } | ||
2702 | 2881 | ||
2703 | if (IS_GEN_I(hpriv)) | 2882 | /** |
2704 | writelfl(~HC_MAIN_MASKED_IRQS_5, mmio + HC_MAIN_IRQ_MASK_OFS); | 2883 | * mv_platform_probe - handle a positive probe of an soc Marvell |
2705 | else | 2884 | * host |
2706 | writelfl(~HC_MAIN_MASKED_IRQS, mmio + HC_MAIN_IRQ_MASK_OFS); | 2885 | * @pdev: platform device found |
2886 | * | ||
2887 | * LOCKING: | ||
2888 | * Inherited from caller. | ||
2889 | */ | ||
2890 | static int mv_platform_probe(struct platform_device *pdev) | ||
2891 | { | ||
2892 | static int printed_version; | ||
2893 | const struct mv_sata_platform_data *mv_platform_data; | ||
2894 | const struct ata_port_info *ppi[] = | ||
2895 | { &mv_port_info[chip_soc], NULL }; | ||
2896 | struct ata_host *host; | ||
2897 | struct mv_host_priv *hpriv; | ||
2898 | struct resource *res; | ||
2899 | int n_ports, rc; | ||
2707 | 2900 | ||
2708 | VPRINTK("HC MAIN IRQ cause/mask=0x%08x/0x%08x " | 2901 | if (!printed_version++) |
2709 | "PCI int cause/mask=0x%08x/0x%08x\n", | 2902 | dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n"); |
2710 | readl(mmio + HC_MAIN_IRQ_CAUSE_OFS), | ||
2711 | readl(mmio + HC_MAIN_IRQ_MASK_OFS), | ||
2712 | readl(mmio + hpriv->irq_cause_ofs), | ||
2713 | readl(mmio + hpriv->irq_mask_ofs)); | ||
2714 | 2903 | ||
2715 | done: | 2904 | /* |
2716 | return rc; | 2905 | * Simple resource validation .. |
2906 | */ | ||
2907 | if (unlikely(pdev->num_resources != 2)) { | ||
2908 | dev_err(&pdev->dev, "invalid number of resources\n"); | ||
2909 | return -EINVAL; | ||
2910 | } | ||
2911 | |||
2912 | /* | ||
2913 | * Get the register base first | ||
2914 | */ | ||
2915 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
2916 | if (res == NULL) | ||
2917 | return -EINVAL; | ||
2918 | |||
2919 | /* allocate host */ | ||
2920 | mv_platform_data = pdev->dev.platform_data; | ||
2921 | n_ports = mv_platform_data->n_ports; | ||
2922 | |||
2923 | host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports); | ||
2924 | hpriv = devm_kzalloc(&pdev->dev, sizeof(*hpriv), GFP_KERNEL); | ||
2925 | |||
2926 | if (!host || !hpriv) | ||
2927 | return -ENOMEM; | ||
2928 | host->private_data = hpriv; | ||
2929 | hpriv->n_ports = n_ports; | ||
2930 | |||
2931 | host->iomap = NULL; | ||
2932 | hpriv->base = ioremap(res->start, res->end - res->start + 1); | ||
2933 | hpriv->base -= MV_SATAHC0_REG_BASE; | ||
2934 | |||
2935 | /* initialize adapter */ | ||
2936 | rc = mv_init_host(host, chip_soc); | ||
2937 | if (rc) | ||
2938 | return rc; | ||
2939 | |||
2940 | dev_printk(KERN_INFO, &pdev->dev, | ||
2941 | "slots %u ports %d\n", (unsigned)MV_MAX_Q_DEPTH, | ||
2942 | host->n_ports); | ||
2943 | |||
2944 | return ata_host_activate(host, platform_get_irq(pdev, 0), mv_interrupt, | ||
2945 | IRQF_SHARED, &mv6_sht); | ||
2946 | } | ||
2947 | |||
2948 | /* | ||
2949 | * | ||
2950 | * mv_platform_remove - unplug a platform interface | ||
2951 | * @pdev: platform device | ||
2952 | * | ||
2953 | * A platform bus SATA device has been unplugged. Perform the needed | ||
2954 | * cleanup. Also called on module unload for any active devices. | ||
2955 | */ | ||
2956 | static int __devexit mv_platform_remove(struct platform_device *pdev) | ||
2957 | { | ||
2958 | struct device *dev = &pdev->dev; | ||
2959 | struct ata_host *host = dev_get_drvdata(dev); | ||
2960 | struct mv_host_priv *hpriv = host->private_data; | ||
2961 | void __iomem *base = hpriv->base; | ||
2962 | |||
2963 | ata_host_detach(host); | ||
2964 | iounmap(base); | ||
2965 | return 0; | ||
2717 | } | 2966 | } |
2718 | 2967 | ||
2968 | static struct platform_driver mv_platform_driver = { | ||
2969 | .probe = mv_platform_probe, | ||
2970 | .remove = __devexit_p(mv_platform_remove), | ||
2971 | .driver = { | ||
2972 | .name = DRV_NAME, | ||
2973 | .owner = THIS_MODULE, | ||
2974 | }, | ||
2975 | }; | ||
2976 | |||
2977 | |||
2719 | #ifdef CONFIG_PCI | 2978 | #ifdef CONFIG_PCI |
2720 | static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); | 2979 | static int mv_pci_init_one(struct pci_dev *pdev, |
2980 | const struct pci_device_id *ent); | ||
2981 | |||
2721 | 2982 | ||
2722 | static struct pci_driver mv_pci_driver = { | 2983 | static struct pci_driver mv_pci_driver = { |
2723 | .name = DRV_NAME, | 2984 | .name = DRV_NAME, |
2724 | .id_table = mv_pci_tbl, | 2985 | .id_table = mv_pci_tbl, |
2725 | .probe = mv_init_one, | 2986 | .probe = mv_pci_init_one, |
2726 | .remove = ata_pci_remove_one, | 2987 | .remove = ata_pci_remove_one, |
2727 | }; | 2988 | }; |
2728 | 2989 | ||
@@ -2828,14 +3089,15 @@ static int mv_create_dma_pools(struct mv_host_priv *hpriv, struct device *dev) | |||
2828 | } | 3089 | } |
2829 | 3090 | ||
2830 | /** | 3091 | /** |
2831 | * mv_init_one - handle a positive probe of a Marvell host | 3092 | * mv_pci_init_one - handle a positive probe of a PCI Marvell host |
2832 | * @pdev: PCI device found | 3093 | * @pdev: PCI device found |
2833 | * @ent: PCI device ID entry for the matched host | 3094 | * @ent: PCI device ID entry for the matched host |
2834 | * | 3095 | * |
2835 | * LOCKING: | 3096 | * LOCKING: |
2836 | * Inherited from caller. | 3097 | * Inherited from caller. |
2837 | */ | 3098 | */ |
2838 | static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | 3099 | static int mv_pci_init_one(struct pci_dev *pdev, |
3100 | const struct pci_device_id *ent) | ||
2839 | { | 3101 | { |
2840 | static int printed_version; | 3102 | static int printed_version; |
2841 | unsigned int board_idx = (unsigned int)ent->driver_data; | 3103 | unsigned int board_idx = (unsigned int)ent->driver_data; |
@@ -2855,6 +3117,7 @@ static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
2855 | if (!host || !hpriv) | 3117 | if (!host || !hpriv) |
2856 | return -ENOMEM; | 3118 | return -ENOMEM; |
2857 | host->private_data = hpriv; | 3119 | host->private_data = hpriv; |
3120 | hpriv->n_ports = n_ports; | ||
2858 | 3121 | ||
2859 | /* acquire resources */ | 3122 | /* acquire resources */ |
2860 | rc = pcim_enable_device(pdev); | 3123 | rc = pcim_enable_device(pdev); |
@@ -2867,6 +3130,7 @@ static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
2867 | if (rc) | 3130 | if (rc) |
2868 | return rc; | 3131 | return rc; |
2869 | host->iomap = pcim_iomap_table(pdev); | 3132 | host->iomap = pcim_iomap_table(pdev); |
3133 | hpriv->base = host->iomap[MV_PRIMARY_BAR]; | ||
2870 | 3134 | ||
2871 | rc = pci_go_64(pdev); | 3135 | rc = pci_go_64(pdev); |
2872 | if (rc) | 3136 | if (rc) |
@@ -2895,11 +3159,22 @@ static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
2895 | } | 3159 | } |
2896 | #endif | 3160 | #endif |
2897 | 3161 | ||
3162 | static int mv_platform_probe(struct platform_device *pdev); | ||
3163 | static int __devexit mv_platform_remove(struct platform_device *pdev); | ||
3164 | |||
2898 | static int __init mv_init(void) | 3165 | static int __init mv_init(void) |
2899 | { | 3166 | { |
2900 | int rc = -ENODEV; | 3167 | int rc = -ENODEV; |
2901 | #ifdef CONFIG_PCI | 3168 | #ifdef CONFIG_PCI |
2902 | rc = pci_register_driver(&mv_pci_driver); | 3169 | rc = pci_register_driver(&mv_pci_driver); |
3170 | if (rc < 0) | ||
3171 | return rc; | ||
3172 | #endif | ||
3173 | rc = platform_driver_register(&mv_platform_driver); | ||
3174 | |||
3175 | #ifdef CONFIG_PCI | ||
3176 | if (rc < 0) | ||
3177 | pci_unregister_driver(&mv_pci_driver); | ||
2903 | #endif | 3178 | #endif |
2904 | return rc; | 3179 | return rc; |
2905 | } | 3180 | } |
@@ -2909,6 +3184,7 @@ static void __exit mv_exit(void) | |||
2909 | #ifdef CONFIG_PCI | 3184 | #ifdef CONFIG_PCI |
2910 | pci_unregister_driver(&mv_pci_driver); | 3185 | pci_unregister_driver(&mv_pci_driver); |
2911 | #endif | 3186 | #endif |
3187 | platform_driver_unregister(&mv_platform_driver); | ||
2912 | } | 3188 | } |
2913 | 3189 | ||
2914 | MODULE_AUTHOR("Brett Russ"); | 3190 | MODULE_AUTHOR("Brett Russ"); |
diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c index bfe92a43cf89..ed5473bf7a0a 100644 --- a/drivers/ata/sata_nv.c +++ b/drivers/ata/sata_nv.c | |||
@@ -247,6 +247,7 @@ struct nv_adma_port_priv { | |||
247 | void __iomem *ctl_block; | 247 | void __iomem *ctl_block; |
248 | void __iomem *gen_block; | 248 | void __iomem *gen_block; |
249 | void __iomem *notifier_clear_block; | 249 | void __iomem *notifier_clear_block; |
250 | u64 adma_dma_mask; | ||
250 | u8 flags; | 251 | u8 flags; |
251 | int last_issue_ncq; | 252 | int last_issue_ncq; |
252 | }; | 253 | }; |
@@ -715,9 +716,10 @@ static int nv_adma_slave_config(struct scsi_device *sdev) | |||
715 | { | 716 | { |
716 | struct ata_port *ap = ata_shost_to_port(sdev->host); | 717 | struct ata_port *ap = ata_shost_to_port(sdev->host); |
717 | struct nv_adma_port_priv *pp = ap->private_data; | 718 | struct nv_adma_port_priv *pp = ap->private_data; |
719 | struct nv_adma_port_priv *port0, *port1; | ||
720 | struct scsi_device *sdev0, *sdev1; | ||
718 | struct pci_dev *pdev = to_pci_dev(ap->host->dev); | 721 | struct pci_dev *pdev = to_pci_dev(ap->host->dev); |
719 | u64 bounce_limit; | 722 | unsigned long segment_boundary, flags; |
720 | unsigned long segment_boundary; | ||
721 | unsigned short sg_tablesize; | 723 | unsigned short sg_tablesize; |
722 | int rc; | 724 | int rc; |
723 | int adma_enable; | 725 | int adma_enable; |
@@ -729,6 +731,8 @@ static int nv_adma_slave_config(struct scsi_device *sdev) | |||
729 | /* Not a proper libata device, ignore */ | 731 | /* Not a proper libata device, ignore */ |
730 | return rc; | 732 | return rc; |
731 | 733 | ||
734 | spin_lock_irqsave(ap->lock, flags); | ||
735 | |||
732 | if (ap->link.device[sdev->id].class == ATA_DEV_ATAPI) { | 736 | if (ap->link.device[sdev->id].class == ATA_DEV_ATAPI) { |
733 | /* | 737 | /* |
734 | * NVIDIA reports that ADMA mode does not support ATAPI commands. | 738 | * NVIDIA reports that ADMA mode does not support ATAPI commands. |
@@ -737,7 +741,6 @@ static int nv_adma_slave_config(struct scsi_device *sdev) | |||
737 | * Restrict DMA parameters as required by the legacy interface | 741 | * Restrict DMA parameters as required by the legacy interface |
738 | * when an ATAPI device is connected. | 742 | * when an ATAPI device is connected. |
739 | */ | 743 | */ |
740 | bounce_limit = ATA_DMA_MASK; | ||
741 | segment_boundary = ATA_DMA_BOUNDARY; | 744 | segment_boundary = ATA_DMA_BOUNDARY; |
742 | /* Subtract 1 since an extra entry may be needed for padding, see | 745 | /* Subtract 1 since an extra entry may be needed for padding, see |
743 | libata-scsi.c */ | 746 | libata-scsi.c */ |
@@ -748,7 +751,6 @@ static int nv_adma_slave_config(struct scsi_device *sdev) | |||
748 | adma_enable = 0; | 751 | adma_enable = 0; |
749 | nv_adma_register_mode(ap); | 752 | nv_adma_register_mode(ap); |
750 | } else { | 753 | } else { |
751 | bounce_limit = *ap->dev->dma_mask; | ||
752 | segment_boundary = NV_ADMA_DMA_BOUNDARY; | 754 | segment_boundary = NV_ADMA_DMA_BOUNDARY; |
753 | sg_tablesize = NV_ADMA_SGTBL_TOTAL_LEN; | 755 | sg_tablesize = NV_ADMA_SGTBL_TOTAL_LEN; |
754 | adma_enable = 1; | 756 | adma_enable = 1; |
@@ -774,12 +776,49 @@ static int nv_adma_slave_config(struct scsi_device *sdev) | |||
774 | if (current_reg != new_reg) | 776 | if (current_reg != new_reg) |
775 | pci_write_config_dword(pdev, NV_MCP_SATA_CFG_20, new_reg); | 777 | pci_write_config_dword(pdev, NV_MCP_SATA_CFG_20, new_reg); |
776 | 778 | ||
777 | blk_queue_bounce_limit(sdev->request_queue, bounce_limit); | 779 | port0 = ap->host->ports[0]->private_data; |
780 | port1 = ap->host->ports[1]->private_data; | ||
781 | sdev0 = ap->host->ports[0]->link.device[0].sdev; | ||
782 | sdev1 = ap->host->ports[1]->link.device[0].sdev; | ||
783 | if ((port0->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) || | ||
784 | (port1->flags & NV_ADMA_ATAPI_SETUP_COMPLETE)) { | ||
785 | /** We have to set the DMA mask to 32-bit if either port is in | ||
786 | ATAPI mode, since they are on the same PCI device which is | ||
787 | used for DMA mapping. If we set the mask we also need to set | ||
788 | the bounce limit on both ports to ensure that the block | ||
789 | layer doesn't feed addresses that cause DMA mapping to | ||
790 | choke. If either SCSI device is not allocated yet, it's OK | ||
791 | since that port will discover its correct setting when it | ||
792 | does get allocated. | ||
793 | Note: Setting 32-bit mask should not fail. */ | ||
794 | if (sdev0) | ||
795 | blk_queue_bounce_limit(sdev0->request_queue, | ||
796 | ATA_DMA_MASK); | ||
797 | if (sdev1) | ||
798 | blk_queue_bounce_limit(sdev1->request_queue, | ||
799 | ATA_DMA_MASK); | ||
800 | |||
801 | pci_set_dma_mask(pdev, ATA_DMA_MASK); | ||
802 | } else { | ||
803 | /** This shouldn't fail as it was set to this value before */ | ||
804 | pci_set_dma_mask(pdev, pp->adma_dma_mask); | ||
805 | if (sdev0) | ||
806 | blk_queue_bounce_limit(sdev0->request_queue, | ||
807 | pp->adma_dma_mask); | ||
808 | if (sdev1) | ||
809 | blk_queue_bounce_limit(sdev1->request_queue, | ||
810 | pp->adma_dma_mask); | ||
811 | } | ||
812 | |||
778 | blk_queue_segment_boundary(sdev->request_queue, segment_boundary); | 813 | blk_queue_segment_boundary(sdev->request_queue, segment_boundary); |
779 | blk_queue_max_hw_segments(sdev->request_queue, sg_tablesize); | 814 | blk_queue_max_hw_segments(sdev->request_queue, sg_tablesize); |
780 | ata_port_printk(ap, KERN_INFO, | 815 | ata_port_printk(ap, KERN_INFO, |
781 | "bounce limit 0x%llX, segment boundary 0x%lX, hw segs %hu\n", | 816 | "DMA mask 0x%llX, segment boundary 0x%lX, hw segs %hu\n", |
782 | (unsigned long long)bounce_limit, segment_boundary, sg_tablesize); | 817 | (unsigned long long)*ap->host->dev->dma_mask, |
818 | segment_boundary, sg_tablesize); | ||
819 | |||
820 | spin_unlock_irqrestore(ap->lock, flags); | ||
821 | |||
783 | return rc; | 822 | return rc; |
784 | } | 823 | } |
785 | 824 | ||
@@ -1140,10 +1179,20 @@ static int nv_adma_port_start(struct ata_port *ap) | |||
1140 | void *mem; | 1179 | void *mem; |
1141 | dma_addr_t mem_dma; | 1180 | dma_addr_t mem_dma; |
1142 | void __iomem *mmio; | 1181 | void __iomem *mmio; |
1182 | struct pci_dev *pdev = to_pci_dev(dev); | ||
1143 | u16 tmp; | 1183 | u16 tmp; |
1144 | 1184 | ||
1145 | VPRINTK("ENTER\n"); | 1185 | VPRINTK("ENTER\n"); |
1146 | 1186 | ||
1187 | /* Ensure DMA mask is set to 32-bit before allocating legacy PRD and | ||
1188 | pad buffers */ | ||
1189 | rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); | ||
1190 | if (rc) | ||
1191 | return rc; | ||
1192 | rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); | ||
1193 | if (rc) | ||
1194 | return rc; | ||
1195 | |||
1147 | rc = ata_port_start(ap); | 1196 | rc = ata_port_start(ap); |
1148 | if (rc) | 1197 | if (rc) |
1149 | return rc; | 1198 | return rc; |
@@ -1159,6 +1208,15 @@ static int nv_adma_port_start(struct ata_port *ap) | |||
1159 | pp->notifier_clear_block = pp->gen_block + | 1208 | pp->notifier_clear_block = pp->gen_block + |
1160 | NV_ADMA_NOTIFIER_CLEAR + (4 * ap->port_no); | 1209 | NV_ADMA_NOTIFIER_CLEAR + (4 * ap->port_no); |
1161 | 1210 | ||
1211 | /* Now that the legacy PRD and padding buffer are allocated we can | ||
1212 | safely raise the DMA mask to allocate the CPB/APRD table. | ||
1213 | These are allowed to fail since we store the value that ends up | ||
1214 | being used to set as the bounce limit in slave_config later if | ||
1215 | needed. */ | ||
1216 | pci_set_dma_mask(pdev, DMA_BIT_MASK(64)); | ||
1217 | pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); | ||
1218 | pp->adma_dma_mask = *dev->dma_mask; | ||
1219 | |||
1162 | mem = dmam_alloc_coherent(dev, NV_ADMA_PORT_PRIV_DMA_SZ, | 1220 | mem = dmam_alloc_coherent(dev, NV_ADMA_PORT_PRIV_DMA_SZ, |
1163 | &mem_dma, GFP_KERNEL); | 1221 | &mem_dma, GFP_KERNEL); |
1164 | if (!mem) | 1222 | if (!mem) |
@@ -2417,12 +2475,6 @@ static int nv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
2417 | hpriv->type = type; | 2475 | hpriv->type = type; |
2418 | host->private_data = hpriv; | 2476 | host->private_data = hpriv; |
2419 | 2477 | ||
2420 | /* set 64bit dma masks, may fail */ | ||
2421 | if (type == ADMA) { | ||
2422 | if (pci_set_dma_mask(pdev, DMA_64BIT_MASK) == 0) | ||
2423 | pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK); | ||
2424 | } | ||
2425 | |||
2426 | /* request and iomap NV_MMIO_BAR */ | 2478 | /* request and iomap NV_MMIO_BAR */ |
2427 | rc = pcim_iomap_regions(pdev, 1 << NV_MMIO_BAR, DRV_NAME); | 2479 | rc = pcim_iomap_regions(pdev, 1 << NV_MMIO_BAR, DRV_NAME); |
2428 | if (rc) | 2480 | if (rc) |
diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c index 3ef072ff319d..30caa0337190 100644 --- a/drivers/ata/sata_via.c +++ b/drivers/ata/sata_via.c | |||
@@ -30,8 +30,6 @@ | |||
30 | * Hardware documentation available under NDA. | 30 | * Hardware documentation available under NDA. |
31 | * | 31 | * |
32 | * | 32 | * |
33 | * To-do list: | ||
34 | * - VT6421 PATA support | ||
35 | * | 33 | * |
36 | */ | 34 | */ |
37 | 35 | ||
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c index c5885f5ce0ac..499b003f9278 100644 --- a/drivers/base/cpu.c +++ b/drivers/base/cpu.c | |||
@@ -110,7 +110,7 @@ static SYSDEV_ATTR(crash_notes, 0400, show_crash_notes, NULL); | |||
110 | * | 110 | * |
111 | * Initialize and register the CPU device. | 111 | * Initialize and register the CPU device. |
112 | */ | 112 | */ |
113 | int __devinit register_cpu(struct cpu *cpu, int num) | 113 | int __cpuinit register_cpu(struct cpu *cpu, int num) |
114 | { | 114 | { |
115 | int error; | 115 | int error; |
116 | cpu->node_id = cpu_to_node(num); | 116 | cpu->node_id = cpu_to_node(num); |
diff --git a/drivers/block/ataflop.c b/drivers/block/ataflop.c index 94268c75d04f..424995073c6b 100644 --- a/drivers/block/ataflop.c +++ b/drivers/block/ataflop.c | |||
@@ -90,7 +90,7 @@ static struct atari_disk_type { | |||
90 | unsigned blocks; /* total number of blocks */ | 90 | unsigned blocks; /* total number of blocks */ |
91 | unsigned fdc_speed; /* fdc_speed setting */ | 91 | unsigned fdc_speed; /* fdc_speed setting */ |
92 | unsigned stretch; /* track doubling ? */ | 92 | unsigned stretch; /* track doubling ? */ |
93 | } disk_type[] = { | 93 | } atari_disk_type[] = { |
94 | { "d360", 9, 720, 0, 0}, /* 0: 360kB diskette */ | 94 | { "d360", 9, 720, 0, 0}, /* 0: 360kB diskette */ |
95 | { "D360", 9, 720, 0, 1}, /* 1: 360kb in 720k or 1.2MB drive */ | 95 | { "D360", 9, 720, 0, 1}, /* 1: 360kb in 720k or 1.2MB drive */ |
96 | { "D720", 9,1440, 0, 0}, /* 2: 720kb in 720k or 1.2MB drive */ | 96 | { "D720", 9,1440, 0, 0}, /* 2: 720kb in 720k or 1.2MB drive */ |
@@ -658,7 +658,7 @@ static int do_format(int drive, int type, struct atari_format_descr *desc) | |||
658 | return -EINVAL; | 658 | return -EINVAL; |
659 | } | 659 | } |
660 | type = minor2disktype[type].index; | 660 | type = minor2disktype[type].index; |
661 | UDT = &disk_type[type]; | 661 | UDT = &atari_disk_type[type]; |
662 | } | 662 | } |
663 | 663 | ||
664 | if (!UDT || desc->track >= UDT->blocks/UDT->spt/2 || desc->head >= 2) { | 664 | if (!UDT || desc->track >= UDT->blocks/UDT->spt/2 || desc->head >= 2) { |
@@ -1064,7 +1064,7 @@ static void fd_rwsec_done1(int status) | |||
1064 | searched for a non-existent sector! */ | 1064 | searched for a non-existent sector! */ |
1065 | !(read_track && FDC_READ(FDCREG_SECTOR) > SUDT->spt)) { | 1065 | !(read_track && FDC_READ(FDCREG_SECTOR) > SUDT->spt)) { |
1066 | if (Probing) { | 1066 | if (Probing) { |
1067 | if (SUDT > disk_type) { | 1067 | if (SUDT > atari_disk_type) { |
1068 | if (SUDT[-1].blocks > ReqBlock) { | 1068 | if (SUDT[-1].blocks > ReqBlock) { |
1069 | /* try another disk type */ | 1069 | /* try another disk type */ |
1070 | SUDT--; | 1070 | SUDT--; |
@@ -1082,7 +1082,7 @@ static void fd_rwsec_done1(int status) | |||
1082 | } else { | 1082 | } else { |
1083 | /* record not found, but not probing. Maybe stretch wrong ? Restart probing */ | 1083 | /* record not found, but not probing. Maybe stretch wrong ? Restart probing */ |
1084 | if (SUD.autoprobe) { | 1084 | if (SUD.autoprobe) { |
1085 | SUDT = disk_type + StartDiskType[DriveType]; | 1085 | SUDT = atari_disk_type + StartDiskType[DriveType]; |
1086 | set_capacity(unit[SelectedDrive].disk, | 1086 | set_capacity(unit[SelectedDrive].disk, |
1087 | SUDT->blocks); | 1087 | SUDT->blocks); |
1088 | Probing = 1; | 1088 | Probing = 1; |
@@ -1421,7 +1421,7 @@ repeat: | |||
1421 | if (type == 0) { | 1421 | if (type == 0) { |
1422 | if (!UDT) { | 1422 | if (!UDT) { |
1423 | Probing = 1; | 1423 | Probing = 1; |
1424 | UDT = disk_type + StartDiskType[DriveType]; | 1424 | UDT = atari_disk_type + StartDiskType[DriveType]; |
1425 | set_capacity(floppy->disk, UDT->blocks); | 1425 | set_capacity(floppy->disk, UDT->blocks); |
1426 | UD.autoprobe = 1; | 1426 | UD.autoprobe = 1; |
1427 | } | 1427 | } |
@@ -1439,7 +1439,7 @@ repeat: | |||
1439 | goto repeat; | 1439 | goto repeat; |
1440 | } | 1440 | } |
1441 | type = minor2disktype[type].index; | 1441 | type = minor2disktype[type].index; |
1442 | UDT = &disk_type[type]; | 1442 | UDT = &atari_disk_type[type]; |
1443 | set_capacity(floppy->disk, UDT->blocks); | 1443 | set_capacity(floppy->disk, UDT->blocks); |
1444 | UD.autoprobe = 0; | 1444 | UD.autoprobe = 0; |
1445 | } | 1445 | } |
@@ -1505,7 +1505,7 @@ static int fd_ioctl(struct inode *inode, struct file *filp, | |||
1505 | if (minor2disktype[type].drive_types > DriveType) | 1505 | if (minor2disktype[type].drive_types > DriveType) |
1506 | return -ENODEV; | 1506 | return -ENODEV; |
1507 | type = minor2disktype[type].index; | 1507 | type = minor2disktype[type].index; |
1508 | dtp = &disk_type[type]; | 1508 | dtp = &atari_disk_type[type]; |
1509 | if (UD.flags & FTD_MSG) | 1509 | if (UD.flags & FTD_MSG) |
1510 | printk (KERN_ERR "floppy%d: found dtp %p name %s!\n", | 1510 | printk (KERN_ERR "floppy%d: found dtp %p name %s!\n", |
1511 | drive, dtp, dtp->name); | 1511 | drive, dtp, dtp->name); |
@@ -1576,7 +1576,7 @@ static int fd_ioctl(struct inode *inode, struct file *filp, | |||
1576 | continue; | 1576 | continue; |
1577 | } | 1577 | } |
1578 | setidx = minor2disktype[settype].index; | 1578 | setidx = minor2disktype[settype].index; |
1579 | dtp = &disk_type[setidx]; | 1579 | dtp = &atari_disk_type[setidx]; |
1580 | 1580 | ||
1581 | /* found matching entry ?? */ | 1581 | /* found matching entry ?? */ |
1582 | if ( dtp->blocks == setprm.size | 1582 | if ( dtp->blocks == setprm.size |
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 855ce8e5efba..9715be3f2487 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c | |||
@@ -2630,12 +2630,14 @@ static void do_cciss_request(struct request_queue *q) | |||
2630 | c->Request.CDB[8] = creq->nr_sectors & 0xff; | 2630 | c->Request.CDB[8] = creq->nr_sectors & 0xff; |
2631 | c->Request.CDB[9] = c->Request.CDB[11] = c->Request.CDB[12] = 0; | 2631 | c->Request.CDB[9] = c->Request.CDB[11] = c->Request.CDB[12] = 0; |
2632 | } else { | 2632 | } else { |
2633 | u32 upper32 = upper_32_bits(start_blk); | ||
2634 | |||
2633 | c->Request.CDBLen = 16; | 2635 | c->Request.CDBLen = 16; |
2634 | c->Request.CDB[1]= 0; | 2636 | c->Request.CDB[1]= 0; |
2635 | c->Request.CDB[2]= (start_blk >> 56) & 0xff; //MSB | 2637 | c->Request.CDB[2]= (upper32 >> 24) & 0xff; //MSB |
2636 | c->Request.CDB[3]= (start_blk >> 48) & 0xff; | 2638 | c->Request.CDB[3]= (upper32 >> 16) & 0xff; |
2637 | c->Request.CDB[4]= (start_blk >> 40) & 0xff; | 2639 | c->Request.CDB[4]= (upper32 >> 8) & 0xff; |
2638 | c->Request.CDB[5]= (start_blk >> 32) & 0xff; | 2640 | c->Request.CDB[5]= upper32 & 0xff; |
2639 | c->Request.CDB[6]= (start_blk >> 24) & 0xff; | 2641 | c->Request.CDB[6]= (start_blk >> 24) & 0xff; |
2640 | c->Request.CDB[7]= (start_blk >> 16) & 0xff; | 2642 | c->Request.CDB[7]= (start_blk >> 16) & 0xff; |
2641 | c->Request.CDB[8]= (start_blk >> 8) & 0xff; | 2643 | c->Request.CDB[8]= (start_blk >> 8) & 0xff; |
diff --git a/drivers/block/loop.c b/drivers/block/loop.c index b8af22e610df..91ebb007416c 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c | |||
@@ -973,6 +973,10 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info) | |||
973 | lo->transfer = xfer->transfer; | 973 | lo->transfer = xfer->transfer; |
974 | lo->ioctl = xfer->ioctl; | 974 | lo->ioctl = xfer->ioctl; |
975 | 975 | ||
976 | if ((lo->lo_flags & LO_FLAGS_AUTOCLEAR) != | ||
977 | (info->lo_flags & LO_FLAGS_AUTOCLEAR)) | ||
978 | lo->lo_flags ^= LO_FLAGS_AUTOCLEAR; | ||
979 | |||
976 | lo->lo_encrypt_key_size = info->lo_encrypt_key_size; | 980 | lo->lo_encrypt_key_size = info->lo_encrypt_key_size; |
977 | lo->lo_init[0] = info->lo_init[0]; | 981 | lo->lo_init[0] = info->lo_init[0]; |
978 | lo->lo_init[1] = info->lo_init[1]; | 982 | lo->lo_init[1] = info->lo_init[1]; |
@@ -1331,6 +1335,10 @@ static int lo_release(struct inode *inode, struct file *file) | |||
1331 | 1335 | ||
1332 | mutex_lock(&lo->lo_ctl_mutex); | 1336 | mutex_lock(&lo->lo_ctl_mutex); |
1333 | --lo->lo_refcnt; | 1337 | --lo->lo_refcnt; |
1338 | |||
1339 | if ((lo->lo_flags & LO_FLAGS_AUTOCLEAR) && !lo->lo_refcnt) | ||
1340 | loop_clr_fd(lo, inode->i_bdev); | ||
1341 | |||
1334 | mutex_unlock(&lo->lo_ctl_mutex); | 1342 | mutex_unlock(&lo->lo_ctl_mutex); |
1335 | 1343 | ||
1336 | return 0; | 1344 | return 0; |
diff --git a/drivers/block/paride/pt.c b/drivers/block/paride/pt.c index 76096cad798f..8b9549ab4a4e 100644 --- a/drivers/block/paride/pt.c +++ b/drivers/block/paride/pt.c | |||
@@ -660,7 +660,7 @@ static int pt_open(struct inode *inode, struct file *file) | |||
660 | pt_identify(tape); | 660 | pt_identify(tape); |
661 | 661 | ||
662 | err = -ENODEV; | 662 | err = -ENODEV; |
663 | if (!tape->flags & PT_MEDIA) | 663 | if (!(tape->flags & PT_MEDIA)) |
664 | goto out; | 664 | goto out; |
665 | 665 | ||
666 | err = -EROFS; | 666 | err = -EROFS; |
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index e9de1712e5a0..674cd66dcaba 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c | |||
@@ -2212,11 +2212,11 @@ static int pkt_media_speed(struct pktcdvd_device *pd, unsigned *speed) | |||
2212 | return ret; | 2212 | return ret; |
2213 | } | 2213 | } |
2214 | 2214 | ||
2215 | if (!buf[6] & 0x40) { | 2215 | if (!(buf[6] & 0x40)) { |
2216 | printk(DRIVER_NAME": Disc type is not CD-RW\n"); | 2216 | printk(DRIVER_NAME": Disc type is not CD-RW\n"); |
2217 | return 1; | 2217 | return 1; |
2218 | } | 2218 | } |
2219 | if (!buf[6] & 0x4) { | 2219 | if (!(buf[6] & 0x4)) { |
2220 | printk(DRIVER_NAME": A1 values on media are not valid, maybe not CDRW?\n"); | 2220 | printk(DRIVER_NAME": A1 values on media are not valid, maybe not CDRW?\n"); |
2221 | return 1; | 2221 | return 1; |
2222 | } | 2222 | } |
diff --git a/drivers/block/rd.c b/drivers/block/rd.c index 82f4eecc8699..06e23be70904 100644 --- a/drivers/block/rd.c +++ b/drivers/block/rd.c | |||
@@ -56,6 +56,7 @@ | |||
56 | #include <linux/backing-dev.h> | 56 | #include <linux/backing-dev.h> |
57 | #include <linux/blkpg.h> | 57 | #include <linux/blkpg.h> |
58 | #include <linux/writeback.h> | 58 | #include <linux/writeback.h> |
59 | #include <linux/log2.h> | ||
59 | 60 | ||
60 | #include <asm/uaccess.h> | 61 | #include <asm/uaccess.h> |
61 | 62 | ||
@@ -450,7 +451,7 @@ static int __init rd_init(void) | |||
450 | err = -ENOMEM; | 451 | err = -ENOMEM; |
451 | 452 | ||
452 | if (rd_blocksize > PAGE_SIZE || rd_blocksize < 512 || | 453 | if (rd_blocksize > PAGE_SIZE || rd_blocksize < 512 || |
453 | (rd_blocksize & (rd_blocksize-1))) { | 454 | !is_power_of_2(rd_blocksize)) { |
454 | printk("RAMDISK: wrong blocksize %d, reverting to defaults\n", | 455 | printk("RAMDISK: wrong blocksize %d, reverting to defaults\n", |
455 | rd_blocksize); | 456 | rd_blocksize); |
456 | rd_blocksize = BLOCK_SIZE; | 457 | rd_blocksize = BLOCK_SIZE; |
diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c index 47e5b40510cb..db259e60289b 100644 --- a/drivers/cdrom/cdrom.c +++ b/drivers/cdrom/cdrom.c | |||
@@ -1206,25 +1206,26 @@ int check_for_audio_disc(struct cdrom_device_info * cdi, | |||
1206 | return 0; | 1206 | return 0; |
1207 | } | 1207 | } |
1208 | 1208 | ||
1209 | /* Admittedly, the logic below could be performed in a nicer way. */ | ||
1210 | int cdrom_release(struct cdrom_device_info *cdi, struct file *fp) | 1209 | int cdrom_release(struct cdrom_device_info *cdi, struct file *fp) |
1211 | { | 1210 | { |
1212 | struct cdrom_device_ops *cdo = cdi->ops; | 1211 | struct cdrom_device_ops *cdo = cdi->ops; |
1213 | int opened_for_data; | 1212 | int opened_for_data; |
1214 | 1213 | ||
1215 | cdinfo(CD_CLOSE, "entering cdrom_release\n"); | 1214 | cdinfo(CD_CLOSE, "entering cdrom_release\n"); |
1216 | 1215 | ||
1217 | if (cdi->use_count > 0) | 1216 | if (cdi->use_count > 0) |
1218 | cdi->use_count--; | 1217 | cdi->use_count--; |
1219 | if (cdi->use_count == 0) | 1218 | |
1219 | if (cdi->use_count == 0) { | ||
1220 | cdinfo(CD_CLOSE, "Use count for \"/dev/%s\" now zero\n", cdi->name); | 1220 | cdinfo(CD_CLOSE, "Use count for \"/dev/%s\" now zero\n", cdi->name); |
1221 | if (cdi->use_count == 0) | ||
1222 | cdrom_dvd_rw_close_write(cdi); | 1221 | cdrom_dvd_rw_close_write(cdi); |
1223 | if (cdi->use_count == 0 && | 1222 | |
1224 | (cdo->capability & CDC_LOCK) && !keeplocked) { | 1223 | if ((cdo->capability & CDC_LOCK) && !keeplocked) { |
1225 | cdinfo(CD_CLOSE, "Unlocking door!\n"); | 1224 | cdinfo(CD_CLOSE, "Unlocking door!\n"); |
1226 | cdo->lock_door(cdi, 0); | 1225 | cdo->lock_door(cdi, 0); |
1226 | } | ||
1227 | } | 1227 | } |
1228 | |||
1228 | opened_for_data = !(cdi->options & CDO_USE_FFLAGS) || | 1229 | opened_for_data = !(cdi->options & CDO_USE_FFLAGS) || |
1229 | !(fp && fp->f_flags & O_NONBLOCK); | 1230 | !(fp && fp->f_flags & O_NONBLOCK); |
1230 | 1231 | ||
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index be8371ac3086..f01ac9a07bf5 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig | |||
@@ -194,17 +194,6 @@ config MOXA_INTELLIO | |||
194 | module will be called moxa. | 194 | module will be called moxa. |
195 | 195 | ||
196 | config MOXA_SMARTIO | 196 | config MOXA_SMARTIO |
197 | tristate "Moxa SmartIO support (OBSOLETE)" | ||
198 | depends on SERIAL_NONSTANDARD | ||
199 | help | ||
200 | Say Y here if you have a Moxa SmartIO multiport serial card. | ||
201 | |||
202 | This driver can also be built as a module ( = code which can be | ||
203 | inserted in and removed from the running kernel whenever you want). | ||
204 | The module will be called mxser. If you want to do that, say M | ||
205 | here. | ||
206 | |||
207 | config MOXA_SMARTIO_NEW | ||
208 | tristate "Moxa SmartIO support v. 2.0" | 197 | tristate "Moxa SmartIO support v. 2.0" |
209 | depends on SERIAL_NONSTANDARD && (PCI || EISA || ISA) | 198 | depends on SERIAL_NONSTANDARD && (PCI || EISA || ISA) |
210 | help | 199 | help |
@@ -215,7 +204,7 @@ config MOXA_SMARTIO_NEW | |||
215 | changes finally resulting in PCI probing. | 204 | changes finally resulting in PCI probing. |
216 | 205 | ||
217 | This driver can also be built as a module. The module will be called | 206 | This driver can also be built as a module. The module will be called |
218 | mxser_new. If you want to do that, say M here. | 207 | mxser. If you want to do that, say M here. |
219 | 208 | ||
220 | config ISI | 209 | config ISI |
221 | tristate "Multi-Tech multiport card support (EXPERIMENTAL)" | 210 | tristate "Multi-Tech multiport card support (EXPERIMENTAL)" |
@@ -276,7 +265,7 @@ config N_HDLC | |||
276 | 265 | ||
277 | config RISCOM8 | 266 | config RISCOM8 |
278 | tristate "SDL RISCom/8 card support" | 267 | tristate "SDL RISCom/8 card support" |
279 | depends on SERIAL_NONSTANDARD && BROKEN_ON_SMP | 268 | depends on SERIAL_NONSTANDARD |
280 | help | 269 | help |
281 | This is a driver for the SDL Communications RISCom/8 multiport card, | 270 | This is a driver for the SDL Communications RISCom/8 multiport card, |
282 | which gives you many serial ports. You would need something like | 271 | which gives you many serial ports. You would need something like |
@@ -765,7 +754,7 @@ config JS_RTC | |||
765 | 754 | ||
766 | config SGI_DS1286 | 755 | config SGI_DS1286 |
767 | tristate "SGI DS1286 RTC support" | 756 | tristate "SGI DS1286 RTC support" |
768 | depends on SGI_IP22 | 757 | depends on SGI_HAS_DS1286 |
769 | help | 758 | help |
770 | If you say Y here and create a character special file /dev/rtc with | 759 | If you say Y here and create a character special file /dev/rtc with |
771 | major number 10 and minor number 135 using mknod ("man mknod"), you | 760 | major number 10 and minor number 135 using mknod ("man mknod"), you |
diff --git a/drivers/char/Makefile b/drivers/char/Makefile index 686fabbd85cd..5407b7615614 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile | |||
@@ -33,7 +33,6 @@ obj-$(CONFIG_MOXA_INTELLIO) += moxa.o | |||
33 | obj-$(CONFIG_A2232) += ser_a2232.o generic_serial.o | 33 | obj-$(CONFIG_A2232) += ser_a2232.o generic_serial.o |
34 | obj-$(CONFIG_ATARI_DSP56K) += dsp56k.o | 34 | obj-$(CONFIG_ATARI_DSP56K) += dsp56k.o |
35 | obj-$(CONFIG_MOXA_SMARTIO) += mxser.o | 35 | obj-$(CONFIG_MOXA_SMARTIO) += mxser.o |
36 | obj-$(CONFIG_MOXA_SMARTIO_NEW) += mxser_new.o | ||
37 | obj-$(CONFIG_COMPUTONE) += ip2/ | 36 | obj-$(CONFIG_COMPUTONE) += ip2/ |
38 | obj-$(CONFIG_RISCOM8) += riscom8.o | 37 | obj-$(CONFIG_RISCOM8) += riscom8.o |
39 | obj-$(CONFIG_ISI) += isicom.o | 38 | obj-$(CONFIG_ISI) += isicom.o |
diff --git a/drivers/char/epca.h b/drivers/char/epca.h index a297238cd3ba..3c77c02b5d65 100644 --- a/drivers/char/epca.h +++ b/drivers/char/epca.h | |||
@@ -77,7 +77,6 @@ static char *board_desc[] = | |||
77 | #define ON 1 | 77 | #define ON 1 |
78 | 78 | ||
79 | #define FEPTIMEOUT 200000 | 79 | #define FEPTIMEOUT 200000 |
80 | #define SERIAL_TYPE_NORMAL 1 | ||
81 | #define SERIAL_TYPE_INFO 3 | 80 | #define SERIAL_TYPE_INFO 3 |
82 | #define EPCA_EVENT_HANGUP 1 | 81 | #define EPCA_EVENT_HANGUP 1 |
83 | #define EPCA_MAGIC 0x5c6df104L | 82 | #define EPCA_MAGIC 0x5c6df104L |
diff --git a/drivers/char/esp.c b/drivers/char/esp.c index 28607763ae64..c01e26d9ee5e 100644 --- a/drivers/char/esp.c +++ b/drivers/char/esp.c | |||
@@ -111,9 +111,6 @@ static char serial_version[] __initdata = "2.2"; | |||
111 | 111 | ||
112 | static struct tty_driver *esp_driver; | 112 | static struct tty_driver *esp_driver; |
113 | 113 | ||
114 | /* serial subtype definitions */ | ||
115 | #define SERIAL_TYPE_NORMAL 1 | ||
116 | |||
117 | /* | 114 | /* |
118 | * Serial driver configuration section. Here are the various options: | 115 | * Serial driver configuration section. Here are the various options: |
119 | * | 116 | * |
@@ -245,17 +242,6 @@ static void rs_start(struct tty_struct *tty) | |||
245 | * ----------------------------------------------------------------------- | 242 | * ----------------------------------------------------------------------- |
246 | */ | 243 | */ |
247 | 244 | ||
248 | /* | ||
249 | * This routine is used by the interrupt handler to schedule | ||
250 | * processing in the software interrupt portion of the driver. | ||
251 | */ | ||
252 | static inline void rs_sched_event(struct esp_struct *info, | ||
253 | int event) | ||
254 | { | ||
255 | info->event |= 1 << event; | ||
256 | schedule_work(&info->tqueue); | ||
257 | } | ||
258 | |||
259 | static DEFINE_SPINLOCK(pio_lock); | 245 | static DEFINE_SPINLOCK(pio_lock); |
260 | 246 | ||
261 | static inline struct esp_pio_buffer *get_pio_buffer(void) | 247 | static inline struct esp_pio_buffer *get_pio_buffer(void) |
@@ -477,7 +463,8 @@ static inline void transmit_chars_pio(struct esp_struct *info, | |||
477 | } | 463 | } |
478 | 464 | ||
479 | if (info->xmit_cnt < WAKEUP_CHARS) { | 465 | if (info->xmit_cnt < WAKEUP_CHARS) { |
480 | rs_sched_event(info, ESP_EVENT_WRITE_WAKEUP); | 466 | if (info->tty) |
467 | tty_wakeup(info->tty); | ||
481 | 468 | ||
482 | #ifdef SERIAL_DEBUG_INTR | 469 | #ifdef SERIAL_DEBUG_INTR |
483 | printk("THRE..."); | 470 | printk("THRE..."); |
@@ -515,7 +502,8 @@ static inline void transmit_chars_dma(struct esp_struct *info, int num_bytes) | |||
515 | info->xmit_tail = (info->xmit_tail + dma_bytes) & (ESP_XMIT_SIZE - 1); | 502 | info->xmit_tail = (info->xmit_tail + dma_bytes) & (ESP_XMIT_SIZE - 1); |
516 | 503 | ||
517 | if (info->xmit_cnt < WAKEUP_CHARS) { | 504 | if (info->xmit_cnt < WAKEUP_CHARS) { |
518 | rs_sched_event(info, ESP_EVENT_WRITE_WAKEUP); | 505 | if (info->tty) |
506 | tty_wakeup(info->tty); | ||
519 | 507 | ||
520 | #ifdef SERIAL_DEBUG_INTR | 508 | #ifdef SERIAL_DEBUG_INTR |
521 | printk("THRE..."); | 509 | printk("THRE..."); |
@@ -607,7 +595,7 @@ static inline void check_modem_status(struct esp_struct *info) | |||
607 | #ifdef SERIAL_DEBUG_OPEN | 595 | #ifdef SERIAL_DEBUG_OPEN |
608 | printk("scheduling hangup..."); | 596 | printk("scheduling hangup..."); |
609 | #endif | 597 | #endif |
610 | schedule_work(&info->tqueue_hangup); | 598 | tty_hangup(info->tty); |
611 | } | 599 | } |
612 | } | 600 | } |
613 | } | 601 | } |
@@ -723,41 +711,6 @@ static irqreturn_t rs_interrupt_single(int irq, void *dev_id) | |||
723 | * ------------------------------------------------------------------- | 711 | * ------------------------------------------------------------------- |
724 | */ | 712 | */ |
725 | 713 | ||
726 | static void do_softint(struct work_struct *work) | ||
727 | { | ||
728 | struct esp_struct *info = | ||
729 | container_of(work, struct esp_struct, tqueue); | ||
730 | struct tty_struct *tty; | ||
731 | |||
732 | tty = info->tty; | ||
733 | if (!tty) | ||
734 | return; | ||
735 | |||
736 | if (test_and_clear_bit(ESP_EVENT_WRITE_WAKEUP, &info->event)) { | ||
737 | tty_wakeup(tty); | ||
738 | } | ||
739 | } | ||
740 | |||
741 | /* | ||
742 | * This routine is called from the scheduler tqueue when the interrupt | ||
743 | * routine has signalled that a hangup has occurred. The path of | ||
744 | * hangup processing is: | ||
745 | * | ||
746 | * serial interrupt routine -> (scheduler tqueue) -> | ||
747 | * do_serial_hangup() -> tty->hangup() -> esp_hangup() | ||
748 | * | ||
749 | */ | ||
750 | static void do_serial_hangup(struct work_struct *work) | ||
751 | { | ||
752 | struct esp_struct *info = | ||
753 | container_of(work, struct esp_struct, tqueue_hangup); | ||
754 | struct tty_struct *tty; | ||
755 | |||
756 | tty = info->tty; | ||
757 | if (tty) | ||
758 | tty_hangup(tty); | ||
759 | } | ||
760 | |||
761 | /* | 714 | /* |
762 | * --------------------------------------------------------------- | 715 | * --------------------------------------------------------------- |
763 | * Low level utility subroutines for the serial driver: routines to | 716 | * Low level utility subroutines for the serial driver: routines to |
@@ -2041,7 +1994,6 @@ static void rs_close(struct tty_struct *tty, struct file * filp) | |||
2041 | tty->driver->flush_buffer(tty); | 1994 | tty->driver->flush_buffer(tty); |
2042 | tty_ldisc_flush(tty); | 1995 | tty_ldisc_flush(tty); |
2043 | tty->closing = 0; | 1996 | tty->closing = 0; |
2044 | info->event = 0; | ||
2045 | info->tty = NULL; | 1997 | info->tty = NULL; |
2046 | 1998 | ||
2047 | if (info->blocked_open) { | 1999 | if (info->blocked_open) { |
@@ -2109,7 +2061,6 @@ static void esp_hangup(struct tty_struct *tty) | |||
2109 | 2061 | ||
2110 | rs_flush_buffer(tty); | 2062 | rs_flush_buffer(tty); |
2111 | shutdown(info); | 2063 | shutdown(info); |
2112 | info->event = 0; | ||
2113 | info->count = 0; | 2064 | info->count = 0; |
2114 | info->flags &= ~ASYNC_NORMAL_ACTIVE; | 2065 | info->flags &= ~ASYNC_NORMAL_ACTIVE; |
2115 | info->tty = NULL; | 2066 | info->tty = NULL; |
@@ -2495,8 +2446,6 @@ static int __init espserial_init(void) | |||
2495 | info->magic = ESP_MAGIC; | 2446 | info->magic = ESP_MAGIC; |
2496 | info->close_delay = 5*HZ/10; | 2447 | info->close_delay = 5*HZ/10; |
2497 | info->closing_wait = 30*HZ; | 2448 | info->closing_wait = 30*HZ; |
2498 | INIT_WORK(&info->tqueue, do_softint); | ||
2499 | INIT_WORK(&info->tqueue_hangup, do_serial_hangup); | ||
2500 | info->config.rx_timeout = rx_timeout; | 2449 | info->config.rx_timeout = rx_timeout; |
2501 | info->config.flow_on = flow_on; | 2450 | info->config.flow_on = flow_on; |
2502 | info->config.flow_off = flow_off; | 2451 | info->config.flow_off = flow_off; |
diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c index 480fae29c9b2..44160d5ebca0 100644 --- a/drivers/char/hvc_console.c +++ b/drivers/char/hvc_console.c | |||
@@ -93,7 +93,7 @@ struct hvc_struct { | |||
93 | }; | 93 | }; |
94 | 94 | ||
95 | /* dynamic list of hvc_struct instances */ | 95 | /* dynamic list of hvc_struct instances */ |
96 | static struct list_head hvc_structs = LIST_HEAD_INIT(hvc_structs); | 96 | static LIST_HEAD(hvc_structs); |
97 | 97 | ||
98 | /* | 98 | /* |
99 | * Protect the list of hvc_struct instances from inserts and removals during | 99 | * Protect the list of hvc_struct instances from inserts and removals during |
diff --git a/drivers/char/hvcs.c b/drivers/char/hvcs.c index 3402def22007..786d518e9477 100644 --- a/drivers/char/hvcs.c +++ b/drivers/char/hvcs.c | |||
@@ -306,7 +306,7 @@ struct hvcs_struct { | |||
306 | /* Required to back map a kref to its containing object */ | 306 | /* Required to back map a kref to its containing object */ |
307 | #define from_kref(k) container_of(k, struct hvcs_struct, kref) | 307 | #define from_kref(k) container_of(k, struct hvcs_struct, kref) |
308 | 308 | ||
309 | static struct list_head hvcs_structs = LIST_HEAD_INIT(hvcs_structs); | 309 | static LIST_HEAD(hvcs_structs); |
310 | static DEFINE_SPINLOCK(hvcs_structs_lock); | 310 | static DEFINE_SPINLOCK(hvcs_structs_lock); |
311 | 311 | ||
312 | static void hvcs_unthrottle(struct tty_struct *tty); | 312 | static void hvcs_unthrottle(struct tty_struct *tty); |
diff --git a/drivers/char/hw_random/via-rng.c b/drivers/char/hw_random/via-rng.c index 868e39fd42e4..f7feae4ebb5e 100644 --- a/drivers/char/hw_random/via-rng.c +++ b/drivers/char/hw_random/via-rng.c | |||
@@ -42,6 +42,8 @@ enum { | |||
42 | VIA_STRFILT_ENABLE = (1 << 14), | 42 | VIA_STRFILT_ENABLE = (1 << 14), |
43 | VIA_RAWBITS_ENABLE = (1 << 13), | 43 | VIA_RAWBITS_ENABLE = (1 << 13), |
44 | VIA_RNG_ENABLE = (1 << 6), | 44 | VIA_RNG_ENABLE = (1 << 6), |
45 | VIA_NOISESRC1 = (1 << 8), | ||
46 | VIA_NOISESRC2 = (1 << 9), | ||
45 | VIA_XSTORE_CNT_MASK = 0x0F, | 47 | VIA_XSTORE_CNT_MASK = 0x0F, |
46 | 48 | ||
47 | VIA_RNG_CHUNK_8 = 0x00, /* 64 rand bits, 64 stored bits */ | 49 | VIA_RNG_CHUNK_8 = 0x00, /* 64 rand bits, 64 stored bits */ |
@@ -119,6 +121,7 @@ static int via_rng_data_read(struct hwrng *rng, u32 *data) | |||
119 | 121 | ||
120 | static int via_rng_init(struct hwrng *rng) | 122 | static int via_rng_init(struct hwrng *rng) |
121 | { | 123 | { |
124 | struct cpuinfo_x86 *c = &cpu_data(0); | ||
122 | u32 lo, hi, old_lo; | 125 | u32 lo, hi, old_lo; |
123 | 126 | ||
124 | /* Control the RNG via MSR. Tread lightly and pay very close | 127 | /* Control the RNG via MSR. Tread lightly and pay very close |
@@ -134,6 +137,17 @@ static int via_rng_init(struct hwrng *rng) | |||
134 | lo &= ~VIA_XSTORE_CNT_MASK; | 137 | lo &= ~VIA_XSTORE_CNT_MASK; |
135 | lo &= ~(VIA_STRFILT_ENABLE | VIA_STRFILT_FAIL | VIA_RAWBITS_ENABLE); | 138 | lo &= ~(VIA_STRFILT_ENABLE | VIA_STRFILT_FAIL | VIA_RAWBITS_ENABLE); |
136 | lo |= VIA_RNG_ENABLE; | 139 | lo |= VIA_RNG_ENABLE; |
140 | lo |= VIA_NOISESRC1; | ||
141 | |||
142 | /* Enable secondary noise source on CPUs where it is present. */ | ||
143 | |||
144 | /* Nehemiah stepping 8 and higher */ | ||
145 | if ((c->x86_model == 9) && (c->x86_mask > 7)) | ||
146 | lo |= VIA_NOISESRC2; | ||
147 | |||
148 | /* Esther */ | ||
149 | if (c->x86_model >= 10) | ||
150 | lo |= VIA_NOISESRC2; | ||
137 | 151 | ||
138 | if (lo != old_lo) | 152 | if (lo != old_lo) |
139 | wrmsr(MSR_VIA_RNG, lo, hi); | 153 | wrmsr(MSR_VIA_RNG, lo, hi); |
diff --git a/drivers/char/i8k.c b/drivers/char/i8k.c index 30e564516422..8609b8236c67 100644 --- a/drivers/char/i8k.c +++ b/drivers/char/i8k.c | |||
@@ -113,6 +113,33 @@ static int i8k_smm(struct smm_regs *regs) | |||
113 | int rc; | 113 | int rc; |
114 | int eax = regs->eax; | 114 | int eax = regs->eax; |
115 | 115 | ||
116 | #if defined(CONFIG_X86_64) | ||
117 | asm("pushq %%rax\n\t" | ||
118 | "movl 0(%%rax),%%edx\n\t" | ||
119 | "pushq %%rdx\n\t" | ||
120 | "movl 4(%%rax),%%ebx\n\t" | ||
121 | "movl 8(%%rax),%%ecx\n\t" | ||
122 | "movl 12(%%rax),%%edx\n\t" | ||
123 | "movl 16(%%rax),%%esi\n\t" | ||
124 | "movl 20(%%rax),%%edi\n\t" | ||
125 | "popq %%rax\n\t" | ||
126 | "out %%al,$0xb2\n\t" | ||
127 | "out %%al,$0x84\n\t" | ||
128 | "xchgq %%rax,(%%rsp)\n\t" | ||
129 | "movl %%ebx,4(%%rax)\n\t" | ||
130 | "movl %%ecx,8(%%rax)\n\t" | ||
131 | "movl %%edx,12(%%rax)\n\t" | ||
132 | "movl %%esi,16(%%rax)\n\t" | ||
133 | "movl %%edi,20(%%rax)\n\t" | ||
134 | "popq %%rdx\n\t" | ||
135 | "movl %%edx,0(%%rax)\n\t" | ||
136 | "lahf\n\t" | ||
137 | "shrl $8,%%eax\n\t" | ||
138 | "andl $1,%%eax\n" | ||
139 | :"=a"(rc) | ||
140 | : "a"(regs) | ||
141 | : "%ebx", "%ecx", "%edx", "%esi", "%edi", "memory"); | ||
142 | #else | ||
116 | asm("pushl %%eax\n\t" | 143 | asm("pushl %%eax\n\t" |
117 | "movl 0(%%eax),%%edx\n\t" | 144 | "movl 0(%%eax),%%edx\n\t" |
118 | "push %%edx\n\t" | 145 | "push %%edx\n\t" |
@@ -137,7 +164,7 @@ static int i8k_smm(struct smm_regs *regs) | |||
137 | "andl $1,%%eax\n":"=a"(rc) | 164 | "andl $1,%%eax\n":"=a"(rc) |
138 | : "a"(regs) | 165 | : "a"(regs) |
139 | : "%ebx", "%ecx", "%edx", "%esi", "%edi", "memory"); | 166 | : "%ebx", "%ecx", "%edx", "%esi", "%edi", "memory"); |
140 | 167 | #endif | |
141 | if (rc != 0 || (regs->eax & 0xffff) == 0xffff || regs->eax == eax) | 168 | if (rc != 0 || (regs->eax & 0xffff) == 0xffff || regs->eax == eax) |
142 | return -EINVAL; | 169 | return -EINVAL; |
143 | 170 | ||
@@ -439,6 +466,20 @@ static struct dmi_system_id __initdata i8k_dmi_table[] = { | |||
439 | DMI_MATCH(DMI_PRODUCT_NAME, "Latitude"), | 466 | DMI_MATCH(DMI_PRODUCT_NAME, "Latitude"), |
440 | }, | 467 | }, |
441 | }, | 468 | }, |
469 | { /* UK Inspiron 6400 */ | ||
470 | .ident = "Dell Inspiron 3", | ||
471 | .matches = { | ||
472 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | ||
473 | DMI_MATCH(DMI_PRODUCT_NAME, "MM061"), | ||
474 | }, | ||
475 | }, | ||
476 | { | ||
477 | .ident = "Dell Inspiron 3", | ||
478 | .matches = { | ||
479 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | ||
480 | DMI_MATCH(DMI_PRODUCT_NAME, "MP061"), | ||
481 | }, | ||
482 | }, | ||
442 | { } | 483 | { } |
443 | }; | 484 | }; |
444 | 485 | ||
diff --git a/drivers/char/ip2/ip2main.c b/drivers/char/ip2/ip2main.c index 0f49ccf02a7f..b1d6cad84282 100644 --- a/drivers/char/ip2/ip2main.c +++ b/drivers/char/ip2/ip2main.c | |||
@@ -153,9 +153,6 @@ static char *pcVersion = "1.2.14"; | |||
153 | static char *pcDriver_name = "ip2"; | 153 | static char *pcDriver_name = "ip2"; |
154 | static char *pcIpl = "ip2ipl"; | 154 | static char *pcIpl = "ip2ipl"; |
155 | 155 | ||
156 | /* Serial subtype definitions */ | ||
157 | #define SERIAL_TYPE_NORMAL 1 | ||
158 | |||
159 | // cheezy kludge or genius - you decide? | 156 | // cheezy kludge or genius - you decide? |
160 | int ip2_loadmain(int *, int *, unsigned char *, int); | 157 | int ip2_loadmain(int *, int *, unsigned char *, int); |
161 | static unsigned char *Fip_firmware; | 158 | static unsigned char *Fip_firmware; |
diff --git a/drivers/char/ip27-rtc.c b/drivers/char/ip27-rtc.c index 932264a657d0..86e6538a77b0 100644 --- a/drivers/char/ip27-rtc.c +++ b/drivers/char/ip27-rtc.c | |||
@@ -46,8 +46,8 @@ | |||
46 | #include <asm/sn/sn0/hub.h> | 46 | #include <asm/sn/sn0/hub.h> |
47 | #include <asm/sn/sn_private.h> | 47 | #include <asm/sn/sn_private.h> |
48 | 48 | ||
49 | static int rtc_ioctl(struct inode *inode, struct file *file, | 49 | static long rtc_ioctl(struct file *filp, unsigned int cmd, |
50 | unsigned int cmd, unsigned long arg); | 50 | unsigned long arg); |
51 | 51 | ||
52 | static int rtc_read_proc(char *page, char **start, off_t off, | 52 | static int rtc_read_proc(char *page, char **start, off_t off, |
53 | int count, int *eof, void *data); | 53 | int count, int *eof, void *data); |
@@ -75,8 +75,7 @@ static unsigned long epoch = 1970; /* year corresponding to 0x00 */ | |||
75 | static const unsigned char days_in_mo[] = | 75 | static const unsigned char days_in_mo[] = |
76 | {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; | 76 | {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; |
77 | 77 | ||
78 | static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | 78 | static long rtc_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) |
79 | unsigned long arg) | ||
80 | { | 79 | { |
81 | 80 | ||
82 | struct rtc_time wtime; | 81 | struct rtc_time wtime; |
@@ -197,7 +196,7 @@ static int rtc_release(struct inode *inode, struct file *file) | |||
197 | 196 | ||
198 | static const struct file_operations rtc_fops = { | 197 | static const struct file_operations rtc_fops = { |
199 | .owner = THIS_MODULE, | 198 | .owner = THIS_MODULE, |
200 | .ioctl = rtc_ioctl, | 199 | .unlocked_ioctl = rtc_ioctl, |
201 | .open = rtc_open, | 200 | .open = rtc_open, |
202 | .release = rtc_release, | 201 | .release = rtc_release, |
203 | }; | 202 | }; |
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index 5dc1265ce1d5..32b2b22996dc 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c | |||
@@ -365,12 +365,12 @@ static struct device_driver ipmidriver = { | |||
365 | }; | 365 | }; |
366 | static DEFINE_MUTEX(ipmidriver_mutex); | 366 | static DEFINE_MUTEX(ipmidriver_mutex); |
367 | 367 | ||
368 | static struct list_head ipmi_interfaces = LIST_HEAD_INIT(ipmi_interfaces); | 368 | static LIST_HEAD(ipmi_interfaces); |
369 | static DEFINE_MUTEX(ipmi_interfaces_mutex); | 369 | static DEFINE_MUTEX(ipmi_interfaces_mutex); |
370 | 370 | ||
371 | /* List of watchers that want to know when smi's are added and | 371 | /* List of watchers that want to know when smi's are added and |
372 | deleted. */ | 372 | deleted. */ |
373 | static struct list_head smi_watchers = LIST_HEAD_INIT(smi_watchers); | 373 | static LIST_HEAD(smi_watchers); |
374 | static DEFINE_MUTEX(smi_watchers_mutex); | 374 | static DEFINE_MUTEX(smi_watchers_mutex); |
375 | 375 | ||
376 | 376 | ||
@@ -441,7 +441,7 @@ struct watcher_entry { | |||
441 | int ipmi_smi_watcher_register(struct ipmi_smi_watcher *watcher) | 441 | int ipmi_smi_watcher_register(struct ipmi_smi_watcher *watcher) |
442 | { | 442 | { |
443 | ipmi_smi_t intf; | 443 | ipmi_smi_t intf; |
444 | struct list_head to_deliver = LIST_HEAD_INIT(to_deliver); | 444 | LIST_HEAD(to_deliver); |
445 | struct watcher_entry *e, *e2; | 445 | struct watcher_entry *e, *e2; |
446 | 446 | ||
447 | mutex_lock(&smi_watchers_mutex); | 447 | mutex_lock(&smi_watchers_mutex); |
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c index 1f27be1ec3d4..c645455c3fd1 100644 --- a/drivers/char/istallion.c +++ b/drivers/char/istallion.c | |||
@@ -627,7 +627,6 @@ static int stli_initopen(struct stlibrd *brdp, struct stliport *portp); | |||
627 | static int stli_rawopen(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait); | 627 | static int stli_rawopen(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait); |
628 | static int stli_rawclose(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait); | 628 | static int stli_rawclose(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait); |
629 | static int stli_waitcarrier(struct stlibrd *brdp, struct stliport *portp, struct file *filp); | 629 | static int stli_waitcarrier(struct stlibrd *brdp, struct stliport *portp, struct file *filp); |
630 | static void stli_dohangup(struct work_struct *); | ||
631 | static int stli_setport(struct stliport *portp); | 630 | static int stli_setport(struct stliport *portp); |
632 | static int stli_cmdwait(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback); | 631 | static int stli_cmdwait(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback); |
633 | static void stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback); | 632 | static void stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback); |
@@ -1824,25 +1823,6 @@ static void stli_start(struct tty_struct *tty) | |||
1824 | /*****************************************************************************/ | 1823 | /*****************************************************************************/ |
1825 | 1824 | ||
1826 | /* | 1825 | /* |
1827 | * Scheduler called hang up routine. This is called from the scheduler, | ||
1828 | * not direct from the driver "poll" routine. We can't call it there | ||
1829 | * since the real local hangup code will enable/disable the board and | ||
1830 | * other things that we can't do while handling the poll. Much easier | ||
1831 | * to deal with it some time later (don't really care when, hangups | ||
1832 | * aren't that time critical). | ||
1833 | */ | ||
1834 | |||
1835 | static void stli_dohangup(struct work_struct *ugly_api) | ||
1836 | { | ||
1837 | struct stliport *portp = container_of(ugly_api, struct stliport, tqhangup); | ||
1838 | if (portp->tty != NULL) { | ||
1839 | tty_hangup(portp->tty); | ||
1840 | } | ||
1841 | } | ||
1842 | |||
1843 | /*****************************************************************************/ | ||
1844 | |||
1845 | /* | ||
1846 | * Hangup this port. This is pretty much like closing the port, only | 1826 | * Hangup this port. This is pretty much like closing the port, only |
1847 | * a little more brutal. No waiting for data to drain. Shutdown the | 1827 | * a little more brutal. No waiting for data to drain. Shutdown the |
1848 | * port and maybe drop signals. This is rather tricky really. We want | 1828 | * port and maybe drop signals. This is rather tricky really. We want |
@@ -2405,7 +2385,7 @@ static int stli_hostcmd(struct stlibrd *brdp, struct stliport *portp) | |||
2405 | ((portp->sigs & TIOCM_CD) == 0)) { | 2385 | ((portp->sigs & TIOCM_CD) == 0)) { |
2406 | if (portp->flags & ASYNC_CHECK_CD) { | 2386 | if (portp->flags & ASYNC_CHECK_CD) { |
2407 | if (tty) | 2387 | if (tty) |
2408 | schedule_work(&portp->tqhangup); | 2388 | tty_hangup(tty); |
2409 | } | 2389 | } |
2410 | } | 2390 | } |
2411 | } | 2391 | } |
@@ -2733,7 +2713,6 @@ static int stli_initports(struct stlibrd *brdp) | |||
2733 | portp->baud_base = STL_BAUDBASE; | 2713 | portp->baud_base = STL_BAUDBASE; |
2734 | portp->close_delay = STL_CLOSEDELAY; | 2714 | portp->close_delay = STL_CLOSEDELAY; |
2735 | portp->closing_wait = 30 * HZ; | 2715 | portp->closing_wait = 30 * HZ; |
2736 | INIT_WORK(&portp->tqhangup, stli_dohangup); | ||
2737 | init_waitqueue_head(&portp->open_wait); | 2716 | init_waitqueue_head(&portp->open_wait); |
2738 | init_waitqueue_head(&portp->close_wait); | 2717 | init_waitqueue_head(&portp->close_wait); |
2739 | init_waitqueue_head(&portp->raw_wait); | 2718 | init_waitqueue_head(&portp->raw_wait); |
diff --git a/drivers/char/lp.c b/drivers/char/lp.c index 81674d7c56c7..60ac642752be 100644 --- a/drivers/char/lp.c +++ b/drivers/char/lp.c | |||
@@ -312,7 +312,7 @@ static ssize_t lp_write(struct file * file, const char __user * buf, | |||
312 | if (copy_size > LP_BUFFER_SIZE) | 312 | if (copy_size > LP_BUFFER_SIZE) |
313 | copy_size = LP_BUFFER_SIZE; | 313 | copy_size = LP_BUFFER_SIZE; |
314 | 314 | ||
315 | if (down_interruptible (&lp_table[minor].port_mutex)) | 315 | if (mutex_lock_interruptible(&lp_table[minor].port_mutex)) |
316 | return -EINTR; | 316 | return -EINTR; |
317 | 317 | ||
318 | if (copy_from_user (kbuf, buf, copy_size)) { | 318 | if (copy_from_user (kbuf, buf, copy_size)) { |
@@ -399,7 +399,7 @@ static ssize_t lp_write(struct file * file, const char __user * buf, | |||
399 | lp_release_parport (&lp_table[minor]); | 399 | lp_release_parport (&lp_table[minor]); |
400 | } | 400 | } |
401 | out_unlock: | 401 | out_unlock: |
402 | up (&lp_table[minor].port_mutex); | 402 | mutex_unlock(&lp_table[minor].port_mutex); |
403 | 403 | ||
404 | return retv; | 404 | return retv; |
405 | } | 405 | } |
@@ -421,7 +421,7 @@ static ssize_t lp_read(struct file * file, char __user * buf, | |||
421 | if (count > LP_BUFFER_SIZE) | 421 | if (count > LP_BUFFER_SIZE) |
422 | count = LP_BUFFER_SIZE; | 422 | count = LP_BUFFER_SIZE; |
423 | 423 | ||
424 | if (down_interruptible (&lp_table[minor].port_mutex)) | 424 | if (mutex_lock_interruptible(&lp_table[minor].port_mutex)) |
425 | return -EINTR; | 425 | return -EINTR; |
426 | 426 | ||
427 | lp_claim_parport_or_block (&lp_table[minor]); | 427 | lp_claim_parport_or_block (&lp_table[minor]); |
@@ -479,7 +479,7 @@ static ssize_t lp_read(struct file * file, char __user * buf, | |||
479 | if (retval > 0 && copy_to_user (buf, kbuf, retval)) | 479 | if (retval > 0 && copy_to_user (buf, kbuf, retval)) |
480 | retval = -EFAULT; | 480 | retval = -EFAULT; |
481 | 481 | ||
482 | up (&lp_table[minor].port_mutex); | 482 | mutex_unlock(&lp_table[minor].port_mutex); |
483 | 483 | ||
484 | return retval; | 484 | return retval; |
485 | } | 485 | } |
@@ -888,7 +888,7 @@ static int __init lp_init (void) | |||
888 | lp_table[i].last_error = 0; | 888 | lp_table[i].last_error = 0; |
889 | init_waitqueue_head (&lp_table[i].waitq); | 889 | init_waitqueue_head (&lp_table[i].waitq); |
890 | init_waitqueue_head (&lp_table[i].dataq); | 890 | init_waitqueue_head (&lp_table[i].dataq); |
891 | init_MUTEX (&lp_table[i].port_mutex); | 891 | mutex_init(&lp_table[i].port_mutex); |
892 | lp_table[i].timeout = 10 * HZ; | 892 | lp_table[i].timeout = 10 * HZ; |
893 | } | 893 | } |
894 | 894 | ||
diff --git a/drivers/char/mbcs.c b/drivers/char/mbcs.c index 3c5802ae1716..f4716ad7348a 100644 --- a/drivers/char/mbcs.c +++ b/drivers/char/mbcs.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/device.h> | 23 | #include <linux/device.h> |
24 | #include <linux/mm.h> | 24 | #include <linux/mm.h> |
25 | #include <linux/uio.h> | 25 | #include <linux/uio.h> |
26 | #include <linux/mutex.h> | ||
26 | #include <asm/io.h> | 27 | #include <asm/io.h> |
27 | #include <asm/uaccess.h> | 28 | #include <asm/uaccess.h> |
28 | #include <asm/system.h> | 29 | #include <asm/system.h> |
@@ -281,7 +282,7 @@ static inline int mbcs_algo_start(struct mbcs_soft *soft) | |||
281 | void *mmr_base = soft->mmr_base; | 282 | void *mmr_base = soft->mmr_base; |
282 | union cm_control cm_control; | 283 | union cm_control cm_control; |
283 | 284 | ||
284 | if (down_interruptible(&soft->algolock)) | 285 | if (mutex_lock_interruptible(&soft->algolock)) |
285 | return -ERESTARTSYS; | 286 | return -ERESTARTSYS; |
286 | 287 | ||
287 | atomic_set(&soft->algo_done, 0); | 288 | atomic_set(&soft->algo_done, 0); |
@@ -298,7 +299,7 @@ static inline int mbcs_algo_start(struct mbcs_soft *soft) | |||
298 | cm_control.alg_go = 1; | 299 | cm_control.alg_go = 1; |
299 | MBCS_MMR_SET(mmr_base, MBCS_CM_CONTROL, cm_control.cm_control_reg); | 300 | MBCS_MMR_SET(mmr_base, MBCS_CM_CONTROL, cm_control.cm_control_reg); |
300 | 301 | ||
301 | up(&soft->algolock); | 302 | mutex_unlock(&soft->algolock); |
302 | 303 | ||
303 | return 0; | 304 | return 0; |
304 | } | 305 | } |
@@ -309,7 +310,7 @@ do_mbcs_sram_dmawrite(struct mbcs_soft *soft, uint64_t hostAddr, | |||
309 | { | 310 | { |
310 | int rv = 0; | 311 | int rv = 0; |
311 | 312 | ||
312 | if (down_interruptible(&soft->dmawritelock)) | 313 | if (mutex_lock_interruptible(&soft->dmawritelock)) |
313 | return -ERESTARTSYS; | 314 | return -ERESTARTSYS; |
314 | 315 | ||
315 | atomic_set(&soft->dmawrite_done, 0); | 316 | atomic_set(&soft->dmawrite_done, 0); |
@@ -335,7 +336,7 @@ do_mbcs_sram_dmawrite(struct mbcs_soft *soft, uint64_t hostAddr, | |||
335 | *off += len; | 336 | *off += len; |
336 | 337 | ||
337 | dmawrite_exit: | 338 | dmawrite_exit: |
338 | up(&soft->dmawritelock); | 339 | mutex_unlock(&soft->dmawritelock); |
339 | 340 | ||
340 | return rv; | 341 | return rv; |
341 | } | 342 | } |
@@ -346,7 +347,7 @@ do_mbcs_sram_dmaread(struct mbcs_soft *soft, uint64_t hostAddr, | |||
346 | { | 347 | { |
347 | int rv = 0; | 348 | int rv = 0; |
348 | 349 | ||
349 | if (down_interruptible(&soft->dmareadlock)) | 350 | if (mutex_lock_interruptible(&soft->dmareadlock)) |
350 | return -ERESTARTSYS; | 351 | return -ERESTARTSYS; |
351 | 352 | ||
352 | atomic_set(&soft->dmawrite_done, 0); | 353 | atomic_set(&soft->dmawrite_done, 0); |
@@ -371,7 +372,7 @@ do_mbcs_sram_dmaread(struct mbcs_soft *soft, uint64_t hostAddr, | |||
371 | *off += len; | 372 | *off += len; |
372 | 373 | ||
373 | dmaread_exit: | 374 | dmaread_exit: |
374 | up(&soft->dmareadlock); | 375 | mutex_unlock(&soft->dmareadlock); |
375 | 376 | ||
376 | return rv; | 377 | return rv; |
377 | } | 378 | } |
@@ -762,9 +763,9 @@ static int mbcs_probe(struct cx_dev *dev, const struct cx_device_id *id) | |||
762 | init_waitqueue_head(&soft->dmaread_queue); | 763 | init_waitqueue_head(&soft->dmaread_queue); |
763 | init_waitqueue_head(&soft->algo_queue); | 764 | init_waitqueue_head(&soft->algo_queue); |
764 | 765 | ||
765 | init_MUTEX(&soft->dmawritelock); | 766 | mutex_init(&soft->dmawritelock); |
766 | init_MUTEX(&soft->dmareadlock); | 767 | mutex_init(&soft->dmareadlock); |
767 | init_MUTEX(&soft->algolock); | 768 | mutex_init(&soft->algolock); |
768 | 769 | ||
769 | mbcs_getdma_init(&soft->getdma); | 770 | mbcs_getdma_init(&soft->getdma); |
770 | mbcs_putdma_init(&soft->putdma); | 771 | mbcs_putdma_init(&soft->putdma); |
diff --git a/drivers/char/mbcs.h b/drivers/char/mbcs.h index c9905a3c3353..ba671589f4cb 100644 --- a/drivers/char/mbcs.h +++ b/drivers/char/mbcs.h | |||
@@ -537,9 +537,9 @@ struct mbcs_soft { | |||
537 | atomic_t dmawrite_done; | 537 | atomic_t dmawrite_done; |
538 | atomic_t dmaread_done; | 538 | atomic_t dmaread_done; |
539 | atomic_t algo_done; | 539 | atomic_t algo_done; |
540 | struct semaphore dmawritelock; | 540 | struct mutex dmawritelock; |
541 | struct semaphore dmareadlock; | 541 | struct mutex dmareadlock; |
542 | struct semaphore algolock; | 542 | struct mutex algolock; |
543 | }; | 543 | }; |
544 | 544 | ||
545 | static int mbcs_open(struct inode *ip, struct file *fp); | 545 | static int mbcs_open(struct inode *ip, struct file *fp); |
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c index fd0abef7ee08..68c2e9234691 100644 --- a/drivers/char/mxser.c +++ b/drivers/char/mxser.c | |||
@@ -1,43 +1,25 @@ | |||
1 | /* | 1 | /* |
2 | * mxser.c -- MOXA Smartio/Industio family multiport serial driver. | 2 | * mxser.c -- MOXA Smartio/Industio family multiport serial driver. |
3 | * | 3 | * |
4 | * Copyright (C) 1999-2001 Moxa Technologies (support@moxa.com.tw). | 4 | * Copyright (C) 1999-2006 Moxa Technologies (support@moxa.com). |
5 | * Copyright (C) 2006-2008 Jiri Slaby <jirislaby@gmail.com> | ||
5 | * | 6 | * |
6 | * This code is loosely based on the Linux serial driver, written by | 7 | * This code is loosely based on the 1.8 moxa driver which is based on |
7 | * Linus Torvalds, Theodore T'so and others. | 8 | * Linux serial driver, written by Linus Torvalds, Theodore T'so and |
9 | * others. | ||
8 | * | 10 | * |
9 | * This program is free software; you can redistribute it and/or modify | 11 | * This program is free software; you can redistribute it and/or modify |
10 | * it under the terms of the GNU General Public License as published by | 12 | * it under the terms of the GNU General Public License as published by |
11 | * the Free Software Foundation; either version 2 of the License, or | 13 | * the Free Software Foundation; either version 2 of the License, or |
12 | * (at your option) any later version. | 14 | * (at your option) any later version. |
13 | * | 15 | * |
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | * | ||
23 | * Original release 10/26/00 | ||
24 | * | ||
25 | * 02/06/01 Support MOXA Industio family boards. | ||
26 | * 02/06/01 Support TIOCGICOUNT. | ||
27 | * 02/06/01 Fix the problem for connecting to serial mouse. | ||
28 | * 02/06/01 Fix the problem for H/W flow control. | ||
29 | * 02/06/01 Fix the compling warning when CONFIG_PCI | ||
30 | * don't be defined. | ||
31 | * | ||
32 | * Fed through a cleanup, indent and remove of non 2.6 code by Alan Cox | 16 | * Fed through a cleanup, indent and remove of non 2.6 code by Alan Cox |
33 | * <alan@redhat.com>. The original 1.8 code is available on www.moxa.com. | 17 | * <alan@redhat.com>. The original 1.8 code is available on www.moxa.com. |
34 | * - Fixed x86_64 cleanness | 18 | * - Fixed x86_64 cleanness |
35 | * - Fixed sleep with spinlock held in mxser_send_break | 19 | * - Fixed sleep with spinlock held in mxser_send_break |
36 | */ | 20 | */ |
37 | 21 | ||
38 | |||
39 | #include <linux/module.h> | 22 | #include <linux/module.h> |
40 | #include <linux/autoconf.h> | ||
41 | #include <linux/errno.h> | 23 | #include <linux/errno.h> |
42 | #include <linux/signal.h> | 24 | #include <linux/signal.h> |
43 | #include <linux/sched.h> | 25 | #include <linux/sched.h> |
@@ -65,33 +47,37 @@ | |||
65 | 47 | ||
66 | #include "mxser.h" | 48 | #include "mxser.h" |
67 | 49 | ||
68 | #define MXSER_VERSION "1.8" | 50 | #define MXSER_VERSION "2.0.3" /* 1.11 */ |
69 | #define MXSERMAJOR 174 | 51 | #define MXSERMAJOR 174 |
70 | #define MXSERCUMAJOR 175 | 52 | #define MXSERCUMAJOR 175 |
71 | 53 | ||
72 | #define MXSER_EVENT_TXLOW 1 | ||
73 | #define MXSER_EVENT_HANGUP 2 | ||
74 | |||
75 | #define MXSER_BOARDS 4 /* Max. boards */ | 54 | #define MXSER_BOARDS 4 /* Max. boards */ |
76 | #define MXSER_PORTS 32 /* Max. ports */ | ||
77 | #define MXSER_PORTS_PER_BOARD 8 /* Max. ports per board */ | 55 | #define MXSER_PORTS_PER_BOARD 8 /* Max. ports per board */ |
78 | #define MXSER_ISR_PASS_LIMIT 256 | 56 | #define MXSER_PORTS (MXSER_BOARDS * MXSER_PORTS_PER_BOARD) |
57 | #define MXSER_ISR_PASS_LIMIT 100 | ||
79 | 58 | ||
80 | #define MXSER_ERR_IOADDR -1 | 59 | #define MXSER_ERR_IOADDR -1 |
81 | #define MXSER_ERR_IRQ -2 | 60 | #define MXSER_ERR_IRQ -2 |
82 | #define MXSER_ERR_IRQ_CONFLIT -3 | 61 | #define MXSER_ERR_IRQ_CONFLIT -3 |
83 | #define MXSER_ERR_VECTOR -4 | 62 | #define MXSER_ERR_VECTOR -4 |
84 | 63 | ||
85 | #define SERIAL_TYPE_NORMAL 1 | 64 | /*CheckIsMoxaMust return value*/ |
86 | #define SERIAL_TYPE_CALLOUT 2 | 65 | #define MOXA_OTHER_UART 0x00 |
66 | #define MOXA_MUST_MU150_HWID 0x01 | ||
67 | #define MOXA_MUST_MU860_HWID 0x02 | ||
87 | 68 | ||
88 | #define WAKEUP_CHARS 256 | 69 | #define WAKEUP_CHARS 256 |
89 | 70 | ||
90 | #define UART_MCR_AFE 0x20 | 71 | #define UART_MCR_AFE 0x20 |
91 | #define UART_LSR_SPECIAL 0x1E | 72 | #define UART_LSR_SPECIAL 0x1E |
92 | 73 | ||
74 | #define PCI_DEVICE_ID_CB108 0x1080 | ||
75 | #define PCI_DEVICE_ID_CB114 0x1142 | ||
76 | #define PCI_DEVICE_ID_CP114UL 0x1143 | ||
77 | #define PCI_DEVICE_ID_CB134I 0x1341 | ||
78 | #define PCI_DEVICE_ID_CP138U 0x1380 | ||
79 | #define PCI_DEVICE_ID_POS104UL 0x1044 | ||
93 | 80 | ||
94 | #define IRQ_T(info) ((info->flags & ASYNC_SHARE_IRQ) ? IRQF_SHARED : IRQF_DISABLED) | ||
95 | 81 | ||
96 | #define C168_ASIC_ID 1 | 82 | #define C168_ASIC_ID 1 |
97 | #define C104_ASIC_ID 2 | 83 | #define C104_ASIC_ID 2 |
@@ -100,88 +86,11 @@ | |||
100 | #define CI134_ASIC_ID 3 | 86 | #define CI134_ASIC_ID 3 |
101 | #define CI104J_ASIC_ID 5 | 87 | #define CI104J_ASIC_ID 5 |
102 | 88 | ||
103 | enum { | 89 | #define MXSER_HIGHBAUD 1 |
104 | MXSER_BOARD_C168_ISA = 1, | 90 | #define MXSER_HAS2 2 |
105 | MXSER_BOARD_C104_ISA, | ||
106 | MXSER_BOARD_CI104J, | ||
107 | MXSER_BOARD_C168_PCI, | ||
108 | MXSER_BOARD_C104_PCI, | ||
109 | MXSER_BOARD_C102_ISA, | ||
110 | MXSER_BOARD_CI132, | ||
111 | MXSER_BOARD_CI134, | ||
112 | MXSER_BOARD_CP132, | ||
113 | MXSER_BOARD_CP114, | ||
114 | MXSER_BOARD_CT114, | ||
115 | MXSER_BOARD_CP102, | ||
116 | MXSER_BOARD_CP104U, | ||
117 | MXSER_BOARD_CP168U, | ||
118 | MXSER_BOARD_CP132U, | ||
119 | MXSER_BOARD_CP134U, | ||
120 | MXSER_BOARD_CP104JU, | ||
121 | MXSER_BOARD_RC7000, | ||
122 | MXSER_BOARD_CP118U, | ||
123 | MXSER_BOARD_CP102UL, | ||
124 | MXSER_BOARD_CP102U, | ||
125 | }; | ||
126 | |||
127 | static char *mxser_brdname[] = { | ||
128 | "C168 series", | ||
129 | "C104 series", | ||
130 | "CI-104J series", | ||
131 | "C168H/PCI series", | ||
132 | "C104H/PCI series", | ||
133 | "C102 series", | ||
134 | "CI-132 series", | ||
135 | "CI-134 series", | ||
136 | "CP-132 series", | ||
137 | "CP-114 series", | ||
138 | "CT-114 series", | ||
139 | "CP-102 series", | ||
140 | "CP-104U series", | ||
141 | "CP-168U series", | ||
142 | "CP-132U series", | ||
143 | "CP-134U series", | ||
144 | "CP-104JU series", | ||
145 | "Moxa UC7000 Serial", | ||
146 | "CP-118U series", | ||
147 | "CP-102UL series", | ||
148 | "CP-102U series", | ||
149 | }; | ||
150 | |||
151 | static int mxser_numports[] = { | ||
152 | 8, /* C168-ISA */ | ||
153 | 4, /* C104-ISA */ | ||
154 | 4, /* CI104J */ | ||
155 | 8, /* C168-PCI */ | ||
156 | 4, /* C104-PCI */ | ||
157 | 2, /* C102-ISA */ | ||
158 | 2, /* CI132 */ | ||
159 | 4, /* CI134 */ | ||
160 | 2, /* CP132 */ | ||
161 | 4, /* CP114 */ | ||
162 | 4, /* CT114 */ | ||
163 | 2, /* CP102 */ | ||
164 | 4, /* CP104U */ | ||
165 | 8, /* CP168U */ | ||
166 | 2, /* CP132U */ | ||
167 | 4, /* CP134U */ | ||
168 | 4, /* CP104JU */ | ||
169 | 8, /* RC7000 */ | ||
170 | 8, /* CP118U */ | ||
171 | 2, /* CP102UL */ | ||
172 | 2, /* CP102U */ | ||
173 | }; | ||
174 | |||
175 | #define UART_TYPE_NUM 2 | ||
176 | |||
177 | static const unsigned int Gmoxa_uart_id[UART_TYPE_NUM] = { | ||
178 | MOXA_MUST_MU150_HWID, | ||
179 | MOXA_MUST_MU860_HWID | ||
180 | }; | ||
181 | 91 | ||
182 | /* This is only for PCI */ | 92 | /* This is only for PCI */ |
183 | #define UART_INFO_NUM 3 | 93 | static const struct { |
184 | struct mxpciuart_info { | ||
185 | int type; | 94 | int type; |
186 | int tx_fifo; | 95 | int tx_fifo; |
187 | int rx_fifo; | 96 | int rx_fifo; |
@@ -190,51 +99,85 @@ struct mxpciuart_info { | |||
190 | int rx_trigger; | 99 | int rx_trigger; |
191 | int rx_low_water; | 100 | int rx_low_water; |
192 | long max_baud; | 101 | long max_baud; |
193 | }; | 102 | } Gpci_uart_info[] = { |
194 | |||
195 | static const struct mxpciuart_info Gpci_uart_info[UART_INFO_NUM] = { | ||
196 | {MOXA_OTHER_UART, 16, 16, 16, 14, 14, 1, 921600L}, | 103 | {MOXA_OTHER_UART, 16, 16, 16, 14, 14, 1, 921600L}, |
197 | {MOXA_MUST_MU150_HWID, 64, 64, 64, 48, 48, 16, 230400L}, | 104 | {MOXA_MUST_MU150_HWID, 64, 64, 64, 48, 48, 16, 230400L}, |
198 | {MOXA_MUST_MU860_HWID, 128, 128, 128, 96, 96, 32, 921600L} | 105 | {MOXA_MUST_MU860_HWID, 128, 128, 128, 96, 96, 32, 921600L} |
199 | }; | 106 | }; |
107 | #define UART_INFO_NUM ARRAY_SIZE(Gpci_uart_info) | ||
200 | 108 | ||
109 | struct mxser_cardinfo { | ||
110 | char *name; | ||
111 | unsigned int nports; | ||
112 | unsigned int flags; | ||
113 | }; | ||
201 | 114 | ||
202 | #ifdef CONFIG_PCI | 115 | static const struct mxser_cardinfo mxser_cards[] = { |
116 | /* 0*/ { "C168 series", 8, }, | ||
117 | { "C104 series", 4, }, | ||
118 | { "CI-104J series", 4, }, | ||
119 | { "C168H/PCI series", 8, }, | ||
120 | { "C104H/PCI series", 4, }, | ||
121 | /* 5*/ { "C102 series", 4, MXSER_HAS2 }, /* C102-ISA */ | ||
122 | { "CI-132 series", 4, MXSER_HAS2 }, | ||
123 | { "CI-134 series", 4, }, | ||
124 | { "CP-132 series", 2, }, | ||
125 | { "CP-114 series", 4, }, | ||
126 | /*10*/ { "CT-114 series", 4, }, | ||
127 | { "CP-102 series", 2, MXSER_HIGHBAUD }, | ||
128 | { "CP-104U series", 4, }, | ||
129 | { "CP-168U series", 8, }, | ||
130 | { "CP-132U series", 2, }, | ||
131 | /*15*/ { "CP-134U series", 4, }, | ||
132 | { "CP-104JU series", 4, }, | ||
133 | { "Moxa UC7000 Serial", 8, }, /* RC7000 */ | ||
134 | { "CP-118U series", 8, }, | ||
135 | { "CP-102UL series", 2, }, | ||
136 | /*20*/ { "CP-102U series", 2, }, | ||
137 | { "CP-118EL series", 8, }, | ||
138 | { "CP-168EL series", 8, }, | ||
139 | { "CP-104EL series", 4, }, | ||
140 | { "CB-108 series", 8, }, | ||
141 | /*25*/ { "CB-114 series", 4, }, | ||
142 | { "CB-134I series", 4, }, | ||
143 | { "CP-138U series", 8, }, | ||
144 | { "POS-104UL series", 4, }, | ||
145 | { "CP-114UL series", 4, } | ||
146 | }; | ||
203 | 147 | ||
148 | /* driver_data correspond to the lines in the structure above | ||
149 | see also ISA probe function before you change something */ | ||
204 | static struct pci_device_id mxser_pcibrds[] = { | 150 | static struct pci_device_id mxser_pcibrds[] = { |
205 | {PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_C168, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MXSER_BOARD_C168_PCI}, | 151 | { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_C168), .driver_data = 3 }, |
206 | {PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_C104, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MXSER_BOARD_C104_PCI}, | 152 | { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_C104), .driver_data = 4 }, |
207 | {PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP132, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MXSER_BOARD_CP132}, | 153 | { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP132), .driver_data = 8 }, |
208 | {PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP114, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MXSER_BOARD_CP114}, | 154 | { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP114), .driver_data = 9 }, |
209 | {PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CT114, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MXSER_BOARD_CT114}, | 155 | { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CT114), .driver_data = 10 }, |
210 | {PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP102, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MXSER_BOARD_CP102}, | 156 | { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP102), .driver_data = 11 }, |
211 | {PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP104U, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MXSER_BOARD_CP104U}, | 157 | { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP104U), .driver_data = 12 }, |
212 | {PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP168U, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MXSER_BOARD_CP168U}, | 158 | { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP168U), .driver_data = 13 }, |
213 | {PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP132U, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MXSER_BOARD_CP132U}, | 159 | { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP132U), .driver_data = 14 }, |
214 | {PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP134U, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MXSER_BOARD_CP134U}, | 160 | { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP134U), .driver_data = 15 }, |
215 | {PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP104JU, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MXSER_BOARD_CP104JU}, | 161 | { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP104JU),.driver_data = 16 }, |
216 | {PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_RC7000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MXSER_BOARD_RC7000}, | 162 | { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_RC7000), .driver_data = 17 }, |
217 | {PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP118U, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MXSER_BOARD_CP118U}, | 163 | { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP118U), .driver_data = 18 }, |
218 | {PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP102UL, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MXSER_BOARD_CP102UL}, | 164 | { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP102UL),.driver_data = 19 }, |
219 | {PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP102U, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MXSER_BOARD_CP102U}, | 165 | { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP102U), .driver_data = 20 }, |
220 | {0} | 166 | { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP118EL),.driver_data = 21 }, |
167 | { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP168EL),.driver_data = 22 }, | ||
168 | { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP104EL),.driver_data = 23 }, | ||
169 | { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CB108), .driver_data = 24 }, | ||
170 | { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CB114), .driver_data = 25 }, | ||
171 | { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CB134I), .driver_data = 26 }, | ||
172 | { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CP138U), .driver_data = 27 }, | ||
173 | { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_POS104UL), .driver_data = 28 }, | ||
174 | { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CP114UL), .driver_data = 29 }, | ||
175 | { } | ||
221 | }; | 176 | }; |
222 | |||
223 | MODULE_DEVICE_TABLE(pci, mxser_pcibrds); | 177 | MODULE_DEVICE_TABLE(pci, mxser_pcibrds); |
224 | 178 | ||
225 | |||
226 | #endif | ||
227 | |||
228 | typedef struct _moxa_pci_info { | ||
229 | unsigned short busNum; | ||
230 | unsigned short devNum; | ||
231 | struct pci_dev *pdev; /* add by Victor Yu. 06-23-2003 */ | ||
232 | } moxa_pci_info; | ||
233 | |||
234 | static int ioaddr[MXSER_BOARDS] = { 0, 0, 0, 0 }; | 179 | static int ioaddr[MXSER_BOARDS] = { 0, 0, 0, 0 }; |
235 | static int ttymajor = MXSERMAJOR; | 180 | static int ttymajor = MXSERMAJOR; |
236 | static int calloutmajor = MXSERCUMAJOR; | ||
237 | static int verbose = 0; | ||
238 | 181 | ||
239 | /* Variables for insmod */ | 182 | /* Variables for insmod */ |
240 | 183 | ||
@@ -242,8 +185,6 @@ MODULE_AUTHOR("Casper Yang"); | |||
242 | MODULE_DESCRIPTION("MOXA Smartio/Industio Family Multiport Board Device Driver"); | 185 | MODULE_DESCRIPTION("MOXA Smartio/Industio Family Multiport Board Device Driver"); |
243 | module_param_array(ioaddr, int, NULL, 0); | 186 | module_param_array(ioaddr, int, NULL, 0); |
244 | module_param(ttymajor, int, 0); | 187 | module_param(ttymajor, int, 0); |
245 | module_param(calloutmajor, int, 0); | ||
246 | module_param(verbose, bool, 0); | ||
247 | MODULE_LICENSE("GPL"); | 188 | MODULE_LICENSE("GPL"); |
248 | 189 | ||
249 | struct mxser_log { | 190 | struct mxser_log { |
@@ -278,67 +219,69 @@ struct mxser_mon_ext { | |||
278 | int iftype[32]; | 219 | int iftype[32]; |
279 | }; | 220 | }; |
280 | 221 | ||
281 | struct mxser_hwconf { | 222 | struct mxser_board; |
282 | int board_type; | 223 | |
283 | int ports; | 224 | struct mxser_port { |
284 | int irq; | 225 | struct mxser_board *board; |
285 | int vector; | 226 | struct tty_struct *tty; |
286 | int vector_mask; | 227 | |
287 | int uart_type; | 228 | unsigned long ioaddr; |
288 | int ioaddr[MXSER_PORTS_PER_BOARD]; | 229 | unsigned long opmode_ioaddr; |
289 | int baud_base[MXSER_PORTS_PER_BOARD]; | 230 | int max_baud; |
290 | moxa_pci_info pciInfo; | ||
291 | int IsMoxaMustChipFlag; /* add by Victor Yu. 08-30-2002 */ | ||
292 | int MaxCanSetBaudRate[MXSER_PORTS_PER_BOARD]; /* add by Victor Yu. 09-04-2002 */ | ||
293 | int opmode_ioaddr[MXSER_PORTS_PER_BOARD]; /* add by Victor Yu. 01-05-2004 */ | ||
294 | }; | ||
295 | 231 | ||
296 | struct mxser_struct { | ||
297 | int port; | ||
298 | int base; /* port base address */ | ||
299 | int irq; /* port using irq no. */ | ||
300 | int vector; /* port irq vector */ | ||
301 | int vectormask; /* port vector mask */ | ||
302 | int rx_high_water; | 232 | int rx_high_water; |
303 | int rx_trigger; /* Rx fifo trigger level */ | 233 | int rx_trigger; /* Rx fifo trigger level */ |
304 | int rx_low_water; | 234 | int rx_low_water; |
305 | int baud_base; /* max. speed */ | 235 | int baud_base; /* max. speed */ |
306 | int flags; /* defined in tty.h */ | ||
307 | int type; /* UART type */ | 236 | int type; /* UART type */ |
308 | struct tty_struct *tty; | 237 | int flags; /* defined in tty.h */ |
309 | int read_status_mask; | 238 | |
310 | int ignore_status_mask; | ||
311 | int xmit_fifo_size; | ||
312 | int custom_divisor; | ||
313 | int x_char; /* xon/xoff character */ | 239 | int x_char; /* xon/xoff character */ |
314 | int close_delay; | ||
315 | unsigned short closing_wait; | ||
316 | int IER; /* Interrupt Enable Register */ | 240 | int IER; /* Interrupt Enable Register */ |
317 | int MCR; /* Modem control register */ | 241 | int MCR; /* Modem control register */ |
242 | |||
243 | unsigned char stop_rx; | ||
244 | unsigned char ldisc_stop_rx; | ||
245 | |||
246 | int custom_divisor; | ||
247 | int close_delay; | ||
248 | unsigned short closing_wait; | ||
249 | unsigned char err_shadow; | ||
318 | unsigned long event; | 250 | unsigned long event; |
251 | |||
319 | int count; /* # of fd on device */ | 252 | int count; /* # of fd on device */ |
320 | int blocked_open; /* # of blocked opens */ | 253 | int blocked_open; /* # of blocked opens */ |
254 | struct async_icount icount; /* kernel counters for 4 input interrupts */ | ||
255 | int timeout; | ||
256 | |||
257 | int read_status_mask; | ||
258 | int ignore_status_mask; | ||
259 | int xmit_fifo_size; | ||
321 | unsigned char *xmit_buf; | 260 | unsigned char *xmit_buf; |
322 | int xmit_head; | 261 | int xmit_head; |
323 | int xmit_tail; | 262 | int xmit_tail; |
324 | int xmit_cnt; | 263 | int xmit_cnt; |
325 | struct work_struct tqueue; | 264 | |
326 | struct ktermios normal_termios; | 265 | struct ktermios normal_termios; |
327 | struct ktermios callout_termios; | 266 | |
328 | wait_queue_head_t open_wait; | ||
329 | wait_queue_head_t close_wait; | ||
330 | wait_queue_head_t delta_msr_wait; | ||
331 | struct async_icount icount; /* kernel counters for the 4 input interrupts */ | ||
332 | int timeout; | ||
333 | int IsMoxaMustChipFlag; /* add by Victor Yu. 08-30-2002 */ | ||
334 | int MaxCanSetBaudRate; /* add by Victor Yu. 09-04-2002 */ | ||
335 | int opmode_ioaddr; /* add by Victor Yu. 01-05-2004 */ | ||
336 | unsigned char stop_rx; | ||
337 | unsigned char ldisc_stop_rx; | ||
338 | long realbaud; | ||
339 | struct mxser_mon mon_data; | 267 | struct mxser_mon mon_data; |
340 | unsigned char err_shadow; | 268 | |
341 | spinlock_t slock; | 269 | spinlock_t slock; |
270 | wait_queue_head_t open_wait; | ||
271 | wait_queue_head_t delta_msr_wait; | ||
272 | }; | ||
273 | |||
274 | struct mxser_board { | ||
275 | unsigned int idx; | ||
276 | int irq; | ||
277 | const struct mxser_cardinfo *info; | ||
278 | unsigned long vector; | ||
279 | unsigned long vector_mask; | ||
280 | |||
281 | int chip_flag; | ||
282 | int uart_type; | ||
283 | |||
284 | struct mxser_port ports[MXSER_PORTS_PER_BOARD]; | ||
342 | }; | 285 | }; |
343 | 286 | ||
344 | struct mxser_mstatus { | 287 | struct mxser_mstatus { |
@@ -356,73 +299,16 @@ static int mxserBoardCAP[MXSER_BOARDS] = { | |||
356 | /* 0x180, 0x280, 0x200, 0x320 */ | 299 | /* 0x180, 0x280, 0x200, 0x320 */ |
357 | }; | 300 | }; |
358 | 301 | ||
302 | static struct mxser_board mxser_boards[MXSER_BOARDS]; | ||
359 | static struct tty_driver *mxvar_sdriver; | 303 | static struct tty_driver *mxvar_sdriver; |
360 | static struct mxser_struct mxvar_table[MXSER_PORTS]; | ||
361 | static struct tty_struct *mxvar_tty[MXSER_PORTS + 1]; | ||
362 | static struct ktermios *mxvar_termios[MXSER_PORTS + 1]; | ||
363 | static struct ktermios *mxvar_termios_locked[MXSER_PORTS + 1]; | ||
364 | static struct mxser_log mxvar_log; | 304 | static struct mxser_log mxvar_log; |
365 | static int mxvar_diagflag; | 305 | static int mxvar_diagflag; |
366 | static unsigned char mxser_msr[MXSER_PORTS + 1]; | 306 | static unsigned char mxser_msr[MXSER_PORTS + 1]; |
367 | static struct mxser_mon_ext mon_data_ext; | 307 | static struct mxser_mon_ext mon_data_ext; |
368 | static int mxser_set_baud_method[MXSER_PORTS + 1]; | 308 | static int mxser_set_baud_method[MXSER_PORTS + 1]; |
369 | static spinlock_t gm_lock; | ||
370 | |||
371 | /* | ||
372 | * This is used to figure out the divisor speeds and the timeouts | ||
373 | */ | ||
374 | |||
375 | static struct mxser_hwconf mxsercfg[MXSER_BOARDS]; | ||
376 | |||
377 | /* | ||
378 | * static functions: | ||
379 | */ | ||
380 | |||
381 | static void mxser_getcfg(int board, struct mxser_hwconf *hwconf); | ||
382 | static int mxser_init(void); | ||
383 | |||
384 | /* static void mxser_poll(unsigned long); */ | ||
385 | static int mxser_get_ISA_conf(int, struct mxser_hwconf *); | ||
386 | static void mxser_do_softint(struct work_struct *); | ||
387 | static int mxser_open(struct tty_struct *, struct file *); | ||
388 | static void mxser_close(struct tty_struct *, struct file *); | ||
389 | static int mxser_write(struct tty_struct *, const unsigned char *, int); | ||
390 | static int mxser_write_room(struct tty_struct *); | ||
391 | static void mxser_flush_buffer(struct tty_struct *); | ||
392 | static int mxser_chars_in_buffer(struct tty_struct *); | ||
393 | static void mxser_flush_chars(struct tty_struct *); | ||
394 | static void mxser_put_char(struct tty_struct *, unsigned char); | ||
395 | static int mxser_ioctl(struct tty_struct *, struct file *, uint, ulong); | ||
396 | static int mxser_ioctl_special(unsigned int, void __user *); | ||
397 | static void mxser_throttle(struct tty_struct *); | ||
398 | static void mxser_unthrottle(struct tty_struct *); | ||
399 | static void mxser_set_termios(struct tty_struct *, struct ktermios *); | ||
400 | static void mxser_stop(struct tty_struct *); | ||
401 | static void mxser_start(struct tty_struct *); | ||
402 | static void mxser_hangup(struct tty_struct *); | ||
403 | static void mxser_rs_break(struct tty_struct *, int); | ||
404 | static irqreturn_t mxser_interrupt(int, void *); | ||
405 | static void mxser_receive_chars(struct mxser_struct *, int *); | ||
406 | static void mxser_transmit_chars(struct mxser_struct *); | ||
407 | static void mxser_check_modem_status(struct mxser_struct *, int); | ||
408 | static int mxser_block_til_ready(struct tty_struct *, struct file *, struct mxser_struct *); | ||
409 | static int mxser_startup(struct mxser_struct *); | ||
410 | static void mxser_shutdown(struct mxser_struct *); | ||
411 | static int mxser_change_speed(struct mxser_struct *, struct ktermios *old_termios); | ||
412 | static int mxser_get_serial_info(struct mxser_struct *, struct serial_struct __user *); | ||
413 | static int mxser_set_serial_info(struct mxser_struct *, struct serial_struct __user *); | ||
414 | static int mxser_get_lsr_info(struct mxser_struct *, unsigned int __user *); | ||
415 | static void mxser_send_break(struct mxser_struct *, int); | ||
416 | static int mxser_tiocmget(struct tty_struct *, struct file *); | ||
417 | static int mxser_tiocmset(struct tty_struct *, struct file *, unsigned int, unsigned int); | ||
418 | static int mxser_set_baud(struct mxser_struct *info, long newspd); | ||
419 | static void mxser_wait_until_sent(struct tty_struct *tty, int timeout); | ||
420 | |||
421 | static void mxser_startrx(struct tty_struct *tty); | ||
422 | static void mxser_stoprx(struct tty_struct *tty); | ||
423 | 309 | ||
424 | #ifdef CONFIG_PCI | 310 | #ifdef CONFIG_PCI |
425 | static int CheckIsMoxaMust(int io) | 311 | static int __devinit CheckIsMoxaMust(unsigned long io) |
426 | { | 312 | { |
427 | u8 oldmcr, hwid; | 313 | u8 oldmcr, hwid; |
428 | int i; | 314 | int i; |
@@ -438,90 +324,15 @@ static int CheckIsMoxaMust(int io) | |||
438 | } | 324 | } |
439 | 325 | ||
440 | GET_MOXA_MUST_HARDWARE_ID(io, &hwid); | 326 | GET_MOXA_MUST_HARDWARE_ID(io, &hwid); |
441 | for (i = 0; i < UART_TYPE_NUM; i++) { | 327 | for (i = 1; i < UART_INFO_NUM; i++) { /* 0 = OTHER_UART */ |
442 | if (hwid == Gmoxa_uart_id[i]) | 328 | if (hwid == Gpci_uart_info[i].type) |
443 | return (int)hwid; | 329 | return (int)hwid; |
444 | } | 330 | } |
445 | return MOXA_OTHER_UART; | 331 | return MOXA_OTHER_UART; |
446 | } | 332 | } |
447 | #endif | 333 | #endif |
448 | 334 | ||
449 | /* above is modified by Victor Yu. 08-15-2002 */ | 335 | static void process_txrx_fifo(struct mxser_port *info) |
450 | |||
451 | static const struct tty_operations mxser_ops = { | ||
452 | .open = mxser_open, | ||
453 | .close = mxser_close, | ||
454 | .write = mxser_write, | ||
455 | .put_char = mxser_put_char, | ||
456 | .flush_chars = mxser_flush_chars, | ||
457 | .write_room = mxser_write_room, | ||
458 | .chars_in_buffer = mxser_chars_in_buffer, | ||
459 | .flush_buffer = mxser_flush_buffer, | ||
460 | .ioctl = mxser_ioctl, | ||
461 | .throttle = mxser_throttle, | ||
462 | .unthrottle = mxser_unthrottle, | ||
463 | .set_termios = mxser_set_termios, | ||
464 | .stop = mxser_stop, | ||
465 | .start = mxser_start, | ||
466 | .hangup = mxser_hangup, | ||
467 | .break_ctl = mxser_rs_break, | ||
468 | .wait_until_sent = mxser_wait_until_sent, | ||
469 | .tiocmget = mxser_tiocmget, | ||
470 | .tiocmset = mxser_tiocmset, | ||
471 | }; | ||
472 | |||
473 | /* | ||
474 | * The MOXA Smartio/Industio serial driver boot-time initialization code! | ||
475 | */ | ||
476 | |||
477 | static int __init mxser_module_init(void) | ||
478 | { | ||
479 | int ret; | ||
480 | |||
481 | if (verbose) | ||
482 | printk(KERN_DEBUG "Loading module mxser ...\n"); | ||
483 | ret = mxser_init(); | ||
484 | if (verbose) | ||
485 | printk(KERN_DEBUG "Done.\n"); | ||
486 | return ret; | ||
487 | } | ||
488 | |||
489 | static void __exit mxser_module_exit(void) | ||
490 | { | ||
491 | int i, err; | ||
492 | |||
493 | if (verbose) | ||
494 | printk(KERN_DEBUG "Unloading module mxser ...\n"); | ||
495 | |||
496 | err = tty_unregister_driver(mxvar_sdriver); | ||
497 | if (!err) | ||
498 | put_tty_driver(mxvar_sdriver); | ||
499 | else | ||
500 | printk(KERN_ERR "Couldn't unregister MOXA Smartio/Industio family serial driver\n"); | ||
501 | |||
502 | for (i = 0; i < MXSER_BOARDS; i++) { | ||
503 | struct pci_dev *pdev; | ||
504 | |||
505 | if (mxsercfg[i].board_type == -1) | ||
506 | continue; | ||
507 | else { | ||
508 | pdev = mxsercfg[i].pciInfo.pdev; | ||
509 | free_irq(mxsercfg[i].irq, &mxvar_table[i * MXSER_PORTS_PER_BOARD]); | ||
510 | if (pdev != NULL) { /* PCI */ | ||
511 | release_region(pci_resource_start(pdev, 2), pci_resource_len(pdev, 2)); | ||
512 | release_region(pci_resource_start(pdev, 3), pci_resource_len(pdev, 3)); | ||
513 | pci_dev_put(pdev); | ||
514 | } else { | ||
515 | release_region(mxsercfg[i].ioaddr[0], 8 * mxsercfg[i].ports); | ||
516 | release_region(mxsercfg[i].vector, 1); | ||
517 | } | ||
518 | } | ||
519 | } | ||
520 | if (verbose) | ||
521 | printk(KERN_DEBUG "Done.\n"); | ||
522 | } | ||
523 | |||
524 | static void process_txrx_fifo(struct mxser_struct *info) | ||
525 | { | 336 | { |
526 | int i; | 337 | int i; |
527 | 338 | ||
@@ -530,424 +341,548 @@ static void process_txrx_fifo(struct mxser_struct *info) | |||
530 | info->rx_high_water = 1; | 341 | info->rx_high_water = 1; |
531 | info->rx_low_water = 1; | 342 | info->rx_low_water = 1; |
532 | info->xmit_fifo_size = 1; | 343 | info->xmit_fifo_size = 1; |
533 | } else { | 344 | } else |
534 | for (i = 0; i < UART_INFO_NUM; i++) { | 345 | for (i = 0; i < UART_INFO_NUM; i++) |
535 | if (info->IsMoxaMustChipFlag == Gpci_uart_info[i].type) { | 346 | if (info->board->chip_flag == Gpci_uart_info[i].type) { |
536 | info->rx_trigger = Gpci_uart_info[i].rx_trigger; | 347 | info->rx_trigger = Gpci_uart_info[i].rx_trigger; |
537 | info->rx_low_water = Gpci_uart_info[i].rx_low_water; | 348 | info->rx_low_water = Gpci_uart_info[i].rx_low_water; |
538 | info->rx_high_water = Gpci_uart_info[i].rx_high_water; | 349 | info->rx_high_water = Gpci_uart_info[i].rx_high_water; |
539 | info->xmit_fifo_size = Gpci_uart_info[i].xmit_fifo_size; | 350 | info->xmit_fifo_size = Gpci_uart_info[i].xmit_fifo_size; |
540 | break; | 351 | break; |
541 | } | 352 | } |
542 | } | ||
543 | } | ||
544 | } | 353 | } |
545 | 354 | ||
546 | static int mxser_initbrd(int board, struct mxser_hwconf *hwconf) | 355 | static unsigned char mxser_get_msr(int baseaddr, int mode, int port) |
547 | { | 356 | { |
548 | struct mxser_struct *info; | 357 | unsigned char status = 0; |
549 | int retval; | ||
550 | int i, n; | ||
551 | 358 | ||
552 | n = board * MXSER_PORTS_PER_BOARD; | 359 | status = inb(baseaddr + UART_MSR); |
553 | info = &mxvar_table[n]; | ||
554 | /*if (verbose) */ { | ||
555 | printk(KERN_DEBUG " ttyMI%d - ttyMI%d ", | ||
556 | n, n + hwconf->ports - 1); | ||
557 | printk(" max. baud rate = %d bps.\n", | ||
558 | hwconf->MaxCanSetBaudRate[0]); | ||
559 | } | ||
560 | |||
561 | for (i = 0; i < hwconf->ports; i++, n++, info++) { | ||
562 | info->port = n; | ||
563 | info->base = hwconf->ioaddr[i]; | ||
564 | info->irq = hwconf->irq; | ||
565 | info->vector = hwconf->vector; | ||
566 | info->vectormask = hwconf->vector_mask; | ||
567 | info->opmode_ioaddr = hwconf->opmode_ioaddr[i]; /* add by Victor Yu. 01-05-2004 */ | ||
568 | info->stop_rx = 0; | ||
569 | info->ldisc_stop_rx = 0; | ||
570 | 360 | ||
571 | info->IsMoxaMustChipFlag = hwconf->IsMoxaMustChipFlag; | 361 | mxser_msr[port] &= 0x0F; |
572 | /* Enhance mode enabled here */ | 362 | mxser_msr[port] |= status; |
573 | if (info->IsMoxaMustChipFlag != MOXA_OTHER_UART) { | 363 | status = mxser_msr[port]; |
574 | ENABLE_MOXA_MUST_ENCHANCE_MODE(info->base); | 364 | if (mode) |
575 | } | 365 | mxser_msr[port] = 0; |
576 | 366 | ||
577 | info->flags = ASYNC_SHARE_IRQ; | 367 | return status; |
578 | info->type = hwconf->uart_type; | 368 | } |
579 | info->baud_base = hwconf->baud_base[i]; | ||
580 | 369 | ||
581 | info->MaxCanSetBaudRate = hwconf->MaxCanSetBaudRate[i]; | 370 | static int mxser_block_til_ready(struct tty_struct *tty, struct file *filp, |
371 | struct mxser_port *port) | ||
372 | { | ||
373 | DECLARE_WAITQUEUE(wait, current); | ||
374 | int retval; | ||
375 | int do_clocal = 0; | ||
376 | unsigned long flags; | ||
582 | 377 | ||
583 | process_txrx_fifo(info); | 378 | /* |
379 | * If non-blocking mode is set, or the port is not enabled, | ||
380 | * then make the check up front and then exit. | ||
381 | */ | ||
382 | if ((filp->f_flags & O_NONBLOCK) || | ||
383 | test_bit(TTY_IO_ERROR, &tty->flags)) { | ||
384 | port->flags |= ASYNC_NORMAL_ACTIVE; | ||
385 | return 0; | ||
386 | } | ||
584 | 387 | ||
388 | if (tty->termios->c_cflag & CLOCAL) | ||
389 | do_clocal = 1; | ||
585 | 390 | ||
586 | info->custom_divisor = hwconf->baud_base[i] * 16; | ||
587 | info->close_delay = 5 * HZ / 10; | ||
588 | info->closing_wait = 30 * HZ; | ||
589 | INIT_WORK(&info->tqueue, mxser_do_softint); | ||
590 | info->normal_termios = mxvar_sdriver->init_termios; | ||
591 | init_waitqueue_head(&info->open_wait); | ||
592 | init_waitqueue_head(&info->close_wait); | ||
593 | init_waitqueue_head(&info->delta_msr_wait); | ||
594 | memset(&info->mon_data, 0, sizeof(struct mxser_mon)); | ||
595 | info->err_shadow = 0; | ||
596 | spin_lock_init(&info->slock); | ||
597 | } | ||
598 | /* | 391 | /* |
599 | * Allocate the IRQ if necessary | 392 | * Block waiting for the carrier detect and the line to become |
393 | * free (i.e., not in use by the callout). While we are in | ||
394 | * this loop, port->count is dropped by one, so that | ||
395 | * mxser_close() knows when to free things. We restore it upon | ||
396 | * exit, either normal or abnormal. | ||
600 | */ | 397 | */ |
398 | retval = 0; | ||
399 | add_wait_queue(&port->open_wait, &wait); | ||
601 | 400 | ||
602 | 401 | spin_lock_irqsave(&port->slock, flags); | |
603 | /* before set INT ISR, disable all int */ | 402 | if (!tty_hung_up_p(filp)) |
604 | for (i = 0; i < hwconf->ports; i++) { | 403 | port->count--; |
605 | outb(inb(hwconf->ioaddr[i] + UART_IER) & 0xf0, | 404 | spin_unlock_irqrestore(&port->slock, flags); |
606 | hwconf->ioaddr[i] + UART_IER); | 405 | port->blocked_open++; |
406 | while (1) { | ||
407 | spin_lock_irqsave(&port->slock, flags); | ||
408 | outb(inb(port->ioaddr + UART_MCR) | | ||
409 | UART_MCR_DTR | UART_MCR_RTS, port->ioaddr + UART_MCR); | ||
410 | spin_unlock_irqrestore(&port->slock, flags); | ||
411 | set_current_state(TASK_INTERRUPTIBLE); | ||
412 | if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)) { | ||
413 | if (port->flags & ASYNC_HUP_NOTIFY) | ||
414 | retval = -EAGAIN; | ||
415 | else | ||
416 | retval = -ERESTARTSYS; | ||
417 | break; | ||
418 | } | ||
419 | if (!(port->flags & ASYNC_CLOSING) && | ||
420 | (do_clocal || | ||
421 | (inb(port->ioaddr + UART_MSR) & UART_MSR_DCD))) | ||
422 | break; | ||
423 | if (signal_pending(current)) { | ||
424 | retval = -ERESTARTSYS; | ||
425 | break; | ||
426 | } | ||
427 | schedule(); | ||
607 | } | 428 | } |
608 | 429 | set_current_state(TASK_RUNNING); | |
609 | n = board * MXSER_PORTS_PER_BOARD; | 430 | remove_wait_queue(&port->open_wait, &wait); |
610 | info = &mxvar_table[n]; | 431 | if (!tty_hung_up_p(filp)) |
611 | 432 | port->count++; | |
612 | retval = request_irq(hwconf->irq, mxser_interrupt, IRQ_T(info), | 433 | port->blocked_open--; |
613 | "mxser", info); | 434 | if (retval) |
614 | if (retval) { | ||
615 | printk(KERN_ERR "Board %d: %s", | ||
616 | board, mxser_brdname[hwconf->board_type - 1]); | ||
617 | printk(" Request irq failed, IRQ (%d) may conflict with" | ||
618 | " another device.\n", info->irq); | ||
619 | return retval; | 435 | return retval; |
620 | } | 436 | port->flags |= ASYNC_NORMAL_ACTIVE; |
621 | return 0; | 437 | return 0; |
622 | } | 438 | } |
623 | 439 | ||
624 | static void mxser_getcfg(int board, struct mxser_hwconf *hwconf) | 440 | static int mxser_set_baud(struct mxser_port *info, long newspd) |
625 | { | 441 | { |
626 | mxsercfg[board] = *hwconf; | 442 | int quot = 0, baud; |
627 | } | 443 | unsigned char cval; |
628 | 444 | ||
629 | #ifdef CONFIG_PCI | 445 | if (!info->tty || !info->tty->termios) |
630 | static int mxser_get_PCI_conf(int busnum, int devnum, int board_type, struct mxser_hwconf *hwconf) | 446 | return -1; |
631 | { | ||
632 | int i, j; | ||
633 | /* unsigned int val; */ | ||
634 | unsigned int ioaddress; | ||
635 | struct pci_dev *pdev = hwconf->pciInfo.pdev; | ||
636 | 447 | ||
637 | /* io address */ | 448 | if (!(info->ioaddr)) |
638 | hwconf->board_type = board_type; | 449 | return -1; |
639 | hwconf->ports = mxser_numports[board_type - 1]; | ||
640 | ioaddress = pci_resource_start(pdev, 2); | ||
641 | request_region(pci_resource_start(pdev, 2), pci_resource_len(pdev, 2), | ||
642 | "mxser(IO)"); | ||
643 | 450 | ||
644 | for (i = 0; i < hwconf->ports; i++) | 451 | if (newspd > info->max_baud) |
645 | hwconf->ioaddr[i] = ioaddress + 8 * i; | 452 | return -1; |
646 | 453 | ||
647 | /* vector */ | 454 | if (newspd == 134) { |
648 | ioaddress = pci_resource_start(pdev, 3); | 455 | quot = 2 * info->baud_base / 269; |
649 | request_region(pci_resource_start(pdev, 3), pci_resource_len(pdev, 3), | 456 | tty_encode_baud_rate(info->tty, 134, 134); |
650 | "mxser(vector)"); | 457 | } else if (newspd) { |
651 | hwconf->vector = ioaddress; | 458 | quot = info->baud_base / newspd; |
459 | if (quot == 0) | ||
460 | quot = 1; | ||
461 | baud = info->baud_base/quot; | ||
462 | tty_encode_baud_rate(info->tty, baud, baud); | ||
463 | } else { | ||
464 | quot = 0; | ||
465 | } | ||
652 | 466 | ||
653 | /* irq */ | 467 | info->timeout = ((info->xmit_fifo_size * HZ * 10 * quot) / info->baud_base); |
654 | hwconf->irq = hwconf->pciInfo.pdev->irq; | 468 | info->timeout += HZ / 50; /* Add .02 seconds of slop */ |
655 | 469 | ||
656 | hwconf->IsMoxaMustChipFlag = CheckIsMoxaMust(hwconf->ioaddr[0]); | 470 | if (quot) { |
657 | hwconf->uart_type = PORT_16550A; | 471 | info->MCR |= UART_MCR_DTR; |
658 | hwconf->vector_mask = 0; | 472 | outb(info->MCR, info->ioaddr + UART_MCR); |
473 | } else { | ||
474 | info->MCR &= ~UART_MCR_DTR; | ||
475 | outb(info->MCR, info->ioaddr + UART_MCR); | ||
476 | return 0; | ||
477 | } | ||
659 | 478 | ||
479 | cval = inb(info->ioaddr + UART_LCR); | ||
660 | 480 | ||
661 | for (i = 0; i < hwconf->ports; i++) { | 481 | outb(cval | UART_LCR_DLAB, info->ioaddr + UART_LCR); /* set DLAB */ |
662 | for (j = 0; j < UART_INFO_NUM; j++) { | ||
663 | if (Gpci_uart_info[j].type == hwconf->IsMoxaMustChipFlag) { | ||
664 | hwconf->MaxCanSetBaudRate[i] = Gpci_uart_info[j].max_baud; | ||
665 | 482 | ||
666 | /* exception....CP-102 */ | 483 | outb(quot & 0xff, info->ioaddr + UART_DLL); /* LS of divisor */ |
667 | if (board_type == MXSER_BOARD_CP102) | 484 | outb(quot >> 8, info->ioaddr + UART_DLM); /* MS of divisor */ |
668 | hwconf->MaxCanSetBaudRate[i] = 921600; | 485 | outb(cval, info->ioaddr + UART_LCR); /* reset DLAB */ |
669 | break; | ||
670 | } | ||
671 | } | ||
672 | } | ||
673 | 486 | ||
674 | if (hwconf->IsMoxaMustChipFlag == MOXA_MUST_MU860_HWID) { | 487 | #ifdef BOTHER |
675 | for (i = 0; i < hwconf->ports; i++) { | 488 | if (C_BAUD(info->tty) == BOTHER) { |
676 | if (i < 4) | 489 | quot = info->baud_base % newspd; |
677 | hwconf->opmode_ioaddr[i] = ioaddress + 4; | 490 | quot *= 8; |
678 | else | 491 | if (quot % newspd > newspd / 2) { |
679 | hwconf->opmode_ioaddr[i] = ioaddress + 0x0c; | 492 | quot /= newspd; |
680 | } | 493 | quot++; |
681 | outb(0, ioaddress + 4); /* default set to RS232 mode */ | 494 | } else |
682 | outb(0, ioaddress + 0x0c); /* default set to RS232 mode */ | 495 | quot /= newspd; |
683 | } | 496 | |
497 | SET_MOXA_MUST_ENUM_VALUE(info->ioaddr, quot); | ||
498 | } else | ||
499 | #endif | ||
500 | SET_MOXA_MUST_ENUM_VALUE(info->ioaddr, 0); | ||
684 | 501 | ||
685 | for (i = 0; i < hwconf->ports; i++) { | ||
686 | hwconf->vector_mask |= (1 << i); | ||
687 | hwconf->baud_base[i] = 921600; | ||
688 | } | ||
689 | return 0; | 502 | return 0; |
690 | } | 503 | } |
691 | #endif | ||
692 | 504 | ||
693 | static int mxser_init(void) | 505 | /* |
506 | * This routine is called to set the UART divisor registers to match | ||
507 | * the specified baud rate for a serial port. | ||
508 | */ | ||
509 | static int mxser_change_speed(struct mxser_port *info, | ||
510 | struct ktermios *old_termios) | ||
694 | { | 511 | { |
695 | int i, m, retval, b, n; | 512 | unsigned cflag, cval, fcr; |
696 | struct pci_dev *pdev = NULL; | 513 | int ret = 0; |
697 | int index; | 514 | unsigned char status; |
698 | unsigned char busnum, devnum; | ||
699 | struct mxser_hwconf hwconf; | ||
700 | |||
701 | mxvar_sdriver = alloc_tty_driver(MXSER_PORTS + 1); | ||
702 | if (!mxvar_sdriver) | ||
703 | return -ENOMEM; | ||
704 | spin_lock_init(&gm_lock); | ||
705 | |||
706 | for (i = 0; i < MXSER_BOARDS; i++) { | ||
707 | mxsercfg[i].board_type = -1; | ||
708 | } | ||
709 | 515 | ||
710 | printk(KERN_INFO "MOXA Smartio/Industio family driver version %s\n", | 516 | if (!info->tty || !info->tty->termios) |
711 | MXSER_VERSION); | 517 | return ret; |
518 | cflag = info->tty->termios->c_cflag; | ||
519 | if (!(info->ioaddr)) | ||
520 | return ret; | ||
712 | 521 | ||
713 | /* Initialize the tty_driver structure */ | 522 | if (mxser_set_baud_method[info->tty->index] == 0) |
714 | memset(mxvar_sdriver, 0, sizeof(struct tty_driver)); | 523 | mxser_set_baud(info, tty_get_baud_rate(info->tty)); |
715 | mxvar_sdriver->owner = THIS_MODULE; | ||
716 | mxvar_sdriver->magic = TTY_DRIVER_MAGIC; | ||
717 | mxvar_sdriver->name = "ttyMI"; | ||
718 | mxvar_sdriver->major = ttymajor; | ||
719 | mxvar_sdriver->minor_start = 0; | ||
720 | mxvar_sdriver->num = MXSER_PORTS + 1; | ||
721 | mxvar_sdriver->type = TTY_DRIVER_TYPE_SERIAL; | ||
722 | mxvar_sdriver->subtype = SERIAL_TYPE_NORMAL; | ||
723 | mxvar_sdriver->init_termios = tty_std_termios; | ||
724 | mxvar_sdriver->init_termios.c_cflag = B9600|CS8|CREAD|HUPCL|CLOCAL; | ||
725 | mxvar_sdriver->init_termios.c_ispeed = 9600; | ||
726 | mxvar_sdriver->init_termios.c_ospeed = 9600; | ||
727 | mxvar_sdriver->flags = TTY_DRIVER_REAL_RAW; | ||
728 | tty_set_operations(mxvar_sdriver, &mxser_ops); | ||
729 | mxvar_sdriver->ttys = mxvar_tty; | ||
730 | mxvar_sdriver->termios = mxvar_termios; | ||
731 | mxvar_sdriver->termios_locked = mxvar_termios_locked; | ||
732 | 524 | ||
733 | mxvar_diagflag = 0; | 525 | /* byte size and parity */ |
734 | memset(mxvar_table, 0, MXSER_PORTS * sizeof(struct mxser_struct)); | 526 | switch (cflag & CSIZE) { |
735 | memset(&mxvar_log, 0, sizeof(struct mxser_log)); | 527 | case CS5: |
528 | cval = 0x00; | ||
529 | break; | ||
530 | case CS6: | ||
531 | cval = 0x01; | ||
532 | break; | ||
533 | case CS7: | ||
534 | cval = 0x02; | ||
535 | break; | ||
536 | case CS8: | ||
537 | cval = 0x03; | ||
538 | break; | ||
539 | default: | ||
540 | cval = 0x00; | ||
541 | break; /* too keep GCC shut... */ | ||
542 | } | ||
543 | if (cflag & CSTOPB) | ||
544 | cval |= 0x04; | ||
545 | if (cflag & PARENB) | ||
546 | cval |= UART_LCR_PARITY; | ||
547 | if (!(cflag & PARODD)) | ||
548 | cval |= UART_LCR_EPAR; | ||
549 | if (cflag & CMSPAR) | ||
550 | cval |= UART_LCR_SPAR; | ||
736 | 551 | ||
737 | memset(&mxser_msr, 0, sizeof(unsigned char) * (MXSER_PORTS + 1)); | 552 | if ((info->type == PORT_8250) || (info->type == PORT_16450)) { |
738 | memset(&mon_data_ext, 0, sizeof(struct mxser_mon_ext)); | 553 | if (info->board->chip_flag) { |
739 | memset(&mxser_set_baud_method, 0, sizeof(int) * (MXSER_PORTS + 1)); | 554 | fcr = UART_FCR_ENABLE_FIFO; |
740 | memset(&hwconf, 0, sizeof(struct mxser_hwconf)); | 555 | fcr |= MOXA_MUST_FCR_GDA_MODE_ENABLE; |
556 | SET_MOXA_MUST_FIFO_VALUE(info); | ||
557 | } else | ||
558 | fcr = 0; | ||
559 | } else { | ||
560 | fcr = UART_FCR_ENABLE_FIFO; | ||
561 | if (info->board->chip_flag) { | ||
562 | fcr |= MOXA_MUST_FCR_GDA_MODE_ENABLE; | ||
563 | SET_MOXA_MUST_FIFO_VALUE(info); | ||
564 | } else { | ||
565 | switch (info->rx_trigger) { | ||
566 | case 1: | ||
567 | fcr |= UART_FCR_TRIGGER_1; | ||
568 | break; | ||
569 | case 4: | ||
570 | fcr |= UART_FCR_TRIGGER_4; | ||
571 | break; | ||
572 | case 8: | ||
573 | fcr |= UART_FCR_TRIGGER_8; | ||
574 | break; | ||
575 | default: | ||
576 | fcr |= UART_FCR_TRIGGER_14; | ||
577 | break; | ||
578 | } | ||
579 | } | ||
580 | } | ||
741 | 581 | ||
742 | m = 0; | 582 | /* CTS flow control flag and modem status interrupts */ |
743 | /* Start finding ISA boards here */ | 583 | info->IER &= ~UART_IER_MSI; |
744 | for (b = 0; b < MXSER_BOARDS && m < MXSER_BOARDS; b++) { | 584 | info->MCR &= ~UART_MCR_AFE; |
745 | int cap; | 585 | if (cflag & CRTSCTS) { |
746 | 586 | info->flags |= ASYNC_CTS_FLOW; | |
747 | if (!(cap = mxserBoardCAP[b])) | 587 | info->IER |= UART_IER_MSI; |
748 | continue; | 588 | if ((info->type == PORT_16550A) || (info->board->chip_flag)) { |
749 | 589 | info->MCR |= UART_MCR_AFE; | |
750 | retval = mxser_get_ISA_conf(cap, &hwconf); | 590 | } else { |
751 | 591 | status = inb(info->ioaddr + UART_MSR); | |
752 | if (retval != 0) | 592 | if (info->tty->hw_stopped) { |
753 | printk(KERN_INFO "Found MOXA %s board (CAP=0x%x)\n", | 593 | if (status & UART_MSR_CTS) { |
754 | mxser_brdname[hwconf.board_type - 1], ioaddr[b]); | 594 | info->tty->hw_stopped = 0; |
755 | 595 | if (info->type != PORT_16550A && | |
756 | if (retval <= 0) { | 596 | !info->board->chip_flag) { |
757 | if (retval == MXSER_ERR_IRQ) | 597 | outb(info->IER & ~UART_IER_THRI, |
758 | printk(KERN_ERR "Invalid interrupt number, " | 598 | info->ioaddr + |
759 | "board not configured\n"); | 599 | UART_IER); |
760 | else if (retval == MXSER_ERR_IRQ_CONFLIT) | 600 | info->IER |= UART_IER_THRI; |
761 | printk(KERN_ERR "Invalid interrupt number, " | 601 | outb(info->IER, info->ioaddr + |
762 | "board not configured\n"); | 602 | UART_IER); |
763 | else if (retval == MXSER_ERR_VECTOR) | 603 | } |
764 | printk(KERN_ERR "Invalid interrupt vector, " | 604 | tty_wakeup(info->tty); |
765 | "board not configured\n"); | 605 | } |
766 | else if (retval == MXSER_ERR_IOADDR) | 606 | } else { |
767 | printk(KERN_ERR "Invalid I/O address, " | 607 | if (!(status & UART_MSR_CTS)) { |
768 | "board not configured\n"); | 608 | info->tty->hw_stopped = 1; |
769 | 609 | if ((info->type != PORT_16550A) && | |
770 | continue; | 610 | (!info->board->chip_flag)) { |
611 | info->IER &= ~UART_IER_THRI; | ||
612 | outb(info->IER, info->ioaddr + | ||
613 | UART_IER); | ||
614 | } | ||
615 | } | ||
616 | } | ||
771 | } | 617 | } |
618 | } else { | ||
619 | info->flags &= ~ASYNC_CTS_FLOW; | ||
620 | } | ||
621 | outb(info->MCR, info->ioaddr + UART_MCR); | ||
622 | if (cflag & CLOCAL) { | ||
623 | info->flags &= ~ASYNC_CHECK_CD; | ||
624 | } else { | ||
625 | info->flags |= ASYNC_CHECK_CD; | ||
626 | info->IER |= UART_IER_MSI; | ||
627 | } | ||
628 | outb(info->IER, info->ioaddr + UART_IER); | ||
772 | 629 | ||
773 | hwconf.pciInfo.busNum = 0; | 630 | /* |
774 | hwconf.pciInfo.devNum = 0; | 631 | * Set up parity check flag |
775 | hwconf.pciInfo.pdev = NULL; | 632 | */ |
633 | info->read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR; | ||
634 | if (I_INPCK(info->tty)) | ||
635 | info->read_status_mask |= UART_LSR_FE | UART_LSR_PE; | ||
636 | if (I_BRKINT(info->tty) || I_PARMRK(info->tty)) | ||
637 | info->read_status_mask |= UART_LSR_BI; | ||
638 | |||
639 | info->ignore_status_mask = 0; | ||
776 | 640 | ||
777 | mxser_getcfg(m, &hwconf); | 641 | if (I_IGNBRK(info->tty)) { |
642 | info->ignore_status_mask |= UART_LSR_BI; | ||
643 | info->read_status_mask |= UART_LSR_BI; | ||
778 | /* | 644 | /* |
779 | * init mxsercfg first, | 645 | * If we're ignore parity and break indicators, ignore |
780 | * or mxsercfg data is not correct on ISR. | 646 | * overruns too. (For real raw support). |
781 | */ | 647 | */ |
782 | /* mxser_initbrd will hook ISR. */ | 648 | if (I_IGNPAR(info->tty)) { |
783 | if (mxser_initbrd(m, &hwconf) < 0) | 649 | info->ignore_status_mask |= |
784 | continue; | 650 | UART_LSR_OE | |
785 | 651 | UART_LSR_PE | | |
786 | m++; | 652 | UART_LSR_FE; |
653 | info->read_status_mask |= | ||
654 | UART_LSR_OE | | ||
655 | UART_LSR_PE | | ||
656 | UART_LSR_FE; | ||
657 | } | ||
658 | } | ||
659 | if (info->board->chip_flag) { | ||
660 | SET_MOXA_MUST_XON1_VALUE(info->ioaddr, START_CHAR(info->tty)); | ||
661 | SET_MOXA_MUST_XOFF1_VALUE(info->ioaddr, STOP_CHAR(info->tty)); | ||
662 | if (I_IXON(info->tty)) { | ||
663 | ENABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(info->ioaddr); | ||
664 | } else { | ||
665 | DISABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(info->ioaddr); | ||
666 | } | ||
667 | if (I_IXOFF(info->tty)) { | ||
668 | ENABLE_MOXA_MUST_TX_SOFTWARE_FLOW_CONTROL(info->ioaddr); | ||
669 | } else { | ||
670 | DISABLE_MOXA_MUST_TX_SOFTWARE_FLOW_CONTROL(info->ioaddr); | ||
671 | } | ||
787 | } | 672 | } |
788 | 673 | ||
789 | /* Start finding ISA boards from module arg */ | ||
790 | for (b = 0; b < MXSER_BOARDS && m < MXSER_BOARDS; b++) { | ||
791 | int cap; | ||
792 | 674 | ||
793 | if (!(cap = ioaddr[b])) | 675 | outb(fcr, info->ioaddr + UART_FCR); /* set fcr */ |
794 | continue; | 676 | outb(cval, info->ioaddr + UART_LCR); |
795 | 677 | ||
796 | retval = mxser_get_ISA_conf(cap, &hwconf); | 678 | return ret; |
679 | } | ||
797 | 680 | ||
798 | if (retval != 0) | 681 | static void mxser_check_modem_status(struct mxser_port *port, int status) |
799 | printk(KERN_INFO "Found MOXA %s board (CAP=0x%x)\n", | 682 | { |
800 | mxser_brdname[hwconf.board_type - 1], ioaddr[b]); | 683 | /* update input line counters */ |
684 | if (status & UART_MSR_TERI) | ||
685 | port->icount.rng++; | ||
686 | if (status & UART_MSR_DDSR) | ||
687 | port->icount.dsr++; | ||
688 | if (status & UART_MSR_DDCD) | ||
689 | port->icount.dcd++; | ||
690 | if (status & UART_MSR_DCTS) | ||
691 | port->icount.cts++; | ||
692 | port->mon_data.modem_status = status; | ||
693 | wake_up_interruptible(&port->delta_msr_wait); | ||
801 | 694 | ||
802 | if (retval <= 0) { | 695 | if ((port->flags & ASYNC_CHECK_CD) && (status & UART_MSR_DDCD)) { |
803 | if (retval == MXSER_ERR_IRQ) | 696 | if (status & UART_MSR_DCD) |
804 | printk(KERN_ERR "Invalid interrupt number, " | 697 | wake_up_interruptible(&port->open_wait); |
805 | "board not configured\n"); | 698 | } |
806 | else if (retval == MXSER_ERR_IRQ_CONFLIT) | ||
807 | printk(KERN_ERR "Invalid interrupt number, " | ||
808 | "board not configured\n"); | ||
809 | else if (retval == MXSER_ERR_VECTOR) | ||
810 | printk(KERN_ERR "Invalid interrupt vector, " | ||
811 | "board not configured\n"); | ||
812 | else if (retval == MXSER_ERR_IOADDR) | ||
813 | printk(KERN_ERR "Invalid I/O address, " | ||
814 | "board not configured\n"); | ||
815 | 699 | ||
816 | continue; | 700 | if (port->flags & ASYNC_CTS_FLOW) { |
701 | if (port->tty->hw_stopped) { | ||
702 | if (status & UART_MSR_CTS) { | ||
703 | port->tty->hw_stopped = 0; | ||
704 | |||
705 | if ((port->type != PORT_16550A) && | ||
706 | (!port->board->chip_flag)) { | ||
707 | outb(port->IER & ~UART_IER_THRI, | ||
708 | port->ioaddr + UART_IER); | ||
709 | port->IER |= UART_IER_THRI; | ||
710 | outb(port->IER, port->ioaddr + | ||
711 | UART_IER); | ||
712 | } | ||
713 | tty_wakeup(port->tty); | ||
714 | } | ||
715 | } else { | ||
716 | if (!(status & UART_MSR_CTS)) { | ||
717 | port->tty->hw_stopped = 1; | ||
718 | if (port->type != PORT_16550A && | ||
719 | !port->board->chip_flag) { | ||
720 | port->IER &= ~UART_IER_THRI; | ||
721 | outb(port->IER, port->ioaddr + | ||
722 | UART_IER); | ||
723 | } | ||
724 | } | ||
817 | } | 725 | } |
726 | } | ||
727 | } | ||
818 | 728 | ||
819 | hwconf.pciInfo.busNum = 0; | 729 | static int mxser_startup(struct mxser_port *info) |
820 | hwconf.pciInfo.devNum = 0; | 730 | { |
821 | hwconf.pciInfo.pdev = NULL; | 731 | unsigned long page; |
732 | unsigned long flags; | ||
822 | 733 | ||
823 | mxser_getcfg(m, &hwconf); | 734 | page = __get_free_page(GFP_KERNEL); |
824 | /* | 735 | if (!page) |
825 | * init mxsercfg first, | 736 | return -ENOMEM; |
826 | * or mxsercfg data is not correct on ISR. | 737 | |
827 | */ | 738 | spin_lock_irqsave(&info->slock, flags); |
828 | /* mxser_initbrd will hook ISR. */ | ||
829 | if (mxser_initbrd(m, &hwconf) < 0) | ||
830 | continue; | ||
831 | 739 | ||
832 | m++; | 740 | if (info->flags & ASYNC_INITIALIZED) { |
741 | free_page(page); | ||
742 | spin_unlock_irqrestore(&info->slock, flags); | ||
743 | return 0; | ||
833 | } | 744 | } |
834 | 745 | ||
835 | /* start finding PCI board here */ | 746 | if (!info->ioaddr || !info->type) { |
836 | #ifdef CONFIG_PCI | 747 | if (info->tty) |
837 | n = ARRAY_SIZE(mxser_pcibrds) - 1; | 748 | set_bit(TTY_IO_ERROR, &info->tty->flags); |
838 | index = 0; | 749 | free_page(page); |
839 | b = 0; | 750 | spin_unlock_irqrestore(&info->slock, flags); |
840 | while (b < n) { | 751 | return 0; |
841 | pdev = pci_get_device(mxser_pcibrds[b].vendor, | ||
842 | mxser_pcibrds[b].device, pdev); | ||
843 | if (pdev == NULL) { | ||
844 | b++; | ||
845 | continue; | ||
846 | } | ||
847 | hwconf.pciInfo.busNum = busnum = pdev->bus->number; | ||
848 | hwconf.pciInfo.devNum = devnum = PCI_SLOT(pdev->devfn) << 3; | ||
849 | hwconf.pciInfo.pdev = pdev; | ||
850 | printk(KERN_INFO "Found MOXA %s board(BusNo=%d,DevNo=%d)\n", | ||
851 | mxser_brdname[(int) (mxser_pcibrds[b].driver_data) - 1], | ||
852 | busnum, devnum >> 3); | ||
853 | index++; | ||
854 | if (m >= MXSER_BOARDS) | ||
855 | printk(KERN_ERR | ||
856 | "Too many Smartio/Industio family boards find " | ||
857 | "(maximum %d), board not configured\n", | ||
858 | MXSER_BOARDS); | ||
859 | else { | ||
860 | if (pci_enable_device(pdev)) { | ||
861 | printk(KERN_ERR "Moxa SmartI/O PCI enable " | ||
862 | "fail !\n"); | ||
863 | continue; | ||
864 | } | ||
865 | retval = mxser_get_PCI_conf(busnum, devnum, | ||
866 | (int)mxser_pcibrds[b].driver_data, | ||
867 | &hwconf); | ||
868 | if (retval < 0) { | ||
869 | if (retval == MXSER_ERR_IRQ) | ||
870 | printk(KERN_ERR | ||
871 | "Invalid interrupt number, " | ||
872 | "board not configured\n"); | ||
873 | else if (retval == MXSER_ERR_IRQ_CONFLIT) | ||
874 | printk(KERN_ERR | ||
875 | "Invalid interrupt number, " | ||
876 | "board not configured\n"); | ||
877 | else if (retval == MXSER_ERR_VECTOR) | ||
878 | printk(KERN_ERR | ||
879 | "Invalid interrupt vector, " | ||
880 | "board not configured\n"); | ||
881 | else if (retval == MXSER_ERR_IOADDR) | ||
882 | printk(KERN_ERR | ||
883 | "Invalid I/O address, " | ||
884 | "board not configured\n"); | ||
885 | continue; | ||
886 | } | ||
887 | mxser_getcfg(m, &hwconf); | ||
888 | /* init mxsercfg first, | ||
889 | * or mxsercfg data is not correct on ISR. | ||
890 | */ | ||
891 | /* mxser_initbrd will hook ISR. */ | ||
892 | if (mxser_initbrd(m, &hwconf) < 0) | ||
893 | continue; | ||
894 | m++; | ||
895 | /* Keep an extra reference if we succeeded. It will | ||
896 | be returned at unload time */ | ||
897 | pci_dev_get(pdev); | ||
898 | } | ||
899 | } | 752 | } |
900 | #endif | 753 | if (info->xmit_buf) |
754 | free_page(page); | ||
755 | else | ||
756 | info->xmit_buf = (unsigned char *) page; | ||
901 | 757 | ||
902 | retval = tty_register_driver(mxvar_sdriver); | 758 | /* |
903 | if (retval) { | 759 | * Clear the FIFO buffers and disable them |
904 | printk(KERN_ERR "Couldn't install MOXA Smartio/Industio family" | 760 | * (they will be reenabled in mxser_change_speed()) |
905 | " driver !\n"); | 761 | */ |
906 | put_tty_driver(mxvar_sdriver); | 762 | if (info->board->chip_flag) |
763 | outb((UART_FCR_CLEAR_RCVR | | ||
764 | UART_FCR_CLEAR_XMIT | | ||
765 | MOXA_MUST_FCR_GDA_MODE_ENABLE), info->ioaddr + UART_FCR); | ||
766 | else | ||
767 | outb((UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT), | ||
768 | info->ioaddr + UART_FCR); | ||
907 | 769 | ||
908 | for (i = 0; i < MXSER_BOARDS; i++) { | 770 | /* |
909 | if (mxsercfg[i].board_type == -1) | 771 | * At this point there's no way the LSR could still be 0xFF; |
910 | continue; | 772 | * if it is, then bail out, because there's likely no UART |
911 | else { | 773 | * here. |
912 | free_irq(mxsercfg[i].irq, &mxvar_table[i * MXSER_PORTS_PER_BOARD]); | 774 | */ |
913 | /* todo: release io, vector */ | 775 | if (inb(info->ioaddr + UART_LSR) == 0xff) { |
914 | } | 776 | spin_unlock_irqrestore(&info->slock, flags); |
915 | } | 777 | if (capable(CAP_SYS_ADMIN)) { |
916 | return retval; | 778 | if (info->tty) |
779 | set_bit(TTY_IO_ERROR, &info->tty->flags); | ||
780 | return 0; | ||
781 | } else | ||
782 | return -ENODEV; | ||
917 | } | 783 | } |
918 | 784 | ||
785 | /* | ||
786 | * Clear the interrupt registers. | ||
787 | */ | ||
788 | (void) inb(info->ioaddr + UART_LSR); | ||
789 | (void) inb(info->ioaddr + UART_RX); | ||
790 | (void) inb(info->ioaddr + UART_IIR); | ||
791 | (void) inb(info->ioaddr + UART_MSR); | ||
792 | |||
793 | /* | ||
794 | * Now, initialize the UART | ||
795 | */ | ||
796 | outb(UART_LCR_WLEN8, info->ioaddr + UART_LCR); /* reset DLAB */ | ||
797 | info->MCR = UART_MCR_DTR | UART_MCR_RTS; | ||
798 | outb(info->MCR, info->ioaddr + UART_MCR); | ||
799 | |||
800 | /* | ||
801 | * Finally, enable interrupts | ||
802 | */ | ||
803 | info->IER = UART_IER_MSI | UART_IER_RLSI | UART_IER_RDI; | ||
804 | |||
805 | if (info->board->chip_flag) | ||
806 | info->IER |= MOXA_MUST_IER_EGDAI; | ||
807 | outb(info->IER, info->ioaddr + UART_IER); /* enable interrupts */ | ||
808 | |||
809 | /* | ||
810 | * And clear the interrupt registers again for luck. | ||
811 | */ | ||
812 | (void) inb(info->ioaddr + UART_LSR); | ||
813 | (void) inb(info->ioaddr + UART_RX); | ||
814 | (void) inb(info->ioaddr + UART_IIR); | ||
815 | (void) inb(info->ioaddr + UART_MSR); | ||
816 | |||
817 | if (info->tty) | ||
818 | clear_bit(TTY_IO_ERROR, &info->tty->flags); | ||
819 | info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; | ||
820 | |||
821 | /* | ||
822 | * and set the speed of the serial port | ||
823 | */ | ||
824 | mxser_change_speed(info, NULL); | ||
825 | info->flags |= ASYNC_INITIALIZED; | ||
826 | spin_unlock_irqrestore(&info->slock, flags); | ||
827 | |||
919 | return 0; | 828 | return 0; |
920 | } | 829 | } |
921 | 830 | ||
922 | static void mxser_do_softint(struct work_struct *work) | 831 | /* |
832 | * This routine will shutdown a serial port; interrupts maybe disabled, and | ||
833 | * DTR is dropped if the hangup on close termio flag is on. | ||
834 | */ | ||
835 | static void mxser_shutdown(struct mxser_port *info) | ||
923 | { | 836 | { |
924 | struct mxser_struct *info = | 837 | unsigned long flags; |
925 | container_of(work, struct mxser_struct, tqueue); | ||
926 | struct tty_struct *tty; | ||
927 | 838 | ||
928 | tty = info->tty; | 839 | if (!(info->flags & ASYNC_INITIALIZED)) |
840 | return; | ||
841 | |||
842 | spin_lock_irqsave(&info->slock, flags); | ||
843 | |||
844 | /* | ||
845 | * clear delta_msr_wait queue to avoid mem leaks: we may free the irq | ||
846 | * here so the queue might never be waken up | ||
847 | */ | ||
848 | wake_up_interruptible(&info->delta_msr_wait); | ||
929 | 849 | ||
930 | if (tty) { | 850 | /* |
931 | if (test_and_clear_bit(MXSER_EVENT_TXLOW, &info->event)) | 851 | * Free the IRQ, if necessary |
932 | tty_wakeup(tty); | 852 | */ |
933 | if (test_and_clear_bit(MXSER_EVENT_HANGUP, &info->event)) | 853 | if (info->xmit_buf) { |
934 | tty_hangup(tty); | 854 | free_page((unsigned long) info->xmit_buf); |
855 | info->xmit_buf = NULL; | ||
935 | } | 856 | } |
936 | } | ||
937 | 857 | ||
938 | static unsigned char mxser_get_msr(int baseaddr, int mode, int port, struct mxser_struct *info) | 858 | info->IER = 0; |
939 | { | 859 | outb(0x00, info->ioaddr + UART_IER); |
940 | unsigned char status = 0; | ||
941 | 860 | ||
942 | status = inb(baseaddr + UART_MSR); | 861 | if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) |
862 | info->MCR &= ~(UART_MCR_DTR | UART_MCR_RTS); | ||
863 | outb(info->MCR, info->ioaddr + UART_MCR); | ||
943 | 864 | ||
944 | mxser_msr[port] &= 0x0F; | 865 | /* clear Rx/Tx FIFO's */ |
945 | mxser_msr[port] |= status; | 866 | if (info->board->chip_flag) |
946 | status = mxser_msr[port]; | 867 | outb(UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT | |
947 | if (mode) | 868 | MOXA_MUST_FCR_GDA_MODE_ENABLE, |
948 | mxser_msr[port] = 0; | 869 | info->ioaddr + UART_FCR); |
870 | else | ||
871 | outb(UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT, | ||
872 | info->ioaddr + UART_FCR); | ||
949 | 873 | ||
950 | return status; | 874 | /* read data port to reset things */ |
875 | (void) inb(info->ioaddr + UART_RX); | ||
876 | |||
877 | if (info->tty) | ||
878 | set_bit(TTY_IO_ERROR, &info->tty->flags); | ||
879 | |||
880 | info->flags &= ~ASYNC_INITIALIZED; | ||
881 | |||
882 | if (info->board->chip_flag) | ||
883 | SET_MOXA_MUST_NO_SOFTWARE_FLOW_CONTROL(info->ioaddr); | ||
884 | |||
885 | spin_unlock_irqrestore(&info->slock, flags); | ||
951 | } | 886 | } |
952 | 887 | ||
953 | /* | 888 | /* |
@@ -958,19 +893,17 @@ static unsigned char mxser_get_msr(int baseaddr, int mode, int port, struct mxse | |||
958 | */ | 893 | */ |
959 | static int mxser_open(struct tty_struct *tty, struct file *filp) | 894 | static int mxser_open(struct tty_struct *tty, struct file *filp) |
960 | { | 895 | { |
961 | struct mxser_struct *info; | 896 | struct mxser_port *info; |
897 | unsigned long flags; | ||
962 | int retval, line; | 898 | int retval, line; |
963 | 899 | ||
964 | /* initialize driver_data in case something fails */ | ||
965 | tty->driver_data = NULL; | ||
966 | |||
967 | line = tty->index; | 900 | line = tty->index; |
968 | if (line == MXSER_PORTS) | 901 | if (line == MXSER_PORTS) |
969 | return 0; | 902 | return 0; |
970 | if (line < 0 || line > MXSER_PORTS) | 903 | if (line < 0 || line > MXSER_PORTS) |
971 | return -ENODEV; | 904 | return -ENODEV; |
972 | info = mxvar_table + line; | 905 | info = &mxser_boards[line / MXSER_PORTS_PER_BOARD].ports[line % MXSER_PORTS_PER_BOARD]; |
973 | if (!info->base) | 906 | if (!info->ioaddr) |
974 | return -ENODEV; | 907 | return -ENODEV; |
975 | 908 | ||
976 | tty->driver_data = info; | 909 | tty->driver_data = info; |
@@ -978,6 +911,9 @@ static int mxser_open(struct tty_struct *tty, struct file *filp) | |||
978 | /* | 911 | /* |
979 | * Start up serial port | 912 | * Start up serial port |
980 | */ | 913 | */ |
914 | spin_lock_irqsave(&info->slock, flags); | ||
915 | info->count++; | ||
916 | spin_unlock_irqrestore(&info->slock, flags); | ||
981 | retval = mxser_startup(info); | 917 | retval = mxser_startup(info); |
982 | if (retval) | 918 | if (retval) |
983 | return retval; | 919 | return retval; |
@@ -986,21 +922,6 @@ static int mxser_open(struct tty_struct *tty, struct file *filp) | |||
986 | if (retval) | 922 | if (retval) |
987 | return retval; | 923 | return retval; |
988 | 924 | ||
989 | info->count++; | ||
990 | |||
991 | if ((info->count == 1) && (info->flags & ASYNC_SPLIT_TERMIOS)) { | ||
992 | if (tty->driver->subtype == SERIAL_TYPE_NORMAL) | ||
993 | *tty->termios = info->normal_termios; | ||
994 | else | ||
995 | *tty->termios = info->callout_termios; | ||
996 | mxser_change_speed(info, NULL); | ||
997 | } | ||
998 | |||
999 | /* | ||
1000 | status = mxser_get_msr(info->base, 0, info->port); | ||
1001 | mxser_check_modem_status(info, status); | ||
1002 | */ | ||
1003 | |||
1004 | /* unmark here for very high baud rate (ex. 921600 bps) used */ | 925 | /* unmark here for very high baud rate (ex. 921600 bps) used */ |
1005 | tty->low_latency = 1; | 926 | tty->low_latency = 1; |
1006 | return 0; | 927 | return 0; |
@@ -1014,11 +935,10 @@ static int mxser_open(struct tty_struct *tty, struct file *filp) | |||
1014 | */ | 935 | */ |
1015 | static void mxser_close(struct tty_struct *tty, struct file *filp) | 936 | static void mxser_close(struct tty_struct *tty, struct file *filp) |
1016 | { | 937 | { |
1017 | struct mxser_struct *info = tty->driver_data; | 938 | struct mxser_port *info = tty->driver_data; |
1018 | 939 | ||
1019 | unsigned long timeout; | 940 | unsigned long timeout; |
1020 | unsigned long flags; | 941 | unsigned long flags; |
1021 | struct tty_ldisc *ld; | ||
1022 | 942 | ||
1023 | if (tty->index == MXSER_PORTS) | 943 | if (tty->index == MXSER_PORTS) |
1024 | return; | 944 | return; |
@@ -1045,7 +965,7 @@ static void mxser_close(struct tty_struct *tty, struct file *filp) | |||
1045 | } | 965 | } |
1046 | if (--info->count < 0) { | 966 | if (--info->count < 0) { |
1047 | printk(KERN_ERR "mxser_close: bad serial port count for " | 967 | printk(KERN_ERR "mxser_close: bad serial port count for " |
1048 | "ttys%d: %d\n", info->port, info->count); | 968 | "ttys%d: %d\n", tty->index, info->count); |
1049 | info->count = 0; | 969 | info->count = 0; |
1050 | } | 970 | } |
1051 | if (info->count) { | 971 | if (info->count) { |
@@ -1074,20 +994,18 @@ static void mxser_close(struct tty_struct *tty, struct file *filp) | |||
1074 | * line status register. | 994 | * line status register. |
1075 | */ | 995 | */ |
1076 | info->IER &= ~UART_IER_RLSI; | 996 | info->IER &= ~UART_IER_RLSI; |
1077 | if (info->IsMoxaMustChipFlag) | 997 | if (info->board->chip_flag) |
1078 | info->IER &= ~MOXA_MUST_RECV_ISR; | 998 | info->IER &= ~MOXA_MUST_RECV_ISR; |
1079 | /* by William | 999 | |
1080 | info->read_status_mask &= ~UART_LSR_DR; | ||
1081 | */ | ||
1082 | if (info->flags & ASYNC_INITIALIZED) { | 1000 | if (info->flags & ASYNC_INITIALIZED) { |
1083 | outb(info->IER, info->base + UART_IER); | 1001 | outb(info->IER, info->ioaddr + UART_IER); |
1084 | /* | 1002 | /* |
1085 | * Before we drop DTR, make sure the UART transmitter | 1003 | * Before we drop DTR, make sure the UART transmitter |
1086 | * has completely drained; this is especially | 1004 | * has completely drained; this is especially |
1087 | * important if there is a transmit FIFO! | 1005 | * important if there is a transmit FIFO! |
1088 | */ | 1006 | */ |
1089 | timeout = jiffies + HZ; | 1007 | timeout = jiffies + HZ; |
1090 | while (!(inb(info->base + UART_LSR) & UART_LSR_TEMT)) { | 1008 | while (!(inb(info->ioaddr + UART_LSR) & UART_LSR_TEMT)) { |
1091 | schedule_timeout_interruptible(5); | 1009 | schedule_timeout_interruptible(5); |
1092 | if (time_after(jiffies, timeout)) | 1010 | if (time_after(jiffies, timeout)) |
1093 | break; | 1011 | break; |
@@ -1097,14 +1015,9 @@ static void mxser_close(struct tty_struct *tty, struct file *filp) | |||
1097 | 1015 | ||
1098 | if (tty->driver->flush_buffer) | 1016 | if (tty->driver->flush_buffer) |
1099 | tty->driver->flush_buffer(tty); | 1017 | tty->driver->flush_buffer(tty); |
1100 | 1018 | ||
1101 | ld = tty_ldisc_ref(tty); | 1019 | tty_ldisc_flush(tty); |
1102 | if (ld) { | 1020 | |
1103 | if (ld->flush_buffer) | ||
1104 | ld->flush_buffer(tty); | ||
1105 | tty_ldisc_deref(ld); | ||
1106 | } | ||
1107 | |||
1108 | tty->closing = 0; | 1021 | tty->closing = 0; |
1109 | info->event = 0; | 1022 | info->event = 0; |
1110 | info->tty = NULL; | 1023 | info->tty = NULL; |
@@ -1115,14 +1028,12 @@ static void mxser_close(struct tty_struct *tty, struct file *filp) | |||
1115 | } | 1028 | } |
1116 | 1029 | ||
1117 | info->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING); | 1030 | info->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING); |
1118 | wake_up_interruptible(&info->close_wait); | ||
1119 | |||
1120 | } | 1031 | } |
1121 | 1032 | ||
1122 | static int mxser_write(struct tty_struct *tty, const unsigned char *buf, int count) | 1033 | static int mxser_write(struct tty_struct *tty, const unsigned char *buf, int count) |
1123 | { | 1034 | { |
1124 | int c, total = 0; | 1035 | int c, total = 0; |
1125 | struct mxser_struct *info = tty->driver_data; | 1036 | struct mxser_port *info = tty->driver_data; |
1126 | unsigned long flags; | 1037 | unsigned long flags; |
1127 | 1038 | ||
1128 | if (!info->xmit_buf) | 1039 | if (!info->xmit_buf) |
@@ -1146,13 +1057,15 @@ static int mxser_write(struct tty_struct *tty, const unsigned char *buf, int cou | |||
1146 | total += c; | 1057 | total += c; |
1147 | } | 1058 | } |
1148 | 1059 | ||
1149 | if (info->xmit_cnt && !tty->stopped && !(info->IER & UART_IER_THRI)) { | 1060 | if (info->xmit_cnt && !tty->stopped) { |
1150 | if (!tty->hw_stopped || | 1061 | if (!tty->hw_stopped || |
1151 | (info->type == PORT_16550A) || | 1062 | (info->type == PORT_16550A) || |
1152 | (info->IsMoxaMustChipFlag)) { | 1063 | (info->board->chip_flag)) { |
1153 | spin_lock_irqsave(&info->slock, flags); | 1064 | spin_lock_irqsave(&info->slock, flags); |
1065 | outb(info->IER & ~UART_IER_THRI, info->ioaddr + | ||
1066 | UART_IER); | ||
1154 | info->IER |= UART_IER_THRI; | 1067 | info->IER |= UART_IER_THRI; |
1155 | outb(info->IER, info->base + UART_IER); | 1068 | outb(info->IER, info->ioaddr + UART_IER); |
1156 | spin_unlock_irqrestore(&info->slock, flags); | 1069 | spin_unlock_irqrestore(&info->slock, flags); |
1157 | } | 1070 | } |
1158 | } | 1071 | } |
@@ -1161,7 +1074,7 @@ static int mxser_write(struct tty_struct *tty, const unsigned char *buf, int cou | |||
1161 | 1074 | ||
1162 | static void mxser_put_char(struct tty_struct *tty, unsigned char ch) | 1075 | static void mxser_put_char(struct tty_struct *tty, unsigned char ch) |
1163 | { | 1076 | { |
1164 | struct mxser_struct *info = tty->driver_data; | 1077 | struct mxser_port *info = tty->driver_data; |
1165 | unsigned long flags; | 1078 | unsigned long flags; |
1166 | 1079 | ||
1167 | if (!info->xmit_buf) | 1080 | if (!info->xmit_buf) |
@@ -1175,13 +1088,14 @@ static void mxser_put_char(struct tty_struct *tty, unsigned char ch) | |||
1175 | info->xmit_head &= SERIAL_XMIT_SIZE - 1; | 1088 | info->xmit_head &= SERIAL_XMIT_SIZE - 1; |
1176 | info->xmit_cnt++; | 1089 | info->xmit_cnt++; |
1177 | spin_unlock_irqrestore(&info->slock, flags); | 1090 | spin_unlock_irqrestore(&info->slock, flags); |
1178 | if (!tty->stopped && !(info->IER & UART_IER_THRI)) { | 1091 | if (!tty->stopped) { |
1179 | if (!tty->hw_stopped || | 1092 | if (!tty->hw_stopped || |
1180 | (info->type == PORT_16550A) || | 1093 | (info->type == PORT_16550A) || |
1181 | info->IsMoxaMustChipFlag) { | 1094 | info->board->chip_flag) { |
1182 | spin_lock_irqsave(&info->slock, flags); | 1095 | spin_lock_irqsave(&info->slock, flags); |
1096 | outb(info->IER & ~UART_IER_THRI, info->ioaddr + UART_IER); | ||
1183 | info->IER |= UART_IER_THRI; | 1097 | info->IER |= UART_IER_THRI; |
1184 | outb(info->IER, info->base + UART_IER); | 1098 | outb(info->IER, info->ioaddr + UART_IER); |
1185 | spin_unlock_irqrestore(&info->slock, flags); | 1099 | spin_unlock_irqrestore(&info->slock, flags); |
1186 | } | 1100 | } |
1187 | } | 1101 | } |
@@ -1190,7 +1104,7 @@ static void mxser_put_char(struct tty_struct *tty, unsigned char ch) | |||
1190 | 1104 | ||
1191 | static void mxser_flush_chars(struct tty_struct *tty) | 1105 | static void mxser_flush_chars(struct tty_struct *tty) |
1192 | { | 1106 | { |
1193 | struct mxser_struct *info = tty->driver_data; | 1107 | struct mxser_port *info = tty->driver_data; |
1194 | unsigned long flags; | 1108 | unsigned long flags; |
1195 | 1109 | ||
1196 | if (info->xmit_cnt <= 0 || | 1110 | if (info->xmit_cnt <= 0 || |
@@ -1198,21 +1112,22 @@ static void mxser_flush_chars(struct tty_struct *tty) | |||
1198 | !info->xmit_buf || | 1112 | !info->xmit_buf || |
1199 | (tty->hw_stopped && | 1113 | (tty->hw_stopped && |
1200 | (info->type != PORT_16550A) && | 1114 | (info->type != PORT_16550A) && |
1201 | (!info->IsMoxaMustChipFlag) | 1115 | (!info->board->chip_flag) |
1202 | )) | 1116 | )) |
1203 | return; | 1117 | return; |
1204 | 1118 | ||
1205 | spin_lock_irqsave(&info->slock, flags); | 1119 | spin_lock_irqsave(&info->slock, flags); |
1206 | 1120 | ||
1121 | outb(info->IER & ~UART_IER_THRI, info->ioaddr + UART_IER); | ||
1207 | info->IER |= UART_IER_THRI; | 1122 | info->IER |= UART_IER_THRI; |
1208 | outb(info->IER, info->base + UART_IER); | 1123 | outb(info->IER, info->ioaddr + UART_IER); |
1209 | 1124 | ||
1210 | spin_unlock_irqrestore(&info->slock, flags); | 1125 | spin_unlock_irqrestore(&info->slock, flags); |
1211 | } | 1126 | } |
1212 | 1127 | ||
1213 | static int mxser_write_room(struct tty_struct *tty) | 1128 | static int mxser_write_room(struct tty_struct *tty) |
1214 | { | 1129 | { |
1215 | struct mxser_struct *info = tty->driver_data; | 1130 | struct mxser_port *info = tty->driver_data; |
1216 | int ret; | 1131 | int ret; |
1217 | 1132 | ||
1218 | ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1; | 1133 | ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1; |
@@ -1223,13 +1138,13 @@ static int mxser_write_room(struct tty_struct *tty) | |||
1223 | 1138 | ||
1224 | static int mxser_chars_in_buffer(struct tty_struct *tty) | 1139 | static int mxser_chars_in_buffer(struct tty_struct *tty) |
1225 | { | 1140 | { |
1226 | struct mxser_struct *info = tty->driver_data; | 1141 | struct mxser_port *info = tty->driver_data; |
1227 | return info->xmit_cnt; | 1142 | return info->xmit_cnt; |
1228 | } | 1143 | } |
1229 | 1144 | ||
1230 | static void mxser_flush_buffer(struct tty_struct *tty) | 1145 | static void mxser_flush_buffer(struct tty_struct *tty) |
1231 | { | 1146 | { |
1232 | struct mxser_struct *info = tty->driver_data; | 1147 | struct mxser_port *info = tty->driver_data; |
1233 | char fcr; | 1148 | char fcr; |
1234 | unsigned long flags; | 1149 | unsigned long flags; |
1235 | 1150 | ||
@@ -1237,39 +1152,497 @@ static void mxser_flush_buffer(struct tty_struct *tty) | |||
1237 | spin_lock_irqsave(&info->slock, flags); | 1152 | spin_lock_irqsave(&info->slock, flags); |
1238 | info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; | 1153 | info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; |
1239 | 1154 | ||
1240 | /* below added by shinhay */ | 1155 | fcr = inb(info->ioaddr + UART_FCR); |
1241 | fcr = inb(info->base + UART_FCR); | ||
1242 | outb((fcr | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT), | 1156 | outb((fcr | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT), |
1243 | info->base + UART_FCR); | 1157 | info->ioaddr + UART_FCR); |
1244 | outb(fcr, info->base + UART_FCR); | 1158 | outb(fcr, info->ioaddr + UART_FCR); |
1245 | 1159 | ||
1246 | spin_unlock_irqrestore(&info->slock, flags); | 1160 | spin_unlock_irqrestore(&info->slock, flags); |
1247 | /* above added by shinhay */ | ||
1248 | 1161 | ||
1249 | tty_wakeup(tty); | 1162 | tty_wakeup(tty); |
1250 | } | 1163 | } |
1251 | 1164 | ||
1252 | static int mxser_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg) | 1165 | /* |
1166 | * ------------------------------------------------------------ | ||
1167 | * friends of mxser_ioctl() | ||
1168 | * ------------------------------------------------------------ | ||
1169 | */ | ||
1170 | static int mxser_get_serial_info(struct mxser_port *info, | ||
1171 | struct serial_struct __user *retinfo) | ||
1253 | { | 1172 | { |
1254 | struct mxser_struct *info = tty->driver_data; | 1173 | struct serial_struct tmp = { |
1255 | int retval; | 1174 | .type = info->type, |
1256 | struct async_icount cprev, cnow; /* kernel counter temps */ | 1175 | .line = info->tty->index, |
1176 | .port = info->ioaddr, | ||
1177 | .irq = info->board->irq, | ||
1178 | .flags = info->flags, | ||
1179 | .baud_base = info->baud_base, | ||
1180 | .close_delay = info->close_delay, | ||
1181 | .closing_wait = info->closing_wait, | ||
1182 | .custom_divisor = info->custom_divisor, | ||
1183 | .hub6 = 0 | ||
1184 | }; | ||
1185 | if (copy_to_user(retinfo, &tmp, sizeof(*retinfo))) | ||
1186 | return -EFAULT; | ||
1187 | return 0; | ||
1188 | } | ||
1189 | |||
1190 | static int mxser_set_serial_info(struct mxser_port *info, | ||
1191 | struct serial_struct __user *new_info) | ||
1192 | { | ||
1193 | struct serial_struct new_serial; | ||
1194 | speed_t baud; | ||
1195 | unsigned long sl_flags; | ||
1196 | unsigned int flags; | ||
1197 | int retval = 0; | ||
1198 | |||
1199 | if (!new_info || !info->ioaddr) | ||
1200 | return -ENODEV; | ||
1201 | if (copy_from_user(&new_serial, new_info, sizeof(new_serial))) | ||
1202 | return -EFAULT; | ||
1203 | |||
1204 | if (new_serial.irq != info->board->irq || | ||
1205 | new_serial.port != info->ioaddr) | ||
1206 | return -EINVAL; | ||
1207 | |||
1208 | flags = info->flags & ASYNC_SPD_MASK; | ||
1209 | |||
1210 | if (!capable(CAP_SYS_ADMIN)) { | ||
1211 | if ((new_serial.baud_base != info->baud_base) || | ||
1212 | (new_serial.close_delay != info->close_delay) || | ||
1213 | ((new_serial.flags & ~ASYNC_USR_MASK) != (info->flags & ~ASYNC_USR_MASK))) | ||
1214 | return -EPERM; | ||
1215 | info->flags = ((info->flags & ~ASYNC_USR_MASK) | | ||
1216 | (new_serial.flags & ASYNC_USR_MASK)); | ||
1217 | } else { | ||
1218 | /* | ||
1219 | * OK, past this point, all the error checking has been done. | ||
1220 | * At this point, we start making changes..... | ||
1221 | */ | ||
1222 | info->flags = ((info->flags & ~ASYNC_FLAGS) | | ||
1223 | (new_serial.flags & ASYNC_FLAGS)); | ||
1224 | info->close_delay = new_serial.close_delay * HZ / 100; | ||
1225 | info->closing_wait = new_serial.closing_wait * HZ / 100; | ||
1226 | info->tty->low_latency = | ||
1227 | (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0; | ||
1228 | info->tty->low_latency = 0; | ||
1229 | if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST && | ||
1230 | (new_serial.baud_base != info->baud_base || | ||
1231 | new_serial.custom_divisor != | ||
1232 | info->custom_divisor)) { | ||
1233 | baud = new_serial.baud_base / new_serial.custom_divisor; | ||
1234 | tty_encode_baud_rate(info->tty, baud, baud); | ||
1235 | } | ||
1236 | } | ||
1237 | |||
1238 | info->type = new_serial.type; | ||
1239 | |||
1240 | process_txrx_fifo(info); | ||
1241 | |||
1242 | if (info->flags & ASYNC_INITIALIZED) { | ||
1243 | if (flags != (info->flags & ASYNC_SPD_MASK)) { | ||
1244 | spin_lock_irqsave(&info->slock, sl_flags); | ||
1245 | mxser_change_speed(info, NULL); | ||
1246 | spin_unlock_irqrestore(&info->slock, sl_flags); | ||
1247 | } | ||
1248 | } else | ||
1249 | retval = mxser_startup(info); | ||
1250 | |||
1251 | return retval; | ||
1252 | } | ||
1253 | |||
1254 | /* | ||
1255 | * mxser_get_lsr_info - get line status register info | ||
1256 | * | ||
1257 | * Purpose: Let user call ioctl() to get info when the UART physically | ||
1258 | * is emptied. On bus types like RS485, the transmitter must | ||
1259 | * release the bus after transmitting. This must be done when | ||
1260 | * the transmit shift register is empty, not be done when the | ||
1261 | * transmit holding register is empty. This functionality | ||
1262 | * allows an RS485 driver to be written in user space. | ||
1263 | */ | ||
1264 | static int mxser_get_lsr_info(struct mxser_port *info, | ||
1265 | unsigned int __user *value) | ||
1266 | { | ||
1267 | unsigned char status; | ||
1268 | unsigned int result; | ||
1269 | unsigned long flags; | ||
1270 | |||
1271 | spin_lock_irqsave(&info->slock, flags); | ||
1272 | status = inb(info->ioaddr + UART_LSR); | ||
1273 | spin_unlock_irqrestore(&info->slock, flags); | ||
1274 | result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0); | ||
1275 | return put_user(result, value); | ||
1276 | } | ||
1277 | |||
1278 | /* | ||
1279 | * This routine sends a break character out the serial port. | ||
1280 | */ | ||
1281 | static void mxser_send_break(struct mxser_port *info, int duration) | ||
1282 | { | ||
1283 | unsigned long flags; | ||
1284 | |||
1285 | if (!info->ioaddr) | ||
1286 | return; | ||
1287 | set_current_state(TASK_INTERRUPTIBLE); | ||
1288 | spin_lock_irqsave(&info->slock, flags); | ||
1289 | outb(inb(info->ioaddr + UART_LCR) | UART_LCR_SBC, | ||
1290 | info->ioaddr + UART_LCR); | ||
1291 | spin_unlock_irqrestore(&info->slock, flags); | ||
1292 | schedule_timeout(duration); | ||
1293 | spin_lock_irqsave(&info->slock, flags); | ||
1294 | outb(inb(info->ioaddr + UART_LCR) & ~UART_LCR_SBC, | ||
1295 | info->ioaddr + UART_LCR); | ||
1296 | spin_unlock_irqrestore(&info->slock, flags); | ||
1297 | } | ||
1298 | |||
1299 | static int mxser_tiocmget(struct tty_struct *tty, struct file *file) | ||
1300 | { | ||
1301 | struct mxser_port *info = tty->driver_data; | ||
1302 | unsigned char control, status; | ||
1303 | unsigned long flags; | ||
1304 | |||
1305 | |||
1306 | if (tty->index == MXSER_PORTS) | ||
1307 | return -ENOIOCTLCMD; | ||
1308 | if (test_bit(TTY_IO_ERROR, &tty->flags)) | ||
1309 | return -EIO; | ||
1310 | |||
1311 | control = info->MCR; | ||
1312 | |||
1313 | spin_lock_irqsave(&info->slock, flags); | ||
1314 | status = inb(info->ioaddr + UART_MSR); | ||
1315 | if (status & UART_MSR_ANY_DELTA) | ||
1316 | mxser_check_modem_status(info, status); | ||
1317 | spin_unlock_irqrestore(&info->slock, flags); | ||
1318 | return ((control & UART_MCR_RTS) ? TIOCM_RTS : 0) | | ||
1319 | ((control & UART_MCR_DTR) ? TIOCM_DTR : 0) | | ||
1320 | ((status & UART_MSR_DCD) ? TIOCM_CAR : 0) | | ||
1321 | ((status & UART_MSR_RI) ? TIOCM_RNG : 0) | | ||
1322 | ((status & UART_MSR_DSR) ? TIOCM_DSR : 0) | | ||
1323 | ((status & UART_MSR_CTS) ? TIOCM_CTS : 0); | ||
1324 | } | ||
1325 | |||
1326 | static int mxser_tiocmset(struct tty_struct *tty, struct file *file, | ||
1327 | unsigned int set, unsigned int clear) | ||
1328 | { | ||
1329 | struct mxser_port *info = tty->driver_data; | ||
1330 | unsigned long flags; | ||
1331 | |||
1332 | |||
1333 | if (tty->index == MXSER_PORTS) | ||
1334 | return -ENOIOCTLCMD; | ||
1335 | if (test_bit(TTY_IO_ERROR, &tty->flags)) | ||
1336 | return -EIO; | ||
1337 | |||
1338 | spin_lock_irqsave(&info->slock, flags); | ||
1339 | |||
1340 | if (set & TIOCM_RTS) | ||
1341 | info->MCR |= UART_MCR_RTS; | ||
1342 | if (set & TIOCM_DTR) | ||
1343 | info->MCR |= UART_MCR_DTR; | ||
1344 | |||
1345 | if (clear & TIOCM_RTS) | ||
1346 | info->MCR &= ~UART_MCR_RTS; | ||
1347 | if (clear & TIOCM_DTR) | ||
1348 | info->MCR &= ~UART_MCR_DTR; | ||
1349 | |||
1350 | outb(info->MCR, info->ioaddr + UART_MCR); | ||
1351 | spin_unlock_irqrestore(&info->slock, flags); | ||
1352 | return 0; | ||
1353 | } | ||
1354 | |||
1355 | static int __init mxser_program_mode(int port) | ||
1356 | { | ||
1357 | int id, i, j, n; | ||
1358 | |||
1359 | outb(0, port); | ||
1360 | outb(0, port); | ||
1361 | outb(0, port); | ||
1362 | (void)inb(port); | ||
1363 | (void)inb(port); | ||
1364 | outb(0, port); | ||
1365 | (void)inb(port); | ||
1366 | |||
1367 | id = inb(port + 1) & 0x1F; | ||
1368 | if ((id != C168_ASIC_ID) && | ||
1369 | (id != C104_ASIC_ID) && | ||
1370 | (id != C102_ASIC_ID) && | ||
1371 | (id != CI132_ASIC_ID) && | ||
1372 | (id != CI134_ASIC_ID) && | ||
1373 | (id != CI104J_ASIC_ID)) | ||
1374 | return -1; | ||
1375 | for (i = 0, j = 0; i < 4; i++) { | ||
1376 | n = inb(port + 2); | ||
1377 | if (n == 'M') { | ||
1378 | j = 1; | ||
1379 | } else if ((j == 1) && (n == 1)) { | ||
1380 | j = 2; | ||
1381 | break; | ||
1382 | } else | ||
1383 | j = 0; | ||
1384 | } | ||
1385 | if (j != 2) | ||
1386 | id = -2; | ||
1387 | return id; | ||
1388 | } | ||
1389 | |||
1390 | static void __init mxser_normal_mode(int port) | ||
1391 | { | ||
1392 | int i, n; | ||
1393 | |||
1394 | outb(0xA5, port + 1); | ||
1395 | outb(0x80, port + 3); | ||
1396 | outb(12, port + 0); /* 9600 bps */ | ||
1397 | outb(0, port + 1); | ||
1398 | outb(0x03, port + 3); /* 8 data bits */ | ||
1399 | outb(0x13, port + 4); /* loop back mode */ | ||
1400 | for (i = 0; i < 16; i++) { | ||
1401 | n = inb(port + 5); | ||
1402 | if ((n & 0x61) == 0x60) | ||
1403 | break; | ||
1404 | if ((n & 1) == 1) | ||
1405 | (void)inb(port); | ||
1406 | } | ||
1407 | outb(0x00, port + 4); | ||
1408 | } | ||
1409 | |||
1410 | #define CHIP_SK 0x01 /* Serial Data Clock in Eprom */ | ||
1411 | #define CHIP_DO 0x02 /* Serial Data Output in Eprom */ | ||
1412 | #define CHIP_CS 0x04 /* Serial Chip Select in Eprom */ | ||
1413 | #define CHIP_DI 0x08 /* Serial Data Input in Eprom */ | ||
1414 | #define EN_CCMD 0x000 /* Chip's command register */ | ||
1415 | #define EN0_RSARLO 0x008 /* Remote start address reg 0 */ | ||
1416 | #define EN0_RSARHI 0x009 /* Remote start address reg 1 */ | ||
1417 | #define EN0_RCNTLO 0x00A /* Remote byte count reg WR */ | ||
1418 | #define EN0_RCNTHI 0x00B /* Remote byte count reg WR */ | ||
1419 | #define EN0_DCFG 0x00E /* Data configuration reg WR */ | ||
1420 | #define EN0_PORT 0x010 /* Rcv missed frame error counter RD */ | ||
1421 | #define ENC_PAGE0 0x000 /* Select page 0 of chip registers */ | ||
1422 | #define ENC_PAGE3 0x0C0 /* Select page 3 of chip registers */ | ||
1423 | static int __init mxser_read_register(int port, unsigned short *regs) | ||
1424 | { | ||
1425 | int i, k, value, id; | ||
1426 | unsigned int j; | ||
1427 | |||
1428 | id = mxser_program_mode(port); | ||
1429 | if (id < 0) | ||
1430 | return id; | ||
1431 | for (i = 0; i < 14; i++) { | ||
1432 | k = (i & 0x3F) | 0x180; | ||
1433 | for (j = 0x100; j > 0; j >>= 1) { | ||
1434 | outb(CHIP_CS, port); | ||
1435 | if (k & j) { | ||
1436 | outb(CHIP_CS | CHIP_DO, port); | ||
1437 | outb(CHIP_CS | CHIP_DO | CHIP_SK, port); /* A? bit of read */ | ||
1438 | } else { | ||
1439 | outb(CHIP_CS, port); | ||
1440 | outb(CHIP_CS | CHIP_SK, port); /* A? bit of read */ | ||
1441 | } | ||
1442 | } | ||
1443 | (void)inb(port); | ||
1444 | value = 0; | ||
1445 | for (k = 0, j = 0x8000; k < 16; k++, j >>= 1) { | ||
1446 | outb(CHIP_CS, port); | ||
1447 | outb(CHIP_CS | CHIP_SK, port); | ||
1448 | if (inb(port) & CHIP_DI) | ||
1449 | value |= j; | ||
1450 | } | ||
1451 | regs[i] = value; | ||
1452 | outb(0, port); | ||
1453 | } | ||
1454 | mxser_normal_mode(port); | ||
1455 | return id; | ||
1456 | } | ||
1457 | |||
1458 | static int mxser_ioctl_special(unsigned int cmd, void __user *argp) | ||
1459 | { | ||
1460 | struct mxser_port *port; | ||
1461 | int result, status; | ||
1462 | unsigned int i, j; | ||
1463 | |||
1464 | switch (cmd) { | ||
1465 | case MOXA_GET_MAJOR: | ||
1466 | return put_user(ttymajor, (int __user *)argp); | ||
1467 | |||
1468 | case MOXA_CHKPORTENABLE: | ||
1469 | result = 0; | ||
1470 | |||
1471 | for (i = 0; i < MXSER_BOARDS; i++) | ||
1472 | for (j = 0; j < MXSER_PORTS_PER_BOARD; j++) | ||
1473 | if (mxser_boards[i].ports[j].ioaddr) | ||
1474 | result |= (1 << i); | ||
1475 | |||
1476 | return put_user(result, (unsigned long __user *)argp); | ||
1477 | case MOXA_GETDATACOUNT: | ||
1478 | if (copy_to_user(argp, &mxvar_log, sizeof(mxvar_log))) | ||
1479 | return -EFAULT; | ||
1480 | return 0; | ||
1481 | case MOXA_GETMSTATUS: | ||
1482 | for (i = 0; i < MXSER_BOARDS; i++) | ||
1483 | for (j = 0; j < MXSER_PORTS_PER_BOARD; j++) { | ||
1484 | port = &mxser_boards[i].ports[j]; | ||
1485 | |||
1486 | GMStatus[i].ri = 0; | ||
1487 | if (!port->ioaddr) { | ||
1488 | GMStatus[i].dcd = 0; | ||
1489 | GMStatus[i].dsr = 0; | ||
1490 | GMStatus[i].cts = 0; | ||
1491 | continue; | ||
1492 | } | ||
1493 | |||
1494 | if (!port->tty || !port->tty->termios) | ||
1495 | GMStatus[i].cflag = | ||
1496 | port->normal_termios.c_cflag; | ||
1497 | else | ||
1498 | GMStatus[i].cflag = | ||
1499 | port->tty->termios->c_cflag; | ||
1500 | |||
1501 | status = inb(port->ioaddr + UART_MSR); | ||
1502 | if (status & 0x80 /*UART_MSR_DCD */ ) | ||
1503 | GMStatus[i].dcd = 1; | ||
1504 | else | ||
1505 | GMStatus[i].dcd = 0; | ||
1506 | |||
1507 | if (status & 0x20 /*UART_MSR_DSR */ ) | ||
1508 | GMStatus[i].dsr = 1; | ||
1509 | else | ||
1510 | GMStatus[i].dsr = 0; | ||
1511 | |||
1512 | |||
1513 | if (status & 0x10 /*UART_MSR_CTS */ ) | ||
1514 | GMStatus[i].cts = 1; | ||
1515 | else | ||
1516 | GMStatus[i].cts = 0; | ||
1517 | } | ||
1518 | if (copy_to_user(argp, GMStatus, | ||
1519 | sizeof(struct mxser_mstatus) * MXSER_PORTS)) | ||
1520 | return -EFAULT; | ||
1521 | return 0; | ||
1522 | case MOXA_ASPP_MON_EXT: { | ||
1523 | int p, shiftbit; | ||
1524 | unsigned long opmode; | ||
1525 | unsigned cflag, iflag; | ||
1526 | |||
1527 | for (i = 0; i < MXSER_BOARDS; i++) | ||
1528 | for (j = 0; j < MXSER_PORTS_PER_BOARD; j++) { | ||
1529 | port = &mxser_boards[i].ports[j]; | ||
1530 | if (!port->ioaddr) | ||
1531 | continue; | ||
1532 | |||
1533 | status = mxser_get_msr(port->ioaddr, 0, i); | ||
1534 | |||
1535 | if (status & UART_MSR_TERI) | ||
1536 | port->icount.rng++; | ||
1537 | if (status & UART_MSR_DDSR) | ||
1538 | port->icount.dsr++; | ||
1539 | if (status & UART_MSR_DDCD) | ||
1540 | port->icount.dcd++; | ||
1541 | if (status & UART_MSR_DCTS) | ||
1542 | port->icount.cts++; | ||
1543 | |||
1544 | port->mon_data.modem_status = status; | ||
1545 | mon_data_ext.rx_cnt[i] = port->mon_data.rxcnt; | ||
1546 | mon_data_ext.tx_cnt[i] = port->mon_data.txcnt; | ||
1547 | mon_data_ext.up_rxcnt[i] = | ||
1548 | port->mon_data.up_rxcnt; | ||
1549 | mon_data_ext.up_txcnt[i] = | ||
1550 | port->mon_data.up_txcnt; | ||
1551 | mon_data_ext.modem_status[i] = | ||
1552 | port->mon_data.modem_status; | ||
1553 | mon_data_ext.baudrate[i] = | ||
1554 | tty_get_baud_rate(port->tty); | ||
1555 | |||
1556 | if (!port->tty || !port->tty->termios) { | ||
1557 | cflag = port->normal_termios.c_cflag; | ||
1558 | iflag = port->normal_termios.c_iflag; | ||
1559 | } else { | ||
1560 | cflag = port->tty->termios->c_cflag; | ||
1561 | iflag = port->tty->termios->c_iflag; | ||
1562 | } | ||
1563 | |||
1564 | mon_data_ext.databits[i] = cflag & CSIZE; | ||
1565 | |||
1566 | mon_data_ext.stopbits[i] = cflag & CSTOPB; | ||
1567 | |||
1568 | mon_data_ext.parity[i] = | ||
1569 | cflag & (PARENB | PARODD | CMSPAR); | ||
1570 | |||
1571 | mon_data_ext.flowctrl[i] = 0x00; | ||
1572 | |||
1573 | if (cflag & CRTSCTS) | ||
1574 | mon_data_ext.flowctrl[i] |= 0x03; | ||
1575 | |||
1576 | if (iflag & (IXON | IXOFF)) | ||
1577 | mon_data_ext.flowctrl[i] |= 0x0C; | ||
1578 | |||
1579 | if (port->type == PORT_16550A) | ||
1580 | mon_data_ext.fifo[i] = 1; | ||
1581 | else | ||
1582 | mon_data_ext.fifo[i] = 0; | ||
1583 | |||
1584 | p = i % 4; | ||
1585 | shiftbit = p * 2; | ||
1586 | opmode = inb(port->opmode_ioaddr) >> shiftbit; | ||
1587 | opmode &= OP_MODE_MASK; | ||
1588 | |||
1589 | mon_data_ext.iftype[i] = opmode; | ||
1590 | |||
1591 | } | ||
1592 | if (copy_to_user(argp, &mon_data_ext, | ||
1593 | sizeof(mon_data_ext))) | ||
1594 | return -EFAULT; | ||
1595 | |||
1596 | return 0; | ||
1597 | |||
1598 | } default: | ||
1599 | return -ENOIOCTLCMD; | ||
1600 | } | ||
1601 | return 0; | ||
1602 | } | ||
1603 | |||
1604 | static int mxser_cflags_changed(struct mxser_port *info, unsigned long arg, | ||
1605 | struct async_icount *cprev) | ||
1606 | { | ||
1607 | struct async_icount cnow; | ||
1608 | unsigned long flags; | ||
1609 | int ret; | ||
1610 | |||
1611 | spin_lock_irqsave(&info->slock, flags); | ||
1612 | cnow = info->icount; /* atomic copy */ | ||
1613 | spin_unlock_irqrestore(&info->slock, flags); | ||
1614 | |||
1615 | ret = ((arg & TIOCM_RNG) && (cnow.rng != cprev->rng)) || | ||
1616 | ((arg & TIOCM_DSR) && (cnow.dsr != cprev->dsr)) || | ||
1617 | ((arg & TIOCM_CD) && (cnow.dcd != cprev->dcd)) || | ||
1618 | ((arg & TIOCM_CTS) && (cnow.cts != cprev->cts)); | ||
1619 | |||
1620 | *cprev = cnow; | ||
1621 | |||
1622 | return ret; | ||
1623 | } | ||
1624 | |||
1625 | static int mxser_ioctl(struct tty_struct *tty, struct file *file, | ||
1626 | unsigned int cmd, unsigned long arg) | ||
1627 | { | ||
1628 | struct mxser_port *info = tty->driver_data; | ||
1629 | struct async_icount cnow; | ||
1257 | struct serial_icounter_struct __user *p_cuser; | 1630 | struct serial_icounter_struct __user *p_cuser; |
1258 | unsigned long templ; | ||
1259 | unsigned long flags; | 1631 | unsigned long flags; |
1260 | void __user *argp = (void __user *)arg; | 1632 | void __user *argp = (void __user *)arg; |
1633 | int retval; | ||
1261 | 1634 | ||
1262 | if (tty->index == MXSER_PORTS) | 1635 | if (tty->index == MXSER_PORTS) |
1263 | return mxser_ioctl_special(cmd, argp); | 1636 | return mxser_ioctl_special(cmd, argp); |
1264 | 1637 | ||
1265 | /* following add by Victor Yu. 01-05-2004 */ | ||
1266 | if (cmd == MOXA_SET_OP_MODE || cmd == MOXA_GET_OP_MODE) { | 1638 | if (cmd == MOXA_SET_OP_MODE || cmd == MOXA_GET_OP_MODE) { |
1267 | int opmode, p; | 1639 | int p; |
1640 | unsigned long opmode; | ||
1268 | static unsigned char ModeMask[] = { 0xfc, 0xf3, 0xcf, 0x3f }; | 1641 | static unsigned char ModeMask[] = { 0xfc, 0xf3, 0xcf, 0x3f }; |
1269 | int shiftbit; | 1642 | int shiftbit; |
1270 | unsigned char val, mask; | 1643 | unsigned char val, mask; |
1271 | 1644 | ||
1272 | p = info->port % 4; | 1645 | p = tty->index % 4; |
1273 | if (cmd == MOXA_SET_OP_MODE) { | 1646 | if (cmd == MOXA_SET_OP_MODE) { |
1274 | if (get_user(opmode, (int __user *) argp)) | 1647 | if (get_user(opmode, (int __user *) argp)) |
1275 | return -EFAULT; | 1648 | return -EFAULT; |
@@ -1288,17 +1661,16 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, unsigned int c | |||
1288 | shiftbit = p * 2; | 1661 | shiftbit = p * 2; |
1289 | opmode = inb(info->opmode_ioaddr) >> shiftbit; | 1662 | opmode = inb(info->opmode_ioaddr) >> shiftbit; |
1290 | opmode &= OP_MODE_MASK; | 1663 | opmode &= OP_MODE_MASK; |
1291 | if (copy_to_user(argp, &opmode, sizeof(int))) | 1664 | if (put_user(opmode, (int __user *)argp)) |
1292 | return -EFAULT; | 1665 | return -EFAULT; |
1293 | } | 1666 | } |
1294 | return 0; | 1667 | return 0; |
1295 | } | 1668 | } |
1296 | /* above add by Victor Yu. 01-05-2004 */ | ||
1297 | 1669 | ||
1298 | if ((cmd != TIOCGSERIAL) && (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) { | 1670 | if (cmd != TIOCGSERIAL && cmd != TIOCMIWAIT && cmd != TIOCGICOUNT && |
1299 | if (tty->flags & (1 << TTY_IO_ERROR)) | 1671 | test_bit(TTY_IO_ERROR, &tty->flags)) |
1300 | return -EIO; | 1672 | return -EIO; |
1301 | } | 1673 | |
1302 | switch (cmd) { | 1674 | switch (cmd) { |
1303 | case TCSBRK: /* SVID version: non-zero arg --> no break */ | 1675 | case TCSBRK: /* SVID version: non-zero arg --> no break */ |
1304 | retval = tty_check_change(tty); | 1676 | retval = tty_check_change(tty); |
@@ -1316,11 +1688,10 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, unsigned int c | |||
1316 | mxser_send_break(info, arg ? arg * (HZ / 10) : HZ / 4); | 1688 | mxser_send_break(info, arg ? arg * (HZ / 10) : HZ / 4); |
1317 | return 0; | 1689 | return 0; |
1318 | case TIOCGSOFTCAR: | 1690 | case TIOCGSOFTCAR: |
1319 | return put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long __user *)argp); | 1691 | return put_user(!!C_CLOCAL(tty), (unsigned long __user *)argp); |
1320 | case TIOCSSOFTCAR: | 1692 | case TIOCSSOFTCAR: |
1321 | if (get_user(templ, (unsigned long __user *) argp)) | 1693 | if (get_user(arg, (unsigned long __user *)argp)) |
1322 | return -EFAULT; | 1694 | return -EFAULT; |
1323 | arg = templ; | ||
1324 | tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) | (arg ? CLOCAL : 0)); | 1695 | tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) | (arg ? CLOCAL : 0)); |
1325 | return 0; | 1696 | return 0; |
1326 | case TIOCGSERIAL: | 1697 | case TIOCGSERIAL: |
@@ -1340,30 +1711,19 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, unsigned int c | |||
1340 | cnow = info->icount; /* note the counters on entry */ | 1711 | cnow = info->icount; /* note the counters on entry */ |
1341 | spin_unlock_irqrestore(&info->slock, flags); | 1712 | spin_unlock_irqrestore(&info->slock, flags); |
1342 | 1713 | ||
1343 | wait_event_interruptible(info->delta_msr_wait, ({ | 1714 | return wait_event_interruptible(info->delta_msr_wait, |
1344 | cprev = cnow; | 1715 | mxser_cflags_changed(info, arg, &cnow)); |
1345 | spin_lock_irqsave(&info->slock, flags); | 1716 | /* |
1346 | cnow = info->icount; /* atomic copy */ | 1717 | * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) |
1347 | spin_unlock_irqrestore(&info->slock, flags); | 1718 | * Return: write counters to the user passed counter struct |
1348 | 1719 | * NB: both 1->0 and 0->1 transitions are counted except for | |
1349 | ((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || | 1720 | * RI where only 0->1 is counted. |
1350 | ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || | 1721 | */ |
1351 | ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || | ||
1352 | ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)); | ||
1353 | })); | ||
1354 | break; | ||
1355 | /* | ||
1356 | * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) | ||
1357 | * Return: write counters to the user passed counter struct | ||
1358 | * NB: both 1->0 and 0->1 transitions are counted except for | ||
1359 | * RI where only 0->1 is counted. | ||
1360 | */ | ||
1361 | case TIOCGICOUNT: | 1722 | case TIOCGICOUNT: |
1362 | spin_lock_irqsave(&info->slock, flags); | 1723 | spin_lock_irqsave(&info->slock, flags); |
1363 | cnow = info->icount; | 1724 | cnow = info->icount; |
1364 | spin_unlock_irqrestore(&info->slock, flags); | 1725 | spin_unlock_irqrestore(&info->slock, flags); |
1365 | p_cuser = argp; | 1726 | p_cuser = argp; |
1366 | /* modified by casper 1/11/2000 */ | ||
1367 | if (put_user(cnow.frame, &p_cuser->frame)) | 1727 | if (put_user(cnow.frame, &p_cuser->frame)) |
1368 | return -EFAULT; | 1728 | return -EFAULT; |
1369 | if (put_user(cnow.brk, &p_cuser->brk)) | 1729 | if (put_user(cnow.brk, &p_cuser->brk)) |
@@ -1385,240 +1745,65 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, unsigned int c | |||
1385 | return 0; | 1745 | return 0; |
1386 | case MOXA_HighSpeedOn: | 1746 | case MOXA_HighSpeedOn: |
1387 | return put_user(info->baud_base != 115200 ? 1 : 0, (int __user *)argp); | 1747 | return put_user(info->baud_base != 115200 ? 1 : 0, (int __user *)argp); |
1388 | case MOXA_SDS_RSTICOUNTER: { | 1748 | case MOXA_SDS_RSTICOUNTER: |
1389 | info->mon_data.rxcnt = 0; | 1749 | info->mon_data.rxcnt = 0; |
1390 | info->mon_data.txcnt = 0; | 1750 | info->mon_data.txcnt = 0; |
1391 | return 0; | ||
1392 | } | ||
1393 | /* (above) added by James. */ | ||
1394 | case MOXA_ASPP_SETBAUD:{ | ||
1395 | long baud; | ||
1396 | if (get_user(baud, (long __user *)argp)) | ||
1397 | return -EFAULT; | ||
1398 | mxser_set_baud(info, baud); | ||
1399 | return 0; | ||
1400 | } | ||
1401 | case MOXA_ASPP_GETBAUD: | ||
1402 | if (copy_to_user(argp, &info->realbaud, sizeof(long))) | ||
1403 | return -EFAULT; | ||
1404 | |||
1405 | return 0; | 1751 | return 0; |
1406 | 1752 | ||
1407 | case MOXA_ASPP_OQUEUE:{ | 1753 | case MOXA_ASPP_OQUEUE:{ |
1408 | int len, lsr; | 1754 | int len, lsr; |
1409 | 1755 | ||
1410 | len = mxser_chars_in_buffer(tty); | 1756 | len = mxser_chars_in_buffer(tty); |
1411 | 1757 | ||
1412 | lsr = inb(info->base + UART_LSR) & UART_LSR_TEMT; | 1758 | lsr = inb(info->ioaddr + UART_LSR) & UART_LSR_TEMT; |
1413 | 1759 | ||
1414 | len += (lsr ? 0 : 1); | 1760 | len += (lsr ? 0 : 1); |
1415 | 1761 | ||
1416 | if (copy_to_user(argp, &len, sizeof(int))) | 1762 | return put_user(len, (int __user *)argp); |
1417 | return -EFAULT; | 1763 | } |
1418 | |||
1419 | return 0; | ||
1420 | } | ||
1421 | case MOXA_ASPP_MON: { | 1764 | case MOXA_ASPP_MON: { |
1422 | int mcr, status; | 1765 | int mcr, status; |
1423 | |||
1424 | /* info->mon_data.ser_param = tty->termios->c_cflag; */ | ||
1425 | 1766 | ||
1426 | status = mxser_get_msr(info->base, 1, info->port, info); | 1767 | status = mxser_get_msr(info->ioaddr, 1, tty->index); |
1427 | mxser_check_modem_status(info, status); | 1768 | mxser_check_modem_status(info, status); |
1428 | |||
1429 | mcr = inb(info->base + UART_MCR); | ||
1430 | if (mcr & MOXA_MUST_MCR_XON_FLAG) | ||
1431 | info->mon_data.hold_reason &= ~NPPI_NOTIFY_XOFFHOLD; | ||
1432 | else | ||
1433 | info->mon_data.hold_reason |= NPPI_NOTIFY_XOFFHOLD; | ||
1434 | |||
1435 | if (mcr & MOXA_MUST_MCR_TX_XON) | ||
1436 | info->mon_data.hold_reason &= ~NPPI_NOTIFY_XOFFXENT; | ||
1437 | else | ||
1438 | info->mon_data.hold_reason |= NPPI_NOTIFY_XOFFXENT; | ||
1439 | |||
1440 | if (info->tty->hw_stopped) | ||
1441 | info->mon_data.hold_reason |= NPPI_NOTIFY_CTSHOLD; | ||
1442 | else | ||
1443 | info->mon_data.hold_reason &= ~NPPI_NOTIFY_CTSHOLD; | ||
1444 | |||
1445 | if (copy_to_user(argp, &info->mon_data, | ||
1446 | sizeof(struct mxser_mon))) | ||
1447 | return -EFAULT; | ||
1448 | |||
1449 | return 0; | ||
1450 | } | ||
1451 | |||
1452 | case MOXA_ASPP_LSTATUS: { | ||
1453 | if (copy_to_user(argp, &info->err_shadow, | ||
1454 | sizeof(unsigned char))) | ||
1455 | return -EFAULT; | ||
1456 | |||
1457 | info->err_shadow = 0; | ||
1458 | return 0; | ||
1459 | } | ||
1460 | case MOXA_SET_BAUD_METHOD: { | ||
1461 | int method; | ||
1462 | |||
1463 | if (get_user(method, (int __user *)argp)) | ||
1464 | return -EFAULT; | ||
1465 | mxser_set_baud_method[info->port] = method; | ||
1466 | if (copy_to_user(argp, &method, sizeof(int))) | ||
1467 | return -EFAULT; | ||
1468 | 1769 | ||
1469 | return 0; | 1770 | mcr = inb(info->ioaddr + UART_MCR); |
1470 | } | 1771 | if (mcr & MOXA_MUST_MCR_XON_FLAG) |
1471 | default: | 1772 | info->mon_data.hold_reason &= ~NPPI_NOTIFY_XOFFHOLD; |
1472 | return -ENOIOCTLCMD; | 1773 | else |
1473 | } | 1774 | info->mon_data.hold_reason |= NPPI_NOTIFY_XOFFHOLD; |
1474 | return 0; | ||
1475 | } | ||
1476 | 1775 | ||
1477 | #ifndef CMSPAR | 1776 | if (mcr & MOXA_MUST_MCR_TX_XON) |
1478 | #define CMSPAR 010000000000 | 1777 | info->mon_data.hold_reason &= ~NPPI_NOTIFY_XOFFXENT; |
1479 | #endif | 1778 | else |
1779 | info->mon_data.hold_reason |= NPPI_NOTIFY_XOFFXENT; | ||
1480 | 1780 | ||
1481 | static int mxser_ioctl_special(unsigned int cmd, void __user *argp) | 1781 | if (info->tty->hw_stopped) |
1482 | { | 1782 | info->mon_data.hold_reason |= NPPI_NOTIFY_CTSHOLD; |
1483 | int i, result, status; | 1783 | else |
1784 | info->mon_data.hold_reason &= ~NPPI_NOTIFY_CTSHOLD; | ||
1484 | 1785 | ||
1485 | switch (cmd) { | 1786 | if (copy_to_user(argp, &info->mon_data, |
1486 | case MOXA_GET_CONF: | 1787 | sizeof(struct mxser_mon))) |
1487 | if (copy_to_user(argp, mxsercfg, | ||
1488 | sizeof(struct mxser_hwconf) * 4)) | ||
1489 | return -EFAULT; | 1788 | return -EFAULT; |
1490 | return 0; | ||
1491 | case MOXA_GET_MAJOR: | ||
1492 | if (copy_to_user(argp, &ttymajor, sizeof(int))) | ||
1493 | return -EFAULT; | ||
1494 | return 0; | ||
1495 | 1789 | ||
1496 | case MOXA_GET_CUMAJOR: | ||
1497 | if (copy_to_user(argp, &calloutmajor, sizeof(int))) | ||
1498 | return -EFAULT; | ||
1499 | return 0; | 1790 | return 0; |
1500 | 1791 | } | |
1501 | case MOXA_CHKPORTENABLE: | 1792 | case MOXA_ASPP_LSTATUS: { |
1502 | result = 0; | 1793 | if (put_user(info->err_shadow, (unsigned char __user *)argp)) |
1503 | for (i = 0; i < MXSER_PORTS; i++) { | ||
1504 | if (mxvar_table[i].base) | ||
1505 | result |= (1 << i); | ||
1506 | } | ||
1507 | return put_user(result, (unsigned long __user *)argp); | ||
1508 | case MOXA_GETDATACOUNT: | ||
1509 | if (copy_to_user(argp, &mxvar_log, sizeof(mxvar_log))) | ||
1510 | return -EFAULT; | 1794 | return -EFAULT; |
1511 | return 0; | ||
1512 | case MOXA_GETMSTATUS: | ||
1513 | for (i = 0; i < MXSER_PORTS; i++) { | ||
1514 | GMStatus[i].ri = 0; | ||
1515 | if (!mxvar_table[i].base) { | ||
1516 | GMStatus[i].dcd = 0; | ||
1517 | GMStatus[i].dsr = 0; | ||
1518 | GMStatus[i].cts = 0; | ||
1519 | continue; | ||
1520 | } | ||
1521 | |||
1522 | if (!mxvar_table[i].tty || !mxvar_table[i].tty->termios) | ||
1523 | GMStatus[i].cflag = mxvar_table[i].normal_termios.c_cflag; | ||
1524 | else | ||
1525 | GMStatus[i].cflag = mxvar_table[i].tty->termios->c_cflag; | ||
1526 | |||
1527 | status = inb(mxvar_table[i].base + UART_MSR); | ||
1528 | if (status & 0x80 /*UART_MSR_DCD */ ) | ||
1529 | GMStatus[i].dcd = 1; | ||
1530 | else | ||
1531 | GMStatus[i].dcd = 0; | ||
1532 | |||
1533 | if (status & 0x20 /*UART_MSR_DSR */ ) | ||
1534 | GMStatus[i].dsr = 1; | ||
1535 | else | ||
1536 | GMStatus[i].dsr = 0; | ||
1537 | |||
1538 | 1795 | ||
1539 | if (status & 0x10 /*UART_MSR_CTS */ ) | 1796 | info->err_shadow = 0; |
1540 | GMStatus[i].cts = 1; | ||
1541 | else | ||
1542 | GMStatus[i].cts = 0; | ||
1543 | } | ||
1544 | if (copy_to_user(argp, GMStatus, | ||
1545 | sizeof(struct mxser_mstatus) * MXSER_PORTS)) | ||
1546 | return -EFAULT; | ||
1547 | return 0; | 1797 | return 0; |
1548 | case MOXA_ASPP_MON_EXT: { | 1798 | } |
1549 | int status; | 1799 | case MOXA_SET_BAUD_METHOD: { |
1550 | int opmode, p; | 1800 | int method; |
1551 | int shiftbit; | ||
1552 | unsigned cflag, iflag; | ||
1553 | |||
1554 | for (i = 0; i < MXSER_PORTS; i++) { | ||
1555 | if (!mxvar_table[i].base) | ||
1556 | continue; | ||
1557 | |||
1558 | status = mxser_get_msr(mxvar_table[i].base, 0, | ||
1559 | i, &(mxvar_table[i])); | ||
1560 | /* | ||
1561 | mxser_check_modem_status(&mxvar_table[i], | ||
1562 | status); | ||
1563 | */ | ||
1564 | if (status & UART_MSR_TERI) | ||
1565 | mxvar_table[i].icount.rng++; | ||
1566 | if (status & UART_MSR_DDSR) | ||
1567 | mxvar_table[i].icount.dsr++; | ||
1568 | if (status & UART_MSR_DDCD) | ||
1569 | mxvar_table[i].icount.dcd++; | ||
1570 | if (status & UART_MSR_DCTS) | ||
1571 | mxvar_table[i].icount.cts++; | ||
1572 | |||
1573 | mxvar_table[i].mon_data.modem_status = status; | ||
1574 | mon_data_ext.rx_cnt[i] = mxvar_table[i].mon_data.rxcnt; | ||
1575 | mon_data_ext.tx_cnt[i] = mxvar_table[i].mon_data.txcnt; | ||
1576 | mon_data_ext.up_rxcnt[i] = mxvar_table[i].mon_data.up_rxcnt; | ||
1577 | mon_data_ext.up_txcnt[i] = mxvar_table[i].mon_data.up_txcnt; | ||
1578 | mon_data_ext.modem_status[i] = mxvar_table[i].mon_data.modem_status; | ||
1579 | mon_data_ext.baudrate[i] = mxvar_table[i].realbaud; | ||
1580 | |||
1581 | if (!mxvar_table[i].tty || !mxvar_table[i].tty->termios) { | ||
1582 | cflag = mxvar_table[i].normal_termios.c_cflag; | ||
1583 | iflag = mxvar_table[i].normal_termios.c_iflag; | ||
1584 | } else { | ||
1585 | cflag = mxvar_table[i].tty->termios->c_cflag; | ||
1586 | iflag = mxvar_table[i].tty->termios->c_iflag; | ||
1587 | } | ||
1588 | |||
1589 | mon_data_ext.databits[i] = cflag & CSIZE; | ||
1590 | |||
1591 | mon_data_ext.stopbits[i] = cflag & CSTOPB; | ||
1592 | |||
1593 | mon_data_ext.parity[i] = cflag & (PARENB | PARODD | CMSPAR); | ||
1594 | |||
1595 | mon_data_ext.flowctrl[i] = 0x00; | ||
1596 | |||
1597 | if (cflag & CRTSCTS) | ||
1598 | mon_data_ext.flowctrl[i] |= 0x03; | ||
1599 | |||
1600 | if (iflag & (IXON | IXOFF)) | ||
1601 | mon_data_ext.flowctrl[i] |= 0x0C; | ||
1602 | |||
1603 | if (mxvar_table[i].type == PORT_16550A) | ||
1604 | mon_data_ext.fifo[i] = 1; | ||
1605 | else | ||
1606 | mon_data_ext.fifo[i] = 0; | ||
1607 | |||
1608 | p = i % 4; | ||
1609 | shiftbit = p * 2; | ||
1610 | opmode = inb(mxvar_table[i].opmode_ioaddr) >> shiftbit; | ||
1611 | opmode &= OP_MODE_MASK; | ||
1612 | |||
1613 | mon_data_ext.iftype[i] = opmode; | ||
1614 | |||
1615 | } | ||
1616 | if (copy_to_user(argp, &mon_data_ext, sizeof(struct mxser_mon_ext))) | ||
1617 | return -EFAULT; | ||
1618 | |||
1619 | return 0; | ||
1620 | 1801 | ||
1621 | } | 1802 | if (get_user(method, (int __user *)argp)) |
1803 | return -EFAULT; | ||
1804 | mxser_set_baud_method[tty->index] = method; | ||
1805 | return put_user(method, (int __user *)argp); | ||
1806 | } | ||
1622 | default: | 1807 | default: |
1623 | return -ENOIOCTLCMD; | 1808 | return -ENOIOCTLCMD; |
1624 | } | 1809 | } |
@@ -1627,107 +1812,105 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp) | |||
1627 | 1812 | ||
1628 | static void mxser_stoprx(struct tty_struct *tty) | 1813 | static void mxser_stoprx(struct tty_struct *tty) |
1629 | { | 1814 | { |
1630 | struct mxser_struct *info = tty->driver_data; | 1815 | struct mxser_port *info = tty->driver_data; |
1631 | /* unsigned long flags; */ | ||
1632 | 1816 | ||
1633 | info->ldisc_stop_rx = 1; | 1817 | info->ldisc_stop_rx = 1; |
1634 | if (I_IXOFF(tty)) { | 1818 | if (I_IXOFF(tty)) { |
1635 | /* MX_LOCK(&info->slock); */ | 1819 | if (info->board->chip_flag) { |
1636 | /* following add by Victor Yu. 09-02-2002 */ | ||
1637 | if (info->IsMoxaMustChipFlag) { | ||
1638 | info->IER &= ~MOXA_MUST_RECV_ISR; | 1820 | info->IER &= ~MOXA_MUST_RECV_ISR; |
1639 | outb(info->IER, info->base + UART_IER); | 1821 | outb(info->IER, info->ioaddr + UART_IER); |
1640 | } else { | 1822 | } else { |
1641 | /* above add by Victor Yu. 09-02-2002 */ | ||
1642 | info->x_char = STOP_CHAR(tty); | 1823 | info->x_char = STOP_CHAR(tty); |
1643 | /* mask by Victor Yu. 09-02-2002 */ | 1824 | outb(0, info->ioaddr + UART_IER); |
1644 | /* outb(info->IER, 0); */ | ||
1645 | outb(0, info->base + UART_IER); | ||
1646 | info->IER |= UART_IER_THRI; | 1825 | info->IER |= UART_IER_THRI; |
1647 | /* force Tx interrupt */ | 1826 | outb(info->IER, info->ioaddr + UART_IER); |
1648 | outb(info->IER, info->base + UART_IER); | 1827 | } |
1649 | } /* add by Victor Yu. 09-02-2002 */ | ||
1650 | /* MX_UNLOCK(&info->slock); */ | ||
1651 | } | 1828 | } |
1652 | 1829 | ||
1653 | if (info->tty->termios->c_cflag & CRTSCTS) { | 1830 | if (info->tty->termios->c_cflag & CRTSCTS) { |
1654 | /* MX_LOCK(&info->slock); */ | ||
1655 | info->MCR &= ~UART_MCR_RTS; | 1831 | info->MCR &= ~UART_MCR_RTS; |
1656 | outb(info->MCR, info->base + UART_MCR); | 1832 | outb(info->MCR, info->ioaddr + UART_MCR); |
1657 | /* MX_UNLOCK(&info->slock); */ | ||
1658 | } | 1833 | } |
1659 | } | 1834 | } |
1660 | 1835 | ||
1661 | static void mxser_startrx(struct tty_struct *tty) | 1836 | /* |
1837 | * This routine is called by the upper-layer tty layer to signal that | ||
1838 | * incoming characters should be throttled. | ||
1839 | */ | ||
1840 | static void mxser_throttle(struct tty_struct *tty) | ||
1841 | { | ||
1842 | mxser_stoprx(tty); | ||
1843 | } | ||
1844 | |||
1845 | static void mxser_unthrottle(struct tty_struct *tty) | ||
1662 | { | 1846 | { |
1663 | struct mxser_struct *info = tty->driver_data; | 1847 | struct mxser_port *info = tty->driver_data; |
1664 | /* unsigned long flags; */ | ||
1665 | 1848 | ||
1849 | /* startrx */ | ||
1666 | info->ldisc_stop_rx = 0; | 1850 | info->ldisc_stop_rx = 0; |
1667 | if (I_IXOFF(tty)) { | 1851 | if (I_IXOFF(tty)) { |
1668 | if (info->x_char) | 1852 | if (info->x_char) |
1669 | info->x_char = 0; | 1853 | info->x_char = 0; |
1670 | else { | 1854 | else { |
1671 | /* MX_LOCK(&info->slock); */ | 1855 | if (info->board->chip_flag) { |
1672 | |||
1673 | /* following add by Victor Yu. 09-02-2002 */ | ||
1674 | if (info->IsMoxaMustChipFlag) { | ||
1675 | info->IER |= MOXA_MUST_RECV_ISR; | 1856 | info->IER |= MOXA_MUST_RECV_ISR; |
1676 | outb(info->IER, info->base + UART_IER); | 1857 | outb(info->IER, info->ioaddr + UART_IER); |
1677 | } else { | 1858 | } else { |
1678 | /* above add by Victor Yu. 09-02-2002 */ | ||
1679 | |||
1680 | info->x_char = START_CHAR(tty); | 1859 | info->x_char = START_CHAR(tty); |
1681 | /* mask by Victor Yu. 09-02-2002 */ | 1860 | outb(0, info->ioaddr + UART_IER); |
1682 | /* outb(info->IER, 0); */ | ||
1683 | /* add by Victor Yu. 09-02-2002 */ | ||
1684 | outb(0, info->base + UART_IER); | ||
1685 | /* force Tx interrupt */ | ||
1686 | info->IER |= UART_IER_THRI; | 1861 | info->IER |= UART_IER_THRI; |
1687 | outb(info->IER, info->base + UART_IER); | 1862 | outb(info->IER, info->ioaddr + UART_IER); |
1688 | } /* add by Victor Yu. 09-02-2002 */ | 1863 | } |
1689 | /* MX_UNLOCK(&info->slock); */ | ||
1690 | } | 1864 | } |
1691 | } | 1865 | } |
1692 | 1866 | ||
1693 | if (info->tty->termios->c_cflag & CRTSCTS) { | 1867 | if (info->tty->termios->c_cflag & CRTSCTS) { |
1694 | /* MX_LOCK(&info->slock); */ | ||
1695 | info->MCR |= UART_MCR_RTS; | 1868 | info->MCR |= UART_MCR_RTS; |
1696 | outb(info->MCR, info->base + UART_MCR); | 1869 | outb(info->MCR, info->ioaddr + UART_MCR); |
1697 | /* MX_UNLOCK(&info->slock); */ | ||
1698 | } | 1870 | } |
1699 | } | 1871 | } |
1700 | 1872 | ||
1701 | /* | 1873 | /* |
1702 | * This routine is called by the upper-layer tty layer to signal that | 1874 | * mxser_stop() and mxser_start() |
1703 | * incoming characters should be throttled. | 1875 | * |
1876 | * This routines are called before setting or resetting tty->stopped. | ||
1877 | * They enable or disable transmitter interrupts, as necessary. | ||
1704 | */ | 1878 | */ |
1705 | static void mxser_throttle(struct tty_struct *tty) | 1879 | static void mxser_stop(struct tty_struct *tty) |
1706 | { | 1880 | { |
1707 | /* struct mxser_struct *info = tty->driver_data; */ | 1881 | struct mxser_port *info = tty->driver_data; |
1708 | /* unsigned long flags; */ | 1882 | unsigned long flags; |
1709 | 1883 | ||
1710 | /* MX_LOCK(&info->slock); */ | 1884 | spin_lock_irqsave(&info->slock, flags); |
1711 | mxser_stoprx(tty); | 1885 | if (info->IER & UART_IER_THRI) { |
1712 | /* MX_UNLOCK(&info->slock); */ | 1886 | info->IER &= ~UART_IER_THRI; |
1887 | outb(info->IER, info->ioaddr + UART_IER); | ||
1888 | } | ||
1889 | spin_unlock_irqrestore(&info->slock, flags); | ||
1713 | } | 1890 | } |
1714 | 1891 | ||
1715 | static void mxser_unthrottle(struct tty_struct *tty) | 1892 | static void mxser_start(struct tty_struct *tty) |
1716 | { | 1893 | { |
1717 | /* struct mxser_struct *info = tty->driver_data; */ | 1894 | struct mxser_port *info = tty->driver_data; |
1718 | /* unsigned long flags; */ | 1895 | unsigned long flags; |
1719 | 1896 | ||
1720 | /* MX_LOCK(&info->slock); */ | 1897 | spin_lock_irqsave(&info->slock, flags); |
1721 | mxser_startrx(tty); | 1898 | if (info->xmit_cnt && info->xmit_buf) { |
1722 | /* MX_UNLOCK(&info->slock); */ | 1899 | outb(info->IER & ~UART_IER_THRI, info->ioaddr + UART_IER); |
1900 | info->IER |= UART_IER_THRI; | ||
1901 | outb(info->IER, info->ioaddr + UART_IER); | ||
1902 | } | ||
1903 | spin_unlock_irqrestore(&info->slock, flags); | ||
1723 | } | 1904 | } |
1724 | 1905 | ||
1725 | static void mxser_set_termios(struct tty_struct *tty, struct ktermios *old_termios) | 1906 | static void mxser_set_termios(struct tty_struct *tty, struct ktermios *old_termios) |
1726 | { | 1907 | { |
1727 | struct mxser_struct *info = tty->driver_data; | 1908 | struct mxser_port *info = tty->driver_data; |
1728 | unsigned long flags; | 1909 | unsigned long flags; |
1729 | 1910 | ||
1911 | spin_lock_irqsave(&info->slock, flags); | ||
1730 | mxser_change_speed(info, old_termios); | 1912 | mxser_change_speed(info, old_termios); |
1913 | spin_unlock_irqrestore(&info->slock, flags); | ||
1731 | 1914 | ||
1732 | if ((old_termios->c_cflag & CRTSCTS) && | 1915 | if ((old_termios->c_cflag & CRTSCTS) && |
1733 | !(tty->termios->c_cflag & CRTSCTS)) { | 1916 | !(tty->termios->c_cflag & CRTSCTS)) { |
@@ -1735,61 +1918,27 @@ static void mxser_set_termios(struct tty_struct *tty, struct ktermios *old_termi | |||
1735 | mxser_start(tty); | 1918 | mxser_start(tty); |
1736 | } | 1919 | } |
1737 | 1920 | ||
1738 | /* Handle sw stopped */ | 1921 | /* Handle sw stopped */ |
1739 | if ((old_termios->c_iflag & IXON) && | 1922 | if ((old_termios->c_iflag & IXON) && |
1740 | !(tty->termios->c_iflag & IXON)) { | 1923 | !(tty->termios->c_iflag & IXON)) { |
1741 | tty->stopped = 0; | 1924 | tty->stopped = 0; |
1742 | 1925 | ||
1743 | /* following add by Victor Yu. 09-02-2002 */ | 1926 | if (info->board->chip_flag) { |
1744 | if (info->IsMoxaMustChipFlag) { | ||
1745 | spin_lock_irqsave(&info->slock, flags); | 1927 | spin_lock_irqsave(&info->slock, flags); |
1746 | DISABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(info->base); | 1928 | DISABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(info->ioaddr); |
1747 | spin_unlock_irqrestore(&info->slock, flags); | 1929 | spin_unlock_irqrestore(&info->slock, flags); |
1748 | } | 1930 | } |
1749 | /* above add by Victor Yu. 09-02-2002 */ | ||
1750 | 1931 | ||
1751 | mxser_start(tty); | 1932 | mxser_start(tty); |
1752 | } | 1933 | } |
1753 | } | 1934 | } |
1754 | 1935 | ||
1755 | /* | 1936 | /* |
1756 | * mxser_stop() and mxser_start() | ||
1757 | * | ||
1758 | * This routines are called before setting or resetting tty->stopped. | ||
1759 | * They enable or disable transmitter interrupts, as necessary. | ||
1760 | */ | ||
1761 | static void mxser_stop(struct tty_struct *tty) | ||
1762 | { | ||
1763 | struct mxser_struct *info = tty->driver_data; | ||
1764 | unsigned long flags; | ||
1765 | |||
1766 | spin_lock_irqsave(&info->slock, flags); | ||
1767 | if (info->IER & UART_IER_THRI) { | ||
1768 | info->IER &= ~UART_IER_THRI; | ||
1769 | outb(info->IER, info->base + UART_IER); | ||
1770 | } | ||
1771 | spin_unlock_irqrestore(&info->slock, flags); | ||
1772 | } | ||
1773 | |||
1774 | static void mxser_start(struct tty_struct *tty) | ||
1775 | { | ||
1776 | struct mxser_struct *info = tty->driver_data; | ||
1777 | unsigned long flags; | ||
1778 | |||
1779 | spin_lock_irqsave(&info->slock, flags); | ||
1780 | if (info->xmit_cnt && info->xmit_buf && !(info->IER & UART_IER_THRI)) { | ||
1781 | info->IER |= UART_IER_THRI; | ||
1782 | outb(info->IER, info->base + UART_IER); | ||
1783 | } | ||
1784 | spin_unlock_irqrestore(&info->slock, flags); | ||
1785 | } | ||
1786 | |||
1787 | /* | ||
1788 | * mxser_wait_until_sent() --- wait until the transmitter is empty | 1937 | * mxser_wait_until_sent() --- wait until the transmitter is empty |
1789 | */ | 1938 | */ |
1790 | static void mxser_wait_until_sent(struct tty_struct *tty, int timeout) | 1939 | static void mxser_wait_until_sent(struct tty_struct *tty, int timeout) |
1791 | { | 1940 | { |
1792 | struct mxser_struct *info = tty->driver_data; | 1941 | struct mxser_port *info = tty->driver_data; |
1793 | unsigned long orig_jiffies, char_time; | 1942 | unsigned long orig_jiffies, char_time; |
1794 | int lsr; | 1943 | int lsr; |
1795 | 1944 | ||
@@ -1830,7 +1979,7 @@ static void mxser_wait_until_sent(struct tty_struct *tty, int timeout) | |||
1830 | timeout, char_time); | 1979 | timeout, char_time); |
1831 | printk("jiff=%lu...", jiffies); | 1980 | printk("jiff=%lu...", jiffies); |
1832 | #endif | 1981 | #endif |
1833 | while (!((lsr = inb(info->base + UART_LSR)) & UART_LSR_TEMT)) { | 1982 | while (!((lsr = inb(info->ioaddr + UART_LSR)) & UART_LSR_TEMT)) { |
1834 | #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT | 1983 | #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT |
1835 | printk("lsr = %d (jiff=%lu)...", lsr, jiffies); | 1984 | printk("lsr = %d (jiff=%lu)...", lsr, jiffies); |
1836 | #endif | 1985 | #endif |
@@ -1847,13 +1996,12 @@ static void mxser_wait_until_sent(struct tty_struct *tty, int timeout) | |||
1847 | #endif | 1996 | #endif |
1848 | } | 1997 | } |
1849 | 1998 | ||
1850 | |||
1851 | /* | 1999 | /* |
1852 | * This routine is called by tty_hangup() when a hangup is signaled. | 2000 | * This routine is called by tty_hangup() when a hangup is signaled. |
1853 | */ | 2001 | */ |
1854 | void mxser_hangup(struct tty_struct *tty) | 2002 | static void mxser_hangup(struct tty_struct *tty) |
1855 | { | 2003 | { |
1856 | struct mxser_struct *info = tty->driver_data; | 2004 | struct mxser_port *info = tty->driver_data; |
1857 | 2005 | ||
1858 | mxser_flush_buffer(tty); | 2006 | mxser_flush_buffer(tty); |
1859 | mxser_shutdown(info); | 2007 | mxser_shutdown(info); |
@@ -1864,231 +2012,73 @@ void mxser_hangup(struct tty_struct *tty) | |||
1864 | wake_up_interruptible(&info->open_wait); | 2012 | wake_up_interruptible(&info->open_wait); |
1865 | } | 2013 | } |
1866 | 2014 | ||
1867 | |||
1868 | /* added by James 03-12-2004. */ | ||
1869 | /* | 2015 | /* |
1870 | * mxser_rs_break() --- routine which turns the break handling on or off | 2016 | * mxser_rs_break() --- routine which turns the break handling on or off |
1871 | */ | 2017 | */ |
1872 | static void mxser_rs_break(struct tty_struct *tty, int break_state) | 2018 | static void mxser_rs_break(struct tty_struct *tty, int break_state) |
1873 | { | 2019 | { |
1874 | struct mxser_struct *info = tty->driver_data; | 2020 | struct mxser_port *info = tty->driver_data; |
1875 | unsigned long flags; | 2021 | unsigned long flags; |
1876 | 2022 | ||
1877 | spin_lock_irqsave(&info->slock, flags); | 2023 | spin_lock_irqsave(&info->slock, flags); |
1878 | if (break_state == -1) | 2024 | if (break_state == -1) |
1879 | outb(inb(info->base + UART_LCR) | UART_LCR_SBC, | 2025 | outb(inb(info->ioaddr + UART_LCR) | UART_LCR_SBC, |
1880 | info->base + UART_LCR); | 2026 | info->ioaddr + UART_LCR); |
1881 | else | 2027 | else |
1882 | outb(inb(info->base + UART_LCR) & ~UART_LCR_SBC, | 2028 | outb(inb(info->ioaddr + UART_LCR) & ~UART_LCR_SBC, |
1883 | info->base + UART_LCR); | 2029 | info->ioaddr + UART_LCR); |
1884 | spin_unlock_irqrestore(&info->slock, flags); | 2030 | spin_unlock_irqrestore(&info->slock, flags); |
1885 | } | 2031 | } |
1886 | 2032 | ||
1887 | /* (above) added by James. */ | 2033 | static void mxser_receive_chars(struct mxser_port *port, int *status) |
1888 | |||
1889 | |||
1890 | /* | ||
1891 | * This is the serial driver's generic interrupt routine | ||
1892 | */ | ||
1893 | static irqreturn_t mxser_interrupt(int irq, void *dev_id) | ||
1894 | { | 2034 | { |
1895 | int status, iir, i; | 2035 | struct tty_struct *tty = port->tty; |
1896 | struct mxser_struct *info; | ||
1897 | struct mxser_struct *port; | ||
1898 | int max, irqbits, bits, msr; | ||
1899 | int pass_counter = 0; | ||
1900 | int handled = IRQ_NONE; | ||
1901 | |||
1902 | port = NULL; | ||
1903 | /* spin_lock(&gm_lock); */ | ||
1904 | |||
1905 | for (i = 0; i < MXSER_BOARDS; i++) { | ||
1906 | if (dev_id == &(mxvar_table[i * MXSER_PORTS_PER_BOARD])) { | ||
1907 | port = dev_id; | ||
1908 | break; | ||
1909 | } | ||
1910 | } | ||
1911 | |||
1912 | if (i == MXSER_BOARDS) | ||
1913 | goto irq_stop; | ||
1914 | if (port == 0) | ||
1915 | goto irq_stop; | ||
1916 | max = mxser_numports[mxsercfg[i].board_type - 1]; | ||
1917 | while (1) { | ||
1918 | irqbits = inb(port->vector) & port->vectormask; | ||
1919 | if (irqbits == port->vectormask) | ||
1920 | break; | ||
1921 | |||
1922 | handled = IRQ_HANDLED; | ||
1923 | for (i = 0, bits = 1; i < max; i++, irqbits |= bits, bits <<= 1) { | ||
1924 | if (irqbits == port->vectormask) | ||
1925 | break; | ||
1926 | if (bits & irqbits) | ||
1927 | continue; | ||
1928 | info = port + i; | ||
1929 | |||
1930 | /* following add by Victor Yu. 09-13-2002 */ | ||
1931 | iir = inb(info->base + UART_IIR); | ||
1932 | if (iir & UART_IIR_NO_INT) | ||
1933 | continue; | ||
1934 | iir &= MOXA_MUST_IIR_MASK; | ||
1935 | if (!info->tty) { | ||
1936 | status = inb(info->base + UART_LSR); | ||
1937 | outb(0x27, info->base + UART_FCR); | ||
1938 | inb(info->base + UART_MSR); | ||
1939 | continue; | ||
1940 | } | ||
1941 | |||
1942 | /* mask by Victor Yu. 09-13-2002 | ||
1943 | if ( !info->tty || | ||
1944 | (inb(info->base + UART_IIR) & UART_IIR_NO_INT) ) | ||
1945 | continue; | ||
1946 | */ | ||
1947 | /* mask by Victor Yu. 09-02-2002 | ||
1948 | status = inb(info->base + UART_LSR) & info->read_status_mask; | ||
1949 | */ | ||
1950 | |||
1951 | /* following add by Victor Yu. 09-02-2002 */ | ||
1952 | status = inb(info->base + UART_LSR); | ||
1953 | |||
1954 | if (status & UART_LSR_PE) | ||
1955 | info->err_shadow |= NPPI_NOTIFY_PARITY; | ||
1956 | if (status & UART_LSR_FE) | ||
1957 | info->err_shadow |= NPPI_NOTIFY_FRAMING; | ||
1958 | if (status & UART_LSR_OE) | ||
1959 | info->err_shadow |= NPPI_NOTIFY_HW_OVERRUN; | ||
1960 | if (status & UART_LSR_BI) | ||
1961 | info->err_shadow |= NPPI_NOTIFY_BREAK; | ||
1962 | |||
1963 | if (info->IsMoxaMustChipFlag) { | ||
1964 | /* | ||
1965 | if ( (status & 0x02) && !(status & 0x01) ) { | ||
1966 | outb(info->base+UART_FCR, 0x23); | ||
1967 | continue; | ||
1968 | } | ||
1969 | */ | ||
1970 | if (iir == MOXA_MUST_IIR_GDA || | ||
1971 | iir == MOXA_MUST_IIR_RDA || | ||
1972 | iir == MOXA_MUST_IIR_RTO || | ||
1973 | iir == MOXA_MUST_IIR_LSR) | ||
1974 | mxser_receive_chars(info, &status); | ||
1975 | |||
1976 | } else { | ||
1977 | /* above add by Victor Yu. 09-02-2002 */ | ||
1978 | |||
1979 | status &= info->read_status_mask; | ||
1980 | if (status & UART_LSR_DR) | ||
1981 | mxser_receive_chars(info, &status); | ||
1982 | } | ||
1983 | msr = inb(info->base + UART_MSR); | ||
1984 | if (msr & UART_MSR_ANY_DELTA) { | ||
1985 | mxser_check_modem_status(info, msr); | ||
1986 | } | ||
1987 | /* following add by Victor Yu. 09-13-2002 */ | ||
1988 | if (info->IsMoxaMustChipFlag) { | ||
1989 | if ((iir == 0x02) && (status & UART_LSR_THRE)) { | ||
1990 | mxser_transmit_chars(info); | ||
1991 | } | ||
1992 | } else { | ||
1993 | /* above add by Victor Yu. 09-13-2002 */ | ||
1994 | |||
1995 | if (status & UART_LSR_THRE) { | ||
1996 | /* 8-2-99 by William | ||
1997 | if ( info->x_char || (info->xmit_cnt > 0) ) | ||
1998 | */ | ||
1999 | mxser_transmit_chars(info); | ||
2000 | } | ||
2001 | } | ||
2002 | } | ||
2003 | if (pass_counter++ > MXSER_ISR_PASS_LIMIT) { | ||
2004 | break; /* Prevent infinite loops */ | ||
2005 | } | ||
2006 | } | ||
2007 | |||
2008 | irq_stop: | ||
2009 | /* spin_unlock(&gm_lock); */ | ||
2010 | return handled; | ||
2011 | } | ||
2012 | |||
2013 | static void mxser_receive_chars(struct mxser_struct *info, int *status) | ||
2014 | { | ||
2015 | struct tty_struct *tty = info->tty; | ||
2016 | unsigned char ch, gdl; | 2036 | unsigned char ch, gdl; |
2017 | int ignored = 0; | 2037 | int ignored = 0; |
2018 | int cnt = 0; | 2038 | int cnt = 0; |
2019 | int recv_room; | 2039 | int recv_room; |
2020 | int max = 256; | 2040 | int max = 256; |
2021 | unsigned long flags; | ||
2022 | |||
2023 | spin_lock_irqsave(&info->slock, flags); | ||
2024 | 2041 | ||
2025 | recv_room = tty->receive_room; | 2042 | recv_room = tty->receive_room; |
2026 | if ((recv_room == 0) && (!info->ldisc_stop_rx)) { | 2043 | if ((recv_room == 0) && (!port->ldisc_stop_rx)) |
2027 | /* mxser_throttle(tty); */ | ||
2028 | mxser_stoprx(tty); | 2044 | mxser_stoprx(tty); |
2029 | /* return; */ | ||
2030 | } | ||
2031 | 2045 | ||
2032 | /* following add by Victor Yu. 09-02-2002 */ | 2046 | if (port->board->chip_flag != MOXA_OTHER_UART) { |
2033 | if (info->IsMoxaMustChipFlag != MOXA_OTHER_UART) { | ||
2034 | 2047 | ||
2035 | if (*status & UART_LSR_SPECIAL) { | 2048 | if (*status & UART_LSR_SPECIAL) |
2036 | goto intr_old; | 2049 | goto intr_old; |
2037 | } | 2050 | if (port->board->chip_flag == MOXA_MUST_MU860_HWID && |
2038 | /* following add by Victor Yu. 02-11-2004 */ | ||
2039 | if (info->IsMoxaMustChipFlag == MOXA_MUST_MU860_HWID && | ||
2040 | (*status & MOXA_MUST_LSR_RERR)) | 2051 | (*status & MOXA_MUST_LSR_RERR)) |
2041 | goto intr_old; | 2052 | goto intr_old; |
2042 | /* above add by Victor Yu. 02-14-2004 */ | ||
2043 | if (*status & MOXA_MUST_LSR_RERR) | 2053 | if (*status & MOXA_MUST_LSR_RERR) |
2044 | goto intr_old; | 2054 | goto intr_old; |
2045 | 2055 | ||
2046 | gdl = inb(info->base + MOXA_MUST_GDL_REGISTER); | 2056 | gdl = inb(port->ioaddr + MOXA_MUST_GDL_REGISTER); |
2047 | 2057 | ||
2048 | /* add by Victor Yu. 02-11-2004 */ | 2058 | if (port->board->chip_flag == MOXA_MUST_MU150_HWID) |
2049 | if (info->IsMoxaMustChipFlag == MOXA_MUST_MU150_HWID) | ||
2050 | gdl &= MOXA_MUST_GDL_MASK; | 2059 | gdl &= MOXA_MUST_GDL_MASK; |
2051 | if (gdl >= recv_room) { | 2060 | if (gdl >= recv_room) { |
2052 | if (!info->ldisc_stop_rx) { | 2061 | if (!port->ldisc_stop_rx) |
2053 | /* mxser_throttle(tty); */ | ||
2054 | mxser_stoprx(tty); | 2062 | mxser_stoprx(tty); |
2055 | } | ||
2056 | /* return; */ | ||
2057 | } | 2063 | } |
2058 | while (gdl--) { | 2064 | while (gdl--) { |
2059 | ch = inb(info->base + UART_RX); | 2065 | ch = inb(port->ioaddr + UART_RX); |
2060 | tty_insert_flip_char(tty, ch, 0); | 2066 | tty_insert_flip_char(tty, ch, 0); |
2061 | cnt++; | 2067 | cnt++; |
2062 | /* | ||
2063 | if ((cnt >= HI_WATER) && (info->stop_rx == 0)) { | ||
2064 | mxser_stoprx(tty); | ||
2065 | info->stop_rx = 1; | ||
2066 | break; | ||
2067 | } */ | ||
2068 | } | 2068 | } |
2069 | goto end_intr; | 2069 | goto end_intr; |
2070 | } | 2070 | } |
2071 | intr_old: | 2071 | intr_old: |
2072 | /* above add by Victor Yu. 09-02-2002 */ | ||
2073 | 2072 | ||
2074 | do { | 2073 | do { |
2075 | if (max-- < 0) | 2074 | if (max-- < 0) |
2076 | break; | 2075 | break; |
2077 | /* | ||
2078 | if ((cnt >= HI_WATER) && (info->stop_rx == 0)) { | ||
2079 | mxser_stoprx(tty); | ||
2080 | info->stop_rx=1; | ||
2081 | break; | ||
2082 | } | ||
2083 | */ | ||
2084 | 2076 | ||
2085 | ch = inb(info->base + UART_RX); | 2077 | ch = inb(port->ioaddr + UART_RX); |
2086 | /* following add by Victor Yu. 09-02-2002 */ | 2078 | if (port->board->chip_flag && (*status & UART_LSR_OE)) |
2087 | if (info->IsMoxaMustChipFlag && (*status & UART_LSR_OE) /*&& !(*status&UART_LSR_DR) */ ) | 2079 | outb(0x23, port->ioaddr + UART_FCR); |
2088 | outb(0x23, info->base + UART_FCR); | 2080 | *status &= port->read_status_mask; |
2089 | *status &= info->read_status_mask; | 2081 | if (*status & port->ignore_status_mask) { |
2090 | /* above add by Victor Yu. 09-02-2002 */ | ||
2091 | if (*status & info->ignore_status_mask) { | ||
2092 | if (++ignored > 100) | 2082 | if (++ignored > 100) |
2093 | break; | 2083 | break; |
2094 | } else { | 2084 | } else { |
@@ -2096,1038 +2086,652 @@ static void mxser_receive_chars(struct mxser_struct *info, int *status) | |||
2096 | if (*status & UART_LSR_SPECIAL) { | 2086 | if (*status & UART_LSR_SPECIAL) { |
2097 | if (*status & UART_LSR_BI) { | 2087 | if (*status & UART_LSR_BI) { |
2098 | flag = TTY_BREAK; | 2088 | flag = TTY_BREAK; |
2099 | /* added by casper 1/11/2000 */ | 2089 | port->icount.brk++; |
2100 | info->icount.brk++; | 2090 | |
2101 | /* */ | 2091 | if (port->flags & ASYNC_SAK) |
2102 | if (info->flags & ASYNC_SAK) | ||
2103 | do_SAK(tty); | 2092 | do_SAK(tty); |
2104 | } else if (*status & UART_LSR_PE) { | 2093 | } else if (*status & UART_LSR_PE) { |
2105 | flag = TTY_PARITY; | 2094 | flag = TTY_PARITY; |
2106 | /* added by casper 1/11/2000 */ | 2095 | port->icount.parity++; |
2107 | info->icount.parity++; | ||
2108 | /* */ | ||
2109 | } else if (*status & UART_LSR_FE) { | 2096 | } else if (*status & UART_LSR_FE) { |
2110 | flag = TTY_FRAME; | 2097 | flag = TTY_FRAME; |
2111 | /* added by casper 1/11/2000 */ | 2098 | port->icount.frame++; |
2112 | info->icount.frame++; | ||
2113 | /* */ | ||
2114 | } else if (*status & UART_LSR_OE) { | 2099 | } else if (*status & UART_LSR_OE) { |
2115 | flag = TTY_OVERRUN; | 2100 | flag = TTY_OVERRUN; |
2116 | /* added by casper 1/11/2000 */ | 2101 | port->icount.overrun++; |
2117 | info->icount.overrun++; | 2102 | } else |
2118 | /* */ | 2103 | flag = TTY_BREAK; |
2119 | } | ||
2120 | } | 2104 | } |
2121 | tty_insert_flip_char(tty, ch, flag); | 2105 | tty_insert_flip_char(tty, ch, flag); |
2122 | cnt++; | 2106 | cnt++; |
2123 | if (cnt >= recv_room) { | 2107 | if (cnt >= recv_room) { |
2124 | if (!info->ldisc_stop_rx) { | 2108 | if (!port->ldisc_stop_rx) |
2125 | /* mxser_throttle(tty); */ | ||
2126 | mxser_stoprx(tty); | 2109 | mxser_stoprx(tty); |
2127 | } | ||
2128 | break; | 2110 | break; |
2129 | } | 2111 | } |
2130 | 2112 | ||
2131 | } | 2113 | } |
2132 | 2114 | ||
2133 | /* following add by Victor Yu. 09-02-2002 */ | 2115 | if (port->board->chip_flag) |
2134 | if (info->IsMoxaMustChipFlag) | ||
2135 | break; | 2116 | break; |
2136 | /* above add by Victor Yu. 09-02-2002 */ | ||
2137 | 2117 | ||
2138 | /* mask by Victor Yu. 09-02-2002 | 2118 | *status = inb(port->ioaddr + UART_LSR); |
2139 | *status = inb(info->base + UART_LSR) & info->read_status_mask; | ||
2140 | */ | ||
2141 | /* following add by Victor Yu. 09-02-2002 */ | ||
2142 | *status = inb(info->base + UART_LSR); | ||
2143 | /* above add by Victor Yu. 09-02-2002 */ | ||
2144 | } while (*status & UART_LSR_DR); | 2119 | } while (*status & UART_LSR_DR); |
2145 | 2120 | ||
2146 | end_intr: /* add by Victor Yu. 09-02-2002 */ | 2121 | end_intr: |
2147 | mxvar_log.rxcnt[info->port] += cnt; | 2122 | mxvar_log.rxcnt[port->tty->index] += cnt; |
2148 | info->mon_data.rxcnt += cnt; | 2123 | port->mon_data.rxcnt += cnt; |
2149 | info->mon_data.up_rxcnt += cnt; | 2124 | port->mon_data.up_rxcnt += cnt; |
2150 | spin_unlock_irqrestore(&info->slock, flags); | ||
2151 | 2125 | ||
2126 | /* | ||
2127 | * We are called from an interrupt context with &port->slock | ||
2128 | * being held. Drop it temporarily in order to prevent | ||
2129 | * recursive locking. | ||
2130 | */ | ||
2131 | spin_unlock(&port->slock); | ||
2152 | tty_flip_buffer_push(tty); | 2132 | tty_flip_buffer_push(tty); |
2133 | spin_lock(&port->slock); | ||
2153 | } | 2134 | } |
2154 | 2135 | ||
2155 | static void mxser_transmit_chars(struct mxser_struct *info) | 2136 | static void mxser_transmit_chars(struct mxser_port *port) |
2156 | { | 2137 | { |
2157 | int count, cnt; | 2138 | int count, cnt; |
2158 | unsigned long flags; | ||
2159 | 2139 | ||
2160 | spin_lock_irqsave(&info->slock, flags); | 2140 | if (port->x_char) { |
2161 | 2141 | outb(port->x_char, port->ioaddr + UART_TX); | |
2162 | if (info->x_char) { | 2142 | port->x_char = 0; |
2163 | outb(info->x_char, info->base + UART_TX); | 2143 | mxvar_log.txcnt[port->tty->index]++; |
2164 | info->x_char = 0; | 2144 | port->mon_data.txcnt++; |
2165 | mxvar_log.txcnt[info->port]++; | 2145 | port->mon_data.up_txcnt++; |
2166 | info->mon_data.txcnt++; | 2146 | port->icount.tx++; |
2167 | info->mon_data.up_txcnt++; | ||
2168 | |||
2169 | /* added by casper 1/11/2000 */ | ||
2170 | info->icount.tx++; | ||
2171 | /* */ | ||
2172 | spin_unlock_irqrestore(&info->slock, flags); | ||
2173 | return; | 2147 | return; |
2174 | } | 2148 | } |
2175 | 2149 | ||
2176 | if (info->xmit_buf == 0) { | 2150 | if (port->xmit_buf == NULL) |
2177 | spin_unlock_irqrestore(&info->slock, flags); | ||
2178 | return; | 2151 | return; |
2179 | } | ||
2180 | 2152 | ||
2181 | if ((info->xmit_cnt <= 0) || info->tty->stopped || | 2153 | if ((port->xmit_cnt <= 0) || port->tty->stopped || |
2182 | (info->tty->hw_stopped && | 2154 | (port->tty->hw_stopped && |
2183 | (info->type != PORT_16550A) && | 2155 | (port->type != PORT_16550A) && |
2184 | (!info->IsMoxaMustChipFlag))) { | 2156 | (!port->board->chip_flag))) { |
2185 | info->IER &= ~UART_IER_THRI; | 2157 | port->IER &= ~UART_IER_THRI; |
2186 | outb(info->IER, info->base + UART_IER); | 2158 | outb(port->IER, port->ioaddr + UART_IER); |
2187 | spin_unlock_irqrestore(&info->slock, flags); | ||
2188 | return; | 2159 | return; |
2189 | } | 2160 | } |
2190 | 2161 | ||
2191 | cnt = info->xmit_cnt; | 2162 | cnt = port->xmit_cnt; |
2192 | count = info->xmit_fifo_size; | 2163 | count = port->xmit_fifo_size; |
2193 | do { | 2164 | do { |
2194 | outb(info->xmit_buf[info->xmit_tail++], | 2165 | outb(port->xmit_buf[port->xmit_tail++], |
2195 | info->base + UART_TX); | 2166 | port->ioaddr + UART_TX); |
2196 | info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE - 1); | 2167 | port->xmit_tail = port->xmit_tail & (SERIAL_XMIT_SIZE - 1); |
2197 | if (--info->xmit_cnt <= 0) | 2168 | if (--port->xmit_cnt <= 0) |
2198 | break; | 2169 | break; |
2199 | } while (--count > 0); | 2170 | } while (--count > 0); |
2200 | mxvar_log.txcnt[info->port] += (cnt - info->xmit_cnt); | 2171 | mxvar_log.txcnt[port->tty->index] += (cnt - port->xmit_cnt); |
2201 | 2172 | ||
2202 | /* added by James 03-12-2004. */ | 2173 | port->mon_data.txcnt += (cnt - port->xmit_cnt); |
2203 | info->mon_data.txcnt += (cnt - info->xmit_cnt); | 2174 | port->mon_data.up_txcnt += (cnt - port->xmit_cnt); |
2204 | info->mon_data.up_txcnt += (cnt - info->xmit_cnt); | 2175 | port->icount.tx += (cnt - port->xmit_cnt); |
2205 | /* (above) added by James. */ | ||
2206 | 2176 | ||
2207 | /* added by casper 1/11/2000 */ | 2177 | if (port->xmit_cnt < WAKEUP_CHARS) |
2208 | info->icount.tx += (cnt - info->xmit_cnt); | 2178 | tty_wakeup(port->tty); |
2209 | /* */ | ||
2210 | 2179 | ||
2211 | if (info->xmit_cnt < WAKEUP_CHARS) { | 2180 | if (port->xmit_cnt <= 0) { |
2212 | set_bit(MXSER_EVENT_TXLOW, &info->event); | 2181 | port->IER &= ~UART_IER_THRI; |
2213 | schedule_work(&info->tqueue); | 2182 | outb(port->IER, port->ioaddr + UART_IER); |
2214 | } | 2183 | } |
2215 | if (info->xmit_cnt <= 0) { | ||
2216 | info->IER &= ~UART_IER_THRI; | ||
2217 | outb(info->IER, info->base + UART_IER); | ||
2218 | } | ||
2219 | spin_unlock_irqrestore(&info->slock, flags); | ||
2220 | } | 2184 | } |
2221 | 2185 | ||
2222 | static void mxser_check_modem_status(struct mxser_struct *info, int status) | 2186 | /* |
2187 | * This is the serial driver's generic interrupt routine | ||
2188 | */ | ||
2189 | static irqreturn_t mxser_interrupt(int irq, void *dev_id) | ||
2223 | { | 2190 | { |
2224 | /* update input line counters */ | 2191 | int status, iir, i; |
2225 | if (status & UART_MSR_TERI) | 2192 | struct mxser_board *brd = NULL; |
2226 | info->icount.rng++; | 2193 | struct mxser_port *port; |
2227 | if (status & UART_MSR_DDSR) | 2194 | int max, irqbits, bits, msr; |
2228 | info->icount.dsr++; | 2195 | unsigned int int_cnt, pass_counter = 0; |
2229 | if (status & UART_MSR_DDCD) | 2196 | int handled = IRQ_NONE; |
2230 | info->icount.dcd++; | ||
2231 | if (status & UART_MSR_DCTS) | ||
2232 | info->icount.cts++; | ||
2233 | info->mon_data.modem_status = status; | ||
2234 | wake_up_interruptible(&info->delta_msr_wait); | ||
2235 | |||
2236 | if ((info->flags & ASYNC_CHECK_CD) && (status & UART_MSR_DDCD)) { | ||
2237 | if (status & UART_MSR_DCD) | ||
2238 | wake_up_interruptible(&info->open_wait); | ||
2239 | schedule_work(&info->tqueue); | ||
2240 | } | ||
2241 | |||
2242 | if (info->flags & ASYNC_CTS_FLOW) { | ||
2243 | if (info->tty->hw_stopped) { | ||
2244 | if (status & UART_MSR_CTS) { | ||
2245 | info->tty->hw_stopped = 0; | ||
2246 | 2197 | ||
2247 | if ((info->type != PORT_16550A) && | 2198 | for (i = 0; i < MXSER_BOARDS; i++) |
2248 | (!info->IsMoxaMustChipFlag)) { | 2199 | if (dev_id == &mxser_boards[i]) { |
2249 | info->IER |= UART_IER_THRI; | 2200 | brd = dev_id; |
2250 | outb(info->IER, info->base + UART_IER); | 2201 | break; |
2251 | } | ||
2252 | set_bit(MXSER_EVENT_TXLOW, &info->event); | ||
2253 | schedule_work(&info->tqueue); } | ||
2254 | } else { | ||
2255 | if (!(status & UART_MSR_CTS)) { | ||
2256 | info->tty->hw_stopped = 1; | ||
2257 | if ((info->type != PORT_16550A) && | ||
2258 | (!info->IsMoxaMustChipFlag)) { | ||
2259 | info->IER &= ~UART_IER_THRI; | ||
2260 | outb(info->IER, info->base + UART_IER); | ||
2261 | } | ||
2262 | } | ||
2263 | } | 2202 | } |
2264 | } | ||
2265 | } | ||
2266 | 2203 | ||
2267 | static int mxser_block_til_ready(struct tty_struct *tty, struct file *filp, struct mxser_struct *info) | 2204 | if (i == MXSER_BOARDS) |
2268 | { | 2205 | goto irq_stop; |
2269 | DECLARE_WAITQUEUE(wait, current); | 2206 | if (brd == NULL) |
2270 | int retval; | 2207 | goto irq_stop; |
2271 | int do_clocal = 0; | 2208 | max = brd->info->nports; |
2272 | unsigned long flags; | 2209 | while (pass_counter++ < MXSER_ISR_PASS_LIMIT) { |
2273 | 2210 | irqbits = inb(brd->vector) & brd->vector_mask; | |
2274 | /* | 2211 | if (irqbits == brd->vector_mask) |
2275 | * If non-blocking mode is set, or the port is not enabled, | 2212 | break; |
2276 | * then make the check up front and then exit. | ||
2277 | */ | ||
2278 | if ((filp->f_flags & O_NONBLOCK) || (tty->flags & (1 << TTY_IO_ERROR))) { | ||
2279 | info->flags |= ASYNC_NORMAL_ACTIVE; | ||
2280 | return 0; | ||
2281 | } | ||
2282 | 2213 | ||
2283 | if (tty->termios->c_cflag & CLOCAL) | 2214 | handled = IRQ_HANDLED; |
2284 | do_clocal = 1; | 2215 | for (i = 0, bits = 1; i < max; i++, irqbits |= bits, bits <<= 1) { |
2216 | if (irqbits == brd->vector_mask) | ||
2217 | break; | ||
2218 | if (bits & irqbits) | ||
2219 | continue; | ||
2220 | port = &brd->ports[i]; | ||
2221 | |||
2222 | int_cnt = 0; | ||
2223 | spin_lock(&port->slock); | ||
2224 | do { | ||
2225 | iir = inb(port->ioaddr + UART_IIR); | ||
2226 | if (iir & UART_IIR_NO_INT) | ||
2227 | break; | ||
2228 | iir &= MOXA_MUST_IIR_MASK; | ||
2229 | if (!port->tty || | ||
2230 | (port->flags & ASYNC_CLOSING) || | ||
2231 | !(port->flags & | ||
2232 | ASYNC_INITIALIZED)) { | ||
2233 | status = inb(port->ioaddr + UART_LSR); | ||
2234 | outb(0x27, port->ioaddr + UART_FCR); | ||
2235 | inb(port->ioaddr + UART_MSR); | ||
2236 | break; | ||
2237 | } | ||
2285 | 2238 | ||
2286 | /* | 2239 | status = inb(port->ioaddr + UART_LSR); |
2287 | * Block waiting for the carrier detect and the line to become | 2240 | |
2288 | * free (i.e., not in use by the callout). While we are in | 2241 | if (status & UART_LSR_PE) |
2289 | * this loop, info->count is dropped by one, so that | 2242 | port->err_shadow |= NPPI_NOTIFY_PARITY; |
2290 | * mxser_close() knows when to free things. We restore it upon | 2243 | if (status & UART_LSR_FE) |
2291 | * exit, either normal or abnormal. | 2244 | port->err_shadow |= NPPI_NOTIFY_FRAMING; |
2292 | */ | 2245 | if (status & UART_LSR_OE) |
2293 | retval = 0; | 2246 | port->err_shadow |= |
2294 | add_wait_queue(&info->open_wait, &wait); | 2247 | NPPI_NOTIFY_HW_OVERRUN; |
2248 | if (status & UART_LSR_BI) | ||
2249 | port->err_shadow |= NPPI_NOTIFY_BREAK; | ||
2250 | |||
2251 | if (port->board->chip_flag) { | ||
2252 | if (iir == MOXA_MUST_IIR_GDA || | ||
2253 | iir == MOXA_MUST_IIR_RDA || | ||
2254 | iir == MOXA_MUST_IIR_RTO || | ||
2255 | iir == MOXA_MUST_IIR_LSR) | ||
2256 | mxser_receive_chars(port, | ||
2257 | &status); | ||
2295 | 2258 | ||
2296 | spin_lock_irqsave(&info->slock, flags); | 2259 | } else { |
2297 | if (!tty_hung_up_p(filp)) | 2260 | status &= port->read_status_mask; |
2298 | info->count--; | 2261 | if (status & UART_LSR_DR) |
2299 | spin_unlock_irqrestore(&info->slock, flags); | 2262 | mxser_receive_chars(port, |
2300 | info->blocked_open++; | 2263 | &status); |
2301 | while (1) { | 2264 | } |
2302 | spin_lock_irqsave(&info->slock, flags); | 2265 | msr = inb(port->ioaddr + UART_MSR); |
2303 | outb(inb(info->base + UART_MCR) | | 2266 | if (msr & UART_MSR_ANY_DELTA) |
2304 | UART_MCR_DTR | UART_MCR_RTS, info->base + UART_MCR); | 2267 | mxser_check_modem_status(port, msr); |
2305 | spin_unlock_irqrestore(&info->slock, flags); | 2268 | |
2306 | set_current_state(TASK_INTERRUPTIBLE); | 2269 | if (port->board->chip_flag) { |
2307 | if (tty_hung_up_p(filp) || !(info->flags & ASYNC_INITIALIZED)) { | 2270 | if (iir == 0x02 && (status & |
2308 | if (info->flags & ASYNC_HUP_NOTIFY) | 2271 | UART_LSR_THRE)) |
2309 | retval = -EAGAIN; | 2272 | mxser_transmit_chars(port); |
2310 | else | 2273 | } else { |
2311 | retval = -ERESTARTSYS; | 2274 | if (status & UART_LSR_THRE) |
2312 | break; | 2275 | mxser_transmit_chars(port); |
2313 | } | 2276 | } |
2314 | if (!(info->flags & ASYNC_CLOSING) && | 2277 | } while (int_cnt++ < MXSER_ISR_PASS_LIMIT); |
2315 | (do_clocal || | 2278 | spin_unlock(&port->slock); |
2316 | (inb(info->base + UART_MSR) & UART_MSR_DCD))) | ||
2317 | break; | ||
2318 | if (signal_pending(current)) { | ||
2319 | retval = -ERESTARTSYS; | ||
2320 | break; | ||
2321 | } | 2279 | } |
2322 | schedule(); | ||
2323 | } | 2280 | } |
2324 | set_current_state(TASK_RUNNING); | ||
2325 | remove_wait_queue(&info->open_wait, &wait); | ||
2326 | if (!tty_hung_up_p(filp)) | ||
2327 | info->count++; | ||
2328 | info->blocked_open--; | ||
2329 | if (retval) | ||
2330 | return retval; | ||
2331 | info->flags |= ASYNC_NORMAL_ACTIVE; | ||
2332 | return 0; | ||
2333 | } | ||
2334 | 2281 | ||
2335 | static int mxser_startup(struct mxser_struct *info) | 2282 | irq_stop: |
2336 | { | 2283 | return handled; |
2337 | unsigned long page; | 2284 | } |
2338 | unsigned long flags; | ||
2339 | |||
2340 | page = __get_free_page(GFP_KERNEL); | ||
2341 | if (!page) | ||
2342 | return -ENOMEM; | ||
2343 | |||
2344 | spin_lock_irqsave(&info->slock, flags); | ||
2345 | |||
2346 | if (info->flags & ASYNC_INITIALIZED) { | ||
2347 | free_page(page); | ||
2348 | spin_unlock_irqrestore(&info->slock, flags); | ||
2349 | return 0; | ||
2350 | } | ||
2351 | 2285 | ||
2352 | if (!info->base || !info->type) { | 2286 | static const struct tty_operations mxser_ops = { |
2353 | if (info->tty) | 2287 | .open = mxser_open, |
2354 | set_bit(TTY_IO_ERROR, &info->tty->flags); | 2288 | .close = mxser_close, |
2355 | free_page(page); | 2289 | .write = mxser_write, |
2356 | spin_unlock_irqrestore(&info->slock, flags); | 2290 | .put_char = mxser_put_char, |
2357 | return 0; | 2291 | .flush_chars = mxser_flush_chars, |
2358 | } | 2292 | .write_room = mxser_write_room, |
2359 | if (info->xmit_buf) | 2293 | .chars_in_buffer = mxser_chars_in_buffer, |
2360 | free_page(page); | 2294 | .flush_buffer = mxser_flush_buffer, |
2361 | else | 2295 | .ioctl = mxser_ioctl, |
2362 | info->xmit_buf = (unsigned char *) page; | 2296 | .throttle = mxser_throttle, |
2297 | .unthrottle = mxser_unthrottle, | ||
2298 | .set_termios = mxser_set_termios, | ||
2299 | .stop = mxser_stop, | ||
2300 | .start = mxser_start, | ||
2301 | .hangup = mxser_hangup, | ||
2302 | .break_ctl = mxser_rs_break, | ||
2303 | .wait_until_sent = mxser_wait_until_sent, | ||
2304 | .tiocmget = mxser_tiocmget, | ||
2305 | .tiocmset = mxser_tiocmset, | ||
2306 | }; | ||
2363 | 2307 | ||
2364 | /* | 2308 | /* |
2365 | * Clear the FIFO buffers and disable them | 2309 | * The MOXA Smartio/Industio serial driver boot-time initialization code! |
2366 | * (they will be reenabled in mxser_change_speed()) | 2310 | */ |
2367 | */ | ||
2368 | if (info->IsMoxaMustChipFlag) | ||
2369 | outb((UART_FCR_CLEAR_RCVR | | ||
2370 | UART_FCR_CLEAR_XMIT | | ||
2371 | MOXA_MUST_FCR_GDA_MODE_ENABLE), info->base + UART_FCR); | ||
2372 | else | ||
2373 | outb((UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT), | ||
2374 | info->base + UART_FCR); | ||
2375 | 2311 | ||
2376 | /* | 2312 | static void mxser_release_res(struct mxser_board *brd, struct pci_dev *pdev, |
2377 | * At this point there's no way the LSR could still be 0xFF; | 2313 | unsigned int irq) |
2378 | * if it is, then bail out, because there's likely no UART | 2314 | { |
2379 | * here. | 2315 | if (irq) |
2380 | */ | 2316 | free_irq(brd->irq, brd); |
2381 | if (inb(info->base + UART_LSR) == 0xff) { | 2317 | if (pdev != NULL) { /* PCI */ |
2382 | spin_unlock_irqrestore(&info->slock, flags); | 2318 | #ifdef CONFIG_PCI |
2383 | if (capable(CAP_SYS_ADMIN)) { | 2319 | pci_release_region(pdev, 2); |
2384 | if (info->tty) | 2320 | pci_release_region(pdev, 3); |
2385 | set_bit(TTY_IO_ERROR, &info->tty->flags); | 2321 | #endif |
2386 | return 0; | 2322 | } else { |
2387 | } else | 2323 | release_region(brd->ports[0].ioaddr, 8 * brd->info->nports); |
2388 | return -ENODEV; | 2324 | release_region(brd->vector, 1); |
2389 | } | 2325 | } |
2390 | |||
2391 | /* | ||
2392 | * Clear the interrupt registers. | ||
2393 | */ | ||
2394 | (void) inb(info->base + UART_LSR); | ||
2395 | (void) inb(info->base + UART_RX); | ||
2396 | (void) inb(info->base + UART_IIR); | ||
2397 | (void) inb(info->base + UART_MSR); | ||
2398 | |||
2399 | /* | ||
2400 | * Now, initialize the UART | ||
2401 | */ | ||
2402 | outb(UART_LCR_WLEN8, info->base + UART_LCR); /* reset DLAB */ | ||
2403 | info->MCR = UART_MCR_DTR | UART_MCR_RTS; | ||
2404 | outb(info->MCR, info->base + UART_MCR); | ||
2405 | |||
2406 | /* | ||
2407 | * Finally, enable interrupts | ||
2408 | */ | ||
2409 | info->IER = UART_IER_MSI | UART_IER_RLSI | UART_IER_RDI; | ||
2410 | /* info->IER = UART_IER_RLSI | UART_IER_RDI; */ | ||
2411 | |||
2412 | /* following add by Victor Yu. 08-30-2002 */ | ||
2413 | if (info->IsMoxaMustChipFlag) | ||
2414 | info->IER |= MOXA_MUST_IER_EGDAI; | ||
2415 | /* above add by Victor Yu. 08-30-2002 */ | ||
2416 | outb(info->IER, info->base + UART_IER); /* enable interrupts */ | ||
2417 | |||
2418 | /* | ||
2419 | * And clear the interrupt registers again for luck. | ||
2420 | */ | ||
2421 | (void) inb(info->base + UART_LSR); | ||
2422 | (void) inb(info->base + UART_RX); | ||
2423 | (void) inb(info->base + UART_IIR); | ||
2424 | (void) inb(info->base + UART_MSR); | ||
2425 | |||
2426 | if (info->tty) | ||
2427 | clear_bit(TTY_IO_ERROR, &info->tty->flags); | ||
2428 | info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; | ||
2429 | |||
2430 | /* | ||
2431 | * and set the speed of the serial port | ||
2432 | */ | ||
2433 | spin_unlock_irqrestore(&info->slock, flags); | ||
2434 | mxser_change_speed(info, NULL); | ||
2435 | |||
2436 | info->flags |= ASYNC_INITIALIZED; | ||
2437 | return 0; | ||
2438 | } | 2326 | } |
2439 | 2327 | ||
2440 | /* | 2328 | static int __devinit mxser_initbrd(struct mxser_board *brd, |
2441 | * This routine will shutdown a serial port; interrupts maybe disabled, and | 2329 | struct pci_dev *pdev) |
2442 | * DTR is dropped if the hangup on close termio flag is on. | ||
2443 | */ | ||
2444 | static void mxser_shutdown(struct mxser_struct *info) | ||
2445 | { | 2330 | { |
2446 | unsigned long flags; | 2331 | struct mxser_port *info; |
2447 | 2332 | unsigned int i; | |
2448 | if (!(info->flags & ASYNC_INITIALIZED)) | 2333 | int retval; |
2449 | return; | ||
2450 | |||
2451 | spin_lock_irqsave(&info->slock, flags); | ||
2452 | |||
2453 | /* | ||
2454 | * clear delta_msr_wait queue to avoid mem leaks: we may free the irq | ||
2455 | * here so the queue might never be waken up | ||
2456 | */ | ||
2457 | wake_up_interruptible(&info->delta_msr_wait); | ||
2458 | |||
2459 | /* | ||
2460 | * Free the IRQ, if necessary | ||
2461 | */ | ||
2462 | if (info->xmit_buf) { | ||
2463 | free_page((unsigned long) info->xmit_buf); | ||
2464 | info->xmit_buf = NULL; | ||
2465 | } | ||
2466 | 2334 | ||
2467 | info->IER = 0; | 2335 | printk(KERN_INFO "max. baud rate = %d bps.\n", brd->ports[0].max_baud); |
2468 | outb(0x00, info->base + UART_IER); | ||
2469 | 2336 | ||
2470 | if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) | 2337 | for (i = 0; i < brd->info->nports; i++) { |
2471 | info->MCR &= ~(UART_MCR_DTR | UART_MCR_RTS); | 2338 | info = &brd->ports[i]; |
2472 | outb(info->MCR, info->base + UART_MCR); | 2339 | info->board = brd; |
2340 | info->stop_rx = 0; | ||
2341 | info->ldisc_stop_rx = 0; | ||
2473 | 2342 | ||
2474 | /* clear Rx/Tx FIFO's */ | 2343 | /* Enhance mode enabled here */ |
2475 | /* following add by Victor Yu. 08-30-2002 */ | 2344 | if (brd->chip_flag != MOXA_OTHER_UART) |
2476 | if (info->IsMoxaMustChipFlag) | 2345 | ENABLE_MOXA_MUST_ENCHANCE_MODE(info->ioaddr); |
2477 | outb((UART_FCR_CLEAR_RCVR | | ||
2478 | UART_FCR_CLEAR_XMIT | | ||
2479 | MOXA_MUST_FCR_GDA_MODE_ENABLE), info->base + UART_FCR); | ||
2480 | else | ||
2481 | /* above add by Victor Yu. 08-30-2002 */ | ||
2482 | outb((UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT), | ||
2483 | info->base + UART_FCR); | ||
2484 | 2346 | ||
2485 | /* read data port to reset things */ | 2347 | info->flags = ASYNC_SHARE_IRQ; |
2486 | (void) inb(info->base + UART_RX); | 2348 | info->type = brd->uart_type; |
2487 | 2349 | ||
2488 | if (info->tty) | 2350 | process_txrx_fifo(info); |
2489 | set_bit(TTY_IO_ERROR, &info->tty->flags); | ||
2490 | 2351 | ||
2491 | info->flags &= ~ASYNC_INITIALIZED; | 2352 | info->custom_divisor = info->baud_base * 16; |
2353 | info->close_delay = 5 * HZ / 10; | ||
2354 | info->closing_wait = 30 * HZ; | ||
2355 | info->normal_termios = mxvar_sdriver->init_termios; | ||
2356 | init_waitqueue_head(&info->open_wait); | ||
2357 | init_waitqueue_head(&info->delta_msr_wait); | ||
2358 | memset(&info->mon_data, 0, sizeof(struct mxser_mon)); | ||
2359 | info->err_shadow = 0; | ||
2360 | spin_lock_init(&info->slock); | ||
2492 | 2361 | ||
2493 | /* following add by Victor Yu. 09-23-2002 */ | 2362 | /* before set INT ISR, disable all int */ |
2494 | if (info->IsMoxaMustChipFlag) | 2363 | outb(inb(info->ioaddr + UART_IER) & 0xf0, |
2495 | SET_MOXA_MUST_NO_SOFTWARE_FLOW_CONTROL(info->base); | 2364 | info->ioaddr + UART_IER); |
2496 | /* above add by Victor Yu. 09-23-2002 */ | 2365 | } |
2497 | 2366 | ||
2498 | spin_unlock_irqrestore(&info->slock, flags); | 2367 | retval = request_irq(brd->irq, mxser_interrupt, IRQF_SHARED, "mxser", |
2368 | brd); | ||
2369 | if (retval) { | ||
2370 | printk(KERN_ERR "Board %s: Request irq failed, IRQ (%d) may " | ||
2371 | "conflict with another device.\n", | ||
2372 | brd->info->name, brd->irq); | ||
2373 | /* We hold resources, we need to release them. */ | ||
2374 | mxser_release_res(brd, pdev, 0); | ||
2375 | } | ||
2376 | return retval; | ||
2499 | } | 2377 | } |
2500 | 2378 | ||
2501 | /* | 2379 | static int __init mxser_get_ISA_conf(int cap, struct mxser_board *brd) |
2502 | * This routine is called to set the UART divisor registers to match | ||
2503 | * the specified baud rate for a serial port. | ||
2504 | */ | ||
2505 | static int mxser_change_speed(struct mxser_struct *info, struct ktermios *old_termios) | ||
2506 | { | 2380 | { |
2507 | unsigned cflag, cval, fcr; | 2381 | int id, i, bits; |
2508 | int ret = 0; | 2382 | unsigned short regs[16], irq; |
2509 | unsigned char status; | 2383 | unsigned char scratch, scratch2; |
2510 | long baud; | ||
2511 | unsigned long flags; | ||
2512 | |||
2513 | if (!info->tty || !info->tty->termios) | ||
2514 | return ret; | ||
2515 | cflag = info->tty->termios->c_cflag; | ||
2516 | if (!(info->base)) | ||
2517 | return ret; | ||
2518 | 2384 | ||
2519 | #ifndef B921600 | 2385 | brd->chip_flag = MOXA_OTHER_UART; |
2520 | #define B921600 (B460800 +1) | ||
2521 | #endif | ||
2522 | if (mxser_set_baud_method[info->port] == 0) { | ||
2523 | baud = tty_get_baud_rate(info->tty); | ||
2524 | mxser_set_baud(info, baud); | ||
2525 | } | ||
2526 | 2386 | ||
2527 | /* byte size and parity */ | 2387 | id = mxser_read_register(cap, regs); |
2528 | switch (cflag & CSIZE) { | 2388 | switch (id) { |
2529 | case CS5: | 2389 | case C168_ASIC_ID: |
2530 | cval = 0x00; | 2390 | brd->info = &mxser_cards[0]; |
2531 | break; | 2391 | break; |
2532 | case CS6: | 2392 | case C104_ASIC_ID: |
2533 | cval = 0x01; | 2393 | brd->info = &mxser_cards[1]; |
2534 | break; | 2394 | break; |
2535 | case CS7: | 2395 | case CI104J_ASIC_ID: |
2536 | cval = 0x02; | 2396 | brd->info = &mxser_cards[2]; |
2537 | break; | 2397 | break; |
2538 | case CS8: | 2398 | case C102_ASIC_ID: |
2539 | cval = 0x03; | 2399 | brd->info = &mxser_cards[5]; |
2400 | break; | ||
2401 | case CI132_ASIC_ID: | ||
2402 | brd->info = &mxser_cards[6]; | ||
2403 | break; | ||
2404 | case CI134_ASIC_ID: | ||
2405 | brd->info = &mxser_cards[7]; | ||
2540 | break; | 2406 | break; |
2541 | default: | 2407 | default: |
2542 | cval = 0x00; | 2408 | return 0; |
2543 | break; /* too keep GCC shut... */ | ||
2544 | } | 2409 | } |
2545 | if (cflag & CSTOPB) | ||
2546 | cval |= 0x04; | ||
2547 | if (cflag & PARENB) | ||
2548 | cval |= UART_LCR_PARITY; | ||
2549 | if (!(cflag & PARODD)) | ||
2550 | cval |= UART_LCR_EPAR; | ||
2551 | if (cflag & CMSPAR) | ||
2552 | cval |= UART_LCR_SPAR; | ||
2553 | 2410 | ||
2554 | if ((info->type == PORT_8250) || (info->type == PORT_16450)) { | 2411 | irq = 0; |
2555 | if (info->IsMoxaMustChipFlag) { | 2412 | /* some ISA cards have 2 ports, but we want to see them as 4-port (why?) |
2556 | fcr = UART_FCR_ENABLE_FIFO; | 2413 | Flag-hack checks if configuration should be read as 2-port here. */ |
2557 | fcr |= MOXA_MUST_FCR_GDA_MODE_ENABLE; | 2414 | if (brd->info->nports == 2 || (brd->info->flags & MXSER_HAS2)) { |
2558 | SET_MOXA_MUST_FIFO_VALUE(info); | 2415 | irq = regs[9] & 0xF000; |
2559 | } else | 2416 | irq = irq | (irq >> 4); |
2560 | fcr = 0; | 2417 | if (irq != (regs[9] & 0xFF00)) |
2561 | } else { | 2418 | return MXSER_ERR_IRQ_CONFLIT; |
2562 | fcr = UART_FCR_ENABLE_FIFO; | 2419 | } else if (brd->info->nports == 4) { |
2563 | /* following add by Victor Yu. 08-30-2002 */ | 2420 | irq = regs[9] & 0xF000; |
2564 | if (info->IsMoxaMustChipFlag) { | 2421 | irq = irq | (irq >> 4); |
2565 | fcr |= MOXA_MUST_FCR_GDA_MODE_ENABLE; | 2422 | irq = irq | (irq >> 8); |
2566 | SET_MOXA_MUST_FIFO_VALUE(info); | 2423 | if (irq != regs[9]) |
2567 | } else { | 2424 | return MXSER_ERR_IRQ_CONFLIT; |
2568 | /* above add by Victor Yu. 08-30-2002 */ | 2425 | } else if (brd->info->nports == 8) { |
2569 | switch (info->rx_trigger) { | 2426 | irq = regs[9] & 0xF000; |
2570 | case 1: | 2427 | irq = irq | (irq >> 4); |
2571 | fcr |= UART_FCR_TRIGGER_1; | 2428 | irq = irq | (irq >> 8); |
2572 | break; | 2429 | if ((irq != regs[9]) || (irq != regs[10])) |
2573 | case 4: | 2430 | return MXSER_ERR_IRQ_CONFLIT; |
2574 | fcr |= UART_FCR_TRIGGER_4; | ||
2575 | break; | ||
2576 | case 8: | ||
2577 | fcr |= UART_FCR_TRIGGER_8; | ||
2578 | break; | ||
2579 | default: | ||
2580 | fcr |= UART_FCR_TRIGGER_14; | ||
2581 | break; | ||
2582 | } | ||
2583 | } | ||
2584 | } | 2431 | } |
2585 | 2432 | ||
2586 | /* CTS flow control flag and modem status interrupts */ | 2433 | if (!irq) |
2587 | info->IER &= ~UART_IER_MSI; | 2434 | return MXSER_ERR_IRQ; |
2588 | info->MCR &= ~UART_MCR_AFE; | 2435 | brd->irq = ((int)(irq & 0xF000) >> 12); |
2589 | if (cflag & CRTSCTS) { | 2436 | for (i = 0; i < 8; i++) |
2590 | info->flags |= ASYNC_CTS_FLOW; | 2437 | brd->ports[i].ioaddr = (int) regs[i + 1] & 0xFFF8; |
2591 | info->IER |= UART_IER_MSI; | 2438 | if ((regs[12] & 0x80) == 0) |
2592 | if ((info->type == PORT_16550A) || (info->IsMoxaMustChipFlag)) { | 2439 | return MXSER_ERR_VECTOR; |
2593 | info->MCR |= UART_MCR_AFE; | 2440 | brd->vector = (int)regs[11]; /* interrupt vector */ |
2441 | if (id == 1) | ||
2442 | brd->vector_mask = 0x00FF; | ||
2443 | else | ||
2444 | brd->vector_mask = 0x000F; | ||
2445 | for (i = 7, bits = 0x0100; i >= 0; i--, bits <<= 1) { | ||
2446 | if (regs[12] & bits) { | ||
2447 | brd->ports[i].baud_base = 921600; | ||
2448 | brd->ports[i].max_baud = 921600; | ||
2594 | } else { | 2449 | } else { |
2595 | status = inb(info->base + UART_MSR); | 2450 | brd->ports[i].baud_base = 115200; |
2596 | if (info->tty->hw_stopped) { | 2451 | brd->ports[i].max_baud = 115200; |
2597 | if (status & UART_MSR_CTS) { | ||
2598 | info->tty->hw_stopped = 0; | ||
2599 | if ((info->type != PORT_16550A) && | ||
2600 | (!info->IsMoxaMustChipFlag)) { | ||
2601 | info->IER |= UART_IER_THRI; | ||
2602 | outb(info->IER, info->base + UART_IER); | ||
2603 | } | ||
2604 | set_bit(MXSER_EVENT_TXLOW, &info->event); | ||
2605 | schedule_work(&info->tqueue); } | ||
2606 | } else { | ||
2607 | if (!(status & UART_MSR_CTS)) { | ||
2608 | info->tty->hw_stopped = 1; | ||
2609 | if ((info->type != PORT_16550A) && | ||
2610 | (!info->IsMoxaMustChipFlag)) { | ||
2611 | info->IER &= ~UART_IER_THRI; | ||
2612 | outb(info->IER, info->base + UART_IER); | ||
2613 | } | ||
2614 | } | ||
2615 | } | ||
2616 | } | 2452 | } |
2617 | } else { | ||
2618 | info->flags &= ~ASYNC_CTS_FLOW; | ||
2619 | } | ||
2620 | outb(info->MCR, info->base + UART_MCR); | ||
2621 | if (cflag & CLOCAL) { | ||
2622 | info->flags &= ~ASYNC_CHECK_CD; | ||
2623 | } else { | ||
2624 | info->flags |= ASYNC_CHECK_CD; | ||
2625 | info->IER |= UART_IER_MSI; | ||
2626 | } | 2453 | } |
2627 | outb(info->IER, info->base + UART_IER); | 2454 | scratch2 = inb(cap + UART_LCR) & (~UART_LCR_DLAB); |
2628 | 2455 | outb(scratch2 | UART_LCR_DLAB, cap + UART_LCR); | |
2629 | /* | 2456 | outb(0, cap + UART_EFR); /* EFR is the same as FCR */ |
2630 | * Set up parity check flag | 2457 | outb(scratch2, cap + UART_LCR); |
2631 | */ | 2458 | outb(UART_FCR_ENABLE_FIFO, cap + UART_FCR); |
2632 | info->read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR; | 2459 | scratch = inb(cap + UART_IIR); |
2633 | if (I_INPCK(info->tty)) | ||
2634 | info->read_status_mask |= UART_LSR_FE | UART_LSR_PE; | ||
2635 | if (I_BRKINT(info->tty) || I_PARMRK(info->tty)) | ||
2636 | info->read_status_mask |= UART_LSR_BI; | ||
2637 | |||
2638 | info->ignore_status_mask = 0; | ||
2639 | 2460 | ||
2640 | if (I_IGNBRK(info->tty)) { | 2461 | if (scratch & 0xC0) |
2641 | info->ignore_status_mask |= UART_LSR_BI; | 2462 | brd->uart_type = PORT_16550A; |
2642 | info->read_status_mask |= UART_LSR_BI; | 2463 | else |
2643 | /* | 2464 | brd->uart_type = PORT_16450; |
2644 | * If we're ignore parity and break indicators, ignore | 2465 | if (!request_region(brd->ports[0].ioaddr, 8 * brd->info->nports, |
2645 | * overruns too. (For real raw support). | 2466 | "mxser(IO)")) |
2646 | */ | 2467 | return MXSER_ERR_IOADDR; |
2647 | if (I_IGNPAR(info->tty)) { | 2468 | if (!request_region(brd->vector, 1, "mxser(vector)")) { |
2648 | info->ignore_status_mask |= | 2469 | release_region(brd->ports[0].ioaddr, 8 * brd->info->nports); |
2649 | UART_LSR_OE | | 2470 | return MXSER_ERR_VECTOR; |
2650 | UART_LSR_PE | | ||
2651 | UART_LSR_FE; | ||
2652 | info->read_status_mask |= | ||
2653 | UART_LSR_OE | | ||
2654 | UART_LSR_PE | | ||
2655 | UART_LSR_FE; | ||
2656 | } | ||
2657 | } | ||
2658 | /* following add by Victor Yu. 09-02-2002 */ | ||
2659 | if (info->IsMoxaMustChipFlag) { | ||
2660 | spin_lock_irqsave(&info->slock, flags); | ||
2661 | SET_MOXA_MUST_XON1_VALUE(info->base, START_CHAR(info->tty)); | ||
2662 | SET_MOXA_MUST_XOFF1_VALUE(info->base, STOP_CHAR(info->tty)); | ||
2663 | if (I_IXON(info->tty)) { | ||
2664 | ENABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(info->base); | ||
2665 | } else { | ||
2666 | DISABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(info->base); | ||
2667 | } | ||
2668 | if (I_IXOFF(info->tty)) { | ||
2669 | ENABLE_MOXA_MUST_TX_SOFTWARE_FLOW_CONTROL(info->base); | ||
2670 | } else { | ||
2671 | DISABLE_MOXA_MUST_TX_SOFTWARE_FLOW_CONTROL(info->base); | ||
2672 | } | ||
2673 | /* | ||
2674 | if ( I_IXANY(info->tty) ) { | ||
2675 | info->MCR |= MOXA_MUST_MCR_XON_ANY; | ||
2676 | ENABLE_MOXA_MUST_XON_ANY_FLOW_CONTROL(info->base); | ||
2677 | } else { | ||
2678 | info->MCR &= ~MOXA_MUST_MCR_XON_ANY; | ||
2679 | DISABLE_MOXA_MUST_XON_ANY_FLOW_CONTROL(info->base); | ||
2680 | } | ||
2681 | */ | ||
2682 | spin_unlock_irqrestore(&info->slock, flags); | ||
2683 | } | 2471 | } |
2684 | /* above add by Victor Yu. 09-02-2002 */ | 2472 | return brd->info->nports; |
2685 | |||
2686 | |||
2687 | outb(fcr, info->base + UART_FCR); /* set fcr */ | ||
2688 | outb(cval, info->base + UART_LCR); | ||
2689 | |||
2690 | return ret; | ||
2691 | } | 2473 | } |
2692 | 2474 | ||
2693 | 2475 | static int __devinit mxser_probe(struct pci_dev *pdev, | |
2694 | static int mxser_set_baud(struct mxser_struct *info, long newspd) | 2476 | const struct pci_device_id *ent) |
2695 | { | 2477 | { |
2696 | int quot = 0; | 2478 | #ifdef CONFIG_PCI |
2697 | unsigned char cval; | 2479 | struct mxser_board *brd; |
2698 | int ret = 0; | 2480 | unsigned int i, j; |
2699 | unsigned long flags; | 2481 | unsigned long ioaddress; |
2700 | 2482 | int retval = -EINVAL; | |
2701 | if (!info->tty || !info->tty->termios) | ||
2702 | return ret; | ||
2703 | |||
2704 | if (!(info->base)) | ||
2705 | return ret; | ||
2706 | 2483 | ||
2707 | if (newspd > info->MaxCanSetBaudRate) | 2484 | for (i = 0; i < MXSER_BOARDS; i++) |
2708 | return 0; | 2485 | if (mxser_boards[i].info == NULL) |
2486 | break; | ||
2709 | 2487 | ||
2710 | info->realbaud = newspd; | 2488 | if (i >= MXSER_BOARDS) { |
2711 | if (newspd == 134) { | 2489 | printk(KERN_ERR "Too many Smartio/Industio family boards found " |
2712 | quot = (2 * info->baud_base / 269); | 2490 | "(maximum %d), board not configured\n", MXSER_BOARDS); |
2713 | } else if (newspd) { | 2491 | goto err; |
2714 | quot = info->baud_base / newspd; | ||
2715 | if (quot == 0) | ||
2716 | quot = 1; | ||
2717 | } else { | ||
2718 | quot = 0; | ||
2719 | } | 2492 | } |
2720 | 2493 | ||
2721 | info->timeout = ((info->xmit_fifo_size * HZ * 10 * quot) / info->baud_base); | 2494 | brd = &mxser_boards[i]; |
2722 | info->timeout += HZ / 50; /* Add .02 seconds of slop */ | 2495 | brd->idx = i * MXSER_PORTS_PER_BOARD; |
2496 | printk(KERN_INFO "Found MOXA %s board (BusNo=%d, DevNo=%d)\n", | ||
2497 | mxser_cards[ent->driver_data].name, | ||
2498 | pdev->bus->number, PCI_SLOT(pdev->devfn)); | ||
2723 | 2499 | ||
2724 | if (quot) { | 2500 | retval = pci_enable_device(pdev); |
2725 | spin_lock_irqsave(&info->slock, flags); | 2501 | if (retval) { |
2726 | info->MCR |= UART_MCR_DTR; | 2502 | printk(KERN_ERR "Moxa SmartI/O PCI enable fail !\n"); |
2727 | outb(info->MCR, info->base + UART_MCR); | 2503 | goto err; |
2728 | spin_unlock_irqrestore(&info->slock, flags); | ||
2729 | } else { | ||
2730 | spin_lock_irqsave(&info->slock, flags); | ||
2731 | info->MCR &= ~UART_MCR_DTR; | ||
2732 | outb(info->MCR, info->base + UART_MCR); | ||
2733 | spin_unlock_irqrestore(&info->slock, flags); | ||
2734 | return ret; | ||
2735 | } | 2504 | } |
2736 | 2505 | ||
2737 | cval = inb(info->base + UART_LCR); | 2506 | /* io address */ |
2738 | 2507 | ioaddress = pci_resource_start(pdev, 2); | |
2739 | outb(cval | UART_LCR_DLAB, info->base + UART_LCR); /* set DLAB */ | 2508 | retval = pci_request_region(pdev, 2, "mxser(IO)"); |
2740 | 2509 | if (retval) | |
2741 | outb(quot & 0xff, info->base + UART_DLL); /* LS of divisor */ | 2510 | goto err; |
2742 | outb(quot >> 8, info->base + UART_DLM); /* MS of divisor */ | ||
2743 | outb(cval, info->base + UART_LCR); /* reset DLAB */ | ||
2744 | |||
2745 | 2511 | ||
2746 | return ret; | 2512 | brd->info = &mxser_cards[ent->driver_data]; |
2747 | } | 2513 | for (i = 0; i < brd->info->nports; i++) |
2514 | brd->ports[i].ioaddr = ioaddress + 8 * i; | ||
2748 | 2515 | ||
2749 | /* | 2516 | /* vector */ |
2750 | * ------------------------------------------------------------ | 2517 | ioaddress = pci_resource_start(pdev, 3); |
2751 | * friends of mxser_ioctl() | 2518 | retval = pci_request_region(pdev, 3, "mxser(vector)"); |
2752 | * ------------------------------------------------------------ | 2519 | if (retval) |
2753 | */ | 2520 | goto err_relio; |
2754 | static int mxser_get_serial_info(struct mxser_struct *info, struct serial_struct __user *retinfo) | 2521 | brd->vector = ioaddress; |
2755 | { | ||
2756 | struct serial_struct tmp; | ||
2757 | 2522 | ||
2758 | if (!retinfo) | 2523 | /* irq */ |
2759 | return -EFAULT; | 2524 | brd->irq = pdev->irq; |
2760 | memset(&tmp, 0, sizeof(tmp)); | ||
2761 | tmp.type = info->type; | ||
2762 | tmp.line = info->port; | ||
2763 | tmp.port = info->base; | ||
2764 | tmp.irq = info->irq; | ||
2765 | tmp.flags = info->flags; | ||
2766 | tmp.baud_base = info->baud_base; | ||
2767 | tmp.close_delay = info->close_delay; | ||
2768 | tmp.closing_wait = info->closing_wait; | ||
2769 | tmp.custom_divisor = info->custom_divisor; | ||
2770 | tmp.hub6 = 0; | ||
2771 | if (copy_to_user(retinfo, &tmp, sizeof(*retinfo))) | ||
2772 | return -EFAULT; | ||
2773 | return 0; | ||
2774 | } | ||
2775 | 2525 | ||
2776 | static int mxser_set_serial_info(struct mxser_struct *info, struct serial_struct __user *new_info) | 2526 | brd->chip_flag = CheckIsMoxaMust(brd->ports[0].ioaddr); |
2777 | { | 2527 | brd->uart_type = PORT_16550A; |
2778 | struct serial_struct new_serial; | 2528 | brd->vector_mask = 0; |
2779 | unsigned int flags; | ||
2780 | int retval = 0; | ||
2781 | 2529 | ||
2782 | if (!new_info || !info->base) | 2530 | for (i = 0; i < brd->info->nports; i++) { |
2783 | return -EFAULT; | 2531 | for (j = 0; j < UART_INFO_NUM; j++) { |
2784 | if (copy_from_user(&new_serial, new_info, sizeof(new_serial))) | 2532 | if (Gpci_uart_info[j].type == brd->chip_flag) { |
2785 | return -EFAULT; | 2533 | brd->ports[i].max_baud = |
2534 | Gpci_uart_info[j].max_baud; | ||
2786 | 2535 | ||
2787 | if ((new_serial.irq != info->irq) || | 2536 | /* exception....CP-102 */ |
2788 | (new_serial.port != info->base) || | 2537 | if (brd->info->flags & MXSER_HIGHBAUD) |
2789 | (new_serial.custom_divisor != info->custom_divisor) || | 2538 | brd->ports[i].max_baud = 921600; |
2790 | (new_serial.baud_base != info->baud_base)) | 2539 | break; |
2791 | return -EPERM; | 2540 | } |
2541 | } | ||
2542 | } | ||
2792 | 2543 | ||
2793 | flags = info->flags & ASYNC_SPD_MASK; | 2544 | if (brd->chip_flag == MOXA_MUST_MU860_HWID) { |
2545 | for (i = 0; i < brd->info->nports; i++) { | ||
2546 | if (i < 4) | ||
2547 | brd->ports[i].opmode_ioaddr = ioaddress + 4; | ||
2548 | else | ||
2549 | brd->ports[i].opmode_ioaddr = ioaddress + 0x0c; | ||
2550 | } | ||
2551 | outb(0, ioaddress + 4); /* default set to RS232 mode */ | ||
2552 | outb(0, ioaddress + 0x0c); /* default set to RS232 mode */ | ||
2553 | } | ||
2794 | 2554 | ||
2795 | if (!capable(CAP_SYS_ADMIN)) { | 2555 | for (i = 0; i < brd->info->nports; i++) { |
2796 | if ((new_serial.baud_base != info->baud_base) || | 2556 | brd->vector_mask |= (1 << i); |
2797 | (new_serial.close_delay != info->close_delay) || | 2557 | brd->ports[i].baud_base = 921600; |
2798 | ((new_serial.flags & ~ASYNC_USR_MASK) != (info->flags & ~ASYNC_USR_MASK))) | ||
2799 | return -EPERM; | ||
2800 | info->flags = ((info->flags & ~ASYNC_USR_MASK) | | ||
2801 | (new_serial.flags & ASYNC_USR_MASK)); | ||
2802 | } else { | ||
2803 | /* | ||
2804 | * OK, past this point, all the error checking has been done. | ||
2805 | * At this point, we start making changes..... | ||
2806 | */ | ||
2807 | info->flags = ((info->flags & ~ASYNC_FLAGS) | | ||
2808 | (new_serial.flags & ASYNC_FLAGS)); | ||
2809 | info->close_delay = new_serial.close_delay * HZ / 100; | ||
2810 | info->closing_wait = new_serial.closing_wait * HZ / 100; | ||
2811 | info->tty->low_latency = | ||
2812 | (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0; | ||
2813 | info->tty->low_latency = 0; /* (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0; */ | ||
2814 | } | 2558 | } |
2815 | 2559 | ||
2816 | /* added by casper, 3/17/2000, for mouse */ | 2560 | /* mxser_initbrd will hook ISR. */ |
2817 | info->type = new_serial.type; | 2561 | retval = mxser_initbrd(brd, pdev); |
2562 | if (retval) | ||
2563 | goto err_null; | ||
2818 | 2564 | ||
2819 | process_txrx_fifo(info); | 2565 | for (i = 0; i < brd->info->nports; i++) |
2566 | tty_register_device(mxvar_sdriver, brd->idx + i, &pdev->dev); | ||
2820 | 2567 | ||
2821 | if (info->flags & ASYNC_INITIALIZED) { | 2568 | pci_set_drvdata(pdev, brd); |
2822 | if (flags != (info->flags & ASYNC_SPD_MASK)) { | 2569 | |
2823 | mxser_change_speed(info, NULL); | 2570 | return 0; |
2824 | } | 2571 | err_relio: |
2825 | } else { | 2572 | pci_release_region(pdev, 2); |
2826 | retval = mxser_startup(info); | 2573 | err_null: |
2827 | } | 2574 | brd->info = NULL; |
2575 | err: | ||
2828 | return retval; | 2576 | return retval; |
2577 | #else | ||
2578 | return -ENODEV; | ||
2579 | #endif | ||
2829 | } | 2580 | } |
2830 | 2581 | ||
2831 | /* | 2582 | static void __devexit mxser_remove(struct pci_dev *pdev) |
2832 | * mxser_get_lsr_info - get line status register info | ||
2833 | * | ||
2834 | * Purpose: Let user call ioctl() to get info when the UART physically | ||
2835 | * is emptied. On bus types like RS485, the transmitter must | ||
2836 | * release the bus after transmitting. This must be done when | ||
2837 | * the transmit shift register is empty, not be done when the | ||
2838 | * transmit holding register is empty. This functionality | ||
2839 | * allows an RS485 driver to be written in user space. | ||
2840 | */ | ||
2841 | static int mxser_get_lsr_info(struct mxser_struct *info, unsigned int __user *value) | ||
2842 | { | 2583 | { |
2843 | unsigned char status; | 2584 | struct mxser_board *brd = pci_get_drvdata(pdev); |
2844 | unsigned int result; | 2585 | unsigned int i; |
2845 | unsigned long flags; | ||
2846 | 2586 | ||
2847 | spin_lock_irqsave(&info->slock, flags); | 2587 | for (i = 0; i < brd->info->nports; i++) |
2848 | status = inb(info->base + UART_LSR); | 2588 | tty_unregister_device(mxvar_sdriver, brd->idx + i); |
2849 | spin_unlock_irqrestore(&info->slock, flags); | ||
2850 | result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0); | ||
2851 | return put_user(result, value); | ||
2852 | } | ||
2853 | 2589 | ||
2854 | /* | 2590 | mxser_release_res(brd, pdev, 1); |
2855 | * This routine sends a break character out the serial port. | 2591 | brd->info = NULL; |
2856 | */ | ||
2857 | static void mxser_send_break(struct mxser_struct *info, int duration) | ||
2858 | { | ||
2859 | unsigned long flags; | ||
2860 | |||
2861 | if (!info->base) | ||
2862 | return; | ||
2863 | set_current_state(TASK_INTERRUPTIBLE); | ||
2864 | spin_lock_irqsave(&info->slock, flags); | ||
2865 | outb(inb(info->base + UART_LCR) | UART_LCR_SBC, | ||
2866 | info->base + UART_LCR); | ||
2867 | spin_unlock_irqrestore(&info->slock, flags); | ||
2868 | schedule_timeout(duration); | ||
2869 | spin_lock_irqsave(&info->slock, flags); | ||
2870 | outb(inb(info->base + UART_LCR) & ~UART_LCR_SBC, | ||
2871 | info->base + UART_LCR); | ||
2872 | spin_unlock_irqrestore(&info->slock, flags); | ||
2873 | } | 2592 | } |
2874 | 2593 | ||
2875 | static int mxser_tiocmget(struct tty_struct *tty, struct file *file) | 2594 | static struct pci_driver mxser_driver = { |
2876 | { | 2595 | .name = "mxser", |
2877 | struct mxser_struct *info = tty->driver_data; | 2596 | .id_table = mxser_pcibrds, |
2878 | unsigned char control, status; | 2597 | .probe = mxser_probe, |
2879 | unsigned long flags; | 2598 | .remove = __devexit_p(mxser_remove) |
2599 | }; | ||
2880 | 2600 | ||
2601 | static int __init mxser_module_init(void) | ||
2602 | { | ||
2603 | struct mxser_board *brd; | ||
2604 | unsigned long cap; | ||
2605 | unsigned int i, m, isaloop; | ||
2606 | int retval, b; | ||
2881 | 2607 | ||
2882 | if (tty->index == MXSER_PORTS) | 2608 | pr_debug("Loading module mxser ...\n"); |
2883 | return -ENOIOCTLCMD; | ||
2884 | if (tty->flags & (1 << TTY_IO_ERROR)) | ||
2885 | return -EIO; | ||
2886 | 2609 | ||
2887 | control = info->MCR; | 2610 | mxvar_sdriver = alloc_tty_driver(MXSER_PORTS + 1); |
2611 | if (!mxvar_sdriver) | ||
2612 | return -ENOMEM; | ||
2888 | 2613 | ||
2889 | spin_lock_irqsave(&info->slock, flags); | 2614 | printk(KERN_INFO "MOXA Smartio/Industio family driver version %s\n", |
2890 | status = inb(info->base + UART_MSR); | 2615 | MXSER_VERSION); |
2891 | if (status & UART_MSR_ANY_DELTA) | ||
2892 | mxser_check_modem_status(info, status); | ||
2893 | spin_unlock_irqrestore(&info->slock, flags); | ||
2894 | return ((control & UART_MCR_RTS) ? TIOCM_RTS : 0) | | ||
2895 | ((control & UART_MCR_DTR) ? TIOCM_DTR : 0) | | ||
2896 | ((status & UART_MSR_DCD) ? TIOCM_CAR : 0) | | ||
2897 | ((status & UART_MSR_RI) ? TIOCM_RNG : 0) | | ||
2898 | ((status & UART_MSR_DSR) ? TIOCM_DSR : 0) | | ||
2899 | ((status & UART_MSR_CTS) ? TIOCM_CTS : 0); | ||
2900 | } | ||
2901 | 2616 | ||
2902 | static int mxser_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear) | 2617 | /* Initialize the tty_driver structure */ |
2903 | { | 2618 | mxvar_sdriver->owner = THIS_MODULE; |
2904 | struct mxser_struct *info = tty->driver_data; | 2619 | mxvar_sdriver->magic = TTY_DRIVER_MAGIC; |
2905 | unsigned long flags; | 2620 | mxvar_sdriver->name = "ttyMI"; |
2621 | mxvar_sdriver->major = ttymajor; | ||
2622 | mxvar_sdriver->minor_start = 0; | ||
2623 | mxvar_sdriver->num = MXSER_PORTS + 1; | ||
2624 | mxvar_sdriver->type = TTY_DRIVER_TYPE_SERIAL; | ||
2625 | mxvar_sdriver->subtype = SERIAL_TYPE_NORMAL; | ||
2626 | mxvar_sdriver->init_termios = tty_std_termios; | ||
2627 | mxvar_sdriver->init_termios.c_cflag = B9600|CS8|CREAD|HUPCL|CLOCAL; | ||
2628 | mxvar_sdriver->flags = TTY_DRIVER_REAL_RAW|TTY_DRIVER_DYNAMIC_DEV; | ||
2629 | tty_set_operations(mxvar_sdriver, &mxser_ops); | ||
2906 | 2630 | ||
2631 | retval = tty_register_driver(mxvar_sdriver); | ||
2632 | if (retval) { | ||
2633 | printk(KERN_ERR "Couldn't install MOXA Smartio/Industio family " | ||
2634 | "tty driver !\n"); | ||
2635 | goto err_put; | ||
2636 | } | ||
2907 | 2637 | ||
2908 | if (tty->index == MXSER_PORTS) | 2638 | mxvar_diagflag = 0; |
2909 | return -ENOIOCTLCMD; | ||
2910 | if (tty->flags & (1 << TTY_IO_ERROR)) | ||
2911 | return -EIO; | ||
2912 | 2639 | ||
2913 | spin_lock_irqsave(&info->slock, flags); | 2640 | m = 0; |
2641 | /* Start finding ISA boards here */ | ||
2642 | for (isaloop = 0; isaloop < 2; isaloop++) | ||
2643 | for (b = 0; b < MXSER_BOARDS && m < MXSER_BOARDS; b++) { | ||
2644 | if (!isaloop) | ||
2645 | cap = mxserBoardCAP[b]; /* predefined */ | ||
2646 | else | ||
2647 | cap = ioaddr[b]; /* module param */ | ||
2914 | 2648 | ||
2915 | if (set & TIOCM_RTS) | 2649 | if (!cap) |
2916 | info->MCR |= UART_MCR_RTS; | 2650 | continue; |
2917 | if (set & TIOCM_DTR) | ||
2918 | info->MCR |= UART_MCR_DTR; | ||
2919 | 2651 | ||
2920 | if (clear & TIOCM_RTS) | 2652 | brd = &mxser_boards[m]; |
2921 | info->MCR &= ~UART_MCR_RTS; | 2653 | retval = mxser_get_ISA_conf(cap, brd); |
2922 | if (clear & TIOCM_DTR) | ||
2923 | info->MCR &= ~UART_MCR_DTR; | ||
2924 | 2654 | ||
2925 | outb(info->MCR, info->base + UART_MCR); | 2655 | if (retval != 0) |
2926 | spin_unlock_irqrestore(&info->slock, flags); | 2656 | printk(KERN_INFO "Found MOXA %s board " |
2927 | return 0; | 2657 | "(CAP=0x%x)\n", |
2928 | } | 2658 | brd->info->name, ioaddr[b]); |
2929 | 2659 | ||
2660 | if (retval <= 0) { | ||
2661 | if (retval == MXSER_ERR_IRQ) | ||
2662 | printk(KERN_ERR "Invalid interrupt " | ||
2663 | "number, board not " | ||
2664 | "configured\n"); | ||
2665 | else if (retval == MXSER_ERR_IRQ_CONFLIT) | ||
2666 | printk(KERN_ERR "Invalid interrupt " | ||
2667 | "number, board not " | ||
2668 | "configured\n"); | ||
2669 | else if (retval == MXSER_ERR_VECTOR) | ||
2670 | printk(KERN_ERR "Invalid interrupt " | ||
2671 | "vector, board not " | ||
2672 | "configured\n"); | ||
2673 | else if (retval == MXSER_ERR_IOADDR) | ||
2674 | printk(KERN_ERR "Invalid I/O address, " | ||
2675 | "board not configured\n"); | ||
2930 | 2676 | ||
2931 | static int mxser_read_register(int, unsigned short *); | 2677 | brd->info = NULL; |
2932 | static int mxser_program_mode(int); | 2678 | continue; |
2933 | static void mxser_normal_mode(int); | 2679 | } |
2934 | 2680 | ||
2935 | static int mxser_get_ISA_conf(int cap, struct mxser_hwconf *hwconf) | 2681 | /* mxser_initbrd will hook ISR. */ |
2936 | { | 2682 | if (mxser_initbrd(brd, NULL) < 0) { |
2937 | int id, i, bits; | 2683 | brd->info = NULL; |
2938 | unsigned short regs[16], irq; | 2684 | continue; |
2939 | unsigned char scratch, scratch2; | 2685 | } |
2940 | 2686 | ||
2941 | hwconf->IsMoxaMustChipFlag = MOXA_OTHER_UART; | 2687 | brd->idx = m * MXSER_PORTS_PER_BOARD; |
2688 | for (i = 0; i < brd->info->nports; i++) | ||
2689 | tty_register_device(mxvar_sdriver, brd->idx + i, | ||
2690 | NULL); | ||
2942 | 2691 | ||
2943 | id = mxser_read_register(cap, regs); | 2692 | m++; |
2944 | if (id == C168_ASIC_ID) { | 2693 | } |
2945 | hwconf->board_type = MXSER_BOARD_C168_ISA; | ||
2946 | hwconf->ports = 8; | ||
2947 | } else if (id == C104_ASIC_ID) { | ||
2948 | hwconf->board_type = MXSER_BOARD_C104_ISA; | ||
2949 | hwconf->ports = 4; | ||
2950 | } else if (id == C102_ASIC_ID) { | ||
2951 | hwconf->board_type = MXSER_BOARD_C102_ISA; | ||
2952 | hwconf->ports = 2; | ||
2953 | } else if (id == CI132_ASIC_ID) { | ||
2954 | hwconf->board_type = MXSER_BOARD_CI132; | ||
2955 | hwconf->ports = 2; | ||
2956 | } else if (id == CI134_ASIC_ID) { | ||
2957 | hwconf->board_type = MXSER_BOARD_CI134; | ||
2958 | hwconf->ports = 4; | ||
2959 | } else if (id == CI104J_ASIC_ID) { | ||
2960 | hwconf->board_type = MXSER_BOARD_CI104J; | ||
2961 | hwconf->ports = 4; | ||
2962 | } else | ||
2963 | return 0; | ||
2964 | 2694 | ||
2965 | irq = 0; | 2695 | retval = pci_register_driver(&mxser_driver); |
2966 | if (hwconf->ports == 2) { | 2696 | if (retval) { |
2967 | irq = regs[9] & 0xF000; | 2697 | printk(KERN_ERR "Can't register pci driver\n"); |
2968 | irq = irq | (irq >> 4); | 2698 | if (!m) { |
2969 | if (irq != (regs[9] & 0xFF00)) | 2699 | retval = -ENODEV; |
2970 | return MXSER_ERR_IRQ_CONFLIT; | 2700 | goto err_unr; |
2971 | } else if (hwconf->ports == 4) { | 2701 | } /* else: we have some ISA cards under control */ |
2972 | irq = regs[9] & 0xF000; | ||
2973 | irq = irq | (irq >> 4); | ||
2974 | irq = irq | (irq >> 8); | ||
2975 | if (irq != regs[9]) | ||
2976 | return MXSER_ERR_IRQ_CONFLIT; | ||
2977 | } else if (hwconf->ports == 8) { | ||
2978 | irq = regs[9] & 0xF000; | ||
2979 | irq = irq | (irq >> 4); | ||
2980 | irq = irq | (irq >> 8); | ||
2981 | if ((irq != regs[9]) || (irq != regs[10])) | ||
2982 | return MXSER_ERR_IRQ_CONFLIT; | ||
2983 | } | 2702 | } |
2984 | 2703 | ||
2985 | if (!irq) | 2704 | pr_debug("Done.\n"); |
2986 | return MXSER_ERR_IRQ; | ||
2987 | hwconf->irq = ((int)(irq & 0xF000) >> 12); | ||
2988 | for (i = 0; i < 8; i++) | ||
2989 | hwconf->ioaddr[i] = (int) regs[i + 1] & 0xFFF8; | ||
2990 | if ((regs[12] & 0x80) == 0) | ||
2991 | return MXSER_ERR_VECTOR; | ||
2992 | hwconf->vector = (int)regs[11]; /* interrupt vector */ | ||
2993 | if (id == 1) | ||
2994 | hwconf->vector_mask = 0x00FF; | ||
2995 | else | ||
2996 | hwconf->vector_mask = 0x000F; | ||
2997 | for (i = 7, bits = 0x0100; i >= 0; i--, bits <<= 1) { | ||
2998 | if (regs[12] & bits) { | ||
2999 | hwconf->baud_base[i] = 921600; | ||
3000 | hwconf->MaxCanSetBaudRate[i] = 921600; /* add by Victor Yu. 09-04-2002 */ | ||
3001 | } else { | ||
3002 | hwconf->baud_base[i] = 115200; | ||
3003 | hwconf->MaxCanSetBaudRate[i] = 115200; /* add by Victor Yu. 09-04-2002 */ | ||
3004 | } | ||
3005 | } | ||
3006 | scratch2 = inb(cap + UART_LCR) & (~UART_LCR_DLAB); | ||
3007 | outb(scratch2 | UART_LCR_DLAB, cap + UART_LCR); | ||
3008 | outb(0, cap + UART_EFR); /* EFR is the same as FCR */ | ||
3009 | outb(scratch2, cap + UART_LCR); | ||
3010 | outb(UART_FCR_ENABLE_FIFO, cap + UART_FCR); | ||
3011 | scratch = inb(cap + UART_IIR); | ||
3012 | 2705 | ||
3013 | if (scratch & 0xC0) | 2706 | return 0; |
3014 | hwconf->uart_type = PORT_16550A; | 2707 | err_unr: |
3015 | else | 2708 | tty_unregister_driver(mxvar_sdriver); |
3016 | hwconf->uart_type = PORT_16450; | 2709 | err_put: |
3017 | if (id == 1) | 2710 | put_tty_driver(mxvar_sdriver); |
3018 | hwconf->ports = 8; | 2711 | return retval; |
3019 | else | ||
3020 | hwconf->ports = 4; | ||
3021 | request_region(hwconf->ioaddr[0], 8 * hwconf->ports, "mxser(IO)"); | ||
3022 | request_region(hwconf->vector, 1, "mxser(vector)"); | ||
3023 | return hwconf->ports; | ||
3024 | } | 2712 | } |
3025 | 2713 | ||
3026 | #define CHIP_SK 0x01 /* Serial Data Clock in Eprom */ | 2714 | static void __exit mxser_module_exit(void) |
3027 | #define CHIP_DO 0x02 /* Serial Data Output in Eprom */ | ||
3028 | #define CHIP_CS 0x04 /* Serial Chip Select in Eprom */ | ||
3029 | #define CHIP_DI 0x08 /* Serial Data Input in Eprom */ | ||
3030 | #define EN_CCMD 0x000 /* Chip's command register */ | ||
3031 | #define EN0_RSARLO 0x008 /* Remote start address reg 0 */ | ||
3032 | #define EN0_RSARHI 0x009 /* Remote start address reg 1 */ | ||
3033 | #define EN0_RCNTLO 0x00A /* Remote byte count reg WR */ | ||
3034 | #define EN0_RCNTHI 0x00B /* Remote byte count reg WR */ | ||
3035 | #define EN0_DCFG 0x00E /* Data configuration reg WR */ | ||
3036 | #define EN0_PORT 0x010 /* Rcv missed frame error counter RD */ | ||
3037 | #define ENC_PAGE0 0x000 /* Select page 0 of chip registers */ | ||
3038 | #define ENC_PAGE3 0x0C0 /* Select page 3 of chip registers */ | ||
3039 | static int mxser_read_register(int port, unsigned short *regs) | ||
3040 | { | 2715 | { |
3041 | int i, k, value, id; | 2716 | unsigned int i, j; |
3042 | unsigned int j; | ||
3043 | |||
3044 | id = mxser_program_mode(port); | ||
3045 | if (id < 0) | ||
3046 | return id; | ||
3047 | for (i = 0; i < 14; i++) { | ||
3048 | k = (i & 0x3F) | 0x180; | ||
3049 | for (j = 0x100; j > 0; j >>= 1) { | ||
3050 | outb(CHIP_CS, port); | ||
3051 | if (k & j) { | ||
3052 | outb(CHIP_CS | CHIP_DO, port); | ||
3053 | outb(CHIP_CS | CHIP_DO | CHIP_SK, port); /* A? bit of read */ | ||
3054 | } else { | ||
3055 | outb(CHIP_CS, port); | ||
3056 | outb(CHIP_CS | CHIP_SK, port); /* A? bit of read */ | ||
3057 | } | ||
3058 | } | ||
3059 | (void)inb(port); | ||
3060 | value = 0; | ||
3061 | for (k = 0, j = 0x8000; k < 16; k++, j >>= 1) { | ||
3062 | outb(CHIP_CS, port); | ||
3063 | outb(CHIP_CS | CHIP_SK, port); | ||
3064 | if (inb(port) & CHIP_DI) | ||
3065 | value |= j; | ||
3066 | } | ||
3067 | regs[i] = value; | ||
3068 | outb(0, port); | ||
3069 | } | ||
3070 | mxser_normal_mode(port); | ||
3071 | return id; | ||
3072 | } | ||
3073 | 2717 | ||
3074 | static int mxser_program_mode(int port) | 2718 | pr_debug("Unloading module mxser ...\n"); |
3075 | { | ||
3076 | int id, i, j, n; | ||
3077 | /* unsigned long flags; */ | ||
3078 | 2719 | ||
3079 | spin_lock(&gm_lock); | 2720 | pci_unregister_driver(&mxser_driver); |
3080 | outb(0, port); | ||
3081 | outb(0, port); | ||
3082 | outb(0, port); | ||
3083 | (void)inb(port); | ||
3084 | (void)inb(port); | ||
3085 | outb(0, port); | ||
3086 | (void)inb(port); | ||
3087 | /* restore_flags(flags); */ | ||
3088 | spin_unlock(&gm_lock); | ||
3089 | 2721 | ||
3090 | id = inb(port + 1) & 0x1F; | 2722 | for (i = 0; i < MXSER_BOARDS; i++) /* ISA remains */ |
3091 | if ((id != C168_ASIC_ID) && | 2723 | if (mxser_boards[i].info != NULL) |
3092 | (id != C104_ASIC_ID) && | 2724 | for (j = 0; j < mxser_boards[i].info->nports; j++) |
3093 | (id != C102_ASIC_ID) && | 2725 | tty_unregister_device(mxvar_sdriver, |
3094 | (id != CI132_ASIC_ID) && | 2726 | mxser_boards[i].idx + j); |
3095 | (id != CI134_ASIC_ID) && | 2727 | tty_unregister_driver(mxvar_sdriver); |
3096 | (id != CI104J_ASIC_ID)) | 2728 | put_tty_driver(mxvar_sdriver); |
3097 | return -1; | ||
3098 | for (i = 0, j = 0; i < 4; i++) { | ||
3099 | n = inb(port + 2); | ||
3100 | if (n == 'M') { | ||
3101 | j = 1; | ||
3102 | } else if ((j == 1) && (n == 1)) { | ||
3103 | j = 2; | ||
3104 | break; | ||
3105 | } else | ||
3106 | j = 0; | ||
3107 | } | ||
3108 | if (j != 2) | ||
3109 | id = -2; | ||
3110 | return id; | ||
3111 | } | ||
3112 | 2729 | ||
3113 | static void mxser_normal_mode(int port) | 2730 | for (i = 0; i < MXSER_BOARDS; i++) |
3114 | { | 2731 | if (mxser_boards[i].info != NULL) |
3115 | int i, n; | 2732 | mxser_release_res(&mxser_boards[i], NULL, 1); |
3116 | 2733 | ||
3117 | outb(0xA5, port + 1); | 2734 | pr_debug("Done.\n"); |
3118 | outb(0x80, port + 3); | ||
3119 | outb(12, port + 0); /* 9600 bps */ | ||
3120 | outb(0, port + 1); | ||
3121 | outb(0x03, port + 3); /* 8 data bits */ | ||
3122 | outb(0x13, port + 4); /* loop back mode */ | ||
3123 | for (i = 0; i < 16; i++) { | ||
3124 | n = inb(port + 5); | ||
3125 | if ((n & 0x61) == 0x60) | ||
3126 | break; | ||
3127 | if ((n & 1) == 1) | ||
3128 | (void)inb(port); | ||
3129 | } | ||
3130 | outb(0x00, port + 4); | ||
3131 | } | 2735 | } |
3132 | 2736 | ||
3133 | module_init(mxser_module_init); | 2737 | module_init(mxser_module_init); |
diff --git a/drivers/char/mxser.h b/drivers/char/mxser.h index 1f4aa45ec004..844171115954 100644 --- a/drivers/char/mxser.h +++ b/drivers/char/mxser.h | |||
@@ -4,19 +4,17 @@ | |||
4 | /* | 4 | /* |
5 | * Semi-public control interfaces | 5 | * Semi-public control interfaces |
6 | */ | 6 | */ |
7 | 7 | ||
8 | /* | 8 | /* |
9 | * MOXA ioctls | 9 | * MOXA ioctls |
10 | */ | 10 | */ |
11 | 11 | ||
12 | #define MOXA 0x400 | 12 | #define MOXA 0x400 |
13 | #define MOXA_GETDATACOUNT (MOXA + 23) | 13 | #define MOXA_GETDATACOUNT (MOXA + 23) |
14 | #define MOXA_GET_CONF (MOXA + 35) | ||
15 | #define MOXA_DIAGNOSE (MOXA + 50) | 14 | #define MOXA_DIAGNOSE (MOXA + 50) |
16 | #define MOXA_CHKPORTENABLE (MOXA + 60) | 15 | #define MOXA_CHKPORTENABLE (MOXA + 60) |
17 | #define MOXA_HighSpeedOn (MOXA + 61) | 16 | #define MOXA_HighSpeedOn (MOXA + 61) |
18 | #define MOXA_GET_MAJOR (MOXA + 63) | 17 | #define MOXA_GET_MAJOR (MOXA + 63) |
19 | #define MOXA_GET_CUMAJOR (MOXA + 64) | ||
20 | #define MOXA_GETMSTATUS (MOXA + 65) | 18 | #define MOXA_GETMSTATUS (MOXA + 65) |
21 | #define MOXA_SET_OP_MODE (MOXA + 66) | 19 | #define MOXA_SET_OP_MODE (MOXA + 66) |
22 | #define MOXA_GET_OP_MODE (MOXA + 67) | 20 | #define MOXA_GET_OP_MODE (MOXA + 67) |
@@ -26,26 +24,14 @@ | |||
26 | #define RS422_MODE 2 | 24 | #define RS422_MODE 2 |
27 | #define RS485_4WIRE_MODE 3 | 25 | #define RS485_4WIRE_MODE 3 |
28 | #define OP_MODE_MASK 3 | 26 | #define OP_MODE_MASK 3 |
29 | // above add by Victor Yu. 01-05-2004 | ||
30 | |||
31 | #define TTY_THRESHOLD_THROTTLE 128 | ||
32 | |||
33 | #define HI_WATER 768 | ||
34 | |||
35 | // added by James. 03-11-2004. | ||
36 | #define MOXA_SDS_GETICOUNTER (MOXA + 68) | ||
37 | #define MOXA_SDS_RSTICOUNTER (MOXA + 69) | ||
38 | // (above) added by James. | ||
39 | 27 | ||
28 | #define MOXA_SDS_RSTICOUNTER (MOXA + 69) | ||
40 | #define MOXA_ASPP_OQUEUE (MOXA + 70) | 29 | #define MOXA_ASPP_OQUEUE (MOXA + 70) |
41 | #define MOXA_ASPP_SETBAUD (MOXA + 71) | ||
42 | #define MOXA_ASPP_GETBAUD (MOXA + 72) | ||
43 | #define MOXA_ASPP_MON (MOXA + 73) | 30 | #define MOXA_ASPP_MON (MOXA + 73) |
44 | #define MOXA_ASPP_LSTATUS (MOXA + 74) | 31 | #define MOXA_ASPP_LSTATUS (MOXA + 74) |
45 | #define MOXA_ASPP_MON_EXT (MOXA + 75) | 32 | #define MOXA_ASPP_MON_EXT (MOXA + 75) |
46 | #define MOXA_SET_BAUD_METHOD (MOXA + 76) | 33 | #define MOXA_SET_BAUD_METHOD (MOXA + 76) |
47 | 34 | ||
48 | |||
49 | /* --------------------------------------------------- */ | 35 | /* --------------------------------------------------- */ |
50 | 36 | ||
51 | #define NPPI_NOTIFY_PARITY 0x01 | 37 | #define NPPI_NOTIFY_PARITY 0x01 |
@@ -54,51 +40,46 @@ | |||
54 | #define NPPI_NOTIFY_SW_OVERRUN 0x08 | 40 | #define NPPI_NOTIFY_SW_OVERRUN 0x08 |
55 | #define NPPI_NOTIFY_BREAK 0x10 | 41 | #define NPPI_NOTIFY_BREAK 0x10 |
56 | 42 | ||
57 | #define NPPI_NOTIFY_CTSHOLD 0x01 // Tx hold by CTS low | 43 | #define NPPI_NOTIFY_CTSHOLD 0x01 /* Tx hold by CTS low */ |
58 | #define NPPI_NOTIFY_DSRHOLD 0x02 // Tx hold by DSR low | 44 | #define NPPI_NOTIFY_DSRHOLD 0x02 /* Tx hold by DSR low */ |
59 | #define NPPI_NOTIFY_XOFFHOLD 0x08 // Tx hold by Xoff received | 45 | #define NPPI_NOTIFY_XOFFHOLD 0x08 /* Tx hold by Xoff received */ |
60 | #define NPPI_NOTIFY_XOFFXENT 0x10 // Xoff Sent | 46 | #define NPPI_NOTIFY_XOFFXENT 0x10 /* Xoff Sent */ |
61 | 47 | ||
62 | //CheckIsMoxaMust return value | 48 | /* follow just for Moxa Must chip define. */ |
63 | #define MOXA_OTHER_UART 0x00 | 49 | /* */ |
64 | #define MOXA_MUST_MU150_HWID 0x01 | 50 | /* when LCR register (offset 0x03) write following value, */ |
65 | #define MOXA_MUST_MU860_HWID 0x02 | 51 | /* the Must chip will enter enchance mode. And write value */ |
66 | 52 | /* on EFR (offset 0x02) bit 6,7 to change bank. */ | |
67 | // follow just for Moxa Must chip define. | ||
68 | // | ||
69 | // when LCR register (offset 0x03) write following value, | ||
70 | // the Must chip will enter enchance mode. And write value | ||
71 | // on EFR (offset 0x02) bit 6,7 to change bank. | ||
72 | #define MOXA_MUST_ENTER_ENCHANCE 0xBF | 53 | #define MOXA_MUST_ENTER_ENCHANCE 0xBF |
73 | 54 | ||
74 | // when enhance mode enable, access on general bank register | 55 | /* when enhance mode enable, access on general bank register */ |
75 | #define MOXA_MUST_GDL_REGISTER 0x07 | 56 | #define MOXA_MUST_GDL_REGISTER 0x07 |
76 | #define MOXA_MUST_GDL_MASK 0x7F | 57 | #define MOXA_MUST_GDL_MASK 0x7F |
77 | #define MOXA_MUST_GDL_HAS_BAD_DATA 0x80 | 58 | #define MOXA_MUST_GDL_HAS_BAD_DATA 0x80 |
78 | 59 | ||
79 | #define MOXA_MUST_LSR_RERR 0x80 // error in receive FIFO | 60 | #define MOXA_MUST_LSR_RERR 0x80 /* error in receive FIFO */ |
80 | // enchance register bank select and enchance mode setting register | 61 | /* enchance register bank select and enchance mode setting register */ |
81 | // when LCR register equal to 0xBF | 62 | /* when LCR register equal to 0xBF */ |
82 | #define MOXA_MUST_EFR_REGISTER 0x02 | 63 | #define MOXA_MUST_EFR_REGISTER 0x02 |
83 | // enchance mode enable | 64 | /* enchance mode enable */ |
84 | #define MOXA_MUST_EFR_EFRB_ENABLE 0x10 | 65 | #define MOXA_MUST_EFR_EFRB_ENABLE 0x10 |
85 | // enchance reister bank set 0, 1, 2 | 66 | /* enchance reister bank set 0, 1, 2 */ |
86 | #define MOXA_MUST_EFR_BANK0 0x00 | 67 | #define MOXA_MUST_EFR_BANK0 0x00 |
87 | #define MOXA_MUST_EFR_BANK1 0x40 | 68 | #define MOXA_MUST_EFR_BANK1 0x40 |
88 | #define MOXA_MUST_EFR_BANK2 0x80 | 69 | #define MOXA_MUST_EFR_BANK2 0x80 |
89 | #define MOXA_MUST_EFR_BANK3 0xC0 | 70 | #define MOXA_MUST_EFR_BANK3 0xC0 |
90 | #define MOXA_MUST_EFR_BANK_MASK 0xC0 | 71 | #define MOXA_MUST_EFR_BANK_MASK 0xC0 |
91 | 72 | ||
92 | // set XON1 value register, when LCR=0xBF and change to bank0 | 73 | /* set XON1 value register, when LCR=0xBF and change to bank0 */ |
93 | #define MOXA_MUST_XON1_REGISTER 0x04 | 74 | #define MOXA_MUST_XON1_REGISTER 0x04 |
94 | 75 | ||
95 | // set XON2 value register, when LCR=0xBF and change to bank0 | 76 | /* set XON2 value register, when LCR=0xBF and change to bank0 */ |
96 | #define MOXA_MUST_XON2_REGISTER 0x05 | 77 | #define MOXA_MUST_XON2_REGISTER 0x05 |
97 | 78 | ||
98 | // set XOFF1 value register, when LCR=0xBF and change to bank0 | 79 | /* set XOFF1 value register, when LCR=0xBF and change to bank0 */ |
99 | #define MOXA_MUST_XOFF1_REGISTER 0x06 | 80 | #define MOXA_MUST_XOFF1_REGISTER 0x06 |
100 | 81 | ||
101 | // set XOFF2 value register, when LCR=0xBF and change to bank0 | 82 | /* set XOFF2 value register, when LCR=0xBF and change to bank0 */ |
102 | #define MOXA_MUST_XOFF2_REGISTER 0x07 | 83 | #define MOXA_MUST_XOFF2_REGISTER 0x07 |
103 | 84 | ||
104 | #define MOXA_MUST_RBRTL_REGISTER 0x04 | 85 | #define MOXA_MUST_RBRTL_REGISTER 0x04 |
@@ -110,32 +91,32 @@ | |||
110 | #define MOXA_MUST_ECR_REGISTER 0x06 | 91 | #define MOXA_MUST_ECR_REGISTER 0x06 |
111 | #define MOXA_MUST_CSR_REGISTER 0x07 | 92 | #define MOXA_MUST_CSR_REGISTER 0x07 |
112 | 93 | ||
113 | // good data mode enable | 94 | /* good data mode enable */ |
114 | #define MOXA_MUST_FCR_GDA_MODE_ENABLE 0x20 | 95 | #define MOXA_MUST_FCR_GDA_MODE_ENABLE 0x20 |
115 | // only good data put into RxFIFO | 96 | /* only good data put into RxFIFO */ |
116 | #define MOXA_MUST_FCR_GDA_ONLY_ENABLE 0x10 | 97 | #define MOXA_MUST_FCR_GDA_ONLY_ENABLE 0x10 |
117 | 98 | ||
118 | // enable CTS interrupt | 99 | /* enable CTS interrupt */ |
119 | #define MOXA_MUST_IER_ECTSI 0x80 | 100 | #define MOXA_MUST_IER_ECTSI 0x80 |
120 | // enable RTS interrupt | 101 | /* enable RTS interrupt */ |
121 | #define MOXA_MUST_IER_ERTSI 0x40 | 102 | #define MOXA_MUST_IER_ERTSI 0x40 |
122 | // enable Xon/Xoff interrupt | 103 | /* enable Xon/Xoff interrupt */ |
123 | #define MOXA_MUST_IER_XINT 0x20 | 104 | #define MOXA_MUST_IER_XINT 0x20 |
124 | // enable GDA interrupt | 105 | /* enable GDA interrupt */ |
125 | #define MOXA_MUST_IER_EGDAI 0x10 | 106 | #define MOXA_MUST_IER_EGDAI 0x10 |
126 | 107 | ||
127 | #define MOXA_MUST_RECV_ISR (UART_IER_RDI | MOXA_MUST_IER_EGDAI) | 108 | #define MOXA_MUST_RECV_ISR (UART_IER_RDI | MOXA_MUST_IER_EGDAI) |
128 | 109 | ||
129 | // GDA interrupt pending | 110 | /* GDA interrupt pending */ |
130 | #define MOXA_MUST_IIR_GDA 0x1C | 111 | #define MOXA_MUST_IIR_GDA 0x1C |
131 | #define MOXA_MUST_IIR_RDA 0x04 | 112 | #define MOXA_MUST_IIR_RDA 0x04 |
132 | #define MOXA_MUST_IIR_RTO 0x0C | 113 | #define MOXA_MUST_IIR_RTO 0x0C |
133 | #define MOXA_MUST_IIR_LSR 0x06 | 114 | #define MOXA_MUST_IIR_LSR 0x06 |
134 | 115 | ||
135 | // recieved Xon/Xoff or specical interrupt pending | 116 | /* recieved Xon/Xoff or specical interrupt pending */ |
136 | #define MOXA_MUST_IIR_XSC 0x10 | 117 | #define MOXA_MUST_IIR_XSC 0x10 |
137 | 118 | ||
138 | // RTS/CTS change state interrupt pending | 119 | /* RTS/CTS change state interrupt pending */ |
139 | #define MOXA_MUST_IIR_RTSCTS 0x20 | 120 | #define MOXA_MUST_IIR_RTSCTS 0x20 |
140 | #define MOXA_MUST_IIR_MASK 0x3E | 121 | #define MOXA_MUST_IIR_MASK 0x3E |
141 | 122 | ||
@@ -143,299 +124,164 @@ | |||
143 | #define MOXA_MUST_MCR_XON_ANY 0x80 | 124 | #define MOXA_MUST_MCR_XON_ANY 0x80 |
144 | #define MOXA_MUST_MCR_TX_XON 0x08 | 125 | #define MOXA_MUST_MCR_TX_XON 0x08 |
145 | 126 | ||
146 | 127 | /* software flow control on chip mask value */ | |
147 | // software flow control on chip mask value | ||
148 | #define MOXA_MUST_EFR_SF_MASK 0x0F | 128 | #define MOXA_MUST_EFR_SF_MASK 0x0F |
149 | // send Xon1/Xoff1 | 129 | /* send Xon1/Xoff1 */ |
150 | #define MOXA_MUST_EFR_SF_TX1 0x08 | 130 | #define MOXA_MUST_EFR_SF_TX1 0x08 |
151 | // send Xon2/Xoff2 | 131 | /* send Xon2/Xoff2 */ |
152 | #define MOXA_MUST_EFR_SF_TX2 0x04 | 132 | #define MOXA_MUST_EFR_SF_TX2 0x04 |
153 | // send Xon1,Xon2/Xoff1,Xoff2 | 133 | /* send Xon1,Xon2/Xoff1,Xoff2 */ |
154 | #define MOXA_MUST_EFR_SF_TX12 0x0C | 134 | #define MOXA_MUST_EFR_SF_TX12 0x0C |
155 | // don't send Xon/Xoff | 135 | /* don't send Xon/Xoff */ |
156 | #define MOXA_MUST_EFR_SF_TX_NO 0x00 | 136 | #define MOXA_MUST_EFR_SF_TX_NO 0x00 |
157 | // Tx software flow control mask | 137 | /* Tx software flow control mask */ |
158 | #define MOXA_MUST_EFR_SF_TX_MASK 0x0C | 138 | #define MOXA_MUST_EFR_SF_TX_MASK 0x0C |
159 | // don't receive Xon/Xoff | 139 | /* don't receive Xon/Xoff */ |
160 | #define MOXA_MUST_EFR_SF_RX_NO 0x00 | 140 | #define MOXA_MUST_EFR_SF_RX_NO 0x00 |
161 | // receive Xon1/Xoff1 | 141 | /* receive Xon1/Xoff1 */ |
162 | #define MOXA_MUST_EFR_SF_RX1 0x02 | 142 | #define MOXA_MUST_EFR_SF_RX1 0x02 |
163 | // receive Xon2/Xoff2 | 143 | /* receive Xon2/Xoff2 */ |
164 | #define MOXA_MUST_EFR_SF_RX2 0x01 | 144 | #define MOXA_MUST_EFR_SF_RX2 0x01 |
165 | // receive Xon1,Xon2/Xoff1,Xoff2 | 145 | /* receive Xon1,Xon2/Xoff1,Xoff2 */ |
166 | #define MOXA_MUST_EFR_SF_RX12 0x03 | 146 | #define MOXA_MUST_EFR_SF_RX12 0x03 |
167 | // Rx software flow control mask | 147 | /* Rx software flow control mask */ |
168 | #define MOXA_MUST_EFR_SF_RX_MASK 0x03 | 148 | #define MOXA_MUST_EFR_SF_RX_MASK 0x03 |
169 | 149 | ||
170 | //#define MOXA_MUST_MIN_XOFFLIMIT 66 | 150 | #define ENABLE_MOXA_MUST_ENCHANCE_MODE(baseio) do { \ |
171 | //#define MOXA_MUST_MIN_XONLIMIT 20 | 151 | u8 __oldlcr, __efr; \ |
172 | //#define ID1_RX_TRIG 120 | 152 | __oldlcr = inb((baseio)+UART_LCR); \ |
173 | |||
174 | |||
175 | #define CHECK_MOXA_MUST_XOFFLIMIT(info) { \ | ||
176 | if ( (info)->IsMoxaMustChipFlag && \ | ||
177 | (info)->HandFlow.XoffLimit < MOXA_MUST_MIN_XOFFLIMIT ) { \ | ||
178 | (info)->HandFlow.XoffLimit = MOXA_MUST_MIN_XOFFLIMIT; \ | ||
179 | (info)->HandFlow.XonLimit = MOXA_MUST_MIN_XONLIMIT; \ | ||
180 | } \ | ||
181 | } | ||
182 | |||
183 | #define ENABLE_MOXA_MUST_ENCHANCE_MODE(baseio) { \ | ||
184 | u8 __oldlcr, __efr; \ | ||
185 | __oldlcr = inb((baseio)+UART_LCR); \ | ||
186 | outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ | 153 | outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ |
187 | __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ | 154 | __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ |
188 | __efr |= MOXA_MUST_EFR_EFRB_ENABLE; \ | 155 | __efr |= MOXA_MUST_EFR_EFRB_ENABLE; \ |
189 | outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ | 156 | outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ |
190 | outb(__oldlcr, (baseio)+UART_LCR); \ | 157 | outb(__oldlcr, (baseio)+UART_LCR); \ |
191 | } | 158 | } while (0) |
192 | 159 | ||
193 | #define DISABLE_MOXA_MUST_ENCHANCE_MODE(baseio) { \ | 160 | #define DISABLE_MOXA_MUST_ENCHANCE_MODE(baseio) do { \ |
194 | u8 __oldlcr, __efr; \ | 161 | u8 __oldlcr, __efr; \ |
195 | __oldlcr = inb((baseio)+UART_LCR); \ | 162 | __oldlcr = inb((baseio)+UART_LCR); \ |
196 | outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ | 163 | outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ |
197 | __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ | 164 | __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ |
198 | __efr &= ~MOXA_MUST_EFR_EFRB_ENABLE; \ | 165 | __efr &= ~MOXA_MUST_EFR_EFRB_ENABLE; \ |
199 | outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ | 166 | outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ |
200 | outb(__oldlcr, (baseio)+UART_LCR); \ | 167 | outb(__oldlcr, (baseio)+UART_LCR); \ |
201 | } | 168 | } while (0) |
202 | 169 | ||
203 | #define SET_MOXA_MUST_XON1_VALUE(baseio, Value) { \ | 170 | #define SET_MOXA_MUST_XON1_VALUE(baseio, Value) do { \ |
204 | u8 __oldlcr, __efr; \ | 171 | u8 __oldlcr, __efr; \ |
205 | __oldlcr = inb((baseio)+UART_LCR); \ | 172 | __oldlcr = inb((baseio)+UART_LCR); \ |
206 | outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ | 173 | outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ |
207 | __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ | 174 | __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ |
208 | __efr &= ~MOXA_MUST_EFR_BANK_MASK; \ | 175 | __efr &= ~MOXA_MUST_EFR_BANK_MASK; \ |
209 | __efr |= MOXA_MUST_EFR_BANK0; \ | 176 | __efr |= MOXA_MUST_EFR_BANK0; \ |
210 | outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ | 177 | outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ |
211 | outb((u8)(Value), (baseio)+MOXA_MUST_XON1_REGISTER); \ | 178 | outb((u8)(Value), (baseio)+MOXA_MUST_XON1_REGISTER); \ |
212 | outb(__oldlcr, (baseio)+UART_LCR); \ | 179 | outb(__oldlcr, (baseio)+UART_LCR); \ |
213 | } | 180 | } while (0) |
214 | 181 | ||
215 | #define SET_MOXA_MUST_XON2_VALUE(baseio, Value) { \ | 182 | #define SET_MOXA_MUST_XOFF1_VALUE(baseio, Value) do { \ |
216 | u8 __oldlcr, __efr; \ | 183 | u8 __oldlcr, __efr; \ |
217 | __oldlcr = inb((baseio)+UART_LCR); \ | 184 | __oldlcr = inb((baseio)+UART_LCR); \ |
218 | outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ | 185 | outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ |
219 | __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ | 186 | __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ |
220 | __efr &= ~MOXA_MUST_EFR_BANK_MASK; \ | 187 | __efr &= ~MOXA_MUST_EFR_BANK_MASK; \ |
221 | __efr |= MOXA_MUST_EFR_BANK0; \ | 188 | __efr |= MOXA_MUST_EFR_BANK0; \ |
222 | outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ | 189 | outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ |
223 | outb((u8)(Value), (baseio)+MOXA_MUST_XON2_REGISTER); \ | ||
224 | outb(__oldlcr, (baseio)+UART_LCR); \ | ||
225 | } | ||
226 | |||
227 | #define SET_MOXA_MUST_XOFF1_VALUE(baseio, Value) { \ | ||
228 | u8 __oldlcr, __efr; \ | ||
229 | __oldlcr = inb((baseio)+UART_LCR); \ | ||
230 | outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ | ||
231 | __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ | ||
232 | __efr &= ~MOXA_MUST_EFR_BANK_MASK; \ | ||
233 | __efr |= MOXA_MUST_EFR_BANK0; \ | ||
234 | outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ | ||
235 | outb((u8)(Value), (baseio)+MOXA_MUST_XOFF1_REGISTER); \ | 190 | outb((u8)(Value), (baseio)+MOXA_MUST_XOFF1_REGISTER); \ |
236 | outb(__oldlcr, (baseio)+UART_LCR); \ | 191 | outb(__oldlcr, (baseio)+UART_LCR); \ |
237 | } | 192 | } while (0) |
238 | 193 | ||
239 | #define SET_MOXA_MUST_XOFF2_VALUE(baseio, Value) { \ | 194 | #define SET_MOXA_MUST_FIFO_VALUE(info) do { \ |
240 | u8 __oldlcr, __efr; \ | 195 | u8 __oldlcr, __efr; \ |
241 | __oldlcr = inb((baseio)+UART_LCR); \ | 196 | __oldlcr = inb((info)->ioaddr+UART_LCR); \ |
242 | outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ | 197 | outb(MOXA_MUST_ENTER_ENCHANCE, (info)->ioaddr+UART_LCR);\ |
243 | __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ | 198 | __efr = inb((info)->ioaddr+MOXA_MUST_EFR_REGISTER); \ |
244 | __efr &= ~MOXA_MUST_EFR_BANK_MASK; \ | 199 | __efr &= ~MOXA_MUST_EFR_BANK_MASK; \ |
245 | __efr |= MOXA_MUST_EFR_BANK0; \ | 200 | __efr |= MOXA_MUST_EFR_BANK1; \ |
246 | outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ | 201 | outb(__efr, (info)->ioaddr+MOXA_MUST_EFR_REGISTER); \ |
247 | outb((u8)(Value), (baseio)+MOXA_MUST_XOFF2_REGISTER); \ | 202 | outb((u8)((info)->rx_high_water), (info)->ioaddr+ \ |
248 | outb(__oldlcr, (baseio)+UART_LCR); \ | 203 | MOXA_MUST_RBRTH_REGISTER); \ |
249 | } | 204 | outb((u8)((info)->rx_trigger), (info)->ioaddr+ \ |
250 | 205 | MOXA_MUST_RBRTI_REGISTER); \ | |
251 | #define SET_MOXA_MUST_RBRTL_VALUE(baseio, Value) { \ | 206 | outb((u8)((info)->rx_low_water), (info)->ioaddr+ \ |
252 | u8 __oldlcr, __efr; \ | 207 | MOXA_MUST_RBRTL_REGISTER); \ |
253 | __oldlcr = inb((baseio)+UART_LCR); \ | 208 | outb(__oldlcr, (info)->ioaddr+UART_LCR); \ |
254 | outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ | 209 | } while (0) |
255 | __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ | 210 | |
256 | __efr &= ~MOXA_MUST_EFR_BANK_MASK; \ | 211 | #define SET_MOXA_MUST_ENUM_VALUE(baseio, Value) do { \ |
257 | __efr |= MOXA_MUST_EFR_BANK1; \ | 212 | u8 __oldlcr, __efr; \ |
258 | outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ | 213 | __oldlcr = inb((baseio)+UART_LCR); \ |
259 | outb((u8)(Value), (baseio)+MOXA_MUST_RBRTL_REGISTER); \ | ||
260 | outb(__oldlcr, (baseio)+UART_LCR); \ | ||
261 | } | ||
262 | |||
263 | #define SET_MOXA_MUST_RBRTH_VALUE(baseio, Value) { \ | ||
264 | u8 __oldlcr, __efr; \ | ||
265 | __oldlcr = inb((baseio)+UART_LCR); \ | ||
266 | outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ | ||
267 | __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ | ||
268 | __efr &= ~MOXA_MUST_EFR_BANK_MASK; \ | ||
269 | __efr |= MOXA_MUST_EFR_BANK1; \ | ||
270 | outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ | ||
271 | outb((u8)(Value), (baseio)+MOXA_MUST_RBRTH_REGISTER); \ | ||
272 | outb(__oldlcr, (baseio)+UART_LCR); \ | ||
273 | } | ||
274 | |||
275 | #define SET_MOXA_MUST_RBRTI_VALUE(baseio, Value) { \ | ||
276 | u8 __oldlcr, __efr; \ | ||
277 | __oldlcr = inb((baseio)+UART_LCR); \ | ||
278 | outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ | 214 | outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ |
279 | __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ | 215 | __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ |
280 | __efr &= ~MOXA_MUST_EFR_BANK_MASK; \ | 216 | __efr &= ~MOXA_MUST_EFR_BANK_MASK; \ |
281 | __efr |= MOXA_MUST_EFR_BANK1; \ | 217 | __efr |= MOXA_MUST_EFR_BANK2; \ |
282 | outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ | 218 | outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ |
283 | outb((u8)(Value), (baseio)+MOXA_MUST_RBRTI_REGISTER); \ | ||
284 | outb(__oldlcr, (baseio)+UART_LCR); \ | ||
285 | } | ||
286 | |||
287 | #define SET_MOXA_MUST_THRTL_VALUE(baseio, Value) { \ | ||
288 | u8 __oldlcr, __efr; \ | ||
289 | __oldlcr = inb((baseio)+UART_LCR); \ | ||
290 | outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ | ||
291 | __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ | ||
292 | __efr &= ~MOXA_MUST_EFR_BANK_MASK; \ | ||
293 | __efr |= MOXA_MUST_EFR_BANK1; \ | ||
294 | outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ | ||
295 | outb((u8)(Value), (baseio)+MOXA_MUST_THRTL_REGISTER); \ | ||
296 | outb(__oldlcr, (baseio)+UART_LCR); \ | ||
297 | } | ||
298 | |||
299 | //#define MOXA_MUST_RBRL_VALUE 4 | ||
300 | #define SET_MOXA_MUST_FIFO_VALUE(info) { \ | ||
301 | u8 __oldlcr, __efr; \ | ||
302 | __oldlcr = inb((info)->base+UART_LCR); \ | ||
303 | outb(MOXA_MUST_ENTER_ENCHANCE, (info)->base+UART_LCR); \ | ||
304 | __efr = inb((info)->base+MOXA_MUST_EFR_REGISTER); \ | ||
305 | __efr &= ~MOXA_MUST_EFR_BANK_MASK; \ | ||
306 | __efr |= MOXA_MUST_EFR_BANK1; \ | ||
307 | outb(__efr, (info)->base+MOXA_MUST_EFR_REGISTER); \ | ||
308 | outb((u8)((info)->rx_high_water), (info)->base+MOXA_MUST_RBRTH_REGISTER); \ | ||
309 | outb((u8)((info)->rx_trigger), (info)->base+MOXA_MUST_RBRTI_REGISTER); \ | ||
310 | outb((u8)((info)->rx_low_water), (info)->base+MOXA_MUST_RBRTL_REGISTER); \ | ||
311 | outb(__oldlcr, (info)->base+UART_LCR); \ | ||
312 | } | ||
313 | |||
314 | |||
315 | |||
316 | #define SET_MOXA_MUST_ENUM_VALUE(baseio, Value) { \ | ||
317 | u8 __oldlcr, __efr; \ | ||
318 | __oldlcr = inb((baseio)+UART_LCR); \ | ||
319 | outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ | ||
320 | __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ | ||
321 | __efr &= ~MOXA_MUST_EFR_BANK_MASK; \ | ||
322 | __efr |= MOXA_MUST_EFR_BANK2; \ | ||
323 | outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ | ||
324 | outb((u8)(Value), (baseio)+MOXA_MUST_ENUM_REGISTER); \ | 219 | outb((u8)(Value), (baseio)+MOXA_MUST_ENUM_REGISTER); \ |
325 | outb(__oldlcr, (baseio)+UART_LCR); \ | 220 | outb(__oldlcr, (baseio)+UART_LCR); \ |
326 | } | 221 | } while (0) |
327 | 222 | ||
328 | #define GET_MOXA_MUST_HARDWARE_ID(baseio, pId) { \ | 223 | #define GET_MOXA_MUST_HARDWARE_ID(baseio, pId) do { \ |
329 | u8 __oldlcr, __efr; \ | 224 | u8 __oldlcr, __efr; \ |
330 | __oldlcr = inb((baseio)+UART_LCR); \ | 225 | __oldlcr = inb((baseio)+UART_LCR); \ |
331 | outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ | ||
332 | __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ | ||
333 | __efr &= ~MOXA_MUST_EFR_BANK_MASK; \ | ||
334 | __efr |= MOXA_MUST_EFR_BANK2; \ | ||
335 | outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ | ||
336 | *pId = inb((baseio)+MOXA_MUST_HWID_REGISTER); \ | ||
337 | outb(__oldlcr, (baseio)+UART_LCR); \ | ||
338 | } | ||
339 | |||
340 | #define SET_MOXA_MUST_NO_SOFTWARE_FLOW_CONTROL(baseio) { \ | ||
341 | u8 __oldlcr, __efr; \ | ||
342 | __oldlcr = inb((baseio)+UART_LCR); \ | ||
343 | outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ | ||
344 | __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ | ||
345 | __efr &= ~MOXA_MUST_EFR_SF_MASK; \ | ||
346 | outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ | ||
347 | outb(__oldlcr, (baseio)+UART_LCR); \ | ||
348 | } | ||
349 | |||
350 | #define SET_MOXA_MUST_JUST_TX_SOFTWARE_FLOW_CONTROL(baseio) { \ | ||
351 | u8 __oldlcr, __efr; \ | ||
352 | __oldlcr = inb((baseio)+UART_LCR); \ | ||
353 | outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ | ||
354 | __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ | ||
355 | __efr &= ~MOXA_MUST_EFR_SF_MASK; \ | ||
356 | __efr |= MOXA_MUST_EFR_SF_TX1; \ | ||
357 | outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ | ||
358 | outb(__oldlcr, (baseio)+UART_LCR); \ | ||
359 | } | ||
360 | |||
361 | #define ENABLE_MOXA_MUST_TX_SOFTWARE_FLOW_CONTROL(baseio) { \ | ||
362 | u8 __oldlcr, __efr; \ | ||
363 | __oldlcr = inb((baseio)+UART_LCR); \ | ||
364 | outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ | 226 | outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ |
365 | __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ | 227 | __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ |
366 | __efr &= ~MOXA_MUST_EFR_SF_TX_MASK; \ | 228 | __efr &= ~MOXA_MUST_EFR_BANK_MASK; \ |
367 | __efr |= MOXA_MUST_EFR_SF_TX1; \ | 229 | __efr |= MOXA_MUST_EFR_BANK2; \ |
368 | outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ | 230 | outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ |
369 | outb(__oldlcr, (baseio)+UART_LCR); \ | 231 | *pId = inb((baseio)+MOXA_MUST_HWID_REGISTER); \ |
370 | } | 232 | outb(__oldlcr, (baseio)+UART_LCR); \ |
371 | 233 | } while (0) | |
372 | #define DISABLE_MOXA_MUST_TX_SOFTWARE_FLOW_CONTROL(baseio) { \ | 234 | |
373 | u8 __oldlcr, __efr; \ | 235 | #define SET_MOXA_MUST_NO_SOFTWARE_FLOW_CONTROL(baseio) do { \ |
374 | __oldlcr = inb((baseio)+UART_LCR); \ | 236 | u8 __oldlcr, __efr; \ |
237 | __oldlcr = inb((baseio)+UART_LCR); \ | ||
375 | outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ | 238 | outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ |
376 | __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ | 239 | __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ |
377 | __efr &= ~MOXA_MUST_EFR_SF_TX_MASK; \ | 240 | __efr &= ~MOXA_MUST_EFR_SF_MASK; \ |
378 | outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ | 241 | outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ |
379 | outb(__oldlcr, (baseio)+UART_LCR); \ | 242 | outb(__oldlcr, (baseio)+UART_LCR); \ |
380 | } | 243 | } while (0) |
381 | 244 | ||
382 | #define SET_MOXA_MUST_JUST_RX_SOFTWARE_FLOW_CONTROL(baseio) { \ | 245 | #define ENABLE_MOXA_MUST_TX_SOFTWARE_FLOW_CONTROL(baseio) do { \ |
383 | u8 __oldlcr, __efr; \ | 246 | u8 __oldlcr, __efr; \ |
384 | __oldlcr = inb((baseio)+UART_LCR); \ | 247 | __oldlcr = inb((baseio)+UART_LCR); \ |
385 | outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ | 248 | outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ |
386 | __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ | 249 | __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ |
387 | __efr &= ~MOXA_MUST_EFR_SF_MASK; \ | 250 | __efr &= ~MOXA_MUST_EFR_SF_TX_MASK; \ |
388 | __efr |= MOXA_MUST_EFR_SF_RX1; \ | 251 | __efr |= MOXA_MUST_EFR_SF_TX1; \ |
389 | outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ | 252 | outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ |
390 | outb(__oldlcr, (baseio)+UART_LCR); \ | 253 | outb(__oldlcr, (baseio)+UART_LCR); \ |
391 | } | 254 | } while (0) |
392 | 255 | ||
393 | #define ENABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(baseio) { \ | 256 | #define DISABLE_MOXA_MUST_TX_SOFTWARE_FLOW_CONTROL(baseio) do { \ |
394 | u8 __oldlcr, __efr; \ | 257 | u8 __oldlcr, __efr; \ |
395 | __oldlcr = inb((baseio)+UART_LCR); \ | 258 | __oldlcr = inb((baseio)+UART_LCR); \ |
396 | outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ | 259 | outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ |
397 | __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ | 260 | __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ |
398 | __efr &= ~MOXA_MUST_EFR_SF_RX_MASK; \ | 261 | __efr &= ~MOXA_MUST_EFR_SF_TX_MASK; \ |
399 | __efr |= MOXA_MUST_EFR_SF_RX1; \ | 262 | outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ |
400 | outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ | 263 | outb(__oldlcr, (baseio)+UART_LCR); \ |
401 | outb(__oldlcr, (baseio)+UART_LCR); \ | 264 | } while (0) |
402 | } | 265 | |
403 | 266 | #define ENABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(baseio) do { \ | |
404 | #define DISABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(baseio) { \ | 267 | u8 __oldlcr, __efr; \ |
405 | u8 __oldlcr, __efr; \ | 268 | __oldlcr = inb((baseio)+UART_LCR); \ |
406 | __oldlcr = inb((baseio)+UART_LCR); \ | ||
407 | outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ | 269 | outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ |
408 | __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ | 270 | __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ |
409 | __efr &= ~MOXA_MUST_EFR_SF_RX_MASK; \ | 271 | __efr &= ~MOXA_MUST_EFR_SF_RX_MASK; \ |
410 | outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ | 272 | __efr |= MOXA_MUST_EFR_SF_RX1; \ |
411 | outb(__oldlcr, (baseio)+UART_LCR); \ | 273 | outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ |
412 | } | 274 | outb(__oldlcr, (baseio)+UART_LCR); \ |
413 | 275 | } while (0) | |
414 | #define ENABLE_MOXA_MUST_TX_RX_SOFTWARE_FLOW_CONTROL(baseio) { \ | 276 | |
415 | u8 __oldlcr, __efr; \ | 277 | #define DISABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(baseio) do { \ |
416 | __oldlcr = inb((baseio)+UART_LCR); \ | 278 | u8 __oldlcr, __efr; \ |
279 | __oldlcr = inb((baseio)+UART_LCR); \ | ||
417 | outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ | 280 | outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ |
418 | __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ | 281 | __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ |
419 | __efr &= ~MOXA_MUST_EFR_SF_MASK; \ | 282 | __efr &= ~MOXA_MUST_EFR_SF_RX_MASK; \ |
420 | __efr |= (MOXA_MUST_EFR_SF_RX1|MOXA_MUST_EFR_SF_TX1); \ | 283 | outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ |
421 | outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ | 284 | outb(__oldlcr, (baseio)+UART_LCR); \ |
422 | outb(__oldlcr, (baseio)+UART_LCR); \ | 285 | } while (0) |
423 | } | ||
424 | |||
425 | #define ENABLE_MOXA_MUST_XON_ANY_FLOW_CONTROL(baseio) { \ | ||
426 | u8 __oldmcr; \ | ||
427 | __oldmcr = inb((baseio)+UART_MCR); \ | ||
428 | __oldmcr |= MOXA_MUST_MCR_XON_ANY; \ | ||
429 | outb(__oldmcr, (baseio)+UART_MCR); \ | ||
430 | } | ||
431 | |||
432 | #define DISABLE_MOXA_MUST_XON_ANY_FLOW_CONTROL(baseio) { \ | ||
433 | u8 __oldmcr; \ | ||
434 | __oldmcr = inb((baseio)+UART_MCR); \ | ||
435 | __oldmcr &= ~MOXA_MUST_MCR_XON_ANY; \ | ||
436 | outb(__oldmcr, (baseio)+UART_MCR); \ | ||
437 | } | ||
438 | |||
439 | #define READ_MOXA_MUST_GDL(baseio) inb((baseio)+MOXA_MUST_GDL_REGISTER) | ||
440 | 286 | ||
441 | #endif | 287 | #endif |
diff --git a/drivers/char/mxser_new.c b/drivers/char/mxser_new.c deleted file mode 100644 index 081c84c7b548..000000000000 --- a/drivers/char/mxser_new.c +++ /dev/null | |||
@@ -1,2817 +0,0 @@ | |||
1 | /* | ||
2 | * mxser.c -- MOXA Smartio/Industio family multiport serial driver. | ||
3 | * | ||
4 | * Copyright (C) 1999-2006 Moxa Technologies (support@moxa.com.tw). | ||
5 | * Copyright (C) 2006-2007 Jiri Slaby <jirislaby@gmail.com> | ||
6 | * | ||
7 | * This code is loosely based on the 1.8 moxa driver which is based on | ||
8 | * Linux serial driver, written by Linus Torvalds, Theodore T'so and | ||
9 | * others. | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License as published by | ||
13 | * the Free Software Foundation; either version 2 of the License, or | ||
14 | * (at your option) any later version. | ||
15 | * | ||
16 | * Fed through a cleanup, indent and remove of non 2.6 code by Alan Cox | ||
17 | * <alan@redhat.com>. The original 1.8 code is available on www.moxa.com. | ||
18 | * - Fixed x86_64 cleanness | ||
19 | * - Fixed sleep with spinlock held in mxser_send_break | ||
20 | */ | ||
21 | |||
22 | #include <linux/module.h> | ||
23 | #include <linux/autoconf.h> | ||
24 | #include <linux/errno.h> | ||
25 | #include <linux/signal.h> | ||
26 | #include <linux/sched.h> | ||
27 | #include <linux/timer.h> | ||
28 | #include <linux/interrupt.h> | ||
29 | #include <linux/tty.h> | ||
30 | #include <linux/tty_flip.h> | ||
31 | #include <linux/serial.h> | ||
32 | #include <linux/serial_reg.h> | ||
33 | #include <linux/major.h> | ||
34 | #include <linux/string.h> | ||
35 | #include <linux/fcntl.h> | ||
36 | #include <linux/ptrace.h> | ||
37 | #include <linux/gfp.h> | ||
38 | #include <linux/ioport.h> | ||
39 | #include <linux/mm.h> | ||
40 | #include <linux/delay.h> | ||
41 | #include <linux/pci.h> | ||
42 | #include <linux/bitops.h> | ||
43 | |||
44 | #include <asm/system.h> | ||
45 | #include <asm/io.h> | ||
46 | #include <asm/irq.h> | ||
47 | #include <asm/uaccess.h> | ||
48 | |||
49 | #include "mxser_new.h" | ||
50 | |||
51 | #define MXSER_VERSION "2.0.2" /* 1.10 */ | ||
52 | #define MXSERMAJOR 174 | ||
53 | #define MXSERCUMAJOR 175 | ||
54 | |||
55 | #define MXSER_BOARDS 4 /* Max. boards */ | ||
56 | #define MXSER_PORTS_PER_BOARD 8 /* Max. ports per board */ | ||
57 | #define MXSER_PORTS (MXSER_BOARDS * MXSER_PORTS_PER_BOARD) | ||
58 | #define MXSER_ISR_PASS_LIMIT 100 | ||
59 | |||
60 | #define MXSER_ERR_IOADDR -1 | ||
61 | #define MXSER_ERR_IRQ -2 | ||
62 | #define MXSER_ERR_IRQ_CONFLIT -3 | ||
63 | #define MXSER_ERR_VECTOR -4 | ||
64 | |||
65 | /*CheckIsMoxaMust return value*/ | ||
66 | #define MOXA_OTHER_UART 0x00 | ||
67 | #define MOXA_MUST_MU150_HWID 0x01 | ||
68 | #define MOXA_MUST_MU860_HWID 0x02 | ||
69 | |||
70 | #define WAKEUP_CHARS 256 | ||
71 | |||
72 | #define UART_MCR_AFE 0x20 | ||
73 | #define UART_LSR_SPECIAL 0x1E | ||
74 | |||
75 | #define PCI_DEVICE_ID_CB108 0x1080 | ||
76 | #define PCI_DEVICE_ID_CB114 0x1142 | ||
77 | #define PCI_DEVICE_ID_CB134I 0x1341 | ||
78 | #define PCI_DEVICE_ID_CP138U 0x1380 | ||
79 | #define PCI_DEVICE_ID_POS104UL 0x1044 | ||
80 | |||
81 | |||
82 | #define C168_ASIC_ID 1 | ||
83 | #define C104_ASIC_ID 2 | ||
84 | #define C102_ASIC_ID 0xB | ||
85 | #define CI132_ASIC_ID 4 | ||
86 | #define CI134_ASIC_ID 3 | ||
87 | #define CI104J_ASIC_ID 5 | ||
88 | |||
89 | #define MXSER_HIGHBAUD 1 | ||
90 | #define MXSER_HAS2 2 | ||
91 | |||
92 | /* This is only for PCI */ | ||
93 | static const struct { | ||
94 | int type; | ||
95 | int tx_fifo; | ||
96 | int rx_fifo; | ||
97 | int xmit_fifo_size; | ||
98 | int rx_high_water; | ||
99 | int rx_trigger; | ||
100 | int rx_low_water; | ||
101 | long max_baud; | ||
102 | } Gpci_uart_info[] = { | ||
103 | {MOXA_OTHER_UART, 16, 16, 16, 14, 14, 1, 921600L}, | ||
104 | {MOXA_MUST_MU150_HWID, 64, 64, 64, 48, 48, 16, 230400L}, | ||
105 | {MOXA_MUST_MU860_HWID, 128, 128, 128, 96, 96, 32, 921600L} | ||
106 | }; | ||
107 | #define UART_INFO_NUM ARRAY_SIZE(Gpci_uart_info) | ||
108 | |||
109 | struct mxser_cardinfo { | ||
110 | unsigned int nports; | ||
111 | char *name; | ||
112 | unsigned int flags; | ||
113 | }; | ||
114 | |||
115 | static const struct mxser_cardinfo mxser_cards[] = { | ||
116 | /* 0*/ { 8, "C168 series", }, | ||
117 | { 4, "C104 series", }, | ||
118 | { 4, "CI-104J series", }, | ||
119 | { 8, "C168H/PCI series", }, | ||
120 | { 4, "C104H/PCI series", }, | ||
121 | /* 5*/ { 4, "C102 series", MXSER_HAS2 }, /* C102-ISA */ | ||
122 | { 4, "CI-132 series", MXSER_HAS2 }, | ||
123 | { 4, "CI-134 series", }, | ||
124 | { 2, "CP-132 series", }, | ||
125 | { 4, "CP-114 series", }, | ||
126 | /*10*/ { 4, "CT-114 series", }, | ||
127 | { 2, "CP-102 series", MXSER_HIGHBAUD }, | ||
128 | { 4, "CP-104U series", }, | ||
129 | { 8, "CP-168U series", }, | ||
130 | { 2, "CP-132U series", }, | ||
131 | /*15*/ { 4, "CP-134U series", }, | ||
132 | { 4, "CP-104JU series", }, | ||
133 | { 8, "Moxa UC7000 Serial", }, /* RC7000 */ | ||
134 | { 8, "CP-118U series", }, | ||
135 | { 2, "CP-102UL series", }, | ||
136 | /*20*/ { 2, "CP-102U series", }, | ||
137 | { 8, "CP-118EL series", }, | ||
138 | { 8, "CP-168EL series", }, | ||
139 | { 4, "CP-104EL series", }, | ||
140 | { 8, "CB-108 series", }, | ||
141 | /*25*/ { 4, "CB-114 series", }, | ||
142 | { 4, "CB-134I series", }, | ||
143 | { 8, "CP-138U series", }, | ||
144 | { 4, "POS-104UL series", } | ||
145 | }; | ||
146 | |||
147 | /* driver_data correspond to the lines in the structure above | ||
148 | see also ISA probe function before you change something */ | ||
149 | static struct pci_device_id mxser_pcibrds[] = { | ||
150 | { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_C168), .driver_data = 3 }, | ||
151 | { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_C104), .driver_data = 4 }, | ||
152 | { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP132), .driver_data = 8 }, | ||
153 | { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP114), .driver_data = 9 }, | ||
154 | { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CT114), .driver_data = 10 }, | ||
155 | { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP102), .driver_data = 11 }, | ||
156 | { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP104U), .driver_data = 12 }, | ||
157 | { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP168U), .driver_data = 13 }, | ||
158 | { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP132U), .driver_data = 14 }, | ||
159 | { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP134U), .driver_data = 15 }, | ||
160 | { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP104JU),.driver_data = 16 }, | ||
161 | { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_RC7000), .driver_data = 17 }, | ||
162 | { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP118U), .driver_data = 18 }, | ||
163 | { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP102UL),.driver_data = 19 }, | ||
164 | { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP102U), .driver_data = 20 }, | ||
165 | { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP118EL),.driver_data = 21 }, | ||
166 | { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP168EL),.driver_data = 22 }, | ||
167 | { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP104EL),.driver_data = 23 }, | ||
168 | { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CB108), .driver_data = 24 }, | ||
169 | { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CB114), .driver_data = 25 }, | ||
170 | { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CB134I), .driver_data = 26 }, | ||
171 | { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CP138U), .driver_data = 27 }, | ||
172 | { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_POS104UL), .driver_data = 28 }, | ||
173 | { } | ||
174 | }; | ||
175 | MODULE_DEVICE_TABLE(pci, mxser_pcibrds); | ||
176 | |||
177 | static int mxvar_baud_table[] = { | ||
178 | 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, | ||
179 | 4800, 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600 | ||
180 | }; | ||
181 | static unsigned int mxvar_baud_table1[] = { | ||
182 | 0, B50, B75, B110, B134, B150, B200, B300, B600, B1200, B1800, B2400, | ||
183 | B4800, B9600, B19200, B38400, B57600, B115200, B230400, B460800, B921600 | ||
184 | }; | ||
185 | #define BAUD_TABLE_NO ARRAY_SIZE(mxvar_baud_table) | ||
186 | |||
187 | #define B_SPEC B2000000 | ||
188 | |||
189 | static int ioaddr[MXSER_BOARDS] = { 0, 0, 0, 0 }; | ||
190 | static int ttymajor = MXSERMAJOR; | ||
191 | static int calloutmajor = MXSERCUMAJOR; | ||
192 | |||
193 | /* Variables for insmod */ | ||
194 | |||
195 | MODULE_AUTHOR("Casper Yang"); | ||
196 | MODULE_DESCRIPTION("MOXA Smartio/Industio Family Multiport Board Device Driver"); | ||
197 | module_param_array(ioaddr, int, NULL, 0); | ||
198 | module_param(ttymajor, int, 0); | ||
199 | MODULE_LICENSE("GPL"); | ||
200 | |||
201 | struct mxser_log { | ||
202 | int tick; | ||
203 | unsigned long rxcnt[MXSER_PORTS]; | ||
204 | unsigned long txcnt[MXSER_PORTS]; | ||
205 | }; | ||
206 | |||
207 | |||
208 | struct mxser_mon { | ||
209 | unsigned long rxcnt; | ||
210 | unsigned long txcnt; | ||
211 | unsigned long up_rxcnt; | ||
212 | unsigned long up_txcnt; | ||
213 | int modem_status; | ||
214 | unsigned char hold_reason; | ||
215 | }; | ||
216 | |||
217 | struct mxser_mon_ext { | ||
218 | unsigned long rx_cnt[32]; | ||
219 | unsigned long tx_cnt[32]; | ||
220 | unsigned long up_rxcnt[32]; | ||
221 | unsigned long up_txcnt[32]; | ||
222 | int modem_status[32]; | ||
223 | |||
224 | long baudrate[32]; | ||
225 | int databits[32]; | ||
226 | int stopbits[32]; | ||
227 | int parity[32]; | ||
228 | int flowctrl[32]; | ||
229 | int fifo[32]; | ||
230 | int iftype[32]; | ||
231 | }; | ||
232 | |||
233 | struct mxser_board; | ||
234 | |||
235 | struct mxser_port { | ||
236 | struct mxser_board *board; | ||
237 | struct tty_struct *tty; | ||
238 | |||
239 | unsigned long ioaddr; | ||
240 | unsigned long opmode_ioaddr; | ||
241 | int max_baud; | ||
242 | |||
243 | int rx_high_water; | ||
244 | int rx_trigger; /* Rx fifo trigger level */ | ||
245 | int rx_low_water; | ||
246 | int baud_base; /* max. speed */ | ||
247 | long realbaud; | ||
248 | int type; /* UART type */ | ||
249 | int flags; /* defined in tty.h */ | ||
250 | int speed; | ||
251 | |||
252 | int x_char; /* xon/xoff character */ | ||
253 | int IER; /* Interrupt Enable Register */ | ||
254 | int MCR; /* Modem control register */ | ||
255 | |||
256 | unsigned char stop_rx; | ||
257 | unsigned char ldisc_stop_rx; | ||
258 | |||
259 | int custom_divisor; | ||
260 | int close_delay; | ||
261 | unsigned short closing_wait; | ||
262 | unsigned char err_shadow; | ||
263 | unsigned long event; | ||
264 | |||
265 | int count; /* # of fd on device */ | ||
266 | int blocked_open; /* # of blocked opens */ | ||
267 | struct async_icount icount; /* kernel counters for 4 input interrupts */ | ||
268 | int timeout; | ||
269 | |||
270 | int read_status_mask; | ||
271 | int ignore_status_mask; | ||
272 | int xmit_fifo_size; | ||
273 | unsigned char *xmit_buf; | ||
274 | int xmit_head; | ||
275 | int xmit_tail; | ||
276 | int xmit_cnt; | ||
277 | |||
278 | struct ktermios normal_termios; | ||
279 | |||
280 | struct mxser_mon mon_data; | ||
281 | |||
282 | spinlock_t slock; | ||
283 | wait_queue_head_t open_wait; | ||
284 | wait_queue_head_t delta_msr_wait; | ||
285 | }; | ||
286 | |||
287 | struct mxser_board { | ||
288 | unsigned int idx; | ||
289 | int irq; | ||
290 | const struct mxser_cardinfo *info; | ||
291 | unsigned long vector; | ||
292 | unsigned long vector_mask; | ||
293 | |||
294 | int chip_flag; | ||
295 | int uart_type; | ||
296 | |||
297 | struct mxser_port ports[MXSER_PORTS_PER_BOARD]; | ||
298 | }; | ||
299 | |||
300 | struct mxser_mstatus { | ||
301 | tcflag_t cflag; | ||
302 | int cts; | ||
303 | int dsr; | ||
304 | int ri; | ||
305 | int dcd; | ||
306 | }; | ||
307 | |||
308 | static struct mxser_mstatus GMStatus[MXSER_PORTS]; | ||
309 | |||
310 | static int mxserBoardCAP[MXSER_BOARDS] = { | ||
311 | 0, 0, 0, 0 | ||
312 | /* 0x180, 0x280, 0x200, 0x320 */ | ||
313 | }; | ||
314 | |||
315 | static struct mxser_board mxser_boards[MXSER_BOARDS]; | ||
316 | static struct tty_driver *mxvar_sdriver; | ||
317 | static struct mxser_log mxvar_log; | ||
318 | static int mxvar_diagflag; | ||
319 | static unsigned char mxser_msr[MXSER_PORTS + 1]; | ||
320 | static struct mxser_mon_ext mon_data_ext; | ||
321 | static int mxser_set_baud_method[MXSER_PORTS + 1]; | ||
322 | |||
323 | #ifdef CONFIG_PCI | ||
324 | static int __devinit CheckIsMoxaMust(int io) | ||
325 | { | ||
326 | u8 oldmcr, hwid; | ||
327 | int i; | ||
328 | |||
329 | outb(0, io + UART_LCR); | ||
330 | DISABLE_MOXA_MUST_ENCHANCE_MODE(io); | ||
331 | oldmcr = inb(io + UART_MCR); | ||
332 | outb(0, io + UART_MCR); | ||
333 | SET_MOXA_MUST_XON1_VALUE(io, 0x11); | ||
334 | if ((hwid = inb(io + UART_MCR)) != 0) { | ||
335 | outb(oldmcr, io + UART_MCR); | ||
336 | return MOXA_OTHER_UART; | ||
337 | } | ||
338 | |||
339 | GET_MOXA_MUST_HARDWARE_ID(io, &hwid); | ||
340 | for (i = 1; i < UART_INFO_NUM; i++) { /* 0 = OTHER_UART */ | ||
341 | if (hwid == Gpci_uart_info[i].type) | ||
342 | return (int)hwid; | ||
343 | } | ||
344 | return MOXA_OTHER_UART; | ||
345 | } | ||
346 | #endif | ||
347 | |||
348 | static void process_txrx_fifo(struct mxser_port *info) | ||
349 | { | ||
350 | int i; | ||
351 | |||
352 | if ((info->type == PORT_16450) || (info->type == PORT_8250)) { | ||
353 | info->rx_trigger = 1; | ||
354 | info->rx_high_water = 1; | ||
355 | info->rx_low_water = 1; | ||
356 | info->xmit_fifo_size = 1; | ||
357 | } else | ||
358 | for (i = 0; i < UART_INFO_NUM; i++) | ||
359 | if (info->board->chip_flag == Gpci_uart_info[i].type) { | ||
360 | info->rx_trigger = Gpci_uart_info[i].rx_trigger; | ||
361 | info->rx_low_water = Gpci_uart_info[i].rx_low_water; | ||
362 | info->rx_high_water = Gpci_uart_info[i].rx_high_water; | ||
363 | info->xmit_fifo_size = Gpci_uart_info[i].xmit_fifo_size; | ||
364 | break; | ||
365 | } | ||
366 | } | ||
367 | |||
368 | static unsigned char mxser_get_msr(int baseaddr, int mode, int port) | ||
369 | { | ||
370 | unsigned char status = 0; | ||
371 | |||
372 | status = inb(baseaddr + UART_MSR); | ||
373 | |||
374 | mxser_msr[port] &= 0x0F; | ||
375 | mxser_msr[port] |= status; | ||
376 | status = mxser_msr[port]; | ||
377 | if (mode) | ||
378 | mxser_msr[port] = 0; | ||
379 | |||
380 | return status; | ||
381 | } | ||
382 | |||
383 | static int mxser_block_til_ready(struct tty_struct *tty, struct file *filp, | ||
384 | struct mxser_port *port) | ||
385 | { | ||
386 | DECLARE_WAITQUEUE(wait, current); | ||
387 | int retval; | ||
388 | int do_clocal = 0; | ||
389 | unsigned long flags; | ||
390 | |||
391 | /* | ||
392 | * If non-blocking mode is set, or the port is not enabled, | ||
393 | * then make the check up front and then exit. | ||
394 | */ | ||
395 | if ((filp->f_flags & O_NONBLOCK) || | ||
396 | test_bit(TTY_IO_ERROR, &tty->flags)) { | ||
397 | port->flags |= ASYNC_NORMAL_ACTIVE; | ||
398 | return 0; | ||
399 | } | ||
400 | |||
401 | if (tty->termios->c_cflag & CLOCAL) | ||
402 | do_clocal = 1; | ||
403 | |||
404 | /* | ||
405 | * Block waiting for the carrier detect and the line to become | ||
406 | * free (i.e., not in use by the callout). While we are in | ||
407 | * this loop, port->count is dropped by one, so that | ||
408 | * mxser_close() knows when to free things. We restore it upon | ||
409 | * exit, either normal or abnormal. | ||
410 | */ | ||
411 | retval = 0; | ||
412 | add_wait_queue(&port->open_wait, &wait); | ||
413 | |||
414 | spin_lock_irqsave(&port->slock, flags); | ||
415 | if (!tty_hung_up_p(filp)) | ||
416 | port->count--; | ||
417 | spin_unlock_irqrestore(&port->slock, flags); | ||
418 | port->blocked_open++; | ||
419 | while (1) { | ||
420 | spin_lock_irqsave(&port->slock, flags); | ||
421 | outb(inb(port->ioaddr + UART_MCR) | | ||
422 | UART_MCR_DTR | UART_MCR_RTS, port->ioaddr + UART_MCR); | ||
423 | spin_unlock_irqrestore(&port->slock, flags); | ||
424 | set_current_state(TASK_INTERRUPTIBLE); | ||
425 | if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)) { | ||
426 | if (port->flags & ASYNC_HUP_NOTIFY) | ||
427 | retval = -EAGAIN; | ||
428 | else | ||
429 | retval = -ERESTARTSYS; | ||
430 | break; | ||
431 | } | ||
432 | if (!(port->flags & ASYNC_CLOSING) && | ||
433 | (do_clocal || | ||
434 | (inb(port->ioaddr + UART_MSR) & UART_MSR_DCD))) | ||
435 | break; | ||
436 | if (signal_pending(current)) { | ||
437 | retval = -ERESTARTSYS; | ||
438 | break; | ||
439 | } | ||
440 | schedule(); | ||
441 | } | ||
442 | set_current_state(TASK_RUNNING); | ||
443 | remove_wait_queue(&port->open_wait, &wait); | ||
444 | if (!tty_hung_up_p(filp)) | ||
445 | port->count++; | ||
446 | port->blocked_open--; | ||
447 | if (retval) | ||
448 | return retval; | ||
449 | port->flags |= ASYNC_NORMAL_ACTIVE; | ||
450 | return 0; | ||
451 | } | ||
452 | |||
453 | static int mxser_set_baud(struct mxser_port *info, long newspd) | ||
454 | { | ||
455 | unsigned int i; | ||
456 | int quot = 0; | ||
457 | unsigned char cval; | ||
458 | int ret = 0; | ||
459 | |||
460 | if (!info->tty || !info->tty->termios) | ||
461 | return ret; | ||
462 | |||
463 | if (!(info->ioaddr)) | ||
464 | return ret; | ||
465 | |||
466 | if (newspd > info->max_baud) | ||
467 | return 0; | ||
468 | |||
469 | info->realbaud = newspd; | ||
470 | for (i = 0; i < BAUD_TABLE_NO; i++) | ||
471 | if (newspd == mxvar_baud_table[i]) | ||
472 | break; | ||
473 | if (i == BAUD_TABLE_NO) { | ||
474 | quot = info->baud_base / info->speed; | ||
475 | if (info->speed <= 0 || info->speed > info->max_baud) | ||
476 | quot = 0; | ||
477 | } else { | ||
478 | if (newspd == 134) { | ||
479 | quot = (2 * info->baud_base / 269); | ||
480 | } else if (newspd) { | ||
481 | quot = info->baud_base / newspd; | ||
482 | if (quot == 0) | ||
483 | quot = 1; | ||
484 | } else { | ||
485 | quot = 0; | ||
486 | } | ||
487 | } | ||
488 | |||
489 | info->timeout = ((info->xmit_fifo_size * HZ * 10 * quot) / info->baud_base); | ||
490 | info->timeout += HZ / 50; /* Add .02 seconds of slop */ | ||
491 | |||
492 | if (quot) { | ||
493 | info->MCR |= UART_MCR_DTR; | ||
494 | outb(info->MCR, info->ioaddr + UART_MCR); | ||
495 | } else { | ||
496 | info->MCR &= ~UART_MCR_DTR; | ||
497 | outb(info->MCR, info->ioaddr + UART_MCR); | ||
498 | return ret; | ||
499 | } | ||
500 | |||
501 | cval = inb(info->ioaddr + UART_LCR); | ||
502 | |||
503 | outb(cval | UART_LCR_DLAB, info->ioaddr + UART_LCR); /* set DLAB */ | ||
504 | |||
505 | outb(quot & 0xff, info->ioaddr + UART_DLL); /* LS of divisor */ | ||
506 | outb(quot >> 8, info->ioaddr + UART_DLM); /* MS of divisor */ | ||
507 | outb(cval, info->ioaddr + UART_LCR); /* reset DLAB */ | ||
508 | |||
509 | if (i == BAUD_TABLE_NO) { | ||
510 | quot = info->baud_base % info->speed; | ||
511 | quot *= 8; | ||
512 | if ((quot % info->speed) > (info->speed / 2)) { | ||
513 | quot /= info->speed; | ||
514 | quot++; | ||
515 | } else { | ||
516 | quot /= info->speed; | ||
517 | } | ||
518 | SET_MOXA_MUST_ENUM_VALUE(info->ioaddr, quot); | ||
519 | } else | ||
520 | SET_MOXA_MUST_ENUM_VALUE(info->ioaddr, 0); | ||
521 | |||
522 | return ret; | ||
523 | } | ||
524 | |||
525 | /* | ||
526 | * This routine is called to set the UART divisor registers to match | ||
527 | * the specified baud rate for a serial port. | ||
528 | */ | ||
529 | static int mxser_change_speed(struct mxser_port *info, | ||
530 | struct ktermios *old_termios) | ||
531 | { | ||
532 | unsigned cflag, cval, fcr; | ||
533 | int ret = 0; | ||
534 | unsigned char status; | ||
535 | long baud; | ||
536 | |||
537 | if (!info->tty || !info->tty->termios) | ||
538 | return ret; | ||
539 | cflag = info->tty->termios->c_cflag; | ||
540 | if (!(info->ioaddr)) | ||
541 | return ret; | ||
542 | |||
543 | if (mxser_set_baud_method[info->tty->index] == 0) { | ||
544 | if ((cflag & CBAUD) == B_SPEC) | ||
545 | baud = info->speed; | ||
546 | else | ||
547 | baud = tty_get_baud_rate(info->tty); | ||
548 | mxser_set_baud(info, baud); | ||
549 | } | ||
550 | |||
551 | /* byte size and parity */ | ||
552 | switch (cflag & CSIZE) { | ||
553 | case CS5: | ||
554 | cval = 0x00; | ||
555 | break; | ||
556 | case CS6: | ||
557 | cval = 0x01; | ||
558 | break; | ||
559 | case CS7: | ||
560 | cval = 0x02; | ||
561 | break; | ||
562 | case CS8: | ||
563 | cval = 0x03; | ||
564 | break; | ||
565 | default: | ||
566 | cval = 0x00; | ||
567 | break; /* too keep GCC shut... */ | ||
568 | } | ||
569 | if (cflag & CSTOPB) | ||
570 | cval |= 0x04; | ||
571 | if (cflag & PARENB) | ||
572 | cval |= UART_LCR_PARITY; | ||
573 | if (!(cflag & PARODD)) | ||
574 | cval |= UART_LCR_EPAR; | ||
575 | if (cflag & CMSPAR) | ||
576 | cval |= UART_LCR_SPAR; | ||
577 | |||
578 | if ((info->type == PORT_8250) || (info->type == PORT_16450)) { | ||
579 | if (info->board->chip_flag) { | ||
580 | fcr = UART_FCR_ENABLE_FIFO; | ||
581 | fcr |= MOXA_MUST_FCR_GDA_MODE_ENABLE; | ||
582 | SET_MOXA_MUST_FIFO_VALUE(info); | ||
583 | } else | ||
584 | fcr = 0; | ||
585 | } else { | ||
586 | fcr = UART_FCR_ENABLE_FIFO; | ||
587 | if (info->board->chip_flag) { | ||
588 | fcr |= MOXA_MUST_FCR_GDA_MODE_ENABLE; | ||
589 | SET_MOXA_MUST_FIFO_VALUE(info); | ||
590 | } else { | ||
591 | switch (info->rx_trigger) { | ||
592 | case 1: | ||
593 | fcr |= UART_FCR_TRIGGER_1; | ||
594 | break; | ||
595 | case 4: | ||
596 | fcr |= UART_FCR_TRIGGER_4; | ||
597 | break; | ||
598 | case 8: | ||
599 | fcr |= UART_FCR_TRIGGER_8; | ||
600 | break; | ||
601 | default: | ||
602 | fcr |= UART_FCR_TRIGGER_14; | ||
603 | break; | ||
604 | } | ||
605 | } | ||
606 | } | ||
607 | |||
608 | /* CTS flow control flag and modem status interrupts */ | ||
609 | info->IER &= ~UART_IER_MSI; | ||
610 | info->MCR &= ~UART_MCR_AFE; | ||
611 | if (cflag & CRTSCTS) { | ||
612 | info->flags |= ASYNC_CTS_FLOW; | ||
613 | info->IER |= UART_IER_MSI; | ||
614 | if ((info->type == PORT_16550A) || (info->board->chip_flag)) { | ||
615 | info->MCR |= UART_MCR_AFE; | ||
616 | } else { | ||
617 | status = inb(info->ioaddr + UART_MSR); | ||
618 | if (info->tty->hw_stopped) { | ||
619 | if (status & UART_MSR_CTS) { | ||
620 | info->tty->hw_stopped = 0; | ||
621 | if (info->type != PORT_16550A && | ||
622 | !info->board->chip_flag) { | ||
623 | outb(info->IER & ~UART_IER_THRI, | ||
624 | info->ioaddr + | ||
625 | UART_IER); | ||
626 | info->IER |= UART_IER_THRI; | ||
627 | outb(info->IER, info->ioaddr + | ||
628 | UART_IER); | ||
629 | } | ||
630 | tty_wakeup(info->tty); | ||
631 | } | ||
632 | } else { | ||
633 | if (!(status & UART_MSR_CTS)) { | ||
634 | info->tty->hw_stopped = 1; | ||
635 | if ((info->type != PORT_16550A) && | ||
636 | (!info->board->chip_flag)) { | ||
637 | info->IER &= ~UART_IER_THRI; | ||
638 | outb(info->IER, info->ioaddr + | ||
639 | UART_IER); | ||
640 | } | ||
641 | } | ||
642 | } | ||
643 | } | ||
644 | } else { | ||
645 | info->flags &= ~ASYNC_CTS_FLOW; | ||
646 | } | ||
647 | outb(info->MCR, info->ioaddr + UART_MCR); | ||
648 | if (cflag & CLOCAL) { | ||
649 | info->flags &= ~ASYNC_CHECK_CD; | ||
650 | } else { | ||
651 | info->flags |= ASYNC_CHECK_CD; | ||
652 | info->IER |= UART_IER_MSI; | ||
653 | } | ||
654 | outb(info->IER, info->ioaddr + UART_IER); | ||
655 | |||
656 | /* | ||
657 | * Set up parity check flag | ||
658 | */ | ||
659 | info->read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR; | ||
660 | if (I_INPCK(info->tty)) | ||
661 | info->read_status_mask |= UART_LSR_FE | UART_LSR_PE; | ||
662 | if (I_BRKINT(info->tty) || I_PARMRK(info->tty)) | ||
663 | info->read_status_mask |= UART_LSR_BI; | ||
664 | |||
665 | info->ignore_status_mask = 0; | ||
666 | |||
667 | if (I_IGNBRK(info->tty)) { | ||
668 | info->ignore_status_mask |= UART_LSR_BI; | ||
669 | info->read_status_mask |= UART_LSR_BI; | ||
670 | /* | ||
671 | * If we're ignore parity and break indicators, ignore | ||
672 | * overruns too. (For real raw support). | ||
673 | */ | ||
674 | if (I_IGNPAR(info->tty)) { | ||
675 | info->ignore_status_mask |= | ||
676 | UART_LSR_OE | | ||
677 | UART_LSR_PE | | ||
678 | UART_LSR_FE; | ||
679 | info->read_status_mask |= | ||
680 | UART_LSR_OE | | ||
681 | UART_LSR_PE | | ||
682 | UART_LSR_FE; | ||
683 | } | ||
684 | } | ||
685 | if (info->board->chip_flag) { | ||
686 | SET_MOXA_MUST_XON1_VALUE(info->ioaddr, START_CHAR(info->tty)); | ||
687 | SET_MOXA_MUST_XOFF1_VALUE(info->ioaddr, STOP_CHAR(info->tty)); | ||
688 | if (I_IXON(info->tty)) { | ||
689 | ENABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(info->ioaddr); | ||
690 | } else { | ||
691 | DISABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(info->ioaddr); | ||
692 | } | ||
693 | if (I_IXOFF(info->tty)) { | ||
694 | ENABLE_MOXA_MUST_TX_SOFTWARE_FLOW_CONTROL(info->ioaddr); | ||
695 | } else { | ||
696 | DISABLE_MOXA_MUST_TX_SOFTWARE_FLOW_CONTROL(info->ioaddr); | ||
697 | } | ||
698 | } | ||
699 | |||
700 | |||
701 | outb(fcr, info->ioaddr + UART_FCR); /* set fcr */ | ||
702 | outb(cval, info->ioaddr + UART_LCR); | ||
703 | |||
704 | return ret; | ||
705 | } | ||
706 | |||
707 | static void mxser_check_modem_status(struct mxser_port *port, int status) | ||
708 | { | ||
709 | /* update input line counters */ | ||
710 | if (status & UART_MSR_TERI) | ||
711 | port->icount.rng++; | ||
712 | if (status & UART_MSR_DDSR) | ||
713 | port->icount.dsr++; | ||
714 | if (status & UART_MSR_DDCD) | ||
715 | port->icount.dcd++; | ||
716 | if (status & UART_MSR_DCTS) | ||
717 | port->icount.cts++; | ||
718 | port->mon_data.modem_status = status; | ||
719 | wake_up_interruptible(&port->delta_msr_wait); | ||
720 | |||
721 | if ((port->flags & ASYNC_CHECK_CD) && (status & UART_MSR_DDCD)) { | ||
722 | if (status & UART_MSR_DCD) | ||
723 | wake_up_interruptible(&port->open_wait); | ||
724 | } | ||
725 | |||
726 | if (port->flags & ASYNC_CTS_FLOW) { | ||
727 | if (port->tty->hw_stopped) { | ||
728 | if (status & UART_MSR_CTS) { | ||
729 | port->tty->hw_stopped = 0; | ||
730 | |||
731 | if ((port->type != PORT_16550A) && | ||
732 | (!port->board->chip_flag)) { | ||
733 | outb(port->IER & ~UART_IER_THRI, | ||
734 | port->ioaddr + UART_IER); | ||
735 | port->IER |= UART_IER_THRI; | ||
736 | outb(port->IER, port->ioaddr + | ||
737 | UART_IER); | ||
738 | } | ||
739 | tty_wakeup(port->tty); | ||
740 | } | ||
741 | } else { | ||
742 | if (!(status & UART_MSR_CTS)) { | ||
743 | port->tty->hw_stopped = 1; | ||
744 | if (port->type != PORT_16550A && | ||
745 | !port->board->chip_flag) { | ||
746 | port->IER &= ~UART_IER_THRI; | ||
747 | outb(port->IER, port->ioaddr + | ||
748 | UART_IER); | ||
749 | } | ||
750 | } | ||
751 | } | ||
752 | } | ||
753 | } | ||
754 | |||
755 | static int mxser_startup(struct mxser_port *info) | ||
756 | { | ||
757 | unsigned long page; | ||
758 | unsigned long flags; | ||
759 | |||
760 | page = __get_free_page(GFP_KERNEL); | ||
761 | if (!page) | ||
762 | return -ENOMEM; | ||
763 | |||
764 | spin_lock_irqsave(&info->slock, flags); | ||
765 | |||
766 | if (info->flags & ASYNC_INITIALIZED) { | ||
767 | free_page(page); | ||
768 | spin_unlock_irqrestore(&info->slock, flags); | ||
769 | return 0; | ||
770 | } | ||
771 | |||
772 | if (!info->ioaddr || !info->type) { | ||
773 | if (info->tty) | ||
774 | set_bit(TTY_IO_ERROR, &info->tty->flags); | ||
775 | free_page(page); | ||
776 | spin_unlock_irqrestore(&info->slock, flags); | ||
777 | return 0; | ||
778 | } | ||
779 | if (info->xmit_buf) | ||
780 | free_page(page); | ||
781 | else | ||
782 | info->xmit_buf = (unsigned char *) page; | ||
783 | |||
784 | /* | ||
785 | * Clear the FIFO buffers and disable them | ||
786 | * (they will be reenabled in mxser_change_speed()) | ||
787 | */ | ||
788 | if (info->board->chip_flag) | ||
789 | outb((UART_FCR_CLEAR_RCVR | | ||
790 | UART_FCR_CLEAR_XMIT | | ||
791 | MOXA_MUST_FCR_GDA_MODE_ENABLE), info->ioaddr + UART_FCR); | ||
792 | else | ||
793 | outb((UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT), | ||
794 | info->ioaddr + UART_FCR); | ||
795 | |||
796 | /* | ||
797 | * At this point there's no way the LSR could still be 0xFF; | ||
798 | * if it is, then bail out, because there's likely no UART | ||
799 | * here. | ||
800 | */ | ||
801 | if (inb(info->ioaddr + UART_LSR) == 0xff) { | ||
802 | spin_unlock_irqrestore(&info->slock, flags); | ||
803 | if (capable(CAP_SYS_ADMIN)) { | ||
804 | if (info->tty) | ||
805 | set_bit(TTY_IO_ERROR, &info->tty->flags); | ||
806 | return 0; | ||
807 | } else | ||
808 | return -ENODEV; | ||
809 | } | ||
810 | |||
811 | /* | ||
812 | * Clear the interrupt registers. | ||
813 | */ | ||
814 | (void) inb(info->ioaddr + UART_LSR); | ||
815 | (void) inb(info->ioaddr + UART_RX); | ||
816 | (void) inb(info->ioaddr + UART_IIR); | ||
817 | (void) inb(info->ioaddr + UART_MSR); | ||
818 | |||
819 | /* | ||
820 | * Now, initialize the UART | ||
821 | */ | ||
822 | outb(UART_LCR_WLEN8, info->ioaddr + UART_LCR); /* reset DLAB */ | ||
823 | info->MCR = UART_MCR_DTR | UART_MCR_RTS; | ||
824 | outb(info->MCR, info->ioaddr + UART_MCR); | ||
825 | |||
826 | /* | ||
827 | * Finally, enable interrupts | ||
828 | */ | ||
829 | info->IER = UART_IER_MSI | UART_IER_RLSI | UART_IER_RDI; | ||
830 | |||
831 | if (info->board->chip_flag) | ||
832 | info->IER |= MOXA_MUST_IER_EGDAI; | ||
833 | outb(info->IER, info->ioaddr + UART_IER); /* enable interrupts */ | ||
834 | |||
835 | /* | ||
836 | * And clear the interrupt registers again for luck. | ||
837 | */ | ||
838 | (void) inb(info->ioaddr + UART_LSR); | ||
839 | (void) inb(info->ioaddr + UART_RX); | ||
840 | (void) inb(info->ioaddr + UART_IIR); | ||
841 | (void) inb(info->ioaddr + UART_MSR); | ||
842 | |||
843 | if (info->tty) | ||
844 | clear_bit(TTY_IO_ERROR, &info->tty->flags); | ||
845 | info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; | ||
846 | |||
847 | /* | ||
848 | * and set the speed of the serial port | ||
849 | */ | ||
850 | mxser_change_speed(info, NULL); | ||
851 | info->flags |= ASYNC_INITIALIZED; | ||
852 | spin_unlock_irqrestore(&info->slock, flags); | ||
853 | |||
854 | return 0; | ||
855 | } | ||
856 | |||
857 | /* | ||
858 | * This routine will shutdown a serial port; interrupts maybe disabled, and | ||
859 | * DTR is dropped if the hangup on close termio flag is on. | ||
860 | */ | ||
861 | static void mxser_shutdown(struct mxser_port *info) | ||
862 | { | ||
863 | unsigned long flags; | ||
864 | |||
865 | if (!(info->flags & ASYNC_INITIALIZED)) | ||
866 | return; | ||
867 | |||
868 | spin_lock_irqsave(&info->slock, flags); | ||
869 | |||
870 | /* | ||
871 | * clear delta_msr_wait queue to avoid mem leaks: we may free the irq | ||
872 | * here so the queue might never be waken up | ||
873 | */ | ||
874 | wake_up_interruptible(&info->delta_msr_wait); | ||
875 | |||
876 | /* | ||
877 | * Free the IRQ, if necessary | ||
878 | */ | ||
879 | if (info->xmit_buf) { | ||
880 | free_page((unsigned long) info->xmit_buf); | ||
881 | info->xmit_buf = NULL; | ||
882 | } | ||
883 | |||
884 | info->IER = 0; | ||
885 | outb(0x00, info->ioaddr + UART_IER); | ||
886 | |||
887 | if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) | ||
888 | info->MCR &= ~(UART_MCR_DTR | UART_MCR_RTS); | ||
889 | outb(info->MCR, info->ioaddr + UART_MCR); | ||
890 | |||
891 | /* clear Rx/Tx FIFO's */ | ||
892 | if (info->board->chip_flag) | ||
893 | outb(UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT | | ||
894 | MOXA_MUST_FCR_GDA_MODE_ENABLE, | ||
895 | info->ioaddr + UART_FCR); | ||
896 | else | ||
897 | outb(UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT, | ||
898 | info->ioaddr + UART_FCR); | ||
899 | |||
900 | /* read data port to reset things */ | ||
901 | (void) inb(info->ioaddr + UART_RX); | ||
902 | |||
903 | if (info->tty) | ||
904 | set_bit(TTY_IO_ERROR, &info->tty->flags); | ||
905 | |||
906 | info->flags &= ~ASYNC_INITIALIZED; | ||
907 | |||
908 | if (info->board->chip_flag) | ||
909 | SET_MOXA_MUST_NO_SOFTWARE_FLOW_CONTROL(info->ioaddr); | ||
910 | |||
911 | spin_unlock_irqrestore(&info->slock, flags); | ||
912 | } | ||
913 | |||
914 | /* | ||
915 | * This routine is called whenever a serial port is opened. It | ||
916 | * enables interrupts for a serial port, linking in its async structure into | ||
917 | * the IRQ chain. It also performs the serial-specific | ||
918 | * initialization for the tty structure. | ||
919 | */ | ||
920 | static int mxser_open(struct tty_struct *tty, struct file *filp) | ||
921 | { | ||
922 | struct mxser_port *info; | ||
923 | unsigned long flags; | ||
924 | int retval, line; | ||
925 | |||
926 | line = tty->index; | ||
927 | if (line == MXSER_PORTS) | ||
928 | return 0; | ||
929 | if (line < 0 || line > MXSER_PORTS) | ||
930 | return -ENODEV; | ||
931 | info = &mxser_boards[line / MXSER_PORTS_PER_BOARD].ports[line % MXSER_PORTS_PER_BOARD]; | ||
932 | if (!info->ioaddr) | ||
933 | return -ENODEV; | ||
934 | |||
935 | tty->driver_data = info; | ||
936 | info->tty = tty; | ||
937 | /* | ||
938 | * Start up serial port | ||
939 | */ | ||
940 | spin_lock_irqsave(&info->slock, flags); | ||
941 | info->count++; | ||
942 | spin_unlock_irqrestore(&info->slock, flags); | ||
943 | retval = mxser_startup(info); | ||
944 | if (retval) | ||
945 | return retval; | ||
946 | |||
947 | retval = mxser_block_til_ready(tty, filp, info); | ||
948 | if (retval) | ||
949 | return retval; | ||
950 | |||
951 | /* unmark here for very high baud rate (ex. 921600 bps) used */ | ||
952 | tty->low_latency = 1; | ||
953 | return 0; | ||
954 | } | ||
955 | |||
956 | /* | ||
957 | * This routine is called when the serial port gets closed. First, we | ||
958 | * wait for the last remaining data to be sent. Then, we unlink its | ||
959 | * async structure from the interrupt chain if necessary, and we free | ||
960 | * that IRQ if nothing is left in the chain. | ||
961 | */ | ||
962 | static void mxser_close(struct tty_struct *tty, struct file *filp) | ||
963 | { | ||
964 | struct mxser_port *info = tty->driver_data; | ||
965 | |||
966 | unsigned long timeout; | ||
967 | unsigned long flags; | ||
968 | |||
969 | if (tty->index == MXSER_PORTS) | ||
970 | return; | ||
971 | if (!info) | ||
972 | return; | ||
973 | |||
974 | spin_lock_irqsave(&info->slock, flags); | ||
975 | |||
976 | if (tty_hung_up_p(filp)) { | ||
977 | spin_unlock_irqrestore(&info->slock, flags); | ||
978 | return; | ||
979 | } | ||
980 | if ((tty->count == 1) && (info->count != 1)) { | ||
981 | /* | ||
982 | * Uh, oh. tty->count is 1, which means that the tty | ||
983 | * structure will be freed. Info->count should always | ||
984 | * be one in these conditions. If it's greater than | ||
985 | * one, we've got real problems, since it means the | ||
986 | * serial port won't be shutdown. | ||
987 | */ | ||
988 | printk(KERN_ERR "mxser_close: bad serial port count; " | ||
989 | "tty->count is 1, info->count is %d\n", info->count); | ||
990 | info->count = 1; | ||
991 | } | ||
992 | if (--info->count < 0) { | ||
993 | printk(KERN_ERR "mxser_close: bad serial port count for " | ||
994 | "ttys%d: %d\n", tty->index, info->count); | ||
995 | info->count = 0; | ||
996 | } | ||
997 | if (info->count) { | ||
998 | spin_unlock_irqrestore(&info->slock, flags); | ||
999 | return; | ||
1000 | } | ||
1001 | info->flags |= ASYNC_CLOSING; | ||
1002 | spin_unlock_irqrestore(&info->slock, flags); | ||
1003 | /* | ||
1004 | * Save the termios structure, since this port may have | ||
1005 | * separate termios for callout and dialin. | ||
1006 | */ | ||
1007 | if (info->flags & ASYNC_NORMAL_ACTIVE) | ||
1008 | info->normal_termios = *tty->termios; | ||
1009 | /* | ||
1010 | * Now we wait for the transmit buffer to clear; and we notify | ||
1011 | * the line discipline to only process XON/XOFF characters. | ||
1012 | */ | ||
1013 | tty->closing = 1; | ||
1014 | if (info->closing_wait != ASYNC_CLOSING_WAIT_NONE) | ||
1015 | tty_wait_until_sent(tty, info->closing_wait); | ||
1016 | /* | ||
1017 | * At this point we stop accepting input. To do this, we | ||
1018 | * disable the receive line status interrupts, and tell the | ||
1019 | * interrupt driver to stop checking the data ready bit in the | ||
1020 | * line status register. | ||
1021 | */ | ||
1022 | info->IER &= ~UART_IER_RLSI; | ||
1023 | if (info->board->chip_flag) | ||
1024 | info->IER &= ~MOXA_MUST_RECV_ISR; | ||
1025 | |||
1026 | if (info->flags & ASYNC_INITIALIZED) { | ||
1027 | outb(info->IER, info->ioaddr + UART_IER); | ||
1028 | /* | ||
1029 | * Before we drop DTR, make sure the UART transmitter | ||
1030 | * has completely drained; this is especially | ||
1031 | * important if there is a transmit FIFO! | ||
1032 | */ | ||
1033 | timeout = jiffies + HZ; | ||
1034 | while (!(inb(info->ioaddr + UART_LSR) & UART_LSR_TEMT)) { | ||
1035 | schedule_timeout_interruptible(5); | ||
1036 | if (time_after(jiffies, timeout)) | ||
1037 | break; | ||
1038 | } | ||
1039 | } | ||
1040 | mxser_shutdown(info); | ||
1041 | |||
1042 | if (tty->driver->flush_buffer) | ||
1043 | tty->driver->flush_buffer(tty); | ||
1044 | |||
1045 | tty_ldisc_flush(tty); | ||
1046 | |||
1047 | tty->closing = 0; | ||
1048 | info->event = 0; | ||
1049 | info->tty = NULL; | ||
1050 | if (info->blocked_open) { | ||
1051 | if (info->close_delay) | ||
1052 | schedule_timeout_interruptible(info->close_delay); | ||
1053 | wake_up_interruptible(&info->open_wait); | ||
1054 | } | ||
1055 | |||
1056 | info->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING); | ||
1057 | } | ||
1058 | |||
1059 | static int mxser_write(struct tty_struct *tty, const unsigned char *buf, int count) | ||
1060 | { | ||
1061 | int c, total = 0; | ||
1062 | struct mxser_port *info = tty->driver_data; | ||
1063 | unsigned long flags; | ||
1064 | |||
1065 | if (!info->xmit_buf) | ||
1066 | return 0; | ||
1067 | |||
1068 | while (1) { | ||
1069 | c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, | ||
1070 | SERIAL_XMIT_SIZE - info->xmit_head)); | ||
1071 | if (c <= 0) | ||
1072 | break; | ||
1073 | |||
1074 | memcpy(info->xmit_buf + info->xmit_head, buf, c); | ||
1075 | spin_lock_irqsave(&info->slock, flags); | ||
1076 | info->xmit_head = (info->xmit_head + c) & | ||
1077 | (SERIAL_XMIT_SIZE - 1); | ||
1078 | info->xmit_cnt += c; | ||
1079 | spin_unlock_irqrestore(&info->slock, flags); | ||
1080 | |||
1081 | buf += c; | ||
1082 | count -= c; | ||
1083 | total += c; | ||
1084 | } | ||
1085 | |||
1086 | if (info->xmit_cnt && !tty->stopped) { | ||
1087 | if (!tty->hw_stopped || | ||
1088 | (info->type == PORT_16550A) || | ||
1089 | (info->board->chip_flag)) { | ||
1090 | spin_lock_irqsave(&info->slock, flags); | ||
1091 | outb(info->IER & ~UART_IER_THRI, info->ioaddr + | ||
1092 | UART_IER); | ||
1093 | info->IER |= UART_IER_THRI; | ||
1094 | outb(info->IER, info->ioaddr + UART_IER); | ||
1095 | spin_unlock_irqrestore(&info->slock, flags); | ||
1096 | } | ||
1097 | } | ||
1098 | return total; | ||
1099 | } | ||
1100 | |||
1101 | static void mxser_put_char(struct tty_struct *tty, unsigned char ch) | ||
1102 | { | ||
1103 | struct mxser_port *info = tty->driver_data; | ||
1104 | unsigned long flags; | ||
1105 | |||
1106 | if (!info->xmit_buf) | ||
1107 | return; | ||
1108 | |||
1109 | if (info->xmit_cnt >= SERIAL_XMIT_SIZE - 1) | ||
1110 | return; | ||
1111 | |||
1112 | spin_lock_irqsave(&info->slock, flags); | ||
1113 | info->xmit_buf[info->xmit_head++] = ch; | ||
1114 | info->xmit_head &= SERIAL_XMIT_SIZE - 1; | ||
1115 | info->xmit_cnt++; | ||
1116 | spin_unlock_irqrestore(&info->slock, flags); | ||
1117 | if (!tty->stopped) { | ||
1118 | if (!tty->hw_stopped || | ||
1119 | (info->type == PORT_16550A) || | ||
1120 | info->board->chip_flag) { | ||
1121 | spin_lock_irqsave(&info->slock, flags); | ||
1122 | outb(info->IER & ~UART_IER_THRI, info->ioaddr + UART_IER); | ||
1123 | info->IER |= UART_IER_THRI; | ||
1124 | outb(info->IER, info->ioaddr + UART_IER); | ||
1125 | spin_unlock_irqrestore(&info->slock, flags); | ||
1126 | } | ||
1127 | } | ||
1128 | } | ||
1129 | |||
1130 | |||
1131 | static void mxser_flush_chars(struct tty_struct *tty) | ||
1132 | { | ||
1133 | struct mxser_port *info = tty->driver_data; | ||
1134 | unsigned long flags; | ||
1135 | |||
1136 | if (info->xmit_cnt <= 0 || | ||
1137 | tty->stopped || | ||
1138 | !info->xmit_buf || | ||
1139 | (tty->hw_stopped && | ||
1140 | (info->type != PORT_16550A) && | ||
1141 | (!info->board->chip_flag) | ||
1142 | )) | ||
1143 | return; | ||
1144 | |||
1145 | spin_lock_irqsave(&info->slock, flags); | ||
1146 | |||
1147 | outb(info->IER & ~UART_IER_THRI, info->ioaddr + UART_IER); | ||
1148 | info->IER |= UART_IER_THRI; | ||
1149 | outb(info->IER, info->ioaddr + UART_IER); | ||
1150 | |||
1151 | spin_unlock_irqrestore(&info->slock, flags); | ||
1152 | } | ||
1153 | |||
1154 | static int mxser_write_room(struct tty_struct *tty) | ||
1155 | { | ||
1156 | struct mxser_port *info = tty->driver_data; | ||
1157 | int ret; | ||
1158 | |||
1159 | ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1; | ||
1160 | if (ret < 0) | ||
1161 | ret = 0; | ||
1162 | return ret; | ||
1163 | } | ||
1164 | |||
1165 | static int mxser_chars_in_buffer(struct tty_struct *tty) | ||
1166 | { | ||
1167 | struct mxser_port *info = tty->driver_data; | ||
1168 | return info->xmit_cnt; | ||
1169 | } | ||
1170 | |||
1171 | static void mxser_flush_buffer(struct tty_struct *tty) | ||
1172 | { | ||
1173 | struct mxser_port *info = tty->driver_data; | ||
1174 | char fcr; | ||
1175 | unsigned long flags; | ||
1176 | |||
1177 | |||
1178 | spin_lock_irqsave(&info->slock, flags); | ||
1179 | info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; | ||
1180 | |||
1181 | fcr = inb(info->ioaddr + UART_FCR); | ||
1182 | outb((fcr | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT), | ||
1183 | info->ioaddr + UART_FCR); | ||
1184 | outb(fcr, info->ioaddr + UART_FCR); | ||
1185 | |||
1186 | spin_unlock_irqrestore(&info->slock, flags); | ||
1187 | |||
1188 | tty_wakeup(tty); | ||
1189 | } | ||
1190 | |||
1191 | /* | ||
1192 | * ------------------------------------------------------------ | ||
1193 | * friends of mxser_ioctl() | ||
1194 | * ------------------------------------------------------------ | ||
1195 | */ | ||
1196 | static int mxser_get_serial_info(struct mxser_port *info, | ||
1197 | struct serial_struct __user *retinfo) | ||
1198 | { | ||
1199 | struct serial_struct tmp; | ||
1200 | |||
1201 | if (!retinfo) | ||
1202 | return -EFAULT; | ||
1203 | memset(&tmp, 0, sizeof(tmp)); | ||
1204 | tmp.type = info->type; | ||
1205 | tmp.line = info->tty->index; | ||
1206 | tmp.port = info->ioaddr; | ||
1207 | tmp.irq = info->board->irq; | ||
1208 | tmp.flags = info->flags; | ||
1209 | tmp.baud_base = info->baud_base; | ||
1210 | tmp.close_delay = info->close_delay; | ||
1211 | tmp.closing_wait = info->closing_wait; | ||
1212 | tmp.custom_divisor = info->custom_divisor; | ||
1213 | tmp.hub6 = 0; | ||
1214 | if (copy_to_user(retinfo, &tmp, sizeof(*retinfo))) | ||
1215 | return -EFAULT; | ||
1216 | return 0; | ||
1217 | } | ||
1218 | |||
1219 | static int mxser_set_serial_info(struct mxser_port *info, | ||
1220 | struct serial_struct __user *new_info) | ||
1221 | { | ||
1222 | struct serial_struct new_serial; | ||
1223 | unsigned long sl_flags; | ||
1224 | unsigned int flags; | ||
1225 | int retval = 0; | ||
1226 | |||
1227 | if (!new_info || !info->ioaddr) | ||
1228 | return -EFAULT; | ||
1229 | if (copy_from_user(&new_serial, new_info, sizeof(new_serial))) | ||
1230 | return -EFAULT; | ||
1231 | |||
1232 | if ((new_serial.irq != info->board->irq) || | ||
1233 | (new_serial.port != info->ioaddr) || | ||
1234 | (new_serial.custom_divisor != info->custom_divisor) || | ||
1235 | (new_serial.baud_base != info->baud_base)) | ||
1236 | return -EPERM; | ||
1237 | |||
1238 | flags = info->flags & ASYNC_SPD_MASK; | ||
1239 | |||
1240 | if (!capable(CAP_SYS_ADMIN)) { | ||
1241 | if ((new_serial.baud_base != info->baud_base) || | ||
1242 | (new_serial.close_delay != info->close_delay) || | ||
1243 | ((new_serial.flags & ~ASYNC_USR_MASK) != (info->flags & ~ASYNC_USR_MASK))) | ||
1244 | return -EPERM; | ||
1245 | info->flags = ((info->flags & ~ASYNC_USR_MASK) | | ||
1246 | (new_serial.flags & ASYNC_USR_MASK)); | ||
1247 | } else { | ||
1248 | /* | ||
1249 | * OK, past this point, all the error checking has been done. | ||
1250 | * At this point, we start making changes..... | ||
1251 | */ | ||
1252 | info->flags = ((info->flags & ~ASYNC_FLAGS) | | ||
1253 | (new_serial.flags & ASYNC_FLAGS)); | ||
1254 | info->close_delay = new_serial.close_delay * HZ / 100; | ||
1255 | info->closing_wait = new_serial.closing_wait * HZ / 100; | ||
1256 | info->tty->low_latency = | ||
1257 | (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0; | ||
1258 | info->tty->low_latency = 0; | ||
1259 | } | ||
1260 | |||
1261 | info->type = new_serial.type; | ||
1262 | |||
1263 | process_txrx_fifo(info); | ||
1264 | |||
1265 | if (info->flags & ASYNC_INITIALIZED) { | ||
1266 | if (flags != (info->flags & ASYNC_SPD_MASK)) { | ||
1267 | spin_lock_irqsave(&info->slock, sl_flags); | ||
1268 | mxser_change_speed(info, NULL); | ||
1269 | spin_unlock_irqrestore(&info->slock, sl_flags); | ||
1270 | } | ||
1271 | } else | ||
1272 | retval = mxser_startup(info); | ||
1273 | |||
1274 | return retval; | ||
1275 | } | ||
1276 | |||
1277 | /* | ||
1278 | * mxser_get_lsr_info - get line status register info | ||
1279 | * | ||
1280 | * Purpose: Let user call ioctl() to get info when the UART physically | ||
1281 | * is emptied. On bus types like RS485, the transmitter must | ||
1282 | * release the bus after transmitting. This must be done when | ||
1283 | * the transmit shift register is empty, not be done when the | ||
1284 | * transmit holding register is empty. This functionality | ||
1285 | * allows an RS485 driver to be written in user space. | ||
1286 | */ | ||
1287 | static int mxser_get_lsr_info(struct mxser_port *info, | ||
1288 | unsigned int __user *value) | ||
1289 | { | ||
1290 | unsigned char status; | ||
1291 | unsigned int result; | ||
1292 | unsigned long flags; | ||
1293 | |||
1294 | spin_lock_irqsave(&info->slock, flags); | ||
1295 | status = inb(info->ioaddr + UART_LSR); | ||
1296 | spin_unlock_irqrestore(&info->slock, flags); | ||
1297 | result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0); | ||
1298 | return put_user(result, value); | ||
1299 | } | ||
1300 | |||
1301 | /* | ||
1302 | * This routine sends a break character out the serial port. | ||
1303 | */ | ||
1304 | static void mxser_send_break(struct mxser_port *info, int duration) | ||
1305 | { | ||
1306 | unsigned long flags; | ||
1307 | |||
1308 | if (!info->ioaddr) | ||
1309 | return; | ||
1310 | set_current_state(TASK_INTERRUPTIBLE); | ||
1311 | spin_lock_irqsave(&info->slock, flags); | ||
1312 | outb(inb(info->ioaddr + UART_LCR) | UART_LCR_SBC, | ||
1313 | info->ioaddr + UART_LCR); | ||
1314 | spin_unlock_irqrestore(&info->slock, flags); | ||
1315 | schedule_timeout(duration); | ||
1316 | spin_lock_irqsave(&info->slock, flags); | ||
1317 | outb(inb(info->ioaddr + UART_LCR) & ~UART_LCR_SBC, | ||
1318 | info->ioaddr + UART_LCR); | ||
1319 | spin_unlock_irqrestore(&info->slock, flags); | ||
1320 | } | ||
1321 | |||
1322 | static int mxser_tiocmget(struct tty_struct *tty, struct file *file) | ||
1323 | { | ||
1324 | struct mxser_port *info = tty->driver_data; | ||
1325 | unsigned char control, status; | ||
1326 | unsigned long flags; | ||
1327 | |||
1328 | |||
1329 | if (tty->index == MXSER_PORTS) | ||
1330 | return -ENOIOCTLCMD; | ||
1331 | if (test_bit(TTY_IO_ERROR, &tty->flags)) | ||
1332 | return -EIO; | ||
1333 | |||
1334 | control = info->MCR; | ||
1335 | |||
1336 | spin_lock_irqsave(&info->slock, flags); | ||
1337 | status = inb(info->ioaddr + UART_MSR); | ||
1338 | if (status & UART_MSR_ANY_DELTA) | ||
1339 | mxser_check_modem_status(info, status); | ||
1340 | spin_unlock_irqrestore(&info->slock, flags); | ||
1341 | return ((control & UART_MCR_RTS) ? TIOCM_RTS : 0) | | ||
1342 | ((control & UART_MCR_DTR) ? TIOCM_DTR : 0) | | ||
1343 | ((status & UART_MSR_DCD) ? TIOCM_CAR : 0) | | ||
1344 | ((status & UART_MSR_RI) ? TIOCM_RNG : 0) | | ||
1345 | ((status & UART_MSR_DSR) ? TIOCM_DSR : 0) | | ||
1346 | ((status & UART_MSR_CTS) ? TIOCM_CTS : 0); | ||
1347 | } | ||
1348 | |||
1349 | static int mxser_tiocmset(struct tty_struct *tty, struct file *file, | ||
1350 | unsigned int set, unsigned int clear) | ||
1351 | { | ||
1352 | struct mxser_port *info = tty->driver_data; | ||
1353 | unsigned long flags; | ||
1354 | |||
1355 | |||
1356 | if (tty->index == MXSER_PORTS) | ||
1357 | return -ENOIOCTLCMD; | ||
1358 | if (test_bit(TTY_IO_ERROR, &tty->flags)) | ||
1359 | return -EIO; | ||
1360 | |||
1361 | spin_lock_irqsave(&info->slock, flags); | ||
1362 | |||
1363 | if (set & TIOCM_RTS) | ||
1364 | info->MCR |= UART_MCR_RTS; | ||
1365 | if (set & TIOCM_DTR) | ||
1366 | info->MCR |= UART_MCR_DTR; | ||
1367 | |||
1368 | if (clear & TIOCM_RTS) | ||
1369 | info->MCR &= ~UART_MCR_RTS; | ||
1370 | if (clear & TIOCM_DTR) | ||
1371 | info->MCR &= ~UART_MCR_DTR; | ||
1372 | |||
1373 | outb(info->MCR, info->ioaddr + UART_MCR); | ||
1374 | spin_unlock_irqrestore(&info->slock, flags); | ||
1375 | return 0; | ||
1376 | } | ||
1377 | |||
1378 | static int __init mxser_program_mode(int port) | ||
1379 | { | ||
1380 | int id, i, j, n; | ||
1381 | |||
1382 | outb(0, port); | ||
1383 | outb(0, port); | ||
1384 | outb(0, port); | ||
1385 | (void)inb(port); | ||
1386 | (void)inb(port); | ||
1387 | outb(0, port); | ||
1388 | (void)inb(port); | ||
1389 | |||
1390 | id = inb(port + 1) & 0x1F; | ||
1391 | if ((id != C168_ASIC_ID) && | ||
1392 | (id != C104_ASIC_ID) && | ||
1393 | (id != C102_ASIC_ID) && | ||
1394 | (id != CI132_ASIC_ID) && | ||
1395 | (id != CI134_ASIC_ID) && | ||
1396 | (id != CI104J_ASIC_ID)) | ||
1397 | return -1; | ||
1398 | for (i = 0, j = 0; i < 4; i++) { | ||
1399 | n = inb(port + 2); | ||
1400 | if (n == 'M') { | ||
1401 | j = 1; | ||
1402 | } else if ((j == 1) && (n == 1)) { | ||
1403 | j = 2; | ||
1404 | break; | ||
1405 | } else | ||
1406 | j = 0; | ||
1407 | } | ||
1408 | if (j != 2) | ||
1409 | id = -2; | ||
1410 | return id; | ||
1411 | } | ||
1412 | |||
1413 | static void __init mxser_normal_mode(int port) | ||
1414 | { | ||
1415 | int i, n; | ||
1416 | |||
1417 | outb(0xA5, port + 1); | ||
1418 | outb(0x80, port + 3); | ||
1419 | outb(12, port + 0); /* 9600 bps */ | ||
1420 | outb(0, port + 1); | ||
1421 | outb(0x03, port + 3); /* 8 data bits */ | ||
1422 | outb(0x13, port + 4); /* loop back mode */ | ||
1423 | for (i = 0; i < 16; i++) { | ||
1424 | n = inb(port + 5); | ||
1425 | if ((n & 0x61) == 0x60) | ||
1426 | break; | ||
1427 | if ((n & 1) == 1) | ||
1428 | (void)inb(port); | ||
1429 | } | ||
1430 | outb(0x00, port + 4); | ||
1431 | } | ||
1432 | |||
1433 | #define CHIP_SK 0x01 /* Serial Data Clock in Eprom */ | ||
1434 | #define CHIP_DO 0x02 /* Serial Data Output in Eprom */ | ||
1435 | #define CHIP_CS 0x04 /* Serial Chip Select in Eprom */ | ||
1436 | #define CHIP_DI 0x08 /* Serial Data Input in Eprom */ | ||
1437 | #define EN_CCMD 0x000 /* Chip's command register */ | ||
1438 | #define EN0_RSARLO 0x008 /* Remote start address reg 0 */ | ||
1439 | #define EN0_RSARHI 0x009 /* Remote start address reg 1 */ | ||
1440 | #define EN0_RCNTLO 0x00A /* Remote byte count reg WR */ | ||
1441 | #define EN0_RCNTHI 0x00B /* Remote byte count reg WR */ | ||
1442 | #define EN0_DCFG 0x00E /* Data configuration reg WR */ | ||
1443 | #define EN0_PORT 0x010 /* Rcv missed frame error counter RD */ | ||
1444 | #define ENC_PAGE0 0x000 /* Select page 0 of chip registers */ | ||
1445 | #define ENC_PAGE3 0x0C0 /* Select page 3 of chip registers */ | ||
1446 | static int __init mxser_read_register(int port, unsigned short *regs) | ||
1447 | { | ||
1448 | int i, k, value, id; | ||
1449 | unsigned int j; | ||
1450 | |||
1451 | id = mxser_program_mode(port); | ||
1452 | if (id < 0) | ||
1453 | return id; | ||
1454 | for (i = 0; i < 14; i++) { | ||
1455 | k = (i & 0x3F) | 0x180; | ||
1456 | for (j = 0x100; j > 0; j >>= 1) { | ||
1457 | outb(CHIP_CS, port); | ||
1458 | if (k & j) { | ||
1459 | outb(CHIP_CS | CHIP_DO, port); | ||
1460 | outb(CHIP_CS | CHIP_DO | CHIP_SK, port); /* A? bit of read */ | ||
1461 | } else { | ||
1462 | outb(CHIP_CS, port); | ||
1463 | outb(CHIP_CS | CHIP_SK, port); /* A? bit of read */ | ||
1464 | } | ||
1465 | } | ||
1466 | (void)inb(port); | ||
1467 | value = 0; | ||
1468 | for (k = 0, j = 0x8000; k < 16; k++, j >>= 1) { | ||
1469 | outb(CHIP_CS, port); | ||
1470 | outb(CHIP_CS | CHIP_SK, port); | ||
1471 | if (inb(port) & CHIP_DI) | ||
1472 | value |= j; | ||
1473 | } | ||
1474 | regs[i] = value; | ||
1475 | outb(0, port); | ||
1476 | } | ||
1477 | mxser_normal_mode(port); | ||
1478 | return id; | ||
1479 | } | ||
1480 | |||
1481 | static int mxser_ioctl_special(unsigned int cmd, void __user *argp) | ||
1482 | { | ||
1483 | struct mxser_port *port; | ||
1484 | int result, status; | ||
1485 | unsigned int i, j; | ||
1486 | |||
1487 | switch (cmd) { | ||
1488 | case MOXA_GET_CONF: | ||
1489 | /* if (copy_to_user(argp, mxsercfg, | ||
1490 | sizeof(struct mxser_hwconf) * 4)) | ||
1491 | return -EFAULT; | ||
1492 | return 0;*/ | ||
1493 | return -ENXIO; | ||
1494 | case MOXA_GET_MAJOR: | ||
1495 | if (copy_to_user(argp, &ttymajor, sizeof(int))) | ||
1496 | return -EFAULT; | ||
1497 | return 0; | ||
1498 | |||
1499 | case MOXA_GET_CUMAJOR: | ||
1500 | if (copy_to_user(argp, &calloutmajor, sizeof(int))) | ||
1501 | return -EFAULT; | ||
1502 | return 0; | ||
1503 | |||
1504 | case MOXA_CHKPORTENABLE: | ||
1505 | result = 0; | ||
1506 | |||
1507 | for (i = 0; i < MXSER_BOARDS; i++) | ||
1508 | for (j = 0; j < MXSER_PORTS_PER_BOARD; j++) | ||
1509 | if (mxser_boards[i].ports[j].ioaddr) | ||
1510 | result |= (1 << i); | ||
1511 | |||
1512 | return put_user(result, (unsigned long __user *)argp); | ||
1513 | case MOXA_GETDATACOUNT: | ||
1514 | if (copy_to_user(argp, &mxvar_log, sizeof(mxvar_log))) | ||
1515 | return -EFAULT; | ||
1516 | return 0; | ||
1517 | case MOXA_GETMSTATUS: | ||
1518 | for (i = 0; i < MXSER_BOARDS; i++) | ||
1519 | for (j = 0; j < MXSER_PORTS_PER_BOARD; j++) { | ||
1520 | port = &mxser_boards[i].ports[j]; | ||
1521 | |||
1522 | GMStatus[i].ri = 0; | ||
1523 | if (!port->ioaddr) { | ||
1524 | GMStatus[i].dcd = 0; | ||
1525 | GMStatus[i].dsr = 0; | ||
1526 | GMStatus[i].cts = 0; | ||
1527 | continue; | ||
1528 | } | ||
1529 | |||
1530 | if (!port->tty || !port->tty->termios) | ||
1531 | GMStatus[i].cflag = | ||
1532 | port->normal_termios.c_cflag; | ||
1533 | else | ||
1534 | GMStatus[i].cflag = | ||
1535 | port->tty->termios->c_cflag; | ||
1536 | |||
1537 | status = inb(port->ioaddr + UART_MSR); | ||
1538 | if (status & 0x80 /*UART_MSR_DCD */ ) | ||
1539 | GMStatus[i].dcd = 1; | ||
1540 | else | ||
1541 | GMStatus[i].dcd = 0; | ||
1542 | |||
1543 | if (status & 0x20 /*UART_MSR_DSR */ ) | ||
1544 | GMStatus[i].dsr = 1; | ||
1545 | else | ||
1546 | GMStatus[i].dsr = 0; | ||
1547 | |||
1548 | |||
1549 | if (status & 0x10 /*UART_MSR_CTS */ ) | ||
1550 | GMStatus[i].cts = 1; | ||
1551 | else | ||
1552 | GMStatus[i].cts = 0; | ||
1553 | } | ||
1554 | if (copy_to_user(argp, GMStatus, | ||
1555 | sizeof(struct mxser_mstatus) * MXSER_PORTS)) | ||
1556 | return -EFAULT; | ||
1557 | return 0; | ||
1558 | case MOXA_ASPP_MON_EXT: { | ||
1559 | int p, shiftbit; | ||
1560 | unsigned long opmode; | ||
1561 | unsigned cflag, iflag; | ||
1562 | |||
1563 | for (i = 0; i < MXSER_BOARDS; i++) | ||
1564 | for (j = 0; j < MXSER_PORTS_PER_BOARD; j++) { | ||
1565 | port = &mxser_boards[i].ports[j]; | ||
1566 | if (!port->ioaddr) | ||
1567 | continue; | ||
1568 | |||
1569 | status = mxser_get_msr(port->ioaddr, 0, i); | ||
1570 | |||
1571 | if (status & UART_MSR_TERI) | ||
1572 | port->icount.rng++; | ||
1573 | if (status & UART_MSR_DDSR) | ||
1574 | port->icount.dsr++; | ||
1575 | if (status & UART_MSR_DDCD) | ||
1576 | port->icount.dcd++; | ||
1577 | if (status & UART_MSR_DCTS) | ||
1578 | port->icount.cts++; | ||
1579 | |||
1580 | port->mon_data.modem_status = status; | ||
1581 | mon_data_ext.rx_cnt[i] = port->mon_data.rxcnt; | ||
1582 | mon_data_ext.tx_cnt[i] = port->mon_data.txcnt; | ||
1583 | mon_data_ext.up_rxcnt[i] = | ||
1584 | port->mon_data.up_rxcnt; | ||
1585 | mon_data_ext.up_txcnt[i] = | ||
1586 | port->mon_data.up_txcnt; | ||
1587 | mon_data_ext.modem_status[i] = | ||
1588 | port->mon_data.modem_status; | ||
1589 | mon_data_ext.baudrate[i] = port->realbaud; | ||
1590 | |||
1591 | if (!port->tty || !port->tty->termios) { | ||
1592 | cflag = port->normal_termios.c_cflag; | ||
1593 | iflag = port->normal_termios.c_iflag; | ||
1594 | } else { | ||
1595 | cflag = port->tty->termios->c_cflag; | ||
1596 | iflag = port->tty->termios->c_iflag; | ||
1597 | } | ||
1598 | |||
1599 | mon_data_ext.databits[i] = cflag & CSIZE; | ||
1600 | |||
1601 | mon_data_ext.stopbits[i] = cflag & CSTOPB; | ||
1602 | |||
1603 | mon_data_ext.parity[i] = | ||
1604 | cflag & (PARENB | PARODD | CMSPAR); | ||
1605 | |||
1606 | mon_data_ext.flowctrl[i] = 0x00; | ||
1607 | |||
1608 | if (cflag & CRTSCTS) | ||
1609 | mon_data_ext.flowctrl[i] |= 0x03; | ||
1610 | |||
1611 | if (iflag & (IXON | IXOFF)) | ||
1612 | mon_data_ext.flowctrl[i] |= 0x0C; | ||
1613 | |||
1614 | if (port->type == PORT_16550A) | ||
1615 | mon_data_ext.fifo[i] = 1; | ||
1616 | else | ||
1617 | mon_data_ext.fifo[i] = 0; | ||
1618 | |||
1619 | p = i % 4; | ||
1620 | shiftbit = p * 2; | ||
1621 | opmode = inb(port->opmode_ioaddr) >> shiftbit; | ||
1622 | opmode &= OP_MODE_MASK; | ||
1623 | |||
1624 | mon_data_ext.iftype[i] = opmode; | ||
1625 | |||
1626 | } | ||
1627 | if (copy_to_user(argp, &mon_data_ext, | ||
1628 | sizeof(mon_data_ext))) | ||
1629 | return -EFAULT; | ||
1630 | |||
1631 | return 0; | ||
1632 | |||
1633 | } default: | ||
1634 | return -ENOIOCTLCMD; | ||
1635 | } | ||
1636 | return 0; | ||
1637 | } | ||
1638 | |||
1639 | static int mxser_ioctl(struct tty_struct *tty, struct file *file, | ||
1640 | unsigned int cmd, unsigned long arg) | ||
1641 | { | ||
1642 | struct mxser_port *info = tty->driver_data; | ||
1643 | struct async_icount cprev, cnow; /* kernel counter temps */ | ||
1644 | struct serial_icounter_struct __user *p_cuser; | ||
1645 | unsigned long templ; | ||
1646 | unsigned long flags; | ||
1647 | unsigned int i; | ||
1648 | void __user *argp = (void __user *)arg; | ||
1649 | int retval; | ||
1650 | |||
1651 | if (tty->index == MXSER_PORTS) | ||
1652 | return mxser_ioctl_special(cmd, argp); | ||
1653 | |||
1654 | if (cmd == MOXA_SET_OP_MODE || cmd == MOXA_GET_OP_MODE) { | ||
1655 | int p; | ||
1656 | unsigned long opmode; | ||
1657 | static unsigned char ModeMask[] = { 0xfc, 0xf3, 0xcf, 0x3f }; | ||
1658 | int shiftbit; | ||
1659 | unsigned char val, mask; | ||
1660 | |||
1661 | p = tty->index % 4; | ||
1662 | if (cmd == MOXA_SET_OP_MODE) { | ||
1663 | if (get_user(opmode, (int __user *) argp)) | ||
1664 | return -EFAULT; | ||
1665 | if (opmode != RS232_MODE && | ||
1666 | opmode != RS485_2WIRE_MODE && | ||
1667 | opmode != RS422_MODE && | ||
1668 | opmode != RS485_4WIRE_MODE) | ||
1669 | return -EFAULT; | ||
1670 | mask = ModeMask[p]; | ||
1671 | shiftbit = p * 2; | ||
1672 | val = inb(info->opmode_ioaddr); | ||
1673 | val &= mask; | ||
1674 | val |= (opmode << shiftbit); | ||
1675 | outb(val, info->opmode_ioaddr); | ||
1676 | } else { | ||
1677 | shiftbit = p * 2; | ||
1678 | opmode = inb(info->opmode_ioaddr) >> shiftbit; | ||
1679 | opmode &= OP_MODE_MASK; | ||
1680 | if (copy_to_user(argp, &opmode, sizeof(int))) | ||
1681 | return -EFAULT; | ||
1682 | } | ||
1683 | return 0; | ||
1684 | } | ||
1685 | |||
1686 | if (cmd == MOXA_SET_SPECIAL_BAUD_RATE) { | ||
1687 | int speed; | ||
1688 | |||
1689 | if (get_user(speed, (int __user *)argp)) | ||
1690 | return -EFAULT; | ||
1691 | if (speed <= 0 || speed > info->max_baud) | ||
1692 | return -EFAULT; | ||
1693 | if (!info->tty || !info->tty->termios || !info->ioaddr) | ||
1694 | return 0; | ||
1695 | info->tty->termios->c_cflag &= ~(CBAUD | CBAUDEX); | ||
1696 | for (i = 0; i < BAUD_TABLE_NO; i++) | ||
1697 | if (speed == mxvar_baud_table[i]) | ||
1698 | break; | ||
1699 | if (i == BAUD_TABLE_NO) { | ||
1700 | info->tty->termios->c_cflag |= B_SPEC; | ||
1701 | } else if (speed != 0) | ||
1702 | info->tty->termios->c_cflag |= mxvar_baud_table1[i]; | ||
1703 | |||
1704 | info->speed = speed; | ||
1705 | spin_lock_irqsave(&info->slock, flags); | ||
1706 | mxser_change_speed(info, NULL); | ||
1707 | spin_unlock_irqrestore(&info->slock, flags); | ||
1708 | |||
1709 | return 0; | ||
1710 | } else if (cmd == MOXA_GET_SPECIAL_BAUD_RATE) { | ||
1711 | if (copy_to_user(argp, &info->speed, sizeof(int))) | ||
1712 | return -EFAULT; | ||
1713 | return 0; | ||
1714 | } | ||
1715 | |||
1716 | if (cmd != TIOCGSERIAL && cmd != TIOCMIWAIT && cmd != TIOCGICOUNT && | ||
1717 | test_bit(TTY_IO_ERROR, &tty->flags)) | ||
1718 | return -EIO; | ||
1719 | |||
1720 | switch (cmd) { | ||
1721 | case TCSBRK: /* SVID version: non-zero arg --> no break */ | ||
1722 | retval = tty_check_change(tty); | ||
1723 | if (retval) | ||
1724 | return retval; | ||
1725 | tty_wait_until_sent(tty, 0); | ||
1726 | if (!arg) | ||
1727 | mxser_send_break(info, HZ / 4); /* 1/4 second */ | ||
1728 | return 0; | ||
1729 | case TCSBRKP: /* support for POSIX tcsendbreak() */ | ||
1730 | retval = tty_check_change(tty); | ||
1731 | if (retval) | ||
1732 | return retval; | ||
1733 | tty_wait_until_sent(tty, 0); | ||
1734 | mxser_send_break(info, arg ? arg * (HZ / 10) : HZ / 4); | ||
1735 | return 0; | ||
1736 | case TIOCGSOFTCAR: | ||
1737 | return put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long __user *)argp); | ||
1738 | case TIOCSSOFTCAR: | ||
1739 | if (get_user(templ, (unsigned long __user *) argp)) | ||
1740 | return -EFAULT; | ||
1741 | arg = templ; | ||
1742 | tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) | (arg ? CLOCAL : 0)); | ||
1743 | return 0; | ||
1744 | case TIOCGSERIAL: | ||
1745 | return mxser_get_serial_info(info, argp); | ||
1746 | case TIOCSSERIAL: | ||
1747 | return mxser_set_serial_info(info, argp); | ||
1748 | case TIOCSERGETLSR: /* Get line status register */ | ||
1749 | return mxser_get_lsr_info(info, argp); | ||
1750 | /* | ||
1751 | * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change | ||
1752 | * - mask passed in arg for lines of interest | ||
1753 | * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking) | ||
1754 | * Caller should use TIOCGICOUNT to see which one it was | ||
1755 | */ | ||
1756 | case TIOCMIWAIT: | ||
1757 | spin_lock_irqsave(&info->slock, flags); | ||
1758 | cnow = info->icount; /* note the counters on entry */ | ||
1759 | spin_unlock_irqrestore(&info->slock, flags); | ||
1760 | |||
1761 | wait_event_interruptible(info->delta_msr_wait, ({ | ||
1762 | cprev = cnow; | ||
1763 | spin_lock_irqsave(&info->slock, flags); | ||
1764 | cnow = info->icount; /* atomic copy */ | ||
1765 | spin_unlock_irqrestore(&info->slock, flags); | ||
1766 | |||
1767 | ((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || | ||
1768 | ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || | ||
1769 | ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || | ||
1770 | ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)); | ||
1771 | })); | ||
1772 | break; | ||
1773 | /* | ||
1774 | * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) | ||
1775 | * Return: write counters to the user passed counter struct | ||
1776 | * NB: both 1->0 and 0->1 transitions are counted except for | ||
1777 | * RI where only 0->1 is counted. | ||
1778 | */ | ||
1779 | case TIOCGICOUNT: | ||
1780 | spin_lock_irqsave(&info->slock, flags); | ||
1781 | cnow = info->icount; | ||
1782 | spin_unlock_irqrestore(&info->slock, flags); | ||
1783 | p_cuser = argp; | ||
1784 | if (put_user(cnow.frame, &p_cuser->frame)) | ||
1785 | return -EFAULT; | ||
1786 | if (put_user(cnow.brk, &p_cuser->brk)) | ||
1787 | return -EFAULT; | ||
1788 | if (put_user(cnow.overrun, &p_cuser->overrun)) | ||
1789 | return -EFAULT; | ||
1790 | if (put_user(cnow.buf_overrun, &p_cuser->buf_overrun)) | ||
1791 | return -EFAULT; | ||
1792 | if (put_user(cnow.parity, &p_cuser->parity)) | ||
1793 | return -EFAULT; | ||
1794 | if (put_user(cnow.rx, &p_cuser->rx)) | ||
1795 | return -EFAULT; | ||
1796 | if (put_user(cnow.tx, &p_cuser->tx)) | ||
1797 | return -EFAULT; | ||
1798 | put_user(cnow.cts, &p_cuser->cts); | ||
1799 | put_user(cnow.dsr, &p_cuser->dsr); | ||
1800 | put_user(cnow.rng, &p_cuser->rng); | ||
1801 | put_user(cnow.dcd, &p_cuser->dcd); | ||
1802 | return 0; | ||
1803 | case MOXA_HighSpeedOn: | ||
1804 | return put_user(info->baud_base != 115200 ? 1 : 0, (int __user *)argp); | ||
1805 | case MOXA_SDS_RSTICOUNTER: | ||
1806 | info->mon_data.rxcnt = 0; | ||
1807 | info->mon_data.txcnt = 0; | ||
1808 | return 0; | ||
1809 | case MOXA_ASPP_SETBAUD:{ | ||
1810 | long baud; | ||
1811 | if (get_user(baud, (long __user *)argp)) | ||
1812 | return -EFAULT; | ||
1813 | spin_lock_irqsave(&info->slock, flags); | ||
1814 | mxser_set_baud(info, baud); | ||
1815 | spin_unlock_irqrestore(&info->slock, flags); | ||
1816 | return 0; | ||
1817 | } | ||
1818 | case MOXA_ASPP_GETBAUD: | ||
1819 | if (copy_to_user(argp, &info->realbaud, sizeof(long))) | ||
1820 | return -EFAULT; | ||
1821 | |||
1822 | return 0; | ||
1823 | |||
1824 | case MOXA_ASPP_OQUEUE:{ | ||
1825 | int len, lsr; | ||
1826 | |||
1827 | len = mxser_chars_in_buffer(tty); | ||
1828 | |||
1829 | lsr = inb(info->ioaddr + UART_LSR) & UART_LSR_TEMT; | ||
1830 | |||
1831 | len += (lsr ? 0 : 1); | ||
1832 | |||
1833 | if (copy_to_user(argp, &len, sizeof(int))) | ||
1834 | return -EFAULT; | ||
1835 | |||
1836 | return 0; | ||
1837 | } | ||
1838 | case MOXA_ASPP_MON: { | ||
1839 | int mcr, status; | ||
1840 | |||
1841 | status = mxser_get_msr(info->ioaddr, 1, tty->index); | ||
1842 | mxser_check_modem_status(info, status); | ||
1843 | |||
1844 | mcr = inb(info->ioaddr + UART_MCR); | ||
1845 | if (mcr & MOXA_MUST_MCR_XON_FLAG) | ||
1846 | info->mon_data.hold_reason &= ~NPPI_NOTIFY_XOFFHOLD; | ||
1847 | else | ||
1848 | info->mon_data.hold_reason |= NPPI_NOTIFY_XOFFHOLD; | ||
1849 | |||
1850 | if (mcr & MOXA_MUST_MCR_TX_XON) | ||
1851 | info->mon_data.hold_reason &= ~NPPI_NOTIFY_XOFFXENT; | ||
1852 | else | ||
1853 | info->mon_data.hold_reason |= NPPI_NOTIFY_XOFFXENT; | ||
1854 | |||
1855 | if (info->tty->hw_stopped) | ||
1856 | info->mon_data.hold_reason |= NPPI_NOTIFY_CTSHOLD; | ||
1857 | else | ||
1858 | info->mon_data.hold_reason &= ~NPPI_NOTIFY_CTSHOLD; | ||
1859 | |||
1860 | if (copy_to_user(argp, &info->mon_data, | ||
1861 | sizeof(struct mxser_mon))) | ||
1862 | return -EFAULT; | ||
1863 | |||
1864 | return 0; | ||
1865 | } | ||
1866 | case MOXA_ASPP_LSTATUS: { | ||
1867 | if (copy_to_user(argp, &info->err_shadow, | ||
1868 | sizeof(unsigned char))) | ||
1869 | return -EFAULT; | ||
1870 | |||
1871 | info->err_shadow = 0; | ||
1872 | return 0; | ||
1873 | } | ||
1874 | case MOXA_SET_BAUD_METHOD: { | ||
1875 | int method; | ||
1876 | |||
1877 | if (get_user(method, (int __user *)argp)) | ||
1878 | return -EFAULT; | ||
1879 | mxser_set_baud_method[tty->index] = method; | ||
1880 | if (copy_to_user(argp, &method, sizeof(int))) | ||
1881 | return -EFAULT; | ||
1882 | |||
1883 | return 0; | ||
1884 | } | ||
1885 | default: | ||
1886 | return -ENOIOCTLCMD; | ||
1887 | } | ||
1888 | return 0; | ||
1889 | } | ||
1890 | |||
1891 | static void mxser_stoprx(struct tty_struct *tty) | ||
1892 | { | ||
1893 | struct mxser_port *info = tty->driver_data; | ||
1894 | |||
1895 | info->ldisc_stop_rx = 1; | ||
1896 | if (I_IXOFF(tty)) { | ||
1897 | if (info->board->chip_flag) { | ||
1898 | info->IER &= ~MOXA_MUST_RECV_ISR; | ||
1899 | outb(info->IER, info->ioaddr + UART_IER); | ||
1900 | } else { | ||
1901 | info->x_char = STOP_CHAR(tty); | ||
1902 | outb(0, info->ioaddr + UART_IER); | ||
1903 | info->IER |= UART_IER_THRI; | ||
1904 | outb(info->IER, info->ioaddr + UART_IER); | ||
1905 | } | ||
1906 | } | ||
1907 | |||
1908 | if (info->tty->termios->c_cflag & CRTSCTS) { | ||
1909 | info->MCR &= ~UART_MCR_RTS; | ||
1910 | outb(info->MCR, info->ioaddr + UART_MCR); | ||
1911 | } | ||
1912 | } | ||
1913 | |||
1914 | /* | ||
1915 | * This routine is called by the upper-layer tty layer to signal that | ||
1916 | * incoming characters should be throttled. | ||
1917 | */ | ||
1918 | static void mxser_throttle(struct tty_struct *tty) | ||
1919 | { | ||
1920 | mxser_stoprx(tty); | ||
1921 | } | ||
1922 | |||
1923 | static void mxser_unthrottle(struct tty_struct *tty) | ||
1924 | { | ||
1925 | struct mxser_port *info = tty->driver_data; | ||
1926 | |||
1927 | /* startrx */ | ||
1928 | info->ldisc_stop_rx = 0; | ||
1929 | if (I_IXOFF(tty)) { | ||
1930 | if (info->x_char) | ||
1931 | info->x_char = 0; | ||
1932 | else { | ||
1933 | if (info->board->chip_flag) { | ||
1934 | info->IER |= MOXA_MUST_RECV_ISR; | ||
1935 | outb(info->IER, info->ioaddr + UART_IER); | ||
1936 | } else { | ||
1937 | info->x_char = START_CHAR(tty); | ||
1938 | outb(0, info->ioaddr + UART_IER); | ||
1939 | info->IER |= UART_IER_THRI; | ||
1940 | outb(info->IER, info->ioaddr + UART_IER); | ||
1941 | } | ||
1942 | } | ||
1943 | } | ||
1944 | |||
1945 | if (info->tty->termios->c_cflag & CRTSCTS) { | ||
1946 | info->MCR |= UART_MCR_RTS; | ||
1947 | outb(info->MCR, info->ioaddr + UART_MCR); | ||
1948 | } | ||
1949 | } | ||
1950 | |||
1951 | /* | ||
1952 | * mxser_stop() and mxser_start() | ||
1953 | * | ||
1954 | * This routines are called before setting or resetting tty->stopped. | ||
1955 | * They enable or disable transmitter interrupts, as necessary. | ||
1956 | */ | ||
1957 | static void mxser_stop(struct tty_struct *tty) | ||
1958 | { | ||
1959 | struct mxser_port *info = tty->driver_data; | ||
1960 | unsigned long flags; | ||
1961 | |||
1962 | spin_lock_irqsave(&info->slock, flags); | ||
1963 | if (info->IER & UART_IER_THRI) { | ||
1964 | info->IER &= ~UART_IER_THRI; | ||
1965 | outb(info->IER, info->ioaddr + UART_IER); | ||
1966 | } | ||
1967 | spin_unlock_irqrestore(&info->slock, flags); | ||
1968 | } | ||
1969 | |||
1970 | static void mxser_start(struct tty_struct *tty) | ||
1971 | { | ||
1972 | struct mxser_port *info = tty->driver_data; | ||
1973 | unsigned long flags; | ||
1974 | |||
1975 | spin_lock_irqsave(&info->slock, flags); | ||
1976 | if (info->xmit_cnt && info->xmit_buf) { | ||
1977 | outb(info->IER & ~UART_IER_THRI, info->ioaddr + UART_IER); | ||
1978 | info->IER |= UART_IER_THRI; | ||
1979 | outb(info->IER, info->ioaddr + UART_IER); | ||
1980 | } | ||
1981 | spin_unlock_irqrestore(&info->slock, flags); | ||
1982 | } | ||
1983 | |||
1984 | static void mxser_set_termios(struct tty_struct *tty, struct ktermios *old_termios) | ||
1985 | { | ||
1986 | struct mxser_port *info = tty->driver_data; | ||
1987 | unsigned long flags; | ||
1988 | |||
1989 | spin_lock_irqsave(&info->slock, flags); | ||
1990 | mxser_change_speed(info, old_termios); | ||
1991 | spin_unlock_irqrestore(&info->slock, flags); | ||
1992 | |||
1993 | if ((old_termios->c_cflag & CRTSCTS) && | ||
1994 | !(tty->termios->c_cflag & CRTSCTS)) { | ||
1995 | tty->hw_stopped = 0; | ||
1996 | mxser_start(tty); | ||
1997 | } | ||
1998 | |||
1999 | /* Handle sw stopped */ | ||
2000 | if ((old_termios->c_iflag & IXON) && | ||
2001 | !(tty->termios->c_iflag & IXON)) { | ||
2002 | tty->stopped = 0; | ||
2003 | |||
2004 | if (info->board->chip_flag) { | ||
2005 | spin_lock_irqsave(&info->slock, flags); | ||
2006 | DISABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(info->ioaddr); | ||
2007 | spin_unlock_irqrestore(&info->slock, flags); | ||
2008 | } | ||
2009 | |||
2010 | mxser_start(tty); | ||
2011 | } | ||
2012 | } | ||
2013 | |||
2014 | /* | ||
2015 | * mxser_wait_until_sent() --- wait until the transmitter is empty | ||
2016 | */ | ||
2017 | static void mxser_wait_until_sent(struct tty_struct *tty, int timeout) | ||
2018 | { | ||
2019 | struct mxser_port *info = tty->driver_data; | ||
2020 | unsigned long orig_jiffies, char_time; | ||
2021 | int lsr; | ||
2022 | |||
2023 | if (info->type == PORT_UNKNOWN) | ||
2024 | return; | ||
2025 | |||
2026 | if (info->xmit_fifo_size == 0) | ||
2027 | return; /* Just in case.... */ | ||
2028 | |||
2029 | orig_jiffies = jiffies; | ||
2030 | /* | ||
2031 | * Set the check interval to be 1/5 of the estimated time to | ||
2032 | * send a single character, and make it at least 1. The check | ||
2033 | * interval should also be less than the timeout. | ||
2034 | * | ||
2035 | * Note: we have to use pretty tight timings here to satisfy | ||
2036 | * the NIST-PCTS. | ||
2037 | */ | ||
2038 | char_time = (info->timeout - HZ / 50) / info->xmit_fifo_size; | ||
2039 | char_time = char_time / 5; | ||
2040 | if (char_time == 0) | ||
2041 | char_time = 1; | ||
2042 | if (timeout && timeout < char_time) | ||
2043 | char_time = timeout; | ||
2044 | /* | ||
2045 | * If the transmitter hasn't cleared in twice the approximate | ||
2046 | * amount of time to send the entire FIFO, it probably won't | ||
2047 | * ever clear. This assumes the UART isn't doing flow | ||
2048 | * control, which is currently the case. Hence, if it ever | ||
2049 | * takes longer than info->timeout, this is probably due to a | ||
2050 | * UART bug of some kind. So, we clamp the timeout parameter at | ||
2051 | * 2*info->timeout. | ||
2052 | */ | ||
2053 | if (!timeout || timeout > 2 * info->timeout) | ||
2054 | timeout = 2 * info->timeout; | ||
2055 | #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT | ||
2056 | printk(KERN_DEBUG "In rs_wait_until_sent(%d) check=%lu...", | ||
2057 | timeout, char_time); | ||
2058 | printk("jiff=%lu...", jiffies); | ||
2059 | #endif | ||
2060 | while (!((lsr = inb(info->ioaddr + UART_LSR)) & UART_LSR_TEMT)) { | ||
2061 | #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT | ||
2062 | printk("lsr = %d (jiff=%lu)...", lsr, jiffies); | ||
2063 | #endif | ||
2064 | schedule_timeout_interruptible(char_time); | ||
2065 | if (signal_pending(current)) | ||
2066 | break; | ||
2067 | if (timeout && time_after(jiffies, orig_jiffies + timeout)) | ||
2068 | break; | ||
2069 | } | ||
2070 | set_current_state(TASK_RUNNING); | ||
2071 | |||
2072 | #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT | ||
2073 | printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies); | ||
2074 | #endif | ||
2075 | } | ||
2076 | |||
2077 | /* | ||
2078 | * This routine is called by tty_hangup() when a hangup is signaled. | ||
2079 | */ | ||
2080 | static void mxser_hangup(struct tty_struct *tty) | ||
2081 | { | ||
2082 | struct mxser_port *info = tty->driver_data; | ||
2083 | |||
2084 | mxser_flush_buffer(tty); | ||
2085 | mxser_shutdown(info); | ||
2086 | info->event = 0; | ||
2087 | info->count = 0; | ||
2088 | info->flags &= ~ASYNC_NORMAL_ACTIVE; | ||
2089 | info->tty = NULL; | ||
2090 | wake_up_interruptible(&info->open_wait); | ||
2091 | } | ||
2092 | |||
2093 | /* | ||
2094 | * mxser_rs_break() --- routine which turns the break handling on or off | ||
2095 | */ | ||
2096 | static void mxser_rs_break(struct tty_struct *tty, int break_state) | ||
2097 | { | ||
2098 | struct mxser_port *info = tty->driver_data; | ||
2099 | unsigned long flags; | ||
2100 | |||
2101 | spin_lock_irqsave(&info->slock, flags); | ||
2102 | if (break_state == -1) | ||
2103 | outb(inb(info->ioaddr + UART_LCR) | UART_LCR_SBC, | ||
2104 | info->ioaddr + UART_LCR); | ||
2105 | else | ||
2106 | outb(inb(info->ioaddr + UART_LCR) & ~UART_LCR_SBC, | ||
2107 | info->ioaddr + UART_LCR); | ||
2108 | spin_unlock_irqrestore(&info->slock, flags); | ||
2109 | } | ||
2110 | |||
2111 | static void mxser_receive_chars(struct mxser_port *port, int *status) | ||
2112 | { | ||
2113 | struct tty_struct *tty = port->tty; | ||
2114 | unsigned char ch, gdl; | ||
2115 | int ignored = 0; | ||
2116 | int cnt = 0; | ||
2117 | int recv_room; | ||
2118 | int max = 256; | ||
2119 | |||
2120 | recv_room = tty->receive_room; | ||
2121 | if ((recv_room == 0) && (!port->ldisc_stop_rx)) | ||
2122 | mxser_stoprx(tty); | ||
2123 | |||
2124 | if (port->board->chip_flag != MOXA_OTHER_UART) { | ||
2125 | |||
2126 | if (*status & UART_LSR_SPECIAL) | ||
2127 | goto intr_old; | ||
2128 | if (port->board->chip_flag == MOXA_MUST_MU860_HWID && | ||
2129 | (*status & MOXA_MUST_LSR_RERR)) | ||
2130 | goto intr_old; | ||
2131 | if (*status & MOXA_MUST_LSR_RERR) | ||
2132 | goto intr_old; | ||
2133 | |||
2134 | gdl = inb(port->ioaddr + MOXA_MUST_GDL_REGISTER); | ||
2135 | |||
2136 | if (port->board->chip_flag == MOXA_MUST_MU150_HWID) | ||
2137 | gdl &= MOXA_MUST_GDL_MASK; | ||
2138 | if (gdl >= recv_room) { | ||
2139 | if (!port->ldisc_stop_rx) | ||
2140 | mxser_stoprx(tty); | ||
2141 | } | ||
2142 | while (gdl--) { | ||
2143 | ch = inb(port->ioaddr + UART_RX); | ||
2144 | tty_insert_flip_char(tty, ch, 0); | ||
2145 | cnt++; | ||
2146 | } | ||
2147 | goto end_intr; | ||
2148 | } | ||
2149 | intr_old: | ||
2150 | |||
2151 | do { | ||
2152 | if (max-- < 0) | ||
2153 | break; | ||
2154 | |||
2155 | ch = inb(port->ioaddr + UART_RX); | ||
2156 | if (port->board->chip_flag && (*status & UART_LSR_OE)) | ||
2157 | outb(0x23, port->ioaddr + UART_FCR); | ||
2158 | *status &= port->read_status_mask; | ||
2159 | if (*status & port->ignore_status_mask) { | ||
2160 | if (++ignored > 100) | ||
2161 | break; | ||
2162 | } else { | ||
2163 | char flag = 0; | ||
2164 | if (*status & UART_LSR_SPECIAL) { | ||
2165 | if (*status & UART_LSR_BI) { | ||
2166 | flag = TTY_BREAK; | ||
2167 | port->icount.brk++; | ||
2168 | |||
2169 | if (port->flags & ASYNC_SAK) | ||
2170 | do_SAK(tty); | ||
2171 | } else if (*status & UART_LSR_PE) { | ||
2172 | flag = TTY_PARITY; | ||
2173 | port->icount.parity++; | ||
2174 | } else if (*status & UART_LSR_FE) { | ||
2175 | flag = TTY_FRAME; | ||
2176 | port->icount.frame++; | ||
2177 | } else if (*status & UART_LSR_OE) { | ||
2178 | flag = TTY_OVERRUN; | ||
2179 | port->icount.overrun++; | ||
2180 | } else | ||
2181 | flag = TTY_BREAK; | ||
2182 | } | ||
2183 | tty_insert_flip_char(tty, ch, flag); | ||
2184 | cnt++; | ||
2185 | if (cnt >= recv_room) { | ||
2186 | if (!port->ldisc_stop_rx) | ||
2187 | mxser_stoprx(tty); | ||
2188 | break; | ||
2189 | } | ||
2190 | |||
2191 | } | ||
2192 | |||
2193 | if (port->board->chip_flag) | ||
2194 | break; | ||
2195 | |||
2196 | *status = inb(port->ioaddr + UART_LSR); | ||
2197 | } while (*status & UART_LSR_DR); | ||
2198 | |||
2199 | end_intr: | ||
2200 | mxvar_log.rxcnt[port->tty->index] += cnt; | ||
2201 | port->mon_data.rxcnt += cnt; | ||
2202 | port->mon_data.up_rxcnt += cnt; | ||
2203 | |||
2204 | /* | ||
2205 | * We are called from an interrupt context with &port->slock | ||
2206 | * being held. Drop it temporarily in order to prevent | ||
2207 | * recursive locking. | ||
2208 | */ | ||
2209 | spin_unlock(&port->slock); | ||
2210 | tty_flip_buffer_push(tty); | ||
2211 | spin_lock(&port->slock); | ||
2212 | } | ||
2213 | |||
2214 | static void mxser_transmit_chars(struct mxser_port *port) | ||
2215 | { | ||
2216 | int count, cnt; | ||
2217 | |||
2218 | if (port->x_char) { | ||
2219 | outb(port->x_char, port->ioaddr + UART_TX); | ||
2220 | port->x_char = 0; | ||
2221 | mxvar_log.txcnt[port->tty->index]++; | ||
2222 | port->mon_data.txcnt++; | ||
2223 | port->mon_data.up_txcnt++; | ||
2224 | port->icount.tx++; | ||
2225 | return; | ||
2226 | } | ||
2227 | |||
2228 | if (port->xmit_buf == 0) | ||
2229 | return; | ||
2230 | |||
2231 | if ((port->xmit_cnt <= 0) || port->tty->stopped || | ||
2232 | (port->tty->hw_stopped && | ||
2233 | (port->type != PORT_16550A) && | ||
2234 | (!port->board->chip_flag))) { | ||
2235 | port->IER &= ~UART_IER_THRI; | ||
2236 | outb(port->IER, port->ioaddr + UART_IER); | ||
2237 | return; | ||
2238 | } | ||
2239 | |||
2240 | cnt = port->xmit_cnt; | ||
2241 | count = port->xmit_fifo_size; | ||
2242 | do { | ||
2243 | outb(port->xmit_buf[port->xmit_tail++], | ||
2244 | port->ioaddr + UART_TX); | ||
2245 | port->xmit_tail = port->xmit_tail & (SERIAL_XMIT_SIZE - 1); | ||
2246 | if (--port->xmit_cnt <= 0) | ||
2247 | break; | ||
2248 | } while (--count > 0); | ||
2249 | mxvar_log.txcnt[port->tty->index] += (cnt - port->xmit_cnt); | ||
2250 | |||
2251 | port->mon_data.txcnt += (cnt - port->xmit_cnt); | ||
2252 | port->mon_data.up_txcnt += (cnt - port->xmit_cnt); | ||
2253 | port->icount.tx += (cnt - port->xmit_cnt); | ||
2254 | |||
2255 | if (port->xmit_cnt < WAKEUP_CHARS) | ||
2256 | tty_wakeup(port->tty); | ||
2257 | |||
2258 | if (port->xmit_cnt <= 0) { | ||
2259 | port->IER &= ~UART_IER_THRI; | ||
2260 | outb(port->IER, port->ioaddr + UART_IER); | ||
2261 | } | ||
2262 | } | ||
2263 | |||
2264 | /* | ||
2265 | * This is the serial driver's generic interrupt routine | ||
2266 | */ | ||
2267 | static irqreturn_t mxser_interrupt(int irq, void *dev_id) | ||
2268 | { | ||
2269 | int status, iir, i; | ||
2270 | struct mxser_board *brd = NULL; | ||
2271 | struct mxser_port *port; | ||
2272 | int max, irqbits, bits, msr; | ||
2273 | unsigned int int_cnt, pass_counter = 0; | ||
2274 | int handled = IRQ_NONE; | ||
2275 | |||
2276 | for (i = 0; i < MXSER_BOARDS; i++) | ||
2277 | if (dev_id == &mxser_boards[i]) { | ||
2278 | brd = dev_id; | ||
2279 | break; | ||
2280 | } | ||
2281 | |||
2282 | if (i == MXSER_BOARDS) | ||
2283 | goto irq_stop; | ||
2284 | if (brd == NULL) | ||
2285 | goto irq_stop; | ||
2286 | max = brd->info->nports; | ||
2287 | while (pass_counter++ < MXSER_ISR_PASS_LIMIT) { | ||
2288 | irqbits = inb(brd->vector) & brd->vector_mask; | ||
2289 | if (irqbits == brd->vector_mask) | ||
2290 | break; | ||
2291 | |||
2292 | handled = IRQ_HANDLED; | ||
2293 | for (i = 0, bits = 1; i < max; i++, irqbits |= bits, bits <<= 1) { | ||
2294 | if (irqbits == brd->vector_mask) | ||
2295 | break; | ||
2296 | if (bits & irqbits) | ||
2297 | continue; | ||
2298 | port = &brd->ports[i]; | ||
2299 | |||
2300 | int_cnt = 0; | ||
2301 | spin_lock(&port->slock); | ||
2302 | do { | ||
2303 | iir = inb(port->ioaddr + UART_IIR); | ||
2304 | if (iir & UART_IIR_NO_INT) | ||
2305 | break; | ||
2306 | iir &= MOXA_MUST_IIR_MASK; | ||
2307 | if (!port->tty || | ||
2308 | (port->flags & ASYNC_CLOSING) || | ||
2309 | !(port->flags & | ||
2310 | ASYNC_INITIALIZED)) { | ||
2311 | status = inb(port->ioaddr + UART_LSR); | ||
2312 | outb(0x27, port->ioaddr + UART_FCR); | ||
2313 | inb(port->ioaddr + UART_MSR); | ||
2314 | break; | ||
2315 | } | ||
2316 | |||
2317 | status = inb(port->ioaddr + UART_LSR); | ||
2318 | |||
2319 | if (status & UART_LSR_PE) | ||
2320 | port->err_shadow |= NPPI_NOTIFY_PARITY; | ||
2321 | if (status & UART_LSR_FE) | ||
2322 | port->err_shadow |= NPPI_NOTIFY_FRAMING; | ||
2323 | if (status & UART_LSR_OE) | ||
2324 | port->err_shadow |= | ||
2325 | NPPI_NOTIFY_HW_OVERRUN; | ||
2326 | if (status & UART_LSR_BI) | ||
2327 | port->err_shadow |= NPPI_NOTIFY_BREAK; | ||
2328 | |||
2329 | if (port->board->chip_flag) { | ||
2330 | if (iir == MOXA_MUST_IIR_GDA || | ||
2331 | iir == MOXA_MUST_IIR_RDA || | ||
2332 | iir == MOXA_MUST_IIR_RTO || | ||
2333 | iir == MOXA_MUST_IIR_LSR) | ||
2334 | mxser_receive_chars(port, | ||
2335 | &status); | ||
2336 | |||
2337 | } else { | ||
2338 | status &= port->read_status_mask; | ||
2339 | if (status & UART_LSR_DR) | ||
2340 | mxser_receive_chars(port, | ||
2341 | &status); | ||
2342 | } | ||
2343 | msr = inb(port->ioaddr + UART_MSR); | ||
2344 | if (msr & UART_MSR_ANY_DELTA) | ||
2345 | mxser_check_modem_status(port, msr); | ||
2346 | |||
2347 | if (port->board->chip_flag) { | ||
2348 | if (iir == 0x02 && (status & | ||
2349 | UART_LSR_THRE)) | ||
2350 | mxser_transmit_chars(port); | ||
2351 | } else { | ||
2352 | if (status & UART_LSR_THRE) | ||
2353 | mxser_transmit_chars(port); | ||
2354 | } | ||
2355 | } while (int_cnt++ < MXSER_ISR_PASS_LIMIT); | ||
2356 | spin_unlock(&port->slock); | ||
2357 | } | ||
2358 | } | ||
2359 | |||
2360 | irq_stop: | ||
2361 | return handled; | ||
2362 | } | ||
2363 | |||
2364 | static const struct tty_operations mxser_ops = { | ||
2365 | .open = mxser_open, | ||
2366 | .close = mxser_close, | ||
2367 | .write = mxser_write, | ||
2368 | .put_char = mxser_put_char, | ||
2369 | .flush_chars = mxser_flush_chars, | ||
2370 | .write_room = mxser_write_room, | ||
2371 | .chars_in_buffer = mxser_chars_in_buffer, | ||
2372 | .flush_buffer = mxser_flush_buffer, | ||
2373 | .ioctl = mxser_ioctl, | ||
2374 | .throttle = mxser_throttle, | ||
2375 | .unthrottle = mxser_unthrottle, | ||
2376 | .set_termios = mxser_set_termios, | ||
2377 | .stop = mxser_stop, | ||
2378 | .start = mxser_start, | ||
2379 | .hangup = mxser_hangup, | ||
2380 | .break_ctl = mxser_rs_break, | ||
2381 | .wait_until_sent = mxser_wait_until_sent, | ||
2382 | .tiocmget = mxser_tiocmget, | ||
2383 | .tiocmset = mxser_tiocmset, | ||
2384 | }; | ||
2385 | |||
2386 | /* | ||
2387 | * The MOXA Smartio/Industio serial driver boot-time initialization code! | ||
2388 | */ | ||
2389 | |||
2390 | static void mxser_release_res(struct mxser_board *brd, struct pci_dev *pdev, | ||
2391 | unsigned int irq) | ||
2392 | { | ||
2393 | if (irq) | ||
2394 | free_irq(brd->irq, brd); | ||
2395 | if (pdev != NULL) { /* PCI */ | ||
2396 | #ifdef CONFIG_PCI | ||
2397 | pci_release_region(pdev, 2); | ||
2398 | pci_release_region(pdev, 3); | ||
2399 | #endif | ||
2400 | } else { | ||
2401 | release_region(brd->ports[0].ioaddr, 8 * brd->info->nports); | ||
2402 | release_region(brd->vector, 1); | ||
2403 | } | ||
2404 | } | ||
2405 | |||
2406 | static int __devinit mxser_initbrd(struct mxser_board *brd, | ||
2407 | struct pci_dev *pdev) | ||
2408 | { | ||
2409 | struct mxser_port *info; | ||
2410 | unsigned int i; | ||
2411 | int retval; | ||
2412 | |||
2413 | printk(KERN_INFO "max. baud rate = %d bps.\n", brd->ports[0].max_baud); | ||
2414 | |||
2415 | for (i = 0; i < brd->info->nports; i++) { | ||
2416 | info = &brd->ports[i]; | ||
2417 | info->board = brd; | ||
2418 | info->stop_rx = 0; | ||
2419 | info->ldisc_stop_rx = 0; | ||
2420 | |||
2421 | /* Enhance mode enabled here */ | ||
2422 | if (brd->chip_flag != MOXA_OTHER_UART) | ||
2423 | ENABLE_MOXA_MUST_ENCHANCE_MODE(info->ioaddr); | ||
2424 | |||
2425 | info->flags = ASYNC_SHARE_IRQ; | ||
2426 | info->type = brd->uart_type; | ||
2427 | |||
2428 | process_txrx_fifo(info); | ||
2429 | |||
2430 | info->custom_divisor = info->baud_base * 16; | ||
2431 | info->close_delay = 5 * HZ / 10; | ||
2432 | info->closing_wait = 30 * HZ; | ||
2433 | info->normal_termios = mxvar_sdriver->init_termios; | ||
2434 | init_waitqueue_head(&info->open_wait); | ||
2435 | init_waitqueue_head(&info->delta_msr_wait); | ||
2436 | info->speed = 9600; | ||
2437 | memset(&info->mon_data, 0, sizeof(struct mxser_mon)); | ||
2438 | info->err_shadow = 0; | ||
2439 | spin_lock_init(&info->slock); | ||
2440 | |||
2441 | /* before set INT ISR, disable all int */ | ||
2442 | outb(inb(info->ioaddr + UART_IER) & 0xf0, | ||
2443 | info->ioaddr + UART_IER); | ||
2444 | } | ||
2445 | |||
2446 | retval = request_irq(brd->irq, mxser_interrupt, IRQF_SHARED, "mxser", | ||
2447 | brd); | ||
2448 | if (retval) { | ||
2449 | printk(KERN_ERR "Board %s: Request irq failed, IRQ (%d) may " | ||
2450 | "conflict with another device.\n", | ||
2451 | brd->info->name, brd->irq); | ||
2452 | /* We hold resources, we need to release them. */ | ||
2453 | mxser_release_res(brd, pdev, 0); | ||
2454 | } | ||
2455 | return retval; | ||
2456 | } | ||
2457 | |||
2458 | static int __init mxser_get_ISA_conf(int cap, struct mxser_board *brd) | ||
2459 | { | ||
2460 | int id, i, bits; | ||
2461 | unsigned short regs[16], irq; | ||
2462 | unsigned char scratch, scratch2; | ||
2463 | |||
2464 | brd->chip_flag = MOXA_OTHER_UART; | ||
2465 | |||
2466 | id = mxser_read_register(cap, regs); | ||
2467 | switch (id) { | ||
2468 | case C168_ASIC_ID: | ||
2469 | brd->info = &mxser_cards[0]; | ||
2470 | break; | ||
2471 | case C104_ASIC_ID: | ||
2472 | brd->info = &mxser_cards[1]; | ||
2473 | break; | ||
2474 | case CI104J_ASIC_ID: | ||
2475 | brd->info = &mxser_cards[2]; | ||
2476 | break; | ||
2477 | case C102_ASIC_ID: | ||
2478 | brd->info = &mxser_cards[5]; | ||
2479 | break; | ||
2480 | case CI132_ASIC_ID: | ||
2481 | brd->info = &mxser_cards[6]; | ||
2482 | break; | ||
2483 | case CI134_ASIC_ID: | ||
2484 | brd->info = &mxser_cards[7]; | ||
2485 | break; | ||
2486 | default: | ||
2487 | return 0; | ||
2488 | } | ||
2489 | |||
2490 | irq = 0; | ||
2491 | /* some ISA cards have 2 ports, but we want to see them as 4-port (why?) | ||
2492 | Flag-hack checks if configuration should be read as 2-port here. */ | ||
2493 | if (brd->info->nports == 2 || (brd->info->flags & MXSER_HAS2)) { | ||
2494 | irq = regs[9] & 0xF000; | ||
2495 | irq = irq | (irq >> 4); | ||
2496 | if (irq != (regs[9] & 0xFF00)) | ||
2497 | return MXSER_ERR_IRQ_CONFLIT; | ||
2498 | } else if (brd->info->nports == 4) { | ||
2499 | irq = regs[9] & 0xF000; | ||
2500 | irq = irq | (irq >> 4); | ||
2501 | irq = irq | (irq >> 8); | ||
2502 | if (irq != regs[9]) | ||
2503 | return MXSER_ERR_IRQ_CONFLIT; | ||
2504 | } else if (brd->info->nports == 8) { | ||
2505 | irq = regs[9] & 0xF000; | ||
2506 | irq = irq | (irq >> 4); | ||
2507 | irq = irq | (irq >> 8); | ||
2508 | if ((irq != regs[9]) || (irq != regs[10])) | ||
2509 | return MXSER_ERR_IRQ_CONFLIT; | ||
2510 | } | ||
2511 | |||
2512 | if (!irq) | ||
2513 | return MXSER_ERR_IRQ; | ||
2514 | brd->irq = ((int)(irq & 0xF000) >> 12); | ||
2515 | for (i = 0; i < 8; i++) | ||
2516 | brd->ports[i].ioaddr = (int) regs[i + 1] & 0xFFF8; | ||
2517 | if ((regs[12] & 0x80) == 0) | ||
2518 | return MXSER_ERR_VECTOR; | ||
2519 | brd->vector = (int)regs[11]; /* interrupt vector */ | ||
2520 | if (id == 1) | ||
2521 | brd->vector_mask = 0x00FF; | ||
2522 | else | ||
2523 | brd->vector_mask = 0x000F; | ||
2524 | for (i = 7, bits = 0x0100; i >= 0; i--, bits <<= 1) { | ||
2525 | if (regs[12] & bits) { | ||
2526 | brd->ports[i].baud_base = 921600; | ||
2527 | brd->ports[i].max_baud = 921600; | ||
2528 | } else { | ||
2529 | brd->ports[i].baud_base = 115200; | ||
2530 | brd->ports[i].max_baud = 115200; | ||
2531 | } | ||
2532 | } | ||
2533 | scratch2 = inb(cap + UART_LCR) & (~UART_LCR_DLAB); | ||
2534 | outb(scratch2 | UART_LCR_DLAB, cap + UART_LCR); | ||
2535 | outb(0, cap + UART_EFR); /* EFR is the same as FCR */ | ||
2536 | outb(scratch2, cap + UART_LCR); | ||
2537 | outb(UART_FCR_ENABLE_FIFO, cap + UART_FCR); | ||
2538 | scratch = inb(cap + UART_IIR); | ||
2539 | |||
2540 | if (scratch & 0xC0) | ||
2541 | brd->uart_type = PORT_16550A; | ||
2542 | else | ||
2543 | brd->uart_type = PORT_16450; | ||
2544 | if (!request_region(brd->ports[0].ioaddr, 8 * brd->info->nports, | ||
2545 | "mxser(IO)")) | ||
2546 | return MXSER_ERR_IOADDR; | ||
2547 | if (!request_region(brd->vector, 1, "mxser(vector)")) { | ||
2548 | release_region(brd->ports[0].ioaddr, 8 * brd->info->nports); | ||
2549 | return MXSER_ERR_VECTOR; | ||
2550 | } | ||
2551 | return brd->info->nports; | ||
2552 | } | ||
2553 | |||
2554 | static int __devinit mxser_probe(struct pci_dev *pdev, | ||
2555 | const struct pci_device_id *ent) | ||
2556 | { | ||
2557 | #ifdef CONFIG_PCI | ||
2558 | struct mxser_board *brd; | ||
2559 | unsigned int i, j; | ||
2560 | unsigned long ioaddress; | ||
2561 | int retval = -EINVAL; | ||
2562 | |||
2563 | for (i = 0; i < MXSER_BOARDS; i++) | ||
2564 | if (mxser_boards[i].info == NULL) | ||
2565 | break; | ||
2566 | |||
2567 | if (i >= MXSER_BOARDS) { | ||
2568 | printk(KERN_ERR "Too many Smartio/Industio family boards found " | ||
2569 | "(maximum %d), board not configured\n", MXSER_BOARDS); | ||
2570 | goto err; | ||
2571 | } | ||
2572 | |||
2573 | brd = &mxser_boards[i]; | ||
2574 | brd->idx = i * MXSER_PORTS_PER_BOARD; | ||
2575 | printk(KERN_INFO "Found MOXA %s board (BusNo=%d, DevNo=%d)\n", | ||
2576 | mxser_cards[ent->driver_data].name, | ||
2577 | pdev->bus->number, PCI_SLOT(pdev->devfn)); | ||
2578 | |||
2579 | retval = pci_enable_device(pdev); | ||
2580 | if (retval) { | ||
2581 | printk(KERN_ERR "Moxa SmartI/O PCI enable fail !\n"); | ||
2582 | goto err; | ||
2583 | } | ||
2584 | |||
2585 | /* io address */ | ||
2586 | ioaddress = pci_resource_start(pdev, 2); | ||
2587 | retval = pci_request_region(pdev, 2, "mxser(IO)"); | ||
2588 | if (retval) | ||
2589 | goto err; | ||
2590 | |||
2591 | brd->info = &mxser_cards[ent->driver_data]; | ||
2592 | for (i = 0; i < brd->info->nports; i++) | ||
2593 | brd->ports[i].ioaddr = ioaddress + 8 * i; | ||
2594 | |||
2595 | /* vector */ | ||
2596 | ioaddress = pci_resource_start(pdev, 3); | ||
2597 | retval = pci_request_region(pdev, 3, "mxser(vector)"); | ||
2598 | if (retval) | ||
2599 | goto err_relio; | ||
2600 | brd->vector = ioaddress; | ||
2601 | |||
2602 | /* irq */ | ||
2603 | brd->irq = pdev->irq; | ||
2604 | |||
2605 | brd->chip_flag = CheckIsMoxaMust(brd->ports[0].ioaddr); | ||
2606 | brd->uart_type = PORT_16550A; | ||
2607 | brd->vector_mask = 0; | ||
2608 | |||
2609 | for (i = 0; i < brd->info->nports; i++) { | ||
2610 | for (j = 0; j < UART_INFO_NUM; j++) { | ||
2611 | if (Gpci_uart_info[j].type == brd->chip_flag) { | ||
2612 | brd->ports[i].max_baud = | ||
2613 | Gpci_uart_info[j].max_baud; | ||
2614 | |||
2615 | /* exception....CP-102 */ | ||
2616 | if (brd->info->flags & MXSER_HIGHBAUD) | ||
2617 | brd->ports[i].max_baud = 921600; | ||
2618 | break; | ||
2619 | } | ||
2620 | } | ||
2621 | } | ||
2622 | |||
2623 | if (brd->chip_flag == MOXA_MUST_MU860_HWID) { | ||
2624 | for (i = 0; i < brd->info->nports; i++) { | ||
2625 | if (i < 4) | ||
2626 | brd->ports[i].opmode_ioaddr = ioaddress + 4; | ||
2627 | else | ||
2628 | brd->ports[i].opmode_ioaddr = ioaddress + 0x0c; | ||
2629 | } | ||
2630 | outb(0, ioaddress + 4); /* default set to RS232 mode */ | ||
2631 | outb(0, ioaddress + 0x0c); /* default set to RS232 mode */ | ||
2632 | } | ||
2633 | |||
2634 | for (i = 0; i < brd->info->nports; i++) { | ||
2635 | brd->vector_mask |= (1 << i); | ||
2636 | brd->ports[i].baud_base = 921600; | ||
2637 | } | ||
2638 | |||
2639 | /* mxser_initbrd will hook ISR. */ | ||
2640 | retval = mxser_initbrd(brd, pdev); | ||
2641 | if (retval) | ||
2642 | goto err_null; | ||
2643 | |||
2644 | for (i = 0; i < brd->info->nports; i++) | ||
2645 | tty_register_device(mxvar_sdriver, brd->idx + i, &pdev->dev); | ||
2646 | |||
2647 | pci_set_drvdata(pdev, brd); | ||
2648 | |||
2649 | return 0; | ||
2650 | err_relio: | ||
2651 | pci_release_region(pdev, 2); | ||
2652 | err_null: | ||
2653 | brd->info = NULL; | ||
2654 | err: | ||
2655 | return retval; | ||
2656 | #else | ||
2657 | return -ENODEV; | ||
2658 | #endif | ||
2659 | } | ||
2660 | |||
2661 | static void __devexit mxser_remove(struct pci_dev *pdev) | ||
2662 | { | ||
2663 | struct mxser_board *brd = pci_get_drvdata(pdev); | ||
2664 | unsigned int i; | ||
2665 | |||
2666 | for (i = 0; i < brd->info->nports; i++) | ||
2667 | tty_unregister_device(mxvar_sdriver, brd->idx + i); | ||
2668 | |||
2669 | mxser_release_res(brd, pdev, 1); | ||
2670 | brd->info = NULL; | ||
2671 | } | ||
2672 | |||
2673 | static struct pci_driver mxser_driver = { | ||
2674 | .name = "mxser", | ||
2675 | .id_table = mxser_pcibrds, | ||
2676 | .probe = mxser_probe, | ||
2677 | .remove = __devexit_p(mxser_remove) | ||
2678 | }; | ||
2679 | |||
2680 | static int __init mxser_module_init(void) | ||
2681 | { | ||
2682 | struct mxser_board *brd; | ||
2683 | unsigned long cap; | ||
2684 | unsigned int i, m, isaloop; | ||
2685 | int retval, b; | ||
2686 | |||
2687 | pr_debug("Loading module mxser ...\n"); | ||
2688 | |||
2689 | mxvar_sdriver = alloc_tty_driver(MXSER_PORTS + 1); | ||
2690 | if (!mxvar_sdriver) | ||
2691 | return -ENOMEM; | ||
2692 | |||
2693 | printk(KERN_INFO "MOXA Smartio/Industio family driver version %s\n", | ||
2694 | MXSER_VERSION); | ||
2695 | |||
2696 | /* Initialize the tty_driver structure */ | ||
2697 | mxvar_sdriver->owner = THIS_MODULE; | ||
2698 | mxvar_sdriver->magic = TTY_DRIVER_MAGIC; | ||
2699 | mxvar_sdriver->name = "ttyMI"; | ||
2700 | mxvar_sdriver->major = ttymajor; | ||
2701 | mxvar_sdriver->minor_start = 0; | ||
2702 | mxvar_sdriver->num = MXSER_PORTS + 1; | ||
2703 | mxvar_sdriver->type = TTY_DRIVER_TYPE_SERIAL; | ||
2704 | mxvar_sdriver->subtype = SERIAL_TYPE_NORMAL; | ||
2705 | mxvar_sdriver->init_termios = tty_std_termios; | ||
2706 | mxvar_sdriver->init_termios.c_cflag = B9600|CS8|CREAD|HUPCL|CLOCAL; | ||
2707 | mxvar_sdriver->flags = TTY_DRIVER_REAL_RAW|TTY_DRIVER_DYNAMIC_DEV; | ||
2708 | tty_set_operations(mxvar_sdriver, &mxser_ops); | ||
2709 | |||
2710 | retval = tty_register_driver(mxvar_sdriver); | ||
2711 | if (retval) { | ||
2712 | printk(KERN_ERR "Couldn't install MOXA Smartio/Industio family " | ||
2713 | "tty driver !\n"); | ||
2714 | goto err_put; | ||
2715 | } | ||
2716 | |||
2717 | mxvar_diagflag = 0; | ||
2718 | |||
2719 | m = 0; | ||
2720 | /* Start finding ISA boards here */ | ||
2721 | for (isaloop = 0; isaloop < 2; isaloop++) | ||
2722 | for (b = 0; b < MXSER_BOARDS && m < MXSER_BOARDS; b++) { | ||
2723 | if (!isaloop) | ||
2724 | cap = mxserBoardCAP[b]; /* predefined */ | ||
2725 | else | ||
2726 | cap = ioaddr[b]; /* module param */ | ||
2727 | |||
2728 | if (!cap) | ||
2729 | continue; | ||
2730 | |||
2731 | brd = &mxser_boards[m]; | ||
2732 | retval = mxser_get_ISA_conf(cap, brd); | ||
2733 | |||
2734 | if (retval != 0) | ||
2735 | printk(KERN_INFO "Found MOXA %s board " | ||
2736 | "(CAP=0x%x)\n", | ||
2737 | brd->info->name, ioaddr[b]); | ||
2738 | |||
2739 | if (retval <= 0) { | ||
2740 | if (retval == MXSER_ERR_IRQ) | ||
2741 | printk(KERN_ERR "Invalid interrupt " | ||
2742 | "number, board not " | ||
2743 | "configured\n"); | ||
2744 | else if (retval == MXSER_ERR_IRQ_CONFLIT) | ||
2745 | printk(KERN_ERR "Invalid interrupt " | ||
2746 | "number, board not " | ||
2747 | "configured\n"); | ||
2748 | else if (retval == MXSER_ERR_VECTOR) | ||
2749 | printk(KERN_ERR "Invalid interrupt " | ||
2750 | "vector, board not " | ||
2751 | "configured\n"); | ||
2752 | else if (retval == MXSER_ERR_IOADDR) | ||
2753 | printk(KERN_ERR "Invalid I/O address, " | ||
2754 | "board not configured\n"); | ||
2755 | |||
2756 | brd->info = NULL; | ||
2757 | continue; | ||
2758 | } | ||
2759 | |||
2760 | /* mxser_initbrd will hook ISR. */ | ||
2761 | if (mxser_initbrd(brd, NULL) < 0) { | ||
2762 | brd->info = NULL; | ||
2763 | continue; | ||
2764 | } | ||
2765 | |||
2766 | brd->idx = m * MXSER_PORTS_PER_BOARD; | ||
2767 | for (i = 0; i < brd->info->nports; i++) | ||
2768 | tty_register_device(mxvar_sdriver, brd->idx + i, | ||
2769 | NULL); | ||
2770 | |||
2771 | m++; | ||
2772 | } | ||
2773 | |||
2774 | retval = pci_register_driver(&mxser_driver); | ||
2775 | if (retval) { | ||
2776 | printk(KERN_ERR "Can't register pci driver\n"); | ||
2777 | if (!m) { | ||
2778 | retval = -ENODEV; | ||
2779 | goto err_unr; | ||
2780 | } /* else: we have some ISA cards under control */ | ||
2781 | } | ||
2782 | |||
2783 | pr_debug("Done.\n"); | ||
2784 | |||
2785 | return 0; | ||
2786 | err_unr: | ||
2787 | tty_unregister_driver(mxvar_sdriver); | ||
2788 | err_put: | ||
2789 | put_tty_driver(mxvar_sdriver); | ||
2790 | return retval; | ||
2791 | } | ||
2792 | |||
2793 | static void __exit mxser_module_exit(void) | ||
2794 | { | ||
2795 | unsigned int i, j; | ||
2796 | |||
2797 | pr_debug("Unloading module mxser ...\n"); | ||
2798 | |||
2799 | pci_unregister_driver(&mxser_driver); | ||
2800 | |||
2801 | for (i = 0; i < MXSER_BOARDS; i++) /* ISA remains */ | ||
2802 | if (mxser_boards[i].info != NULL) | ||
2803 | for (j = 0; j < mxser_boards[i].info->nports; j++) | ||
2804 | tty_unregister_device(mxvar_sdriver, | ||
2805 | mxser_boards[i].idx + j); | ||
2806 | tty_unregister_driver(mxvar_sdriver); | ||
2807 | put_tty_driver(mxvar_sdriver); | ||
2808 | |||
2809 | for (i = 0; i < MXSER_BOARDS; i++) | ||
2810 | if (mxser_boards[i].info != NULL) | ||
2811 | mxser_release_res(&mxser_boards[i], NULL, 1); | ||
2812 | |||
2813 | pr_debug("Done.\n"); | ||
2814 | } | ||
2815 | |||
2816 | module_init(mxser_module_init); | ||
2817 | module_exit(mxser_module_exit); | ||
diff --git a/drivers/char/mxser_new.h b/drivers/char/mxser_new.h deleted file mode 100644 index d42f7766c652..000000000000 --- a/drivers/char/mxser_new.h +++ /dev/null | |||
@@ -1,293 +0,0 @@ | |||
1 | #ifndef _MXSER_H | ||
2 | #define _MXSER_H | ||
3 | |||
4 | /* | ||
5 | * Semi-public control interfaces | ||
6 | */ | ||
7 | |||
8 | /* | ||
9 | * MOXA ioctls | ||
10 | */ | ||
11 | |||
12 | #define MOXA 0x400 | ||
13 | #define MOXA_GETDATACOUNT (MOXA + 23) | ||
14 | #define MOXA_GET_CONF (MOXA + 35) | ||
15 | #define MOXA_DIAGNOSE (MOXA + 50) | ||
16 | #define MOXA_CHKPORTENABLE (MOXA + 60) | ||
17 | #define MOXA_HighSpeedOn (MOXA + 61) | ||
18 | #define MOXA_GET_MAJOR (MOXA + 63) | ||
19 | #define MOXA_GET_CUMAJOR (MOXA + 64) | ||
20 | #define MOXA_GETMSTATUS (MOXA + 65) | ||
21 | #define MOXA_SET_OP_MODE (MOXA + 66) | ||
22 | #define MOXA_GET_OP_MODE (MOXA + 67) | ||
23 | |||
24 | #define RS232_MODE 0 | ||
25 | #define RS485_2WIRE_MODE 1 | ||
26 | #define RS422_MODE 2 | ||
27 | #define RS485_4WIRE_MODE 3 | ||
28 | #define OP_MODE_MASK 3 | ||
29 | |||
30 | #define MOXA_SDS_RSTICOUNTER (MOXA + 69) | ||
31 | #define MOXA_ASPP_OQUEUE (MOXA + 70) | ||
32 | #define MOXA_ASPP_SETBAUD (MOXA + 71) | ||
33 | #define MOXA_ASPP_GETBAUD (MOXA + 72) | ||
34 | #define MOXA_ASPP_MON (MOXA + 73) | ||
35 | #define MOXA_ASPP_LSTATUS (MOXA + 74) | ||
36 | #define MOXA_ASPP_MON_EXT (MOXA + 75) | ||
37 | #define MOXA_SET_BAUD_METHOD (MOXA + 76) | ||
38 | #define MOXA_SET_SPECIAL_BAUD_RATE (MOXA + 77) | ||
39 | #define MOXA_GET_SPECIAL_BAUD_RATE (MOXA + 78) | ||
40 | |||
41 | /* --------------------------------------------------- */ | ||
42 | |||
43 | #define NPPI_NOTIFY_PARITY 0x01 | ||
44 | #define NPPI_NOTIFY_FRAMING 0x02 | ||
45 | #define NPPI_NOTIFY_HW_OVERRUN 0x04 | ||
46 | #define NPPI_NOTIFY_SW_OVERRUN 0x08 | ||
47 | #define NPPI_NOTIFY_BREAK 0x10 | ||
48 | |||
49 | #define NPPI_NOTIFY_CTSHOLD 0x01 /* Tx hold by CTS low */ | ||
50 | #define NPPI_NOTIFY_DSRHOLD 0x02 /* Tx hold by DSR low */ | ||
51 | #define NPPI_NOTIFY_XOFFHOLD 0x08 /* Tx hold by Xoff received */ | ||
52 | #define NPPI_NOTIFY_XOFFXENT 0x10 /* Xoff Sent */ | ||
53 | |||
54 | /* follow just for Moxa Must chip define. */ | ||
55 | /* */ | ||
56 | /* when LCR register (offset 0x03) write following value, */ | ||
57 | /* the Must chip will enter enchance mode. And write value */ | ||
58 | /* on EFR (offset 0x02) bit 6,7 to change bank. */ | ||
59 | #define MOXA_MUST_ENTER_ENCHANCE 0xBF | ||
60 | |||
61 | /* when enhance mode enable, access on general bank register */ | ||
62 | #define MOXA_MUST_GDL_REGISTER 0x07 | ||
63 | #define MOXA_MUST_GDL_MASK 0x7F | ||
64 | #define MOXA_MUST_GDL_HAS_BAD_DATA 0x80 | ||
65 | |||
66 | #define MOXA_MUST_LSR_RERR 0x80 /* error in receive FIFO */ | ||
67 | /* enchance register bank select and enchance mode setting register */ | ||
68 | /* when LCR register equal to 0xBF */ | ||
69 | #define MOXA_MUST_EFR_REGISTER 0x02 | ||
70 | /* enchance mode enable */ | ||
71 | #define MOXA_MUST_EFR_EFRB_ENABLE 0x10 | ||
72 | /* enchance reister bank set 0, 1, 2 */ | ||
73 | #define MOXA_MUST_EFR_BANK0 0x00 | ||
74 | #define MOXA_MUST_EFR_BANK1 0x40 | ||
75 | #define MOXA_MUST_EFR_BANK2 0x80 | ||
76 | #define MOXA_MUST_EFR_BANK3 0xC0 | ||
77 | #define MOXA_MUST_EFR_BANK_MASK 0xC0 | ||
78 | |||
79 | /* set XON1 value register, when LCR=0xBF and change to bank0 */ | ||
80 | #define MOXA_MUST_XON1_REGISTER 0x04 | ||
81 | |||
82 | /* set XON2 value register, when LCR=0xBF and change to bank0 */ | ||
83 | #define MOXA_MUST_XON2_REGISTER 0x05 | ||
84 | |||
85 | /* set XOFF1 value register, when LCR=0xBF and change to bank0 */ | ||
86 | #define MOXA_MUST_XOFF1_REGISTER 0x06 | ||
87 | |||
88 | /* set XOFF2 value register, when LCR=0xBF and change to bank0 */ | ||
89 | #define MOXA_MUST_XOFF2_REGISTER 0x07 | ||
90 | |||
91 | #define MOXA_MUST_RBRTL_REGISTER 0x04 | ||
92 | #define MOXA_MUST_RBRTH_REGISTER 0x05 | ||
93 | #define MOXA_MUST_RBRTI_REGISTER 0x06 | ||
94 | #define MOXA_MUST_THRTL_REGISTER 0x07 | ||
95 | #define MOXA_MUST_ENUM_REGISTER 0x04 | ||
96 | #define MOXA_MUST_HWID_REGISTER 0x05 | ||
97 | #define MOXA_MUST_ECR_REGISTER 0x06 | ||
98 | #define MOXA_MUST_CSR_REGISTER 0x07 | ||
99 | |||
100 | /* good data mode enable */ | ||
101 | #define MOXA_MUST_FCR_GDA_MODE_ENABLE 0x20 | ||
102 | /* only good data put into RxFIFO */ | ||
103 | #define MOXA_MUST_FCR_GDA_ONLY_ENABLE 0x10 | ||
104 | |||
105 | /* enable CTS interrupt */ | ||
106 | #define MOXA_MUST_IER_ECTSI 0x80 | ||
107 | /* enable RTS interrupt */ | ||
108 | #define MOXA_MUST_IER_ERTSI 0x40 | ||
109 | /* enable Xon/Xoff interrupt */ | ||
110 | #define MOXA_MUST_IER_XINT 0x20 | ||
111 | /* enable GDA interrupt */ | ||
112 | #define MOXA_MUST_IER_EGDAI 0x10 | ||
113 | |||
114 | #define MOXA_MUST_RECV_ISR (UART_IER_RDI | MOXA_MUST_IER_EGDAI) | ||
115 | |||
116 | /* GDA interrupt pending */ | ||
117 | #define MOXA_MUST_IIR_GDA 0x1C | ||
118 | #define MOXA_MUST_IIR_RDA 0x04 | ||
119 | #define MOXA_MUST_IIR_RTO 0x0C | ||
120 | #define MOXA_MUST_IIR_LSR 0x06 | ||
121 | |||
122 | /* recieved Xon/Xoff or specical interrupt pending */ | ||
123 | #define MOXA_MUST_IIR_XSC 0x10 | ||
124 | |||
125 | /* RTS/CTS change state interrupt pending */ | ||
126 | #define MOXA_MUST_IIR_RTSCTS 0x20 | ||
127 | #define MOXA_MUST_IIR_MASK 0x3E | ||
128 | |||
129 | #define MOXA_MUST_MCR_XON_FLAG 0x40 | ||
130 | #define MOXA_MUST_MCR_XON_ANY 0x80 | ||
131 | #define MOXA_MUST_MCR_TX_XON 0x08 | ||
132 | |||
133 | /* software flow control on chip mask value */ | ||
134 | #define MOXA_MUST_EFR_SF_MASK 0x0F | ||
135 | /* send Xon1/Xoff1 */ | ||
136 | #define MOXA_MUST_EFR_SF_TX1 0x08 | ||
137 | /* send Xon2/Xoff2 */ | ||
138 | #define MOXA_MUST_EFR_SF_TX2 0x04 | ||
139 | /* send Xon1,Xon2/Xoff1,Xoff2 */ | ||
140 | #define MOXA_MUST_EFR_SF_TX12 0x0C | ||
141 | /* don't send Xon/Xoff */ | ||
142 | #define MOXA_MUST_EFR_SF_TX_NO 0x00 | ||
143 | /* Tx software flow control mask */ | ||
144 | #define MOXA_MUST_EFR_SF_TX_MASK 0x0C | ||
145 | /* don't receive Xon/Xoff */ | ||
146 | #define MOXA_MUST_EFR_SF_RX_NO 0x00 | ||
147 | /* receive Xon1/Xoff1 */ | ||
148 | #define MOXA_MUST_EFR_SF_RX1 0x02 | ||
149 | /* receive Xon2/Xoff2 */ | ||
150 | #define MOXA_MUST_EFR_SF_RX2 0x01 | ||
151 | /* receive Xon1,Xon2/Xoff1,Xoff2 */ | ||
152 | #define MOXA_MUST_EFR_SF_RX12 0x03 | ||
153 | /* Rx software flow control mask */ | ||
154 | #define MOXA_MUST_EFR_SF_RX_MASK 0x03 | ||
155 | |||
156 | #define ENABLE_MOXA_MUST_ENCHANCE_MODE(baseio) do { \ | ||
157 | u8 __oldlcr, __efr; \ | ||
158 | __oldlcr = inb((baseio)+UART_LCR); \ | ||
159 | outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ | ||
160 | __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ | ||
161 | __efr |= MOXA_MUST_EFR_EFRB_ENABLE; \ | ||
162 | outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ | ||
163 | outb(__oldlcr, (baseio)+UART_LCR); \ | ||
164 | } while (0) | ||
165 | |||
166 | #define DISABLE_MOXA_MUST_ENCHANCE_MODE(baseio) do { \ | ||
167 | u8 __oldlcr, __efr; \ | ||
168 | __oldlcr = inb((baseio)+UART_LCR); \ | ||
169 | outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ | ||
170 | __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ | ||
171 | __efr &= ~MOXA_MUST_EFR_EFRB_ENABLE; \ | ||
172 | outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ | ||
173 | outb(__oldlcr, (baseio)+UART_LCR); \ | ||
174 | } while (0) | ||
175 | |||
176 | #define SET_MOXA_MUST_XON1_VALUE(baseio, Value) do { \ | ||
177 | u8 __oldlcr, __efr; \ | ||
178 | __oldlcr = inb((baseio)+UART_LCR); \ | ||
179 | outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ | ||
180 | __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ | ||
181 | __efr &= ~MOXA_MUST_EFR_BANK_MASK; \ | ||
182 | __efr |= MOXA_MUST_EFR_BANK0; \ | ||
183 | outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ | ||
184 | outb((u8)(Value), (baseio)+MOXA_MUST_XON1_REGISTER); \ | ||
185 | outb(__oldlcr, (baseio)+UART_LCR); \ | ||
186 | } while (0) | ||
187 | |||
188 | #define SET_MOXA_MUST_XOFF1_VALUE(baseio, Value) do { \ | ||
189 | u8 __oldlcr, __efr; \ | ||
190 | __oldlcr = inb((baseio)+UART_LCR); \ | ||
191 | outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ | ||
192 | __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ | ||
193 | __efr &= ~MOXA_MUST_EFR_BANK_MASK; \ | ||
194 | __efr |= MOXA_MUST_EFR_BANK0; \ | ||
195 | outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ | ||
196 | outb((u8)(Value), (baseio)+MOXA_MUST_XOFF1_REGISTER); \ | ||
197 | outb(__oldlcr, (baseio)+UART_LCR); \ | ||
198 | } while (0) | ||
199 | |||
200 | #define SET_MOXA_MUST_FIFO_VALUE(info) do { \ | ||
201 | u8 __oldlcr, __efr; \ | ||
202 | __oldlcr = inb((info)->ioaddr+UART_LCR); \ | ||
203 | outb(MOXA_MUST_ENTER_ENCHANCE, (info)->ioaddr+UART_LCR);\ | ||
204 | __efr = inb((info)->ioaddr+MOXA_MUST_EFR_REGISTER); \ | ||
205 | __efr &= ~MOXA_MUST_EFR_BANK_MASK; \ | ||
206 | __efr |= MOXA_MUST_EFR_BANK1; \ | ||
207 | outb(__efr, (info)->ioaddr+MOXA_MUST_EFR_REGISTER); \ | ||
208 | outb((u8)((info)->rx_high_water), (info)->ioaddr+ \ | ||
209 | MOXA_MUST_RBRTH_REGISTER); \ | ||
210 | outb((u8)((info)->rx_trigger), (info)->ioaddr+ \ | ||
211 | MOXA_MUST_RBRTI_REGISTER); \ | ||
212 | outb((u8)((info)->rx_low_water), (info)->ioaddr+ \ | ||
213 | MOXA_MUST_RBRTL_REGISTER); \ | ||
214 | outb(__oldlcr, (info)->ioaddr+UART_LCR); \ | ||
215 | } while (0) | ||
216 | |||
217 | #define SET_MOXA_MUST_ENUM_VALUE(baseio, Value) do { \ | ||
218 | u8 __oldlcr, __efr; \ | ||
219 | __oldlcr = inb((baseio)+UART_LCR); \ | ||
220 | outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ | ||
221 | __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ | ||
222 | __efr &= ~MOXA_MUST_EFR_BANK_MASK; \ | ||
223 | __efr |= MOXA_MUST_EFR_BANK2; \ | ||
224 | outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ | ||
225 | outb((u8)(Value), (baseio)+MOXA_MUST_ENUM_REGISTER); \ | ||
226 | outb(__oldlcr, (baseio)+UART_LCR); \ | ||
227 | } while (0) | ||
228 | |||
229 | #define GET_MOXA_MUST_HARDWARE_ID(baseio, pId) do { \ | ||
230 | u8 __oldlcr, __efr; \ | ||
231 | __oldlcr = inb((baseio)+UART_LCR); \ | ||
232 | outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ | ||
233 | __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ | ||
234 | __efr &= ~MOXA_MUST_EFR_BANK_MASK; \ | ||
235 | __efr |= MOXA_MUST_EFR_BANK2; \ | ||
236 | outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ | ||
237 | *pId = inb((baseio)+MOXA_MUST_HWID_REGISTER); \ | ||
238 | outb(__oldlcr, (baseio)+UART_LCR); \ | ||
239 | } while (0) | ||
240 | |||
241 | #define SET_MOXA_MUST_NO_SOFTWARE_FLOW_CONTROL(baseio) do { \ | ||
242 | u8 __oldlcr, __efr; \ | ||
243 | __oldlcr = inb((baseio)+UART_LCR); \ | ||
244 | outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ | ||
245 | __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ | ||
246 | __efr &= ~MOXA_MUST_EFR_SF_MASK; \ | ||
247 | outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ | ||
248 | outb(__oldlcr, (baseio)+UART_LCR); \ | ||
249 | } while (0) | ||
250 | |||
251 | #define ENABLE_MOXA_MUST_TX_SOFTWARE_FLOW_CONTROL(baseio) do { \ | ||
252 | u8 __oldlcr, __efr; \ | ||
253 | __oldlcr = inb((baseio)+UART_LCR); \ | ||
254 | outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ | ||
255 | __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ | ||
256 | __efr &= ~MOXA_MUST_EFR_SF_TX_MASK; \ | ||
257 | __efr |= MOXA_MUST_EFR_SF_TX1; \ | ||
258 | outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ | ||
259 | outb(__oldlcr, (baseio)+UART_LCR); \ | ||
260 | } while (0) | ||
261 | |||
262 | #define DISABLE_MOXA_MUST_TX_SOFTWARE_FLOW_CONTROL(baseio) do { \ | ||
263 | u8 __oldlcr, __efr; \ | ||
264 | __oldlcr = inb((baseio)+UART_LCR); \ | ||
265 | outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ | ||
266 | __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ | ||
267 | __efr &= ~MOXA_MUST_EFR_SF_TX_MASK; \ | ||
268 | outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ | ||
269 | outb(__oldlcr, (baseio)+UART_LCR); \ | ||
270 | } while (0) | ||
271 | |||
272 | #define ENABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(baseio) do { \ | ||
273 | u8 __oldlcr, __efr; \ | ||
274 | __oldlcr = inb((baseio)+UART_LCR); \ | ||
275 | outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ | ||
276 | __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ | ||
277 | __efr &= ~MOXA_MUST_EFR_SF_RX_MASK; \ | ||
278 | __efr |= MOXA_MUST_EFR_SF_RX1; \ | ||
279 | outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ | ||
280 | outb(__oldlcr, (baseio)+UART_LCR); \ | ||
281 | } while (0) | ||
282 | |||
283 | #define DISABLE_MOXA_MUST_RX_SOFTWARE_FLOW_CONTROL(baseio) do { \ | ||
284 | u8 __oldlcr, __efr; \ | ||
285 | __oldlcr = inb((baseio)+UART_LCR); \ | ||
286 | outb(MOXA_MUST_ENTER_ENCHANCE, (baseio)+UART_LCR); \ | ||
287 | __efr = inb((baseio)+MOXA_MUST_EFR_REGISTER); \ | ||
288 | __efr &= ~MOXA_MUST_EFR_SF_RX_MASK; \ | ||
289 | outb(__efr, (baseio)+MOXA_MUST_EFR_REGISTER); \ | ||
290 | outb(__oldlcr, (baseio)+UART_LCR); \ | ||
291 | } while (0) | ||
292 | |||
293 | #endif | ||
diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c index 596c7173997b..90c3969012a3 100644 --- a/drivers/char/n_tty.c +++ b/drivers/char/n_tty.c | |||
@@ -695,17 +695,16 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c) | |||
695 | return; | 695 | return; |
696 | } | 696 | } |
697 | 697 | ||
698 | if (tty->stopped && !tty->flow_stopped && | ||
699 | I_IXON(tty) && I_IXANY(tty)) { | ||
700 | start_tty(tty); | ||
701 | return; | ||
702 | } | ||
703 | |||
704 | if (I_ISTRIP(tty)) | 698 | if (I_ISTRIP(tty)) |
705 | c &= 0x7f; | 699 | c &= 0x7f; |
706 | if (I_IUCLC(tty) && L_IEXTEN(tty)) | 700 | if (I_IUCLC(tty) && L_IEXTEN(tty)) |
707 | c=tolower(c); | 701 | c=tolower(c); |
708 | 702 | ||
703 | if (tty->stopped && !tty->flow_stopped && I_IXON(tty) && | ||
704 | ((I_IXANY(tty) && c != START_CHAR(tty) && c != STOP_CHAR(tty)) || | ||
705 | c == INTR_CHAR(tty) || c == QUIT_CHAR(tty))) | ||
706 | start_tty(tty); | ||
707 | |||
709 | if (tty->closing) { | 708 | if (tty->closing) { |
710 | if (I_IXON(tty)) { | 709 | if (I_IXON(tty)) { |
711 | if (c == START_CHAR(tty)) | 710 | if (c == START_CHAR(tty)) |
@@ -769,7 +768,21 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c) | |||
769 | signal = SIGTSTP; | 768 | signal = SIGTSTP; |
770 | if (c == SUSP_CHAR(tty)) { | 769 | if (c == SUSP_CHAR(tty)) { |
771 | send_signal: | 770 | send_signal: |
772 | isig(signal, tty, 0); | 771 | /* |
772 | * Echo character, and then send the signal. | ||
773 | * Note that we do not use isig() here because we want | ||
774 | * the order to be: | ||
775 | * 1) flush, 2) echo, 3) signal | ||
776 | */ | ||
777 | if (!L_NOFLSH(tty)) { | ||
778 | n_tty_flush_buffer(tty); | ||
779 | if (tty->driver->flush_buffer) | ||
780 | tty->driver->flush_buffer(tty); | ||
781 | } | ||
782 | if (L_ECHO(tty)) | ||
783 | echo_char(c, tty); | ||
784 | if (tty->pgrp) | ||
785 | kill_pgrp(tty->pgrp, signal, 1); | ||
773 | return; | 786 | return; |
774 | } | 787 | } |
775 | } | 788 | } |
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index 8caff0ca80ff..279ff5005cec 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c | |||
@@ -57,6 +57,7 @@ | |||
57 | #include <linux/init.h> | 57 | #include <linux/init.h> |
58 | #include <linux/delay.h> | 58 | #include <linux/delay.h> |
59 | #include <linux/ioctl.h> | 59 | #include <linux/ioctl.h> |
60 | #include <linux/synclink.h> | ||
60 | 61 | ||
61 | #include <asm/system.h> | 62 | #include <asm/system.h> |
62 | #include <asm/io.h> | 63 | #include <asm/io.h> |
@@ -87,8 +88,6 @@ | |||
87 | 88 | ||
88 | #include <asm/uaccess.h> | 89 | #include <asm/uaccess.h> |
89 | 90 | ||
90 | #include "linux/synclink.h" | ||
91 | |||
92 | static MGSL_PARAMS default_params = { | 91 | static MGSL_PARAMS default_params = { |
93 | MGSL_MODE_HDLC, /* unsigned long mode */ | 92 | MGSL_MODE_HDLC, /* unsigned long mode */ |
94 | 0, /* unsigned char loopback; */ | 93 | 0, /* unsigned char loopback; */ |
diff --git a/drivers/char/random.c b/drivers/char/random.c index c511a831f0c0..f43c89f7c449 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c | |||
@@ -1039,6 +1039,7 @@ write_pool(struct entropy_store *r, const char __user *buffer, size_t count) | |||
1039 | p += bytes; | 1039 | p += bytes; |
1040 | 1040 | ||
1041 | add_entropy_words(r, buf, (bytes + 3) / 4); | 1041 | add_entropy_words(r, buf, (bytes + 3) / 4); |
1042 | cond_resched(); | ||
1042 | } | 1043 | } |
1043 | 1044 | ||
1044 | return 0; | 1045 | return 0; |
diff --git a/drivers/char/riscom8.c b/drivers/char/riscom8.c index 102ece4c4e0e..8fc4fe4e38f1 100644 --- a/drivers/char/riscom8.c +++ b/drivers/char/riscom8.c | |||
@@ -47,6 +47,7 @@ | |||
47 | #include <linux/init.h> | 47 | #include <linux/init.h> |
48 | #include <linux/delay.h> | 48 | #include <linux/delay.h> |
49 | #include <linux/tty_flip.h> | 49 | #include <linux/tty_flip.h> |
50 | #include <linux/spinlock.h> | ||
50 | 51 | ||
51 | #include <asm/uaccess.h> | 52 | #include <asm/uaccess.h> |
52 | 53 | ||
@@ -77,10 +78,10 @@ | |||
77 | ASYNC_SPD_HI | ASYNC_SPEED_VHI | ASYNC_SESSION_LOCKOUT | \ | 78 | ASYNC_SPD_HI | ASYNC_SPEED_VHI | ASYNC_SESSION_LOCKOUT | \ |
78 | ASYNC_PGRP_LOCKOUT | ASYNC_CALLOUT_NOHUP) | 79 | ASYNC_PGRP_LOCKOUT | ASYNC_CALLOUT_NOHUP) |
79 | 80 | ||
80 | #define RS_EVENT_WRITE_WAKEUP 0 | ||
81 | |||
82 | static struct tty_driver *riscom_driver; | 81 | static struct tty_driver *riscom_driver; |
83 | 82 | ||
83 | static DEFINE_SPINLOCK(riscom_lock); | ||
84 | |||
84 | static struct riscom_board rc_board[RC_NBOARD] = { | 85 | static struct riscom_board rc_board[RC_NBOARD] = { |
85 | { | 86 | { |
86 | .base = RC_IOBASE1, | 87 | .base = RC_IOBASE1, |
@@ -217,13 +218,14 @@ static void __init rc_init_CD180(struct riscom_board const * bp) | |||
217 | { | 218 | { |
218 | unsigned long flags; | 219 | unsigned long flags; |
219 | 220 | ||
220 | save_flags(flags); cli(); | 221 | spin_lock_irqsave(&riscom_lock, flags); |
222 | |||
221 | rc_out(bp, RC_CTOUT, 0); /* Clear timeout */ | 223 | rc_out(bp, RC_CTOUT, 0); /* Clear timeout */ |
222 | rc_wait_CCR(bp); /* Wait for CCR ready */ | 224 | rc_wait_CCR(bp); /* Wait for CCR ready */ |
223 | rc_out(bp, CD180_CCR, CCR_HARDRESET); /* Reset CD180 chip */ | 225 | rc_out(bp, CD180_CCR, CCR_HARDRESET); /* Reset CD180 chip */ |
224 | sti(); | 226 | spin_unlock_irqrestore(&riscom_lock, flags); |
225 | msleep(50); /* Delay 0.05 sec */ | 227 | msleep(50); /* Delay 0.05 sec */ |
226 | cli(); | 228 | spin_lock_irqsave(&riscom_lock, flags); |
227 | rc_out(bp, CD180_GIVR, RC_ID); /* Set ID for this chip */ | 229 | rc_out(bp, CD180_GIVR, RC_ID); /* Set ID for this chip */ |
228 | rc_out(bp, CD180_GICR, 0); /* Clear all bits */ | 230 | rc_out(bp, CD180_GICR, 0); /* Clear all bits */ |
229 | rc_out(bp, CD180_PILR1, RC_ACK_MINT); /* Prio for modem intr */ | 231 | rc_out(bp, CD180_PILR1, RC_ACK_MINT); /* Prio for modem intr */ |
@@ -234,7 +236,7 @@ static void __init rc_init_CD180(struct riscom_board const * bp) | |||
234 | rc_out(bp, CD180_PPRH, (RC_OSCFREQ/(1000000/RISCOM_TPS)) >> 8); | 236 | rc_out(bp, CD180_PPRH, (RC_OSCFREQ/(1000000/RISCOM_TPS)) >> 8); |
235 | rc_out(bp, CD180_PPRL, (RC_OSCFREQ/(1000000/RISCOM_TPS)) & 0xff); | 237 | rc_out(bp, CD180_PPRL, (RC_OSCFREQ/(1000000/RISCOM_TPS)) & 0xff); |
236 | 238 | ||
237 | restore_flags(flags); | 239 | spin_unlock_irqrestore(&riscom_lock, flags); |
238 | } | 240 | } |
239 | 241 | ||
240 | /* Main probing routine, also sets irq. */ | 242 | /* Main probing routine, also sets irq. */ |
@@ -310,12 +312,6 @@ out_release: | |||
310 | * | 312 | * |
311 | */ | 313 | */ |
312 | 314 | ||
313 | static inline void rc_mark_event(struct riscom_port * port, int event) | ||
314 | { | ||
315 | set_bit(event, &port->event); | ||
316 | schedule_work(&port->tqueue); | ||
317 | } | ||
318 | |||
319 | static inline struct riscom_port * rc_get_port(struct riscom_board const * bp, | 315 | static inline struct riscom_port * rc_get_port(struct riscom_board const * bp, |
320 | unsigned char const * what) | 316 | unsigned char const * what) |
321 | { | 317 | { |
@@ -482,7 +478,7 @@ static inline void rc_transmit(struct riscom_board const * bp) | |||
482 | rc_out(bp, CD180_IER, port->IER); | 478 | rc_out(bp, CD180_IER, port->IER); |
483 | } | 479 | } |
484 | if (port->xmit_cnt <= port->wakeup_chars) | 480 | if (port->xmit_cnt <= port->wakeup_chars) |
485 | rc_mark_event(port, RS_EVENT_WRITE_WAKEUP); | 481 | tty_wakeup(tty); |
486 | } | 482 | } |
487 | 483 | ||
488 | static inline void rc_check_modem(struct riscom_board const * bp) | 484 | static inline void rc_check_modem(struct riscom_board const * bp) |
@@ -501,7 +497,7 @@ static inline void rc_check_modem(struct riscom_board const * bp) | |||
501 | if (rc_in(bp, CD180_MSVR) & MSVR_CD) | 497 | if (rc_in(bp, CD180_MSVR) & MSVR_CD) |
502 | wake_up_interruptible(&port->open_wait); | 498 | wake_up_interruptible(&port->open_wait); |
503 | else | 499 | else |
504 | schedule_work(&port->tqueue_hangup); | 500 | tty_hangup(tty); |
505 | } | 501 | } |
506 | 502 | ||
507 | #ifdef RISCOM_BRAIN_DAMAGED_CTS | 503 | #ifdef RISCOM_BRAIN_DAMAGED_CTS |
@@ -510,7 +506,7 @@ static inline void rc_check_modem(struct riscom_board const * bp) | |||
510 | tty->hw_stopped = 0; | 506 | tty->hw_stopped = 0; |
511 | port->IER |= IER_TXRDY; | 507 | port->IER |= IER_TXRDY; |
512 | if (port->xmit_cnt <= port->wakeup_chars) | 508 | if (port->xmit_cnt <= port->wakeup_chars) |
513 | rc_mark_event(port, RS_EVENT_WRITE_WAKEUP); | 509 | tty_wakeup(tty); |
514 | } else { | 510 | } else { |
515 | tty->hw_stopped = 1; | 511 | tty->hw_stopped = 1; |
516 | port->IER &= ~IER_TXRDY; | 512 | port->IER &= ~IER_TXRDY; |
@@ -522,7 +518,7 @@ static inline void rc_check_modem(struct riscom_board const * bp) | |||
522 | tty->hw_stopped = 0; | 518 | tty->hw_stopped = 0; |
523 | port->IER |= IER_TXRDY; | 519 | port->IER |= IER_TXRDY; |
524 | if (port->xmit_cnt <= port->wakeup_chars) | 520 | if (port->xmit_cnt <= port->wakeup_chars) |
525 | rc_mark_event(port, RS_EVENT_WRITE_WAKEUP); | 521 | tty_wakeup(tty); |
526 | } else { | 522 | } else { |
527 | tty->hw_stopped = 1; | 523 | tty->hw_stopped = 1; |
528 | port->IER &= ~IER_TXRDY; | 524 | port->IER &= ~IER_TXRDY; |
@@ -812,9 +808,9 @@ static int rc_setup_port(struct riscom_board *bp, struct riscom_port *port) | |||
812 | } | 808 | } |
813 | port->xmit_buf = (unsigned char *) tmp; | 809 | port->xmit_buf = (unsigned char *) tmp; |
814 | } | 810 | } |
815 | 811 | ||
816 | save_flags(flags); cli(); | 812 | spin_lock_irqsave(&riscom_lock, flags); |
817 | 813 | ||
818 | if (port->tty) | 814 | if (port->tty) |
819 | clear_bit(TTY_IO_ERROR, &port->tty->flags); | 815 | clear_bit(TTY_IO_ERROR, &port->tty->flags); |
820 | 816 | ||
@@ -825,7 +821,7 @@ static int rc_setup_port(struct riscom_board *bp, struct riscom_port *port) | |||
825 | rc_change_speed(bp, port); | 821 | rc_change_speed(bp, port); |
826 | port->flags |= ASYNC_INITIALIZED; | 822 | port->flags |= ASYNC_INITIALIZED; |
827 | 823 | ||
828 | restore_flags(flags); | 824 | spin_unlock_irqrestore(&riscom_lock, flags); |
829 | return 0; | 825 | return 0; |
830 | } | 826 | } |
831 | 827 | ||
@@ -901,6 +897,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, | |||
901 | int retval; | 897 | int retval; |
902 | int do_clocal = 0; | 898 | int do_clocal = 0; |
903 | int CD; | 899 | int CD; |
900 | unsigned long flags; | ||
904 | 901 | ||
905 | /* | 902 | /* |
906 | * If the device is in the middle of being closed, then block | 903 | * If the device is in the middle of being closed, then block |
@@ -936,19 +933,26 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, | |||
936 | */ | 933 | */ |
937 | retval = 0; | 934 | retval = 0; |
938 | add_wait_queue(&port->open_wait, &wait); | 935 | add_wait_queue(&port->open_wait, &wait); |
939 | cli(); | 936 | |
937 | spin_lock_irqsave(&riscom_lock, flags); | ||
938 | |||
940 | if (!tty_hung_up_p(filp)) | 939 | if (!tty_hung_up_p(filp)) |
941 | port->count--; | 940 | port->count--; |
942 | sti(); | 941 | |
942 | spin_unlock_irqrestore(&riscom_lock, flags); | ||
943 | |||
943 | port->blocked_open++; | 944 | port->blocked_open++; |
944 | while (1) { | 945 | while (1) { |
945 | cli(); | 946 | spin_lock_irqsave(&riscom_lock, flags); |
947 | |||
946 | rc_out(bp, CD180_CAR, port_No(port)); | 948 | rc_out(bp, CD180_CAR, port_No(port)); |
947 | CD = rc_in(bp, CD180_MSVR) & MSVR_CD; | 949 | CD = rc_in(bp, CD180_MSVR) & MSVR_CD; |
948 | rc_out(bp, CD180_MSVR, MSVR_RTS); | 950 | rc_out(bp, CD180_MSVR, MSVR_RTS); |
949 | bp->DTR &= ~(1u << port_No(port)); | 951 | bp->DTR &= ~(1u << port_No(port)); |
950 | rc_out(bp, RC_DTR, bp->DTR); | 952 | rc_out(bp, RC_DTR, bp->DTR); |
951 | sti(); | 953 | |
954 | spin_unlock_irqrestore(&riscom_lock, flags); | ||
955 | |||
952 | set_current_state(TASK_INTERRUPTIBLE); | 956 | set_current_state(TASK_INTERRUPTIBLE); |
953 | if (tty_hung_up_p(filp) || | 957 | if (tty_hung_up_p(filp) || |
954 | !(port->flags & ASYNC_INITIALIZED)) { | 958 | !(port->flags & ASYNC_INITIALIZED)) { |
@@ -1020,8 +1024,9 @@ static void rc_close(struct tty_struct * tty, struct file * filp) | |||
1020 | 1024 | ||
1021 | if (!port || rc_paranoia_check(port, tty->name, "close")) | 1025 | if (!port || rc_paranoia_check(port, tty->name, "close")) |
1022 | return; | 1026 | return; |
1023 | 1027 | ||
1024 | save_flags(flags); cli(); | 1028 | spin_lock_irqsave(&riscom_lock, flags); |
1029 | |||
1025 | if (tty_hung_up_p(filp)) | 1030 | if (tty_hung_up_p(filp)) |
1026 | goto out; | 1031 | goto out; |
1027 | 1032 | ||
@@ -1078,7 +1083,6 @@ static void rc_close(struct tty_struct * tty, struct file * filp) | |||
1078 | tty_ldisc_flush(tty); | 1083 | tty_ldisc_flush(tty); |
1079 | 1084 | ||
1080 | tty->closing = 0; | 1085 | tty->closing = 0; |
1081 | port->event = 0; | ||
1082 | port->tty = NULL; | 1086 | port->tty = NULL; |
1083 | if (port->blocked_open) { | 1087 | if (port->blocked_open) { |
1084 | if (port->close_delay) { | 1088 | if (port->close_delay) { |
@@ -1088,7 +1092,9 @@ static void rc_close(struct tty_struct * tty, struct file * filp) | |||
1088 | } | 1092 | } |
1089 | port->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); | 1093 | port->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); |
1090 | wake_up_interruptible(&port->close_wait); | 1094 | wake_up_interruptible(&port->close_wait); |
1091 | out: restore_flags(flags); | 1095 | |
1096 | out: | ||
1097 | spin_unlock_irqrestore(&riscom_lock, flags); | ||
1092 | } | 1098 | } |
1093 | 1099 | ||
1094 | static int rc_write(struct tty_struct * tty, | 1100 | static int rc_write(struct tty_struct * tty, |
@@ -1107,34 +1113,33 @@ static int rc_write(struct tty_struct * tty, | |||
1107 | if (!tty || !port->xmit_buf) | 1113 | if (!tty || !port->xmit_buf) |
1108 | return 0; | 1114 | return 0; |
1109 | 1115 | ||
1110 | save_flags(flags); | ||
1111 | while (1) { | 1116 | while (1) { |
1112 | cli(); | 1117 | spin_lock_irqsave(&riscom_lock, flags); |
1118 | |||
1113 | c = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1, | 1119 | c = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1, |
1114 | SERIAL_XMIT_SIZE - port->xmit_head)); | 1120 | SERIAL_XMIT_SIZE - port->xmit_head)); |
1115 | if (c <= 0) { | 1121 | if (c <= 0) |
1116 | restore_flags(flags); | 1122 | break; /* lock continues to be held */ |
1117 | break; | ||
1118 | } | ||
1119 | 1123 | ||
1120 | memcpy(port->xmit_buf + port->xmit_head, buf, c); | 1124 | memcpy(port->xmit_buf + port->xmit_head, buf, c); |
1121 | port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1); | 1125 | port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1); |
1122 | port->xmit_cnt += c; | 1126 | port->xmit_cnt += c; |
1123 | restore_flags(flags); | 1127 | |
1128 | spin_unlock_irqrestore(&riscom_lock, flags); | ||
1124 | 1129 | ||
1125 | buf += c; | 1130 | buf += c; |
1126 | count -= c; | 1131 | count -= c; |
1127 | total += c; | 1132 | total += c; |
1128 | } | 1133 | } |
1129 | 1134 | ||
1130 | cli(); | ||
1131 | if (port->xmit_cnt && !tty->stopped && !tty->hw_stopped && | 1135 | if (port->xmit_cnt && !tty->stopped && !tty->hw_stopped && |
1132 | !(port->IER & IER_TXRDY)) { | 1136 | !(port->IER & IER_TXRDY)) { |
1133 | port->IER |= IER_TXRDY; | 1137 | port->IER |= IER_TXRDY; |
1134 | rc_out(bp, CD180_CAR, port_No(port)); | 1138 | rc_out(bp, CD180_CAR, port_No(port)); |
1135 | rc_out(bp, CD180_IER, port->IER); | 1139 | rc_out(bp, CD180_IER, port->IER); |
1136 | } | 1140 | } |
1137 | restore_flags(flags); | 1141 | |
1142 | spin_unlock_irqrestore(&riscom_lock, flags); | ||
1138 | 1143 | ||
1139 | return total; | 1144 | return total; |
1140 | } | 1145 | } |
@@ -1150,7 +1155,7 @@ static void rc_put_char(struct tty_struct * tty, unsigned char ch) | |||
1150 | if (!tty || !port->xmit_buf) | 1155 | if (!tty || !port->xmit_buf) |
1151 | return; | 1156 | return; |
1152 | 1157 | ||
1153 | save_flags(flags); cli(); | 1158 | spin_lock_irqsave(&riscom_lock, flags); |
1154 | 1159 | ||
1155 | if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1) | 1160 | if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1) |
1156 | goto out; | 1161 | goto out; |
@@ -1158,7 +1163,9 @@ static void rc_put_char(struct tty_struct * tty, unsigned char ch) | |||
1158 | port->xmit_buf[port->xmit_head++] = ch; | 1163 | port->xmit_buf[port->xmit_head++] = ch; |
1159 | port->xmit_head &= SERIAL_XMIT_SIZE - 1; | 1164 | port->xmit_head &= SERIAL_XMIT_SIZE - 1; |
1160 | port->xmit_cnt++; | 1165 | port->xmit_cnt++; |
1161 | out: restore_flags(flags); | 1166 | |
1167 | out: | ||
1168 | spin_unlock_irqrestore(&riscom_lock, flags); | ||
1162 | } | 1169 | } |
1163 | 1170 | ||
1164 | static void rc_flush_chars(struct tty_struct * tty) | 1171 | static void rc_flush_chars(struct tty_struct * tty) |
@@ -1173,11 +1180,13 @@ static void rc_flush_chars(struct tty_struct * tty) | |||
1173 | !port->xmit_buf) | 1180 | !port->xmit_buf) |
1174 | return; | 1181 | return; |
1175 | 1182 | ||
1176 | save_flags(flags); cli(); | 1183 | spin_lock_irqsave(&riscom_lock, flags); |
1184 | |||
1177 | port->IER |= IER_TXRDY; | 1185 | port->IER |= IER_TXRDY; |
1178 | rc_out(port_Board(port), CD180_CAR, port_No(port)); | 1186 | rc_out(port_Board(port), CD180_CAR, port_No(port)); |
1179 | rc_out(port_Board(port), CD180_IER, port->IER); | 1187 | rc_out(port_Board(port), CD180_IER, port->IER); |
1180 | restore_flags(flags); | 1188 | |
1189 | spin_unlock_irqrestore(&riscom_lock, flags); | ||
1181 | } | 1190 | } |
1182 | 1191 | ||
1183 | static int rc_write_room(struct tty_struct * tty) | 1192 | static int rc_write_room(struct tty_struct * tty) |
@@ -1212,9 +1221,11 @@ static void rc_flush_buffer(struct tty_struct *tty) | |||
1212 | if (rc_paranoia_check(port, tty->name, "rc_flush_buffer")) | 1221 | if (rc_paranoia_check(port, tty->name, "rc_flush_buffer")) |
1213 | return; | 1222 | return; |
1214 | 1223 | ||
1215 | save_flags(flags); cli(); | 1224 | spin_lock_irqsave(&riscom_lock, flags); |
1225 | |||
1216 | port->xmit_cnt = port->xmit_head = port->xmit_tail = 0; | 1226 | port->xmit_cnt = port->xmit_head = port->xmit_tail = 0; |
1217 | restore_flags(flags); | 1227 | |
1228 | spin_unlock_irqrestore(&riscom_lock, flags); | ||
1218 | 1229 | ||
1219 | tty_wakeup(tty); | 1230 | tty_wakeup(tty); |
1220 | } | 1231 | } |
@@ -1231,11 +1242,15 @@ static int rc_tiocmget(struct tty_struct *tty, struct file *file) | |||
1231 | return -ENODEV; | 1242 | return -ENODEV; |
1232 | 1243 | ||
1233 | bp = port_Board(port); | 1244 | bp = port_Board(port); |
1234 | save_flags(flags); cli(); | 1245 | |
1246 | spin_lock_irqsave(&riscom_lock, flags); | ||
1247 | |||
1235 | rc_out(bp, CD180_CAR, port_No(port)); | 1248 | rc_out(bp, CD180_CAR, port_No(port)); |
1236 | status = rc_in(bp, CD180_MSVR); | 1249 | status = rc_in(bp, CD180_MSVR); |
1237 | result = rc_in(bp, RC_RI) & (1u << port_No(port)) ? 0 : TIOCM_RNG; | 1250 | result = rc_in(bp, RC_RI) & (1u << port_No(port)) ? 0 : TIOCM_RNG; |
1238 | restore_flags(flags); | 1251 | |
1252 | spin_unlock_irqrestore(&riscom_lock, flags); | ||
1253 | |||
1239 | result |= ((status & MSVR_RTS) ? TIOCM_RTS : 0) | 1254 | result |= ((status & MSVR_RTS) ? TIOCM_RTS : 0) |
1240 | | ((status & MSVR_DTR) ? TIOCM_DTR : 0) | 1255 | | ((status & MSVR_DTR) ? TIOCM_DTR : 0) |
1241 | | ((status & MSVR_CD) ? TIOCM_CAR : 0) | 1256 | | ((status & MSVR_CD) ? TIOCM_CAR : 0) |
@@ -1256,7 +1271,8 @@ static int rc_tiocmset(struct tty_struct *tty, struct file *file, | |||
1256 | 1271 | ||
1257 | bp = port_Board(port); | 1272 | bp = port_Board(port); |
1258 | 1273 | ||
1259 | save_flags(flags); cli(); | 1274 | spin_lock_irqsave(&riscom_lock, flags); |
1275 | |||
1260 | if (set & TIOCM_RTS) | 1276 | if (set & TIOCM_RTS) |
1261 | port->MSVR |= MSVR_RTS; | 1277 | port->MSVR |= MSVR_RTS; |
1262 | if (set & TIOCM_DTR) | 1278 | if (set & TIOCM_DTR) |
@@ -1270,7 +1286,9 @@ static int rc_tiocmset(struct tty_struct *tty, struct file *file, | |||
1270 | rc_out(bp, CD180_CAR, port_No(port)); | 1286 | rc_out(bp, CD180_CAR, port_No(port)); |
1271 | rc_out(bp, CD180_MSVR, port->MSVR); | 1287 | rc_out(bp, CD180_MSVR, port->MSVR); |
1272 | rc_out(bp, RC_DTR, bp->DTR); | 1288 | rc_out(bp, RC_DTR, bp->DTR); |
1273 | restore_flags(flags); | 1289 | |
1290 | spin_unlock_irqrestore(&riscom_lock, flags); | ||
1291 | |||
1274 | return 0; | 1292 | return 0; |
1275 | } | 1293 | } |
1276 | 1294 | ||
@@ -1279,7 +1297,8 @@ static inline void rc_send_break(struct riscom_port * port, unsigned long length | |||
1279 | struct riscom_board *bp = port_Board(port); | 1297 | struct riscom_board *bp = port_Board(port); |
1280 | unsigned long flags; | 1298 | unsigned long flags; |
1281 | 1299 | ||
1282 | save_flags(flags); cli(); | 1300 | spin_lock_irqsave(&riscom_lock, flags); |
1301 | |||
1283 | port->break_length = RISCOM_TPS / HZ * length; | 1302 | port->break_length = RISCOM_TPS / HZ * length; |
1284 | port->COR2 |= COR2_ETC; | 1303 | port->COR2 |= COR2_ETC; |
1285 | port->IER |= IER_TXRDY; | 1304 | port->IER |= IER_TXRDY; |
@@ -1289,7 +1308,8 @@ static inline void rc_send_break(struct riscom_port * port, unsigned long length | |||
1289 | rc_wait_CCR(bp); | 1308 | rc_wait_CCR(bp); |
1290 | rc_out(bp, CD180_CCR, CCR_CORCHG2); | 1309 | rc_out(bp, CD180_CCR, CCR_CORCHG2); |
1291 | rc_wait_CCR(bp); | 1310 | rc_wait_CCR(bp); |
1292 | restore_flags(flags); | 1311 | |
1312 | spin_unlock_irqrestore(&riscom_lock, flags); | ||
1293 | } | 1313 | } |
1294 | 1314 | ||
1295 | static inline int rc_set_serial_info(struct riscom_port * port, | 1315 | static inline int rc_set_serial_info(struct riscom_port * port, |
@@ -1298,7 +1318,6 @@ static inline int rc_set_serial_info(struct riscom_port * port, | |||
1298 | struct serial_struct tmp; | 1318 | struct serial_struct tmp; |
1299 | struct riscom_board *bp = port_Board(port); | 1319 | struct riscom_board *bp = port_Board(port); |
1300 | int change_speed; | 1320 | int change_speed; |
1301 | unsigned long flags; | ||
1302 | 1321 | ||
1303 | if (copy_from_user(&tmp, newinfo, sizeof(tmp))) | 1322 | if (copy_from_user(&tmp, newinfo, sizeof(tmp))) |
1304 | return -EFAULT; | 1323 | return -EFAULT; |
@@ -1332,9 +1351,11 @@ static inline int rc_set_serial_info(struct riscom_port * port, | |||
1332 | port->closing_wait = tmp.closing_wait; | 1351 | port->closing_wait = tmp.closing_wait; |
1333 | } | 1352 | } |
1334 | if (change_speed) { | 1353 | if (change_speed) { |
1335 | save_flags(flags); cli(); | 1354 | unsigned long flags; |
1355 | |||
1356 | spin_lock_irqsave(&riscom_lock, flags); | ||
1336 | rc_change_speed(bp, port); | 1357 | rc_change_speed(bp, port); |
1337 | restore_flags(flags); | 1358 | spin_unlock_irqrestore(&riscom_lock, flags); |
1338 | } | 1359 | } |
1339 | return 0; | 1360 | return 0; |
1340 | } | 1361 | } |
@@ -1414,17 +1435,19 @@ static void rc_throttle(struct tty_struct * tty) | |||
1414 | return; | 1435 | return; |
1415 | 1436 | ||
1416 | bp = port_Board(port); | 1437 | bp = port_Board(port); |
1417 | 1438 | ||
1418 | save_flags(flags); cli(); | 1439 | spin_lock_irqsave(&riscom_lock, flags); |
1440 | |||
1419 | port->MSVR &= ~MSVR_RTS; | 1441 | port->MSVR &= ~MSVR_RTS; |
1420 | rc_out(bp, CD180_CAR, port_No(port)); | 1442 | rc_out(bp, CD180_CAR, port_No(port)); |
1421 | if (I_IXOFF(tty)) { | 1443 | if (I_IXOFF(tty)) { |
1422 | rc_wait_CCR(bp); | 1444 | rc_wait_CCR(bp); |
1423 | rc_out(bp, CD180_CCR, CCR_SSCH2); | 1445 | rc_out(bp, CD180_CCR, CCR_SSCH2); |
1424 | rc_wait_CCR(bp); | 1446 | rc_wait_CCR(bp); |
1425 | } | 1447 | } |
1426 | rc_out(bp, CD180_MSVR, port->MSVR); | 1448 | rc_out(bp, CD180_MSVR, port->MSVR); |
1427 | restore_flags(flags); | 1449 | |
1450 | spin_unlock_irqrestore(&riscom_lock, flags); | ||
1428 | } | 1451 | } |
1429 | 1452 | ||
1430 | static void rc_unthrottle(struct tty_struct * tty) | 1453 | static void rc_unthrottle(struct tty_struct * tty) |
@@ -1438,7 +1461,8 @@ static void rc_unthrottle(struct tty_struct * tty) | |||
1438 | 1461 | ||
1439 | bp = port_Board(port); | 1462 | bp = port_Board(port); |
1440 | 1463 | ||
1441 | save_flags(flags); cli(); | 1464 | spin_lock_irqsave(&riscom_lock, flags); |
1465 | |||
1442 | port->MSVR |= MSVR_RTS; | 1466 | port->MSVR |= MSVR_RTS; |
1443 | rc_out(bp, CD180_CAR, port_No(port)); | 1467 | rc_out(bp, CD180_CAR, port_No(port)); |
1444 | if (I_IXOFF(tty)) { | 1468 | if (I_IXOFF(tty)) { |
@@ -1447,7 +1471,8 @@ static void rc_unthrottle(struct tty_struct * tty) | |||
1447 | rc_wait_CCR(bp); | 1471 | rc_wait_CCR(bp); |
1448 | } | 1472 | } |
1449 | rc_out(bp, CD180_MSVR, port->MSVR); | 1473 | rc_out(bp, CD180_MSVR, port->MSVR); |
1450 | restore_flags(flags); | 1474 | |
1475 | spin_unlock_irqrestore(&riscom_lock, flags); | ||
1451 | } | 1476 | } |
1452 | 1477 | ||
1453 | static void rc_stop(struct tty_struct * tty) | 1478 | static void rc_stop(struct tty_struct * tty) |
@@ -1461,11 +1486,13 @@ static void rc_stop(struct tty_struct * tty) | |||
1461 | 1486 | ||
1462 | bp = port_Board(port); | 1487 | bp = port_Board(port); |
1463 | 1488 | ||
1464 | save_flags(flags); cli(); | 1489 | spin_lock_irqsave(&riscom_lock, flags); |
1490 | |||
1465 | port->IER &= ~IER_TXRDY; | 1491 | port->IER &= ~IER_TXRDY; |
1466 | rc_out(bp, CD180_CAR, port_No(port)); | 1492 | rc_out(bp, CD180_CAR, port_No(port)); |
1467 | rc_out(bp, CD180_IER, port->IER); | 1493 | rc_out(bp, CD180_IER, port->IER); |
1468 | restore_flags(flags); | 1494 | |
1495 | spin_unlock_irqrestore(&riscom_lock, flags); | ||
1469 | } | 1496 | } |
1470 | 1497 | ||
1471 | static void rc_start(struct tty_struct * tty) | 1498 | static void rc_start(struct tty_struct * tty) |
@@ -1479,32 +1506,15 @@ static void rc_start(struct tty_struct * tty) | |||
1479 | 1506 | ||
1480 | bp = port_Board(port); | 1507 | bp = port_Board(port); |
1481 | 1508 | ||
1482 | save_flags(flags); cli(); | 1509 | spin_lock_irqsave(&riscom_lock, flags); |
1510 | |||
1483 | if (port->xmit_cnt && port->xmit_buf && !(port->IER & IER_TXRDY)) { | 1511 | if (port->xmit_cnt && port->xmit_buf && !(port->IER & IER_TXRDY)) { |
1484 | port->IER |= IER_TXRDY; | 1512 | port->IER |= IER_TXRDY; |
1485 | rc_out(bp, CD180_CAR, port_No(port)); | 1513 | rc_out(bp, CD180_CAR, port_No(port)); |
1486 | rc_out(bp, CD180_IER, port->IER); | 1514 | rc_out(bp, CD180_IER, port->IER); |
1487 | } | 1515 | } |
1488 | restore_flags(flags); | ||
1489 | } | ||
1490 | 1516 | ||
1491 | /* | 1517 | spin_unlock_irqrestore(&riscom_lock, flags); |
1492 | * This routine is called from the work queue when the interrupt | ||
1493 | * routine has signalled that a hangup has occurred. The path of | ||
1494 | * hangup processing is: | ||
1495 | * | ||
1496 | * serial interrupt routine -> (workqueue) -> | ||
1497 | * do_rc_hangup() -> tty->hangup() -> rc_hangup() | ||
1498 | * | ||
1499 | */ | ||
1500 | static void do_rc_hangup(struct work_struct *ugly_api) | ||
1501 | { | ||
1502 | struct riscom_port *port = container_of(ugly_api, struct riscom_port, tqueue_hangup); | ||
1503 | struct tty_struct *tty; | ||
1504 | |||
1505 | tty = port->tty; | ||
1506 | if (tty) | ||
1507 | tty_hangup(tty); /* FIXME: module removal race still here */ | ||
1508 | } | 1518 | } |
1509 | 1519 | ||
1510 | static void rc_hangup(struct tty_struct * tty) | 1520 | static void rc_hangup(struct tty_struct * tty) |
@@ -1518,7 +1528,6 @@ static void rc_hangup(struct tty_struct * tty) | |||
1518 | bp = port_Board(port); | 1528 | bp = port_Board(port); |
1519 | 1529 | ||
1520 | rc_shutdown_port(bp, port); | 1530 | rc_shutdown_port(bp, port); |
1521 | port->event = 0; | ||
1522 | port->count = 0; | 1531 | port->count = 0; |
1523 | port->flags &= ~ASYNC_NORMAL_ACTIVE; | 1532 | port->flags &= ~ASYNC_NORMAL_ACTIVE; |
1524 | port->tty = NULL; | 1533 | port->tty = NULL; |
@@ -1537,9 +1546,9 @@ static void rc_set_termios(struct tty_struct * tty, struct ktermios * old_termio | |||
1537 | tty->termios->c_iflag == old_termios->c_iflag) | 1546 | tty->termios->c_iflag == old_termios->c_iflag) |
1538 | return; | 1547 | return; |
1539 | 1548 | ||
1540 | save_flags(flags); cli(); | 1549 | spin_lock_irqsave(&riscom_lock, flags); |
1541 | rc_change_speed(port_Board(port), port); | 1550 | rc_change_speed(port_Board(port), port); |
1542 | restore_flags(flags); | 1551 | spin_unlock_irqrestore(&riscom_lock, flags); |
1543 | 1552 | ||
1544 | if ((old_termios->c_cflag & CRTSCTS) && | 1553 | if ((old_termios->c_cflag & CRTSCTS) && |
1545 | !(tty->termios->c_cflag & CRTSCTS)) { | 1554 | !(tty->termios->c_cflag & CRTSCTS)) { |
@@ -1548,18 +1557,6 @@ static void rc_set_termios(struct tty_struct * tty, struct ktermios * old_termio | |||
1548 | } | 1557 | } |
1549 | } | 1558 | } |
1550 | 1559 | ||
1551 | static void do_softint(struct work_struct *ugly_api) | ||
1552 | { | ||
1553 | struct riscom_port *port = container_of(ugly_api, struct riscom_port, tqueue); | ||
1554 | struct tty_struct *tty; | ||
1555 | |||
1556 | if(!(tty = port->tty)) | ||
1557 | return; | ||
1558 | |||
1559 | if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &port->event)) | ||
1560 | tty_wakeup(tty); | ||
1561 | } | ||
1562 | |||
1563 | static const struct tty_operations riscom_ops = { | 1560 | static const struct tty_operations riscom_ops = { |
1564 | .open = rc_open, | 1561 | .open = rc_open, |
1565 | .close = rc_close, | 1562 | .close = rc_close, |
@@ -1580,7 +1577,7 @@ static const struct tty_operations riscom_ops = { | |||
1580 | .tiocmset = rc_tiocmset, | 1577 | .tiocmset = rc_tiocmset, |
1581 | }; | 1578 | }; |
1582 | 1579 | ||
1583 | static inline int rc_init_drivers(void) | 1580 | static int __init rc_init_drivers(void) |
1584 | { | 1581 | { |
1585 | int error; | 1582 | int error; |
1586 | int i; | 1583 | int i; |
@@ -1612,8 +1609,6 @@ static inline int rc_init_drivers(void) | |||
1612 | memset(rc_port, 0, sizeof(rc_port)); | 1609 | memset(rc_port, 0, sizeof(rc_port)); |
1613 | for (i = 0; i < RC_NPORT * RC_NBOARD; i++) { | 1610 | for (i = 0; i < RC_NPORT * RC_NBOARD; i++) { |
1614 | rc_port[i].magic = RISCOM8_MAGIC; | 1611 | rc_port[i].magic = RISCOM8_MAGIC; |
1615 | INIT_WORK(&rc_port[i].tqueue, do_softint); | ||
1616 | INIT_WORK(&rc_port[i].tqueue_hangup, do_rc_hangup); | ||
1617 | rc_port[i].close_delay = 50 * HZ/100; | 1612 | rc_port[i].close_delay = 50 * HZ/100; |
1618 | rc_port[i].closing_wait = 3000 * HZ/100; | 1613 | rc_port[i].closing_wait = 3000 * HZ/100; |
1619 | init_waitqueue_head(&rc_port[i].open_wait); | 1614 | init_waitqueue_head(&rc_port[i].open_wait); |
@@ -1627,11 +1622,12 @@ static void rc_release_drivers(void) | |||
1627 | { | 1622 | { |
1628 | unsigned long flags; | 1623 | unsigned long flags; |
1629 | 1624 | ||
1630 | save_flags(flags); | 1625 | spin_lock_irqsave(&riscom_lock, flags); |
1631 | cli(); | 1626 | |
1632 | tty_unregister_driver(riscom_driver); | 1627 | tty_unregister_driver(riscom_driver); |
1633 | put_tty_driver(riscom_driver); | 1628 | put_tty_driver(riscom_driver); |
1634 | restore_flags(flags); | 1629 | |
1630 | spin_unlock_irqrestore(&riscom_lock, flags); | ||
1635 | } | 1631 | } |
1636 | 1632 | ||
1637 | #ifndef MODULE | 1633 | #ifndef MODULE |
diff --git a/drivers/char/riscom8.h b/drivers/char/riscom8.h index 9cc1313d5e67..cdfdf4394477 100644 --- a/drivers/char/riscom8.h +++ b/drivers/char/riscom8.h | |||
@@ -71,7 +71,6 @@ struct riscom_port { | |||
71 | struct tty_struct * tty; | 71 | struct tty_struct * tty; |
72 | int count; | 72 | int count; |
73 | int blocked_open; | 73 | int blocked_open; |
74 | unsigned long event; /* long req'd for set_bit --RR */ | ||
75 | int timeout; | 74 | int timeout; |
76 | int close_delay; | 75 | int close_delay; |
77 | unsigned char * xmit_buf; | 76 | unsigned char * xmit_buf; |
@@ -81,8 +80,6 @@ struct riscom_port { | |||
81 | int xmit_cnt; | 80 | int xmit_cnt; |
82 | wait_queue_head_t open_wait; | 81 | wait_queue_head_t open_wait; |
83 | wait_queue_head_t close_wait; | 82 | wait_queue_head_t close_wait; |
84 | struct work_struct tqueue; | ||
85 | struct work_struct tqueue_hangup; | ||
86 | short wakeup_chars; | 83 | short wakeup_chars; |
87 | short break_length; | 84 | short break_length; |
88 | unsigned short closing_wait; | 85 | unsigned short closing_wait; |
diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c index d83419c3857e..68c289fe2dc2 100644 --- a/drivers/char/rocket.c +++ b/drivers/char/rocket.c | |||
@@ -40,12 +40,6 @@ | |||
40 | */ | 40 | */ |
41 | 41 | ||
42 | /****** Defines ******/ | 42 | /****** Defines ******/ |
43 | #ifdef PCI_NUM_RESOURCES | ||
44 | #define PCI_BASE_ADDRESS(dev, r) ((dev)->resource[r].start) | ||
45 | #else | ||
46 | #define PCI_BASE_ADDRESS(dev, r) ((dev)->base_address[r]) | ||
47 | #endif | ||
48 | |||
49 | #define ROCKET_PARANOIA_CHECK | 43 | #define ROCKET_PARANOIA_CHECK |
50 | #define ROCKET_DISABLE_SIMUSAGE | 44 | #define ROCKET_DISABLE_SIMUSAGE |
51 | 45 | ||
@@ -305,8 +299,8 @@ static inline int rocket_paranoia_check(struct r_port *info, | |||
305 | if (!info) | 299 | if (!info) |
306 | return 1; | 300 | return 1; |
307 | if (info->magic != RPORT_MAGIC) { | 301 | if (info->magic != RPORT_MAGIC) { |
308 | printk(KERN_INFO "Warning: bad magic number for rocketport struct in %s\n", | 302 | printk(KERN_WARNING "Warning: bad magic number for rocketport " |
309 | routine); | 303 | "struct in %s\n", routine); |
310 | return 1; | 304 | return 1; |
311 | } | 305 | } |
312 | #endif | 306 | #endif |
@@ -328,7 +322,7 @@ static void rp_do_receive(struct r_port *info, | |||
328 | 322 | ||
329 | ToRecv = sGetRxCnt(cp); | 323 | ToRecv = sGetRxCnt(cp); |
330 | #ifdef ROCKET_DEBUG_INTR | 324 | #ifdef ROCKET_DEBUG_INTR |
331 | printk(KERN_INFO "rp_do_receive(%d)...", ToRecv); | 325 | printk(KERN_INFO "rp_do_receive(%d)...\n", ToRecv); |
332 | #endif | 326 | #endif |
333 | if (ToRecv == 0) | 327 | if (ToRecv == 0) |
334 | return; | 328 | return; |
@@ -341,7 +335,7 @@ static void rp_do_receive(struct r_port *info, | |||
341 | if (ChanStatus & (RXFOVERFL | RXBREAK | RXFRAME | RXPARITY)) { | 335 | if (ChanStatus & (RXFOVERFL | RXBREAK | RXFRAME | RXPARITY)) { |
342 | if (!(ChanStatus & STATMODE)) { | 336 | if (!(ChanStatus & STATMODE)) { |
343 | #ifdef ROCKET_DEBUG_RECEIVE | 337 | #ifdef ROCKET_DEBUG_RECEIVE |
344 | printk(KERN_INFO "Entering STATMODE..."); | 338 | printk(KERN_INFO "Entering STATMODE...\n"); |
345 | #endif | 339 | #endif |
346 | ChanStatus |= STATMODE; | 340 | ChanStatus |= STATMODE; |
347 | sEnRxStatusMode(cp); | 341 | sEnRxStatusMode(cp); |
@@ -355,15 +349,15 @@ static void rp_do_receive(struct r_port *info, | |||
355 | */ | 349 | */ |
356 | if (ChanStatus & STATMODE) { | 350 | if (ChanStatus & STATMODE) { |
357 | #ifdef ROCKET_DEBUG_RECEIVE | 351 | #ifdef ROCKET_DEBUG_RECEIVE |
358 | printk(KERN_INFO "Ignore %x, read %x...", info->ignore_status_mask, | 352 | printk(KERN_INFO "Ignore %x, read %x...\n", |
359 | info->read_status_mask); | 353 | info->ignore_status_mask, info->read_status_mask); |
360 | #endif | 354 | #endif |
361 | while (ToRecv) { | 355 | while (ToRecv) { |
362 | char flag; | 356 | char flag; |
363 | 357 | ||
364 | CharNStat = sInW(sGetTxRxDataIO(cp)); | 358 | CharNStat = sInW(sGetTxRxDataIO(cp)); |
365 | #ifdef ROCKET_DEBUG_RECEIVE | 359 | #ifdef ROCKET_DEBUG_RECEIVE |
366 | printk(KERN_INFO "%x...", CharNStat); | 360 | printk(KERN_INFO "%x...\n", CharNStat); |
367 | #endif | 361 | #endif |
368 | if (CharNStat & STMBREAKH) | 362 | if (CharNStat & STMBREAKH) |
369 | CharNStat &= ~(STMFRAMEH | STMPARITYH); | 363 | CharNStat &= ~(STMFRAMEH | STMPARITYH); |
@@ -435,12 +429,13 @@ static void rp_do_transmit(struct r_port *info) | |||
435 | unsigned long flags; | 429 | unsigned long flags; |
436 | 430 | ||
437 | #ifdef ROCKET_DEBUG_INTR | 431 | #ifdef ROCKET_DEBUG_INTR |
438 | printk(KERN_INFO "rp_do_transmit "); | 432 | printk(KERN_DEBUG "%s\n", __func__); |
439 | #endif | 433 | #endif |
440 | if (!info) | 434 | if (!info) |
441 | return; | 435 | return; |
442 | if (!info->tty) { | 436 | if (!info->tty) { |
443 | printk(KERN_INFO "rp: WARNING rp_do_transmit called with info->tty==NULL\n"); | 437 | printk(KERN_WARNING "rp: WARNING %s called with " |
438 | "info->tty==NULL\n", __func__); | ||
444 | clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]); | 439 | clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]); |
445 | return; | 440 | return; |
446 | } | 441 | } |
@@ -464,7 +459,7 @@ static void rp_do_transmit(struct r_port *info) | |||
464 | info->xmit_cnt -= c; | 459 | info->xmit_cnt -= c; |
465 | info->xmit_fifo_room -= c; | 460 | info->xmit_fifo_room -= c; |
466 | #ifdef ROCKET_DEBUG_INTR | 461 | #ifdef ROCKET_DEBUG_INTR |
467 | printk(KERN_INFO "tx %d chars...", c); | 462 | printk(KERN_INFO "tx %d chars...\n", c); |
468 | #endif | 463 | #endif |
469 | } | 464 | } |
470 | 465 | ||
@@ -481,7 +476,7 @@ static void rp_do_transmit(struct r_port *info) | |||
481 | spin_unlock_irqrestore(&info->slock, flags); | 476 | spin_unlock_irqrestore(&info->slock, flags); |
482 | 477 | ||
483 | #ifdef ROCKET_DEBUG_INTR | 478 | #ifdef ROCKET_DEBUG_INTR |
484 | printk(KERN_INFO "(%d,%d,%d,%d)...", info->xmit_cnt, info->xmit_head, | 479 | printk(KERN_DEBUG "(%d,%d,%d,%d)...\n", info->xmit_cnt, info->xmit_head, |
485 | info->xmit_tail, info->xmit_fifo_room); | 480 | info->xmit_tail, info->xmit_fifo_room); |
486 | #endif | 481 | #endif |
487 | } | 482 | } |
@@ -501,11 +496,13 @@ static void rp_handle_port(struct r_port *info) | |||
501 | return; | 496 | return; |
502 | 497 | ||
503 | if ((info->flags & ROCKET_INITIALIZED) == 0) { | 498 | if ((info->flags & ROCKET_INITIALIZED) == 0) { |
504 | printk(KERN_INFO "rp: WARNING: rp_handle_port called with info->flags & NOT_INIT\n"); | 499 | printk(KERN_WARNING "rp: WARNING: rp_handle_port called with " |
500 | "info->flags & NOT_INIT\n"); | ||
505 | return; | 501 | return; |
506 | } | 502 | } |
507 | if (!info->tty) { | 503 | if (!info->tty) { |
508 | printk(KERN_INFO "rp: WARNING: rp_handle_port called with info->tty==NULL\n"); | 504 | printk(KERN_WARNING "rp: WARNING: rp_handle_port called with " |
505 | "info->tty==NULL\n"); | ||
509 | return; | 506 | return; |
510 | } | 507 | } |
511 | cp = &info->channel; | 508 | cp = &info->channel; |
@@ -513,7 +510,7 @@ static void rp_handle_port(struct r_port *info) | |||
513 | 510 | ||
514 | IntMask = sGetChanIntID(cp) & info->intmask; | 511 | IntMask = sGetChanIntID(cp) & info->intmask; |
515 | #ifdef ROCKET_DEBUG_INTR | 512 | #ifdef ROCKET_DEBUG_INTR |
516 | printk(KERN_INFO "rp_interrupt %02x...", IntMask); | 513 | printk(KERN_INFO "rp_interrupt %02x...\n", IntMask); |
517 | #endif | 514 | #endif |
518 | ChanStatus = sGetChanStatus(cp); | 515 | ChanStatus = sGetChanStatus(cp); |
519 | if (IntMask & RXF_TRIG) { /* Rx FIFO trigger level */ | 516 | if (IntMask & RXF_TRIG) { /* Rx FIFO trigger level */ |
@@ -521,7 +518,7 @@ static void rp_handle_port(struct r_port *info) | |||
521 | } | 518 | } |
522 | if (IntMask & DELTA_CD) { /* CD change */ | 519 | if (IntMask & DELTA_CD) { /* CD change */ |
523 | #if (defined(ROCKET_DEBUG_OPEN) || defined(ROCKET_DEBUG_INTR) || defined(ROCKET_DEBUG_HANGUP)) | 520 | #if (defined(ROCKET_DEBUG_OPEN) || defined(ROCKET_DEBUG_INTR) || defined(ROCKET_DEBUG_HANGUP)) |
524 | printk(KERN_INFO "ttyR%d CD now %s...", info->line, | 521 | printk(KERN_INFO "ttyR%d CD now %s...\n", info->line, |
525 | (ChanStatus & CD_ACT) ? "on" : "off"); | 522 | (ChanStatus & CD_ACT) ? "on" : "off"); |
526 | #endif | 523 | #endif |
527 | if (!(ChanStatus & CD_ACT) && info->cd_status) { | 524 | if (!(ChanStatus & CD_ACT) && info->cd_status) { |
@@ -638,7 +635,8 @@ static void init_r_port(int board, int aiop, int chan, struct pci_dev *pci_dev) | |||
638 | /* Get a r_port struct for the port, fill it in and save it globally, indexed by line number */ | 635 | /* Get a r_port struct for the port, fill it in and save it globally, indexed by line number */ |
639 | info = kzalloc(sizeof (struct r_port), GFP_KERNEL); | 636 | info = kzalloc(sizeof (struct r_port), GFP_KERNEL); |
640 | if (!info) { | 637 | if (!info) { |
641 | printk(KERN_INFO "Couldn't allocate info struct for line #%d\n", line); | 638 | printk(KERN_ERR "Couldn't allocate info struct for line #%d\n", |
639 | line); | ||
642 | return; | 640 | return; |
643 | } | 641 | } |
644 | 642 | ||
@@ -668,7 +666,8 @@ static void init_r_port(int board, int aiop, int chan, struct pci_dev *pci_dev) | |||
668 | 666 | ||
669 | info->intmask = RXF_TRIG | TXFIFO_MT | SRC_INT | DELTA_CD | DELTA_CTS | DELTA_DSR; | 667 | info->intmask = RXF_TRIG | TXFIFO_MT | SRC_INT | DELTA_CD | DELTA_CTS | DELTA_DSR; |
670 | if (sInitChan(ctlp, &info->channel, aiop, chan) == 0) { | 668 | if (sInitChan(ctlp, &info->channel, aiop, chan) == 0) { |
671 | printk(KERN_INFO "RocketPort sInitChan(%d, %d, %d) failed!\n", board, aiop, chan); | 669 | printk(KERN_ERR "RocketPort sInitChan(%d, %d, %d) failed!\n", |
670 | board, aiop, chan); | ||
672 | kfree(info); | 671 | kfree(info); |
673 | return; | 672 | return; |
674 | } | 673 | } |
@@ -976,7 +975,7 @@ static int rp_open(struct tty_struct *tty, struct file *filp) | |||
976 | CHANNEL_t *cp; | 975 | CHANNEL_t *cp; |
977 | unsigned long page; | 976 | unsigned long page; |
978 | 977 | ||
979 | line = TTY_GET_LINE(tty); | 978 | line = tty->index; |
980 | if ((line < 0) || (line >= MAX_RP_PORTS) || ((info = rp_table[line]) == NULL)) | 979 | if ((line < 0) || (line >= MAX_RP_PORTS) || ((info = rp_table[line]) == NULL)) |
981 | return -ENXIO; | 980 | return -ENXIO; |
982 | 981 | ||
@@ -1007,7 +1006,8 @@ static int rp_open(struct tty_struct *tty, struct file *filp) | |||
1007 | atomic_inc(&rp_num_ports_open); | 1006 | atomic_inc(&rp_num_ports_open); |
1008 | 1007 | ||
1009 | #ifdef ROCKET_DEBUG_OPEN | 1008 | #ifdef ROCKET_DEBUG_OPEN |
1010 | printk(KERN_INFO "rocket mod++ = %d...", atomic_read(&rp_num_ports_open)); | 1009 | printk(KERN_INFO "rocket mod++ = %d...\n", |
1010 | atomic_read(&rp_num_ports_open)); | ||
1011 | #endif | 1011 | #endif |
1012 | } | 1012 | } |
1013 | #ifdef ROCKET_DEBUG_OPEN | 1013 | #ifdef ROCKET_DEBUG_OPEN |
@@ -1103,13 +1103,13 @@ static void rp_close(struct tty_struct *tty, struct file *filp) | |||
1103 | * one, we've got real problems, since it means the | 1103 | * one, we've got real problems, since it means the |
1104 | * serial port won't be shutdown. | 1104 | * serial port won't be shutdown. |
1105 | */ | 1105 | */ |
1106 | printk(KERN_INFO "rp_close: bad serial port count; tty->count is 1, " | 1106 | printk(KERN_WARNING "rp_close: bad serial port count; " |
1107 | "info->count is %d\n", info->count); | 1107 | "tty->count is 1, info->count is %d\n", info->count); |
1108 | info->count = 1; | 1108 | info->count = 1; |
1109 | } | 1109 | } |
1110 | if (--info->count < 0) { | 1110 | if (--info->count < 0) { |
1111 | printk(KERN_INFO "rp_close: bad serial port count for ttyR%d: %d\n", | 1111 | printk(KERN_WARNING "rp_close: bad serial port count for " |
1112 | info->line, info->count); | 1112 | "ttyR%d: %d\n", info->line, info->count); |
1113 | info->count = 0; | 1113 | info->count = 0; |
1114 | } | 1114 | } |
1115 | if (info->count) { | 1115 | if (info->count) { |
@@ -1160,8 +1160,7 @@ static void rp_close(struct tty_struct *tty, struct file *filp) | |||
1160 | if (C_HUPCL(tty)) | 1160 | if (C_HUPCL(tty)) |
1161 | sClrDTR(cp); | 1161 | sClrDTR(cp); |
1162 | 1162 | ||
1163 | if (TTY_DRIVER_FLUSH_BUFFER_EXISTS(tty)) | 1163 | rp_flush_buffer(tty); |
1164 | TTY_DRIVER_FLUSH_BUFFER(tty); | ||
1165 | 1164 | ||
1166 | tty_ldisc_flush(tty); | 1165 | tty_ldisc_flush(tty); |
1167 | 1166 | ||
@@ -1184,7 +1183,8 @@ static void rp_close(struct tty_struct *tty, struct file *filp) | |||
1184 | atomic_dec(&rp_num_ports_open); | 1183 | atomic_dec(&rp_num_ports_open); |
1185 | 1184 | ||
1186 | #ifdef ROCKET_DEBUG_OPEN | 1185 | #ifdef ROCKET_DEBUG_OPEN |
1187 | printk(KERN_INFO "rocket mod-- = %d...", atomic_read(&rp_num_ports_open)); | 1186 | printk(KERN_INFO "rocket mod-- = %d...\n", |
1187 | atomic_read(&rp_num_ports_open)); | ||
1188 | printk(KERN_INFO "rp_close ttyR%d complete shutdown\n", info->line); | 1188 | printk(KERN_INFO "rp_close ttyR%d complete shutdown\n", info->line); |
1189 | #endif | 1189 | #endif |
1190 | 1190 | ||
@@ -1569,9 +1569,9 @@ static void rp_wait_until_sent(struct tty_struct *tty, int timeout) | |||
1569 | 1569 | ||
1570 | orig_jiffies = jiffies; | 1570 | orig_jiffies = jiffies; |
1571 | #ifdef ROCKET_DEBUG_WAIT_UNTIL_SENT | 1571 | #ifdef ROCKET_DEBUG_WAIT_UNTIL_SENT |
1572 | printk(KERN_INFO "In RP_wait_until_sent(%d) (jiff=%lu)...", timeout, | 1572 | printk(KERN_INFO "In RP_wait_until_sent(%d) (jiff=%lu)...\n", timeout, |
1573 | jiffies); | 1573 | jiffies); |
1574 | printk(KERN_INFO "cps=%d...", info->cps); | 1574 | printk(KERN_INFO "cps=%d...\n", info->cps); |
1575 | #endif | 1575 | #endif |
1576 | while (1) { | 1576 | while (1) { |
1577 | txcnt = sGetTxCnt(cp); | 1577 | txcnt = sGetTxCnt(cp); |
@@ -1592,7 +1592,8 @@ static void rp_wait_until_sent(struct tty_struct *tty, int timeout) | |||
1592 | if (check_time == 0) | 1592 | if (check_time == 0) |
1593 | check_time = 1; | 1593 | check_time = 1; |
1594 | #ifdef ROCKET_DEBUG_WAIT_UNTIL_SENT | 1594 | #ifdef ROCKET_DEBUG_WAIT_UNTIL_SENT |
1595 | printk(KERN_INFO "txcnt = %d (jiff=%lu,check=%d)...", txcnt, jiffies, check_time); | 1595 | printk(KERN_INFO "txcnt = %d (jiff=%lu,check=%d)...\n", txcnt, |
1596 | jiffies, check_time); | ||
1596 | #endif | 1597 | #endif |
1597 | msleep_interruptible(jiffies_to_msecs(check_time)); | 1598 | msleep_interruptible(jiffies_to_msecs(check_time)); |
1598 | if (signal_pending(current)) | 1599 | if (signal_pending(current)) |
@@ -1616,7 +1617,7 @@ static void rp_hangup(struct tty_struct *tty) | |||
1616 | return; | 1617 | return; |
1617 | 1618 | ||
1618 | #if (defined(ROCKET_DEBUG_OPEN) || defined(ROCKET_DEBUG_HANGUP)) | 1619 | #if (defined(ROCKET_DEBUG_OPEN) || defined(ROCKET_DEBUG_HANGUP)) |
1619 | printk(KERN_INFO "rp_hangup of ttyR%d...", info->line); | 1620 | printk(KERN_INFO "rp_hangup of ttyR%d...\n", info->line); |
1620 | #endif | 1621 | #endif |
1621 | rp_flush_buffer(tty); | 1622 | rp_flush_buffer(tty); |
1622 | if (info->flags & ROCKET_CLOSING) | 1623 | if (info->flags & ROCKET_CLOSING) |
@@ -1664,7 +1665,7 @@ static void rp_put_char(struct tty_struct *tty, unsigned char ch) | |||
1664 | mutex_lock(&info->write_mtx); | 1665 | mutex_lock(&info->write_mtx); |
1665 | 1666 | ||
1666 | #ifdef ROCKET_DEBUG_WRITE | 1667 | #ifdef ROCKET_DEBUG_WRITE |
1667 | printk(KERN_INFO "rp_put_char %c...", ch); | 1668 | printk(KERN_INFO "rp_put_char %c...\n", ch); |
1668 | #endif | 1669 | #endif |
1669 | 1670 | ||
1670 | spin_lock_irqsave(&info->slock, flags); | 1671 | spin_lock_irqsave(&info->slock, flags); |
@@ -1709,7 +1710,7 @@ static int rp_write(struct tty_struct *tty, | |||
1709 | return -ERESTARTSYS; | 1710 | return -ERESTARTSYS; |
1710 | 1711 | ||
1711 | #ifdef ROCKET_DEBUG_WRITE | 1712 | #ifdef ROCKET_DEBUG_WRITE |
1712 | printk(KERN_INFO "rp_write %d chars...", count); | 1713 | printk(KERN_INFO "rp_write %d chars...\n", count); |
1713 | #endif | 1714 | #endif |
1714 | cp = &info->channel; | 1715 | cp = &info->channel; |
1715 | 1716 | ||
@@ -1798,7 +1799,7 @@ static int rp_write_room(struct tty_struct *tty) | |||
1798 | if (ret < 0) | 1799 | if (ret < 0) |
1799 | ret = 0; | 1800 | ret = 0; |
1800 | #ifdef ROCKET_DEBUG_WRITE | 1801 | #ifdef ROCKET_DEBUG_WRITE |
1801 | printk(KERN_INFO "rp_write_room returns %d...", ret); | 1802 | printk(KERN_INFO "rp_write_room returns %d...\n", ret); |
1802 | #endif | 1803 | #endif |
1803 | return ret; | 1804 | return ret; |
1804 | } | 1805 | } |
@@ -1818,7 +1819,7 @@ static int rp_chars_in_buffer(struct tty_struct *tty) | |||
1818 | cp = &info->channel; | 1819 | cp = &info->channel; |
1819 | 1820 | ||
1820 | #ifdef ROCKET_DEBUG_WRITE | 1821 | #ifdef ROCKET_DEBUG_WRITE |
1821 | printk(KERN_INFO "rp_chars_in_buffer returns %d...", info->xmit_cnt); | 1822 | printk(KERN_INFO "rp_chars_in_buffer returns %d...\n", info->xmit_cnt); |
1822 | #endif | 1823 | #endif |
1823 | return info->xmit_cnt; | 1824 | return info->xmit_cnt; |
1824 | } | 1825 | } |
@@ -2161,14 +2162,11 @@ static __init int register_PCI(int i, struct pci_dev *dev) | |||
2161 | for (aiop = 0; aiop < max_num_aiops; aiop++) | 2162 | for (aiop = 0; aiop < max_num_aiops; aiop++) |
2162 | ctlp->AiopNumChan[aiop] = ports_per_aiop; | 2163 | ctlp->AiopNumChan[aiop] = ports_per_aiop; |
2163 | 2164 | ||
2164 | printk("Comtrol PCI controller #%d ID 0x%x found in bus:slot:fn %s at address %04lx, " | 2165 | dev_info(&dev->dev, "comtrol PCI controller #%d found at " |
2165 | "%d AIOP(s) (%s)\n", i, dev->device, pci_name(dev), | 2166 | "address %04lx, %d AIOP(s) (%s), creating ttyR%d - %ld\n", |
2166 | rcktpt_io_addr[i], num_aiops, rocketModel[i].modelString); | 2167 | i, rcktpt_io_addr[i], num_aiops, rocketModel[i].modelString, |
2167 | printk(KERN_INFO "Installing %s, creating /dev/ttyR%d - %ld\n", | 2168 | rocketModel[i].startingPortNumber, |
2168 | rocketModel[i].modelString, | 2169 | rocketModel[i].startingPortNumber + rocketModel[i].numPorts-1); |
2169 | rocketModel[i].startingPortNumber, | ||
2170 | rocketModel[i].startingPortNumber + | ||
2171 | rocketModel[i].numPorts - 1); | ||
2172 | 2170 | ||
2173 | if (num_aiops <= 0) { | 2171 | if (num_aiops <= 0) { |
2174 | rcktpt_io_addr[i] = 0; | 2172 | rcktpt_io_addr[i] = 0; |
@@ -2191,10 +2189,10 @@ static __init int register_PCI(int i, struct pci_dev *dev) | |||
2191 | num_chan = ports_per_aiop; | 2189 | num_chan = ports_per_aiop; |
2192 | for (chan = 0; chan < num_chan; chan++) | 2190 | for (chan = 0; chan < num_chan; chan++) |
2193 | sPCIModemReset(ctlp, chan, 1); | 2191 | sPCIModemReset(ctlp, chan, 1); |
2194 | mdelay(500); | 2192 | msleep(500); |
2195 | for (chan = 0; chan < num_chan; chan++) | 2193 | for (chan = 0; chan < num_chan; chan++) |
2196 | sPCIModemReset(ctlp, chan, 0); | 2194 | sPCIModemReset(ctlp, chan, 0); |
2197 | mdelay(500); | 2195 | msleep(500); |
2198 | rmSpeakerReset(ctlp, rocketModel[i].model); | 2196 | rmSpeakerReset(ctlp, rocketModel[i].model); |
2199 | } | 2197 | } |
2200 | return (1); | 2198 | return (1); |
@@ -2240,7 +2238,9 @@ static int __init init_ISA(int i) | |||
2240 | 2238 | ||
2241 | /* Reserve the IO region */ | 2239 | /* Reserve the IO region */ |
2242 | if (!request_region(rcktpt_io_addr[i], 64, "Comtrol RocketPort")) { | 2240 | if (!request_region(rcktpt_io_addr[i], 64, "Comtrol RocketPort")) { |
2243 | printk(KERN_INFO "Unable to reserve IO region for configured ISA RocketPort at address 0x%lx, board not installed...\n", rcktpt_io_addr[i]); | 2241 | printk(KERN_ERR "Unable to reserve IO region for configured " |
2242 | "ISA RocketPort at address 0x%lx, board not " | ||
2243 | "installed...\n", rcktpt_io_addr[i]); | ||
2244 | rcktpt_io_addr[i] = 0; | 2244 | rcktpt_io_addr[i] = 0; |
2245 | return (0); | 2245 | return (0); |
2246 | } | 2246 | } |
@@ -2309,10 +2309,10 @@ static int __init init_ISA(int i) | |||
2309 | total_num_chan = num_chan; | 2309 | total_num_chan = num_chan; |
2310 | for (chan = 0; chan < num_chan; chan++) | 2310 | for (chan = 0; chan < num_chan; chan++) |
2311 | sModemReset(ctlp, chan, 1); | 2311 | sModemReset(ctlp, chan, 1); |
2312 | mdelay(500); | 2312 | msleep(500); |
2313 | for (chan = 0; chan < num_chan; chan++) | 2313 | for (chan = 0; chan < num_chan; chan++) |
2314 | sModemReset(ctlp, chan, 0); | 2314 | sModemReset(ctlp, chan, 0); |
2315 | mdelay(500); | 2315 | msleep(500); |
2316 | strcpy(rocketModel[i].modelString, "RocketModem ISA"); | 2316 | strcpy(rocketModel[i].modelString, "RocketModem ISA"); |
2317 | } else { | 2317 | } else { |
2318 | strcpy(rocketModel[i].modelString, "RocketPort ISA"); | 2318 | strcpy(rocketModel[i].modelString, "RocketPort ISA"); |
@@ -2480,7 +2480,7 @@ static void rp_cleanup_module(void) | |||
2480 | 2480 | ||
2481 | retval = tty_unregister_driver(rocket_driver); | 2481 | retval = tty_unregister_driver(rocket_driver); |
2482 | if (retval) | 2482 | if (retval) |
2483 | printk(KERN_INFO "Error %d while trying to unregister " | 2483 | printk(KERN_ERR "Error %d while trying to unregister " |
2484 | "rocketport driver\n", -retval); | 2484 | "rocketport driver\n", -retval); |
2485 | 2485 | ||
2486 | for (i = 0; i < MAX_RP_PORTS; i++) | 2486 | for (i = 0; i < MAX_RP_PORTS; i++) |
diff --git a/drivers/char/rocket_int.h b/drivers/char/rocket_int.h index 55b8f2d71a96..f3a75791b811 100644 --- a/drivers/char/rocket_int.h +++ b/drivers/char/rocket_int.h | |||
@@ -42,7 +42,7 @@ typedef unsigned int DWordIO_t; | |||
42 | static inline void sOutB(unsigned short port, unsigned char value) | 42 | static inline void sOutB(unsigned short port, unsigned char value) |
43 | { | 43 | { |
44 | #ifdef ROCKET_DEBUG_IO | 44 | #ifdef ROCKET_DEBUG_IO |
45 | printk("sOutB(%x, %x)...", port, value); | 45 | printk(KERN_DEBUG "sOutB(%x, %x)...\n", port, value); |
46 | #endif | 46 | #endif |
47 | outb_p(value, port); | 47 | outb_p(value, port); |
48 | } | 48 | } |
@@ -50,7 +50,7 @@ static inline void sOutB(unsigned short port, unsigned char value) | |||
50 | static inline void sOutW(unsigned short port, unsigned short value) | 50 | static inline void sOutW(unsigned short port, unsigned short value) |
51 | { | 51 | { |
52 | #ifdef ROCKET_DEBUG_IO | 52 | #ifdef ROCKET_DEBUG_IO |
53 | printk("sOutW(%x, %x)...", port, value); | 53 | printk(KERN_DEBUG "sOutW(%x, %x)...\n", port, value); |
54 | #endif | 54 | #endif |
55 | outw_p(value, port); | 55 | outw_p(value, port); |
56 | } | 56 | } |
@@ -58,7 +58,7 @@ static inline void sOutW(unsigned short port, unsigned short value) | |||
58 | static inline void sOutDW(unsigned short port, unsigned long value) | 58 | static inline void sOutDW(unsigned short port, unsigned long value) |
59 | { | 59 | { |
60 | #ifdef ROCKET_DEBUG_IO | 60 | #ifdef ROCKET_DEBUG_IO |
61 | printk("sOutDW(%x, %lx)...", port, value); | 61 | printk(KERN_DEBUG "sOutDW(%x, %lx)...\n", port, value); |
62 | #endif | 62 | #endif |
63 | outl_p(cpu_to_le32(value), port); | 63 | outl_p(cpu_to_le32(value), port); |
64 | } | 64 | } |
@@ -105,12 +105,6 @@ static inline unsigned short sInW(unsigned short port) | |||
105 | #define AIOPID_NULL -1 /* no AIOP or channel exists */ | 105 | #define AIOPID_NULL -1 /* no AIOP or channel exists */ |
106 | #define AIOPID_0001 0x0001 /* AIOP release 1 */ | 106 | #define AIOPID_0001 0x0001 /* AIOP release 1 */ |
107 | 107 | ||
108 | #define NULLDEV -1 /* identifies non-existant device */ | ||
109 | #define NULLCTL -1 /* identifies non-existant controller */ | ||
110 | #define NULLCTLPTR (CONTROLLER_T *)0 /* identifies non-existant controller */ | ||
111 | #define NULLAIOP -1 /* identifies non-existant AIOP */ | ||
112 | #define NULLCHAN -1 /* identifies non-existant channel */ | ||
113 | |||
114 | /************************************************************************ | 108 | /************************************************************************ |
115 | Global Register Offsets - Direct Access - Fixed values | 109 | Global Register Offsets - Direct Access - Fixed values |
116 | ************************************************************************/ | 110 | ************************************************************************/ |
@@ -1187,9 +1181,6 @@ struct r_port { | |||
1187 | #define ROCKET_CLOSING 0x40000000 /* Serial port is closing */ | 1181 | #define ROCKET_CLOSING 0x40000000 /* Serial port is closing */ |
1188 | #define ROCKET_NORMAL_ACTIVE 0x20000000 /* Normal port is active */ | 1182 | #define ROCKET_NORMAL_ACTIVE 0x20000000 /* Normal port is active */ |
1189 | 1183 | ||
1190 | /* tty subtypes */ | ||
1191 | #define SERIAL_TYPE_NORMAL 1 | ||
1192 | |||
1193 | /* | 1184 | /* |
1194 | * Assigned major numbers for the Comtrol Rocketport | 1185 | * Assigned major numbers for the Comtrol Rocketport |
1195 | */ | 1186 | */ |
@@ -1240,12 +1231,3 @@ struct r_port { | |||
1240 | /* Compact PCI device */ | 1231 | /* Compact PCI device */ |
1241 | #define PCI_DEVICE_ID_CRP16INTF 0x0903 /* Rocketport Compact PCI 16 port w/external I/F */ | 1232 | #define PCI_DEVICE_ID_CRP16INTF 0x0903 /* Rocketport Compact PCI 16 port w/external I/F */ |
1242 | 1233 | ||
1243 | #define TTY_GET_LINE(t) t->index | ||
1244 | #define TTY_DRIVER_MINOR_START(t) t->driver->minor_start | ||
1245 | #define TTY_DRIVER_SUBTYPE(t) t->driver->subtype | ||
1246 | #define TTY_DRIVER_NAME(t) t->driver->name | ||
1247 | #define TTY_DRIVER_NAME_BASE(t) t->driver->name_base | ||
1248 | #define TTY_DRIVER_FLUSH_BUFFER_EXISTS(t) t->driver->flush_buffer | ||
1249 | #define TTY_DRIVER_FLUSH_BUFFER(t) t->driver->flush_buffer(t) | ||
1250 | |||
1251 | |||
diff --git a/drivers/char/ser_a2232.c b/drivers/char/ser_a2232.c index 3c869145bfdc..4ba3aec9e1cd 100644 --- a/drivers/char/ser_a2232.c +++ b/drivers/char/ser_a2232.c | |||
@@ -653,7 +653,7 @@ static void a2232_init_portstructs(void) | |||
653 | port->gs.closing_wait = 30 * HZ; | 653 | port->gs.closing_wait = 30 * HZ; |
654 | port->gs.rd = &a2232_real_driver; | 654 | port->gs.rd = &a2232_real_driver; |
655 | #ifdef NEW_WRITE_LOCKING | 655 | #ifdef NEW_WRITE_LOCKING |
656 | init_MUTEX(&(port->gs.port_write_mutex)); | 656 | mutex_init(&(port->gs.port_write_mutex)); |
657 | #endif | 657 | #endif |
658 | init_waitqueue_head(&port->gs.open_wait); | 658 | init_waitqueue_head(&port->gs.open_wait); |
659 | init_waitqueue_head(&port->gs.close_wait); | 659 | init_waitqueue_head(&port->gs.close_wait); |
diff --git a/drivers/char/serial167.c b/drivers/char/serial167.c index f1497cecffd8..df8cd0ca97eb 100644 --- a/drivers/char/serial167.c +++ b/drivers/char/serial167.c | |||
@@ -90,8 +90,6 @@ | |||
90 | 90 | ||
91 | #define STD_COM_FLAGS (0) | 91 | #define STD_COM_FLAGS (0) |
92 | 92 | ||
93 | #define SERIAL_TYPE_NORMAL 1 | ||
94 | |||
95 | static struct tty_driver *cy_serial_driver; | 93 | static struct tty_driver *cy_serial_driver; |
96 | extern int serial_console; | 94 | extern int serial_console; |
97 | static struct cyclades_port *serial_console_info = NULL; | 95 | static struct cyclades_port *serial_console_info = NULL; |
@@ -359,18 +357,6 @@ static void cy_start(struct tty_struct *tty) | |||
359 | local_irq_restore(flags); | 357 | local_irq_restore(flags); |
360 | } /* cy_start */ | 358 | } /* cy_start */ |
361 | 359 | ||
362 | /* | ||
363 | * This routine is used by the interrupt handler to schedule | ||
364 | * processing in the software interrupt portion of the driver | ||
365 | * (also known as the "bottom half"). This can be called any | ||
366 | * number of times for any channel without harm. | ||
367 | */ | ||
368 | static inline void cy_sched_event(struct cyclades_port *info, int event) | ||
369 | { | ||
370 | info->event |= 1 << event; /* remember what kind of event and who */ | ||
371 | schedule_work(&info->tqueue); | ||
372 | } /* cy_sched_event */ | ||
373 | |||
374 | /* The real interrupt service routines are called | 360 | /* The real interrupt service routines are called |
375 | whenever the card wants its hand held--chars | 361 | whenever the card wants its hand held--chars |
376 | received, out buffer empty, modem change, etc. | 362 | received, out buffer empty, modem change, etc. |
@@ -485,10 +471,12 @@ static irqreturn_t cd2401_modem_interrupt(int irq, void *dev_id) | |||
485 | && (info->flags & ASYNC_CHECK_CD)) { | 471 | && (info->flags & ASYNC_CHECK_CD)) { |
486 | if (mdm_status & CyDCD) { | 472 | if (mdm_status & CyDCD) { |
487 | /* CP('!'); */ | 473 | /* CP('!'); */ |
488 | cy_sched_event(info, Cy_EVENT_OPEN_WAKEUP); | 474 | wake_up_interruptible(&info->open_wait); |
489 | } else { | 475 | } else { |
490 | /* CP('@'); */ | 476 | /* CP('@'); */ |
491 | cy_sched_event(info, Cy_EVENT_HANGUP); | 477 | tty_hangup(info->tty); |
478 | wake_up_interruptible(&info->open_wait); | ||
479 | info->flags &= ~ASYNC_NORMAL_ACTIVE; | ||
492 | } | 480 | } |
493 | } | 481 | } |
494 | if ((mdm_change & CyCTS) | 482 | if ((mdm_change & CyCTS) |
@@ -498,8 +486,7 @@ static irqreturn_t cd2401_modem_interrupt(int irq, void *dev_id) | |||
498 | /* !!! cy_start isn't used because... */ | 486 | /* !!! cy_start isn't used because... */ |
499 | info->tty->stopped = 0; | 487 | info->tty->stopped = 0; |
500 | base_addr[CyIER] |= CyTxMpty; | 488 | base_addr[CyIER] |= CyTxMpty; |
501 | cy_sched_event(info, | 489 | tty_wakeup(info->tty); |
502 | Cy_EVENT_WRITE_WAKEUP); | ||
503 | } | 490 | } |
504 | } else { | 491 | } else { |
505 | if (!(mdm_status & CyCTS)) { | 492 | if (!(mdm_status & CyCTS)) { |
@@ -545,9 +532,6 @@ static irqreturn_t cd2401_tx_interrupt(int irq, void *dev_id) | |||
545 | info->last_active = jiffies; | 532 | info->last_active = jiffies; |
546 | if (info->tty == 0) { | 533 | if (info->tty == 0) { |
547 | base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy); | 534 | base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy); |
548 | if (info->xmit_cnt < WAKEUP_CHARS) { | ||
549 | cy_sched_event(info, Cy_EVENT_WRITE_WAKEUP); | ||
550 | } | ||
551 | base_addr[CyTEOIR] = CyNOTRANS; | 535 | base_addr[CyTEOIR] = CyNOTRANS; |
552 | return IRQ_HANDLED; | 536 | return IRQ_HANDLED; |
553 | } | 537 | } |
@@ -629,9 +613,9 @@ static irqreturn_t cd2401_tx_interrupt(int irq, void *dev_id) | |||
629 | } | 613 | } |
630 | } | 614 | } |
631 | 615 | ||
632 | if (info->xmit_cnt < WAKEUP_CHARS) { | 616 | if (info->xmit_cnt < WAKEUP_CHARS) |
633 | cy_sched_event(info, Cy_EVENT_WRITE_WAKEUP); | 617 | tty_wakeup(info->tty); |
634 | } | 618 | |
635 | base_addr[CyTEOIR] = (char_count != saved_cnt) ? 0 : CyNOTRANS; | 619 | base_addr[CyTEOIR] = (char_count != saved_cnt) ? 0 : CyNOTRANS; |
636 | return IRQ_HANDLED; | 620 | return IRQ_HANDLED; |
637 | } /* cy_tx_interrupt */ | 621 | } /* cy_tx_interrupt */ |
@@ -692,49 +676,6 @@ static irqreturn_t cd2401_rx_interrupt(int irq, void *dev_id) | |||
692 | return IRQ_HANDLED; | 676 | return IRQ_HANDLED; |
693 | } /* cy_rx_interrupt */ | 677 | } /* cy_rx_interrupt */ |
694 | 678 | ||
695 | /* | ||
696 | * This routine is used to handle the "bottom half" processing for the | ||
697 | * serial driver, known also the "software interrupt" processing. | ||
698 | * This processing is done at the kernel interrupt level, after the | ||
699 | * cy#/_interrupt() has returned, BUT WITH INTERRUPTS TURNED ON. This | ||
700 | * is where time-consuming activities which can not be done in the | ||
701 | * interrupt driver proper are done; the interrupt driver schedules | ||
702 | * them using cy_sched_event(), and they get done here. | ||
703 | * | ||
704 | * This is done through one level of indirection--the task queue. | ||
705 | * When a hardware interrupt service routine wants service by the | ||
706 | * driver's bottom half, it enqueues the appropriate tq_struct (one | ||
707 | * per port) to the keventd work queue and sets a request flag | ||
708 | * that the work queue be processed. | ||
709 | * | ||
710 | * Although this may seem unwieldy, it gives the system a way to | ||
711 | * pass an argument (in this case the pointer to the cyclades_port | ||
712 | * structure) to the bottom half of the driver. Previous kernels | ||
713 | * had to poll every port to see if that port needed servicing. | ||
714 | */ | ||
715 | static void do_softint(struct work_struct *ugly_api) | ||
716 | { | ||
717 | struct cyclades_port *info = | ||
718 | container_of(ugly_api, struct cyclades_port, tqueue); | ||
719 | struct tty_struct *tty; | ||
720 | |||
721 | tty = info->tty; | ||
722 | if (!tty) | ||
723 | return; | ||
724 | |||
725 | if (test_and_clear_bit(Cy_EVENT_HANGUP, &info->event)) { | ||
726 | tty_hangup(info->tty); | ||
727 | wake_up_interruptible(&info->open_wait); | ||
728 | info->flags &= ~ASYNC_NORMAL_ACTIVE; | ||
729 | } | ||
730 | if (test_and_clear_bit(Cy_EVENT_OPEN_WAKEUP, &info->event)) { | ||
731 | wake_up_interruptible(&info->open_wait); | ||
732 | } | ||
733 | if (test_and_clear_bit(Cy_EVENT_WRITE_WAKEUP, &info->event)) { | ||
734 | tty_wakeup(tty); | ||
735 | } | ||
736 | } /* do_softint */ | ||
737 | |||
738 | /* This is called whenever a port becomes active; | 679 | /* This is called whenever a port becomes active; |
739 | interrupts are enabled and DTR & RTS are turned on. | 680 | interrupts are enabled and DTR & RTS are turned on. |
740 | */ | 681 | */ |
@@ -1745,7 +1686,6 @@ static void cy_close(struct tty_struct *tty, struct file *filp) | |||
1745 | if (tty->driver->flush_buffer) | 1686 | if (tty->driver->flush_buffer) |
1746 | tty->driver->flush_buffer(tty); | 1687 | tty->driver->flush_buffer(tty); |
1747 | tty_ldisc_flush(tty); | 1688 | tty_ldisc_flush(tty); |
1748 | info->event = 0; | ||
1749 | info->tty = NULL; | 1689 | info->tty = NULL; |
1750 | if (info->blocked_open) { | 1690 | if (info->blocked_open) { |
1751 | if (info->close_delay) { | 1691 | if (info->close_delay) { |
@@ -2236,7 +2176,6 @@ static int __init serial167_init(void) | |||
2236 | info->rco = baud_co[DefSpeed] >> 5; /* Rx CO */ | 2176 | info->rco = baud_co[DefSpeed] >> 5; /* Rx CO */ |
2237 | info->close_delay = 0; | 2177 | info->close_delay = 0; |
2238 | info->x_char = 0; | 2178 | info->x_char = 0; |
2239 | info->event = 0; | ||
2240 | info->count = 0; | 2179 | info->count = 0; |
2241 | #ifdef SERIAL_DEBUG_COUNT | 2180 | #ifdef SERIAL_DEBUG_COUNT |
2242 | printk("cyc: %d: setting count to 0\n", | 2181 | printk("cyc: %d: setting count to 0\n", |
@@ -2245,7 +2184,6 @@ static int __init serial167_init(void) | |||
2245 | info->blocked_open = 0; | 2184 | info->blocked_open = 0; |
2246 | info->default_threshold = 0; | 2185 | info->default_threshold = 0; |
2247 | info->default_timeout = 0; | 2186 | info->default_timeout = 0; |
2248 | INIT_WORK(&info->tqueue, do_softint); | ||
2249 | init_waitqueue_head(&info->open_wait); | 2187 | init_waitqueue_head(&info->open_wait); |
2250 | init_waitqueue_head(&info->close_wait); | 2188 | init_waitqueue_head(&info->close_wait); |
2251 | /* info->session */ | 2189 | /* info->session */ |
diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c index 455855631aef..c0e08c7bca2f 100644 --- a/drivers/char/specialix.c +++ b/drivers/char/specialix.c | |||
@@ -178,9 +178,6 @@ static int sx_poll = HZ; | |||
178 | ASYNC_SPD_HI | ASYNC_SPEED_VHI | ASYNC_SESSION_LOCKOUT | \ | 178 | ASYNC_SPD_HI | ASYNC_SPEED_VHI | ASYNC_SESSION_LOCKOUT | \ |
179 | ASYNC_PGRP_LOCKOUT | ASYNC_CALLOUT_NOHUP) | 179 | ASYNC_PGRP_LOCKOUT | ASYNC_CALLOUT_NOHUP) |
180 | 180 | ||
181 | #undef RS_EVENT_WRITE_WAKEUP | ||
182 | #define RS_EVENT_WRITE_WAKEUP 0 | ||
183 | |||
184 | static struct tty_driver *specialix_driver; | 181 | static struct tty_driver *specialix_driver; |
185 | 182 | ||
186 | static struct specialix_board sx_board[SX_NBOARD] = { | 183 | static struct specialix_board sx_board[SX_NBOARD] = { |
@@ -602,17 +599,6 @@ static int sx_probe(struct specialix_board *bp) | |||
602 | * Interrupt processing routines. | 599 | * Interrupt processing routines. |
603 | * */ | 600 | * */ |
604 | 601 | ||
605 | static inline void sx_mark_event(struct specialix_port * port, int event) | ||
606 | { | ||
607 | func_enter(); | ||
608 | |||
609 | set_bit(event, &port->event); | ||
610 | schedule_work(&port->tqueue); | ||
611 | |||
612 | func_exit(); | ||
613 | } | ||
614 | |||
615 | |||
616 | static inline struct specialix_port * sx_get_port(struct specialix_board * bp, | 602 | static inline struct specialix_port * sx_get_port(struct specialix_board * bp, |
617 | unsigned char const * what) | 603 | unsigned char const * what) |
618 | { | 604 | { |
@@ -809,7 +795,7 @@ static inline void sx_transmit(struct specialix_board * bp) | |||
809 | sx_out(bp, CD186x_IER, port->IER); | 795 | sx_out(bp, CD186x_IER, port->IER); |
810 | } | 796 | } |
811 | if (port->xmit_cnt <= port->wakeup_chars) | 797 | if (port->xmit_cnt <= port->wakeup_chars) |
812 | sx_mark_event(port, RS_EVENT_WRITE_WAKEUP); | 798 | tty_wakeup(tty); |
813 | 799 | ||
814 | func_exit(); | 800 | func_exit(); |
815 | } | 801 | } |
@@ -839,7 +825,7 @@ static inline void sx_check_modem(struct specialix_board * bp) | |||
839 | wake_up_interruptible(&port->open_wait); | 825 | wake_up_interruptible(&port->open_wait); |
840 | } else { | 826 | } else { |
841 | dprintk (SX_DEBUG_SIGNALS, "Sending HUP.\n"); | 827 | dprintk (SX_DEBUG_SIGNALS, "Sending HUP.\n"); |
842 | schedule_work(&port->tqueue_hangup); | 828 | tty_hangup(tty); |
843 | } | 829 | } |
844 | } | 830 | } |
845 | 831 | ||
@@ -849,7 +835,7 @@ static inline void sx_check_modem(struct specialix_board * bp) | |||
849 | tty->hw_stopped = 0; | 835 | tty->hw_stopped = 0; |
850 | port->IER |= IER_TXRDY; | 836 | port->IER |= IER_TXRDY; |
851 | if (port->xmit_cnt <= port->wakeup_chars) | 837 | if (port->xmit_cnt <= port->wakeup_chars) |
852 | sx_mark_event(port, RS_EVENT_WRITE_WAKEUP); | 838 | tty_wakeup(tty); |
853 | } else { | 839 | } else { |
854 | tty->hw_stopped = 1; | 840 | tty->hw_stopped = 1; |
855 | port->IER &= ~IER_TXRDY; | 841 | port->IER &= ~IER_TXRDY; |
@@ -861,7 +847,7 @@ static inline void sx_check_modem(struct specialix_board * bp) | |||
861 | tty->hw_stopped = 0; | 847 | tty->hw_stopped = 0; |
862 | port->IER |= IER_TXRDY; | 848 | port->IER |= IER_TXRDY; |
863 | if (port->xmit_cnt <= port->wakeup_chars) | 849 | if (port->xmit_cnt <= port->wakeup_chars) |
864 | sx_mark_event(port, RS_EVENT_WRITE_WAKEUP); | 850 | tty_wakeup(tty); |
865 | } else { | 851 | } else { |
866 | tty->hw_stopped = 1; | 852 | tty->hw_stopped = 1; |
867 | port->IER &= ~IER_TXRDY; | 853 | port->IER &= ~IER_TXRDY; |
@@ -1618,7 +1604,6 @@ static void sx_close(struct tty_struct * tty, struct file * filp) | |||
1618 | tty_ldisc_flush(tty); | 1604 | tty_ldisc_flush(tty); |
1619 | spin_lock_irqsave(&port->lock, flags); | 1605 | spin_lock_irqsave(&port->lock, flags); |
1620 | tty->closing = 0; | 1606 | tty->closing = 0; |
1621 | port->event = 0; | ||
1622 | port->tty = NULL; | 1607 | port->tty = NULL; |
1623 | spin_unlock_irqrestore(&port->lock, flags); | 1608 | spin_unlock_irqrestore(&port->lock, flags); |
1624 | if (port->blocked_open) { | 1609 | if (port->blocked_open) { |
@@ -2235,32 +2220,6 @@ static void sx_start(struct tty_struct * tty) | |||
2235 | func_exit(); | 2220 | func_exit(); |
2236 | } | 2221 | } |
2237 | 2222 | ||
2238 | |||
2239 | /* | ||
2240 | * This routine is called from the work-queue when the interrupt | ||
2241 | * routine has signalled that a hangup has occurred. The path of | ||
2242 | * hangup processing is: | ||
2243 | * | ||
2244 | * serial interrupt routine -> (workqueue) -> | ||
2245 | * do_sx_hangup() -> tty->hangup() -> sx_hangup() | ||
2246 | * | ||
2247 | */ | ||
2248 | static void do_sx_hangup(struct work_struct *work) | ||
2249 | { | ||
2250 | struct specialix_port *port = | ||
2251 | container_of(work, struct specialix_port, tqueue_hangup); | ||
2252 | struct tty_struct *tty; | ||
2253 | |||
2254 | func_enter(); | ||
2255 | |||
2256 | tty = port->tty; | ||
2257 | if (tty) | ||
2258 | tty_hangup(tty); /* FIXME: module removal race here */ | ||
2259 | |||
2260 | func_exit(); | ||
2261 | } | ||
2262 | |||
2263 | |||
2264 | static void sx_hangup(struct tty_struct * tty) | 2223 | static void sx_hangup(struct tty_struct * tty) |
2265 | { | 2224 | { |
2266 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; | 2225 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; |
@@ -2278,7 +2237,6 @@ static void sx_hangup(struct tty_struct * tty) | |||
2278 | 2237 | ||
2279 | sx_shutdown_port(bp, port); | 2238 | sx_shutdown_port(bp, port); |
2280 | spin_lock_irqsave(&port->lock, flags); | 2239 | spin_lock_irqsave(&port->lock, flags); |
2281 | port->event = 0; | ||
2282 | bp->count -= port->count; | 2240 | bp->count -= port->count; |
2283 | if (bp->count < 0) { | 2241 | if (bp->count < 0) { |
2284 | printk(KERN_ERR "sx%d: sx_hangup: bad board count: %d port: %d\n", | 2242 | printk(KERN_ERR "sx%d: sx_hangup: bad board count: %d port: %d\n", |
@@ -2320,26 +2278,6 @@ static void sx_set_termios(struct tty_struct * tty, struct ktermios * old_termio | |||
2320 | } | 2278 | } |
2321 | } | 2279 | } |
2322 | 2280 | ||
2323 | |||
2324 | static void do_softint(struct work_struct *work) | ||
2325 | { | ||
2326 | struct specialix_port *port = | ||
2327 | container_of(work, struct specialix_port, tqueue); | ||
2328 | struct tty_struct *tty; | ||
2329 | |||
2330 | func_enter(); | ||
2331 | |||
2332 | if(!(tty = port->tty)) { | ||
2333 | func_exit(); | ||
2334 | return; | ||
2335 | } | ||
2336 | |||
2337 | if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &port->event)) | ||
2338 | tty_wakeup(tty); | ||
2339 | |||
2340 | func_exit(); | ||
2341 | } | ||
2342 | |||
2343 | static const struct tty_operations sx_ops = { | 2281 | static const struct tty_operations sx_ops = { |
2344 | .open = sx_open, | 2282 | .open = sx_open, |
2345 | .close = sx_close, | 2283 | .close = sx_close, |
@@ -2397,8 +2335,6 @@ static int sx_init_drivers(void) | |||
2397 | memset(sx_port, 0, sizeof(sx_port)); | 2335 | memset(sx_port, 0, sizeof(sx_port)); |
2398 | for (i = 0; i < SX_NPORT * SX_NBOARD; i++) { | 2336 | for (i = 0; i < SX_NPORT * SX_NBOARD; i++) { |
2399 | sx_port[i].magic = SPECIALIX_MAGIC; | 2337 | sx_port[i].magic = SPECIALIX_MAGIC; |
2400 | INIT_WORK(&sx_port[i].tqueue, do_softint); | ||
2401 | INIT_WORK(&sx_port[i].tqueue_hangup, do_sx_hangup); | ||
2402 | sx_port[i].close_delay = 50 * HZ/100; | 2338 | sx_port[i].close_delay = 50 * HZ/100; |
2403 | sx_port[i].closing_wait = 3000 * HZ/100; | 2339 | sx_port[i].closing_wait = 3000 * HZ/100; |
2404 | init_waitqueue_head(&sx_port[i].open_wait); | 2340 | init_waitqueue_head(&sx_port[i].open_wait); |
diff --git a/drivers/char/specialix_io8.h b/drivers/char/specialix_io8.h index 895bd90de363..3f2f85bdf516 100644 --- a/drivers/char/specialix_io8.h +++ b/drivers/char/specialix_io8.h | |||
@@ -112,7 +112,6 @@ struct specialix_port { | |||
112 | struct tty_struct * tty; | 112 | struct tty_struct * tty; |
113 | int count; | 113 | int count; |
114 | int blocked_open; | 114 | int blocked_open; |
115 | ulong event; | ||
116 | int timeout; | 115 | int timeout; |
117 | int close_delay; | 116 | int close_delay; |
118 | unsigned char * xmit_buf; | 117 | unsigned char * xmit_buf; |
@@ -122,8 +121,6 @@ struct specialix_port { | |||
122 | int xmit_cnt; | 121 | int xmit_cnt; |
123 | wait_queue_head_t open_wait; | 122 | wait_queue_head_t open_wait; |
124 | wait_queue_head_t close_wait; | 123 | wait_queue_head_t close_wait; |
125 | struct work_struct tqueue; | ||
126 | struct work_struct tqueue_hangup; | ||
127 | short wakeup_chars; | 124 | short wakeup_chars; |
128 | short break_length; | 125 | short break_length; |
129 | unsigned short closing_wait; | 126 | unsigned short closing_wait; |
diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c index 45758d5b56ef..feac54e32a12 100644 --- a/drivers/char/stallion.c +++ b/drivers/char/stallion.c | |||
@@ -145,8 +145,7 @@ static struct stlbrd *stl_brds[STL_MAXBRDS]; | |||
145 | */ | 145 | */ |
146 | #define ASYI_TXBUSY 1 | 146 | #define ASYI_TXBUSY 1 |
147 | #define ASYI_TXLOW 2 | 147 | #define ASYI_TXLOW 2 |
148 | #define ASYI_DCDCHANGE 3 | 148 | #define ASYI_TXFLOWED 3 |
149 | #define ASYI_TXFLOWED 4 | ||
150 | 149 | ||
151 | /* | 150 | /* |
152 | * Define an array of board names as printable strings. Handy for | 151 | * Define an array of board names as printable strings. Handy for |
@@ -610,6 +609,23 @@ static const struct file_operations stl_fsiomem = { | |||
610 | 609 | ||
611 | static struct class *stallion_class; | 610 | static struct class *stallion_class; |
612 | 611 | ||
612 | static void stl_cd_change(struct stlport *portp) | ||
613 | { | ||
614 | unsigned int oldsigs = portp->sigs; | ||
615 | |||
616 | if (!portp->tty) | ||
617 | return; | ||
618 | |||
619 | portp->sigs = stl_getsignals(portp); | ||
620 | |||
621 | if ((portp->sigs & TIOCM_CD) && ((oldsigs & TIOCM_CD) == 0)) | ||
622 | wake_up_interruptible(&portp->open_wait); | ||
623 | |||
624 | if ((oldsigs & TIOCM_CD) && ((portp->sigs & TIOCM_CD) == 0)) | ||
625 | if (portp->flags & ASYNC_CHECK_CD) | ||
626 | tty_hangup(portp->tty); | ||
627 | } | ||
628 | |||
613 | /* | 629 | /* |
614 | * Check for any arguments passed in on the module load command line. | 630 | * Check for any arguments passed in on the module load command line. |
615 | */ | 631 | */ |
@@ -1771,41 +1787,6 @@ static int stl_echpci64intr(struct stlbrd *brdp) | |||
1771 | /*****************************************************************************/ | 1787 | /*****************************************************************************/ |
1772 | 1788 | ||
1773 | /* | 1789 | /* |
1774 | * Service an off-level request for some channel. | ||
1775 | */ | ||
1776 | static void stl_offintr(struct work_struct *work) | ||
1777 | { | ||
1778 | struct stlport *portp = container_of(work, struct stlport, tqueue); | ||
1779 | struct tty_struct *tty; | ||
1780 | unsigned int oldsigs; | ||
1781 | |||
1782 | pr_debug("stl_offintr(portp=%p)\n", portp); | ||
1783 | |||
1784 | if (portp == NULL) | ||
1785 | return; | ||
1786 | |||
1787 | tty = portp->tty; | ||
1788 | if (tty == NULL) | ||
1789 | return; | ||
1790 | |||
1791 | if (test_bit(ASYI_TXLOW, &portp->istate)) | ||
1792 | tty_wakeup(tty); | ||
1793 | |||
1794 | if (test_bit(ASYI_DCDCHANGE, &portp->istate)) { | ||
1795 | clear_bit(ASYI_DCDCHANGE, &portp->istate); | ||
1796 | oldsigs = portp->sigs; | ||
1797 | portp->sigs = stl_getsignals(portp); | ||
1798 | if ((portp->sigs & TIOCM_CD) && ((oldsigs & TIOCM_CD) == 0)) | ||
1799 | wake_up_interruptible(&portp->open_wait); | ||
1800 | if ((oldsigs & TIOCM_CD) && ((portp->sigs & TIOCM_CD) == 0)) | ||
1801 | if (portp->flags & ASYNC_CHECK_CD) | ||
1802 | tty_hangup(tty); /* FIXME: module removal race here - AKPM */ | ||
1803 | } | ||
1804 | } | ||
1805 | |||
1806 | /*****************************************************************************/ | ||
1807 | |||
1808 | /* | ||
1809 | * Initialize all the ports on a panel. | 1790 | * Initialize all the ports on a panel. |
1810 | */ | 1791 | */ |
1811 | 1792 | ||
@@ -1840,7 +1821,6 @@ static int __devinit stl_initports(struct stlbrd *brdp, struct stlpanel *panelp) | |||
1840 | portp->baud_base = STL_BAUDBASE; | 1821 | portp->baud_base = STL_BAUDBASE; |
1841 | portp->close_delay = STL_CLOSEDELAY; | 1822 | portp->close_delay = STL_CLOSEDELAY; |
1842 | portp->closing_wait = 30 * HZ; | 1823 | portp->closing_wait = 30 * HZ; |
1843 | INIT_WORK(&portp->tqueue, stl_offintr); | ||
1844 | init_waitqueue_head(&portp->open_wait); | 1824 | init_waitqueue_head(&portp->open_wait); |
1845 | init_waitqueue_head(&portp->close_wait); | 1825 | init_waitqueue_head(&portp->close_wait); |
1846 | portp->stats.brd = portp->brdnr; | 1826 | portp->stats.brd = portp->brdnr; |
@@ -3530,7 +3510,8 @@ static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr) | |||
3530 | if ((len == 0) || ((len < STL_TXBUFLOW) && | 3510 | if ((len == 0) || ((len < STL_TXBUFLOW) && |
3531 | (test_bit(ASYI_TXLOW, &portp->istate) == 0))) { | 3511 | (test_bit(ASYI_TXLOW, &portp->istate) == 0))) { |
3532 | set_bit(ASYI_TXLOW, &portp->istate); | 3512 | set_bit(ASYI_TXLOW, &portp->istate); |
3533 | schedule_work(&portp->tqueue); | 3513 | if (portp->tty) |
3514 | tty_wakeup(portp->tty); | ||
3534 | } | 3515 | } |
3535 | 3516 | ||
3536 | if (len == 0) { | 3517 | if (len == 0) { |
@@ -3546,7 +3527,8 @@ static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr) | |||
3546 | } else { | 3527 | } else { |
3547 | len = min(len, CD1400_TXFIFOSIZE); | 3528 | len = min(len, CD1400_TXFIFOSIZE); |
3548 | portp->stats.txtotal += len; | 3529 | portp->stats.txtotal += len; |
3549 | stlen = min(len, ((portp->tx.buf + STL_TXBUFSIZE) - tail)); | 3530 | stlen = min_t(unsigned int, len, |
3531 | (portp->tx.buf + STL_TXBUFSIZE) - tail); | ||
3550 | outb((TDR + portp->uartaddr), ioaddr); | 3532 | outb((TDR + portp->uartaddr), ioaddr); |
3551 | outsb((ioaddr + EREG_DATA), tail, stlen); | 3533 | outsb((ioaddr + EREG_DATA), tail, stlen); |
3552 | len -= stlen; | 3534 | len -= stlen; |
@@ -3599,7 +3581,7 @@ static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr) | |||
3599 | outb((RDCR + portp->uartaddr), ioaddr); | 3581 | outb((RDCR + portp->uartaddr), ioaddr); |
3600 | len = inb(ioaddr + EREG_DATA); | 3582 | len = inb(ioaddr + EREG_DATA); |
3601 | if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) { | 3583 | if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) { |
3602 | len = min(len, sizeof(stl_unwanted)); | 3584 | len = min_t(unsigned int, len, sizeof(stl_unwanted)); |
3603 | outb((RDSR + portp->uartaddr), ioaddr); | 3585 | outb((RDSR + portp->uartaddr), ioaddr); |
3604 | insb((ioaddr + EREG_DATA), &stl_unwanted[0], len); | 3586 | insb((ioaddr + EREG_DATA), &stl_unwanted[0], len); |
3605 | portp->stats.rxlost += len; | 3587 | portp->stats.rxlost += len; |
@@ -3692,8 +3674,7 @@ static void stl_cd1400mdmisr(struct stlpanel *panelp, int ioaddr) | |||
3692 | outb((MISR + portp->uartaddr), ioaddr); | 3674 | outb((MISR + portp->uartaddr), ioaddr); |
3693 | misr = inb(ioaddr + EREG_DATA); | 3675 | misr = inb(ioaddr + EREG_DATA); |
3694 | if (misr & MISR_DCD) { | 3676 | if (misr & MISR_DCD) { |
3695 | set_bit(ASYI_DCDCHANGE, &portp->istate); | 3677 | stl_cd_change(portp); |
3696 | schedule_work(&portp->tqueue); | ||
3697 | portp->stats.modem++; | 3678 | portp->stats.modem++; |
3698 | } | 3679 | } |
3699 | 3680 | ||
@@ -4447,7 +4428,8 @@ static void stl_sc26198txisr(struct stlport *portp) | |||
4447 | if ((len == 0) || ((len < STL_TXBUFLOW) && | 4428 | if ((len == 0) || ((len < STL_TXBUFLOW) && |
4448 | (test_bit(ASYI_TXLOW, &portp->istate) == 0))) { | 4429 | (test_bit(ASYI_TXLOW, &portp->istate) == 0))) { |
4449 | set_bit(ASYI_TXLOW, &portp->istate); | 4430 | set_bit(ASYI_TXLOW, &portp->istate); |
4450 | schedule_work(&portp->tqueue); | 4431 | if (portp->tty) |
4432 | tty_wakeup(portp->tty); | ||
4451 | } | 4433 | } |
4452 | 4434 | ||
4453 | if (len == 0) { | 4435 | if (len == 0) { |
@@ -4465,7 +4447,8 @@ static void stl_sc26198txisr(struct stlport *portp) | |||
4465 | } else { | 4447 | } else { |
4466 | len = min(len, SC26198_TXFIFOSIZE); | 4448 | len = min(len, SC26198_TXFIFOSIZE); |
4467 | portp->stats.txtotal += len; | 4449 | portp->stats.txtotal += len; |
4468 | stlen = min(len, ((portp->tx.buf + STL_TXBUFSIZE) - tail)); | 4450 | stlen = min_t(unsigned int, len, |
4451 | (portp->tx.buf + STL_TXBUFSIZE) - tail); | ||
4469 | outb(GTXFIFO, (ioaddr + XP_ADDR)); | 4452 | outb(GTXFIFO, (ioaddr + XP_ADDR)); |
4470 | outsb((ioaddr + XP_DATA), tail, stlen); | 4453 | outsb((ioaddr + XP_DATA), tail, stlen); |
4471 | len -= stlen; | 4454 | len -= stlen; |
@@ -4506,7 +4489,7 @@ static void stl_sc26198rxisr(struct stlport *portp, unsigned int iack) | |||
4506 | 4489 | ||
4507 | if ((iack & IVR_TYPEMASK) == IVR_RXDATA) { | 4490 | if ((iack & IVR_TYPEMASK) == IVR_RXDATA) { |
4508 | if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) { | 4491 | if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) { |
4509 | len = min(len, sizeof(stl_unwanted)); | 4492 | len = min_t(unsigned int, len, sizeof(stl_unwanted)); |
4510 | outb(GRXFIFO, (ioaddr + XP_ADDR)); | 4493 | outb(GRXFIFO, (ioaddr + XP_ADDR)); |
4511 | insb((ioaddr + XP_DATA), &stl_unwanted[0], len); | 4494 | insb((ioaddr + XP_DATA), &stl_unwanted[0], len); |
4512 | portp->stats.rxlost += len; | 4495 | portp->stats.rxlost += len; |
@@ -4647,8 +4630,7 @@ static void stl_sc26198otherisr(struct stlport *portp, unsigned int iack) | |||
4647 | case CIR_SUBCOS: | 4630 | case CIR_SUBCOS: |
4648 | ipr = stl_sc26198getreg(portp, IPR); | 4631 | ipr = stl_sc26198getreg(portp, IPR); |
4649 | if (ipr & IPR_DCDCHANGE) { | 4632 | if (ipr & IPR_DCDCHANGE) { |
4650 | set_bit(ASYI_DCDCHANGE, &portp->istate); | 4633 | stl_cd_change(portp); |
4651 | schedule_work(&portp->tqueue); | ||
4652 | portp->stats.modem++; | 4634 | portp->stats.modem++; |
4653 | } | 4635 | } |
4654 | break; | 4636 | break; |
diff --git a/drivers/char/sx.h b/drivers/char/sx.h index 70d9783c7323..87c2defdead7 100644 --- a/drivers/char/sx.h +++ b/drivers/char/sx.h | |||
@@ -88,8 +88,6 @@ struct vpd_prom { | |||
88 | 88 | ||
89 | #define IS_CF_BOARD(board) (board->flags & (SX_CFISA_BOARD | SX_CFPCI_BOARD)) | 89 | #define IS_CF_BOARD(board) (board->flags & (SX_CFISA_BOARD | SX_CFPCI_BOARD)) |
90 | 90 | ||
91 | #define SERIAL_TYPE_NORMAL 1 | ||
92 | |||
93 | /* The SI processor clock is required to calculate the cc_int_count register | 91 | /* The SI processor clock is required to calculate the cc_int_count register |
94 | value for the SI cards. */ | 92 | value for the SI cards. */ |
95 | #define SI_PROCESSOR_CLOCK 25000000 | 93 | #define SI_PROCESSOR_CLOCK 25000000 |
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c index d010ed95ed3b..ddc74d1f4f1b 100644 --- a/drivers/char/synclink.c +++ b/drivers/char/synclink.c | |||
@@ -85,6 +85,7 @@ | |||
85 | #include <linux/vmalloc.h> | 85 | #include <linux/vmalloc.h> |
86 | #include <linux/init.h> | 86 | #include <linux/init.h> |
87 | #include <linux/ioctl.h> | 87 | #include <linux/ioctl.h> |
88 | #include <linux/synclink.h> | ||
88 | 89 | ||
89 | #include <asm/system.h> | 90 | #include <asm/system.h> |
90 | #include <asm/io.h> | 91 | #include <asm/io.h> |
@@ -110,8 +111,6 @@ | |||
110 | 111 | ||
111 | #include <asm/uaccess.h> | 112 | #include <asm/uaccess.h> |
112 | 113 | ||
113 | #include "linux/synclink.h" | ||
114 | |||
115 | #define RCLRVALUE 0xffff | 114 | #define RCLRVALUE 0xffff |
116 | 115 | ||
117 | static MGSL_PARAMS default_params = { | 116 | static MGSL_PARAMS default_params = { |
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c index 64e835f62438..1f954acf2bac 100644 --- a/drivers/char/synclink_gt.c +++ b/drivers/char/synclink_gt.c | |||
@@ -73,6 +73,7 @@ | |||
73 | #include <linux/bitops.h> | 73 | #include <linux/bitops.h> |
74 | #include <linux/workqueue.h> | 74 | #include <linux/workqueue.h> |
75 | #include <linux/hdlc.h> | 75 | #include <linux/hdlc.h> |
76 | #include <linux/synclink.h> | ||
76 | 77 | ||
77 | #include <asm/system.h> | 78 | #include <asm/system.h> |
78 | #include <asm/io.h> | 79 | #include <asm/io.h> |
@@ -81,8 +82,6 @@ | |||
81 | #include <asm/types.h> | 82 | #include <asm/types.h> |
82 | #include <asm/uaccess.h> | 83 | #include <asm/uaccess.h> |
83 | 84 | ||
84 | #include "linux/synclink.h" | ||
85 | |||
86 | #if defined(CONFIG_HDLC) || (defined(CONFIG_HDLC_MODULE) && defined(CONFIG_SYNCLINK_GT_MODULE)) | 85 | #if defined(CONFIG_HDLC) || (defined(CONFIG_HDLC_MODULE) && defined(CONFIG_SYNCLINK_GT_MODULE)) |
87 | #define SYNCLINK_GENERIC_HDLC 1 | 86 | #define SYNCLINK_GENERIC_HDLC 1 |
88 | #else | 87 | #else |
@@ -2040,37 +2039,41 @@ static void bh_transmit(struct slgt_info *info) | |||
2040 | tty_wakeup(tty); | 2039 | tty_wakeup(tty); |
2041 | } | 2040 | } |
2042 | 2041 | ||
2043 | static void dsr_change(struct slgt_info *info) | 2042 | static void dsr_change(struct slgt_info *info, unsigned short status) |
2044 | { | 2043 | { |
2045 | get_signals(info); | 2044 | if (status & BIT3) { |
2045 | info->signals |= SerialSignal_DSR; | ||
2046 | info->input_signal_events.dsr_up++; | ||
2047 | } else { | ||
2048 | info->signals &= ~SerialSignal_DSR; | ||
2049 | info->input_signal_events.dsr_down++; | ||
2050 | } | ||
2046 | DBGISR(("dsr_change %s signals=%04X\n", info->device_name, info->signals)); | 2051 | DBGISR(("dsr_change %s signals=%04X\n", info->device_name, info->signals)); |
2047 | if ((info->dsr_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) { | 2052 | if ((info->dsr_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) { |
2048 | slgt_irq_off(info, IRQ_DSR); | 2053 | slgt_irq_off(info, IRQ_DSR); |
2049 | return; | 2054 | return; |
2050 | } | 2055 | } |
2051 | info->icount.dsr++; | 2056 | info->icount.dsr++; |
2052 | if (info->signals & SerialSignal_DSR) | ||
2053 | info->input_signal_events.dsr_up++; | ||
2054 | else | ||
2055 | info->input_signal_events.dsr_down++; | ||
2056 | wake_up_interruptible(&info->status_event_wait_q); | 2057 | wake_up_interruptible(&info->status_event_wait_q); |
2057 | wake_up_interruptible(&info->event_wait_q); | 2058 | wake_up_interruptible(&info->event_wait_q); |
2058 | info->pending_bh |= BH_STATUS; | 2059 | info->pending_bh |= BH_STATUS; |
2059 | } | 2060 | } |
2060 | 2061 | ||
2061 | static void cts_change(struct slgt_info *info) | 2062 | static void cts_change(struct slgt_info *info, unsigned short status) |
2062 | { | 2063 | { |
2063 | get_signals(info); | 2064 | if (status & BIT2) { |
2065 | info->signals |= SerialSignal_CTS; | ||
2066 | info->input_signal_events.cts_up++; | ||
2067 | } else { | ||
2068 | info->signals &= ~SerialSignal_CTS; | ||
2069 | info->input_signal_events.cts_down++; | ||
2070 | } | ||
2064 | DBGISR(("cts_change %s signals=%04X\n", info->device_name, info->signals)); | 2071 | DBGISR(("cts_change %s signals=%04X\n", info->device_name, info->signals)); |
2065 | if ((info->cts_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) { | 2072 | if ((info->cts_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) { |
2066 | slgt_irq_off(info, IRQ_CTS); | 2073 | slgt_irq_off(info, IRQ_CTS); |
2067 | return; | 2074 | return; |
2068 | } | 2075 | } |
2069 | info->icount.cts++; | 2076 | info->icount.cts++; |
2070 | if (info->signals & SerialSignal_CTS) | ||
2071 | info->input_signal_events.cts_up++; | ||
2072 | else | ||
2073 | info->input_signal_events.cts_down++; | ||
2074 | wake_up_interruptible(&info->status_event_wait_q); | 2077 | wake_up_interruptible(&info->status_event_wait_q); |
2075 | wake_up_interruptible(&info->event_wait_q); | 2078 | wake_up_interruptible(&info->event_wait_q); |
2076 | info->pending_bh |= BH_STATUS; | 2079 | info->pending_bh |= BH_STATUS; |
@@ -2091,20 +2094,21 @@ static void cts_change(struct slgt_info *info) | |||
2091 | } | 2094 | } |
2092 | } | 2095 | } |
2093 | 2096 | ||
2094 | static void dcd_change(struct slgt_info *info) | 2097 | static void dcd_change(struct slgt_info *info, unsigned short status) |
2095 | { | 2098 | { |
2096 | get_signals(info); | 2099 | if (status & BIT1) { |
2100 | info->signals |= SerialSignal_DCD; | ||
2101 | info->input_signal_events.dcd_up++; | ||
2102 | } else { | ||
2103 | info->signals &= ~SerialSignal_DCD; | ||
2104 | info->input_signal_events.dcd_down++; | ||
2105 | } | ||
2097 | DBGISR(("dcd_change %s signals=%04X\n", info->device_name, info->signals)); | 2106 | DBGISR(("dcd_change %s signals=%04X\n", info->device_name, info->signals)); |
2098 | if ((info->dcd_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) { | 2107 | if ((info->dcd_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) { |
2099 | slgt_irq_off(info, IRQ_DCD); | 2108 | slgt_irq_off(info, IRQ_DCD); |
2100 | return; | 2109 | return; |
2101 | } | 2110 | } |
2102 | info->icount.dcd++; | 2111 | info->icount.dcd++; |
2103 | if (info->signals & SerialSignal_DCD) { | ||
2104 | info->input_signal_events.dcd_up++; | ||
2105 | } else { | ||
2106 | info->input_signal_events.dcd_down++; | ||
2107 | } | ||
2108 | #if SYNCLINK_GENERIC_HDLC | 2112 | #if SYNCLINK_GENERIC_HDLC |
2109 | if (info->netcount) { | 2113 | if (info->netcount) { |
2110 | if (info->signals & SerialSignal_DCD) | 2114 | if (info->signals & SerialSignal_DCD) |
@@ -2127,20 +2131,21 @@ static void dcd_change(struct slgt_info *info) | |||
2127 | } | 2131 | } |
2128 | } | 2132 | } |
2129 | 2133 | ||
2130 | static void ri_change(struct slgt_info *info) | 2134 | static void ri_change(struct slgt_info *info, unsigned short status) |
2131 | { | 2135 | { |
2132 | get_signals(info); | 2136 | if (status & BIT0) { |
2137 | info->signals |= SerialSignal_RI; | ||
2138 | info->input_signal_events.ri_up++; | ||
2139 | } else { | ||
2140 | info->signals &= ~SerialSignal_RI; | ||
2141 | info->input_signal_events.ri_down++; | ||
2142 | } | ||
2133 | DBGISR(("ri_change %s signals=%04X\n", info->device_name, info->signals)); | 2143 | DBGISR(("ri_change %s signals=%04X\n", info->device_name, info->signals)); |
2134 | if ((info->ri_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) { | 2144 | if ((info->ri_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) { |
2135 | slgt_irq_off(info, IRQ_RI); | 2145 | slgt_irq_off(info, IRQ_RI); |
2136 | return; | 2146 | return; |
2137 | } | 2147 | } |
2138 | info->icount.dcd++; | 2148 | info->icount.rng++; |
2139 | if (info->signals & SerialSignal_RI) { | ||
2140 | info->input_signal_events.ri_up++; | ||
2141 | } else { | ||
2142 | info->input_signal_events.ri_down++; | ||
2143 | } | ||
2144 | wake_up_interruptible(&info->status_event_wait_q); | 2149 | wake_up_interruptible(&info->status_event_wait_q); |
2145 | wake_up_interruptible(&info->event_wait_q); | 2150 | wake_up_interruptible(&info->event_wait_q); |
2146 | info->pending_bh |= BH_STATUS; | 2151 | info->pending_bh |= BH_STATUS; |
@@ -2191,13 +2196,13 @@ static void isr_serial(struct slgt_info *info) | |||
2191 | } | 2196 | } |
2192 | 2197 | ||
2193 | if (status & IRQ_DSR) | 2198 | if (status & IRQ_DSR) |
2194 | dsr_change(info); | 2199 | dsr_change(info, status); |
2195 | if (status & IRQ_CTS) | 2200 | if (status & IRQ_CTS) |
2196 | cts_change(info); | 2201 | cts_change(info, status); |
2197 | if (status & IRQ_DCD) | 2202 | if (status & IRQ_DCD) |
2198 | dcd_change(info); | 2203 | dcd_change(info, status); |
2199 | if (status & IRQ_RI) | 2204 | if (status & IRQ_RI) |
2200 | ri_change(info); | 2205 | ri_change(info, status); |
2201 | } | 2206 | } |
2202 | 2207 | ||
2203 | static void isr_rdma(struct slgt_info *info) | 2208 | static void isr_rdma(struct slgt_info *info) |
diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c index c63013b2fc36..f3e7807f78d9 100644 --- a/drivers/char/synclinkmp.c +++ b/drivers/char/synclinkmp.c | |||
@@ -66,6 +66,7 @@ | |||
66 | #include <linux/termios.h> | 66 | #include <linux/termios.h> |
67 | #include <linux/workqueue.h> | 67 | #include <linux/workqueue.h> |
68 | #include <linux/hdlc.h> | 68 | #include <linux/hdlc.h> |
69 | #include <linux/synclink.h> | ||
69 | 70 | ||
70 | #if defined(CONFIG_HDLC) || (defined(CONFIG_HDLC_MODULE) && defined(CONFIG_SYNCLINKMP_MODULE)) | 71 | #if defined(CONFIG_HDLC) || (defined(CONFIG_HDLC_MODULE) && defined(CONFIG_SYNCLINKMP_MODULE)) |
71 | #define SYNCLINK_GENERIC_HDLC 1 | 72 | #define SYNCLINK_GENERIC_HDLC 1 |
@@ -80,8 +81,6 @@ | |||
80 | 81 | ||
81 | #include <asm/uaccess.h> | 82 | #include <asm/uaccess.h> |
82 | 83 | ||
83 | #include "linux/synclink.h" | ||
84 | |||
85 | static MGSL_PARAMS default_params = { | 84 | static MGSL_PARAMS default_params = { |
86 | MGSL_MODE_HDLC, /* unsigned long mode */ | 85 | MGSL_MODE_HDLC, /* unsigned long mode */ |
87 | 0, /* unsigned char loopback; */ | 86 | 0, /* unsigned char loopback; */ |
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index c88424a0c89b..a5d8bcb40000 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c | |||
@@ -1031,18 +1031,13 @@ void tpm_remove_hardware(struct device *dev) | |||
1031 | 1031 | ||
1032 | spin_unlock(&driver_lock); | 1032 | spin_unlock(&driver_lock); |
1033 | 1033 | ||
1034 | dev_set_drvdata(dev, NULL); | ||
1035 | misc_deregister(&chip->vendor.miscdev); | 1034 | misc_deregister(&chip->vendor.miscdev); |
1036 | kfree(chip->vendor.miscdev.name); | ||
1037 | 1035 | ||
1038 | sysfs_remove_group(&dev->kobj, chip->vendor.attr_group); | 1036 | sysfs_remove_group(&dev->kobj, chip->vendor.attr_group); |
1039 | tpm_bios_log_teardown(chip->bios_dir); | 1037 | tpm_bios_log_teardown(chip->bios_dir); |
1040 | 1038 | ||
1041 | clear_bit(chip->dev_num, dev_mask); | 1039 | /* write it this way to be explicit (chip->dev == dev) */ |
1042 | 1040 | put_device(chip->dev); | |
1043 | kfree(chip); | ||
1044 | |||
1045 | put_device(dev); | ||
1046 | } | 1041 | } |
1047 | EXPORT_SYMBOL_GPL(tpm_remove_hardware); | 1042 | EXPORT_SYMBOL_GPL(tpm_remove_hardware); |
1048 | 1043 | ||
@@ -1083,6 +1078,26 @@ int tpm_pm_resume(struct device *dev) | |||
1083 | EXPORT_SYMBOL_GPL(tpm_pm_resume); | 1078 | EXPORT_SYMBOL_GPL(tpm_pm_resume); |
1084 | 1079 | ||
1085 | /* | 1080 | /* |
1081 | * Once all references to platform device are down to 0, | ||
1082 | * release all allocated structures. | ||
1083 | * In case vendor provided release function, | ||
1084 | * call it too. | ||
1085 | */ | ||
1086 | static void tpm_dev_release(struct device *dev) | ||
1087 | { | ||
1088 | struct tpm_chip *chip = dev_get_drvdata(dev); | ||
1089 | |||
1090 | if (chip->vendor.release) | ||
1091 | chip->vendor.release(dev); | ||
1092 | |||
1093 | chip->release(dev); | ||
1094 | |||
1095 | clear_bit(chip->dev_num, dev_mask); | ||
1096 | kfree(chip->vendor.miscdev.name); | ||
1097 | kfree(chip); | ||
1098 | } | ||
1099 | |||
1100 | /* | ||
1086 | * Called from tpm_<specific>.c probe function only for devices | 1101 | * Called from tpm_<specific>.c probe function only for devices |
1087 | * the driver has determined it should claim. Prior to calling | 1102 | * the driver has determined it should claim. Prior to calling |
1088 | * this function the specific probe function has called pci_enable_device | 1103 | * this function the specific probe function has called pci_enable_device |
@@ -1136,23 +1151,21 @@ struct tpm_chip *tpm_register_hardware(struct device *dev, const struct tpm_vend | |||
1136 | 1151 | ||
1137 | chip->vendor.miscdev.parent = dev; | 1152 | chip->vendor.miscdev.parent = dev; |
1138 | chip->dev = get_device(dev); | 1153 | chip->dev = get_device(dev); |
1154 | chip->release = dev->release; | ||
1155 | dev->release = tpm_dev_release; | ||
1156 | dev_set_drvdata(dev, chip); | ||
1139 | 1157 | ||
1140 | if (misc_register(&chip->vendor.miscdev)) { | 1158 | if (misc_register(&chip->vendor.miscdev)) { |
1141 | dev_err(chip->dev, | 1159 | dev_err(chip->dev, |
1142 | "unable to misc_register %s, minor %d\n", | 1160 | "unable to misc_register %s, minor %d\n", |
1143 | chip->vendor.miscdev.name, | 1161 | chip->vendor.miscdev.name, |
1144 | chip->vendor.miscdev.minor); | 1162 | chip->vendor.miscdev.minor); |
1145 | put_device(dev); | 1163 | put_device(chip->dev); |
1146 | clear_bit(chip->dev_num, dev_mask); | ||
1147 | kfree(chip); | ||
1148 | kfree(devname); | ||
1149 | return NULL; | 1164 | return NULL; |
1150 | } | 1165 | } |
1151 | 1166 | ||
1152 | spin_lock(&driver_lock); | 1167 | spin_lock(&driver_lock); |
1153 | 1168 | ||
1154 | dev_set_drvdata(dev, chip); | ||
1155 | |||
1156 | list_add(&chip->list, &tpm_chip_list); | 1169 | list_add(&chip->list, &tpm_chip_list); |
1157 | 1170 | ||
1158 | spin_unlock(&driver_lock); | 1171 | spin_unlock(&driver_lock); |
@@ -1160,10 +1173,7 @@ struct tpm_chip *tpm_register_hardware(struct device *dev, const struct tpm_vend | |||
1160 | if (sysfs_create_group(&dev->kobj, chip->vendor.attr_group)) { | 1173 | if (sysfs_create_group(&dev->kobj, chip->vendor.attr_group)) { |
1161 | list_del(&chip->list); | 1174 | list_del(&chip->list); |
1162 | misc_deregister(&chip->vendor.miscdev); | 1175 | misc_deregister(&chip->vendor.miscdev); |
1163 | put_device(dev); | 1176 | put_device(chip->dev); |
1164 | clear_bit(chip->dev_num, dev_mask); | ||
1165 | kfree(chip); | ||
1166 | kfree(devname); | ||
1167 | return NULL; | 1177 | return NULL; |
1168 | } | 1178 | } |
1169 | 1179 | ||
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index d15ccddc92eb..e885148b4cfb 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h | |||
@@ -74,6 +74,7 @@ struct tpm_vendor_specific { | |||
74 | int (*send) (struct tpm_chip *, u8 *, size_t); | 74 | int (*send) (struct tpm_chip *, u8 *, size_t); |
75 | void (*cancel) (struct tpm_chip *); | 75 | void (*cancel) (struct tpm_chip *); |
76 | u8 (*status) (struct tpm_chip *); | 76 | u8 (*status) (struct tpm_chip *); |
77 | void (*release) (struct device *); | ||
77 | struct miscdevice miscdev; | 78 | struct miscdevice miscdev; |
78 | struct attribute_group *attr_group; | 79 | struct attribute_group *attr_group; |
79 | struct list_head list; | 80 | struct list_head list; |
@@ -106,6 +107,7 @@ struct tpm_chip { | |||
106 | struct dentry **bios_dir; | 107 | struct dentry **bios_dir; |
107 | 108 | ||
108 | struct list_head list; | 109 | struct list_head list; |
110 | void (*release) (struct device *); | ||
109 | }; | 111 | }; |
110 | 112 | ||
111 | #define to_tpm_chip(n) container_of(n, struct tpm_chip, vendor) | 113 | #define to_tpm_chip(n) container_of(n, struct tpm_chip, vendor) |
diff --git a/drivers/char/tpm/tpm_infineon.c b/drivers/char/tpm/tpm_infineon.c index 967002a5a1e5..726ee8a0277f 100644 --- a/drivers/char/tpm/tpm_infineon.c +++ b/drivers/char/tpm/tpm_infineon.c | |||
@@ -611,7 +611,7 @@ static __devexit void tpm_inf_pnp_remove(struct pnp_dev *dev) | |||
611 | } | 611 | } |
612 | } | 612 | } |
613 | 613 | ||
614 | static struct pnp_driver tpm_inf_pnp = { | 614 | static struct pnp_driver tpm_inf_pnp_driver = { |
615 | .name = "tpm_inf_pnp", | 615 | .name = "tpm_inf_pnp", |
616 | .driver = { | 616 | .driver = { |
617 | .owner = THIS_MODULE, | 617 | .owner = THIS_MODULE, |
@@ -625,12 +625,12 @@ static struct pnp_driver tpm_inf_pnp = { | |||
625 | 625 | ||
626 | static int __init init_inf(void) | 626 | static int __init init_inf(void) |
627 | { | 627 | { |
628 | return pnp_register_driver(&tpm_inf_pnp); | 628 | return pnp_register_driver(&tpm_inf_pnp_driver); |
629 | } | 629 | } |
630 | 630 | ||
631 | static void __exit cleanup_inf(void) | 631 | static void __exit cleanup_inf(void) |
632 | { | 632 | { |
633 | pnp_unregister_driver(&tpm_inf_pnp); | 633 | pnp_unregister_driver(&tpm_inf_pnp_driver); |
634 | } | 634 | } |
635 | 635 | ||
636 | module_init(init_inf); | 636 | module_init(init_inf); |
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index f36fecd3fd26..79c86c47947f 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c | |||
@@ -138,7 +138,7 @@ EXPORT_SYMBOL(tty_mutex); | |||
138 | extern struct tty_driver *ptm_driver; /* Unix98 pty masters; for /dev/ptmx */ | 138 | extern struct tty_driver *ptm_driver; /* Unix98 pty masters; for /dev/ptmx */ |
139 | extern int pty_limit; /* Config limit on Unix98 ptys */ | 139 | extern int pty_limit; /* Config limit on Unix98 ptys */ |
140 | static DEFINE_IDR(allocated_ptys); | 140 | static DEFINE_IDR(allocated_ptys); |
141 | static DECLARE_MUTEX(allocated_ptys_lock); | 141 | static DEFINE_MUTEX(allocated_ptys_lock); |
142 | static int ptmx_open(struct inode *, struct file *); | 142 | static int ptmx_open(struct inode *, struct file *); |
143 | #endif | 143 | #endif |
144 | 144 | ||
@@ -2571,9 +2571,9 @@ static void release_dev(struct file * filp) | |||
2571 | #ifdef CONFIG_UNIX98_PTYS | 2571 | #ifdef CONFIG_UNIX98_PTYS |
2572 | /* Make this pty number available for reallocation */ | 2572 | /* Make this pty number available for reallocation */ |
2573 | if (devpts) { | 2573 | if (devpts) { |
2574 | down(&allocated_ptys_lock); | 2574 | mutex_lock(&allocated_ptys_lock); |
2575 | idr_remove(&allocated_ptys, idx); | 2575 | idr_remove(&allocated_ptys, idx); |
2576 | up(&allocated_ptys_lock); | 2576 | mutex_unlock(&allocated_ptys_lock); |
2577 | } | 2577 | } |
2578 | #endif | 2578 | #endif |
2579 | 2579 | ||
@@ -2737,24 +2737,24 @@ static int ptmx_open(struct inode * inode, struct file * filp) | |||
2737 | nonseekable_open(inode, filp); | 2737 | nonseekable_open(inode, filp); |
2738 | 2738 | ||
2739 | /* find a device that is not in use. */ | 2739 | /* find a device that is not in use. */ |
2740 | down(&allocated_ptys_lock); | 2740 | mutex_lock(&allocated_ptys_lock); |
2741 | if (!idr_pre_get(&allocated_ptys, GFP_KERNEL)) { | 2741 | if (!idr_pre_get(&allocated_ptys, GFP_KERNEL)) { |
2742 | up(&allocated_ptys_lock); | 2742 | mutex_unlock(&allocated_ptys_lock); |
2743 | return -ENOMEM; | 2743 | return -ENOMEM; |
2744 | } | 2744 | } |
2745 | idr_ret = idr_get_new(&allocated_ptys, NULL, &index); | 2745 | idr_ret = idr_get_new(&allocated_ptys, NULL, &index); |
2746 | if (idr_ret < 0) { | 2746 | if (idr_ret < 0) { |
2747 | up(&allocated_ptys_lock); | 2747 | mutex_unlock(&allocated_ptys_lock); |
2748 | if (idr_ret == -EAGAIN) | 2748 | if (idr_ret == -EAGAIN) |
2749 | return -ENOMEM; | 2749 | return -ENOMEM; |
2750 | return -EIO; | 2750 | return -EIO; |
2751 | } | 2751 | } |
2752 | if (index >= pty_limit) { | 2752 | if (index >= pty_limit) { |
2753 | idr_remove(&allocated_ptys, index); | 2753 | idr_remove(&allocated_ptys, index); |
2754 | up(&allocated_ptys_lock); | 2754 | mutex_unlock(&allocated_ptys_lock); |
2755 | return -EIO; | 2755 | return -EIO; |
2756 | } | 2756 | } |
2757 | up(&allocated_ptys_lock); | 2757 | mutex_unlock(&allocated_ptys_lock); |
2758 | 2758 | ||
2759 | mutex_lock(&tty_mutex); | 2759 | mutex_lock(&tty_mutex); |
2760 | retval = init_dev(ptm_driver, index, &tty); | 2760 | retval = init_dev(ptm_driver, index, &tty); |
@@ -2781,9 +2781,9 @@ out1: | |||
2781 | release_dev(filp); | 2781 | release_dev(filp); |
2782 | return retval; | 2782 | return retval; |
2783 | out: | 2783 | out: |
2784 | down(&allocated_ptys_lock); | 2784 | mutex_lock(&allocated_ptys_lock); |
2785 | idr_remove(&allocated_ptys, index); | 2785 | idr_remove(&allocated_ptys, index); |
2786 | up(&allocated_ptys_lock); | 2786 | mutex_unlock(&allocated_ptys_lock); |
2787 | return retval; | 2787 | return retval; |
2788 | } | 2788 | } |
2789 | #endif | 2789 | #endif |
@@ -3721,7 +3721,6 @@ static void initialize_tty_struct(struct tty_struct *tty) | |||
3721 | tty->buf.head = tty->buf.tail = NULL; | 3721 | tty->buf.head = tty->buf.tail = NULL; |
3722 | tty_buffer_init(tty); | 3722 | tty_buffer_init(tty); |
3723 | INIT_DELAYED_WORK(&tty->buf.work, flush_to_ldisc); | 3723 | INIT_DELAYED_WORK(&tty->buf.work, flush_to_ldisc); |
3724 | init_MUTEX(&tty->buf.pty_sem); | ||
3725 | mutex_init(&tty->termios_mutex); | 3724 | mutex_init(&tty->termios_mutex); |
3726 | init_waitqueue_head(&tty->write_wait); | 3725 | init_waitqueue_head(&tty->write_wait); |
3727 | init_waitqueue_head(&tty->read_wait); | 3726 | init_waitqueue_head(&tty->read_wait); |
@@ -4048,10 +4047,6 @@ void __init console_init(void) | |||
4048 | } | 4047 | } |
4049 | } | 4048 | } |
4050 | 4049 | ||
4051 | #ifdef CONFIG_VT | ||
4052 | extern int vty_init(void); | ||
4053 | #endif | ||
4054 | |||
4055 | static int __init tty_class_init(void) | 4050 | static int __init tty_class_init(void) |
4056 | { | 4051 | { |
4057 | tty_class = class_create(THIS_MODULE, "tty"); | 4052 | tty_class = class_create(THIS_MODULE, "tty"); |
diff --git a/drivers/char/vt.c b/drivers/char/vt.c index 7a5badfb7d84..367be9175061 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c | |||
@@ -2400,13 +2400,15 @@ static void vt_console_print(struct console *co, const char *b, unsigned count) | |||
2400 | { | 2400 | { |
2401 | struct vc_data *vc = vc_cons[fg_console].d; | 2401 | struct vc_data *vc = vc_cons[fg_console].d; |
2402 | unsigned char c; | 2402 | unsigned char c; |
2403 | static unsigned long printing; | 2403 | static DEFINE_SPINLOCK(printing_lock); |
2404 | const ushort *start; | 2404 | const ushort *start; |
2405 | ushort cnt = 0; | 2405 | ushort cnt = 0; |
2406 | ushort myx; | 2406 | ushort myx; |
2407 | 2407 | ||
2408 | /* console busy or not yet initialized */ | 2408 | /* console busy or not yet initialized */ |
2409 | if (!printable || test_and_set_bit(0, &printing)) | 2409 | if (!printable) |
2410 | return; | ||
2411 | if (!spin_trylock(&printing_lock)) | ||
2410 | return; | 2412 | return; |
2411 | 2413 | ||
2412 | if (kmsg_redirect && vc_cons_allocated(kmsg_redirect - 1)) | 2414 | if (kmsg_redirect && vc_cons_allocated(kmsg_redirect - 1)) |
@@ -2481,7 +2483,7 @@ static void vt_console_print(struct console *co, const char *b, unsigned count) | |||
2481 | notify_update(vc); | 2483 | notify_update(vc); |
2482 | 2484 | ||
2483 | quit: | 2485 | quit: |
2484 | clear_bit(0, &printing); | 2486 | spin_unlock(&printing_lock); |
2485 | } | 2487 | } |
2486 | 2488 | ||
2487 | static struct tty_driver *vt_console_device(struct console *c, int *index) | 2489 | static struct tty_driver *vt_console_device(struct console *c, int *index) |
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index c46b7c219ee9..a703deffb795 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig | |||
@@ -5,6 +5,7 @@ | |||
5 | menuconfig DMADEVICES | 5 | menuconfig DMADEVICES |
6 | bool "DMA Engine support" | 6 | bool "DMA Engine support" |
7 | depends on (PCI && X86) || ARCH_IOP32X || ARCH_IOP33X || ARCH_IOP13XX | 7 | depends on (PCI && X86) || ARCH_IOP32X || ARCH_IOP33X || ARCH_IOP13XX |
8 | depends on !HIGHMEM64G | ||
8 | help | 9 | help |
9 | DMA engines can do asynchronous data transfers without | 10 | DMA engines can do asynchronous data transfers without |
10 | involving the host CPU. Currently, this framework can be | 11 | involving the host CPU. Currently, this framework can be |
diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c index bcf52df30339..29965231b912 100644 --- a/drivers/dma/dmaengine.c +++ b/drivers/dma/dmaengine.c | |||
@@ -473,20 +473,22 @@ dma_async_memcpy_buf_to_buf(struct dma_chan *chan, void *dest, | |||
473 | { | 473 | { |
474 | struct dma_device *dev = chan->device; | 474 | struct dma_device *dev = chan->device; |
475 | struct dma_async_tx_descriptor *tx; | 475 | struct dma_async_tx_descriptor *tx; |
476 | dma_addr_t addr; | 476 | dma_addr_t dma_dest, dma_src; |
477 | dma_cookie_t cookie; | 477 | dma_cookie_t cookie; |
478 | int cpu; | 478 | int cpu; |
479 | 479 | ||
480 | tx = dev->device_prep_dma_memcpy(chan, len, 0); | 480 | dma_src = dma_map_single(dev->dev, src, len, DMA_TO_DEVICE); |
481 | if (!tx) | 481 | dma_dest = dma_map_single(dev->dev, dest, len, DMA_FROM_DEVICE); |
482 | tx = dev->device_prep_dma_memcpy(chan, dma_dest, dma_src, len, 0); | ||
483 | |||
484 | if (!tx) { | ||
485 | dma_unmap_single(dev->dev, dma_src, len, DMA_TO_DEVICE); | ||
486 | dma_unmap_single(dev->dev, dma_dest, len, DMA_FROM_DEVICE); | ||
482 | return -ENOMEM; | 487 | return -ENOMEM; |
488 | } | ||
483 | 489 | ||
484 | tx->ack = 1; | 490 | tx->ack = 1; |
485 | tx->callback = NULL; | 491 | tx->callback = NULL; |
486 | addr = dma_map_single(dev->dev, src, len, DMA_TO_DEVICE); | ||
487 | tx->tx_set_src(addr, tx, 0); | ||
488 | addr = dma_map_single(dev->dev, dest, len, DMA_FROM_DEVICE); | ||
489 | tx->tx_set_dest(addr, tx, 0); | ||
490 | cookie = tx->tx_submit(tx); | 492 | cookie = tx->tx_submit(tx); |
491 | 493 | ||
492 | cpu = get_cpu(); | 494 | cpu = get_cpu(); |
@@ -517,20 +519,22 @@ dma_async_memcpy_buf_to_pg(struct dma_chan *chan, struct page *page, | |||
517 | { | 519 | { |
518 | struct dma_device *dev = chan->device; | 520 | struct dma_device *dev = chan->device; |
519 | struct dma_async_tx_descriptor *tx; | 521 | struct dma_async_tx_descriptor *tx; |
520 | dma_addr_t addr; | 522 | dma_addr_t dma_dest, dma_src; |
521 | dma_cookie_t cookie; | 523 | dma_cookie_t cookie; |
522 | int cpu; | 524 | int cpu; |
523 | 525 | ||
524 | tx = dev->device_prep_dma_memcpy(chan, len, 0); | 526 | dma_src = dma_map_single(dev->dev, kdata, len, DMA_TO_DEVICE); |
525 | if (!tx) | 527 | dma_dest = dma_map_page(dev->dev, page, offset, len, DMA_FROM_DEVICE); |
528 | tx = dev->device_prep_dma_memcpy(chan, dma_dest, dma_src, len, 0); | ||
529 | |||
530 | if (!tx) { | ||
531 | dma_unmap_single(dev->dev, dma_src, len, DMA_TO_DEVICE); | ||
532 | dma_unmap_page(dev->dev, dma_dest, len, DMA_FROM_DEVICE); | ||
526 | return -ENOMEM; | 533 | return -ENOMEM; |
534 | } | ||
527 | 535 | ||
528 | tx->ack = 1; | 536 | tx->ack = 1; |
529 | tx->callback = NULL; | 537 | tx->callback = NULL; |
530 | addr = dma_map_single(dev->dev, kdata, len, DMA_TO_DEVICE); | ||
531 | tx->tx_set_src(addr, tx, 0); | ||
532 | addr = dma_map_page(dev->dev, page, offset, len, DMA_FROM_DEVICE); | ||
533 | tx->tx_set_dest(addr, tx, 0); | ||
534 | cookie = tx->tx_submit(tx); | 538 | cookie = tx->tx_submit(tx); |
535 | 539 | ||
536 | cpu = get_cpu(); | 540 | cpu = get_cpu(); |
@@ -563,20 +567,23 @@ dma_async_memcpy_pg_to_pg(struct dma_chan *chan, struct page *dest_pg, | |||
563 | { | 567 | { |
564 | struct dma_device *dev = chan->device; | 568 | struct dma_device *dev = chan->device; |
565 | struct dma_async_tx_descriptor *tx; | 569 | struct dma_async_tx_descriptor *tx; |
566 | dma_addr_t addr; | 570 | dma_addr_t dma_dest, dma_src; |
567 | dma_cookie_t cookie; | 571 | dma_cookie_t cookie; |
568 | int cpu; | 572 | int cpu; |
569 | 573 | ||
570 | tx = dev->device_prep_dma_memcpy(chan, len, 0); | 574 | dma_src = dma_map_page(dev->dev, src_pg, src_off, len, DMA_TO_DEVICE); |
571 | if (!tx) | 575 | dma_dest = dma_map_page(dev->dev, dest_pg, dest_off, len, |
576 | DMA_FROM_DEVICE); | ||
577 | tx = dev->device_prep_dma_memcpy(chan, dma_dest, dma_src, len, 0); | ||
578 | |||
579 | if (!tx) { | ||
580 | dma_unmap_page(dev->dev, dma_src, len, DMA_TO_DEVICE); | ||
581 | dma_unmap_page(dev->dev, dma_dest, len, DMA_FROM_DEVICE); | ||
572 | return -ENOMEM; | 582 | return -ENOMEM; |
583 | } | ||
573 | 584 | ||
574 | tx->ack = 1; | 585 | tx->ack = 1; |
575 | tx->callback = NULL; | 586 | tx->callback = NULL; |
576 | addr = dma_map_page(dev->dev, src_pg, src_off, len, DMA_TO_DEVICE); | ||
577 | tx->tx_set_src(addr, tx, 0); | ||
578 | addr = dma_map_page(dev->dev, dest_pg, dest_off, len, DMA_FROM_DEVICE); | ||
579 | tx->tx_set_dest(addr, tx, 0); | ||
580 | cookie = tx->tx_submit(tx); | 587 | cookie = tx->tx_submit(tx); |
581 | 588 | ||
582 | cpu = get_cpu(); | 589 | cpu = get_cpu(); |
diff --git a/drivers/dma/ioat_dma.c b/drivers/dma/ioat_dma.c index 45e7b4666c7b..dff38accc5c1 100644 --- a/drivers/dma/ioat_dma.c +++ b/drivers/dma/ioat_dma.c | |||
@@ -159,20 +159,6 @@ static int ioat_dma_enumerate_channels(struct ioatdma_device *device) | |||
159 | return device->common.chancnt; | 159 | return device->common.chancnt; |
160 | } | 160 | } |
161 | 161 | ||
162 | static void ioat_set_src(dma_addr_t addr, | ||
163 | struct dma_async_tx_descriptor *tx, | ||
164 | int index) | ||
165 | { | ||
166 | tx_to_ioat_desc(tx)->src = addr; | ||
167 | } | ||
168 | |||
169 | static void ioat_set_dest(dma_addr_t addr, | ||
170 | struct dma_async_tx_descriptor *tx, | ||
171 | int index) | ||
172 | { | ||
173 | tx_to_ioat_desc(tx)->dst = addr; | ||
174 | } | ||
175 | |||
176 | /** | 162 | /** |
177 | * ioat_dma_memcpy_issue_pending - push potentially unrecognized appended | 163 | * ioat_dma_memcpy_issue_pending - push potentially unrecognized appended |
178 | * descriptors to hw | 164 | * descriptors to hw |
@@ -415,8 +401,6 @@ static struct ioat_desc_sw *ioat_dma_alloc_descriptor( | |||
415 | 401 | ||
416 | memset(desc, 0, sizeof(*desc)); | 402 | memset(desc, 0, sizeof(*desc)); |
417 | dma_async_tx_descriptor_init(&desc_sw->async_tx, &ioat_chan->common); | 403 | dma_async_tx_descriptor_init(&desc_sw->async_tx, &ioat_chan->common); |
418 | desc_sw->async_tx.tx_set_src = ioat_set_src; | ||
419 | desc_sw->async_tx.tx_set_dest = ioat_set_dest; | ||
420 | switch (ioat_chan->device->version) { | 404 | switch (ioat_chan->device->version) { |
421 | case IOAT_VER_1_2: | 405 | case IOAT_VER_1_2: |
422 | desc_sw->async_tx.tx_submit = ioat1_tx_submit; | 406 | desc_sw->async_tx.tx_submit = ioat1_tx_submit; |
@@ -714,8 +698,10 @@ static struct ioat_desc_sw *ioat_dma_get_next_descriptor( | |||
714 | 698 | ||
715 | static struct dma_async_tx_descriptor *ioat1_dma_prep_memcpy( | 699 | static struct dma_async_tx_descriptor *ioat1_dma_prep_memcpy( |
716 | struct dma_chan *chan, | 700 | struct dma_chan *chan, |
701 | dma_addr_t dma_dest, | ||
702 | dma_addr_t dma_src, | ||
717 | size_t len, | 703 | size_t len, |
718 | int int_en) | 704 | unsigned long flags) |
719 | { | 705 | { |
720 | struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan); | 706 | struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan); |
721 | struct ioat_desc_sw *new; | 707 | struct ioat_desc_sw *new; |
@@ -726,6 +712,8 @@ static struct dma_async_tx_descriptor *ioat1_dma_prep_memcpy( | |||
726 | 712 | ||
727 | if (new) { | 713 | if (new) { |
728 | new->len = len; | 714 | new->len = len; |
715 | new->dst = dma_dest; | ||
716 | new->src = dma_src; | ||
729 | return &new->async_tx; | 717 | return &new->async_tx; |
730 | } else | 718 | } else |
731 | return NULL; | 719 | return NULL; |
@@ -733,8 +721,10 @@ static struct dma_async_tx_descriptor *ioat1_dma_prep_memcpy( | |||
733 | 721 | ||
734 | static struct dma_async_tx_descriptor *ioat2_dma_prep_memcpy( | 722 | static struct dma_async_tx_descriptor *ioat2_dma_prep_memcpy( |
735 | struct dma_chan *chan, | 723 | struct dma_chan *chan, |
724 | dma_addr_t dma_dest, | ||
725 | dma_addr_t dma_src, | ||
736 | size_t len, | 726 | size_t len, |
737 | int int_en) | 727 | unsigned long flags) |
738 | { | 728 | { |
739 | struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan); | 729 | struct ioat_dma_chan *ioat_chan = to_ioat_chan(chan); |
740 | struct ioat_desc_sw *new; | 730 | struct ioat_desc_sw *new; |
@@ -749,6 +739,8 @@ static struct dma_async_tx_descriptor *ioat2_dma_prep_memcpy( | |||
749 | 739 | ||
750 | if (new) { | 740 | if (new) { |
751 | new->len = len; | 741 | new->len = len; |
742 | new->dst = dma_dest; | ||
743 | new->src = dma_src; | ||
752 | return &new->async_tx; | 744 | return &new->async_tx; |
753 | } else | 745 | } else |
754 | return NULL; | 746 | return NULL; |
@@ -1045,7 +1037,7 @@ static int ioat_dma_self_test(struct ioatdma_device *device) | |||
1045 | u8 *dest; | 1037 | u8 *dest; |
1046 | struct dma_chan *dma_chan; | 1038 | struct dma_chan *dma_chan; |
1047 | struct dma_async_tx_descriptor *tx; | 1039 | struct dma_async_tx_descriptor *tx; |
1048 | dma_addr_t addr; | 1040 | dma_addr_t dma_dest, dma_src; |
1049 | dma_cookie_t cookie; | 1041 | dma_cookie_t cookie; |
1050 | int err = 0; | 1042 | int err = 0; |
1051 | 1043 | ||
@@ -1073,7 +1065,12 @@ static int ioat_dma_self_test(struct ioatdma_device *device) | |||
1073 | goto out; | 1065 | goto out; |
1074 | } | 1066 | } |
1075 | 1067 | ||
1076 | tx = device->common.device_prep_dma_memcpy(dma_chan, IOAT_TEST_SIZE, 0); | 1068 | dma_src = dma_map_single(dma_chan->device->dev, src, IOAT_TEST_SIZE, |
1069 | DMA_TO_DEVICE); | ||
1070 | dma_dest = dma_map_single(dma_chan->device->dev, dest, IOAT_TEST_SIZE, | ||
1071 | DMA_FROM_DEVICE); | ||
1072 | tx = device->common.device_prep_dma_memcpy(dma_chan, dma_dest, dma_src, | ||
1073 | IOAT_TEST_SIZE, 0); | ||
1077 | if (!tx) { | 1074 | if (!tx) { |
1078 | dev_err(&device->pdev->dev, | 1075 | dev_err(&device->pdev->dev, |
1079 | "Self-test prep failed, disabling\n"); | 1076 | "Self-test prep failed, disabling\n"); |
@@ -1082,12 +1079,6 @@ static int ioat_dma_self_test(struct ioatdma_device *device) | |||
1082 | } | 1079 | } |
1083 | 1080 | ||
1084 | async_tx_ack(tx); | 1081 | async_tx_ack(tx); |
1085 | addr = dma_map_single(dma_chan->device->dev, src, IOAT_TEST_SIZE, | ||
1086 | DMA_TO_DEVICE); | ||
1087 | tx->tx_set_src(addr, tx, 0); | ||
1088 | addr = dma_map_single(dma_chan->device->dev, dest, IOAT_TEST_SIZE, | ||
1089 | DMA_FROM_DEVICE); | ||
1090 | tx->tx_set_dest(addr, tx, 0); | ||
1091 | tx->callback = ioat_dma_test_callback; | 1082 | tx->callback = ioat_dma_test_callback; |
1092 | tx->callback_param = (void *)0x8086; | 1083 | tx->callback_param = (void *)0x8086; |
1093 | cookie = tx->tx_submit(tx); | 1084 | cookie = tx->tx_submit(tx); |
diff --git a/drivers/dma/iop-adma.c b/drivers/dma/iop-adma.c index e5c62b75f36f..3986d54492bd 100644 --- a/drivers/dma/iop-adma.c +++ b/drivers/dma/iop-adma.c | |||
@@ -284,7 +284,7 @@ iop_adma_alloc_slots(struct iop_adma_chan *iop_chan, int num_slots, | |||
284 | int slots_per_op) | 284 | int slots_per_op) |
285 | { | 285 | { |
286 | struct iop_adma_desc_slot *iter, *_iter, *alloc_start = NULL; | 286 | struct iop_adma_desc_slot *iter, *_iter, *alloc_start = NULL; |
287 | struct list_head chain = LIST_HEAD_INIT(chain); | 287 | LIST_HEAD(chain); |
288 | int slots_found, retry = 0; | 288 | int slots_found, retry = 0; |
289 | 289 | ||
290 | /* start search from the last allocated descrtiptor | 290 | /* start search from the last allocated descrtiptor |
@@ -443,17 +443,6 @@ iop_adma_tx_submit(struct dma_async_tx_descriptor *tx) | |||
443 | return cookie; | 443 | return cookie; |
444 | } | 444 | } |
445 | 445 | ||
446 | static void | ||
447 | iop_adma_set_dest(dma_addr_t addr, struct dma_async_tx_descriptor *tx, | ||
448 | int index) | ||
449 | { | ||
450 | struct iop_adma_desc_slot *sw_desc = tx_to_iop_adma_slot(tx); | ||
451 | struct iop_adma_chan *iop_chan = to_iop_adma_chan(tx->chan); | ||
452 | |||
453 | /* to do: support transfers lengths > IOP_ADMA_MAX_BYTE_COUNT */ | ||
454 | iop_desc_set_dest_addr(sw_desc->group_head, iop_chan, addr); | ||
455 | } | ||
456 | |||
457 | static void iop_chan_start_null_memcpy(struct iop_adma_chan *iop_chan); | 446 | static void iop_chan_start_null_memcpy(struct iop_adma_chan *iop_chan); |
458 | static void iop_chan_start_null_xor(struct iop_adma_chan *iop_chan); | 447 | static void iop_chan_start_null_xor(struct iop_adma_chan *iop_chan); |
459 | 448 | ||
@@ -486,7 +475,6 @@ static int iop_adma_alloc_chan_resources(struct dma_chan *chan) | |||
486 | 475 | ||
487 | dma_async_tx_descriptor_init(&slot->async_tx, chan); | 476 | dma_async_tx_descriptor_init(&slot->async_tx, chan); |
488 | slot->async_tx.tx_submit = iop_adma_tx_submit; | 477 | slot->async_tx.tx_submit = iop_adma_tx_submit; |
489 | slot->async_tx.tx_set_dest = iop_adma_set_dest; | ||
490 | INIT_LIST_HEAD(&slot->chain_node); | 478 | INIT_LIST_HEAD(&slot->chain_node); |
491 | INIT_LIST_HEAD(&slot->slot_node); | 479 | INIT_LIST_HEAD(&slot->slot_node); |
492 | INIT_LIST_HEAD(&slot->async_tx.tx_list); | 480 | INIT_LIST_HEAD(&slot->async_tx.tx_list); |
@@ -547,18 +535,9 @@ iop_adma_prep_dma_interrupt(struct dma_chan *chan) | |||
547 | return sw_desc ? &sw_desc->async_tx : NULL; | 535 | return sw_desc ? &sw_desc->async_tx : NULL; |
548 | } | 536 | } |
549 | 537 | ||
550 | static void | ||
551 | iop_adma_memcpy_set_src(dma_addr_t addr, struct dma_async_tx_descriptor *tx, | ||
552 | int index) | ||
553 | { | ||
554 | struct iop_adma_desc_slot *sw_desc = tx_to_iop_adma_slot(tx); | ||
555 | struct iop_adma_desc_slot *grp_start = sw_desc->group_head; | ||
556 | |||
557 | iop_desc_set_memcpy_src_addr(grp_start, addr); | ||
558 | } | ||
559 | |||
560 | static struct dma_async_tx_descriptor * | 538 | static struct dma_async_tx_descriptor * |
561 | iop_adma_prep_dma_memcpy(struct dma_chan *chan, size_t len, int int_en) | 539 | iop_adma_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dma_dest, |
540 | dma_addr_t dma_src, size_t len, unsigned long flags) | ||
562 | { | 541 | { |
563 | struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan); | 542 | struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan); |
564 | struct iop_adma_desc_slot *sw_desc, *grp_start; | 543 | struct iop_adma_desc_slot *sw_desc, *grp_start; |
@@ -576,11 +555,12 @@ iop_adma_prep_dma_memcpy(struct dma_chan *chan, size_t len, int int_en) | |||
576 | sw_desc = iop_adma_alloc_slots(iop_chan, slot_cnt, slots_per_op); | 555 | sw_desc = iop_adma_alloc_slots(iop_chan, slot_cnt, slots_per_op); |
577 | if (sw_desc) { | 556 | if (sw_desc) { |
578 | grp_start = sw_desc->group_head; | 557 | grp_start = sw_desc->group_head; |
579 | iop_desc_init_memcpy(grp_start, int_en); | 558 | iop_desc_init_memcpy(grp_start, flags); |
580 | iop_desc_set_byte_count(grp_start, iop_chan, len); | 559 | iop_desc_set_byte_count(grp_start, iop_chan, len); |
560 | iop_desc_set_dest_addr(grp_start, iop_chan, dma_dest); | ||
561 | iop_desc_set_memcpy_src_addr(grp_start, dma_src); | ||
581 | sw_desc->unmap_src_cnt = 1; | 562 | sw_desc->unmap_src_cnt = 1; |
582 | sw_desc->unmap_len = len; | 563 | sw_desc->unmap_len = len; |
583 | sw_desc->async_tx.tx_set_src = iop_adma_memcpy_set_src; | ||
584 | } | 564 | } |
585 | spin_unlock_bh(&iop_chan->lock); | 565 | spin_unlock_bh(&iop_chan->lock); |
586 | 566 | ||
@@ -588,8 +568,8 @@ iop_adma_prep_dma_memcpy(struct dma_chan *chan, size_t len, int int_en) | |||
588 | } | 568 | } |
589 | 569 | ||
590 | static struct dma_async_tx_descriptor * | 570 | static struct dma_async_tx_descriptor * |
591 | iop_adma_prep_dma_memset(struct dma_chan *chan, int value, size_t len, | 571 | iop_adma_prep_dma_memset(struct dma_chan *chan, dma_addr_t dma_dest, |
592 | int int_en) | 572 | int value, size_t len, unsigned long flags) |
593 | { | 573 | { |
594 | struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan); | 574 | struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan); |
595 | struct iop_adma_desc_slot *sw_desc, *grp_start; | 575 | struct iop_adma_desc_slot *sw_desc, *grp_start; |
@@ -607,9 +587,10 @@ iop_adma_prep_dma_memset(struct dma_chan *chan, int value, size_t len, | |||
607 | sw_desc = iop_adma_alloc_slots(iop_chan, slot_cnt, slots_per_op); | 587 | sw_desc = iop_adma_alloc_slots(iop_chan, slot_cnt, slots_per_op); |
608 | if (sw_desc) { | 588 | if (sw_desc) { |
609 | grp_start = sw_desc->group_head; | 589 | grp_start = sw_desc->group_head; |
610 | iop_desc_init_memset(grp_start, int_en); | 590 | iop_desc_init_memset(grp_start, flags); |
611 | iop_desc_set_byte_count(grp_start, iop_chan, len); | 591 | iop_desc_set_byte_count(grp_start, iop_chan, len); |
612 | iop_desc_set_block_fill_val(grp_start, value); | 592 | iop_desc_set_block_fill_val(grp_start, value); |
593 | iop_desc_set_dest_addr(grp_start, iop_chan, dma_dest); | ||
613 | sw_desc->unmap_src_cnt = 1; | 594 | sw_desc->unmap_src_cnt = 1; |
614 | sw_desc->unmap_len = len; | 595 | sw_desc->unmap_len = len; |
615 | } | 596 | } |
@@ -618,19 +599,10 @@ iop_adma_prep_dma_memset(struct dma_chan *chan, int value, size_t len, | |||
618 | return sw_desc ? &sw_desc->async_tx : NULL; | 599 | return sw_desc ? &sw_desc->async_tx : NULL; |
619 | } | 600 | } |
620 | 601 | ||
621 | static void | ||
622 | iop_adma_xor_set_src(dma_addr_t addr, struct dma_async_tx_descriptor *tx, | ||
623 | int index) | ||
624 | { | ||
625 | struct iop_adma_desc_slot *sw_desc = tx_to_iop_adma_slot(tx); | ||
626 | struct iop_adma_desc_slot *grp_start = sw_desc->group_head; | ||
627 | |||
628 | iop_desc_set_xor_src_addr(grp_start, index, addr); | ||
629 | } | ||
630 | |||
631 | static struct dma_async_tx_descriptor * | 602 | static struct dma_async_tx_descriptor * |
632 | iop_adma_prep_dma_xor(struct dma_chan *chan, unsigned int src_cnt, size_t len, | 603 | iop_adma_prep_dma_xor(struct dma_chan *chan, dma_addr_t dma_dest, |
633 | int int_en) | 604 | dma_addr_t *dma_src, unsigned int src_cnt, size_t len, |
605 | unsigned long flags) | ||
634 | { | 606 | { |
635 | struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan); | 607 | struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan); |
636 | struct iop_adma_desc_slot *sw_desc, *grp_start; | 608 | struct iop_adma_desc_slot *sw_desc, *grp_start; |
@@ -641,39 +613,32 @@ iop_adma_prep_dma_xor(struct dma_chan *chan, unsigned int src_cnt, size_t len, | |||
641 | BUG_ON(unlikely(len > IOP_ADMA_XOR_MAX_BYTE_COUNT)); | 613 | BUG_ON(unlikely(len > IOP_ADMA_XOR_MAX_BYTE_COUNT)); |
642 | 614 | ||
643 | dev_dbg(iop_chan->device->common.dev, | 615 | dev_dbg(iop_chan->device->common.dev, |
644 | "%s src_cnt: %d len: %u int_en: %d\n", | 616 | "%s src_cnt: %d len: %u flags: %lx\n", |
645 | __FUNCTION__, src_cnt, len, int_en); | 617 | __FUNCTION__, src_cnt, len, flags); |
646 | 618 | ||
647 | spin_lock_bh(&iop_chan->lock); | 619 | spin_lock_bh(&iop_chan->lock); |
648 | slot_cnt = iop_chan_xor_slot_count(len, src_cnt, &slots_per_op); | 620 | slot_cnt = iop_chan_xor_slot_count(len, src_cnt, &slots_per_op); |
649 | sw_desc = iop_adma_alloc_slots(iop_chan, slot_cnt, slots_per_op); | 621 | sw_desc = iop_adma_alloc_slots(iop_chan, slot_cnt, slots_per_op); |
650 | if (sw_desc) { | 622 | if (sw_desc) { |
651 | grp_start = sw_desc->group_head; | 623 | grp_start = sw_desc->group_head; |
652 | iop_desc_init_xor(grp_start, src_cnt, int_en); | 624 | iop_desc_init_xor(grp_start, src_cnt, flags); |
653 | iop_desc_set_byte_count(grp_start, iop_chan, len); | 625 | iop_desc_set_byte_count(grp_start, iop_chan, len); |
626 | iop_desc_set_dest_addr(grp_start, iop_chan, dma_dest); | ||
654 | sw_desc->unmap_src_cnt = src_cnt; | 627 | sw_desc->unmap_src_cnt = src_cnt; |
655 | sw_desc->unmap_len = len; | 628 | sw_desc->unmap_len = len; |
656 | sw_desc->async_tx.tx_set_src = iop_adma_xor_set_src; | 629 | while (src_cnt--) |
630 | iop_desc_set_xor_src_addr(grp_start, src_cnt, | ||
631 | dma_src[src_cnt]); | ||
657 | } | 632 | } |
658 | spin_unlock_bh(&iop_chan->lock); | 633 | spin_unlock_bh(&iop_chan->lock); |
659 | 634 | ||
660 | return sw_desc ? &sw_desc->async_tx : NULL; | 635 | return sw_desc ? &sw_desc->async_tx : NULL; |
661 | } | 636 | } |
662 | 637 | ||
663 | static void | ||
664 | iop_adma_xor_zero_sum_set_src(dma_addr_t addr, | ||
665 | struct dma_async_tx_descriptor *tx, | ||
666 | int index) | ||
667 | { | ||
668 | struct iop_adma_desc_slot *sw_desc = tx_to_iop_adma_slot(tx); | ||
669 | struct iop_adma_desc_slot *grp_start = sw_desc->group_head; | ||
670 | |||
671 | iop_desc_set_zero_sum_src_addr(grp_start, index, addr); | ||
672 | } | ||
673 | |||
674 | static struct dma_async_tx_descriptor * | 638 | static struct dma_async_tx_descriptor * |
675 | iop_adma_prep_dma_zero_sum(struct dma_chan *chan, unsigned int src_cnt, | 639 | iop_adma_prep_dma_zero_sum(struct dma_chan *chan, dma_addr_t *dma_src, |
676 | size_t len, u32 *result, int int_en) | 640 | unsigned int src_cnt, size_t len, u32 *result, |
641 | unsigned long flags) | ||
677 | { | 642 | { |
678 | struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan); | 643 | struct iop_adma_chan *iop_chan = to_iop_adma_chan(chan); |
679 | struct iop_adma_desc_slot *sw_desc, *grp_start; | 644 | struct iop_adma_desc_slot *sw_desc, *grp_start; |
@@ -690,14 +655,16 @@ iop_adma_prep_dma_zero_sum(struct dma_chan *chan, unsigned int src_cnt, | |||
690 | sw_desc = iop_adma_alloc_slots(iop_chan, slot_cnt, slots_per_op); | 655 | sw_desc = iop_adma_alloc_slots(iop_chan, slot_cnt, slots_per_op); |
691 | if (sw_desc) { | 656 | if (sw_desc) { |
692 | grp_start = sw_desc->group_head; | 657 | grp_start = sw_desc->group_head; |
693 | iop_desc_init_zero_sum(grp_start, src_cnt, int_en); | 658 | iop_desc_init_zero_sum(grp_start, src_cnt, flags); |
694 | iop_desc_set_zero_sum_byte_count(grp_start, len); | 659 | iop_desc_set_zero_sum_byte_count(grp_start, len); |
695 | grp_start->xor_check_result = result; | 660 | grp_start->xor_check_result = result; |
696 | pr_debug("\t%s: grp_start->xor_check_result: %p\n", | 661 | pr_debug("\t%s: grp_start->xor_check_result: %p\n", |
697 | __FUNCTION__, grp_start->xor_check_result); | 662 | __FUNCTION__, grp_start->xor_check_result); |
698 | sw_desc->unmap_src_cnt = src_cnt; | 663 | sw_desc->unmap_src_cnt = src_cnt; |
699 | sw_desc->unmap_len = len; | 664 | sw_desc->unmap_len = len; |
700 | sw_desc->async_tx.tx_set_src = iop_adma_xor_zero_sum_set_src; | 665 | while (src_cnt--) |
666 | iop_desc_set_zero_sum_src_addr(grp_start, src_cnt, | ||
667 | dma_src[src_cnt]); | ||
701 | } | 668 | } |
702 | spin_unlock_bh(&iop_chan->lock); | 669 | spin_unlock_bh(&iop_chan->lock); |
703 | 670 | ||
@@ -882,13 +849,12 @@ static int __devinit iop_adma_memcpy_self_test(struct iop_adma_device *device) | |||
882 | goto out; | 849 | goto out; |
883 | } | 850 | } |
884 | 851 | ||
885 | tx = iop_adma_prep_dma_memcpy(dma_chan, IOP_ADMA_TEST_SIZE, 1); | ||
886 | dest_dma = dma_map_single(dma_chan->device->dev, dest, | 852 | dest_dma = dma_map_single(dma_chan->device->dev, dest, |
887 | IOP_ADMA_TEST_SIZE, DMA_FROM_DEVICE); | 853 | IOP_ADMA_TEST_SIZE, DMA_FROM_DEVICE); |
888 | iop_adma_set_dest(dest_dma, tx, 0); | ||
889 | src_dma = dma_map_single(dma_chan->device->dev, src, | 854 | src_dma = dma_map_single(dma_chan->device->dev, src, |
890 | IOP_ADMA_TEST_SIZE, DMA_TO_DEVICE); | 855 | IOP_ADMA_TEST_SIZE, DMA_TO_DEVICE); |
891 | iop_adma_memcpy_set_src(src_dma, tx, 0); | 856 | tx = iop_adma_prep_dma_memcpy(dma_chan, dest_dma, src_dma, |
857 | IOP_ADMA_TEST_SIZE, 1); | ||
892 | 858 | ||
893 | cookie = iop_adma_tx_submit(tx); | 859 | cookie = iop_adma_tx_submit(tx); |
894 | iop_adma_issue_pending(dma_chan); | 860 | iop_adma_issue_pending(dma_chan); |
@@ -929,6 +895,7 @@ iop_adma_xor_zero_sum_self_test(struct iop_adma_device *device) | |||
929 | struct page *dest; | 895 | struct page *dest; |
930 | struct page *xor_srcs[IOP_ADMA_NUM_SRC_TEST]; | 896 | struct page *xor_srcs[IOP_ADMA_NUM_SRC_TEST]; |
931 | struct page *zero_sum_srcs[IOP_ADMA_NUM_SRC_TEST + 1]; | 897 | struct page *zero_sum_srcs[IOP_ADMA_NUM_SRC_TEST + 1]; |
898 | dma_addr_t dma_srcs[IOP_ADMA_NUM_SRC_TEST + 1]; | ||
932 | dma_addr_t dma_addr, dest_dma; | 899 | dma_addr_t dma_addr, dest_dma; |
933 | struct dma_async_tx_descriptor *tx; | 900 | struct dma_async_tx_descriptor *tx; |
934 | struct dma_chan *dma_chan; | 901 | struct dma_chan *dma_chan; |
@@ -981,17 +948,13 @@ iop_adma_xor_zero_sum_self_test(struct iop_adma_device *device) | |||
981 | } | 948 | } |
982 | 949 | ||
983 | /* test xor */ | 950 | /* test xor */ |
984 | tx = iop_adma_prep_dma_xor(dma_chan, IOP_ADMA_NUM_SRC_TEST, | ||
985 | PAGE_SIZE, 1); | ||
986 | dest_dma = dma_map_page(dma_chan->device->dev, dest, 0, | 951 | dest_dma = dma_map_page(dma_chan->device->dev, dest, 0, |
987 | PAGE_SIZE, DMA_FROM_DEVICE); | 952 | PAGE_SIZE, DMA_FROM_DEVICE); |
988 | iop_adma_set_dest(dest_dma, tx, 0); | 953 | for (i = 0; i < IOP_ADMA_NUM_SRC_TEST; i++) |
989 | 954 | dma_srcs[i] = dma_map_page(dma_chan->device->dev, xor_srcs[i], | |
990 | for (i = 0; i < IOP_ADMA_NUM_SRC_TEST; i++) { | 955 | 0, PAGE_SIZE, DMA_TO_DEVICE); |
991 | dma_addr = dma_map_page(dma_chan->device->dev, xor_srcs[i], 0, | 956 | tx = iop_adma_prep_dma_xor(dma_chan, dest_dma, dma_srcs, |
992 | PAGE_SIZE, DMA_TO_DEVICE); | 957 | IOP_ADMA_NUM_SRC_TEST, PAGE_SIZE, 1); |
993 | iop_adma_xor_set_src(dma_addr, tx, i); | ||
994 | } | ||
995 | 958 | ||
996 | cookie = iop_adma_tx_submit(tx); | 959 | cookie = iop_adma_tx_submit(tx); |
997 | iop_adma_issue_pending(dma_chan); | 960 | iop_adma_issue_pending(dma_chan); |
@@ -1032,13 +995,13 @@ iop_adma_xor_zero_sum_self_test(struct iop_adma_device *device) | |||
1032 | 995 | ||
1033 | zero_sum_result = 1; | 996 | zero_sum_result = 1; |
1034 | 997 | ||
1035 | tx = iop_adma_prep_dma_zero_sum(dma_chan, IOP_ADMA_NUM_SRC_TEST + 1, | 998 | for (i = 0; i < IOP_ADMA_NUM_SRC_TEST + 1; i++) |
1036 | PAGE_SIZE, &zero_sum_result, 1); | 999 | dma_srcs[i] = dma_map_page(dma_chan->device->dev, |
1037 | for (i = 0; i < IOP_ADMA_NUM_SRC_TEST + 1; i++) { | 1000 | zero_sum_srcs[i], 0, PAGE_SIZE, |
1038 | dma_addr = dma_map_page(dma_chan->device->dev, zero_sum_srcs[i], | 1001 | DMA_TO_DEVICE); |
1039 | 0, PAGE_SIZE, DMA_TO_DEVICE); | 1002 | tx = iop_adma_prep_dma_zero_sum(dma_chan, dma_srcs, |
1040 | iop_adma_xor_zero_sum_set_src(dma_addr, tx, i); | 1003 | IOP_ADMA_NUM_SRC_TEST + 1, PAGE_SIZE, |
1041 | } | 1004 | &zero_sum_result, 1); |
1042 | 1005 | ||
1043 | cookie = iop_adma_tx_submit(tx); | 1006 | cookie = iop_adma_tx_submit(tx); |
1044 | iop_adma_issue_pending(dma_chan); | 1007 | iop_adma_issue_pending(dma_chan); |
@@ -1060,10 +1023,9 @@ iop_adma_xor_zero_sum_self_test(struct iop_adma_device *device) | |||
1060 | } | 1023 | } |
1061 | 1024 | ||
1062 | /* test memset */ | 1025 | /* test memset */ |
1063 | tx = iop_adma_prep_dma_memset(dma_chan, 0, PAGE_SIZE, 1); | ||
1064 | dma_addr = dma_map_page(dma_chan->device->dev, dest, 0, | 1026 | dma_addr = dma_map_page(dma_chan->device->dev, dest, 0, |
1065 | PAGE_SIZE, DMA_FROM_DEVICE); | 1027 | PAGE_SIZE, DMA_FROM_DEVICE); |
1066 | iop_adma_set_dest(dma_addr, tx, 0); | 1028 | tx = iop_adma_prep_dma_memset(dma_chan, dma_addr, 0, PAGE_SIZE, 1); |
1067 | 1029 | ||
1068 | cookie = iop_adma_tx_submit(tx); | 1030 | cookie = iop_adma_tx_submit(tx); |
1069 | iop_adma_issue_pending(dma_chan); | 1031 | iop_adma_issue_pending(dma_chan); |
@@ -1089,13 +1051,13 @@ iop_adma_xor_zero_sum_self_test(struct iop_adma_device *device) | |||
1089 | 1051 | ||
1090 | /* test for non-zero parity sum */ | 1052 | /* test for non-zero parity sum */ |
1091 | zero_sum_result = 0; | 1053 | zero_sum_result = 0; |
1092 | tx = iop_adma_prep_dma_zero_sum(dma_chan, IOP_ADMA_NUM_SRC_TEST + 1, | 1054 | for (i = 0; i < IOP_ADMA_NUM_SRC_TEST + 1; i++) |
1093 | PAGE_SIZE, &zero_sum_result, 1); | 1055 | dma_srcs[i] = dma_map_page(dma_chan->device->dev, |
1094 | for (i = 0; i < IOP_ADMA_NUM_SRC_TEST + 1; i++) { | 1056 | zero_sum_srcs[i], 0, PAGE_SIZE, |
1095 | dma_addr = dma_map_page(dma_chan->device->dev, zero_sum_srcs[i], | 1057 | DMA_TO_DEVICE); |
1096 | 0, PAGE_SIZE, DMA_TO_DEVICE); | 1058 | tx = iop_adma_prep_dma_zero_sum(dma_chan, dma_srcs, |
1097 | iop_adma_xor_zero_sum_set_src(dma_addr, tx, i); | 1059 | IOP_ADMA_NUM_SRC_TEST + 1, PAGE_SIZE, |
1098 | } | 1060 | &zero_sum_result, 1); |
1099 | 1061 | ||
1100 | cookie = iop_adma_tx_submit(tx); | 1062 | cookie = iop_adma_tx_submit(tx); |
1101 | iop_adma_issue_pending(dma_chan); | 1063 | iop_adma_issue_pending(dma_chan); |
diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig index 98b6b4fb4257..2b382990fe58 100644 --- a/drivers/edac/Kconfig +++ b/drivers/edac/Kconfig | |||
@@ -97,7 +97,7 @@ config EDAC_I82975X | |||
97 | 97 | ||
98 | config EDAC_I3000 | 98 | config EDAC_I3000 |
99 | tristate "Intel 3000/3010" | 99 | tristate "Intel 3000/3010" |
100 | depends on EDAC_MM_EDAC && PCI && X86_32 | 100 | depends on EDAC_MM_EDAC && PCI && X86 |
101 | help | 101 | help |
102 | Support for error detection and correction on the Intel | 102 | Support for error detection and correction on the Intel |
103 | 3000 and 3010 server chipsets. | 103 | 3000 and 3010 server chipsets. |
@@ -123,6 +123,20 @@ config EDAC_I5000 | |||
123 | Support for error detection and correction the Intel | 123 | Support for error detection and correction the Intel |
124 | Greekcreek/Blackford chipsets. | 124 | Greekcreek/Blackford chipsets. |
125 | 125 | ||
126 | config EDAC_MPC85XX | ||
127 | tristate "Freescale MPC85xx" | ||
128 | depends on EDAC_MM_EDAC && FSL_SOC && MPC85xx | ||
129 | help | ||
130 | Support for error detection and correction on the Freescale | ||
131 | MPC8560, MPC8540, MPC8548 | ||
132 | |||
133 | config EDAC_MV64X60 | ||
134 | tristate "Marvell MV64x60" | ||
135 | depends on EDAC_MM_EDAC && MV64X60 | ||
136 | help | ||
137 | Support for error detection and correction on the Marvell | ||
138 | MV64360 and MV64460 chipsets. | ||
139 | |||
126 | config EDAC_PASEMI | 140 | config EDAC_PASEMI |
127 | tristate "PA Semi PWRficient" | 141 | tristate "PA Semi PWRficient" |
128 | depends on EDAC_MM_EDAC && PCI | 142 | depends on EDAC_MM_EDAC && PCI |
@@ -131,5 +145,12 @@ config EDAC_PASEMI | |||
131 | Support for error detection and correction on PA Semi | 145 | Support for error detection and correction on PA Semi |
132 | PWRficient. | 146 | PWRficient. |
133 | 147 | ||
148 | config EDAC_CELL | ||
149 | tristate "Cell Broadband Engine memory controller" | ||
150 | depends on EDAC_MM_EDAC && PPC_CELL_NATIVE | ||
151 | help | ||
152 | Support for error detection and correction on the | ||
153 | Cell Broadband Engine internal memory controller | ||
154 | on platform without a hypervisor | ||
134 | 155 | ||
135 | endif # EDAC | 156 | endif # EDAC |
diff --git a/drivers/edac/Makefile b/drivers/edac/Makefile index 02c09f0ff157..83807731d4a9 100644 --- a/drivers/edac/Makefile +++ b/drivers/edac/Makefile | |||
@@ -28,4 +28,7 @@ obj-$(CONFIG_EDAC_I3000) += i3000_edac.o | |||
28 | obj-$(CONFIG_EDAC_I82860) += i82860_edac.o | 28 | obj-$(CONFIG_EDAC_I82860) += i82860_edac.o |
29 | obj-$(CONFIG_EDAC_R82600) += r82600_edac.o | 29 | obj-$(CONFIG_EDAC_R82600) += r82600_edac.o |
30 | obj-$(CONFIG_EDAC_PASEMI) += pasemi_edac.o | 30 | obj-$(CONFIG_EDAC_PASEMI) += pasemi_edac.o |
31 | obj-$(CONFIG_EDAC_MPC85XX) += mpc85xx_edac.o | ||
32 | obj-$(CONFIG_EDAC_MV64X60) += mv64x60_edac.o | ||
33 | obj-$(CONFIG_EDAC_CELL) += cell_edac.o | ||
31 | 34 | ||
diff --git a/drivers/edac/cell_edac.c b/drivers/edac/cell_edac.c new file mode 100644 index 000000000000..b54112ffd282 --- /dev/null +++ b/drivers/edac/cell_edac.c | |||
@@ -0,0 +1,258 @@ | |||
1 | /* | ||
2 | * Cell MIC driver for ECC counting | ||
3 | * | ||
4 | * Copyright 2007 Benjamin Herrenschmidt, IBM Corp. | ||
5 | * <benh@kernel.crashing.org> | ||
6 | * | ||
7 | * This file may be distributed under the terms of the | ||
8 | * GNU General Public License. | ||
9 | */ | ||
10 | #undef DEBUG | ||
11 | |||
12 | #include <linux/module.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/platform_device.h> | ||
15 | #include <linux/stop_machine.h> | ||
16 | #include <linux/io.h> | ||
17 | #include <asm/machdep.h> | ||
18 | #include <asm/cell-regs.h> | ||
19 | |||
20 | #include "edac_core.h" | ||
21 | |||
22 | struct cell_edac_priv | ||
23 | { | ||
24 | struct cbe_mic_tm_regs __iomem *regs; | ||
25 | int node; | ||
26 | int chanmask; | ||
27 | #ifdef DEBUG | ||
28 | u64 prev_fir; | ||
29 | #endif | ||
30 | }; | ||
31 | |||
32 | static void cell_edac_count_ce(struct mem_ctl_info *mci, int chan, u64 ar) | ||
33 | { | ||
34 | struct cell_edac_priv *priv = mci->pvt_info; | ||
35 | struct csrow_info *csrow = &mci->csrows[0]; | ||
36 | unsigned long address, pfn, offset; | ||
37 | |||
38 | dev_dbg(mci->dev, "ECC CE err on node %d, channel %d, ar = 0x%016lx\n", | ||
39 | priv->node, chan, ar); | ||
40 | |||
41 | /* Address decoding is likely a bit bogus, to dbl check */ | ||
42 | address = (ar & 0xffffffffe0000000ul) >> 29; | ||
43 | if (priv->chanmask == 0x3) | ||
44 | address = (address << 1) | chan; | ||
45 | pfn = address >> PAGE_SHIFT; | ||
46 | offset = address & ~PAGE_MASK; | ||
47 | |||
48 | /* TODO: Decoding of the error addresss */ | ||
49 | edac_mc_handle_ce(mci, csrow->first_page + pfn, offset, | ||
50 | 0, 0, chan, ""); | ||
51 | } | ||
52 | |||
53 | static void cell_edac_count_ue(struct mem_ctl_info *mci, int chan, u64 ar) | ||
54 | { | ||
55 | struct cell_edac_priv *priv = mci->pvt_info; | ||
56 | struct csrow_info *csrow = &mci->csrows[0]; | ||
57 | unsigned long address, pfn, offset; | ||
58 | |||
59 | dev_dbg(mci->dev, "ECC UE err on node %d, channel %d, ar = 0x%016lx\n", | ||
60 | priv->node, chan, ar); | ||
61 | |||
62 | /* Address decoding is likely a bit bogus, to dbl check */ | ||
63 | address = (ar & 0xffffffffe0000000ul) >> 29; | ||
64 | if (priv->chanmask == 0x3) | ||
65 | address = (address << 1) | chan; | ||
66 | pfn = address >> PAGE_SHIFT; | ||
67 | offset = address & ~PAGE_MASK; | ||
68 | |||
69 | /* TODO: Decoding of the error addresss */ | ||
70 | edac_mc_handle_ue(mci, csrow->first_page + pfn, offset, 0, ""); | ||
71 | } | ||
72 | |||
73 | static void cell_edac_check(struct mem_ctl_info *mci) | ||
74 | { | ||
75 | struct cell_edac_priv *priv = mci->pvt_info; | ||
76 | u64 fir, addreg, clear = 0; | ||
77 | |||
78 | fir = in_be64(&priv->regs->mic_fir); | ||
79 | #ifdef DEBUG | ||
80 | if (fir != priv->prev_fir) { | ||
81 | dev_dbg(mci->dev, "fir change : 0x%016lx\n", fir); | ||
82 | priv->prev_fir = fir; | ||
83 | } | ||
84 | #endif | ||
85 | if ((priv->chanmask & 0x1) && (fir & CBE_MIC_FIR_ECC_SINGLE_0_ERR)) { | ||
86 | addreg = in_be64(&priv->regs->mic_df_ecc_address_0); | ||
87 | clear |= CBE_MIC_FIR_ECC_SINGLE_0_RESET; | ||
88 | cell_edac_count_ce(mci, 0, addreg); | ||
89 | } | ||
90 | if ((priv->chanmask & 0x2) && (fir & CBE_MIC_FIR_ECC_SINGLE_1_ERR)) { | ||
91 | addreg = in_be64(&priv->regs->mic_df_ecc_address_1); | ||
92 | clear |= CBE_MIC_FIR_ECC_SINGLE_1_RESET; | ||
93 | cell_edac_count_ce(mci, 1, addreg); | ||
94 | } | ||
95 | if ((priv->chanmask & 0x1) && (fir & CBE_MIC_FIR_ECC_MULTI_0_ERR)) { | ||
96 | addreg = in_be64(&priv->regs->mic_df_ecc_address_0); | ||
97 | clear |= CBE_MIC_FIR_ECC_MULTI_0_RESET; | ||
98 | cell_edac_count_ue(mci, 0, addreg); | ||
99 | } | ||
100 | if ((priv->chanmask & 0x2) && (fir & CBE_MIC_FIR_ECC_MULTI_1_ERR)) { | ||
101 | addreg = in_be64(&priv->regs->mic_df_ecc_address_1); | ||
102 | clear |= CBE_MIC_FIR_ECC_MULTI_1_RESET; | ||
103 | cell_edac_count_ue(mci, 1, addreg); | ||
104 | } | ||
105 | |||
106 | /* The procedure for clearing FIR bits is a bit ... weird */ | ||
107 | if (clear) { | ||
108 | fir &= ~(CBE_MIC_FIR_ECC_ERR_MASK | CBE_MIC_FIR_ECC_SET_MASK); | ||
109 | fir |= CBE_MIC_FIR_ECC_RESET_MASK; | ||
110 | fir &= ~clear; | ||
111 | out_be64(&priv->regs->mic_fir, fir); | ||
112 | (void)in_be64(&priv->regs->mic_fir); | ||
113 | |||
114 | mb(); /* sync up */ | ||
115 | #ifdef DEBUG | ||
116 | fir = in_be64(&priv->regs->mic_fir); | ||
117 | dev_dbg(mci->dev, "fir clear : 0x%016lx\n", fir); | ||
118 | #endif | ||
119 | } | ||
120 | } | ||
121 | |||
122 | static void __devinit cell_edac_init_csrows(struct mem_ctl_info *mci) | ||
123 | { | ||
124 | struct csrow_info *csrow = &mci->csrows[0]; | ||
125 | struct cell_edac_priv *priv = mci->pvt_info; | ||
126 | struct device_node *np; | ||
127 | |||
128 | for (np = NULL; | ||
129 | (np = of_find_node_by_name(np, "memory")) != NULL;) { | ||
130 | struct resource r; | ||
131 | |||
132 | /* We "know" that the Cell firmware only creates one entry | ||
133 | * in the "memory" nodes. If that changes, this code will | ||
134 | * need to be adapted. | ||
135 | */ | ||
136 | if (of_address_to_resource(np, 0, &r)) | ||
137 | continue; | ||
138 | if (of_node_to_nid(np) != priv->node) | ||
139 | continue; | ||
140 | csrow->first_page = r.start >> PAGE_SHIFT; | ||
141 | csrow->nr_pages = (r.end - r.start + 1) >> PAGE_SHIFT; | ||
142 | csrow->last_page = csrow->first_page + csrow->nr_pages - 1; | ||
143 | csrow->mtype = MEM_XDR; | ||
144 | csrow->edac_mode = EDAC_FLAG_EC | EDAC_FLAG_SECDED; | ||
145 | dev_dbg(mci->dev, | ||
146 | "Initialized on node %d, chanmask=0x%x," | ||
147 | " first_page=0x%lx, nr_pages=0x%x\n", | ||
148 | priv->node, priv->chanmask, | ||
149 | csrow->first_page, csrow->nr_pages); | ||
150 | break; | ||
151 | } | ||
152 | } | ||
153 | |||
154 | static int __devinit cell_edac_probe(struct platform_device *pdev) | ||
155 | { | ||
156 | struct cbe_mic_tm_regs __iomem *regs; | ||
157 | struct mem_ctl_info *mci; | ||
158 | struct cell_edac_priv *priv; | ||
159 | u64 reg; | ||
160 | int rc, chanmask; | ||
161 | |||
162 | regs = cbe_get_cpu_mic_tm_regs(cbe_node_to_cpu(pdev->id)); | ||
163 | if (regs == NULL) | ||
164 | return -ENODEV; | ||
165 | |||
166 | /* Get channel population */ | ||
167 | reg = in_be64(®s->mic_mnt_cfg); | ||
168 | dev_dbg(&pdev->dev, "MIC_MNT_CFG = 0x%016lx\n", reg); | ||
169 | chanmask = 0; | ||
170 | if (reg & CBE_MIC_MNT_CFG_CHAN_0_POP) | ||
171 | chanmask |= 0x1; | ||
172 | if (reg & CBE_MIC_MNT_CFG_CHAN_1_POP) | ||
173 | chanmask |= 0x2; | ||
174 | if (chanmask == 0) { | ||
175 | dev_warn(&pdev->dev, | ||
176 | "Yuck ! No channel populated ? Aborting !\n"); | ||
177 | return -ENODEV; | ||
178 | } | ||
179 | dev_dbg(&pdev->dev, "Initial FIR = 0x%016lx\n", | ||
180 | in_be64(®s->mic_fir)); | ||
181 | |||
182 | /* Allocate & init EDAC MC data structure */ | ||
183 | mci = edac_mc_alloc(sizeof(struct cell_edac_priv), 1, | ||
184 | chanmask == 3 ? 2 : 1, pdev->id); | ||
185 | if (mci == NULL) | ||
186 | return -ENOMEM; | ||
187 | priv = mci->pvt_info; | ||
188 | priv->regs = regs; | ||
189 | priv->node = pdev->id; | ||
190 | priv->chanmask = chanmask; | ||
191 | mci->dev = &pdev->dev; | ||
192 | mci->mtype_cap = MEM_FLAG_XDR; | ||
193 | mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED; | ||
194 | mci->edac_cap = EDAC_FLAG_EC | EDAC_FLAG_SECDED; | ||
195 | mci->mod_name = "cell_edac"; | ||
196 | mci->ctl_name = "MIC"; | ||
197 | mci->dev_name = pdev->dev.bus_id; | ||
198 | mci->edac_check = cell_edac_check; | ||
199 | cell_edac_init_csrows(mci); | ||
200 | |||
201 | /* Register with EDAC core */ | ||
202 | rc = edac_mc_add_mc(mci); | ||
203 | if (rc) { | ||
204 | dev_err(&pdev->dev, "failed to register with EDAC core\n"); | ||
205 | edac_mc_free(mci); | ||
206 | return rc; | ||
207 | } | ||
208 | |||
209 | return 0; | ||
210 | } | ||
211 | |||
212 | static int __devexit cell_edac_remove(struct platform_device *pdev) | ||
213 | { | ||
214 | struct mem_ctl_info *mci = edac_mc_del_mc(&pdev->dev); | ||
215 | if (mci) | ||
216 | edac_mc_free(mci); | ||
217 | return 0; | ||
218 | } | ||
219 | |||
220 | static struct platform_driver cell_edac_driver = { | ||
221 | .driver = { | ||
222 | .name = "cbe-mic", | ||
223 | .owner = THIS_MODULE, | ||
224 | }, | ||
225 | .probe = cell_edac_probe, | ||
226 | .remove = cell_edac_remove, | ||
227 | }; | ||
228 | |||
229 | static int __init cell_edac_init(void) | ||
230 | { | ||
231 | /* Sanity check registers data structure */ | ||
232 | BUILD_BUG_ON(offsetof(struct cbe_mic_tm_regs, | ||
233 | mic_df_ecc_address_0) != 0xf8); | ||
234 | BUILD_BUG_ON(offsetof(struct cbe_mic_tm_regs, | ||
235 | mic_df_ecc_address_1) != 0x1b8); | ||
236 | BUILD_BUG_ON(offsetof(struct cbe_mic_tm_regs, | ||
237 | mic_df_config) != 0x218); | ||
238 | BUILD_BUG_ON(offsetof(struct cbe_mic_tm_regs, | ||
239 | mic_fir) != 0x230); | ||
240 | BUILD_BUG_ON(offsetof(struct cbe_mic_tm_regs, | ||
241 | mic_mnt_cfg) != 0x210); | ||
242 | BUILD_BUG_ON(offsetof(struct cbe_mic_tm_regs, | ||
243 | mic_exc) != 0x208); | ||
244 | |||
245 | return platform_driver_register(&cell_edac_driver); | ||
246 | } | ||
247 | |||
248 | static void __exit cell_edac_exit(void) | ||
249 | { | ||
250 | platform_driver_unregister(&cell_edac_driver); | ||
251 | } | ||
252 | |||
253 | module_init(cell_edac_init); | ||
254 | module_exit(cell_edac_exit); | ||
255 | |||
256 | MODULE_LICENSE("GPL"); | ||
257 | MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>"); | ||
258 | MODULE_DESCRIPTION("ECC counting for Cell MIC"); | ||
diff --git a/drivers/edac/edac_core.h b/drivers/edac/edac_core.h index 2d23e304f5ec..a9aa845dbe74 100644 --- a/drivers/edac/edac_core.h +++ b/drivers/edac/edac_core.h | |||
@@ -136,6 +136,7 @@ enum mem_type { | |||
136 | MEM_DDR2, /* DDR2 RAM */ | 136 | MEM_DDR2, /* DDR2 RAM */ |
137 | MEM_FB_DDR2, /* fully buffered DDR2 */ | 137 | MEM_FB_DDR2, /* fully buffered DDR2 */ |
138 | MEM_RDDR2, /* Registered DDR2 RAM */ | 138 | MEM_RDDR2, /* Registered DDR2 RAM */ |
139 | MEM_XDR, /* Rambus XDR */ | ||
139 | }; | 140 | }; |
140 | 141 | ||
141 | #define MEM_FLAG_EMPTY BIT(MEM_EMPTY) | 142 | #define MEM_FLAG_EMPTY BIT(MEM_EMPTY) |
@@ -152,6 +153,7 @@ enum mem_type { | |||
152 | #define MEM_FLAG_DDR2 BIT(MEM_DDR2) | 153 | #define MEM_FLAG_DDR2 BIT(MEM_DDR2) |
153 | #define MEM_FLAG_FB_DDR2 BIT(MEM_FB_DDR2) | 154 | #define MEM_FLAG_FB_DDR2 BIT(MEM_FB_DDR2) |
154 | #define MEM_FLAG_RDDR2 BIT(MEM_RDDR2) | 155 | #define MEM_FLAG_RDDR2 BIT(MEM_RDDR2) |
156 | #define MEM_FLAG_XDR BIT(MEM_XDR) | ||
155 | 157 | ||
156 | /* chipset Error Detection and Correction capabilities and mode */ | 158 | /* chipset Error Detection and Correction capabilities and mode */ |
157 | enum edac_type { | 159 | enum edac_type { |
diff --git a/drivers/edac/edac_device.c b/drivers/edac/edac_device.c index f3690a697cf9..b9552bc03dea 100644 --- a/drivers/edac/edac_device.c +++ b/drivers/edac/edac_device.c | |||
@@ -155,6 +155,10 @@ struct edac_device_ctl_info *edac_device_alloc_ctl_info( | |||
155 | dev_ctl->instances = dev_inst; | 155 | dev_ctl->instances = dev_inst; |
156 | dev_ctl->pvt_info = pvt; | 156 | dev_ctl->pvt_info = pvt; |
157 | 157 | ||
158 | /* Default logging of CEs and UEs */ | ||
159 | dev_ctl->log_ce = 1; | ||
160 | dev_ctl->log_ue = 1; | ||
161 | |||
158 | /* Name of this edac device */ | 162 | /* Name of this edac device */ |
159 | snprintf(dev_ctl->name,sizeof(dev_ctl->name),"%s",edac_device_name); | 163 | snprintf(dev_ctl->name,sizeof(dev_ctl->name),"%s",edac_device_name); |
160 | 164 | ||
@@ -436,7 +440,7 @@ static void edac_device_workq_function(struct work_struct *work_req) | |||
436 | */ | 440 | */ |
437 | if (edac_dev->poll_msec == 1000) | 441 | if (edac_dev->poll_msec == 1000) |
438 | queue_delayed_work(edac_workqueue, &edac_dev->work, | 442 | queue_delayed_work(edac_workqueue, &edac_dev->work, |
439 | round_jiffies(edac_dev->delay)); | 443 | round_jiffies_relative(edac_dev->delay)); |
440 | else | 444 | else |
441 | queue_delayed_work(edac_workqueue, &edac_dev->work, | 445 | queue_delayed_work(edac_workqueue, &edac_dev->work, |
442 | edac_dev->delay); | 446 | edac_dev->delay); |
@@ -468,7 +472,7 @@ void edac_device_workq_setup(struct edac_device_ctl_info *edac_dev, | |||
468 | */ | 472 | */ |
469 | if (edac_dev->poll_msec == 1000) | 473 | if (edac_dev->poll_msec == 1000) |
470 | queue_delayed_work(edac_workqueue, &edac_dev->work, | 474 | queue_delayed_work(edac_workqueue, &edac_dev->work, |
471 | round_jiffies(edac_dev->delay)); | 475 | round_jiffies_relative(edac_dev->delay)); |
472 | else | 476 | else |
473 | queue_delayed_work(edac_workqueue, &edac_dev->work, | 477 | queue_delayed_work(edac_workqueue, &edac_dev->work, |
474 | edac_dev->delay); | 478 | edac_dev->delay); |
diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c index 9aac88027fb3..021d18795145 100644 --- a/drivers/edac/edac_mc_sysfs.c +++ b/drivers/edac/edac_mc_sysfs.c | |||
@@ -73,7 +73,8 @@ static const char *mem_types[] = { | |||
73 | [MEM_RMBS] = "RMBS", | 73 | [MEM_RMBS] = "RMBS", |
74 | [MEM_DDR2] = "Unbuffered-DDR2", | 74 | [MEM_DDR2] = "Unbuffered-DDR2", |
75 | [MEM_FB_DDR2] = "FullyBuffered-DDR2", | 75 | [MEM_FB_DDR2] = "FullyBuffered-DDR2", |
76 | [MEM_RDDR2] = "Registered-DDR2" | 76 | [MEM_RDDR2] = "Registered-DDR2", |
77 | [MEM_XDR] = "XDR" | ||
77 | }; | 78 | }; |
78 | 79 | ||
79 | static const char *dev_types[] = { | 80 | static const char *dev_types[] = { |
diff --git a/drivers/edac/edac_pci.c b/drivers/edac/edac_pci.c index e0b47b74ec45..32be43576a8e 100644 --- a/drivers/edac/edac_pci.c +++ b/drivers/edac/edac_pci.c | |||
@@ -246,7 +246,7 @@ static void edac_pci_workq_function(struct work_struct *work_req) | |||
246 | /* if we are on a one second period, then use round */ | 246 | /* if we are on a one second period, then use round */ |
247 | msec = edac_pci_get_poll_msec(); | 247 | msec = edac_pci_get_poll_msec(); |
248 | if (msec == 1000) | 248 | if (msec == 1000) |
249 | delay = round_jiffies(msecs_to_jiffies(msec)); | 249 | delay = round_jiffies_relative(msecs_to_jiffies(msec)); |
250 | else | 250 | else |
251 | delay = msecs_to_jiffies(msec); | 251 | delay = msecs_to_jiffies(msec); |
252 | 252 | ||
diff --git a/drivers/edac/edac_pci_sysfs.c b/drivers/edac/edac_pci_sysfs.c index 5b075da99145..71c3195d3704 100644 --- a/drivers/edac/edac_pci_sysfs.c +++ b/drivers/edac/edac_pci_sysfs.c | |||
@@ -558,8 +558,10 @@ static void edac_pci_dev_parity_test(struct pci_dev *dev) | |||
558 | 558 | ||
559 | debugf4("PCI STATUS= 0x%04x %s\n", status, dev->dev.bus_id); | 559 | debugf4("PCI STATUS= 0x%04x %s\n", status, dev->dev.bus_id); |
560 | 560 | ||
561 | /* check the status reg for errors */ | 561 | /* check the status reg for errors on boards NOT marked as broken |
562 | if (status) { | 562 | * if broken, we cannot trust any of the status bits |
563 | */ | ||
564 | if (status && !dev->broken_parity_status) { | ||
563 | if (status & (PCI_STATUS_SIG_SYSTEM_ERROR)) { | 565 | if (status & (PCI_STATUS_SIG_SYSTEM_ERROR)) { |
564 | edac_printk(KERN_CRIT, EDAC_PCI, | 566 | edac_printk(KERN_CRIT, EDAC_PCI, |
565 | "Signaled System Error on %s\n", | 567 | "Signaled System Error on %s\n", |
@@ -593,8 +595,10 @@ static void edac_pci_dev_parity_test(struct pci_dev *dev) | |||
593 | 595 | ||
594 | debugf4("PCI SEC_STATUS= 0x%04x %s\n", status, dev->dev.bus_id); | 596 | debugf4("PCI SEC_STATUS= 0x%04x %s\n", status, dev->dev.bus_id); |
595 | 597 | ||
596 | /* check the secondary status reg for errors */ | 598 | /* check the secondary status reg for errors, |
597 | if (status) { | 599 | * on NOT broken boards |
600 | */ | ||
601 | if (status && !dev->broken_parity_status) { | ||
598 | if (status & (PCI_STATUS_SIG_SYSTEM_ERROR)) { | 602 | if (status & (PCI_STATUS_SIG_SYSTEM_ERROR)) { |
599 | edac_printk(KERN_CRIT, EDAC_PCI, "Bridge " | 603 | edac_printk(KERN_CRIT, EDAC_PCI, "Bridge " |
600 | "Signaled System Error on %s\n", | 604 | "Signaled System Error on %s\n", |
diff --git a/drivers/edac/i3000_edac.c b/drivers/edac/i3000_edac.c index e895f9f887ab..5d4292811c14 100644 --- a/drivers/edac/i3000_edac.c +++ b/drivers/edac/i3000_edac.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/pci.h> | 14 | #include <linux/pci.h> |
15 | #include <linux/pci_ids.h> | 15 | #include <linux/pci_ids.h> |
16 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
17 | #include <linux/edac.h> | ||
17 | #include "edac_core.h" | 18 | #include "edac_core.h" |
18 | 19 | ||
19 | #define I3000_REVISION "1.1" | 20 | #define I3000_REVISION "1.1" |
@@ -30,105 +31,139 @@ | |||
30 | #define I3000_MCHBAR_MASK 0xffffc000 | 31 | #define I3000_MCHBAR_MASK 0xffffc000 |
31 | #define I3000_MMR_WINDOW_SIZE 16384 | 32 | #define I3000_MMR_WINDOW_SIZE 16384 |
32 | 33 | ||
33 | #define I3000_EDEAP 0x70 /* Extended DRAM Error Address Pointer (8b) | 34 | #define I3000_EDEAP 0x70 /* Extended DRAM Error Address Pointer (8b) |
34 | * | 35 | * |
35 | * 7:1 reserved | 36 | * 7:1 reserved |
36 | * 0 bit 32 of address | 37 | * 0 bit 32 of address |
37 | */ | 38 | */ |
38 | #define I3000_DEAP 0x58 /* DRAM Error Address Pointer (32b) | 39 | #define I3000_DEAP 0x58 /* DRAM Error Address Pointer (32b) |
39 | * | 40 | * |
40 | * 31:7 address | 41 | * 31:7 address |
41 | * 6:1 reserved | 42 | * 6:1 reserved |
42 | * 0 Error channel 0/1 | 43 | * 0 Error channel 0/1 |
43 | */ | 44 | */ |
44 | #define I3000_DEAP_GRAIN (1 << 7) | 45 | #define I3000_DEAP_GRAIN (1 << 7) |
45 | #define I3000_DEAP_PFN(edeap, deap) ((((edeap) & 1) << (32 - PAGE_SHIFT)) | \ | 46 | |
46 | ((deap) >> PAGE_SHIFT)) | 47 | /* |
47 | #define I3000_DEAP_OFFSET(deap) ((deap) & ~(I3000_DEAP_GRAIN-1) & ~PAGE_MASK) | 48 | * Helper functions to decode the DEAP/EDEAP hardware registers. |
48 | #define I3000_DEAP_CHANNEL(deap) ((deap) & 1) | 49 | * |
49 | 50 | * The type promotion here is deliberate; we're deriving an | |
50 | #define I3000_DERRSYN 0x5c /* DRAM Error Syndrome (8b) | 51 | * unsigned long pfn and offset from hardware regs which are u8/u32. |
51 | * | 52 | */ |
52 | * 7:0 DRAM ECC Syndrome | 53 | |
53 | */ | 54 | static inline unsigned long deap_pfn(u8 edeap, u32 deap) |
54 | 55 | { | |
55 | #define I3000_ERRSTS 0xc8 /* Error Status Register (16b) | 56 | deap >>= PAGE_SHIFT; |
56 | * | 57 | deap |= (edeap & 1) << (32 - PAGE_SHIFT); |
57 | * 15:12 reserved | 58 | return deap; |
58 | * 11 MCH Thermal Sensor Event for SMI/SCI/SERR | 59 | } |
59 | * 10 reserved | 60 | |
60 | * 9 LOCK to non-DRAM Memory Flag (LCKF) | 61 | static inline unsigned long deap_offset(u32 deap) |
61 | * 8 Received Refresh Timeout Flag (RRTOF) | 62 | { |
62 | * 7:2 reserved | 63 | return deap & ~(I3000_DEAP_GRAIN - 1) & ~PAGE_MASK; |
63 | * 1 Multiple-bit DRAM ECC Error Flag (DMERR) | 64 | } |
64 | * 0 Single-bit DRAM ECC Error Flag (DSERR) | 65 | |
65 | */ | 66 | static inline int deap_channel(u32 deap) |
67 | { | ||
68 | return deap & 1; | ||
69 | } | ||
70 | |||
71 | #define I3000_DERRSYN 0x5c /* DRAM Error Syndrome (8b) | ||
72 | * | ||
73 | * 7:0 DRAM ECC Syndrome | ||
74 | */ | ||
75 | |||
76 | #define I3000_ERRSTS 0xc8 /* Error Status Register (16b) | ||
77 | * | ||
78 | * 15:12 reserved | ||
79 | * 11 MCH Thermal Sensor Event | ||
80 | * for SMI/SCI/SERR | ||
81 | * 10 reserved | ||
82 | * 9 LOCK to non-DRAM Memory Flag (LCKF) | ||
83 | * 8 Received Refresh Timeout Flag (RRTOF) | ||
84 | * 7:2 reserved | ||
85 | * 1 Multi-bit DRAM ECC Error Flag (DMERR) | ||
86 | * 0 Single-bit DRAM ECC Error Flag (DSERR) | ||
87 | */ | ||
66 | #define I3000_ERRSTS_BITS 0x0b03 /* bits which indicate errors */ | 88 | #define I3000_ERRSTS_BITS 0x0b03 /* bits which indicate errors */ |
67 | #define I3000_ERRSTS_UE 0x0002 | 89 | #define I3000_ERRSTS_UE 0x0002 |
68 | #define I3000_ERRSTS_CE 0x0001 | 90 | #define I3000_ERRSTS_CE 0x0001 |
69 | 91 | ||
70 | #define I3000_ERRCMD 0xca /* Error Command (16b) | 92 | #define I3000_ERRCMD 0xca /* Error Command (16b) |
71 | * | 93 | * |
72 | * 15:12 reserved | 94 | * 15:12 reserved |
73 | * 11 SERR on MCH Thermal Sensor Event (TSESERR) | 95 | * 11 SERR on MCH Thermal Sensor Event |
74 | * 10 reserved | 96 | * (TSESERR) |
75 | * 9 SERR on LOCK to non-DRAM Memory (LCKERR) | 97 | * 10 reserved |
76 | * 8 SERR on DRAM Refresh Timeout (DRTOERR) | 98 | * 9 SERR on LOCK to non-DRAM Memory |
77 | * 7:2 reserved | 99 | * (LCKERR) |
78 | * 1 SERR Multiple-Bit DRAM ECC Error (DMERR) | 100 | * 8 SERR on DRAM Refresh Timeout |
79 | * 0 SERR on Single-Bit ECC Error (DSERR) | 101 | * (DRTOERR) |
80 | */ | 102 | * 7:2 reserved |
103 | * 1 SERR Multi-Bit DRAM ECC Error | ||
104 | * (DMERR) | ||
105 | * 0 SERR on Single-Bit ECC Error | ||
106 | * (DSERR) | ||
107 | */ | ||
81 | 108 | ||
82 | /* Intel MMIO register space - device 0 function 0 - MMR space */ | 109 | /* Intel MMIO register space - device 0 function 0 - MMR space */ |
83 | 110 | ||
84 | #define I3000_DRB_SHIFT 25 /* 32MiB grain */ | 111 | #define I3000_DRB_SHIFT 25 /* 32MiB grain */ |
85 | 112 | ||
86 | #define I3000_C0DRB 0x100 /* Channel 0 DRAM Rank Boundary (8b x 4) | 113 | #define I3000_C0DRB 0x100 /* Channel 0 DRAM Rank Boundary (8b x 4) |
87 | * | 114 | * |
88 | * 7:0 Channel 0 DRAM Rank Boundary Address | 115 | * 7:0 Channel 0 DRAM Rank Boundary Address |
89 | */ | 116 | */ |
90 | #define I3000_C1DRB 0x180 /* Channel 1 DRAM Rank Boundary (8b x 4) | 117 | #define I3000_C1DRB 0x180 /* Channel 1 DRAM Rank Boundary (8b x 4) |
91 | * | 118 | * |
92 | * 7:0 Channel 1 DRAM Rank Boundary Address | 119 | * 7:0 Channel 1 DRAM Rank Boundary Address |
93 | */ | 120 | */ |
94 | 121 | ||
95 | #define I3000_C0DRA 0x108 /* Channel 0 DRAM Rank Attribute (8b x 2) | 122 | #define I3000_C0DRA 0x108 /* Channel 0 DRAM Rank Attribute (8b x 2) |
96 | * | 123 | * |
97 | * 7 reserved | 124 | * 7 reserved |
98 | * 6:4 DRAM odd Rank Attribute | 125 | * 6:4 DRAM odd Rank Attribute |
99 | * 3 reserved | 126 | * 3 reserved |
100 | * 2:0 DRAM even Rank Attribute | 127 | * 2:0 DRAM even Rank Attribute |
101 | * | 128 | * |
102 | * Each attribute defines the page | 129 | * Each attribute defines the page |
103 | * size of the corresponding rank: | 130 | * size of the corresponding rank: |
104 | * 000: unpopulated | 131 | * 000: unpopulated |
105 | * 001: reserved | 132 | * 001: reserved |
106 | * 010: 4 KB | 133 | * 010: 4 KB |
107 | * 011: 8 KB | 134 | * 011: 8 KB |
108 | * 100: 16 KB | 135 | * 100: 16 KB |
109 | * Others: reserved | 136 | * Others: reserved |
110 | */ | 137 | */ |
111 | #define I3000_C1DRA 0x188 /* Channel 1 DRAM Rank Attribute (8b x 2) */ | 138 | #define I3000_C1DRA 0x188 /* Channel 1 DRAM Rank Attribute (8b x 2) */ |
112 | #define ODD_RANK_ATTRIB(dra) (((dra) & 0x70) >> 4) | 139 | |
113 | #define EVEN_RANK_ATTRIB(dra) ((dra) & 0x07) | 140 | static inline unsigned char odd_rank_attrib(unsigned char dra) |
114 | 141 | { | |
115 | #define I3000_C0DRC0 0x120 /* DRAM Controller Mode 0 (32b) | 142 | return (dra & 0x70) >> 4; |
116 | * | 143 | } |
117 | * 31:30 reserved | 144 | |
118 | * 29 Initialization Complete (IC) | 145 | static inline unsigned char even_rank_attrib(unsigned char dra) |
119 | * 28:11 reserved | 146 | { |
120 | * 10:8 Refresh Mode Select (RMS) | 147 | return dra & 0x07; |
121 | * 7 reserved | 148 | } |
122 | * 6:4 Mode Select (SMS) | 149 | |
123 | * 3:2 reserved | 150 | #define I3000_C0DRC0 0x120 /* DRAM Controller Mode 0 (32b) |
124 | * 1:0 DRAM Type (DT) | 151 | * |
125 | */ | 152 | * 31:30 reserved |
126 | 153 | * 29 Initialization Complete (IC) | |
127 | #define I3000_C0DRC1 0x124 /* DRAM Controller Mode 1 (32b) | 154 | * 28:11 reserved |
128 | * | 155 | * 10:8 Refresh Mode Select (RMS) |
129 | * 31 Enhanced Addressing Enable (ENHADE) | 156 | * 7 reserved |
130 | * 30:0 reserved | 157 | * 6:4 Mode Select (SMS) |
131 | */ | 158 | * 3:2 reserved |
159 | * 1:0 DRAM Type (DT) | ||
160 | */ | ||
161 | |||
162 | #define I3000_C0DRC1 0x124 /* DRAM Controller Mode 1 (32b) | ||
163 | * | ||
164 | * 31 Enhanced Addressing Enable (ENHADE) | ||
165 | * 30:0 reserved | ||
166 | */ | ||
132 | 167 | ||
133 | enum i3000p_chips { | 168 | enum i3000p_chips { |
134 | I3000 = 0, | 169 | I3000 = 0, |
@@ -187,7 +222,8 @@ static void i3000_get_error_info(struct mem_ctl_info *mci, | |||
187 | pci_read_config_byte(pdev, I3000_DERRSYN, &info->derrsyn); | 222 | pci_read_config_byte(pdev, I3000_DERRSYN, &info->derrsyn); |
188 | } | 223 | } |
189 | 224 | ||
190 | /* Clear any error bits. | 225 | /* |
226 | * Clear any error bits. | ||
191 | * (Yes, we really clear bits by writing 1 to them.) | 227 | * (Yes, we really clear bits by writing 1 to them.) |
192 | */ | 228 | */ |
193 | pci_write_bits16(pdev, I3000_ERRSTS, I3000_ERRSTS_BITS, | 229 | pci_write_bits16(pdev, I3000_ERRSTS, I3000_ERRSTS_BITS, |
@@ -198,8 +234,8 @@ static int i3000_process_error_info(struct mem_ctl_info *mci, | |||
198 | struct i3000_error_info *info, | 234 | struct i3000_error_info *info, |
199 | int handle_errors) | 235 | int handle_errors) |
200 | { | 236 | { |
201 | int row, multi_chan; | 237 | int row, multi_chan, channel; |
202 | int pfn, offset, channel; | 238 | unsigned long pfn, offset; |
203 | 239 | ||
204 | multi_chan = mci->csrows[0].nr_channels - 1; | 240 | multi_chan = mci->csrows[0].nr_channels - 1; |
205 | 241 | ||
@@ -214,9 +250,9 @@ static int i3000_process_error_info(struct mem_ctl_info *mci, | |||
214 | info->errsts = info->errsts2; | 250 | info->errsts = info->errsts2; |
215 | } | 251 | } |
216 | 252 | ||
217 | pfn = I3000_DEAP_PFN(info->edeap, info->deap); | 253 | pfn = deap_pfn(info->edeap, info->deap); |
218 | offset = I3000_DEAP_OFFSET(info->deap); | 254 | offset = deap_offset(info->deap); |
219 | channel = I3000_DEAP_CHANNEL(info->deap); | 255 | channel = deap_channel(info->deap); |
220 | 256 | ||
221 | row = edac_mc_find_csrow_by_page(mci, pfn); | 257 | row = edac_mc_find_csrow_by_page(mci, pfn); |
222 | 258 | ||
@@ -245,16 +281,18 @@ static int i3000_is_interleaved(const unsigned char *c0dra, | |||
245 | { | 281 | { |
246 | int i; | 282 | int i; |
247 | 283 | ||
248 | /* If the channels aren't populated identically then | 284 | /* |
285 | * If the channels aren't populated identically then | ||
249 | * we're not interleaved. | 286 | * we're not interleaved. |
250 | */ | 287 | */ |
251 | for (i = 0; i < I3000_RANKS_PER_CHANNEL / 2; i++) | 288 | for (i = 0; i < I3000_RANKS_PER_CHANNEL / 2; i++) |
252 | if (ODD_RANK_ATTRIB(c0dra[i]) != ODD_RANK_ATTRIB(c1dra[i]) || | 289 | if (odd_rank_attrib(c0dra[i]) != odd_rank_attrib(c1dra[i]) || |
253 | EVEN_RANK_ATTRIB(c0dra[i]) != | 290 | even_rank_attrib(c0dra[i]) != |
254 | EVEN_RANK_ATTRIB(c1dra[i])) | 291 | even_rank_attrib(c1dra[i])) |
255 | return 0; | 292 | return 0; |
256 | 293 | ||
257 | /* If the rank boundaries for the two channels are different | 294 | /* |
295 | * If the rank boundaries for the two channels are different | ||
258 | * then we're not interleaved. | 296 | * then we're not interleaved. |
259 | */ | 297 | */ |
260 | for (i = 0; i < I3000_RANKS_PER_CHANNEL; i++) | 298 | for (i = 0; i < I3000_RANKS_PER_CHANNEL; i++) |
@@ -288,6 +326,15 @@ static int i3000_probe1(struct pci_dev *pdev, int dev_idx) | |||
288 | return -ENODEV; | 326 | return -ENODEV; |
289 | } | 327 | } |
290 | 328 | ||
329 | switch (edac_op_state) { | ||
330 | case EDAC_OPSTATE_POLL: | ||
331 | case EDAC_OPSTATE_NMI: | ||
332 | break; | ||
333 | default: | ||
334 | edac_op_state = EDAC_OPSTATE_POLL; | ||
335 | break; | ||
336 | } | ||
337 | |||
291 | c0dra[0] = readb(window + I3000_C0DRA + 0); /* ranks 0,1 */ | 338 | c0dra[0] = readb(window + I3000_C0DRA + 0); /* ranks 0,1 */ |
292 | c0dra[1] = readb(window + I3000_C0DRA + 1); /* ranks 2,3 */ | 339 | c0dra[1] = readb(window + I3000_C0DRA + 1); /* ranks 2,3 */ |
293 | c1dra[0] = readb(window + I3000_C1DRA + 0); /* ranks 0,1 */ | 340 | c1dra[0] = readb(window + I3000_C1DRA + 0); /* ranks 0,1 */ |
@@ -300,7 +347,8 @@ static int i3000_probe1(struct pci_dev *pdev, int dev_idx) | |||
300 | 347 | ||
301 | iounmap(window); | 348 | iounmap(window); |
302 | 349 | ||
303 | /* Figure out how many channels we have. | 350 | /* |
351 | * Figure out how many channels we have. | ||
304 | * | 352 | * |
305 | * If we have what the datasheet calls "asymmetric channels" | 353 | * If we have what the datasheet calls "asymmetric channels" |
306 | * (essentially the same as what was called "virtual single | 354 | * (essentially the same as what was called "virtual single |
@@ -363,7 +411,8 @@ static int i3000_probe1(struct pci_dev *pdev, int dev_idx) | |||
363 | csrow->edac_mode = EDAC_UNKNOWN; | 411 | csrow->edac_mode = EDAC_UNKNOWN; |
364 | } | 412 | } |
365 | 413 | ||
366 | /* Clear any error bits. | 414 | /* |
415 | * Clear any error bits. | ||
367 | * (Yes, we really clear bits by writing 1 to them.) | 416 | * (Yes, we really clear bits by writing 1 to them.) |
368 | */ | 417 | */ |
369 | pci_write_bits16(pdev, I3000_ERRSTS, I3000_ERRSTS_BITS, | 418 | pci_write_bits16(pdev, I3000_ERRSTS, I3000_ERRSTS_BITS, |
@@ -390,7 +439,7 @@ static int i3000_probe1(struct pci_dev *pdev, int dev_idx) | |||
390 | debugf3("MC: %s(): success\n", __func__); | 439 | debugf3("MC: %s(): success\n", __func__); |
391 | return 0; | 440 | return 0; |
392 | 441 | ||
393 | fail: | 442 | fail: |
394 | if (mci) | 443 | if (mci) |
395 | edac_mc_free(mci); | 444 | edac_mc_free(mci); |
396 | 445 | ||
@@ -409,7 +458,7 @@ static int __devinit i3000_init_one(struct pci_dev *pdev, | |||
409 | return -EIO; | 458 | return -EIO; |
410 | 459 | ||
411 | rc = i3000_probe1(pdev, ent->driver_data); | 460 | rc = i3000_probe1(pdev, ent->driver_data); |
412 | if (mci_pdev == NULL) | 461 | if (!mci_pdev) |
413 | mci_pdev = pci_dev_get(pdev); | 462 | mci_pdev = pci_dev_get(pdev); |
414 | 463 | ||
415 | return rc; | 464 | return rc; |
@@ -424,7 +473,8 @@ static void __devexit i3000_remove_one(struct pci_dev *pdev) | |||
424 | if (i3000_pci) | 473 | if (i3000_pci) |
425 | edac_pci_release_generic_ctl(i3000_pci); | 474 | edac_pci_release_generic_ctl(i3000_pci); |
426 | 475 | ||
427 | if ((mci = edac_mc_del_mc(&pdev->dev)) == NULL) | 476 | mci = edac_mc_del_mc(&pdev->dev); |
477 | if (!mci) | ||
428 | return; | 478 | return; |
429 | 479 | ||
430 | edac_mc_free(mci); | 480 | edac_mc_free(mci); |
@@ -457,7 +507,7 @@ static int __init i3000_init(void) | |||
457 | if (pci_rc < 0) | 507 | if (pci_rc < 0) |
458 | goto fail0; | 508 | goto fail0; |
459 | 509 | ||
460 | if (mci_pdev == NULL) { | 510 | if (!mci_pdev) { |
461 | i3000_registered = 0; | 511 | i3000_registered = 0; |
462 | mci_pdev = pci_get_device(PCI_VENDOR_ID_INTEL, | 512 | mci_pdev = pci_get_device(PCI_VENDOR_ID_INTEL, |
463 | PCI_DEVICE_ID_INTEL_3000_HB, NULL); | 513 | PCI_DEVICE_ID_INTEL_3000_HB, NULL); |
@@ -504,3 +554,6 @@ module_exit(i3000_exit); | |||
504 | MODULE_LICENSE("GPL"); | 554 | MODULE_LICENSE("GPL"); |
505 | MODULE_AUTHOR("Akamai Technologies Arthur Ulfeldt/Jason Uhlenkott"); | 555 | MODULE_AUTHOR("Akamai Technologies Arthur Ulfeldt/Jason Uhlenkott"); |
506 | MODULE_DESCRIPTION("MC support for Intel 3000 memory hub controllers"); | 556 | MODULE_DESCRIPTION("MC support for Intel 3000 memory hub controllers"); |
557 | |||
558 | module_param(edac_op_state, int, 0444); | ||
559 | MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI"); | ||
diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c new file mode 100644 index 000000000000..065732ddf40c --- /dev/null +++ b/drivers/edac/mpc85xx_edac.c | |||
@@ -0,0 +1,1043 @@ | |||
1 | /* | ||
2 | * Freescale MPC85xx Memory Controller kenel module | ||
3 | * | ||
4 | * Author: Dave Jiang <djiang@mvista.com> | ||
5 | * | ||
6 | * 2006-2007 (c) MontaVista Software, Inc. This file is licensed under | ||
7 | * the terms of the GNU General Public License version 2. This program | ||
8 | * is licensed "as is" without any warranty of any kind, whether express | ||
9 | * or implied. | ||
10 | * | ||
11 | */ | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/slab.h> | ||
15 | #include <linux/interrupt.h> | ||
16 | #include <linux/ctype.h> | ||
17 | #include <linux/io.h> | ||
18 | #include <linux/mod_devicetable.h> | ||
19 | #include <linux/edac.h> | ||
20 | |||
21 | #include <linux/of_platform.h> | ||
22 | #include <linux/of_device.h> | ||
23 | #include <asm/mpc85xx.h> | ||
24 | #include "edac_module.h" | ||
25 | #include "edac_core.h" | ||
26 | #include "mpc85xx_edac.h" | ||
27 | |||
28 | static int edac_dev_idx; | ||
29 | static int edac_pci_idx; | ||
30 | static int edac_mc_idx; | ||
31 | |||
32 | static u32 orig_ddr_err_disable; | ||
33 | static u32 orig_ddr_err_sbe; | ||
34 | |||
35 | /* | ||
36 | * PCI Err defines | ||
37 | */ | ||
38 | #ifdef CONFIG_PCI | ||
39 | static u32 orig_pci_err_cap_dr; | ||
40 | static u32 orig_pci_err_en; | ||
41 | #endif | ||
42 | |||
43 | static u32 orig_l2_err_disable; | ||
44 | static u32 orig_hid1; | ||
45 | |||
46 | static const char *mpc85xx_ctl_name = "MPC85xx"; | ||
47 | |||
48 | /************************ MC SYSFS parts ***********************************/ | ||
49 | |||
50 | static ssize_t mpc85xx_mc_inject_data_hi_show(struct mem_ctl_info *mci, | ||
51 | char *data) | ||
52 | { | ||
53 | struct mpc85xx_mc_pdata *pdata = mci->pvt_info; | ||
54 | return sprintf(data, "0x%08x", | ||
55 | in_be32(pdata->mc_vbase + | ||
56 | MPC85XX_MC_DATA_ERR_INJECT_HI)); | ||
57 | } | ||
58 | |||
59 | static ssize_t mpc85xx_mc_inject_data_lo_show(struct mem_ctl_info *mci, | ||
60 | char *data) | ||
61 | { | ||
62 | struct mpc85xx_mc_pdata *pdata = mci->pvt_info; | ||
63 | return sprintf(data, "0x%08x", | ||
64 | in_be32(pdata->mc_vbase + | ||
65 | MPC85XX_MC_DATA_ERR_INJECT_LO)); | ||
66 | } | ||
67 | |||
68 | static ssize_t mpc85xx_mc_inject_ctrl_show(struct mem_ctl_info *mci, char *data) | ||
69 | { | ||
70 | struct mpc85xx_mc_pdata *pdata = mci->pvt_info; | ||
71 | return sprintf(data, "0x%08x", | ||
72 | in_be32(pdata->mc_vbase + MPC85XX_MC_ECC_ERR_INJECT)); | ||
73 | } | ||
74 | |||
75 | static ssize_t mpc85xx_mc_inject_data_hi_store(struct mem_ctl_info *mci, | ||
76 | const char *data, size_t count) | ||
77 | { | ||
78 | struct mpc85xx_mc_pdata *pdata = mci->pvt_info; | ||
79 | if (isdigit(*data)) { | ||
80 | out_be32(pdata->mc_vbase + MPC85XX_MC_DATA_ERR_INJECT_HI, | ||
81 | simple_strtoul(data, NULL, 0)); | ||
82 | return count; | ||
83 | } | ||
84 | return 0; | ||
85 | } | ||
86 | |||
87 | static ssize_t mpc85xx_mc_inject_data_lo_store(struct mem_ctl_info *mci, | ||
88 | const char *data, size_t count) | ||
89 | { | ||
90 | struct mpc85xx_mc_pdata *pdata = mci->pvt_info; | ||
91 | if (isdigit(*data)) { | ||
92 | out_be32(pdata->mc_vbase + MPC85XX_MC_DATA_ERR_INJECT_LO, | ||
93 | simple_strtoul(data, NULL, 0)); | ||
94 | return count; | ||
95 | } | ||
96 | return 0; | ||
97 | } | ||
98 | |||
99 | static ssize_t mpc85xx_mc_inject_ctrl_store(struct mem_ctl_info *mci, | ||
100 | const char *data, size_t count) | ||
101 | { | ||
102 | struct mpc85xx_mc_pdata *pdata = mci->pvt_info; | ||
103 | if (isdigit(*data)) { | ||
104 | out_be32(pdata->mc_vbase + MPC85XX_MC_ECC_ERR_INJECT, | ||
105 | simple_strtoul(data, NULL, 0)); | ||
106 | return count; | ||
107 | } | ||
108 | return 0; | ||
109 | } | ||
110 | |||
111 | static struct mcidev_sysfs_attribute mpc85xx_mc_sysfs_attributes[] = { | ||
112 | { | ||
113 | .attr = { | ||
114 | .name = "inject_data_hi", | ||
115 | .mode = (S_IRUGO | S_IWUSR) | ||
116 | }, | ||
117 | .show = mpc85xx_mc_inject_data_hi_show, | ||
118 | .store = mpc85xx_mc_inject_data_hi_store}, | ||
119 | { | ||
120 | .attr = { | ||
121 | .name = "inject_data_lo", | ||
122 | .mode = (S_IRUGO | S_IWUSR) | ||
123 | }, | ||
124 | .show = mpc85xx_mc_inject_data_lo_show, | ||
125 | .store = mpc85xx_mc_inject_data_lo_store}, | ||
126 | { | ||
127 | .attr = { | ||
128 | .name = "inject_ctrl", | ||
129 | .mode = (S_IRUGO | S_IWUSR) | ||
130 | }, | ||
131 | .show = mpc85xx_mc_inject_ctrl_show, | ||
132 | .store = mpc85xx_mc_inject_ctrl_store}, | ||
133 | |||
134 | /* End of list */ | ||
135 | { | ||
136 | .attr = {.name = NULL} | ||
137 | } | ||
138 | }; | ||
139 | |||
140 | static void mpc85xx_set_mc_sysfs_attributes(struct mem_ctl_info *mci) | ||
141 | { | ||
142 | mci->mc_driver_sysfs_attributes = mpc85xx_mc_sysfs_attributes; | ||
143 | } | ||
144 | |||
145 | /**************************** PCI Err device ***************************/ | ||
146 | #ifdef CONFIG_PCI | ||
147 | |||
148 | static void mpc85xx_pci_check(struct edac_pci_ctl_info *pci) | ||
149 | { | ||
150 | struct mpc85xx_pci_pdata *pdata = pci->pvt_info; | ||
151 | u32 err_detect; | ||
152 | |||
153 | err_detect = in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DR); | ||
154 | |||
155 | /* master aborts can happen during PCI config cycles */ | ||
156 | if (!(err_detect & ~(PCI_EDE_MULTI_ERR | PCI_EDE_MST_ABRT))) { | ||
157 | out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DR, err_detect); | ||
158 | return; | ||
159 | } | ||
160 | |||
161 | printk(KERN_ERR "PCI error(s) detected\n"); | ||
162 | printk(KERN_ERR "PCI/X ERR_DR register: %#08x\n", err_detect); | ||
163 | |||
164 | printk(KERN_ERR "PCI/X ERR_ATTRIB register: %#08x\n", | ||
165 | in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_ATTRIB)); | ||
166 | printk(KERN_ERR "PCI/X ERR_ADDR register: %#08x\n", | ||
167 | in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_ADDR)); | ||
168 | printk(KERN_ERR "PCI/X ERR_EXT_ADDR register: %#08x\n", | ||
169 | in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EXT_ADDR)); | ||
170 | printk(KERN_ERR "PCI/X ERR_DL register: %#08x\n", | ||
171 | in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DL)); | ||
172 | printk(KERN_ERR "PCI/X ERR_DH register: %#08x\n", | ||
173 | in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DH)); | ||
174 | |||
175 | /* clear error bits */ | ||
176 | out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DR, err_detect); | ||
177 | |||
178 | if (err_detect & PCI_EDE_PERR_MASK) | ||
179 | edac_pci_handle_pe(pci, pci->ctl_name); | ||
180 | |||
181 | if ((err_detect & ~PCI_EDE_MULTI_ERR) & ~PCI_EDE_PERR_MASK) | ||
182 | edac_pci_handle_npe(pci, pci->ctl_name); | ||
183 | } | ||
184 | |||
185 | static irqreturn_t mpc85xx_pci_isr(int irq, void *dev_id) | ||
186 | { | ||
187 | struct edac_pci_ctl_info *pci = dev_id; | ||
188 | struct mpc85xx_pci_pdata *pdata = pci->pvt_info; | ||
189 | u32 err_detect; | ||
190 | |||
191 | err_detect = in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DR); | ||
192 | |||
193 | if (!err_detect) | ||
194 | return IRQ_NONE; | ||
195 | |||
196 | mpc85xx_pci_check(pci); | ||
197 | |||
198 | return IRQ_HANDLED; | ||
199 | } | ||
200 | |||
201 | static int __devinit mpc85xx_pci_err_probe(struct platform_device *pdev) | ||
202 | { | ||
203 | struct edac_pci_ctl_info *pci; | ||
204 | struct mpc85xx_pci_pdata *pdata; | ||
205 | struct resource *r; | ||
206 | int res = 0; | ||
207 | |||
208 | if (!devres_open_group(&pdev->dev, mpc85xx_pci_err_probe, GFP_KERNEL)) | ||
209 | return -ENOMEM; | ||
210 | |||
211 | pci = edac_pci_alloc_ctl_info(sizeof(*pdata), "mpc85xx_pci_err"); | ||
212 | if (!pci) | ||
213 | return -ENOMEM; | ||
214 | |||
215 | pdata = pci->pvt_info; | ||
216 | pdata->name = "mpc85xx_pci_err"; | ||
217 | pdata->irq = NO_IRQ; | ||
218 | platform_set_drvdata(pdev, pci); | ||
219 | pci->dev = &pdev->dev; | ||
220 | pci->mod_name = EDAC_MOD_STR; | ||
221 | pci->ctl_name = pdata->name; | ||
222 | pci->dev_name = pdev->dev.bus_id; | ||
223 | |||
224 | if (edac_op_state == EDAC_OPSTATE_POLL) | ||
225 | pci->edac_check = mpc85xx_pci_check; | ||
226 | |||
227 | pdata->edac_idx = edac_pci_idx++; | ||
228 | |||
229 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
230 | if (!r) { | ||
231 | printk(KERN_ERR "%s: Unable to get resource for " | ||
232 | "PCI err regs\n", __func__); | ||
233 | goto err; | ||
234 | } | ||
235 | |||
236 | if (!devm_request_mem_region(&pdev->dev, r->start, | ||
237 | r->end - r->start + 1, pdata->name)) { | ||
238 | printk(KERN_ERR "%s: Error while requesting mem region\n", | ||
239 | __func__); | ||
240 | res = -EBUSY; | ||
241 | goto err; | ||
242 | } | ||
243 | |||
244 | pdata->pci_vbase = devm_ioremap(&pdev->dev, r->start, | ||
245 | r->end - r->start + 1); | ||
246 | if (!pdata->pci_vbase) { | ||
247 | printk(KERN_ERR "%s: Unable to setup PCI err regs\n", __func__); | ||
248 | res = -ENOMEM; | ||
249 | goto err; | ||
250 | } | ||
251 | |||
252 | orig_pci_err_cap_dr = | ||
253 | in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_CAP_DR); | ||
254 | |||
255 | /* PCI master abort is expected during config cycles */ | ||
256 | out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_CAP_DR, 0x40); | ||
257 | |||
258 | orig_pci_err_en = in_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EN); | ||
259 | |||
260 | /* disable master abort reporting */ | ||
261 | out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EN, ~0x40); | ||
262 | |||
263 | /* clear error bits */ | ||
264 | out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_DR, ~0); | ||
265 | |||
266 | if (edac_pci_add_device(pci, pdata->edac_idx) > 0) { | ||
267 | debugf3("%s(): failed edac_pci_add_device()\n", __func__); | ||
268 | goto err; | ||
269 | } | ||
270 | |||
271 | if (edac_op_state == EDAC_OPSTATE_INT) { | ||
272 | pdata->irq = platform_get_irq(pdev, 0); | ||
273 | res = devm_request_irq(&pdev->dev, pdata->irq, | ||
274 | mpc85xx_pci_isr, IRQF_DISABLED, | ||
275 | "[EDAC] PCI err", pci); | ||
276 | if (res < 0) { | ||
277 | printk(KERN_ERR | ||
278 | "%s: Unable to requiest irq %d for " | ||
279 | "MPC85xx PCI err\n", __func__, pdata->irq); | ||
280 | res = -ENODEV; | ||
281 | goto err2; | ||
282 | } | ||
283 | |||
284 | printk(KERN_INFO EDAC_MOD_STR " acquired irq %d for PCI Err\n", | ||
285 | pdata->irq); | ||
286 | } | ||
287 | |||
288 | devres_remove_group(&pdev->dev, mpc85xx_pci_err_probe); | ||
289 | debugf3("%s(): success\n", __func__); | ||
290 | printk(KERN_INFO EDAC_MOD_STR " PCI err registered\n"); | ||
291 | |||
292 | return 0; | ||
293 | |||
294 | err2: | ||
295 | edac_pci_del_device(&pdev->dev); | ||
296 | err: | ||
297 | edac_pci_free_ctl_info(pci); | ||
298 | devres_release_group(&pdev->dev, mpc85xx_pci_err_probe); | ||
299 | return res; | ||
300 | } | ||
301 | |||
302 | static int mpc85xx_pci_err_remove(struct platform_device *pdev) | ||
303 | { | ||
304 | struct edac_pci_ctl_info *pci = platform_get_drvdata(pdev); | ||
305 | struct mpc85xx_pci_pdata *pdata = pci->pvt_info; | ||
306 | |||
307 | debugf0("%s()\n", __func__); | ||
308 | |||
309 | out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_CAP_DR, | ||
310 | orig_pci_err_cap_dr); | ||
311 | |||
312 | out_be32(pdata->pci_vbase + MPC85XX_PCI_ERR_EN, orig_pci_err_en); | ||
313 | |||
314 | edac_pci_del_device(pci->dev); | ||
315 | |||
316 | if (edac_op_state == EDAC_OPSTATE_INT) | ||
317 | irq_dispose_mapping(pdata->irq); | ||
318 | |||
319 | edac_pci_free_ctl_info(pci); | ||
320 | |||
321 | return 0; | ||
322 | } | ||
323 | |||
324 | static struct platform_driver mpc85xx_pci_err_driver = { | ||
325 | .probe = mpc85xx_pci_err_probe, | ||
326 | .remove = __devexit_p(mpc85xx_pci_err_remove), | ||
327 | .driver = { | ||
328 | .name = "mpc85xx_pci_err", | ||
329 | } | ||
330 | }; | ||
331 | |||
332 | #endif /* CONFIG_PCI */ | ||
333 | |||
334 | /**************************** L2 Err device ***************************/ | ||
335 | |||
336 | /************************ L2 SYSFS parts ***********************************/ | ||
337 | |||
338 | static ssize_t mpc85xx_l2_inject_data_hi_show(struct edac_device_ctl_info | ||
339 | *edac_dev, char *data) | ||
340 | { | ||
341 | struct mpc85xx_l2_pdata *pdata = edac_dev->pvt_info; | ||
342 | return sprintf(data, "0x%08x", | ||
343 | in_be32(pdata->l2_vbase + MPC85XX_L2_ERRINJHI)); | ||
344 | } | ||
345 | |||
346 | static ssize_t mpc85xx_l2_inject_data_lo_show(struct edac_device_ctl_info | ||
347 | *edac_dev, char *data) | ||
348 | { | ||
349 | struct mpc85xx_l2_pdata *pdata = edac_dev->pvt_info; | ||
350 | return sprintf(data, "0x%08x", | ||
351 | in_be32(pdata->l2_vbase + MPC85XX_L2_ERRINJLO)); | ||
352 | } | ||
353 | |||
354 | static ssize_t mpc85xx_l2_inject_ctrl_show(struct edac_device_ctl_info | ||
355 | *edac_dev, char *data) | ||
356 | { | ||
357 | struct mpc85xx_l2_pdata *pdata = edac_dev->pvt_info; | ||
358 | return sprintf(data, "0x%08x", | ||
359 | in_be32(pdata->l2_vbase + MPC85XX_L2_ERRINJCTL)); | ||
360 | } | ||
361 | |||
362 | static ssize_t mpc85xx_l2_inject_data_hi_store(struct edac_device_ctl_info | ||
363 | *edac_dev, const char *data, | ||
364 | size_t count) | ||
365 | { | ||
366 | struct mpc85xx_l2_pdata *pdata = edac_dev->pvt_info; | ||
367 | if (isdigit(*data)) { | ||
368 | out_be32(pdata->l2_vbase + MPC85XX_L2_ERRINJHI, | ||
369 | simple_strtoul(data, NULL, 0)); | ||
370 | return count; | ||
371 | } | ||
372 | return 0; | ||
373 | } | ||
374 | |||
375 | static ssize_t mpc85xx_l2_inject_data_lo_store(struct edac_device_ctl_info | ||
376 | *edac_dev, const char *data, | ||
377 | size_t count) | ||
378 | { | ||
379 | struct mpc85xx_l2_pdata *pdata = edac_dev->pvt_info; | ||
380 | if (isdigit(*data)) { | ||
381 | out_be32(pdata->l2_vbase + MPC85XX_L2_ERRINJLO, | ||
382 | simple_strtoul(data, NULL, 0)); | ||
383 | return count; | ||
384 | } | ||
385 | return 0; | ||
386 | } | ||
387 | |||
388 | static ssize_t mpc85xx_l2_inject_ctrl_store(struct edac_device_ctl_info | ||
389 | *edac_dev, const char *data, | ||
390 | size_t count) | ||
391 | { | ||
392 | struct mpc85xx_l2_pdata *pdata = edac_dev->pvt_info; | ||
393 | if (isdigit(*data)) { | ||
394 | out_be32(pdata->l2_vbase + MPC85XX_L2_ERRINJCTL, | ||
395 | simple_strtoul(data, NULL, 0)); | ||
396 | return count; | ||
397 | } | ||
398 | return 0; | ||
399 | } | ||
400 | |||
401 | static struct edac_dev_sysfs_attribute mpc85xx_l2_sysfs_attributes[] = { | ||
402 | { | ||
403 | .attr = { | ||
404 | .name = "inject_data_hi", | ||
405 | .mode = (S_IRUGO | S_IWUSR) | ||
406 | }, | ||
407 | .show = mpc85xx_l2_inject_data_hi_show, | ||
408 | .store = mpc85xx_l2_inject_data_hi_store}, | ||
409 | { | ||
410 | .attr = { | ||
411 | .name = "inject_data_lo", | ||
412 | .mode = (S_IRUGO | S_IWUSR) | ||
413 | }, | ||
414 | .show = mpc85xx_l2_inject_data_lo_show, | ||
415 | .store = mpc85xx_l2_inject_data_lo_store}, | ||
416 | { | ||
417 | .attr = { | ||
418 | .name = "inject_ctrl", | ||
419 | .mode = (S_IRUGO | S_IWUSR) | ||
420 | }, | ||
421 | .show = mpc85xx_l2_inject_ctrl_show, | ||
422 | .store = mpc85xx_l2_inject_ctrl_store}, | ||
423 | |||
424 | /* End of list */ | ||
425 | { | ||
426 | .attr = {.name = NULL} | ||
427 | } | ||
428 | }; | ||
429 | |||
430 | static void mpc85xx_set_l2_sysfs_attributes(struct edac_device_ctl_info | ||
431 | *edac_dev) | ||
432 | { | ||
433 | edac_dev->sysfs_attributes = mpc85xx_l2_sysfs_attributes; | ||
434 | } | ||
435 | |||
436 | /***************************** L2 ops ***********************************/ | ||
437 | |||
438 | static void mpc85xx_l2_check(struct edac_device_ctl_info *edac_dev) | ||
439 | { | ||
440 | struct mpc85xx_l2_pdata *pdata = edac_dev->pvt_info; | ||
441 | u32 err_detect; | ||
442 | |||
443 | err_detect = in_be32(pdata->l2_vbase + MPC85XX_L2_ERRDET); | ||
444 | |||
445 | if (!(err_detect & L2_EDE_MASK)) | ||
446 | return; | ||
447 | |||
448 | printk(KERN_ERR "ECC Error in CPU L2 cache\n"); | ||
449 | printk(KERN_ERR "L2 Error Detect Register: 0x%08x\n", err_detect); | ||
450 | printk(KERN_ERR "L2 Error Capture Data High Register: 0x%08x\n", | ||
451 | in_be32(pdata->l2_vbase + MPC85XX_L2_CAPTDATAHI)); | ||
452 | printk(KERN_ERR "L2 Error Capture Data Lo Register: 0x%08x\n", | ||
453 | in_be32(pdata->l2_vbase + MPC85XX_L2_CAPTDATALO)); | ||
454 | printk(KERN_ERR "L2 Error Syndrome Register: 0x%08x\n", | ||
455 | in_be32(pdata->l2_vbase + MPC85XX_L2_CAPTECC)); | ||
456 | printk(KERN_ERR "L2 Error Attributes Capture Register: 0x%08x\n", | ||
457 | in_be32(pdata->l2_vbase + MPC85XX_L2_ERRATTR)); | ||
458 | printk(KERN_ERR "L2 Error Address Capture Register: 0x%08x\n", | ||
459 | in_be32(pdata->l2_vbase + MPC85XX_L2_ERRADDR)); | ||
460 | |||
461 | /* clear error detect register */ | ||
462 | out_be32(pdata->l2_vbase + MPC85XX_L2_ERRDET, err_detect); | ||
463 | |||
464 | if (err_detect & L2_EDE_CE_MASK) | ||
465 | edac_device_handle_ce(edac_dev, 0, 0, edac_dev->ctl_name); | ||
466 | |||
467 | if (err_detect & L2_EDE_UE_MASK) | ||
468 | edac_device_handle_ue(edac_dev, 0, 0, edac_dev->ctl_name); | ||
469 | } | ||
470 | |||
471 | static irqreturn_t mpc85xx_l2_isr(int irq, void *dev_id) | ||
472 | { | ||
473 | struct edac_device_ctl_info *edac_dev = dev_id; | ||
474 | struct mpc85xx_l2_pdata *pdata = edac_dev->pvt_info; | ||
475 | u32 err_detect; | ||
476 | |||
477 | err_detect = in_be32(pdata->l2_vbase + MPC85XX_L2_ERRDET); | ||
478 | |||
479 | if (!(err_detect & L2_EDE_MASK)) | ||
480 | return IRQ_NONE; | ||
481 | |||
482 | mpc85xx_l2_check(edac_dev); | ||
483 | |||
484 | return IRQ_HANDLED; | ||
485 | } | ||
486 | |||
487 | static int __devinit mpc85xx_l2_err_probe(struct of_device *op, | ||
488 | const struct of_device_id *match) | ||
489 | { | ||
490 | struct edac_device_ctl_info *edac_dev; | ||
491 | struct mpc85xx_l2_pdata *pdata; | ||
492 | struct resource r; | ||
493 | int res; | ||
494 | |||
495 | if (!devres_open_group(&op->dev, mpc85xx_l2_err_probe, GFP_KERNEL)) | ||
496 | return -ENOMEM; | ||
497 | |||
498 | edac_dev = edac_device_alloc_ctl_info(sizeof(*pdata), | ||
499 | "cpu", 1, "L", 1, 2, NULL, 0, | ||
500 | edac_dev_idx); | ||
501 | if (!edac_dev) { | ||
502 | devres_release_group(&op->dev, mpc85xx_l2_err_probe); | ||
503 | return -ENOMEM; | ||
504 | } | ||
505 | |||
506 | pdata = edac_dev->pvt_info; | ||
507 | pdata->name = "mpc85xx_l2_err"; | ||
508 | pdata->irq = NO_IRQ; | ||
509 | edac_dev->dev = &op->dev; | ||
510 | dev_set_drvdata(edac_dev->dev, edac_dev); | ||
511 | edac_dev->ctl_name = pdata->name; | ||
512 | edac_dev->dev_name = pdata->name; | ||
513 | |||
514 | res = of_address_to_resource(op->node, 0, &r); | ||
515 | if (res) { | ||
516 | printk(KERN_ERR "%s: Unable to get resource for " | ||
517 | "L2 err regs\n", __func__); | ||
518 | goto err; | ||
519 | } | ||
520 | |||
521 | /* we only need the error registers */ | ||
522 | r.start += 0xe00; | ||
523 | |||
524 | if (!devm_request_mem_region(&op->dev, r.start, | ||
525 | r.end - r.start + 1, pdata->name)) { | ||
526 | printk(KERN_ERR "%s: Error while requesting mem region\n", | ||
527 | __func__); | ||
528 | res = -EBUSY; | ||
529 | goto err; | ||
530 | } | ||
531 | |||
532 | pdata->l2_vbase = devm_ioremap(&op->dev, r.start, r.end - r.start + 1); | ||
533 | if (!pdata->l2_vbase) { | ||
534 | printk(KERN_ERR "%s: Unable to setup L2 err regs\n", __func__); | ||
535 | res = -ENOMEM; | ||
536 | goto err; | ||
537 | } | ||
538 | |||
539 | out_be32(pdata->l2_vbase + MPC85XX_L2_ERRDET, ~0); | ||
540 | |||
541 | orig_l2_err_disable = in_be32(pdata->l2_vbase + MPC85XX_L2_ERRDIS); | ||
542 | |||
543 | /* clear the err_dis */ | ||
544 | out_be32(pdata->l2_vbase + MPC85XX_L2_ERRDIS, 0); | ||
545 | |||
546 | edac_dev->mod_name = EDAC_MOD_STR; | ||
547 | |||
548 | if (edac_op_state == EDAC_OPSTATE_POLL) | ||
549 | edac_dev->edac_check = mpc85xx_l2_check; | ||
550 | |||
551 | mpc85xx_set_l2_sysfs_attributes(edac_dev); | ||
552 | |||
553 | pdata->edac_idx = edac_dev_idx++; | ||
554 | |||
555 | if (edac_device_add_device(edac_dev) > 0) { | ||
556 | debugf3("%s(): failed edac_device_add_device()\n", __func__); | ||
557 | goto err; | ||
558 | } | ||
559 | |||
560 | if (edac_op_state == EDAC_OPSTATE_INT) { | ||
561 | pdata->irq = irq_of_parse_and_map(op->node, 0); | ||
562 | res = devm_request_irq(&op->dev, pdata->irq, | ||
563 | mpc85xx_l2_isr, IRQF_DISABLED, | ||
564 | "[EDAC] L2 err", edac_dev); | ||
565 | if (res < 0) { | ||
566 | printk(KERN_ERR | ||
567 | "%s: Unable to requiest irq %d for " | ||
568 | "MPC85xx L2 err\n", __func__, pdata->irq); | ||
569 | irq_dispose_mapping(pdata->irq); | ||
570 | res = -ENODEV; | ||
571 | goto err2; | ||
572 | } | ||
573 | |||
574 | printk(KERN_INFO EDAC_MOD_STR " acquired irq %d for L2 Err\n", | ||
575 | pdata->irq); | ||
576 | |||
577 | edac_dev->op_state = OP_RUNNING_INTERRUPT; | ||
578 | |||
579 | out_be32(pdata->l2_vbase + MPC85XX_L2_ERRINTEN, L2_EIE_MASK); | ||
580 | } | ||
581 | |||
582 | devres_remove_group(&op->dev, mpc85xx_l2_err_probe); | ||
583 | |||
584 | debugf3("%s(): success\n", __func__); | ||
585 | printk(KERN_INFO EDAC_MOD_STR " L2 err registered\n"); | ||
586 | |||
587 | return 0; | ||
588 | |||
589 | err2: | ||
590 | edac_device_del_device(&op->dev); | ||
591 | err: | ||
592 | devres_release_group(&op->dev, mpc85xx_l2_err_probe); | ||
593 | edac_device_free_ctl_info(edac_dev); | ||
594 | return res; | ||
595 | } | ||
596 | |||
597 | static int mpc85xx_l2_err_remove(struct of_device *op) | ||
598 | { | ||
599 | struct edac_device_ctl_info *edac_dev = dev_get_drvdata(&op->dev); | ||
600 | struct mpc85xx_l2_pdata *pdata = edac_dev->pvt_info; | ||
601 | |||
602 | debugf0("%s()\n", __func__); | ||
603 | |||
604 | if (edac_op_state == EDAC_OPSTATE_INT) { | ||
605 | out_be32(pdata->l2_vbase + MPC85XX_L2_ERRINTEN, 0); | ||
606 | irq_dispose_mapping(pdata->irq); | ||
607 | } | ||
608 | |||
609 | out_be32(pdata->l2_vbase + MPC85XX_L2_ERRDIS, orig_l2_err_disable); | ||
610 | edac_device_del_device(&op->dev); | ||
611 | edac_device_free_ctl_info(edac_dev); | ||
612 | return 0; | ||
613 | } | ||
614 | |||
615 | static struct of_device_id mpc85xx_l2_err_of_match[] = { | ||
616 | { | ||
617 | .compatible = "fsl,8540-l2-cache-controller", | ||
618 | }, | ||
619 | { | ||
620 | .compatible = "fsl,8541-l2-cache-controller", | ||
621 | }, | ||
622 | { | ||
623 | .compatible = "fsl,8544-l2-cache-controller", | ||
624 | }, | ||
625 | { | ||
626 | .compatible = "fsl,8548-l2-cache-controller", | ||
627 | }, | ||
628 | { | ||
629 | .compatible = "fsl,8555-l2-cache-controller", | ||
630 | }, | ||
631 | { | ||
632 | .compatible = "fsl,8568-l2-cache-controller", | ||
633 | }, | ||
634 | {}, | ||
635 | }; | ||
636 | |||
637 | static struct of_platform_driver mpc85xx_l2_err_driver = { | ||
638 | .owner = THIS_MODULE, | ||
639 | .name = "mpc85xx_l2_err", | ||
640 | .match_table = mpc85xx_l2_err_of_match, | ||
641 | .probe = mpc85xx_l2_err_probe, | ||
642 | .remove = mpc85xx_l2_err_remove, | ||
643 | .driver = { | ||
644 | .name = "mpc85xx_l2_err", | ||
645 | .owner = THIS_MODULE, | ||
646 | }, | ||
647 | }; | ||
648 | |||
649 | /**************************** MC Err device ***************************/ | ||
650 | |||
651 | static void mpc85xx_mc_check(struct mem_ctl_info *mci) | ||
652 | { | ||
653 | struct mpc85xx_mc_pdata *pdata = mci->pvt_info; | ||
654 | struct csrow_info *csrow; | ||
655 | u32 err_detect; | ||
656 | u32 syndrome; | ||
657 | u32 err_addr; | ||
658 | u32 pfn; | ||
659 | int row_index; | ||
660 | |||
661 | err_detect = in_be32(pdata->mc_vbase + MPC85XX_MC_ERR_DETECT); | ||
662 | if (err_detect) | ||
663 | return; | ||
664 | |||
665 | mpc85xx_mc_printk(mci, KERN_ERR, "Err Detect Register: %#8.8x\n", | ||
666 | err_detect); | ||
667 | |||
668 | /* no more processing if not ECC bit errors */ | ||
669 | if (!(err_detect & (DDR_EDE_SBE | DDR_EDE_MBE))) { | ||
670 | out_be32(pdata->mc_vbase + MPC85XX_MC_ERR_DETECT, err_detect); | ||
671 | return; | ||
672 | } | ||
673 | |||
674 | syndrome = in_be32(pdata->mc_vbase + MPC85XX_MC_CAPTURE_ECC); | ||
675 | err_addr = in_be32(pdata->mc_vbase + MPC85XX_MC_CAPTURE_ADDRESS); | ||
676 | pfn = err_addr >> PAGE_SHIFT; | ||
677 | |||
678 | for (row_index = 0; row_index < mci->nr_csrows; row_index++) { | ||
679 | csrow = &mci->csrows[row_index]; | ||
680 | if ((pfn >= csrow->first_page) && (pfn <= csrow->last_page)) | ||
681 | break; | ||
682 | } | ||
683 | |||
684 | mpc85xx_mc_printk(mci, KERN_ERR, "Capture Data High: %#8.8x\n", | ||
685 | in_be32(pdata->mc_vbase + | ||
686 | MPC85XX_MC_CAPTURE_DATA_HI)); | ||
687 | mpc85xx_mc_printk(mci, KERN_ERR, "Capture Data Low: %#8.8x\n", | ||
688 | in_be32(pdata->mc_vbase + | ||
689 | MPC85XX_MC_CAPTURE_DATA_LO)); | ||
690 | mpc85xx_mc_printk(mci, KERN_ERR, "syndrome: %#8.8x\n", syndrome); | ||
691 | mpc85xx_mc_printk(mci, KERN_ERR, "err addr: %#8.8x\n", err_addr); | ||
692 | mpc85xx_mc_printk(mci, KERN_ERR, "PFN: %#8.8x\n", pfn); | ||
693 | |||
694 | /* we are out of range */ | ||
695 | if (row_index == mci->nr_csrows) | ||
696 | mpc85xx_mc_printk(mci, KERN_ERR, "PFN out of range!\n"); | ||
697 | |||
698 | if (err_detect & DDR_EDE_SBE) | ||
699 | edac_mc_handle_ce(mci, pfn, err_addr & PAGE_MASK, | ||
700 | syndrome, row_index, 0, mci->ctl_name); | ||
701 | |||
702 | if (err_detect & DDR_EDE_MBE) | ||
703 | edac_mc_handle_ue(mci, pfn, err_addr & PAGE_MASK, | ||
704 | row_index, mci->ctl_name); | ||
705 | |||
706 | out_be32(pdata->mc_vbase + MPC85XX_MC_ERR_DETECT, err_detect); | ||
707 | } | ||
708 | |||
709 | static irqreturn_t mpc85xx_mc_isr(int irq, void *dev_id) | ||
710 | { | ||
711 | struct mem_ctl_info *mci = dev_id; | ||
712 | struct mpc85xx_mc_pdata *pdata = mci->pvt_info; | ||
713 | u32 err_detect; | ||
714 | |||
715 | err_detect = in_be32(pdata->mc_vbase + MPC85XX_MC_ERR_DETECT); | ||
716 | if (!err_detect) | ||
717 | return IRQ_NONE; | ||
718 | |||
719 | mpc85xx_mc_check(mci); | ||
720 | |||
721 | return IRQ_HANDLED; | ||
722 | } | ||
723 | |||
724 | static void __devinit mpc85xx_init_csrows(struct mem_ctl_info *mci) | ||
725 | { | ||
726 | struct mpc85xx_mc_pdata *pdata = mci->pvt_info; | ||
727 | struct csrow_info *csrow; | ||
728 | u32 sdram_ctl; | ||
729 | u32 sdtype; | ||
730 | enum mem_type mtype; | ||
731 | u32 cs_bnds; | ||
732 | int index; | ||
733 | |||
734 | sdram_ctl = in_be32(pdata->mc_vbase + MPC85XX_MC_DDR_SDRAM_CFG); | ||
735 | |||
736 | sdtype = sdram_ctl & DSC_SDTYPE_MASK; | ||
737 | if (sdram_ctl & DSC_RD_EN) { | ||
738 | switch (sdtype) { | ||
739 | case DSC_SDTYPE_DDR: | ||
740 | mtype = MEM_RDDR; | ||
741 | break; | ||
742 | case DSC_SDTYPE_DDR2: | ||
743 | mtype = MEM_RDDR2; | ||
744 | break; | ||
745 | default: | ||
746 | mtype = MEM_UNKNOWN; | ||
747 | break; | ||
748 | } | ||
749 | } else { | ||
750 | switch (sdtype) { | ||
751 | case DSC_SDTYPE_DDR: | ||
752 | mtype = MEM_DDR; | ||
753 | break; | ||
754 | case DSC_SDTYPE_DDR2: | ||
755 | mtype = MEM_DDR2; | ||
756 | break; | ||
757 | default: | ||
758 | mtype = MEM_UNKNOWN; | ||
759 | break; | ||
760 | } | ||
761 | } | ||
762 | |||
763 | for (index = 0; index < mci->nr_csrows; index++) { | ||
764 | u32 start; | ||
765 | u32 end; | ||
766 | |||
767 | csrow = &mci->csrows[index]; | ||
768 | cs_bnds = in_be32(pdata->mc_vbase + MPC85XX_MC_CS_BNDS_0 + | ||
769 | (index * MPC85XX_MC_CS_BNDS_OFS)); | ||
770 | start = (cs_bnds & 0xfff0000) << 4; | ||
771 | end = ((cs_bnds & 0xfff) << 20); | ||
772 | if (start) | ||
773 | start |= 0xfffff; | ||
774 | if (end) | ||
775 | end |= 0xfffff; | ||
776 | |||
777 | if (start == end) | ||
778 | continue; /* not populated */ | ||
779 | |||
780 | csrow->first_page = start >> PAGE_SHIFT; | ||
781 | csrow->last_page = end >> PAGE_SHIFT; | ||
782 | csrow->nr_pages = csrow->last_page + 1 - csrow->first_page; | ||
783 | csrow->grain = 8; | ||
784 | csrow->mtype = mtype; | ||
785 | csrow->dtype = DEV_UNKNOWN; | ||
786 | if (sdram_ctl & DSC_X32_EN) | ||
787 | csrow->dtype = DEV_X32; | ||
788 | csrow->edac_mode = EDAC_SECDED; | ||
789 | } | ||
790 | } | ||
791 | |||
792 | static int __devinit mpc85xx_mc_err_probe(struct of_device *op, | ||
793 | const struct of_device_id *match) | ||
794 | { | ||
795 | struct mem_ctl_info *mci; | ||
796 | struct mpc85xx_mc_pdata *pdata; | ||
797 | struct resource r; | ||
798 | u32 sdram_ctl; | ||
799 | int res; | ||
800 | |||
801 | if (!devres_open_group(&op->dev, mpc85xx_mc_err_probe, GFP_KERNEL)) | ||
802 | return -ENOMEM; | ||
803 | |||
804 | mci = edac_mc_alloc(sizeof(*pdata), 4, 1, edac_mc_idx); | ||
805 | if (!mci) { | ||
806 | devres_release_group(&op->dev, mpc85xx_mc_err_probe); | ||
807 | return -ENOMEM; | ||
808 | } | ||
809 | |||
810 | pdata = mci->pvt_info; | ||
811 | pdata->name = "mpc85xx_mc_err"; | ||
812 | pdata->irq = NO_IRQ; | ||
813 | mci->dev = &op->dev; | ||
814 | pdata->edac_idx = edac_mc_idx++; | ||
815 | dev_set_drvdata(mci->dev, mci); | ||
816 | mci->ctl_name = pdata->name; | ||
817 | mci->dev_name = pdata->name; | ||
818 | |||
819 | res = of_address_to_resource(op->node, 0, &r); | ||
820 | if (res) { | ||
821 | printk(KERN_ERR "%s: Unable to get resource for MC err regs\n", | ||
822 | __func__); | ||
823 | goto err; | ||
824 | } | ||
825 | |||
826 | if (!devm_request_mem_region(&op->dev, r.start, | ||
827 | r.end - r.start + 1, pdata->name)) { | ||
828 | printk(KERN_ERR "%s: Error while requesting mem region\n", | ||
829 | __func__); | ||
830 | res = -EBUSY; | ||
831 | goto err; | ||
832 | } | ||
833 | |||
834 | pdata->mc_vbase = devm_ioremap(&op->dev, r.start, r.end - r.start + 1); | ||
835 | if (!pdata->mc_vbase) { | ||
836 | printk(KERN_ERR "%s: Unable to setup MC err regs\n", __func__); | ||
837 | res = -ENOMEM; | ||
838 | goto err; | ||
839 | } | ||
840 | |||
841 | sdram_ctl = in_be32(pdata->mc_vbase + MPC85XX_MC_DDR_SDRAM_CFG); | ||
842 | if (!(sdram_ctl & DSC_ECC_EN)) { | ||
843 | /* no ECC */ | ||
844 | printk(KERN_WARNING "%s: No ECC DIMMs discovered\n", __func__); | ||
845 | res = -ENODEV; | ||
846 | goto err; | ||
847 | } | ||
848 | |||
849 | debugf3("%s(): init mci\n", __func__); | ||
850 | mci->mtype_cap = MEM_FLAG_RDDR | MEM_FLAG_RDDR2 | | ||
851 | MEM_FLAG_DDR | MEM_FLAG_DDR2; | ||
852 | mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED; | ||
853 | mci->edac_cap = EDAC_FLAG_SECDED; | ||
854 | mci->mod_name = EDAC_MOD_STR; | ||
855 | mci->mod_ver = MPC85XX_REVISION; | ||
856 | |||
857 | if (edac_op_state == EDAC_OPSTATE_POLL) | ||
858 | mci->edac_check = mpc85xx_mc_check; | ||
859 | |||
860 | mci->ctl_page_to_phys = NULL; | ||
861 | |||
862 | mci->scrub_mode = SCRUB_SW_SRC; | ||
863 | |||
864 | mpc85xx_set_mc_sysfs_attributes(mci); | ||
865 | |||
866 | mpc85xx_init_csrows(mci); | ||
867 | |||
868 | #ifdef CONFIG_EDAC_DEBUG | ||
869 | edac_mc_register_mcidev_debug((struct attribute **)debug_attr); | ||
870 | #endif | ||
871 | |||
872 | /* store the original error disable bits */ | ||
873 | orig_ddr_err_disable = | ||
874 | in_be32(pdata->mc_vbase + MPC85XX_MC_ERR_DISABLE); | ||
875 | out_be32(pdata->mc_vbase + MPC85XX_MC_ERR_DISABLE, 0); | ||
876 | |||
877 | /* clear all error bits */ | ||
878 | out_be32(pdata->mc_vbase + MPC85XX_MC_ERR_DETECT, ~0); | ||
879 | |||
880 | if (edac_mc_add_mc(mci)) { | ||
881 | debugf3("%s(): failed edac_mc_add_mc()\n", __func__); | ||
882 | goto err; | ||
883 | } | ||
884 | |||
885 | if (edac_op_state == EDAC_OPSTATE_INT) { | ||
886 | out_be32(pdata->mc_vbase + MPC85XX_MC_ERR_INT_EN, | ||
887 | DDR_EIE_MBEE | DDR_EIE_SBEE); | ||
888 | |||
889 | /* store the original error management threshold */ | ||
890 | orig_ddr_err_sbe = in_be32(pdata->mc_vbase + | ||
891 | MPC85XX_MC_ERR_SBE) & 0xff0000; | ||
892 | |||
893 | /* set threshold to 1 error per interrupt */ | ||
894 | out_be32(pdata->mc_vbase + MPC85XX_MC_ERR_SBE, 0x10000); | ||
895 | |||
896 | /* register interrupts */ | ||
897 | pdata->irq = irq_of_parse_and_map(op->node, 0); | ||
898 | res = devm_request_irq(&op->dev, pdata->irq, | ||
899 | mpc85xx_mc_isr, IRQF_DISABLED, | ||
900 | "[EDAC] MC err", mci); | ||
901 | if (res < 0) { | ||
902 | printk(KERN_ERR "%s: Unable to request irq %d for " | ||
903 | "MPC85xx DRAM ERR\n", __func__, pdata->irq); | ||
904 | irq_dispose_mapping(pdata->irq); | ||
905 | res = -ENODEV; | ||
906 | goto err2; | ||
907 | } | ||
908 | |||
909 | printk(KERN_INFO EDAC_MOD_STR " acquired irq %d for MC\n", | ||
910 | pdata->irq); | ||
911 | } | ||
912 | |||
913 | devres_remove_group(&op->dev, mpc85xx_mc_err_probe); | ||
914 | debugf3("%s(): success\n", __func__); | ||
915 | printk(KERN_INFO EDAC_MOD_STR " MC err registered\n"); | ||
916 | |||
917 | return 0; | ||
918 | |||
919 | err2: | ||
920 | edac_mc_del_mc(&op->dev); | ||
921 | err: | ||
922 | devres_release_group(&op->dev, mpc85xx_mc_err_probe); | ||
923 | edac_mc_free(mci); | ||
924 | return res; | ||
925 | } | ||
926 | |||
927 | static int mpc85xx_mc_err_remove(struct of_device *op) | ||
928 | { | ||
929 | struct mem_ctl_info *mci = dev_get_drvdata(&op->dev); | ||
930 | struct mpc85xx_mc_pdata *pdata = mci->pvt_info; | ||
931 | |||
932 | debugf0("%s()\n", __func__); | ||
933 | |||
934 | if (edac_op_state == EDAC_OPSTATE_INT) { | ||
935 | out_be32(pdata->mc_vbase + MPC85XX_MC_ERR_INT_EN, 0); | ||
936 | irq_dispose_mapping(pdata->irq); | ||
937 | } | ||
938 | |||
939 | out_be32(pdata->mc_vbase + MPC85XX_MC_ERR_DISABLE, | ||
940 | orig_ddr_err_disable); | ||
941 | out_be32(pdata->mc_vbase + MPC85XX_MC_ERR_SBE, orig_ddr_err_sbe); | ||
942 | |||
943 | edac_mc_del_mc(&op->dev); | ||
944 | edac_mc_free(mci); | ||
945 | return 0; | ||
946 | } | ||
947 | |||
948 | static struct of_device_id mpc85xx_mc_err_of_match[] = { | ||
949 | { | ||
950 | .compatible = "fsl,8540-memory-controller", | ||
951 | }, | ||
952 | { | ||
953 | .compatible = "fsl,8541-memory-controller", | ||
954 | }, | ||
955 | { | ||
956 | .compatible = "fsl,8544-memory-controller", | ||
957 | }, | ||
958 | { | ||
959 | .compatible = "fsl,8548-memory-controller", | ||
960 | }, | ||
961 | { | ||
962 | .compatible = "fsl,8555-memory-controller", | ||
963 | }, | ||
964 | { | ||
965 | .compatible = "fsl,8568-memory-controller", | ||
966 | }, | ||
967 | {}, | ||
968 | }; | ||
969 | |||
970 | static struct of_platform_driver mpc85xx_mc_err_driver = { | ||
971 | .owner = THIS_MODULE, | ||
972 | .name = "mpc85xx_mc_err", | ||
973 | .match_table = mpc85xx_mc_err_of_match, | ||
974 | .probe = mpc85xx_mc_err_probe, | ||
975 | .remove = mpc85xx_mc_err_remove, | ||
976 | .driver = { | ||
977 | .name = "mpc85xx_mc_err", | ||
978 | .owner = THIS_MODULE, | ||
979 | }, | ||
980 | }; | ||
981 | |||
982 | static int __init mpc85xx_mc_init(void) | ||
983 | { | ||
984 | int res = 0; | ||
985 | |||
986 | printk(KERN_INFO "Freescale(R) MPC85xx EDAC driver, " | ||
987 | "(C) 2006 Montavista Software\n"); | ||
988 | |||
989 | /* make sure error reporting method is sane */ | ||
990 | switch (edac_op_state) { | ||
991 | case EDAC_OPSTATE_POLL: | ||
992 | case EDAC_OPSTATE_INT: | ||
993 | break; | ||
994 | default: | ||
995 | edac_op_state = EDAC_OPSTATE_INT; | ||
996 | break; | ||
997 | } | ||
998 | |||
999 | res = of_register_platform_driver(&mpc85xx_mc_err_driver); | ||
1000 | if (res) | ||
1001 | printk(KERN_WARNING EDAC_MOD_STR "MC fails to register\n"); | ||
1002 | |||
1003 | res = of_register_platform_driver(&mpc85xx_l2_err_driver); | ||
1004 | if (res) | ||
1005 | printk(KERN_WARNING EDAC_MOD_STR "L2 fails to register\n"); | ||
1006 | |||
1007 | #ifdef CONFIG_PCI | ||
1008 | res = platform_driver_register(&mpc85xx_pci_err_driver); | ||
1009 | if (res) | ||
1010 | printk(KERN_WARNING EDAC_MOD_STR "PCI fails to register\n"); | ||
1011 | #endif | ||
1012 | |||
1013 | /* | ||
1014 | * need to clear HID1[RFXE] to disable machine check int | ||
1015 | * so we can catch it | ||
1016 | */ | ||
1017 | if (edac_op_state == EDAC_OPSTATE_INT) { | ||
1018 | orig_hid1 = mfspr(SPRN_HID1); | ||
1019 | mtspr(SPRN_HID1, (orig_hid1 & ~0x20000)); | ||
1020 | } | ||
1021 | |||
1022 | return 0; | ||
1023 | } | ||
1024 | |||
1025 | module_init(mpc85xx_mc_init); | ||
1026 | |||
1027 | static void __exit mpc85xx_mc_exit(void) | ||
1028 | { | ||
1029 | mtspr(SPRN_HID1, orig_hid1); | ||
1030 | #ifdef CONFIG_PCI | ||
1031 | platform_driver_unregister(&mpc85xx_pci_err_driver); | ||
1032 | #endif | ||
1033 | of_unregister_platform_driver(&mpc85xx_l2_err_driver); | ||
1034 | of_unregister_platform_driver(&mpc85xx_mc_err_driver); | ||
1035 | } | ||
1036 | |||
1037 | module_exit(mpc85xx_mc_exit); | ||
1038 | |||
1039 | MODULE_LICENSE("GPL"); | ||
1040 | MODULE_AUTHOR("Montavista Software, Inc."); | ||
1041 | module_param(edac_op_state, int, 0444); | ||
1042 | MODULE_PARM_DESC(edac_op_state, | ||
1043 | "EDAC Error Reporting state: 0=Poll, 2=Interrupt"); | ||
diff --git a/drivers/edac/mpc85xx_edac.h b/drivers/edac/mpc85xx_edac.h new file mode 100644 index 000000000000..135b3539a030 --- /dev/null +++ b/drivers/edac/mpc85xx_edac.h | |||
@@ -0,0 +1,162 @@ | |||
1 | /* | ||
2 | * Freescale MPC85xx Memory Controller kenel module | ||
3 | * Author: Dave Jiang <djiang@mvista.com> | ||
4 | * | ||
5 | * 2006-2007 (c) MontaVista Software, Inc. This file is licensed under | ||
6 | * the terms of the GNU General Public License version 2. This program | ||
7 | * is licensed "as is" without any warranty of any kind, whether express | ||
8 | * or implied. | ||
9 | * | ||
10 | */ | ||
11 | #ifndef _MPC85XX_EDAC_H_ | ||
12 | #define _MPC85XX_EDAC_H_ | ||
13 | |||
14 | #define MPC85XX_REVISION " Ver: 2.0.0 " __DATE__ | ||
15 | #define EDAC_MOD_STR "MPC85xx_edac" | ||
16 | |||
17 | #define mpc85xx_printk(level, fmt, arg...) \ | ||
18 | edac_printk(level, "MPC85xx", fmt, ##arg) | ||
19 | |||
20 | #define mpc85xx_mc_printk(mci, level, fmt, arg...) \ | ||
21 | edac_mc_chipset_printk(mci, level, "MPC85xx", fmt, ##arg) | ||
22 | |||
23 | /* | ||
24 | * DRAM error defines | ||
25 | */ | ||
26 | |||
27 | /* DDR_SDRAM_CFG */ | ||
28 | #define MPC85XX_MC_DDR_SDRAM_CFG 0x0110 | ||
29 | #define MPC85XX_MC_CS_BNDS_0 0x0000 | ||
30 | #define MPC85XX_MC_CS_BNDS_1 0x0008 | ||
31 | #define MPC85XX_MC_CS_BNDS_2 0x0010 | ||
32 | #define MPC85XX_MC_CS_BNDS_3 0x0018 | ||
33 | #define MPC85XX_MC_CS_BNDS_OFS 0x0008 | ||
34 | |||
35 | #define MPC85XX_MC_DATA_ERR_INJECT_HI 0x0e00 | ||
36 | #define MPC85XX_MC_DATA_ERR_INJECT_LO 0x0e04 | ||
37 | #define MPC85XX_MC_ECC_ERR_INJECT 0x0e08 | ||
38 | #define MPC85XX_MC_CAPTURE_DATA_HI 0x0e20 | ||
39 | #define MPC85XX_MC_CAPTURE_DATA_LO 0x0e24 | ||
40 | #define MPC85XX_MC_CAPTURE_ECC 0x0e28 | ||
41 | #define MPC85XX_MC_ERR_DETECT 0x0e40 | ||
42 | #define MPC85XX_MC_ERR_DISABLE 0x0e44 | ||
43 | #define MPC85XX_MC_ERR_INT_EN 0x0e48 | ||
44 | #define MPC85XX_MC_CAPTURE_ATRIBUTES 0x0e4c | ||
45 | #define MPC85XX_MC_CAPTURE_ADDRESS 0x0e50 | ||
46 | #define MPC85XX_MC_ERR_SBE 0x0e58 | ||
47 | |||
48 | #define DSC_MEM_EN 0x80000000 | ||
49 | #define DSC_ECC_EN 0x20000000 | ||
50 | #define DSC_RD_EN 0x10000000 | ||
51 | |||
52 | #define DSC_SDTYPE_MASK 0x07000000 | ||
53 | |||
54 | #define DSC_SDTYPE_DDR 0x02000000 | ||
55 | #define DSC_SDTYPE_DDR2 0x03000000 | ||
56 | #define DSC_X32_EN 0x00000020 | ||
57 | |||
58 | /* Err_Int_En */ | ||
59 | #define DDR_EIE_MSEE 0x1 /* memory select */ | ||
60 | #define DDR_EIE_SBEE 0x4 /* single-bit ECC error */ | ||
61 | #define DDR_EIE_MBEE 0x8 /* multi-bit ECC error */ | ||
62 | |||
63 | /* Err_Detect */ | ||
64 | #define DDR_EDE_MSE 0x1 /* memory select */ | ||
65 | #define DDR_EDE_SBE 0x4 /* single-bit ECC error */ | ||
66 | #define DDR_EDE_MBE 0x8 /* multi-bit ECC error */ | ||
67 | #define DDR_EDE_MME 0x80000000 /* multiple memory errors */ | ||
68 | |||
69 | /* Err_Disable */ | ||
70 | #define DDR_EDI_MSED 0x1 /* memory select disable */ | ||
71 | #define DDR_EDI_SBED 0x4 /* single-bit ECC error disable */ | ||
72 | #define DDR_EDI_MBED 0x8 /* multi-bit ECC error disable */ | ||
73 | |||
74 | /* | ||
75 | * L2 Err defines | ||
76 | */ | ||
77 | #define MPC85XX_L2_ERRINJHI 0x0000 | ||
78 | #define MPC85XX_L2_ERRINJLO 0x0004 | ||
79 | #define MPC85XX_L2_ERRINJCTL 0x0008 | ||
80 | #define MPC85XX_L2_CAPTDATAHI 0x0020 | ||
81 | #define MPC85XX_L2_CAPTDATALO 0x0024 | ||
82 | #define MPC85XX_L2_CAPTECC 0x0028 | ||
83 | #define MPC85XX_L2_ERRDET 0x0040 | ||
84 | #define MPC85XX_L2_ERRDIS 0x0044 | ||
85 | #define MPC85XX_L2_ERRINTEN 0x0048 | ||
86 | #define MPC85XX_L2_ERRATTR 0x004c | ||
87 | #define MPC85XX_L2_ERRADDR 0x0050 | ||
88 | #define MPC85XX_L2_ERRCTL 0x0058 | ||
89 | |||
90 | /* Error Interrupt Enable */ | ||
91 | #define L2_EIE_L2CFGINTEN 0x1 | ||
92 | #define L2_EIE_SBECCINTEN 0x4 | ||
93 | #define L2_EIE_MBECCINTEN 0x8 | ||
94 | #define L2_EIE_TPARINTEN 0x10 | ||
95 | #define L2_EIE_MASK (L2_EIE_L2CFGINTEN | L2_EIE_SBECCINTEN | \ | ||
96 | L2_EIE_MBECCINTEN | L2_EIE_TPARINTEN) | ||
97 | |||
98 | /* Error Detect */ | ||
99 | #define L2_EDE_L2CFGERR 0x1 | ||
100 | #define L2_EDE_SBECCERR 0x4 | ||
101 | #define L2_EDE_MBECCERR 0x8 | ||
102 | #define L2_EDE_TPARERR 0x10 | ||
103 | #define L2_EDE_MULL2ERR 0x80000000 | ||
104 | |||
105 | #define L2_EDE_CE_MASK L2_EDE_SBECCERR | ||
106 | #define L2_EDE_UE_MASK (L2_EDE_L2CFGERR | L2_EDE_MBECCERR | \ | ||
107 | L2_EDE_TPARERR) | ||
108 | #define L2_EDE_MASK (L2_EDE_L2CFGERR | L2_EDE_SBECCERR | \ | ||
109 | L2_EDE_MBECCERR | L2_EDE_TPARERR | L2_EDE_MULL2ERR) | ||
110 | |||
111 | /* | ||
112 | * PCI Err defines | ||
113 | */ | ||
114 | #define PCI_EDE_TOE 0x00000001 | ||
115 | #define PCI_EDE_SCM 0x00000002 | ||
116 | #define PCI_EDE_IRMSV 0x00000004 | ||
117 | #define PCI_EDE_ORMSV 0x00000008 | ||
118 | #define PCI_EDE_OWMSV 0x00000010 | ||
119 | #define PCI_EDE_TGT_ABRT 0x00000020 | ||
120 | #define PCI_EDE_MST_ABRT 0x00000040 | ||
121 | #define PCI_EDE_TGT_PERR 0x00000080 | ||
122 | #define PCI_EDE_MST_PERR 0x00000100 | ||
123 | #define PCI_EDE_RCVD_SERR 0x00000200 | ||
124 | #define PCI_EDE_ADDR_PERR 0x00000400 | ||
125 | #define PCI_EDE_MULTI_ERR 0x80000000 | ||
126 | |||
127 | #define PCI_EDE_PERR_MASK (PCI_EDE_TGT_PERR | PCI_EDE_MST_PERR | \ | ||
128 | PCI_EDE_ADDR_PERR) | ||
129 | |||
130 | #define MPC85XX_PCI_ERR_DR 0x0000 | ||
131 | #define MPC85XX_PCI_ERR_CAP_DR 0x0004 | ||
132 | #define MPC85XX_PCI_ERR_EN 0x0008 | ||
133 | #define MPC85XX_PCI_ERR_ATTRIB 0x000c | ||
134 | #define MPC85XX_PCI_ERR_ADDR 0x0010 | ||
135 | #define MPC85XX_PCI_ERR_EXT_ADDR 0x0014 | ||
136 | #define MPC85XX_PCI_ERR_DL 0x0018 | ||
137 | #define MPC85XX_PCI_ERR_DH 0x001c | ||
138 | #define MPC85XX_PCI_GAS_TIMR 0x0020 | ||
139 | #define MPC85XX_PCI_PCIX_TIMR 0x0024 | ||
140 | |||
141 | struct mpc85xx_mc_pdata { | ||
142 | char *name; | ||
143 | int edac_idx; | ||
144 | void __iomem *mc_vbase; | ||
145 | int irq; | ||
146 | }; | ||
147 | |||
148 | struct mpc85xx_l2_pdata { | ||
149 | char *name; | ||
150 | int edac_idx; | ||
151 | void __iomem *l2_vbase; | ||
152 | int irq; | ||
153 | }; | ||
154 | |||
155 | struct mpc85xx_pci_pdata { | ||
156 | char *name; | ||
157 | int edac_idx; | ||
158 | void __iomem *pci_vbase; | ||
159 | int irq; | ||
160 | }; | ||
161 | |||
162 | #endif | ||
diff --git a/drivers/edac/mv64x60_edac.c b/drivers/edac/mv64x60_edac.c new file mode 100644 index 000000000000..bf071f140a05 --- /dev/null +++ b/drivers/edac/mv64x60_edac.c | |||
@@ -0,0 +1,855 @@ | |||
1 | /* | ||
2 | * Marvell MV64x60 Memory Controller kernel module for PPC platforms | ||
3 | * | ||
4 | * Author: Dave Jiang <djiang@mvista.com> | ||
5 | * | ||
6 | * 2006-2007 (c) MontaVista Software, Inc. This file is licensed under | ||
7 | * the terms of the GNU General Public License version 2. This program | ||
8 | * is licensed "as is" without any warranty of any kind, whether express | ||
9 | * or implied. | ||
10 | * | ||
11 | */ | ||
12 | |||
13 | #include <linux/module.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/slab.h> | ||
16 | #include <linux/interrupt.h> | ||
17 | #include <linux/io.h> | ||
18 | #include <linux/edac.h> | ||
19 | |||
20 | #include "edac_core.h" | ||
21 | #include "edac_module.h" | ||
22 | #include "mv64x60_edac.h" | ||
23 | |||
24 | static const char *mv64x60_ctl_name = "MV64x60"; | ||
25 | static int edac_dev_idx; | ||
26 | static int edac_pci_idx; | ||
27 | static int edac_mc_idx; | ||
28 | |||
29 | /*********************** PCI err device **********************************/ | ||
30 | #ifdef CONFIG_PCI | ||
31 | static void mv64x60_pci_check(struct edac_pci_ctl_info *pci) | ||
32 | { | ||
33 | struct mv64x60_pci_pdata *pdata = pci->pvt_info; | ||
34 | u32 cause; | ||
35 | |||
36 | cause = in_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_CAUSE); | ||
37 | if (!cause) | ||
38 | return; | ||
39 | |||
40 | printk(KERN_ERR "Error in PCI %d Interface\n", pdata->pci_hose); | ||
41 | printk(KERN_ERR "Cause register: 0x%08x\n", cause); | ||
42 | printk(KERN_ERR "Address Low: 0x%08x\n", | ||
43 | in_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_ADDR_LO)); | ||
44 | printk(KERN_ERR "Address High: 0x%08x\n", | ||
45 | in_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_ADDR_HI)); | ||
46 | printk(KERN_ERR "Attribute: 0x%08x\n", | ||
47 | in_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_ATTR)); | ||
48 | printk(KERN_ERR "Command: 0x%08x\n", | ||
49 | in_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_CMD)); | ||
50 | out_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_CAUSE, ~cause); | ||
51 | |||
52 | if (cause & MV64X60_PCI_PE_MASK) | ||
53 | edac_pci_handle_pe(pci, pci->ctl_name); | ||
54 | |||
55 | if (!(cause & MV64X60_PCI_PE_MASK)) | ||
56 | edac_pci_handle_npe(pci, pci->ctl_name); | ||
57 | } | ||
58 | |||
59 | static irqreturn_t mv64x60_pci_isr(int irq, void *dev_id) | ||
60 | { | ||
61 | struct edac_pci_ctl_info *pci = dev_id; | ||
62 | struct mv64x60_pci_pdata *pdata = pci->pvt_info; | ||
63 | u32 val; | ||
64 | |||
65 | val = in_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_CAUSE); | ||
66 | if (!val) | ||
67 | return IRQ_NONE; | ||
68 | |||
69 | mv64x60_pci_check(pci); | ||
70 | |||
71 | return IRQ_HANDLED; | ||
72 | } | ||
73 | |||
74 | static int __devinit mv64x60_pci_err_probe(struct platform_device *pdev) | ||
75 | { | ||
76 | struct edac_pci_ctl_info *pci; | ||
77 | struct mv64x60_pci_pdata *pdata; | ||
78 | struct resource *r; | ||
79 | int res = 0; | ||
80 | |||
81 | if (!devres_open_group(&pdev->dev, mv64x60_pci_err_probe, GFP_KERNEL)) | ||
82 | return -ENOMEM; | ||
83 | |||
84 | pci = edac_pci_alloc_ctl_info(sizeof(*pdata), "mv64x60_pci_err"); | ||
85 | if (!pci) | ||
86 | return -ENOMEM; | ||
87 | |||
88 | pdata = pci->pvt_info; | ||
89 | |||
90 | pdata->pci_hose = pdev->id; | ||
91 | pdata->name = "mpc85xx_pci_err"; | ||
92 | pdata->irq = NO_IRQ; | ||
93 | platform_set_drvdata(pdev, pci); | ||
94 | pci->dev = &pdev->dev; | ||
95 | pci->dev_name = pdev->dev.bus_id; | ||
96 | pci->mod_name = EDAC_MOD_STR; | ||
97 | pci->ctl_name = pdata->name; | ||
98 | |||
99 | if (edac_op_state == EDAC_OPSTATE_POLL) | ||
100 | pci->edac_check = mv64x60_pci_check; | ||
101 | |||
102 | pdata->edac_idx = edac_pci_idx++; | ||
103 | |||
104 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
105 | if (!r) { | ||
106 | printk(KERN_ERR "%s: Unable to get resource for " | ||
107 | "PCI err regs\n", __func__); | ||
108 | res = -ENOENT; | ||
109 | goto err; | ||
110 | } | ||
111 | |||
112 | if (!devm_request_mem_region(&pdev->dev, | ||
113 | r->start, | ||
114 | r->end - r->start + 1, | ||
115 | pdata->name)) { | ||
116 | printk(KERN_ERR "%s: Error while requesting mem region\n", | ||
117 | __func__); | ||
118 | res = -EBUSY; | ||
119 | goto err; | ||
120 | } | ||
121 | |||
122 | pdata->pci_vbase = devm_ioremap(&pdev->dev, | ||
123 | r->start, | ||
124 | r->end - r->start + 1); | ||
125 | if (!pdata->pci_vbase) { | ||
126 | printk(KERN_ERR "%s: Unable to setup PCI err regs\n", __func__); | ||
127 | res = -ENOMEM; | ||
128 | goto err; | ||
129 | } | ||
130 | |||
131 | out_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_CAUSE, 0); | ||
132 | out_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_MASK, 0); | ||
133 | out_le32(pdata->pci_vbase + MV64X60_PCI_ERROR_MASK, | ||
134 | MV64X60_PCIx_ERR_MASK_VAL); | ||
135 | |||
136 | if (edac_pci_add_device(pci, pdata->edac_idx) > 0) { | ||
137 | debugf3("%s(): failed edac_pci_add_device()\n", __func__); | ||
138 | goto err; | ||
139 | } | ||
140 | |||
141 | if (edac_op_state == EDAC_OPSTATE_INT) { | ||
142 | pdata->irq = platform_get_irq(pdev, 0); | ||
143 | res = devm_request_irq(&pdev->dev, | ||
144 | pdata->irq, | ||
145 | mv64x60_pci_isr, | ||
146 | IRQF_DISABLED, | ||
147 | "[EDAC] PCI err", | ||
148 | pci); | ||
149 | if (res < 0) { | ||
150 | printk(KERN_ERR "%s: Unable to request irq %d for " | ||
151 | "MV64x60 PCI ERR\n", __func__, pdata->irq); | ||
152 | res = -ENODEV; | ||
153 | goto err2; | ||
154 | } | ||
155 | printk(KERN_INFO EDAC_MOD_STR " acquired irq %d for PCI Err\n", | ||
156 | pdata->irq); | ||
157 | } | ||
158 | |||
159 | devres_remove_group(&pdev->dev, mv64x60_pci_err_probe); | ||
160 | |||
161 | /* get this far and it's successful */ | ||
162 | debugf3("%s(): success\n", __func__); | ||
163 | |||
164 | return 0; | ||
165 | |||
166 | err2: | ||
167 | edac_pci_del_device(&pdev->dev); | ||
168 | err: | ||
169 | edac_pci_free_ctl_info(pci); | ||
170 | devres_release_group(&pdev->dev, mv64x60_pci_err_probe); | ||
171 | return res; | ||
172 | } | ||
173 | |||
174 | static int mv64x60_pci_err_remove(struct platform_device *pdev) | ||
175 | { | ||
176 | struct edac_pci_ctl_info *pci = platform_get_drvdata(pdev); | ||
177 | |||
178 | debugf0("%s()\n", __func__); | ||
179 | |||
180 | edac_pci_del_device(&pdev->dev); | ||
181 | |||
182 | edac_pci_free_ctl_info(pci); | ||
183 | |||
184 | return 0; | ||
185 | } | ||
186 | |||
187 | static struct platform_driver mv64x60_pci_err_driver = { | ||
188 | .probe = mv64x60_pci_err_probe, | ||
189 | .remove = __devexit_p(mv64x60_pci_err_remove), | ||
190 | .driver = { | ||
191 | .name = "mv64x60_pci_err", | ||
192 | } | ||
193 | }; | ||
194 | |||
195 | #endif /* CONFIG_PCI */ | ||
196 | |||
197 | /*********************** SRAM err device **********************************/ | ||
198 | static void mv64x60_sram_check(struct edac_device_ctl_info *edac_dev) | ||
199 | { | ||
200 | struct mv64x60_sram_pdata *pdata = edac_dev->pvt_info; | ||
201 | u32 cause; | ||
202 | |||
203 | cause = in_le32(pdata->sram_vbase + MV64X60_SRAM_ERR_CAUSE); | ||
204 | if (!cause) | ||
205 | return; | ||
206 | |||
207 | printk(KERN_ERR "Error in internal SRAM\n"); | ||
208 | printk(KERN_ERR "Cause register: 0x%08x\n", cause); | ||
209 | printk(KERN_ERR "Address Low: 0x%08x\n", | ||
210 | in_le32(pdata->sram_vbase + MV64X60_SRAM_ERR_ADDR_LO)); | ||
211 | printk(KERN_ERR "Address High: 0x%08x\n", | ||
212 | in_le32(pdata->sram_vbase + MV64X60_SRAM_ERR_ADDR_HI)); | ||
213 | printk(KERN_ERR "Data Low: 0x%08x\n", | ||
214 | in_le32(pdata->sram_vbase + MV64X60_SRAM_ERR_DATA_LO)); | ||
215 | printk(KERN_ERR "Data High: 0x%08x\n", | ||
216 | in_le32(pdata->sram_vbase + MV64X60_SRAM_ERR_DATA_HI)); | ||
217 | printk(KERN_ERR "Parity: 0x%08x\n", | ||
218 | in_le32(pdata->sram_vbase + MV64X60_SRAM_ERR_PARITY)); | ||
219 | out_le32(pdata->sram_vbase + MV64X60_SRAM_ERR_CAUSE, 0); | ||
220 | |||
221 | edac_device_handle_ue(edac_dev, 0, 0, edac_dev->ctl_name); | ||
222 | } | ||
223 | |||
224 | static irqreturn_t mv64x60_sram_isr(int irq, void *dev_id) | ||
225 | { | ||
226 | struct edac_device_ctl_info *edac_dev = dev_id; | ||
227 | struct mv64x60_sram_pdata *pdata = edac_dev->pvt_info; | ||
228 | u32 cause; | ||
229 | |||
230 | cause = in_le32(pdata->sram_vbase + MV64X60_SRAM_ERR_CAUSE); | ||
231 | if (!cause) | ||
232 | return IRQ_NONE; | ||
233 | |||
234 | mv64x60_sram_check(edac_dev); | ||
235 | |||
236 | return IRQ_HANDLED; | ||
237 | } | ||
238 | |||
239 | static int __devinit mv64x60_sram_err_probe(struct platform_device *pdev) | ||
240 | { | ||
241 | struct edac_device_ctl_info *edac_dev; | ||
242 | struct mv64x60_sram_pdata *pdata; | ||
243 | struct resource *r; | ||
244 | int res = 0; | ||
245 | |||
246 | if (!devres_open_group(&pdev->dev, mv64x60_sram_err_probe, GFP_KERNEL)) | ||
247 | return -ENOMEM; | ||
248 | |||
249 | edac_dev = edac_device_alloc_ctl_info(sizeof(*pdata), | ||
250 | "sram", 1, NULL, 0, 0, NULL, 0, | ||
251 | edac_dev_idx); | ||
252 | if (!edac_dev) { | ||
253 | devres_release_group(&pdev->dev, mv64x60_sram_err_probe); | ||
254 | return -ENOMEM; | ||
255 | } | ||
256 | |||
257 | pdata = edac_dev->pvt_info; | ||
258 | pdata->name = "mv64x60_sram_err"; | ||
259 | pdata->irq = NO_IRQ; | ||
260 | edac_dev->dev = &pdev->dev; | ||
261 | platform_set_drvdata(pdev, edac_dev); | ||
262 | edac_dev->dev_name = pdev->dev.bus_id; | ||
263 | |||
264 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
265 | if (!r) { | ||
266 | printk(KERN_ERR "%s: Unable to get resource for " | ||
267 | "SRAM err regs\n", __func__); | ||
268 | res = -ENOENT; | ||
269 | goto err; | ||
270 | } | ||
271 | |||
272 | if (!devm_request_mem_region(&pdev->dev, | ||
273 | r->start, | ||
274 | r->end - r->start + 1, | ||
275 | pdata->name)) { | ||
276 | printk(KERN_ERR "%s: Error while request mem region\n", | ||
277 | __func__); | ||
278 | res = -EBUSY; | ||
279 | goto err; | ||
280 | } | ||
281 | |||
282 | pdata->sram_vbase = devm_ioremap(&pdev->dev, | ||
283 | r->start, | ||
284 | r->end - r->start + 1); | ||
285 | if (!pdata->sram_vbase) { | ||
286 | printk(KERN_ERR "%s: Unable to setup SRAM err regs\n", | ||
287 | __func__); | ||
288 | res = -ENOMEM; | ||
289 | goto err; | ||
290 | } | ||
291 | |||
292 | /* setup SRAM err registers */ | ||
293 | out_le32(pdata->sram_vbase + MV64X60_SRAM_ERR_CAUSE, 0); | ||
294 | |||
295 | edac_dev->mod_name = EDAC_MOD_STR; | ||
296 | edac_dev->ctl_name = pdata->name; | ||
297 | |||
298 | if (edac_op_state == EDAC_OPSTATE_POLL) | ||
299 | edac_dev->edac_check = mv64x60_sram_check; | ||
300 | |||
301 | pdata->edac_idx = edac_dev_idx++; | ||
302 | |||
303 | if (edac_device_add_device(edac_dev) > 0) { | ||
304 | debugf3("%s(): failed edac_device_add_device()\n", __func__); | ||
305 | goto err; | ||
306 | } | ||
307 | |||
308 | if (edac_op_state == EDAC_OPSTATE_INT) { | ||
309 | pdata->irq = platform_get_irq(pdev, 0); | ||
310 | res = devm_request_irq(&pdev->dev, | ||
311 | pdata->irq, | ||
312 | mv64x60_sram_isr, | ||
313 | IRQF_DISABLED, | ||
314 | "[EDAC] SRAM err", | ||
315 | edac_dev); | ||
316 | if (res < 0) { | ||
317 | printk(KERN_ERR | ||
318 | "%s: Unable to request irq %d for " | ||
319 | "MV64x60 SRAM ERR\n", __func__, pdata->irq); | ||
320 | res = -ENODEV; | ||
321 | goto err2; | ||
322 | } | ||
323 | |||
324 | printk(KERN_INFO EDAC_MOD_STR " acquired irq %d for SRAM Err\n", | ||
325 | pdata->irq); | ||
326 | } | ||
327 | |||
328 | devres_remove_group(&pdev->dev, mv64x60_sram_err_probe); | ||
329 | |||
330 | /* get this far and it's successful */ | ||
331 | debugf3("%s(): success\n", __func__); | ||
332 | |||
333 | return 0; | ||
334 | |||
335 | err2: | ||
336 | edac_device_del_device(&pdev->dev); | ||
337 | err: | ||
338 | devres_release_group(&pdev->dev, mv64x60_sram_err_probe); | ||
339 | edac_device_free_ctl_info(edac_dev); | ||
340 | return res; | ||
341 | } | ||
342 | |||
343 | static int mv64x60_sram_err_remove(struct platform_device *pdev) | ||
344 | { | ||
345 | struct edac_device_ctl_info *edac_dev = platform_get_drvdata(pdev); | ||
346 | |||
347 | debugf0("%s()\n", __func__); | ||
348 | |||
349 | edac_device_del_device(&pdev->dev); | ||
350 | edac_device_free_ctl_info(edac_dev); | ||
351 | |||
352 | return 0; | ||
353 | } | ||
354 | |||
355 | static struct platform_driver mv64x60_sram_err_driver = { | ||
356 | .probe = mv64x60_sram_err_probe, | ||
357 | .remove = mv64x60_sram_err_remove, | ||
358 | .driver = { | ||
359 | .name = "mv64x60_sram_err", | ||
360 | } | ||
361 | }; | ||
362 | |||
363 | /*********************** CPU err device **********************************/ | ||
364 | static void mv64x60_cpu_check(struct edac_device_ctl_info *edac_dev) | ||
365 | { | ||
366 | struct mv64x60_cpu_pdata *pdata = edac_dev->pvt_info; | ||
367 | u32 cause; | ||
368 | |||
369 | cause = in_le32(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_CAUSE) & | ||
370 | MV64x60_CPU_CAUSE_MASK; | ||
371 | if (!cause) | ||
372 | return; | ||
373 | |||
374 | printk(KERN_ERR "Error on CPU interface\n"); | ||
375 | printk(KERN_ERR "Cause register: 0x%08x\n", cause); | ||
376 | printk(KERN_ERR "Address Low: 0x%08x\n", | ||
377 | in_le32(pdata->cpu_vbase[0] + MV64x60_CPU_ERR_ADDR_LO)); | ||
378 | printk(KERN_ERR "Address High: 0x%08x\n", | ||
379 | in_le32(pdata->cpu_vbase[0] + MV64x60_CPU_ERR_ADDR_HI)); | ||
380 | printk(KERN_ERR "Data Low: 0x%08x\n", | ||
381 | in_le32(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_DATA_LO)); | ||
382 | printk(KERN_ERR "Data High: 0x%08x\n", | ||
383 | in_le32(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_DATA_HI)); | ||
384 | printk(KERN_ERR "Parity: 0x%08x\n", | ||
385 | in_le32(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_PARITY)); | ||
386 | out_le32(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_CAUSE, 0); | ||
387 | |||
388 | edac_device_handle_ue(edac_dev, 0, 0, edac_dev->ctl_name); | ||
389 | } | ||
390 | |||
391 | static irqreturn_t mv64x60_cpu_isr(int irq, void *dev_id) | ||
392 | { | ||
393 | struct edac_device_ctl_info *edac_dev = dev_id; | ||
394 | struct mv64x60_cpu_pdata *pdata = edac_dev->pvt_info; | ||
395 | u32 cause; | ||
396 | |||
397 | cause = in_le32(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_CAUSE) & | ||
398 | MV64x60_CPU_CAUSE_MASK; | ||
399 | if (!cause) | ||
400 | return IRQ_NONE; | ||
401 | |||
402 | mv64x60_cpu_check(edac_dev); | ||
403 | |||
404 | return IRQ_HANDLED; | ||
405 | } | ||
406 | |||
407 | static int __devinit mv64x60_cpu_err_probe(struct platform_device *pdev) | ||
408 | { | ||
409 | struct edac_device_ctl_info *edac_dev; | ||
410 | struct resource *r; | ||
411 | struct mv64x60_cpu_pdata *pdata; | ||
412 | int res = 0; | ||
413 | |||
414 | if (!devres_open_group(&pdev->dev, mv64x60_cpu_err_probe, GFP_KERNEL)) | ||
415 | return -ENOMEM; | ||
416 | |||
417 | edac_dev = edac_device_alloc_ctl_info(sizeof(*pdata), | ||
418 | "cpu", 1, NULL, 0, 0, NULL, 0, | ||
419 | edac_dev_idx); | ||
420 | if (!edac_dev) { | ||
421 | devres_release_group(&pdev->dev, mv64x60_cpu_err_probe); | ||
422 | return -ENOMEM; | ||
423 | } | ||
424 | |||
425 | pdata = edac_dev->pvt_info; | ||
426 | pdata->name = "mv64x60_cpu_err"; | ||
427 | pdata->irq = NO_IRQ; | ||
428 | edac_dev->dev = &pdev->dev; | ||
429 | platform_set_drvdata(pdev, edac_dev); | ||
430 | edac_dev->dev_name = pdev->dev.bus_id; | ||
431 | |||
432 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
433 | if (!r) { | ||
434 | printk(KERN_ERR "%s: Unable to get resource for " | ||
435 | "CPU err regs\n", __func__); | ||
436 | res = -ENOENT; | ||
437 | goto err; | ||
438 | } | ||
439 | |||
440 | if (!devm_request_mem_region(&pdev->dev, | ||
441 | r->start, | ||
442 | r->end - r->start + 1, | ||
443 | pdata->name)) { | ||
444 | printk(KERN_ERR "%s: Error while requesting mem region\n", | ||
445 | __func__); | ||
446 | res = -EBUSY; | ||
447 | goto err; | ||
448 | } | ||
449 | |||
450 | pdata->cpu_vbase[0] = devm_ioremap(&pdev->dev, | ||
451 | r->start, | ||
452 | r->end - r->start + 1); | ||
453 | if (!pdata->cpu_vbase[0]) { | ||
454 | printk(KERN_ERR "%s: Unable to setup CPU err regs\n", __func__); | ||
455 | res = -ENOMEM; | ||
456 | goto err; | ||
457 | } | ||
458 | |||
459 | r = platform_get_resource(pdev, IORESOURCE_MEM, 1); | ||
460 | if (!r) { | ||
461 | printk(KERN_ERR "%s: Unable to get resource for " | ||
462 | "CPU err regs\n", __func__); | ||
463 | res = -ENOENT; | ||
464 | goto err; | ||
465 | } | ||
466 | |||
467 | if (!devm_request_mem_region(&pdev->dev, | ||
468 | r->start, | ||
469 | r->end - r->start + 1, | ||
470 | pdata->name)) { | ||
471 | printk(KERN_ERR "%s: Error while requesting mem region\n", | ||
472 | __func__); | ||
473 | res = -EBUSY; | ||
474 | goto err; | ||
475 | } | ||
476 | |||
477 | pdata->cpu_vbase[1] = devm_ioremap(&pdev->dev, | ||
478 | r->start, | ||
479 | r->end - r->start + 1); | ||
480 | if (!pdata->cpu_vbase[1]) { | ||
481 | printk(KERN_ERR "%s: Unable to setup CPU err regs\n", __func__); | ||
482 | res = -ENOMEM; | ||
483 | goto err; | ||
484 | } | ||
485 | |||
486 | /* setup CPU err registers */ | ||
487 | out_le32(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_CAUSE, 0); | ||
488 | out_le32(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_MASK, 0); | ||
489 | out_le32(pdata->cpu_vbase[1] + MV64x60_CPU_ERR_MASK, 0x000000ff); | ||
490 | |||
491 | edac_dev->mod_name = EDAC_MOD_STR; | ||
492 | edac_dev->ctl_name = pdata->name; | ||
493 | if (edac_op_state == EDAC_OPSTATE_POLL) | ||
494 | edac_dev->edac_check = mv64x60_cpu_check; | ||
495 | |||
496 | pdata->edac_idx = edac_dev_idx++; | ||
497 | |||
498 | if (edac_device_add_device(edac_dev) > 0) { | ||
499 | debugf3("%s(): failed edac_device_add_device()\n", __func__); | ||
500 | goto err; | ||
501 | } | ||
502 | |||
503 | if (edac_op_state == EDAC_OPSTATE_INT) { | ||
504 | pdata->irq = platform_get_irq(pdev, 0); | ||
505 | res = devm_request_irq(&pdev->dev, | ||
506 | pdata->irq, | ||
507 | mv64x60_cpu_isr, | ||
508 | IRQF_DISABLED, | ||
509 | "[EDAC] CPU err", | ||
510 | edac_dev); | ||
511 | if (res < 0) { | ||
512 | printk(KERN_ERR | ||
513 | "%s: Unable to request irq %d for MV64x60 " | ||
514 | "CPU ERR\n", __func__, pdata->irq); | ||
515 | res = -ENODEV; | ||
516 | goto err2; | ||
517 | } | ||
518 | |||
519 | printk(KERN_INFO EDAC_MOD_STR | ||
520 | " acquired irq %d for CPU Err\n", pdata->irq); | ||
521 | } | ||
522 | |||
523 | devres_remove_group(&pdev->dev, mv64x60_cpu_err_probe); | ||
524 | |||
525 | /* get this far and it's successful */ | ||
526 | debugf3("%s(): success\n", __func__); | ||
527 | |||
528 | return 0; | ||
529 | |||
530 | err2: | ||
531 | edac_device_del_device(&pdev->dev); | ||
532 | err: | ||
533 | devres_release_group(&pdev->dev, mv64x60_cpu_err_probe); | ||
534 | edac_device_free_ctl_info(edac_dev); | ||
535 | return res; | ||
536 | } | ||
537 | |||
538 | static int mv64x60_cpu_err_remove(struct platform_device *pdev) | ||
539 | { | ||
540 | struct edac_device_ctl_info *edac_dev = platform_get_drvdata(pdev); | ||
541 | |||
542 | debugf0("%s()\n", __func__); | ||
543 | |||
544 | edac_device_del_device(&pdev->dev); | ||
545 | edac_device_free_ctl_info(edac_dev); | ||
546 | return 0; | ||
547 | } | ||
548 | |||
549 | static struct platform_driver mv64x60_cpu_err_driver = { | ||
550 | .probe = mv64x60_cpu_err_probe, | ||
551 | .remove = mv64x60_cpu_err_remove, | ||
552 | .driver = { | ||
553 | .name = "mv64x60_cpu_err", | ||
554 | } | ||
555 | }; | ||
556 | |||
557 | /*********************** DRAM err device **********************************/ | ||
558 | |||
559 | static void mv64x60_mc_check(struct mem_ctl_info *mci) | ||
560 | { | ||
561 | struct mv64x60_mc_pdata *pdata = mci->pvt_info; | ||
562 | u32 reg; | ||
563 | u32 err_addr; | ||
564 | u32 sdram_ecc; | ||
565 | u32 comp_ecc; | ||
566 | u32 syndrome; | ||
567 | |||
568 | reg = in_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ADDR); | ||
569 | if (!reg) | ||
570 | return; | ||
571 | |||
572 | err_addr = reg & ~0x3; | ||
573 | sdram_ecc = in_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ECC_RCVD); | ||
574 | comp_ecc = in_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ECC_CALC); | ||
575 | syndrome = sdram_ecc ^ comp_ecc; | ||
576 | |||
577 | /* first bit clear in ECC Err Reg, 1 bit error, correctable by HW */ | ||
578 | if (!(reg & 0x1)) | ||
579 | edac_mc_handle_ce(mci, err_addr >> PAGE_SHIFT, | ||
580 | err_addr & PAGE_MASK, syndrome, 0, 0, | ||
581 | mci->ctl_name); | ||
582 | else /* 2 bit error, UE */ | ||
583 | edac_mc_handle_ue(mci, err_addr >> PAGE_SHIFT, | ||
584 | err_addr & PAGE_MASK, 0, mci->ctl_name); | ||
585 | |||
586 | /* clear the error */ | ||
587 | out_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ADDR, 0); | ||
588 | } | ||
589 | |||
590 | static irqreturn_t mv64x60_mc_isr(int irq, void *dev_id) | ||
591 | { | ||
592 | struct mem_ctl_info *mci = dev_id; | ||
593 | struct mv64x60_mc_pdata *pdata = mci->pvt_info; | ||
594 | u32 reg; | ||
595 | |||
596 | reg = in_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ADDR); | ||
597 | if (!reg) | ||
598 | return IRQ_NONE; | ||
599 | |||
600 | /* writing 0's to the ECC err addr in check function clears irq */ | ||
601 | mv64x60_mc_check(mci); | ||
602 | |||
603 | return IRQ_HANDLED; | ||
604 | } | ||
605 | |||
606 | static void get_total_mem(struct mv64x60_mc_pdata *pdata) | ||
607 | { | ||
608 | struct device_node *np = NULL; | ||
609 | const unsigned int *reg; | ||
610 | |||
611 | np = of_find_node_by_type(NULL, "memory"); | ||
612 | if (!np) | ||
613 | return; | ||
614 | |||
615 | reg = get_property(np, "reg", NULL); | ||
616 | |||
617 | pdata->total_mem = reg[1]; | ||
618 | } | ||
619 | |||
620 | static void mv64x60_init_csrows(struct mem_ctl_info *mci, | ||
621 | struct mv64x60_mc_pdata *pdata) | ||
622 | { | ||
623 | struct csrow_info *csrow; | ||
624 | u32 devtype; | ||
625 | u32 ctl; | ||
626 | |||
627 | get_total_mem(pdata); | ||
628 | |||
629 | ctl = in_le32(pdata->mc_vbase + MV64X60_SDRAM_CONFIG); | ||
630 | |||
631 | csrow = &mci->csrows[0]; | ||
632 | csrow->first_page = 0; | ||
633 | csrow->nr_pages = pdata->total_mem >> PAGE_SHIFT; | ||
634 | csrow->last_page = csrow->first_page + csrow->nr_pages - 1; | ||
635 | csrow->grain = 8; | ||
636 | |||
637 | csrow->mtype = (ctl & MV64X60_SDRAM_REGISTERED) ? MEM_RDDR : MEM_DDR; | ||
638 | |||
639 | devtype = (ctl >> 20) & 0x3; | ||
640 | switch (devtype) { | ||
641 | case 0x0: | ||
642 | csrow->dtype = DEV_X32; | ||
643 | break; | ||
644 | case 0x2: /* could be X8 too, but no way to tell */ | ||
645 | csrow->dtype = DEV_X16; | ||
646 | break; | ||
647 | case 0x3: | ||
648 | csrow->dtype = DEV_X4; | ||
649 | break; | ||
650 | default: | ||
651 | csrow->dtype = DEV_UNKNOWN; | ||
652 | break; | ||
653 | } | ||
654 | |||
655 | csrow->edac_mode = EDAC_SECDED; | ||
656 | } | ||
657 | |||
658 | static int __devinit mv64x60_mc_err_probe(struct platform_device *pdev) | ||
659 | { | ||
660 | struct mem_ctl_info *mci; | ||
661 | struct mv64x60_mc_pdata *pdata; | ||
662 | struct resource *r; | ||
663 | u32 ctl; | ||
664 | int res = 0; | ||
665 | |||
666 | if (!devres_open_group(&pdev->dev, mv64x60_mc_err_probe, GFP_KERNEL)) | ||
667 | return -ENOMEM; | ||
668 | |||
669 | mci = edac_mc_alloc(sizeof(struct mv64x60_mc_pdata), 1, 1, edac_mc_idx); | ||
670 | if (!mci) { | ||
671 | printk(KERN_ERR "%s: No memory for CPU err\n", __func__); | ||
672 | devres_release_group(&pdev->dev, mv64x60_mc_err_probe); | ||
673 | return -ENOMEM; | ||
674 | } | ||
675 | |||
676 | pdata = mci->pvt_info; | ||
677 | mci->dev = &pdev->dev; | ||
678 | platform_set_drvdata(pdev, mci); | ||
679 | pdata->name = "mv64x60_mc_err"; | ||
680 | pdata->irq = NO_IRQ; | ||
681 | mci->dev_name = pdev->dev.bus_id; | ||
682 | pdata->edac_idx = edac_mc_idx++; | ||
683 | |||
684 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
685 | if (!r) { | ||
686 | printk(KERN_ERR "%s: Unable to get resource for " | ||
687 | "MC err regs\n", __func__); | ||
688 | res = -ENOENT; | ||
689 | goto err; | ||
690 | } | ||
691 | |||
692 | if (!devm_request_mem_region(&pdev->dev, | ||
693 | r->start, | ||
694 | r->end - r->start + 1, | ||
695 | pdata->name)) { | ||
696 | printk(KERN_ERR "%s: Error while requesting mem region\n", | ||
697 | __func__); | ||
698 | res = -EBUSY; | ||
699 | goto err; | ||
700 | } | ||
701 | |||
702 | pdata->mc_vbase = devm_ioremap(&pdev->dev, | ||
703 | r->start, | ||
704 | r->end - r->start + 1); | ||
705 | if (!pdata->mc_vbase) { | ||
706 | printk(KERN_ERR "%s: Unable to setup MC err regs\n", __func__); | ||
707 | res = -ENOMEM; | ||
708 | goto err; | ||
709 | } | ||
710 | |||
711 | ctl = in_le32(pdata->mc_vbase + MV64X60_SDRAM_CONFIG); | ||
712 | if (!(ctl & MV64X60_SDRAM_ECC)) { | ||
713 | /* Non-ECC RAM? */ | ||
714 | printk(KERN_WARNING "%s: No ECC DIMMs discovered\n", __func__); | ||
715 | res = -ENODEV; | ||
716 | goto err2; | ||
717 | } | ||
718 | |||
719 | debugf3("%s(): init mci\n", __func__); | ||
720 | mci->mtype_cap = MEM_FLAG_RDDR | MEM_FLAG_DDR; | ||
721 | mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED; | ||
722 | mci->edac_cap = EDAC_FLAG_SECDED; | ||
723 | mci->mod_name = EDAC_MOD_STR; | ||
724 | mci->mod_ver = MV64x60_REVISION; | ||
725 | mci->ctl_name = mv64x60_ctl_name; | ||
726 | |||
727 | if (edac_op_state == EDAC_OPSTATE_POLL) | ||
728 | mci->edac_check = mv64x60_mc_check; | ||
729 | |||
730 | mci->ctl_page_to_phys = NULL; | ||
731 | |||
732 | mci->scrub_mode = SCRUB_SW_SRC; | ||
733 | |||
734 | mv64x60_init_csrows(mci, pdata); | ||
735 | |||
736 | /* setup MC registers */ | ||
737 | out_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ADDR, 0); | ||
738 | ctl = in_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ECC_CNTL); | ||
739 | ctl = (ctl & 0xff00ffff) | 0x10000; | ||
740 | out_le32(pdata->mc_vbase + MV64X60_SDRAM_ERR_ECC_CNTL, ctl); | ||
741 | |||
742 | if (edac_mc_add_mc(mci)) { | ||
743 | debugf3("%s(): failed edac_mc_add_mc()\n", __func__); | ||
744 | goto err; | ||
745 | } | ||
746 | |||
747 | if (edac_op_state == EDAC_OPSTATE_INT) { | ||
748 | /* acquire interrupt that reports errors */ | ||
749 | pdata->irq = platform_get_irq(pdev, 0); | ||
750 | res = devm_request_irq(&pdev->dev, | ||
751 | pdata->irq, | ||
752 | mv64x60_mc_isr, | ||
753 | IRQF_DISABLED, | ||
754 | "[EDAC] MC err", | ||
755 | mci); | ||
756 | if (res < 0) { | ||
757 | printk(KERN_ERR "%s: Unable to request irq %d for " | ||
758 | "MV64x60 DRAM ERR\n", __func__, pdata->irq); | ||
759 | res = -ENODEV; | ||
760 | goto err2; | ||
761 | } | ||
762 | |||
763 | printk(KERN_INFO EDAC_MOD_STR " acquired irq %d for MC Err\n", | ||
764 | pdata->irq); | ||
765 | } | ||
766 | |||
767 | /* get this far and it's successful */ | ||
768 | debugf3("%s(): success\n", __func__); | ||
769 | |||
770 | return 0; | ||
771 | |||
772 | err2: | ||
773 | edac_mc_del_mc(&pdev->dev); | ||
774 | err: | ||
775 | devres_release_group(&pdev->dev, mv64x60_mc_err_probe); | ||
776 | edac_mc_free(mci); | ||
777 | return res; | ||
778 | } | ||
779 | |||
780 | static int mv64x60_mc_err_remove(struct platform_device *pdev) | ||
781 | { | ||
782 | struct mem_ctl_info *mci = platform_get_drvdata(pdev); | ||
783 | |||
784 | debugf0("%s()\n", __func__); | ||
785 | |||
786 | edac_mc_del_mc(&pdev->dev); | ||
787 | edac_mc_free(mci); | ||
788 | return 0; | ||
789 | } | ||
790 | |||
791 | static struct platform_driver mv64x60_mc_err_driver = { | ||
792 | .probe = mv64x60_mc_err_probe, | ||
793 | .remove = mv64x60_mc_err_remove, | ||
794 | .driver = { | ||
795 | .name = "mv64x60_mc_err", | ||
796 | } | ||
797 | }; | ||
798 | |||
799 | static int __init mv64x60_edac_init(void) | ||
800 | { | ||
801 | int ret = 0; | ||
802 | |||
803 | printk(KERN_INFO "Marvell MV64x60 EDAC driver " MV64x60_REVISION "\n"); | ||
804 | printk(KERN_INFO "\t(C) 2006-2007 MontaVista Software\n"); | ||
805 | /* make sure error reporting method is sane */ | ||
806 | switch (edac_op_state) { | ||
807 | case EDAC_OPSTATE_POLL: | ||
808 | case EDAC_OPSTATE_INT: | ||
809 | break; | ||
810 | default: | ||
811 | edac_op_state = EDAC_OPSTATE_INT; | ||
812 | break; | ||
813 | } | ||
814 | |||
815 | ret = platform_driver_register(&mv64x60_mc_err_driver); | ||
816 | if (ret) | ||
817 | printk(KERN_WARNING EDAC_MOD_STR "MC err failed to register\n"); | ||
818 | |||
819 | ret = platform_driver_register(&mv64x60_cpu_err_driver); | ||
820 | if (ret) | ||
821 | printk(KERN_WARNING EDAC_MOD_STR | ||
822 | "CPU err failed to register\n"); | ||
823 | |||
824 | ret = platform_driver_register(&mv64x60_sram_err_driver); | ||
825 | if (ret) | ||
826 | printk(KERN_WARNING EDAC_MOD_STR | ||
827 | "SRAM err failed to register\n"); | ||
828 | |||
829 | #ifdef CONFIG_PCI | ||
830 | ret = platform_driver_register(&mv64x60_pci_err_driver); | ||
831 | if (ret) | ||
832 | printk(KERN_WARNING EDAC_MOD_STR | ||
833 | "PCI err failed to register\n"); | ||
834 | #endif | ||
835 | |||
836 | return ret; | ||
837 | } | ||
838 | module_init(mv64x60_edac_init); | ||
839 | |||
840 | static void __exit mv64x60_edac_exit(void) | ||
841 | { | ||
842 | #ifdef CONFIG_PCI | ||
843 | platform_driver_unregister(&mv64x60_pci_err_driver); | ||
844 | #endif | ||
845 | platform_driver_unregister(&mv64x60_sram_err_driver); | ||
846 | platform_driver_unregister(&mv64x60_cpu_err_driver); | ||
847 | platform_driver_unregister(&mv64x60_mc_err_driver); | ||
848 | } | ||
849 | module_exit(mv64x60_edac_exit); | ||
850 | |||
851 | MODULE_LICENSE("GPL"); | ||
852 | MODULE_AUTHOR("Montavista Software, Inc."); | ||
853 | module_param(edac_op_state, int, 0444); | ||
854 | MODULE_PARM_DESC(edac_op_state, | ||
855 | "EDAC Error Reporting state: 0=Poll, 2=Interrupt"); | ||
diff --git a/drivers/edac/mv64x60_edac.h b/drivers/edac/mv64x60_edac.h new file mode 100644 index 000000000000..e042e2daa8f4 --- /dev/null +++ b/drivers/edac/mv64x60_edac.h | |||
@@ -0,0 +1,114 @@ | |||
1 | /* | ||
2 | * EDAC defs for Marvell MV64x60 bridge chip | ||
3 | * | ||
4 | * Author: Dave Jiang <djiang@mvista.com> | ||
5 | * | ||
6 | * 2007 (c) MontaVista Software, Inc. This file is licensed under | ||
7 | * the terms of the GNU General Public License version 2. This program | ||
8 | * is licensed "as is" without any warranty of any kind, whether express | ||
9 | * or implied. | ||
10 | * | ||
11 | */ | ||
12 | #ifndef _MV64X60_EDAC_H_ | ||
13 | #define _MV64X60_EDAC_H_ | ||
14 | |||
15 | #define MV64x60_REVISION " Ver: 2.0.0 " __DATE__ | ||
16 | #define EDAC_MOD_STR "MV64x60_edac" | ||
17 | |||
18 | #define mv64x60_printk(level, fmt, arg...) \ | ||
19 | edac_printk(level, "MV64x60", fmt, ##arg) | ||
20 | |||
21 | #define mv64x60_mc_printk(mci, level, fmt, arg...) \ | ||
22 | edac_mc_chipset_printk(mci, level, "MV64x60", fmt, ##arg) | ||
23 | |||
24 | /* CPU Error Report Registers */ | ||
25 | #define MV64x60_CPU_ERR_ADDR_LO 0x00 /* 0x0070 */ | ||
26 | #define MV64x60_CPU_ERR_ADDR_HI 0x08 /* 0x0078 */ | ||
27 | #define MV64x60_CPU_ERR_DATA_LO 0x00 /* 0x0128 */ | ||
28 | #define MV64x60_CPU_ERR_DATA_HI 0x08 /* 0x0130 */ | ||
29 | #define MV64x60_CPU_ERR_PARITY 0x10 /* 0x0138 */ | ||
30 | #define MV64x60_CPU_ERR_CAUSE 0x18 /* 0x0140 */ | ||
31 | #define MV64x60_CPU_ERR_MASK 0x20 /* 0x0148 */ | ||
32 | |||
33 | #define MV64x60_CPU_CAUSE_MASK 0x07ffffff | ||
34 | |||
35 | /* SRAM Error Report Registers */ | ||
36 | #define MV64X60_SRAM_ERR_CAUSE 0x08 /* 0x0388 */ | ||
37 | #define MV64X60_SRAM_ERR_ADDR_LO 0x10 /* 0x0390 */ | ||
38 | #define MV64X60_SRAM_ERR_ADDR_HI 0x78 /* 0x03f8 */ | ||
39 | #define MV64X60_SRAM_ERR_DATA_LO 0x18 /* 0x0398 */ | ||
40 | #define MV64X60_SRAM_ERR_DATA_HI 0x20 /* 0x03a0 */ | ||
41 | #define MV64X60_SRAM_ERR_PARITY 0x28 /* 0x03a8 */ | ||
42 | |||
43 | /* SDRAM Controller Registers */ | ||
44 | #define MV64X60_SDRAM_CONFIG 0x00 /* 0x1400 */ | ||
45 | #define MV64X60_SDRAM_ERR_DATA_HI 0x40 /* 0x1440 */ | ||
46 | #define MV64X60_SDRAM_ERR_DATA_LO 0x44 /* 0x1444 */ | ||
47 | #define MV64X60_SDRAM_ERR_ECC_RCVD 0x48 /* 0x1448 */ | ||
48 | #define MV64X60_SDRAM_ERR_ECC_CALC 0x4c /* 0x144c */ | ||
49 | #define MV64X60_SDRAM_ERR_ADDR 0x50 /* 0x1450 */ | ||
50 | #define MV64X60_SDRAM_ERR_ECC_CNTL 0x54 /* 0x1454 */ | ||
51 | #define MV64X60_SDRAM_ERR_ECC_ERR_CNT 0x58 /* 0x1458 */ | ||
52 | |||
53 | #define MV64X60_SDRAM_REGISTERED 0x20000 | ||
54 | #define MV64X60_SDRAM_ECC 0x40000 | ||
55 | |||
56 | #ifdef CONFIG_PCI | ||
57 | /* | ||
58 | * Bit 0 of MV64x60_PCIx_ERR_MASK does not exist on the 64360 and because of | ||
59 | * errata FEr-#11 and FEr-##16 for the 64460, it should be 0 on that chip as | ||
60 | * well. IOW, don't set bit 0. | ||
61 | */ | ||
62 | #define MV64X60_PCIx_ERR_MASK_VAL 0x00a50c24 | ||
63 | |||
64 | /* Register offsets from PCIx error address low register */ | ||
65 | #define MV64X60_PCI_ERROR_ADDR_LO 0x00 | ||
66 | #define MV64X60_PCI_ERROR_ADDR_HI 0x04 | ||
67 | #define MV64X60_PCI_ERROR_ATTR 0x08 | ||
68 | #define MV64X60_PCI_ERROR_CMD 0x10 | ||
69 | #define MV64X60_PCI_ERROR_CAUSE 0x18 | ||
70 | #define MV64X60_PCI_ERROR_MASK 0x1c | ||
71 | |||
72 | #define MV64X60_PCI_ERR_SWrPerr 0x0002 | ||
73 | #define MV64X60_PCI_ERR_SRdPerr 0x0004 | ||
74 | #define MV64X60_PCI_ERR_MWrPerr 0x0020 | ||
75 | #define MV64X60_PCI_ERR_MRdPerr 0x0040 | ||
76 | |||
77 | #define MV64X60_PCI_PE_MASK (MV64X60_PCI_ERR_SWrPerr | \ | ||
78 | MV64X60_PCI_ERR_SRdPerr | \ | ||
79 | MV64X60_PCI_ERR_MWrPerr | \ | ||
80 | MV64X60_PCI_ERR_MRdPerr) | ||
81 | |||
82 | struct mv64x60_pci_pdata { | ||
83 | int pci_hose; | ||
84 | void __iomem *pci_vbase; | ||
85 | char *name; | ||
86 | int irq; | ||
87 | int edac_idx; | ||
88 | }; | ||
89 | |||
90 | #endif /* CONFIG_PCI */ | ||
91 | |||
92 | struct mv64x60_mc_pdata { | ||
93 | void __iomem *mc_vbase; | ||
94 | int total_mem; | ||
95 | char *name; | ||
96 | int irq; | ||
97 | int edac_idx; | ||
98 | }; | ||
99 | |||
100 | struct mv64x60_cpu_pdata { | ||
101 | void __iomem *cpu_vbase[2]; | ||
102 | char *name; | ||
103 | int irq; | ||
104 | int edac_idx; | ||
105 | }; | ||
106 | |||
107 | struct mv64x60_sram_pdata { | ||
108 | void __iomem *sram_vbase; | ||
109 | char *name; | ||
110 | int irq; | ||
111 | int edac_idx; | ||
112 | }; | ||
113 | |||
114 | #endif | ||
diff --git a/drivers/firmware/dcdbas.c b/drivers/firmware/dcdbas.c index 18cdcb3ae1ca..1636806ec55e 100644 --- a/drivers/firmware/dcdbas.c +++ b/drivers/firmware/dcdbas.c | |||
@@ -658,4 +658,5 @@ MODULE_DESCRIPTION(DRIVER_DESCRIPTION " (version " DRIVER_VERSION ")"); | |||
658 | MODULE_VERSION(DRIVER_VERSION); | 658 | MODULE_VERSION(DRIVER_VERSION); |
659 | MODULE_AUTHOR("Dell Inc."); | 659 | MODULE_AUTHOR("Dell Inc."); |
660 | MODULE_LICENSE("GPL"); | 660 | MODULE_LICENSE("GPL"); |
661 | 661 | /* Any System or BIOS claiming to be by Dell */ | |
662 | MODULE_ALIAS("dmi:*:[bs]vnD[Ee][Ll][Ll]*:*"); | ||
diff --git a/drivers/firmware/dmi-id.c b/drivers/firmware/dmi-id.c index 313c99cbdc62..e880d6c8d896 100644 --- a/drivers/firmware/dmi-id.c +++ b/drivers/firmware/dmi-id.c | |||
@@ -11,7 +11,6 @@ | |||
11 | #include <linux/init.h> | 11 | #include <linux/init.h> |
12 | #include <linux/dmi.h> | 12 | #include <linux/dmi.h> |
13 | #include <linux/device.h> | 13 | #include <linux/device.h> |
14 | #include <linux/autoconf.h> | ||
15 | 14 | ||
16 | struct dmi_device_attribute{ | 15 | struct dmi_device_attribute{ |
17 | struct device_attribute dev_attr; | 16 | struct device_attribute dev_attr; |
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 74fac0f5c348..bbd28342e771 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig | |||
@@ -27,15 +27,16 @@ config DEBUG_GPIO | |||
27 | 27 | ||
28 | comment "I2C GPIO expanders:" | 28 | comment "I2C GPIO expanders:" |
29 | 29 | ||
30 | config GPIO_PCA9539 | 30 | config GPIO_PCA953X |
31 | tristate "PCA9539 16-bit I/O port" | 31 | tristate "PCA953x I/O ports" |
32 | depends on I2C | 32 | depends on I2C |
33 | help | 33 | help |
34 | Say yes here to support the PCA9539 16-bit I/O port. These | 34 | Say yes here to support the PCA9534 (8-bit), PCA9535 (16-bit), |
35 | parts are made by NXP and TI. | 35 | PCA9536 (4-bit), PCA9537 (4-bit), PCA9538 (8-bit), and PCA9539 |
36 | (16-bit) I/O ports. These parts are made by NXP and TI. | ||
36 | 37 | ||
37 | This driver can also be built as a module. If so, the module | 38 | This driver can also be built as a module. If so, the module |
38 | will be called pca9539. | 39 | will be called pca953x. |
39 | 40 | ||
40 | config GPIO_PCF857X | 41 | config GPIO_PCF857X |
41 | tristate "PCF857x, PCA857x, and PCA967x I2C GPIO expanders" | 42 | tristate "PCF857x, PCA857x, and PCA967x I2C GPIO expanders" |
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 470ecd6aa778..fdde9923cf33 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile | |||
@@ -5,5 +5,5 @@ ccflags-$(CONFIG_DEBUG_GPIO) += -DDEBUG | |||
5 | obj-$(CONFIG_HAVE_GPIO_LIB) += gpiolib.o | 5 | obj-$(CONFIG_HAVE_GPIO_LIB) += gpiolib.o |
6 | 6 | ||
7 | obj-$(CONFIG_GPIO_MCP23S08) += mcp23s08.o | 7 | obj-$(CONFIG_GPIO_MCP23S08) += mcp23s08.o |
8 | obj-$(CONFIG_GPIO_PCA9539) += pca9539.o | 8 | obj-$(CONFIG_GPIO_PCA953X) += pca953x.o |
9 | obj-$(CONFIG_GPIO_PCF857X) += pcf857x.o | 9 | obj-$(CONFIG_GPIO_PCF857X) += pcf857x.o |
diff --git a/drivers/gpio/pca9539.c b/drivers/gpio/pca9539.c deleted file mode 100644 index 3e85c92a7d59..000000000000 --- a/drivers/gpio/pca9539.c +++ /dev/null | |||
@@ -1,271 +0,0 @@ | |||
1 | /* | ||
2 | * pca9539.c - 16-bit I/O port with interrupt and reset | ||
3 | * | ||
4 | * Copyright (C) 2005 Ben Gardner <bgardner@wabtec.com> | ||
5 | * Copyright (C) 2007 Marvell International Ltd. | ||
6 | * | ||
7 | * Derived from drivers/i2c/chips/pca9539.c | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; version 2 of the License. | ||
12 | */ | ||
13 | |||
14 | #include <linux/module.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/i2c.h> | ||
17 | #include <linux/i2c/pca9539.h> | ||
18 | |||
19 | #include <asm/gpio.h> | ||
20 | |||
21 | |||
22 | #define NR_PCA9539_GPIOS 16 | ||
23 | |||
24 | #define PCA9539_INPUT 0 | ||
25 | #define PCA9539_OUTPUT 2 | ||
26 | #define PCA9539_INVERT 4 | ||
27 | #define PCA9539_DIRECTION 6 | ||
28 | |||
29 | struct pca9539_chip { | ||
30 | unsigned gpio_start; | ||
31 | uint16_t reg_output; | ||
32 | uint16_t reg_direction; | ||
33 | |||
34 | struct i2c_client *client; | ||
35 | struct gpio_chip gpio_chip; | ||
36 | }; | ||
37 | |||
38 | /* NOTE: we can't currently rely on fault codes to come from SMBus | ||
39 | * calls, so we map all errors to EIO here and return zero otherwise. | ||
40 | */ | ||
41 | static int pca9539_write_reg(struct pca9539_chip *chip, int reg, uint16_t val) | ||
42 | { | ||
43 | if (i2c_smbus_write_word_data(chip->client, reg, val) < 0) | ||
44 | return -EIO; | ||
45 | else | ||
46 | return 0; | ||
47 | } | ||
48 | |||
49 | static int pca9539_read_reg(struct pca9539_chip *chip, int reg, uint16_t *val) | ||
50 | { | ||
51 | int ret; | ||
52 | |||
53 | ret = i2c_smbus_read_word_data(chip->client, reg); | ||
54 | if (ret < 0) { | ||
55 | dev_err(&chip->client->dev, "failed reading register\n"); | ||
56 | return -EIO; | ||
57 | } | ||
58 | |||
59 | *val = (uint16_t)ret; | ||
60 | return 0; | ||
61 | } | ||
62 | |||
63 | static int pca9539_gpio_direction_input(struct gpio_chip *gc, unsigned off) | ||
64 | { | ||
65 | struct pca9539_chip *chip; | ||
66 | uint16_t reg_val; | ||
67 | int ret; | ||
68 | |||
69 | chip = container_of(gc, struct pca9539_chip, gpio_chip); | ||
70 | |||
71 | reg_val = chip->reg_direction | (1u << off); | ||
72 | ret = pca9539_write_reg(chip, PCA9539_DIRECTION, reg_val); | ||
73 | if (ret) | ||
74 | return ret; | ||
75 | |||
76 | chip->reg_direction = reg_val; | ||
77 | return 0; | ||
78 | } | ||
79 | |||
80 | static int pca9539_gpio_direction_output(struct gpio_chip *gc, | ||
81 | unsigned off, int val) | ||
82 | { | ||
83 | struct pca9539_chip *chip; | ||
84 | uint16_t reg_val; | ||
85 | int ret; | ||
86 | |||
87 | chip = container_of(gc, struct pca9539_chip, gpio_chip); | ||
88 | |||
89 | /* set output level */ | ||
90 | if (val) | ||
91 | reg_val = chip->reg_output | (1u << off); | ||
92 | else | ||
93 | reg_val = chip->reg_output & ~(1u << off); | ||
94 | |||
95 | ret = pca9539_write_reg(chip, PCA9539_OUTPUT, reg_val); | ||
96 | if (ret) | ||
97 | return ret; | ||
98 | |||
99 | chip->reg_output = reg_val; | ||
100 | |||
101 | /* then direction */ | ||
102 | reg_val = chip->reg_direction & ~(1u << off); | ||
103 | ret = pca9539_write_reg(chip, PCA9539_DIRECTION, reg_val); | ||
104 | if (ret) | ||
105 | return ret; | ||
106 | |||
107 | chip->reg_direction = reg_val; | ||
108 | return 0; | ||
109 | } | ||
110 | |||
111 | static int pca9539_gpio_get_value(struct gpio_chip *gc, unsigned off) | ||
112 | { | ||
113 | struct pca9539_chip *chip; | ||
114 | uint16_t reg_val; | ||
115 | int ret; | ||
116 | |||
117 | chip = container_of(gc, struct pca9539_chip, gpio_chip); | ||
118 | |||
119 | ret = pca9539_read_reg(chip, PCA9539_INPUT, ®_val); | ||
120 | if (ret < 0) { | ||
121 | /* NOTE: diagnostic already emitted; that's all we should | ||
122 | * do unless gpio_*_value_cansleep() calls become different | ||
123 | * from their nonsleeping siblings (and report faults). | ||
124 | */ | ||
125 | return 0; | ||
126 | } | ||
127 | |||
128 | return (reg_val & (1u << off)) ? 1 : 0; | ||
129 | } | ||
130 | |||
131 | static void pca9539_gpio_set_value(struct gpio_chip *gc, unsigned off, int val) | ||
132 | { | ||
133 | struct pca9539_chip *chip; | ||
134 | uint16_t reg_val; | ||
135 | int ret; | ||
136 | |||
137 | chip = container_of(gc, struct pca9539_chip, gpio_chip); | ||
138 | |||
139 | if (val) | ||
140 | reg_val = chip->reg_output | (1u << off); | ||
141 | else | ||
142 | reg_val = chip->reg_output & ~(1u << off); | ||
143 | |||
144 | ret = pca9539_write_reg(chip, PCA9539_OUTPUT, reg_val); | ||
145 | if (ret) | ||
146 | return; | ||
147 | |||
148 | chip->reg_output = reg_val; | ||
149 | } | ||
150 | |||
151 | static int pca9539_init_gpio(struct pca9539_chip *chip) | ||
152 | { | ||
153 | struct gpio_chip *gc; | ||
154 | |||
155 | gc = &chip->gpio_chip; | ||
156 | |||
157 | gc->direction_input = pca9539_gpio_direction_input; | ||
158 | gc->direction_output = pca9539_gpio_direction_output; | ||
159 | gc->get = pca9539_gpio_get_value; | ||
160 | gc->set = pca9539_gpio_set_value; | ||
161 | |||
162 | gc->base = chip->gpio_start; | ||
163 | gc->ngpio = NR_PCA9539_GPIOS; | ||
164 | gc->label = "pca9539"; | ||
165 | |||
166 | return gpiochip_add(gc); | ||
167 | } | ||
168 | |||
169 | static int __devinit pca9539_probe(struct i2c_client *client) | ||
170 | { | ||
171 | struct pca9539_platform_data *pdata; | ||
172 | struct pca9539_chip *chip; | ||
173 | int ret; | ||
174 | |||
175 | pdata = client->dev.platform_data; | ||
176 | if (pdata == NULL) | ||
177 | return -ENODEV; | ||
178 | |||
179 | chip = kzalloc(sizeof(struct pca9539_chip), GFP_KERNEL); | ||
180 | if (chip == NULL) | ||
181 | return -ENOMEM; | ||
182 | |||
183 | chip->client = client; | ||
184 | |||
185 | chip->gpio_start = pdata->gpio_base; | ||
186 | |||
187 | /* initialize cached registers from their original values. | ||
188 | * we can't share this chip with another i2c master. | ||
189 | */ | ||
190 | ret = pca9539_read_reg(chip, PCA9539_OUTPUT, &chip->reg_output); | ||
191 | if (ret) | ||
192 | goto out_failed; | ||
193 | |||
194 | ret = pca9539_read_reg(chip, PCA9539_DIRECTION, &chip->reg_direction); | ||
195 | if (ret) | ||
196 | goto out_failed; | ||
197 | |||
198 | /* set platform specific polarity inversion */ | ||
199 | ret = pca9539_write_reg(chip, PCA9539_INVERT, pdata->invert); | ||
200 | if (ret) | ||
201 | goto out_failed; | ||
202 | |||
203 | ret = pca9539_init_gpio(chip); | ||
204 | if (ret) | ||
205 | goto out_failed; | ||
206 | |||
207 | if (pdata->setup) { | ||
208 | ret = pdata->setup(client, chip->gpio_chip.base, | ||
209 | chip->gpio_chip.ngpio, pdata->context); | ||
210 | if (ret < 0) | ||
211 | dev_warn(&client->dev, "setup failed, %d\n", ret); | ||
212 | } | ||
213 | |||
214 | i2c_set_clientdata(client, chip); | ||
215 | return 0; | ||
216 | |||
217 | out_failed: | ||
218 | kfree(chip); | ||
219 | return ret; | ||
220 | } | ||
221 | |||
222 | static int pca9539_remove(struct i2c_client *client) | ||
223 | { | ||
224 | struct pca9539_platform_data *pdata = client->dev.platform_data; | ||
225 | struct pca9539_chip *chip = i2c_get_clientdata(client); | ||
226 | int ret = 0; | ||
227 | |||
228 | if (pdata->teardown) { | ||
229 | ret = pdata->teardown(client, chip->gpio_chip.base, | ||
230 | chip->gpio_chip.ngpio, pdata->context); | ||
231 | if (ret < 0) { | ||
232 | dev_err(&client->dev, "%s failed, %d\n", | ||
233 | "teardown", ret); | ||
234 | return ret; | ||
235 | } | ||
236 | } | ||
237 | |||
238 | ret = gpiochip_remove(&chip->gpio_chip); | ||
239 | if (ret) { | ||
240 | dev_err(&client->dev, "%s failed, %d\n", | ||
241 | "gpiochip_remove()", ret); | ||
242 | return ret; | ||
243 | } | ||
244 | |||
245 | kfree(chip); | ||
246 | return 0; | ||
247 | } | ||
248 | |||
249 | static struct i2c_driver pca9539_driver = { | ||
250 | .driver = { | ||
251 | .name = "pca9539", | ||
252 | }, | ||
253 | .probe = pca9539_probe, | ||
254 | .remove = pca9539_remove, | ||
255 | }; | ||
256 | |||
257 | static int __init pca9539_init(void) | ||
258 | { | ||
259 | return i2c_add_driver(&pca9539_driver); | ||
260 | } | ||
261 | module_init(pca9539_init); | ||
262 | |||
263 | static void __exit pca9539_exit(void) | ||
264 | { | ||
265 | i2c_del_driver(&pca9539_driver); | ||
266 | } | ||
267 | module_exit(pca9539_exit); | ||
268 | |||
269 | MODULE_AUTHOR("eric miao <eric.miao@marvell.com>"); | ||
270 | MODULE_DESCRIPTION("GPIO expander driver for PCA9539"); | ||
271 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/gpio/pca953x.c b/drivers/gpio/pca953x.c new file mode 100644 index 000000000000..92583cd4bffd --- /dev/null +++ b/drivers/gpio/pca953x.c | |||
@@ -0,0 +1,308 @@ | |||
1 | /* | ||
2 | * pca953x.c - 4/8/16 bit I/O ports | ||
3 | * | ||
4 | * Copyright (C) 2005 Ben Gardner <bgardner@wabtec.com> | ||
5 | * Copyright (C) 2007 Marvell International Ltd. | ||
6 | * | ||
7 | * Derived from drivers/i2c/chips/pca9539.c | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; version 2 of the License. | ||
12 | */ | ||
13 | |||
14 | #include <linux/module.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/i2c.h> | ||
17 | #include <linux/i2c/pca953x.h> | ||
18 | |||
19 | #include <asm/gpio.h> | ||
20 | |||
21 | #define PCA953X_INPUT 0 | ||
22 | #define PCA953X_OUTPUT 1 | ||
23 | #define PCA953X_INVERT 2 | ||
24 | #define PCA953X_DIRECTION 3 | ||
25 | |||
26 | /* This is temporary - in 2.6.26 i2c_driver_data should replace it. */ | ||
27 | struct pca953x_desc { | ||
28 | char name[I2C_NAME_SIZE]; | ||
29 | unsigned long driver_data; | ||
30 | }; | ||
31 | |||
32 | static const struct pca953x_desc pca953x_descs[] = { | ||
33 | { "pca9534", 8, }, | ||
34 | { "pca9535", 16, }, | ||
35 | { "pca9536", 4, }, | ||
36 | { "pca9537", 4, }, | ||
37 | { "pca9538", 8, }, | ||
38 | { "pca9539", 16, }, | ||
39 | /* REVISIT several pca955x parts should work here too */ | ||
40 | }; | ||
41 | |||
42 | struct pca953x_chip { | ||
43 | unsigned gpio_start; | ||
44 | uint16_t reg_output; | ||
45 | uint16_t reg_direction; | ||
46 | |||
47 | struct i2c_client *client; | ||
48 | struct gpio_chip gpio_chip; | ||
49 | }; | ||
50 | |||
51 | /* NOTE: we can't currently rely on fault codes to come from SMBus | ||
52 | * calls, so we map all errors to EIO here and return zero otherwise. | ||
53 | */ | ||
54 | static int pca953x_write_reg(struct pca953x_chip *chip, int reg, uint16_t val) | ||
55 | { | ||
56 | int ret; | ||
57 | |||
58 | if (chip->gpio_chip.ngpio <= 8) | ||
59 | ret = i2c_smbus_write_byte_data(chip->client, reg, val); | ||
60 | else | ||
61 | ret = i2c_smbus_write_word_data(chip->client, reg << 1, val); | ||
62 | |||
63 | if (ret < 0) { | ||
64 | dev_err(&chip->client->dev, "failed writing register\n"); | ||
65 | return -EIO; | ||
66 | } | ||
67 | |||
68 | return 0; | ||
69 | } | ||
70 | |||
71 | static int pca953x_read_reg(struct pca953x_chip *chip, int reg, uint16_t *val) | ||
72 | { | ||
73 | int ret; | ||
74 | |||
75 | if (chip->gpio_chip.ngpio <= 8) | ||
76 | ret = i2c_smbus_read_byte_data(chip->client, reg); | ||
77 | else | ||
78 | ret = i2c_smbus_read_word_data(chip->client, reg << 1); | ||
79 | |||
80 | if (ret < 0) { | ||
81 | dev_err(&chip->client->dev, "failed reading register\n"); | ||
82 | return -EIO; | ||
83 | } | ||
84 | |||
85 | *val = (uint16_t)ret; | ||
86 | return 0; | ||
87 | } | ||
88 | |||
89 | static int pca953x_gpio_direction_input(struct gpio_chip *gc, unsigned off) | ||
90 | { | ||
91 | struct pca953x_chip *chip; | ||
92 | uint16_t reg_val; | ||
93 | int ret; | ||
94 | |||
95 | chip = container_of(gc, struct pca953x_chip, gpio_chip); | ||
96 | |||
97 | reg_val = chip->reg_direction | (1u << off); | ||
98 | ret = pca953x_write_reg(chip, PCA953X_DIRECTION, reg_val); | ||
99 | if (ret) | ||
100 | return ret; | ||
101 | |||
102 | chip->reg_direction = reg_val; | ||
103 | return 0; | ||
104 | } | ||
105 | |||
106 | static int pca953x_gpio_direction_output(struct gpio_chip *gc, | ||
107 | unsigned off, int val) | ||
108 | { | ||
109 | struct pca953x_chip *chip; | ||
110 | uint16_t reg_val; | ||
111 | int ret; | ||
112 | |||
113 | chip = container_of(gc, struct pca953x_chip, gpio_chip); | ||
114 | |||
115 | /* set output level */ | ||
116 | if (val) | ||
117 | reg_val = chip->reg_output | (1u << off); | ||
118 | else | ||
119 | reg_val = chip->reg_output & ~(1u << off); | ||
120 | |||
121 | ret = pca953x_write_reg(chip, PCA953X_OUTPUT, reg_val); | ||
122 | if (ret) | ||
123 | return ret; | ||
124 | |||
125 | chip->reg_output = reg_val; | ||
126 | |||
127 | /* then direction */ | ||
128 | reg_val = chip->reg_direction & ~(1u << off); | ||
129 | ret = pca953x_write_reg(chip, PCA953X_DIRECTION, reg_val); | ||
130 | if (ret) | ||
131 | return ret; | ||
132 | |||
133 | chip->reg_direction = reg_val; | ||
134 | return 0; | ||
135 | } | ||
136 | |||
137 | static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off) | ||
138 | { | ||
139 | struct pca953x_chip *chip; | ||
140 | uint16_t reg_val; | ||
141 | int ret; | ||
142 | |||
143 | chip = container_of(gc, struct pca953x_chip, gpio_chip); | ||
144 | |||
145 | ret = pca953x_read_reg(chip, PCA953X_INPUT, ®_val); | ||
146 | if (ret < 0) { | ||
147 | /* NOTE: diagnostic already emitted; that's all we should | ||
148 | * do unless gpio_*_value_cansleep() calls become different | ||
149 | * from their nonsleeping siblings (and report faults). | ||
150 | */ | ||
151 | return 0; | ||
152 | } | ||
153 | |||
154 | return (reg_val & (1u << off)) ? 1 : 0; | ||
155 | } | ||
156 | |||
157 | static void pca953x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val) | ||
158 | { | ||
159 | struct pca953x_chip *chip; | ||
160 | uint16_t reg_val; | ||
161 | int ret; | ||
162 | |||
163 | chip = container_of(gc, struct pca953x_chip, gpio_chip); | ||
164 | |||
165 | if (val) | ||
166 | reg_val = chip->reg_output | (1u << off); | ||
167 | else | ||
168 | reg_val = chip->reg_output & ~(1u << off); | ||
169 | |||
170 | ret = pca953x_write_reg(chip, PCA953X_OUTPUT, reg_val); | ||
171 | if (ret) | ||
172 | return; | ||
173 | |||
174 | chip->reg_output = reg_val; | ||
175 | } | ||
176 | |||
177 | static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios) | ||
178 | { | ||
179 | struct gpio_chip *gc; | ||
180 | |||
181 | gc = &chip->gpio_chip; | ||
182 | |||
183 | gc->direction_input = pca953x_gpio_direction_input; | ||
184 | gc->direction_output = pca953x_gpio_direction_output; | ||
185 | gc->get = pca953x_gpio_get_value; | ||
186 | gc->set = pca953x_gpio_set_value; | ||
187 | |||
188 | gc->base = chip->gpio_start; | ||
189 | gc->ngpio = gpios; | ||
190 | gc->label = chip->client->name; | ||
191 | } | ||
192 | |||
193 | static int __devinit pca953x_probe(struct i2c_client *client) | ||
194 | { | ||
195 | struct pca953x_platform_data *pdata; | ||
196 | struct pca953x_chip *chip; | ||
197 | int ret, i; | ||
198 | const struct pca953x_desc *id = NULL; | ||
199 | |||
200 | pdata = client->dev.platform_data; | ||
201 | if (pdata == NULL) | ||
202 | return -ENODEV; | ||
203 | |||
204 | /* this loop vanishes when we get i2c_device_id */ | ||
205 | for (i = 0; i < ARRAY_SIZE(pca953x_descs); i++) | ||
206 | if (!strcmp(pca953x_descs[i].name, client->name)) { | ||
207 | id = pca953x_descs + i; | ||
208 | break; | ||
209 | } | ||
210 | if (!id) | ||
211 | return -ENODEV; | ||
212 | |||
213 | chip = kzalloc(sizeof(struct pca953x_chip), GFP_KERNEL); | ||
214 | if (chip == NULL) | ||
215 | return -ENOMEM; | ||
216 | |||
217 | chip->client = client; | ||
218 | |||
219 | chip->gpio_start = pdata->gpio_base; | ||
220 | |||
221 | /* initialize cached registers from their original values. | ||
222 | * we can't share this chip with another i2c master. | ||
223 | */ | ||
224 | pca953x_setup_gpio(chip, id->driver_data); | ||
225 | |||
226 | ret = pca953x_read_reg(chip, PCA953X_OUTPUT, &chip->reg_output); | ||
227 | if (ret) | ||
228 | goto out_failed; | ||
229 | |||
230 | ret = pca953x_read_reg(chip, PCA953X_DIRECTION, &chip->reg_direction); | ||
231 | if (ret) | ||
232 | goto out_failed; | ||
233 | |||
234 | /* set platform specific polarity inversion */ | ||
235 | ret = pca953x_write_reg(chip, PCA953X_INVERT, pdata->invert); | ||
236 | if (ret) | ||
237 | goto out_failed; | ||
238 | |||
239 | |||
240 | ret = gpiochip_add(&chip->gpio_chip); | ||
241 | if (ret) | ||
242 | goto out_failed; | ||
243 | |||
244 | if (pdata->setup) { | ||
245 | ret = pdata->setup(client, chip->gpio_chip.base, | ||
246 | chip->gpio_chip.ngpio, pdata->context); | ||
247 | if (ret < 0) | ||
248 | dev_warn(&client->dev, "setup failed, %d\n", ret); | ||
249 | } | ||
250 | |||
251 | i2c_set_clientdata(client, chip); | ||
252 | return 0; | ||
253 | |||
254 | out_failed: | ||
255 | kfree(chip); | ||
256 | return ret; | ||
257 | } | ||
258 | |||
259 | static int pca953x_remove(struct i2c_client *client) | ||
260 | { | ||
261 | struct pca953x_platform_data *pdata = client->dev.platform_data; | ||
262 | struct pca953x_chip *chip = i2c_get_clientdata(client); | ||
263 | int ret = 0; | ||
264 | |||
265 | if (pdata->teardown) { | ||
266 | ret = pdata->teardown(client, chip->gpio_chip.base, | ||
267 | chip->gpio_chip.ngpio, pdata->context); | ||
268 | if (ret < 0) { | ||
269 | dev_err(&client->dev, "%s failed, %d\n", | ||
270 | "teardown", ret); | ||
271 | return ret; | ||
272 | } | ||
273 | } | ||
274 | |||
275 | ret = gpiochip_remove(&chip->gpio_chip); | ||
276 | if (ret) { | ||
277 | dev_err(&client->dev, "%s failed, %d\n", | ||
278 | "gpiochip_remove()", ret); | ||
279 | return ret; | ||
280 | } | ||
281 | |||
282 | kfree(chip); | ||
283 | return 0; | ||
284 | } | ||
285 | |||
286 | static struct i2c_driver pca953x_driver = { | ||
287 | .driver = { | ||
288 | .name = "pca953x", | ||
289 | }, | ||
290 | .probe = pca953x_probe, | ||
291 | .remove = pca953x_remove, | ||
292 | }; | ||
293 | |||
294 | static int __init pca953x_init(void) | ||
295 | { | ||
296 | return i2c_add_driver(&pca953x_driver); | ||
297 | } | ||
298 | module_init(pca953x_init); | ||
299 | |||
300 | static void __exit pca953x_exit(void) | ||
301 | { | ||
302 | i2c_del_driver(&pca953x_driver); | ||
303 | } | ||
304 | module_exit(pca953x_exit); | ||
305 | |||
306 | MODULE_AUTHOR("eric miao <eric.miao@marvell.com>"); | ||
307 | MODULE_DESCRIPTION("GPIO expander driver for PCA953x"); | ||
308 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index fd0ef8268950..6daea896c5db 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c | |||
@@ -1049,7 +1049,7 @@ static int init_irq (ide_hwif_t *hwif) | |||
1049 | */ | 1049 | */ |
1050 | if (!match || match->irq != hwif->irq) { | 1050 | if (!match || match->irq != hwif->irq) { |
1051 | int sa = 0; | 1051 | int sa = 0; |
1052 | #if defined(__mc68000__) || defined(CONFIG_APUS) | 1052 | #if defined(__mc68000__) |
1053 | sa = IRQF_SHARED; | 1053 | sa = IRQF_SHARED; |
1054 | #endif /* __mc68000__ || CONFIG_APUS */ | 1054 | #endif /* __mc68000__ || CONFIG_APUS */ |
1055 | 1055 | ||
@@ -1072,7 +1072,7 @@ static int init_irq (ide_hwif_t *hwif) | |||
1072 | hwif->rqsize = 65536; | 1072 | hwif->rqsize = 65536; |
1073 | } | 1073 | } |
1074 | 1074 | ||
1075 | #if !defined(__mc68000__) && !defined(CONFIG_APUS) | 1075 | #if !defined(__mc68000__) |
1076 | printk("%s at 0x%03lx-0x%03lx,0x%03lx on irq %d", hwif->name, | 1076 | printk("%s at 0x%03lx-0x%03lx,0x%03lx on irq %d", hwif->name, |
1077 | hwif->io_ports[IDE_DATA_OFFSET], | 1077 | hwif->io_ports[IDE_DATA_OFFSET], |
1078 | hwif->io_ports[IDE_DATA_OFFSET]+7, | 1078 | hwif->io_ports[IDE_DATA_OFFSET]+7, |
@@ -1080,7 +1080,7 @@ static int init_irq (ide_hwif_t *hwif) | |||
1080 | #else | 1080 | #else |
1081 | printk("%s at 0x%08lx on irq %d", hwif->name, | 1081 | printk("%s at 0x%08lx on irq %d", hwif->name, |
1082 | hwif->io_ports[IDE_DATA_OFFSET], hwif->irq); | 1082 | hwif->io_ports[IDE_DATA_OFFSET], hwif->irq); |
1083 | #endif /* __mc68000__ && CONFIG_APUS */ | 1083 | #endif /* __mc68000__ */ |
1084 | if (match) | 1084 | if (match) |
1085 | printk(" (%sed with %s)", | 1085 | printk(" (%sed with %s)", |
1086 | hwif->sharing_irq ? "shar" : "serializ", match->name); | 1086 | hwif->sharing_irq ? "shar" : "serializ", match->name); |
diff --git a/drivers/ide/legacy/ide_platform.c b/drivers/ide/legacy/ide_platform.c index 26c82ce602de..688fcae17488 100644 --- a/drivers/ide/legacy/ide_platform.c +++ b/drivers/ide/legacy/ide_platform.c | |||
@@ -17,7 +17,7 @@ | |||
17 | #include <linux/ide.h> | 17 | #include <linux/ide.h> |
18 | #include <linux/ioport.h> | 18 | #include <linux/ioport.h> |
19 | #include <linux/module.h> | 19 | #include <linux/module.h> |
20 | #include <linux/pata_platform.h> | 20 | #include <linux/ata_platform.h> |
21 | #include <linux/platform_device.h> | 21 | #include <linux/platform_device.h> |
22 | #include <linux/io.h> | 22 | #include <linux/io.h> |
23 | 23 | ||
diff --git a/drivers/input/touchscreen/h3600_ts_input.c b/drivers/input/touchscreen/h3600_ts_input.c index 2ae6c6016a86..28ae15ed12c5 100644 --- a/drivers/input/touchscreen/h3600_ts_input.c +++ b/drivers/input/touchscreen/h3600_ts_input.c | |||
@@ -109,7 +109,7 @@ struct h3600_dev { | |||
109 | static irqreturn_t action_button_handler(int irq, void *dev_id) | 109 | static irqreturn_t action_button_handler(int irq, void *dev_id) |
110 | { | 110 | { |
111 | int down = (GPLR & GPIO_BITSY_ACTION_BUTTON) ? 0 : 1; | 111 | int down = (GPLR & GPIO_BITSY_ACTION_BUTTON) ? 0 : 1; |
112 | struct input_dev *dev = (struct input_dev *) dev_id; | 112 | struct input_dev *dev = dev_id; |
113 | 113 | ||
114 | input_report_key(dev, KEY_ENTER, down); | 114 | input_report_key(dev, KEY_ENTER, down); |
115 | input_sync(dev); | 115 | input_sync(dev); |
@@ -120,7 +120,7 @@ static irqreturn_t action_button_handler(int irq, void *dev_id) | |||
120 | static irqreturn_t npower_button_handler(int irq, void *dev_id) | 120 | static irqreturn_t npower_button_handler(int irq, void *dev_id) |
121 | { | 121 | { |
122 | int down = (GPLR & GPIO_BITSY_NPOWER_BUTTON) ? 0 : 1; | 122 | int down = (GPLR & GPIO_BITSY_NPOWER_BUTTON) ? 0 : 1; |
123 | struct input_dev *dev = (struct input_dev *) dev_id; | 123 | struct input_dev *dev = dev_id; |
124 | 124 | ||
125 | /* | 125 | /* |
126 | * This interrupt is only called when we release the key. So we have | 126 | * This interrupt is only called when we release the key. So we have |
diff --git a/drivers/isdn/act2000/module.c b/drivers/isdn/act2000/module.c index ee2b0b9f8f46..8325022e2bed 100644 --- a/drivers/isdn/act2000/module.c +++ b/drivers/isdn/act2000/module.c | |||
@@ -310,7 +310,7 @@ act2000_command(act2000_card * card, isdn_ctrl * c) | |||
310 | } | 310 | } |
311 | break; | 311 | break; |
312 | case ISDN_CMD_DIAL: | 312 | case ISDN_CMD_DIAL: |
313 | if (!card->flags & ACT2000_FLAGS_RUNNING) | 313 | if (!(card->flags & ACT2000_FLAGS_RUNNING)) |
314 | return -ENODEV; | 314 | return -ENODEV; |
315 | if (!(chan = find_channel(card, c->arg & 0x0f))) | 315 | if (!(chan = find_channel(card, c->arg & 0x0f))) |
316 | break; | 316 | break; |
@@ -339,7 +339,7 @@ act2000_command(act2000_card * card, isdn_ctrl * c) | |||
339 | } | 339 | } |
340 | return ret; | 340 | return ret; |
341 | case ISDN_CMD_ACCEPTD: | 341 | case ISDN_CMD_ACCEPTD: |
342 | if (!card->flags & ACT2000_FLAGS_RUNNING) | 342 | if (!(card->flags & ACT2000_FLAGS_RUNNING)) |
343 | return -ENODEV; | 343 | return -ENODEV; |
344 | if (!(chan = find_channel(card, c->arg & 0x0f))) | 344 | if (!(chan = find_channel(card, c->arg & 0x0f))) |
345 | break; | 345 | break; |
@@ -347,11 +347,11 @@ act2000_command(act2000_card * card, isdn_ctrl * c) | |||
347 | actcapi_select_b2_protocol_req(card, chan); | 347 | actcapi_select_b2_protocol_req(card, chan); |
348 | return 0; | 348 | return 0; |
349 | case ISDN_CMD_ACCEPTB: | 349 | case ISDN_CMD_ACCEPTB: |
350 | if (!card->flags & ACT2000_FLAGS_RUNNING) | 350 | if (!(card->flags & ACT2000_FLAGS_RUNNING)) |
351 | return -ENODEV; | 351 | return -ENODEV; |
352 | return 0; | 352 | return 0; |
353 | case ISDN_CMD_HANGUP: | 353 | case ISDN_CMD_HANGUP: |
354 | if (!card->flags & ACT2000_FLAGS_RUNNING) | 354 | if (!(card->flags & ACT2000_FLAGS_RUNNING)) |
355 | return -ENODEV; | 355 | return -ENODEV; |
356 | if (!(chan = find_channel(card, c->arg & 0x0f))) | 356 | if (!(chan = find_channel(card, c->arg & 0x0f))) |
357 | break; | 357 | break; |
@@ -366,7 +366,7 @@ act2000_command(act2000_card * card, isdn_ctrl * c) | |||
366 | } | 366 | } |
367 | return 0; | 367 | return 0; |
368 | case ISDN_CMD_SETEAZ: | 368 | case ISDN_CMD_SETEAZ: |
369 | if (!card->flags & ACT2000_FLAGS_RUNNING) | 369 | if (!(card->flags & ACT2000_FLAGS_RUNNING)) |
370 | return -ENODEV; | 370 | return -ENODEV; |
371 | if (!(chan = find_channel(card, c->arg & 0x0f))) | 371 | if (!(chan = find_channel(card, c->arg & 0x0f))) |
372 | break; | 372 | break; |
@@ -386,7 +386,7 @@ act2000_command(act2000_card * card, isdn_ctrl * c) | |||
386 | actcapi_listen_req(card); | 386 | actcapi_listen_req(card); |
387 | return 0; | 387 | return 0; |
388 | case ISDN_CMD_CLREAZ: | 388 | case ISDN_CMD_CLREAZ: |
389 | if (!card->flags & ACT2000_FLAGS_RUNNING) | 389 | if (!(card->flags & ACT2000_FLAGS_RUNNING)) |
390 | return -ENODEV; | 390 | return -ENODEV; |
391 | if (!(chan = find_channel(card, c->arg & 0x0f))) | 391 | if (!(chan = find_channel(card, c->arg & 0x0f))) |
392 | break; | 392 | break; |
@@ -394,14 +394,14 @@ act2000_command(act2000_card * card, isdn_ctrl * c) | |||
394 | actcapi_listen_req(card); | 394 | actcapi_listen_req(card); |
395 | return 0; | 395 | return 0; |
396 | case ISDN_CMD_SETL2: | 396 | case ISDN_CMD_SETL2: |
397 | if (!card->flags & ACT2000_FLAGS_RUNNING) | 397 | if (!(card->flags & ACT2000_FLAGS_RUNNING)) |
398 | return -ENODEV; | 398 | return -ENODEV; |
399 | if (!(chan = find_channel(card, c->arg & 0x0f))) | 399 | if (!(chan = find_channel(card, c->arg & 0x0f))) |
400 | break; | 400 | break; |
401 | chan->l2prot = (c->arg >> 8); | 401 | chan->l2prot = (c->arg >> 8); |
402 | return 0; | 402 | return 0; |
403 | case ISDN_CMD_SETL3: | 403 | case ISDN_CMD_SETL3: |
404 | if (!card->flags & ACT2000_FLAGS_RUNNING) | 404 | if (!(card->flags & ACT2000_FLAGS_RUNNING)) |
405 | return -ENODEV; | 405 | return -ENODEV; |
406 | if ((c->arg >> 8) != ISDN_PROTO_L3_TRANS) { | 406 | if ((c->arg >> 8) != ISDN_PROTO_L3_TRANS) { |
407 | printk(KERN_WARNING "L3 protocol unknown\n"); | 407 | printk(KERN_WARNING "L3 protocol unknown\n"); |
@@ -524,7 +524,7 @@ if_writecmd(const u_char __user *buf, int len, int id, int channel) | |||
524 | act2000_card *card = act2000_findcard(id); | 524 | act2000_card *card = act2000_findcard(id); |
525 | 525 | ||
526 | if (card) { | 526 | if (card) { |
527 | if (!card->flags & ACT2000_FLAGS_RUNNING) | 527 | if (!(card->flags & ACT2000_FLAGS_RUNNING)) |
528 | return -ENODEV; | 528 | return -ENODEV; |
529 | return (len); | 529 | return (len); |
530 | } | 530 | } |
@@ -539,7 +539,7 @@ if_readstatus(u_char __user * buf, int len, int id, int channel) | |||
539 | act2000_card *card = act2000_findcard(id); | 539 | act2000_card *card = act2000_findcard(id); |
540 | 540 | ||
541 | if (card) { | 541 | if (card) { |
542 | if (!card->flags & ACT2000_FLAGS_RUNNING) | 542 | if (!(card->flags & ACT2000_FLAGS_RUNNING)) |
543 | return -ENODEV; | 543 | return -ENODEV; |
544 | return (act2000_readstatus(buf, len, card)); | 544 | return (act2000_readstatus(buf, len, card)); |
545 | } | 545 | } |
@@ -554,7 +554,7 @@ if_sendbuf(int id, int channel, int ack, struct sk_buff *skb) | |||
554 | act2000_card *card = act2000_findcard(id); | 554 | act2000_card *card = act2000_findcard(id); |
555 | 555 | ||
556 | if (card) { | 556 | if (card) { |
557 | if (!card->flags & ACT2000_FLAGS_RUNNING) | 557 | if (!(card->flags & ACT2000_FLAGS_RUNNING)) |
558 | return -ENODEV; | 558 | return -ENODEV; |
559 | return (act2000_sendbuf(card, channel, ack, skb)); | 559 | return (act2000_sendbuf(card, channel, ack, skb)); |
560 | } | 560 | } |
diff --git a/drivers/isdn/gigaset/asyncdata.c b/drivers/isdn/gigaset/asyncdata.c index 00a3be5b862b..091deb9d1c47 100644 --- a/drivers/isdn/gigaset/asyncdata.c +++ b/drivers/isdn/gigaset/asyncdata.c | |||
@@ -350,8 +350,8 @@ void gigaset_m10x_input(struct inbuf_t *inbuf) | |||
350 | unsigned char *src, c; | 350 | unsigned char *src, c; |
351 | int procbytes; | 351 | int procbytes; |
352 | 352 | ||
353 | head = atomic_read(&inbuf->head); | 353 | head = inbuf->head; |
354 | tail = atomic_read(&inbuf->tail); | 354 | tail = inbuf->tail; |
355 | gig_dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail); | 355 | gig_dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail); |
356 | 356 | ||
357 | if (head != tail) { | 357 | if (head != tail) { |
@@ -361,7 +361,7 @@ void gigaset_m10x_input(struct inbuf_t *inbuf) | |||
361 | gig_dbg(DEBUG_INTR, "processing %u bytes", numbytes); | 361 | gig_dbg(DEBUG_INTR, "processing %u bytes", numbytes); |
362 | 362 | ||
363 | while (numbytes) { | 363 | while (numbytes) { |
364 | if (atomic_read(&cs->mstate) == MS_LOCKED) { | 364 | if (cs->mstate == MS_LOCKED) { |
365 | procbytes = lock_loop(src, numbytes, inbuf); | 365 | procbytes = lock_loop(src, numbytes, inbuf); |
366 | src += procbytes; | 366 | src += procbytes; |
367 | numbytes -= procbytes; | 367 | numbytes -= procbytes; |
@@ -436,7 +436,7 @@ nextbyte: | |||
436 | } | 436 | } |
437 | 437 | ||
438 | gig_dbg(DEBUG_INTR, "setting head to %u", head); | 438 | gig_dbg(DEBUG_INTR, "setting head to %u", head); |
439 | atomic_set(&inbuf->head, head); | 439 | inbuf->head = head; |
440 | } | 440 | } |
441 | } | 441 | } |
442 | EXPORT_SYMBOL_GPL(gigaset_m10x_input); | 442 | EXPORT_SYMBOL_GPL(gigaset_m10x_input); |
diff --git a/drivers/isdn/gigaset/bas-gigaset.c b/drivers/isdn/gigaset/bas-gigaset.c index af7648274b38..5255b5e20e13 100644 --- a/drivers/isdn/gigaset/bas-gigaset.c +++ b/drivers/isdn/gigaset/bas-gigaset.c | |||
@@ -73,6 +73,14 @@ static int gigaset_probe(struct usb_interface *interface, | |||
73 | /* Function will be called if the device is unplugged */ | 73 | /* Function will be called if the device is unplugged */ |
74 | static void gigaset_disconnect(struct usb_interface *interface); | 74 | static void gigaset_disconnect(struct usb_interface *interface); |
75 | 75 | ||
76 | /* functions called before/after suspend */ | ||
77 | static int gigaset_suspend(struct usb_interface *intf, pm_message_t message); | ||
78 | static int gigaset_resume(struct usb_interface *intf); | ||
79 | |||
80 | /* functions called before/after device reset */ | ||
81 | static int gigaset_pre_reset(struct usb_interface *intf); | ||
82 | static int gigaset_post_reset(struct usb_interface *intf); | ||
83 | |||
76 | static int atread_submit(struct cardstate *, int); | 84 | static int atread_submit(struct cardstate *, int); |
77 | static void stopurbs(struct bas_bc_state *); | 85 | static void stopurbs(struct bas_bc_state *); |
78 | static int req_submit(struct bc_state *, int, int, int); | 86 | static int req_submit(struct bc_state *, int, int, int); |
@@ -105,8 +113,9 @@ struct bas_cardstate { | |||
105 | unsigned char int_in_buf[3]; | 113 | unsigned char int_in_buf[3]; |
106 | 114 | ||
107 | spinlock_t lock; /* locks all following */ | 115 | spinlock_t lock; /* locks all following */ |
108 | atomic_t basstate; /* bitmap (BS_*) */ | 116 | int basstate; /* bitmap (BS_*) */ |
109 | int pending; /* uncompleted base request */ | 117 | int pending; /* uncompleted base request */ |
118 | wait_queue_head_t waitqueue; | ||
110 | int rcvbuf_size; /* size of AT receive buffer */ | 119 | int rcvbuf_size; /* size of AT receive buffer */ |
111 | /* 0: no receive in progress */ | 120 | /* 0: no receive in progress */ |
112 | int retry_cmd_in; /* receive req retry count */ | 121 | int retry_cmd_in; /* receive req retry count */ |
@@ -121,10 +130,10 @@ struct bas_cardstate { | |||
121 | #define BS_ATTIMER 0x020 /* waiting for HD_READY_SEND_ATDATA */ | 130 | #define BS_ATTIMER 0x020 /* waiting for HD_READY_SEND_ATDATA */ |
122 | #define BS_ATRDPEND 0x040 /* urb_cmd_in in use */ | 131 | #define BS_ATRDPEND 0x040 /* urb_cmd_in in use */ |
123 | #define BS_ATWRPEND 0x080 /* urb_cmd_out in use */ | 132 | #define BS_ATWRPEND 0x080 /* urb_cmd_out in use */ |
133 | #define BS_SUSPEND 0x100 /* USB port suspended */ | ||
124 | 134 | ||
125 | 135 | ||
126 | static struct gigaset_driver *driver = NULL; | 136 | static struct gigaset_driver *driver = NULL; |
127 | static struct cardstate *cardstate = NULL; | ||
128 | 137 | ||
129 | /* usb specific object needed to register this driver with the usb subsystem */ | 138 | /* usb specific object needed to register this driver with the usb subsystem */ |
130 | static struct usb_driver gigaset_usb_driver = { | 139 | static struct usb_driver gigaset_usb_driver = { |
@@ -132,6 +141,11 @@ static struct usb_driver gigaset_usb_driver = { | |||
132 | .probe = gigaset_probe, | 141 | .probe = gigaset_probe, |
133 | .disconnect = gigaset_disconnect, | 142 | .disconnect = gigaset_disconnect, |
134 | .id_table = gigaset_table, | 143 | .id_table = gigaset_table, |
144 | .suspend = gigaset_suspend, | ||
145 | .resume = gigaset_resume, | ||
146 | .reset_resume = gigaset_post_reset, | ||
147 | .pre_reset = gigaset_pre_reset, | ||
148 | .post_reset = gigaset_post_reset, | ||
135 | }; | 149 | }; |
136 | 150 | ||
137 | /* get message text for usb_submit_urb return code | 151 | /* get message text for usb_submit_urb return code |
@@ -248,12 +262,12 @@ static inline void dump_urb(enum debuglevel level, const char *tag, | |||
248 | if (urb) { | 262 | if (urb) { |
249 | gig_dbg(level, | 263 | gig_dbg(level, |
250 | " dev=0x%08lx, pipe=%s:EP%d/DV%d:%s, " | 264 | " dev=0x%08lx, pipe=%s:EP%d/DV%d:%s, " |
251 | "status=%d, hcpriv=0x%08lx, transfer_flags=0x%x,", | 265 | "hcpriv=0x%08lx, transfer_flags=0x%x,", |
252 | (unsigned long) urb->dev, | 266 | (unsigned long) urb->dev, |
253 | usb_pipetype_str(urb->pipe), | 267 | usb_pipetype_str(urb->pipe), |
254 | usb_pipeendpoint(urb->pipe), usb_pipedevice(urb->pipe), | 268 | usb_pipeendpoint(urb->pipe), usb_pipedevice(urb->pipe), |
255 | usb_pipein(urb->pipe) ? "in" : "out", | 269 | usb_pipein(urb->pipe) ? "in" : "out", |
256 | urb->status, (unsigned long) urb->hcpriv, | 270 | (unsigned long) urb->hcpriv, |
257 | urb->transfer_flags); | 271 | urb->transfer_flags); |
258 | gig_dbg(level, | 272 | gig_dbg(level, |
259 | " transfer_buffer=0x%08lx[%d], actual_length=%d, " | 273 | " transfer_buffer=0x%08lx[%d], actual_length=%d, " |
@@ -355,27 +369,27 @@ static void check_pending(struct bas_cardstate *ucs) | |||
355 | case 0: | 369 | case 0: |
356 | break; | 370 | break; |
357 | case HD_OPEN_ATCHANNEL: | 371 | case HD_OPEN_ATCHANNEL: |
358 | if (atomic_read(&ucs->basstate) & BS_ATOPEN) | 372 | if (ucs->basstate & BS_ATOPEN) |
359 | ucs->pending = 0; | 373 | ucs->pending = 0; |
360 | break; | 374 | break; |
361 | case HD_OPEN_B1CHANNEL: | 375 | case HD_OPEN_B1CHANNEL: |
362 | if (atomic_read(&ucs->basstate) & BS_B1OPEN) | 376 | if (ucs->basstate & BS_B1OPEN) |
363 | ucs->pending = 0; | 377 | ucs->pending = 0; |
364 | break; | 378 | break; |
365 | case HD_OPEN_B2CHANNEL: | 379 | case HD_OPEN_B2CHANNEL: |
366 | if (atomic_read(&ucs->basstate) & BS_B2OPEN) | 380 | if (ucs->basstate & BS_B2OPEN) |
367 | ucs->pending = 0; | 381 | ucs->pending = 0; |
368 | break; | 382 | break; |
369 | case HD_CLOSE_ATCHANNEL: | 383 | case HD_CLOSE_ATCHANNEL: |
370 | if (!(atomic_read(&ucs->basstate) & BS_ATOPEN)) | 384 | if (!(ucs->basstate & BS_ATOPEN)) |
371 | ucs->pending = 0; | 385 | ucs->pending = 0; |
372 | break; | 386 | break; |
373 | case HD_CLOSE_B1CHANNEL: | 387 | case HD_CLOSE_B1CHANNEL: |
374 | if (!(atomic_read(&ucs->basstate) & BS_B1OPEN)) | 388 | if (!(ucs->basstate & BS_B1OPEN)) |
375 | ucs->pending = 0; | 389 | ucs->pending = 0; |
376 | break; | 390 | break; |
377 | case HD_CLOSE_B2CHANNEL: | 391 | case HD_CLOSE_B2CHANNEL: |
378 | if (!(atomic_read(&ucs->basstate) & BS_B2OPEN)) | 392 | if (!(ucs->basstate & BS_B2OPEN)) |
379 | ucs->pending = 0; | 393 | ucs->pending = 0; |
380 | break; | 394 | break; |
381 | case HD_DEVICE_INIT_ACK: /* no reply expected */ | 395 | case HD_DEVICE_INIT_ACK: /* no reply expected */ |
@@ -441,8 +455,8 @@ inline static int update_basstate(struct bas_cardstate *ucs, | |||
441 | int state; | 455 | int state; |
442 | 456 | ||
443 | spin_lock_irqsave(&ucs->lock, flags); | 457 | spin_lock_irqsave(&ucs->lock, flags); |
444 | state = atomic_read(&ucs->basstate); | 458 | state = ucs->basstate; |
445 | atomic_set(&ucs->basstate, (state & ~clear) | set); | 459 | ucs->basstate = (state & ~clear) | set; |
446 | spin_unlock_irqrestore(&ucs->lock, flags); | 460 | spin_unlock_irqrestore(&ucs->lock, flags); |
447 | return state; | 461 | return state; |
448 | } | 462 | } |
@@ -459,11 +473,13 @@ static void read_ctrl_callback(struct urb *urb) | |||
459 | struct inbuf_t *inbuf = urb->context; | 473 | struct inbuf_t *inbuf = urb->context; |
460 | struct cardstate *cs = inbuf->cs; | 474 | struct cardstate *cs = inbuf->cs; |
461 | struct bas_cardstate *ucs = cs->hw.bas; | 475 | struct bas_cardstate *ucs = cs->hw.bas; |
476 | int status = urb->status; | ||
462 | int have_data = 0; | 477 | int have_data = 0; |
463 | unsigned numbytes; | 478 | unsigned numbytes; |
464 | int rc; | 479 | int rc; |
465 | 480 | ||
466 | update_basstate(ucs, 0, BS_ATRDPEND); | 481 | update_basstate(ucs, 0, BS_ATRDPEND); |
482 | wake_up(&ucs->waitqueue); | ||
467 | 483 | ||
468 | if (!ucs->rcvbuf_size) { | 484 | if (!ucs->rcvbuf_size) { |
469 | dev_warn(cs->dev, "%s: no receive in progress\n", __func__); | 485 | dev_warn(cs->dev, "%s: no receive in progress\n", __func__); |
@@ -472,7 +488,7 @@ static void read_ctrl_callback(struct urb *urb) | |||
472 | 488 | ||
473 | del_timer(&ucs->timer_cmd_in); | 489 | del_timer(&ucs->timer_cmd_in); |
474 | 490 | ||
475 | switch (urb->status) { | 491 | switch (status) { |
476 | case 0: /* normal completion */ | 492 | case 0: /* normal completion */ |
477 | numbytes = urb->actual_length; | 493 | numbytes = urb->actual_length; |
478 | if (unlikely(numbytes != ucs->rcvbuf_size)) { | 494 | if (unlikely(numbytes != ucs->rcvbuf_size)) { |
@@ -506,12 +522,12 @@ static void read_ctrl_callback(struct urb *urb) | |||
506 | case -ESHUTDOWN: /* device shut down */ | 522 | case -ESHUTDOWN: /* device shut down */ |
507 | /* no action necessary */ | 523 | /* no action necessary */ |
508 | gig_dbg(DEBUG_USBREQ, "%s: %s", | 524 | gig_dbg(DEBUG_USBREQ, "%s: %s", |
509 | __func__, get_usb_statmsg(urb->status)); | 525 | __func__, get_usb_statmsg(status)); |
510 | break; | 526 | break; |
511 | 527 | ||
512 | default: /* severe trouble */ | 528 | default: /* severe trouble */ |
513 | dev_warn(cs->dev, "control read: %s\n", | 529 | dev_warn(cs->dev, "control read: %s\n", |
514 | get_usb_statmsg(urb->status)); | 530 | get_usb_statmsg(status)); |
515 | if (ucs->retry_cmd_in++ < BAS_RETRY) { | 531 | if (ucs->retry_cmd_in++ < BAS_RETRY) { |
516 | dev_notice(cs->dev, "control read: retry %d\n", | 532 | dev_notice(cs->dev, "control read: retry %d\n", |
517 | ucs->retry_cmd_in); | 533 | ucs->retry_cmd_in); |
@@ -550,17 +566,28 @@ static void read_ctrl_callback(struct urb *urb) | |||
550 | static int atread_submit(struct cardstate *cs, int timeout) | 566 | static int atread_submit(struct cardstate *cs, int timeout) |
551 | { | 567 | { |
552 | struct bas_cardstate *ucs = cs->hw.bas; | 568 | struct bas_cardstate *ucs = cs->hw.bas; |
569 | int basstate; | ||
553 | int ret; | 570 | int ret; |
554 | 571 | ||
555 | gig_dbg(DEBUG_USBREQ, "-------> HD_READ_ATMESSAGE (%d)", | 572 | gig_dbg(DEBUG_USBREQ, "-------> HD_READ_ATMESSAGE (%d)", |
556 | ucs->rcvbuf_size); | 573 | ucs->rcvbuf_size); |
557 | 574 | ||
558 | if (update_basstate(ucs, BS_ATRDPEND, 0) & BS_ATRDPEND) { | 575 | basstate = update_basstate(ucs, BS_ATRDPEND, 0); |
576 | if (basstate & BS_ATRDPEND) { | ||
559 | dev_err(cs->dev, | 577 | dev_err(cs->dev, |
560 | "could not submit HD_READ_ATMESSAGE: URB busy\n"); | 578 | "could not submit HD_READ_ATMESSAGE: URB busy\n"); |
561 | return -EBUSY; | 579 | return -EBUSY; |
562 | } | 580 | } |
563 | 581 | ||
582 | if (basstate & BS_SUSPEND) { | ||
583 | dev_notice(cs->dev, | ||
584 | "HD_READ_ATMESSAGE not submitted, " | ||
585 | "suspend in progress\n"); | ||
586 | update_basstate(ucs, 0, BS_ATRDPEND); | ||
587 | /* treat like disconnect */ | ||
588 | return -ENODEV; | ||
589 | } | ||
590 | |||
564 | ucs->dr_cmd_in.bRequestType = IN_VENDOR_REQ; | 591 | ucs->dr_cmd_in.bRequestType = IN_VENDOR_REQ; |
565 | ucs->dr_cmd_in.bRequest = HD_READ_ATMESSAGE; | 592 | ucs->dr_cmd_in.bRequest = HD_READ_ATMESSAGE; |
566 | ucs->dr_cmd_in.wValue = 0; | 593 | ucs->dr_cmd_in.wValue = 0; |
@@ -601,12 +628,13 @@ static void read_int_callback(struct urb *urb) | |||
601 | struct cardstate *cs = urb->context; | 628 | struct cardstate *cs = urb->context; |
602 | struct bas_cardstate *ucs = cs->hw.bas; | 629 | struct bas_cardstate *ucs = cs->hw.bas; |
603 | struct bc_state *bcs; | 630 | struct bc_state *bcs; |
631 | int status = urb->status; | ||
604 | unsigned long flags; | 632 | unsigned long flags; |
605 | int rc; | 633 | int rc; |
606 | unsigned l; | 634 | unsigned l; |
607 | int channel; | 635 | int channel; |
608 | 636 | ||
609 | switch (urb->status) { | 637 | switch (status) { |
610 | case 0: /* success */ | 638 | case 0: /* success */ |
611 | break; | 639 | break; |
612 | case -ENOENT: /* cancelled */ | 640 | case -ENOENT: /* cancelled */ |
@@ -614,7 +642,7 @@ static void read_int_callback(struct urb *urb) | |||
614 | case -EINPROGRESS: /* pending */ | 642 | case -EINPROGRESS: /* pending */ |
615 | /* ignore silently */ | 643 | /* ignore silently */ |
616 | gig_dbg(DEBUG_USBREQ, "%s: %s", | 644 | gig_dbg(DEBUG_USBREQ, "%s: %s", |
617 | __func__, get_usb_statmsg(urb->status)); | 645 | __func__, get_usb_statmsg(status)); |
618 | return; | 646 | return; |
619 | case -ENODEV: /* device removed */ | 647 | case -ENODEV: /* device removed */ |
620 | case -ESHUTDOWN: /* device shut down */ | 648 | case -ESHUTDOWN: /* device shut down */ |
@@ -623,7 +651,7 @@ static void read_int_callback(struct urb *urb) | |||
623 | return; | 651 | return; |
624 | default: /* severe trouble */ | 652 | default: /* severe trouble */ |
625 | dev_warn(cs->dev, "interrupt read: %s\n", | 653 | dev_warn(cs->dev, "interrupt read: %s\n", |
626 | get_usb_statmsg(urb->status)); | 654 | get_usb_statmsg(status)); |
627 | //FIXME corrective action? resubmission always ok? | 655 | //FIXME corrective action? resubmission always ok? |
628 | goto resubmit; | 656 | goto resubmit; |
629 | } | 657 | } |
@@ -745,6 +773,7 @@ static void read_int_callback(struct urb *urb) | |||
745 | } | 773 | } |
746 | 774 | ||
747 | check_pending(ucs); | 775 | check_pending(ucs); |
776 | wake_up(&ucs->waitqueue); | ||
748 | 777 | ||
749 | resubmit: | 778 | resubmit: |
750 | rc = usb_submit_urb(urb, GFP_ATOMIC); | 779 | rc = usb_submit_urb(urb, GFP_ATOMIC); |
@@ -766,17 +795,18 @@ static void read_iso_callback(struct urb *urb) | |||
766 | { | 795 | { |
767 | struct bc_state *bcs; | 796 | struct bc_state *bcs; |
768 | struct bas_bc_state *ubc; | 797 | struct bas_bc_state *ubc; |
798 | int status = urb->status; | ||
769 | unsigned long flags; | 799 | unsigned long flags; |
770 | int i, rc; | 800 | int i, rc; |
771 | 801 | ||
772 | /* status codes not worth bothering the tasklet with */ | 802 | /* status codes not worth bothering the tasklet with */ |
773 | if (unlikely(urb->status == -ENOENT || | 803 | if (unlikely(status == -ENOENT || |
774 | urb->status == -ECONNRESET || | 804 | status == -ECONNRESET || |
775 | urb->status == -EINPROGRESS || | 805 | status == -EINPROGRESS || |
776 | urb->status == -ENODEV || | 806 | status == -ENODEV || |
777 | urb->status == -ESHUTDOWN)) { | 807 | status == -ESHUTDOWN)) { |
778 | gig_dbg(DEBUG_ISO, "%s: %s", | 808 | gig_dbg(DEBUG_ISO, "%s: %s", |
779 | __func__, get_usb_statmsg(urb->status)); | 809 | __func__, get_usb_statmsg(status)); |
780 | return; | 810 | return; |
781 | } | 811 | } |
782 | 812 | ||
@@ -787,10 +817,11 @@ static void read_iso_callback(struct urb *urb) | |||
787 | if (likely(ubc->isoindone == NULL)) { | 817 | if (likely(ubc->isoindone == NULL)) { |
788 | /* pass URB to tasklet */ | 818 | /* pass URB to tasklet */ |
789 | ubc->isoindone = urb; | 819 | ubc->isoindone = urb; |
820 | ubc->isoinstatus = status; | ||
790 | tasklet_schedule(&ubc->rcvd_tasklet); | 821 | tasklet_schedule(&ubc->rcvd_tasklet); |
791 | } else { | 822 | } else { |
792 | /* tasklet still busy, drop data and resubmit URB */ | 823 | /* tasklet still busy, drop data and resubmit URB */ |
793 | ubc->loststatus = urb->status; | 824 | ubc->loststatus = status; |
794 | for (i = 0; i < BAS_NUMFRAMES; i++) { | 825 | for (i = 0; i < BAS_NUMFRAMES; i++) { |
795 | ubc->isoinlost += urb->iso_frame_desc[i].actual_length; | 826 | ubc->isoinlost += urb->iso_frame_desc[i].actual_length; |
796 | if (unlikely(urb->iso_frame_desc[i].status != 0 && | 827 | if (unlikely(urb->iso_frame_desc[i].status != 0 && |
@@ -800,7 +831,7 @@ static void read_iso_callback(struct urb *urb) | |||
800 | urb->iso_frame_desc[i].status = 0; | 831 | urb->iso_frame_desc[i].status = 0; |
801 | urb->iso_frame_desc[i].actual_length = 0; | 832 | urb->iso_frame_desc[i].actual_length = 0; |
802 | } | 833 | } |
803 | if (likely(atomic_read(&ubc->running))) { | 834 | if (likely(ubc->running)) { |
804 | /* urb->dev is clobbered by USB subsystem */ | 835 | /* urb->dev is clobbered by USB subsystem */ |
805 | urb->dev = bcs->cs->hw.bas->udev; | 836 | urb->dev = bcs->cs->hw.bas->udev; |
806 | urb->transfer_flags = URB_ISO_ASAP; | 837 | urb->transfer_flags = URB_ISO_ASAP; |
@@ -831,22 +862,24 @@ static void write_iso_callback(struct urb *urb) | |||
831 | { | 862 | { |
832 | struct isow_urbctx_t *ucx; | 863 | struct isow_urbctx_t *ucx; |
833 | struct bas_bc_state *ubc; | 864 | struct bas_bc_state *ubc; |
865 | int status = urb->status; | ||
834 | unsigned long flags; | 866 | unsigned long flags; |
835 | 867 | ||
836 | /* status codes not worth bothering the tasklet with */ | 868 | /* status codes not worth bothering the tasklet with */ |
837 | if (unlikely(urb->status == -ENOENT || | 869 | if (unlikely(status == -ENOENT || |
838 | urb->status == -ECONNRESET || | 870 | status == -ECONNRESET || |
839 | urb->status == -EINPROGRESS || | 871 | status == -EINPROGRESS || |
840 | urb->status == -ENODEV || | 872 | status == -ENODEV || |
841 | urb->status == -ESHUTDOWN)) { | 873 | status == -ESHUTDOWN)) { |
842 | gig_dbg(DEBUG_ISO, "%s: %s", | 874 | gig_dbg(DEBUG_ISO, "%s: %s", |
843 | __func__, get_usb_statmsg(urb->status)); | 875 | __func__, get_usb_statmsg(status)); |
844 | return; | 876 | return; |
845 | } | 877 | } |
846 | 878 | ||
847 | /* pass URB context to tasklet */ | 879 | /* pass URB context to tasklet */ |
848 | ucx = urb->context; | 880 | ucx = urb->context; |
849 | ubc = ucx->bcs->hw.bas; | 881 | ubc = ucx->bcs->hw.bas; |
882 | ucx->status = status; | ||
850 | 883 | ||
851 | spin_lock_irqsave(&ubc->isooutlock, flags); | 884 | spin_lock_irqsave(&ubc->isooutlock, flags); |
852 | ubc->isooutovfl = ubc->isooutdone; | 885 | ubc->isooutovfl = ubc->isooutdone; |
@@ -875,7 +908,7 @@ static int starturbs(struct bc_state *bcs) | |||
875 | bcs->inputstate |= INS_flag_hunt; | 908 | bcs->inputstate |= INS_flag_hunt; |
876 | 909 | ||
877 | /* submit all isochronous input URBs */ | 910 | /* submit all isochronous input URBs */ |
878 | atomic_set(&ubc->running, 1); | 911 | ubc->running = 1; |
879 | for (k = 0; k < BAS_INURBS; k++) { | 912 | for (k = 0; k < BAS_INURBS; k++) { |
880 | urb = ubc->isoinurbs[k]; | 913 | urb = ubc->isoinurbs[k]; |
881 | if (!urb) { | 914 | if (!urb) { |
@@ -932,15 +965,15 @@ static int starturbs(struct bc_state *bcs) | |||
932 | ubc->isoouturbs[k].limit = -1; | 965 | ubc->isoouturbs[k].limit = -1; |
933 | } | 966 | } |
934 | 967 | ||
935 | /* submit two URBs, keep third one */ | 968 | /* keep one URB free, submit the others */ |
936 | for (k = 0; k < 2; ++k) { | 969 | for (k = 0; k < BAS_OUTURBS-1; ++k) { |
937 | dump_urb(DEBUG_ISO, "Initial isoc write", urb); | 970 | dump_urb(DEBUG_ISO, "Initial isoc write", urb); |
938 | rc = usb_submit_urb(ubc->isoouturbs[k].urb, GFP_ATOMIC); | 971 | rc = usb_submit_urb(ubc->isoouturbs[k].urb, GFP_ATOMIC); |
939 | if (rc != 0) | 972 | if (rc != 0) |
940 | goto error; | 973 | goto error; |
941 | } | 974 | } |
942 | dump_urb(DEBUG_ISO, "Initial isoc write (free)", urb); | 975 | dump_urb(DEBUG_ISO, "Initial isoc write (free)", urb); |
943 | ubc->isooutfree = &ubc->isoouturbs[2]; | 976 | ubc->isooutfree = &ubc->isoouturbs[BAS_OUTURBS-1]; |
944 | ubc->isooutdone = ubc->isooutovfl = NULL; | 977 | ubc->isooutdone = ubc->isooutovfl = NULL; |
945 | return 0; | 978 | return 0; |
946 | error: | 979 | error: |
@@ -958,7 +991,7 @@ static void stopurbs(struct bas_bc_state *ubc) | |||
958 | { | 991 | { |
959 | int k, rc; | 992 | int k, rc; |
960 | 993 | ||
961 | atomic_set(&ubc->running, 0); | 994 | ubc->running = 0; |
962 | 995 | ||
963 | for (k = 0; k < BAS_INURBS; ++k) { | 996 | for (k = 0; k < BAS_INURBS; ++k) { |
964 | rc = usb_unlink_urb(ubc->isoinurbs[k]); | 997 | rc = usb_unlink_urb(ubc->isoinurbs[k]); |
@@ -1034,7 +1067,7 @@ static int submit_iso_write_urb(struct isow_urbctx_t *ucx) | |||
1034 | } | 1067 | } |
1035 | break; | 1068 | break; |
1036 | } | 1069 | } |
1037 | ucx->limit = atomic_read(&ubc->isooutbuf->nextread); | 1070 | ucx->limit = ubc->isooutbuf->nextread; |
1038 | ifd->status = 0; | 1071 | ifd->status = 0; |
1039 | ifd->actual_length = 0; | 1072 | ifd->actual_length = 0; |
1040 | } | 1073 | } |
@@ -1070,6 +1103,7 @@ static void write_iso_tasklet(unsigned long data) | |||
1070 | struct cardstate *cs = bcs->cs; | 1103 | struct cardstate *cs = bcs->cs; |
1071 | struct isow_urbctx_t *done, *next, *ovfl; | 1104 | struct isow_urbctx_t *done, *next, *ovfl; |
1072 | struct urb *urb; | 1105 | struct urb *urb; |
1106 | int status; | ||
1073 | struct usb_iso_packet_descriptor *ifd; | 1107 | struct usb_iso_packet_descriptor *ifd; |
1074 | int offset; | 1108 | int offset; |
1075 | unsigned long flags; | 1109 | unsigned long flags; |
@@ -1080,7 +1114,7 @@ static void write_iso_tasklet(unsigned long data) | |||
1080 | 1114 | ||
1081 | /* loop while completed URBs arrive in time */ | 1115 | /* loop while completed URBs arrive in time */ |
1082 | for (;;) { | 1116 | for (;;) { |
1083 | if (unlikely(!(atomic_read(&ubc->running)))) { | 1117 | if (unlikely(!(ubc->running))) { |
1084 | gig_dbg(DEBUG_ISO, "%s: not running", __func__); | 1118 | gig_dbg(DEBUG_ISO, "%s: not running", __func__); |
1085 | return; | 1119 | return; |
1086 | } | 1120 | } |
@@ -1126,7 +1160,8 @@ static void write_iso_tasklet(unsigned long data) | |||
1126 | 1160 | ||
1127 | /* process completed URB */ | 1161 | /* process completed URB */ |
1128 | urb = done->urb; | 1162 | urb = done->urb; |
1129 | switch (urb->status) { | 1163 | status = done->status; |
1164 | switch (status) { | ||
1130 | case -EXDEV: /* partial completion */ | 1165 | case -EXDEV: /* partial completion */ |
1131 | gig_dbg(DEBUG_ISO, "%s: URB partially completed", | 1166 | gig_dbg(DEBUG_ISO, "%s: URB partially completed", |
1132 | __func__); | 1167 | __func__); |
@@ -1179,12 +1214,12 @@ static void write_iso_tasklet(unsigned long data) | |||
1179 | break; | 1214 | break; |
1180 | default: /* severe trouble */ | 1215 | default: /* severe trouble */ |
1181 | dev_warn(cs->dev, "isochronous write: %s\n", | 1216 | dev_warn(cs->dev, "isochronous write: %s\n", |
1182 | get_usb_statmsg(urb->status)); | 1217 | get_usb_statmsg(status)); |
1183 | } | 1218 | } |
1184 | 1219 | ||
1185 | /* mark the write buffer area covered by this URB as free */ | 1220 | /* mark the write buffer area covered by this URB as free */ |
1186 | if (done->limit >= 0) | 1221 | if (done->limit >= 0) |
1187 | atomic_set(&ubc->isooutbuf->read, done->limit); | 1222 | ubc->isooutbuf->read = done->limit; |
1188 | 1223 | ||
1189 | /* mark URB as free */ | 1224 | /* mark URB as free */ |
1190 | spin_lock_irqsave(&ubc->isooutlock, flags); | 1225 | spin_lock_irqsave(&ubc->isooutlock, flags); |
@@ -1233,6 +1268,7 @@ static void read_iso_tasklet(unsigned long data) | |||
1233 | struct bas_bc_state *ubc = bcs->hw.bas; | 1268 | struct bas_bc_state *ubc = bcs->hw.bas; |
1234 | struct cardstate *cs = bcs->cs; | 1269 | struct cardstate *cs = bcs->cs; |
1235 | struct urb *urb; | 1270 | struct urb *urb; |
1271 | int status; | ||
1236 | char *rcvbuf; | 1272 | char *rcvbuf; |
1237 | unsigned long flags; | 1273 | unsigned long flags; |
1238 | int totleft, numbytes, offset, frame, rc; | 1274 | int totleft, numbytes, offset, frame, rc; |
@@ -1245,6 +1281,7 @@ static void read_iso_tasklet(unsigned long data) | |||
1245 | spin_unlock_irqrestore(&ubc->isoinlock, flags); | 1281 | spin_unlock_irqrestore(&ubc->isoinlock, flags); |
1246 | return; | 1282 | return; |
1247 | } | 1283 | } |
1284 | status = ubc->isoinstatus; | ||
1248 | ubc->isoindone = NULL; | 1285 | ubc->isoindone = NULL; |
1249 | if (unlikely(ubc->loststatus != -EINPROGRESS)) { | 1286 | if (unlikely(ubc->loststatus != -EINPROGRESS)) { |
1250 | dev_warn(cs->dev, | 1287 | dev_warn(cs->dev, |
@@ -1256,15 +1293,15 @@ static void read_iso_tasklet(unsigned long data) | |||
1256 | } | 1293 | } |
1257 | spin_unlock_irqrestore(&ubc->isoinlock, flags); | 1294 | spin_unlock_irqrestore(&ubc->isoinlock, flags); |
1258 | 1295 | ||
1259 | if (unlikely(!(atomic_read(&ubc->running)))) { | 1296 | if (unlikely(!(ubc->running))) { |
1260 | gig_dbg(DEBUG_ISO, | 1297 | gig_dbg(DEBUG_ISO, |
1261 | "%s: channel not running, " | 1298 | "%s: channel not running, " |
1262 | "dropped URB with status: %s", | 1299 | "dropped URB with status: %s", |
1263 | __func__, get_usb_statmsg(urb->status)); | 1300 | __func__, get_usb_statmsg(status)); |
1264 | return; | 1301 | return; |
1265 | } | 1302 | } |
1266 | 1303 | ||
1267 | switch (urb->status) { | 1304 | switch (status) { |
1268 | case 0: /* normal completion */ | 1305 | case 0: /* normal completion */ |
1269 | break; | 1306 | break; |
1270 | case -EXDEV: /* inspect individual frames | 1307 | case -EXDEV: /* inspect individual frames |
@@ -1276,7 +1313,7 @@ static void read_iso_tasklet(unsigned long data) | |||
1276 | case -ECONNRESET: | 1313 | case -ECONNRESET: |
1277 | case -EINPROGRESS: | 1314 | case -EINPROGRESS: |
1278 | gig_dbg(DEBUG_ISO, "%s: %s", | 1315 | gig_dbg(DEBUG_ISO, "%s: %s", |
1279 | __func__, get_usb_statmsg(urb->status)); | 1316 | __func__, get_usb_statmsg(status)); |
1280 | continue; /* -> skip */ | 1317 | continue; /* -> skip */ |
1281 | case -EPIPE: | 1318 | case -EPIPE: |
1282 | dev_err(cs->dev, "isochronous read stalled\n"); | 1319 | dev_err(cs->dev, "isochronous read stalled\n"); |
@@ -1284,7 +1321,7 @@ static void read_iso_tasklet(unsigned long data) | |||
1284 | continue; /* -> skip */ | 1321 | continue; /* -> skip */ |
1285 | default: /* severe trouble */ | 1322 | default: /* severe trouble */ |
1286 | dev_warn(cs->dev, "isochronous read: %s\n", | 1323 | dev_warn(cs->dev, "isochronous read: %s\n", |
1287 | get_usb_statmsg(urb->status)); | 1324 | get_usb_statmsg(status)); |
1288 | goto error; | 1325 | goto error; |
1289 | } | 1326 | } |
1290 | 1327 | ||
@@ -1406,6 +1443,8 @@ static void req_timeout(unsigned long data) | |||
1406 | dev_warn(bcs->cs->dev, "request 0x%02x timed out, clearing\n", | 1443 | dev_warn(bcs->cs->dev, "request 0x%02x timed out, clearing\n", |
1407 | pending); | 1444 | pending); |
1408 | } | 1445 | } |
1446 | |||
1447 | wake_up(&ucs->waitqueue); | ||
1409 | } | 1448 | } |
1410 | 1449 | ||
1411 | /* write_ctrl_callback | 1450 | /* write_ctrl_callback |
@@ -1418,11 +1457,12 @@ static void req_timeout(unsigned long data) | |||
1418 | static void write_ctrl_callback(struct urb *urb) | 1457 | static void write_ctrl_callback(struct urb *urb) |
1419 | { | 1458 | { |
1420 | struct bas_cardstate *ucs = urb->context; | 1459 | struct bas_cardstate *ucs = urb->context; |
1460 | int status = urb->status; | ||
1421 | int rc; | 1461 | int rc; |
1422 | unsigned long flags; | 1462 | unsigned long flags; |
1423 | 1463 | ||
1424 | /* check status */ | 1464 | /* check status */ |
1425 | switch (urb->status) { | 1465 | switch (status) { |
1426 | case 0: /* normal completion */ | 1466 | case 0: /* normal completion */ |
1427 | spin_lock_irqsave(&ucs->lock, flags); | 1467 | spin_lock_irqsave(&ucs->lock, flags); |
1428 | switch (ucs->pending) { | 1468 | switch (ucs->pending) { |
@@ -1441,20 +1481,22 @@ static void write_ctrl_callback(struct urb *urb) | |||
1441 | case -ESHUTDOWN: /* device shut down */ | 1481 | case -ESHUTDOWN: /* device shut down */ |
1442 | /* ignore silently */ | 1482 | /* ignore silently */ |
1443 | gig_dbg(DEBUG_USBREQ, "%s: %s", | 1483 | gig_dbg(DEBUG_USBREQ, "%s: %s", |
1444 | __func__, get_usb_statmsg(urb->status)); | 1484 | __func__, get_usb_statmsg(status)); |
1445 | break; | 1485 | break; |
1446 | 1486 | ||
1447 | default: /* any failure */ | 1487 | default: /* any failure */ |
1448 | if (++ucs->retry_ctrl > BAS_RETRY) { | 1488 | /* don't retry if suspend requested */ |
1489 | if (++ucs->retry_ctrl > BAS_RETRY || | ||
1490 | (ucs->basstate & BS_SUSPEND)) { | ||
1449 | dev_err(&ucs->interface->dev, | 1491 | dev_err(&ucs->interface->dev, |
1450 | "control request 0x%02x failed: %s\n", | 1492 | "control request 0x%02x failed: %s\n", |
1451 | ucs->dr_ctrl.bRequest, | 1493 | ucs->dr_ctrl.bRequest, |
1452 | get_usb_statmsg(urb->status)); | 1494 | get_usb_statmsg(status)); |
1453 | break; /* give up */ | 1495 | break; /* give up */ |
1454 | } | 1496 | } |
1455 | dev_notice(&ucs->interface->dev, | 1497 | dev_notice(&ucs->interface->dev, |
1456 | "control request 0x%02x: %s, retry %d\n", | 1498 | "control request 0x%02x: %s, retry %d\n", |
1457 | ucs->dr_ctrl.bRequest, get_usb_statmsg(urb->status), | 1499 | ucs->dr_ctrl.bRequest, get_usb_statmsg(status), |
1458 | ucs->retry_ctrl); | 1500 | ucs->retry_ctrl); |
1459 | /* urb->dev is clobbered by USB subsystem */ | 1501 | /* urb->dev is clobbered by USB subsystem */ |
1460 | urb->dev = ucs->udev; | 1502 | urb->dev = ucs->udev; |
@@ -1474,6 +1516,7 @@ static void write_ctrl_callback(struct urb *urb) | |||
1474 | del_timer(&ucs->timer_ctrl); | 1516 | del_timer(&ucs->timer_ctrl); |
1475 | ucs->pending = 0; | 1517 | ucs->pending = 0; |
1476 | spin_unlock_irqrestore(&ucs->lock, flags); | 1518 | spin_unlock_irqrestore(&ucs->lock, flags); |
1519 | wake_up(&ucs->waitqueue); | ||
1477 | } | 1520 | } |
1478 | 1521 | ||
1479 | /* req_submit | 1522 | /* req_submit |
@@ -1548,37 +1591,46 @@ static int req_submit(struct bc_state *bcs, int req, int val, int timeout) | |||
1548 | */ | 1591 | */ |
1549 | static int gigaset_init_bchannel(struct bc_state *bcs) | 1592 | static int gigaset_init_bchannel(struct bc_state *bcs) |
1550 | { | 1593 | { |
1594 | struct cardstate *cs = bcs->cs; | ||
1551 | int req, ret; | 1595 | int req, ret; |
1552 | unsigned long flags; | 1596 | unsigned long flags; |
1553 | 1597 | ||
1554 | spin_lock_irqsave(&bcs->cs->lock, flags); | 1598 | spin_lock_irqsave(&cs->lock, flags); |
1555 | if (unlikely(!bcs->cs->connected)) { | 1599 | if (unlikely(!cs->connected)) { |
1556 | gig_dbg(DEBUG_USBREQ, "%s: not connected", __func__); | 1600 | gig_dbg(DEBUG_USBREQ, "%s: not connected", __func__); |
1557 | spin_unlock_irqrestore(&bcs->cs->lock, flags); | 1601 | spin_unlock_irqrestore(&cs->lock, flags); |
1558 | return -ENODEV; | 1602 | return -ENODEV; |
1559 | } | 1603 | } |
1560 | 1604 | ||
1605 | if (cs->hw.bas->basstate & BS_SUSPEND) { | ||
1606 | dev_notice(cs->dev, | ||
1607 | "not starting isochronous I/O, " | ||
1608 | "suspend in progress\n"); | ||
1609 | spin_unlock_irqrestore(&cs->lock, flags); | ||
1610 | return -EHOSTUNREACH; | ||
1611 | } | ||
1612 | |||
1561 | if ((ret = starturbs(bcs)) < 0) { | 1613 | if ((ret = starturbs(bcs)) < 0) { |
1562 | dev_err(bcs->cs->dev, | 1614 | dev_err(cs->dev, |
1563 | "could not start isochronous I/O for channel B%d: %s\n", | 1615 | "could not start isochronous I/O for channel B%d: %s\n", |
1564 | bcs->channel + 1, | 1616 | bcs->channel + 1, |
1565 | ret == -EFAULT ? "null URB" : get_usb_rcmsg(ret)); | 1617 | ret == -EFAULT ? "null URB" : get_usb_rcmsg(ret)); |
1566 | if (ret != -ENODEV) | 1618 | if (ret != -ENODEV) |
1567 | error_hangup(bcs); | 1619 | error_hangup(bcs); |
1568 | spin_unlock_irqrestore(&bcs->cs->lock, flags); | 1620 | spin_unlock_irqrestore(&cs->lock, flags); |
1569 | return ret; | 1621 | return ret; |
1570 | } | 1622 | } |
1571 | 1623 | ||
1572 | req = bcs->channel ? HD_OPEN_B2CHANNEL : HD_OPEN_B1CHANNEL; | 1624 | req = bcs->channel ? HD_OPEN_B2CHANNEL : HD_OPEN_B1CHANNEL; |
1573 | if ((ret = req_submit(bcs, req, 0, BAS_TIMEOUT)) < 0) { | 1625 | if ((ret = req_submit(bcs, req, 0, BAS_TIMEOUT)) < 0) { |
1574 | dev_err(bcs->cs->dev, "could not open channel B%d\n", | 1626 | dev_err(cs->dev, "could not open channel B%d\n", |
1575 | bcs->channel + 1); | 1627 | bcs->channel + 1); |
1576 | stopurbs(bcs->hw.bas); | 1628 | stopurbs(bcs->hw.bas); |
1577 | if (ret != -ENODEV) | 1629 | if (ret != -ENODEV) |
1578 | error_hangup(bcs); | 1630 | error_hangup(bcs); |
1579 | } | 1631 | } |
1580 | 1632 | ||
1581 | spin_unlock_irqrestore(&bcs->cs->lock, flags); | 1633 | spin_unlock_irqrestore(&cs->lock, flags); |
1582 | return ret; | 1634 | return ret; |
1583 | } | 1635 | } |
1584 | 1636 | ||
@@ -1594,20 +1646,20 @@ static int gigaset_init_bchannel(struct bc_state *bcs) | |||
1594 | */ | 1646 | */ |
1595 | static int gigaset_close_bchannel(struct bc_state *bcs) | 1647 | static int gigaset_close_bchannel(struct bc_state *bcs) |
1596 | { | 1648 | { |
1649 | struct cardstate *cs = bcs->cs; | ||
1597 | int req, ret; | 1650 | int req, ret; |
1598 | unsigned long flags; | 1651 | unsigned long flags; |
1599 | 1652 | ||
1600 | spin_lock_irqsave(&bcs->cs->lock, flags); | 1653 | spin_lock_irqsave(&cs->lock, flags); |
1601 | if (unlikely(!bcs->cs->connected)) { | 1654 | if (unlikely(!cs->connected)) { |
1602 | spin_unlock_irqrestore(&bcs->cs->lock, flags); | 1655 | spin_unlock_irqrestore(&cs->lock, flags); |
1603 | gig_dbg(DEBUG_USBREQ, "%s: not connected", __func__); | 1656 | gig_dbg(DEBUG_USBREQ, "%s: not connected", __func__); |
1604 | return -ENODEV; | 1657 | return -ENODEV; |
1605 | } | 1658 | } |
1606 | 1659 | ||
1607 | if (!(atomic_read(&bcs->cs->hw.bas->basstate) & | 1660 | if (!(cs->hw.bas->basstate & (bcs->channel ? BS_B2OPEN : BS_B1OPEN))) { |
1608 | (bcs->channel ? BS_B2OPEN : BS_B1OPEN))) { | ||
1609 | /* channel not running: just signal common.c */ | 1661 | /* channel not running: just signal common.c */ |
1610 | spin_unlock_irqrestore(&bcs->cs->lock, flags); | 1662 | spin_unlock_irqrestore(&cs->lock, flags); |
1611 | gigaset_bchannel_down(bcs); | 1663 | gigaset_bchannel_down(bcs); |
1612 | return 0; | 1664 | return 0; |
1613 | } | 1665 | } |
@@ -1615,10 +1667,10 @@ static int gigaset_close_bchannel(struct bc_state *bcs) | |||
1615 | /* channel running: tell device to close it */ | 1667 | /* channel running: tell device to close it */ |
1616 | req = bcs->channel ? HD_CLOSE_B2CHANNEL : HD_CLOSE_B1CHANNEL; | 1668 | req = bcs->channel ? HD_CLOSE_B2CHANNEL : HD_CLOSE_B1CHANNEL; |
1617 | if ((ret = req_submit(bcs, req, 0, BAS_TIMEOUT)) < 0) | 1669 | if ((ret = req_submit(bcs, req, 0, BAS_TIMEOUT)) < 0) |
1618 | dev_err(bcs->cs->dev, "closing channel B%d failed\n", | 1670 | dev_err(cs->dev, "closing channel B%d failed\n", |
1619 | bcs->channel + 1); | 1671 | bcs->channel + 1); |
1620 | 1672 | ||
1621 | spin_unlock_irqrestore(&bcs->cs->lock, flags); | 1673 | spin_unlock_irqrestore(&cs->lock, flags); |
1622 | return ret; | 1674 | return ret; |
1623 | } | 1675 | } |
1624 | 1676 | ||
@@ -1665,12 +1717,14 @@ static void write_command_callback(struct urb *urb) | |||
1665 | { | 1717 | { |
1666 | struct cardstate *cs = urb->context; | 1718 | struct cardstate *cs = urb->context; |
1667 | struct bas_cardstate *ucs = cs->hw.bas; | 1719 | struct bas_cardstate *ucs = cs->hw.bas; |
1720 | int status = urb->status; | ||
1668 | unsigned long flags; | 1721 | unsigned long flags; |
1669 | 1722 | ||
1670 | update_basstate(ucs, 0, BS_ATWRPEND); | 1723 | update_basstate(ucs, 0, BS_ATWRPEND); |
1724 | wake_up(&ucs->waitqueue); | ||
1671 | 1725 | ||
1672 | /* check status */ | 1726 | /* check status */ |
1673 | switch (urb->status) { | 1727 | switch (status) { |
1674 | case 0: /* normal completion */ | 1728 | case 0: /* normal completion */ |
1675 | break; | 1729 | break; |
1676 | case -ENOENT: /* cancelled */ | 1730 | case -ENOENT: /* cancelled */ |
@@ -1680,26 +1734,33 @@ static void write_command_callback(struct urb *urb) | |||
1680 | case -ESHUTDOWN: /* device shut down */ | 1734 | case -ESHUTDOWN: /* device shut down */ |
1681 | /* ignore silently */ | 1735 | /* ignore silently */ |
1682 | gig_dbg(DEBUG_USBREQ, "%s: %s", | 1736 | gig_dbg(DEBUG_USBREQ, "%s: %s", |
1683 | __func__, get_usb_statmsg(urb->status)); | 1737 | __func__, get_usb_statmsg(status)); |
1684 | return; | 1738 | return; |
1685 | default: /* any failure */ | 1739 | default: /* any failure */ |
1686 | if (++ucs->retry_cmd_out > BAS_RETRY) { | 1740 | if (++ucs->retry_cmd_out > BAS_RETRY) { |
1687 | dev_warn(cs->dev, | 1741 | dev_warn(cs->dev, |
1688 | "command write: %s, " | 1742 | "command write: %s, " |
1689 | "giving up after %d retries\n", | 1743 | "giving up after %d retries\n", |
1690 | get_usb_statmsg(urb->status), | 1744 | get_usb_statmsg(status), |
1691 | ucs->retry_cmd_out); | 1745 | ucs->retry_cmd_out); |
1692 | break; | 1746 | break; |
1693 | } | 1747 | } |
1748 | if (ucs->basstate & BS_SUSPEND) { | ||
1749 | dev_warn(cs->dev, | ||
1750 | "command write: %s, " | ||
1751 | "won't retry - suspend requested\n", | ||
1752 | get_usb_statmsg(status)); | ||
1753 | break; | ||
1754 | } | ||
1694 | if (cs->cmdbuf == NULL) { | 1755 | if (cs->cmdbuf == NULL) { |
1695 | dev_warn(cs->dev, | 1756 | dev_warn(cs->dev, |
1696 | "command write: %s, " | 1757 | "command write: %s, " |
1697 | "cannot retry - cmdbuf gone\n", | 1758 | "cannot retry - cmdbuf gone\n", |
1698 | get_usb_statmsg(urb->status)); | 1759 | get_usb_statmsg(status)); |
1699 | break; | 1760 | break; |
1700 | } | 1761 | } |
1701 | dev_notice(cs->dev, "command write: %s, retry %d\n", | 1762 | dev_notice(cs->dev, "command write: %s, retry %d\n", |
1702 | get_usb_statmsg(urb->status), ucs->retry_cmd_out); | 1763 | get_usb_statmsg(status), ucs->retry_cmd_out); |
1703 | if (atwrite_submit(cs, cs->cmdbuf->buf, cs->cmdbuf->len) >= 0) | 1764 | if (atwrite_submit(cs, cs->cmdbuf->buf, cs->cmdbuf->len) >= 0) |
1704 | /* resubmitted - bypass regular exit block */ | 1765 | /* resubmitted - bypass regular exit block */ |
1705 | return; | 1766 | return; |
@@ -1799,8 +1860,14 @@ static int start_cbsend(struct cardstate *cs) | |||
1799 | int rc; | 1860 | int rc; |
1800 | int retval = 0; | 1861 | int retval = 0; |
1801 | 1862 | ||
1863 | /* check if suspend requested */ | ||
1864 | if (ucs->basstate & BS_SUSPEND) { | ||
1865 | gig_dbg(DEBUG_TRANSCMD|DEBUG_LOCKCMD, "suspending"); | ||
1866 | return -EHOSTUNREACH; | ||
1867 | } | ||
1868 | |||
1802 | /* check if AT channel is open */ | 1869 | /* check if AT channel is open */ |
1803 | if (!(atomic_read(&ucs->basstate) & BS_ATOPEN)) { | 1870 | if (!(ucs->basstate & BS_ATOPEN)) { |
1804 | gig_dbg(DEBUG_TRANSCMD|DEBUG_LOCKCMD, "AT channel not open"); | 1871 | gig_dbg(DEBUG_TRANSCMD|DEBUG_LOCKCMD, "AT channel not open"); |
1805 | rc = req_submit(cs->bcs, HD_OPEN_ATCHANNEL, 0, BAS_TIMEOUT); | 1872 | rc = req_submit(cs->bcs, HD_OPEN_ATCHANNEL, 0, BAS_TIMEOUT); |
1806 | if (rc < 0) { | 1873 | if (rc < 0) { |
@@ -1816,8 +1883,7 @@ static int start_cbsend(struct cardstate *cs) | |||
1816 | /* try to send first command in queue */ | 1883 | /* try to send first command in queue */ |
1817 | spin_lock_irqsave(&cs->cmdlock, flags); | 1884 | spin_lock_irqsave(&cs->cmdlock, flags); |
1818 | 1885 | ||
1819 | while ((cb = cs->cmdbuf) != NULL && | 1886 | while ((cb = cs->cmdbuf) != NULL && (ucs->basstate & BS_ATREADY)) { |
1820 | atomic_read(&ucs->basstate) & BS_ATREADY) { | ||
1821 | ucs->retry_cmd_out = 0; | 1887 | ucs->retry_cmd_out = 0; |
1822 | rc = atwrite_submit(cs, cb->buf, cb->len); | 1888 | rc = atwrite_submit(cs, cb->buf, cb->len); |
1823 | if (unlikely(rc)) { | 1889 | if (unlikely(rc)) { |
@@ -1855,7 +1921,7 @@ static int gigaset_write_cmd(struct cardstate *cs, | |||
1855 | unsigned long flags; | 1921 | unsigned long flags; |
1856 | int rc; | 1922 | int rc; |
1857 | 1923 | ||
1858 | gigaset_dbg_buffer(atomic_read(&cs->mstate) != MS_LOCKED ? | 1924 | gigaset_dbg_buffer(cs->mstate != MS_LOCKED ? |
1859 | DEBUG_TRANSCMD : DEBUG_LOCKCMD, | 1925 | DEBUG_TRANSCMD : DEBUG_LOCKCMD, |
1860 | "CMD Transmit", len, buf); | 1926 | "CMD Transmit", len, buf); |
1861 | 1927 | ||
@@ -1970,7 +2036,7 @@ static int gigaset_freebcshw(struct bc_state *bcs) | |||
1970 | return 0; | 2036 | return 0; |
1971 | 2037 | ||
1972 | /* kill URBs and tasklets before freeing - better safe than sorry */ | 2038 | /* kill URBs and tasklets before freeing - better safe than sorry */ |
1973 | atomic_set(&ubc->running, 0); | 2039 | ubc->running = 0; |
1974 | gig_dbg(DEBUG_INIT, "%s: killing iso URBs", __func__); | 2040 | gig_dbg(DEBUG_INIT, "%s: killing iso URBs", __func__); |
1975 | for (i = 0; i < BAS_OUTURBS; ++i) { | 2041 | for (i = 0; i < BAS_OUTURBS; ++i) { |
1976 | usb_kill_urb(ubc->isoouturbs[i].urb); | 2042 | usb_kill_urb(ubc->isoouturbs[i].urb); |
@@ -2005,7 +2071,7 @@ static int gigaset_initbcshw(struct bc_state *bcs) | |||
2005 | return 0; | 2071 | return 0; |
2006 | } | 2072 | } |
2007 | 2073 | ||
2008 | atomic_set(&ubc->running, 0); | 2074 | ubc->running = 0; |
2009 | atomic_set(&ubc->corrbytes, 0); | 2075 | atomic_set(&ubc->corrbytes, 0); |
2010 | spin_lock_init(&ubc->isooutlock); | 2076 | spin_lock_init(&ubc->isooutlock); |
2011 | for (i = 0; i < BAS_OUTURBS; ++i) { | 2077 | for (i = 0; i < BAS_OUTURBS; ++i) { |
@@ -2050,7 +2116,7 @@ static void gigaset_reinitbcshw(struct bc_state *bcs) | |||
2050 | { | 2116 | { |
2051 | struct bas_bc_state *ubc = bcs->hw.bas; | 2117 | struct bas_bc_state *ubc = bcs->hw.bas; |
2052 | 2118 | ||
2053 | atomic_set(&bcs->hw.bas->running, 0); | 2119 | bcs->hw.bas->running = 0; |
2054 | atomic_set(&bcs->hw.bas->corrbytes, 0); | 2120 | atomic_set(&bcs->hw.bas->corrbytes, 0); |
2055 | bcs->hw.bas->numsub = 0; | 2121 | bcs->hw.bas->numsub = 0; |
2056 | spin_lock_init(&ubc->isooutlock); | 2122 | spin_lock_init(&ubc->isooutlock); |
@@ -2081,10 +2147,11 @@ static int gigaset_initcshw(struct cardstate *cs) | |||
2081 | spin_lock_init(&ucs->lock); | 2147 | spin_lock_init(&ucs->lock); |
2082 | ucs->pending = 0; | 2148 | ucs->pending = 0; |
2083 | 2149 | ||
2084 | atomic_set(&ucs->basstate, 0); | 2150 | ucs->basstate = 0; |
2085 | init_timer(&ucs->timer_ctrl); | 2151 | init_timer(&ucs->timer_ctrl); |
2086 | init_timer(&ucs->timer_atrdy); | 2152 | init_timer(&ucs->timer_atrdy); |
2087 | init_timer(&ucs->timer_cmd_in); | 2153 | init_timer(&ucs->timer_cmd_in); |
2154 | init_waitqueue_head(&ucs->waitqueue); | ||
2088 | 2155 | ||
2089 | return 1; | 2156 | return 1; |
2090 | } | 2157 | } |
@@ -2102,7 +2169,7 @@ static void freeurbs(struct cardstate *cs) | |||
2102 | int i, j; | 2169 | int i, j; |
2103 | 2170 | ||
2104 | gig_dbg(DEBUG_INIT, "%s: killing URBs", __func__); | 2171 | gig_dbg(DEBUG_INIT, "%s: killing URBs", __func__); |
2105 | for (j = 0; j < 2; ++j) { | 2172 | for (j = 0; j < BAS_CHANNELS; ++j) { |
2106 | ubc = cs->bcs[j].hw.bas; | 2173 | ubc = cs->bcs[j].hw.bas; |
2107 | for (i = 0; i < BAS_OUTURBS; ++i) { | 2174 | for (i = 0; i < BAS_OUTURBS; ++i) { |
2108 | usb_kill_urb(ubc->isoouturbs[i].urb); | 2175 | usb_kill_urb(ubc->isoouturbs[i].urb); |
@@ -2179,11 +2246,11 @@ static int gigaset_probe(struct usb_interface *interface, | |||
2179 | __func__, le16_to_cpu(udev->descriptor.idVendor), | 2246 | __func__, le16_to_cpu(udev->descriptor.idVendor), |
2180 | le16_to_cpu(udev->descriptor.idProduct)); | 2247 | le16_to_cpu(udev->descriptor.idProduct)); |
2181 | 2248 | ||
2182 | cs = gigaset_getunassignedcs(driver); | 2249 | /* allocate memory for our device state and intialize it */ |
2183 | if (!cs) { | 2250 | cs = gigaset_initcs(driver, BAS_CHANNELS, 0, 0, cidmode, |
2184 | dev_err(&udev->dev, "no free cardstate\n"); | 2251 | GIGASET_MODULENAME); |
2252 | if (!cs) | ||
2185 | return -ENODEV; | 2253 | return -ENODEV; |
2186 | } | ||
2187 | ucs = cs->hw.bas; | 2254 | ucs = cs->hw.bas; |
2188 | 2255 | ||
2189 | /* save off device structure ptrs for later use */ | 2256 | /* save off device structure ptrs for later use */ |
@@ -2203,7 +2270,7 @@ static int gigaset_probe(struct usb_interface *interface, | |||
2203 | !(ucs->urb_ctrl = usb_alloc_urb(0, GFP_KERNEL))) | 2270 | !(ucs->urb_ctrl = usb_alloc_urb(0, GFP_KERNEL))) |
2204 | goto allocerr; | 2271 | goto allocerr; |
2205 | 2272 | ||
2206 | for (j = 0; j < 2; ++j) { | 2273 | for (j = 0; j < BAS_CHANNELS; ++j) { |
2207 | ubc = cs->bcs[j].hw.bas; | 2274 | ubc = cs->bcs[j].hw.bas; |
2208 | for (i = 0; i < BAS_OUTURBS; ++i) | 2275 | for (i = 0; i < BAS_OUTURBS; ++i) |
2209 | if (!(ubc->isoouturbs[i].urb = | 2276 | if (!(ubc->isoouturbs[i].urb = |
@@ -2237,7 +2304,7 @@ static int gigaset_probe(struct usb_interface *interface, | |||
2237 | 2304 | ||
2238 | /* tell common part that the device is ready */ | 2305 | /* tell common part that the device is ready */ |
2239 | if (startmode == SM_LOCKED) | 2306 | if (startmode == SM_LOCKED) |
2240 | atomic_set(&cs->mstate, MS_LOCKED); | 2307 | cs->mstate = MS_LOCKED; |
2241 | 2308 | ||
2242 | /* save address of controller structure */ | 2309 | /* save address of controller structure */ |
2243 | usb_set_intfdata(interface, cs); | 2310 | usb_set_intfdata(interface, cs); |
@@ -2252,7 +2319,7 @@ allocerr: | |||
2252 | error: | 2319 | error: |
2253 | freeurbs(cs); | 2320 | freeurbs(cs); |
2254 | usb_set_intfdata(interface, NULL); | 2321 | usb_set_intfdata(interface, NULL); |
2255 | gigaset_unassign(cs); | 2322 | gigaset_freecs(cs); |
2256 | return -ENODEV; | 2323 | return -ENODEV; |
2257 | } | 2324 | } |
2258 | 2325 | ||
@@ -2272,11 +2339,10 @@ static void gigaset_disconnect(struct usb_interface *interface) | |||
2272 | dev_info(cs->dev, "disconnecting Gigaset base\n"); | 2339 | dev_info(cs->dev, "disconnecting Gigaset base\n"); |
2273 | 2340 | ||
2274 | /* mark base as not ready, all channels disconnected */ | 2341 | /* mark base as not ready, all channels disconnected */ |
2275 | atomic_set(&ucs->basstate, 0); | 2342 | ucs->basstate = 0; |
2276 | 2343 | ||
2277 | /* tell LL all channels are down */ | 2344 | /* tell LL all channels are down */ |
2278 | //FIXME shouldn't gigaset_stop() do this? | 2345 | for (j = 0; j < BAS_CHANNELS; ++j) |
2279 | for (j = 0; j < 2; ++j) | ||
2280 | gigaset_bchannel_down(cs->bcs + j); | 2346 | gigaset_bchannel_down(cs->bcs + j); |
2281 | 2347 | ||
2282 | /* stop driver (common part) */ | 2348 | /* stop driver (common part) */ |
@@ -2295,9 +2361,113 @@ static void gigaset_disconnect(struct usb_interface *interface) | |||
2295 | ucs->interface = NULL; | 2361 | ucs->interface = NULL; |
2296 | ucs->udev = NULL; | 2362 | ucs->udev = NULL; |
2297 | cs->dev = NULL; | 2363 | cs->dev = NULL; |
2298 | gigaset_unassign(cs); | 2364 | gigaset_freecs(cs); |
2299 | } | 2365 | } |
2300 | 2366 | ||
2367 | /* gigaset_suspend | ||
2368 | * This function is called before the USB connection is suspended. | ||
2369 | */ | ||
2370 | static int gigaset_suspend(struct usb_interface *intf, pm_message_t message) | ||
2371 | { | ||
2372 | struct cardstate *cs = usb_get_intfdata(intf); | ||
2373 | struct bas_cardstate *ucs = cs->hw.bas; | ||
2374 | int rc; | ||
2375 | |||
2376 | /* set suspend flag; this stops AT command/response traffic */ | ||
2377 | if (update_basstate(ucs, BS_SUSPEND, 0) & BS_SUSPEND) { | ||
2378 | gig_dbg(DEBUG_SUSPEND, "already suspended"); | ||
2379 | return 0; | ||
2380 | } | ||
2381 | |||
2382 | /* wait a bit for blocking conditions to go away */ | ||
2383 | rc = wait_event_timeout(ucs->waitqueue, | ||
2384 | !(ucs->basstate & | ||
2385 | (BS_B1OPEN|BS_B2OPEN|BS_ATRDPEND|BS_ATWRPEND)), | ||
2386 | BAS_TIMEOUT*HZ/10); | ||
2387 | gig_dbg(DEBUG_SUSPEND, "wait_event_timeout() -> %d", rc); | ||
2388 | |||
2389 | /* check for conditions preventing suspend */ | ||
2390 | if (ucs->basstate & (BS_B1OPEN|BS_B2OPEN|BS_ATRDPEND|BS_ATWRPEND)) { | ||
2391 | dev_warn(cs->dev, "cannot suspend:\n"); | ||
2392 | if (ucs->basstate & BS_B1OPEN) | ||
2393 | dev_warn(cs->dev, " B channel 1 open\n"); | ||
2394 | if (ucs->basstate & BS_B2OPEN) | ||
2395 | dev_warn(cs->dev, " B channel 2 open\n"); | ||
2396 | if (ucs->basstate & BS_ATRDPEND) | ||
2397 | dev_warn(cs->dev, " receiving AT reply\n"); | ||
2398 | if (ucs->basstate & BS_ATWRPEND) | ||
2399 | dev_warn(cs->dev, " sending AT command\n"); | ||
2400 | update_basstate(ucs, 0, BS_SUSPEND); | ||
2401 | return -EBUSY; | ||
2402 | } | ||
2403 | |||
2404 | /* close AT channel if open */ | ||
2405 | if (ucs->basstate & BS_ATOPEN) { | ||
2406 | gig_dbg(DEBUG_SUSPEND, "closing AT channel"); | ||
2407 | rc = req_submit(cs->bcs, HD_CLOSE_ATCHANNEL, 0, 0); | ||
2408 | if (rc) { | ||
2409 | update_basstate(ucs, 0, BS_SUSPEND); | ||
2410 | return rc; | ||
2411 | } | ||
2412 | wait_event_timeout(ucs->waitqueue, !ucs->pending, | ||
2413 | BAS_TIMEOUT*HZ/10); | ||
2414 | /* in case of timeout, proceed anyway */ | ||
2415 | } | ||
2416 | |||
2417 | /* kill all URBs and timers that might still be pending */ | ||
2418 | usb_kill_urb(ucs->urb_ctrl); | ||
2419 | usb_kill_urb(ucs->urb_int_in); | ||
2420 | del_timer_sync(&ucs->timer_ctrl); | ||
2421 | |||
2422 | gig_dbg(DEBUG_SUSPEND, "suspend complete"); | ||
2423 | return 0; | ||
2424 | } | ||
2425 | |||
2426 | /* gigaset_resume | ||
2427 | * This function is called after the USB connection has been resumed. | ||
2428 | */ | ||
2429 | static int gigaset_resume(struct usb_interface *intf) | ||
2430 | { | ||
2431 | struct cardstate *cs = usb_get_intfdata(intf); | ||
2432 | struct bas_cardstate *ucs = cs->hw.bas; | ||
2433 | int rc; | ||
2434 | |||
2435 | /* resubmit interrupt URB for spontaneous messages from base */ | ||
2436 | rc = usb_submit_urb(ucs->urb_int_in, GFP_KERNEL); | ||
2437 | if (rc) { | ||
2438 | dev_err(cs->dev, "could not resubmit interrupt URB: %s\n", | ||
2439 | get_usb_rcmsg(rc)); | ||
2440 | return rc; | ||
2441 | } | ||
2442 | |||
2443 | /* clear suspend flag to reallow activity */ | ||
2444 | update_basstate(ucs, 0, BS_SUSPEND); | ||
2445 | |||
2446 | gig_dbg(DEBUG_SUSPEND, "resume complete"); | ||
2447 | return 0; | ||
2448 | } | ||
2449 | |||
2450 | /* gigaset_pre_reset | ||
2451 | * This function is called before the USB connection is reset. | ||
2452 | */ | ||
2453 | static int gigaset_pre_reset(struct usb_interface *intf) | ||
2454 | { | ||
2455 | /* handle just like suspend */ | ||
2456 | return gigaset_suspend(intf, PMSG_ON); | ||
2457 | } | ||
2458 | |||
2459 | /* gigaset_post_reset | ||
2460 | * This function is called after the USB connection has been reset. | ||
2461 | */ | ||
2462 | static int gigaset_post_reset(struct usb_interface *intf) | ||
2463 | { | ||
2464 | /* FIXME: send HD_DEVICE_INIT_ACK? */ | ||
2465 | |||
2466 | /* resume operations */ | ||
2467 | return gigaset_resume(intf); | ||
2468 | } | ||
2469 | |||
2470 | |||
2301 | static const struct gigaset_ops gigops = { | 2471 | static const struct gigaset_ops gigops = { |
2302 | gigaset_write_cmd, | 2472 | gigaset_write_cmd, |
2303 | gigaset_write_room, | 2473 | gigaset_write_room, |
@@ -2330,12 +2500,6 @@ static int __init bas_gigaset_init(void) | |||
2330 | &gigops, THIS_MODULE)) == NULL) | 2500 | &gigops, THIS_MODULE)) == NULL) |
2331 | goto error; | 2501 | goto error; |
2332 | 2502 | ||
2333 | /* allocate memory for our device state and intialize it */ | ||
2334 | cardstate = gigaset_initcs(driver, 2, 0, 0, cidmode, | ||
2335 | GIGASET_MODULENAME); | ||
2336 | if (!cardstate) | ||
2337 | goto error; | ||
2338 | |||
2339 | /* register this driver with the USB subsystem */ | 2503 | /* register this driver with the USB subsystem */ |
2340 | result = usb_register(&gigaset_usb_driver); | 2504 | result = usb_register(&gigaset_usb_driver); |
2341 | if (result < 0) { | 2505 | if (result < 0) { |
@@ -2347,9 +2511,7 @@ static int __init bas_gigaset_init(void) | |||
2347 | info(DRIVER_DESC); | 2511 | info(DRIVER_DESC); |
2348 | return 0; | 2512 | return 0; |
2349 | 2513 | ||
2350 | error: if (cardstate) | 2514 | error: |
2351 | gigaset_freecs(cardstate); | ||
2352 | cardstate = NULL; | ||
2353 | if (driver) | 2515 | if (driver) |
2354 | gigaset_freedriver(driver); | 2516 | gigaset_freedriver(driver); |
2355 | driver = NULL; | 2517 | driver = NULL; |
@@ -2361,43 +2523,50 @@ error: if (cardstate) | |||
2361 | */ | 2523 | */ |
2362 | static void __exit bas_gigaset_exit(void) | 2524 | static void __exit bas_gigaset_exit(void) |
2363 | { | 2525 | { |
2364 | struct bas_cardstate *ucs = cardstate->hw.bas; | 2526 | struct bas_cardstate *ucs; |
2527 | int i; | ||
2365 | 2528 | ||
2366 | gigaset_blockdriver(driver); /* => probe will fail | 2529 | gigaset_blockdriver(driver); /* => probe will fail |
2367 | * => no gigaset_start any more | 2530 | * => no gigaset_start any more |
2368 | */ | 2531 | */ |
2369 | 2532 | ||
2370 | gigaset_shutdown(cardstate); | 2533 | /* stop all connected devices */ |
2371 | /* from now on, no isdn callback should be possible */ | 2534 | for (i = 0; i < driver->minors; i++) { |
2372 | 2535 | if (gigaset_shutdown(driver->cs + i) < 0) | |
2373 | /* close all still open channels */ | 2536 | continue; /* no device */ |
2374 | if (atomic_read(&ucs->basstate) & BS_B1OPEN) { | 2537 | /* from now on, no isdn callback should be possible */ |
2375 | gig_dbg(DEBUG_INIT, "closing B1 channel"); | 2538 | |
2376 | usb_control_msg(ucs->udev, usb_sndctrlpipe(ucs->udev, 0), | 2539 | /* close all still open channels */ |
2377 | HD_CLOSE_B1CHANNEL, OUT_VENDOR_REQ, 0, 0, | 2540 | ucs = driver->cs[i].hw.bas; |
2378 | NULL, 0, BAS_TIMEOUT); | 2541 | if (ucs->basstate & BS_B1OPEN) { |
2379 | } | 2542 | gig_dbg(DEBUG_INIT, "closing B1 channel"); |
2380 | if (atomic_read(&ucs->basstate) & BS_B2OPEN) { | 2543 | usb_control_msg(ucs->udev, |
2381 | gig_dbg(DEBUG_INIT, "closing B2 channel"); | 2544 | usb_sndctrlpipe(ucs->udev, 0), |
2382 | usb_control_msg(ucs->udev, usb_sndctrlpipe(ucs->udev, 0), | 2545 | HD_CLOSE_B1CHANNEL, OUT_VENDOR_REQ, |
2383 | HD_CLOSE_B2CHANNEL, OUT_VENDOR_REQ, 0, 0, | 2546 | 0, 0, NULL, 0, BAS_TIMEOUT); |
2384 | NULL, 0, BAS_TIMEOUT); | 2547 | } |
2385 | } | 2548 | if (ucs->basstate & BS_B2OPEN) { |
2386 | if (atomic_read(&ucs->basstate) & BS_ATOPEN) { | 2549 | gig_dbg(DEBUG_INIT, "closing B2 channel"); |
2387 | gig_dbg(DEBUG_INIT, "closing AT channel"); | 2550 | usb_control_msg(ucs->udev, |
2388 | usb_control_msg(ucs->udev, usb_sndctrlpipe(ucs->udev, 0), | 2551 | usb_sndctrlpipe(ucs->udev, 0), |
2389 | HD_CLOSE_ATCHANNEL, OUT_VENDOR_REQ, 0, 0, | 2552 | HD_CLOSE_B2CHANNEL, OUT_VENDOR_REQ, |
2390 | NULL, 0, BAS_TIMEOUT); | 2553 | 0, 0, NULL, 0, BAS_TIMEOUT); |
2554 | } | ||
2555 | if (ucs->basstate & BS_ATOPEN) { | ||
2556 | gig_dbg(DEBUG_INIT, "closing AT channel"); | ||
2557 | usb_control_msg(ucs->udev, | ||
2558 | usb_sndctrlpipe(ucs->udev, 0), | ||
2559 | HD_CLOSE_ATCHANNEL, OUT_VENDOR_REQ, | ||
2560 | 0, 0, NULL, 0, BAS_TIMEOUT); | ||
2561 | } | ||
2562 | ucs->basstate = 0; | ||
2391 | } | 2563 | } |
2392 | atomic_set(&ucs->basstate, 0); | ||
2393 | 2564 | ||
2394 | /* deregister this driver with the USB subsystem */ | 2565 | /* deregister this driver with the USB subsystem */ |
2395 | usb_deregister(&gigaset_usb_driver); | 2566 | usb_deregister(&gigaset_usb_driver); |
2396 | /* this will call the disconnect-callback */ | 2567 | /* this will call the disconnect-callback */ |
2397 | /* from now on, no disconnect/probe callback should be running */ | 2568 | /* from now on, no disconnect/probe callback should be running */ |
2398 | 2569 | ||
2399 | gigaset_freecs(cardstate); | ||
2400 | cardstate = NULL; | ||
2401 | gigaset_freedriver(driver); | 2570 | gigaset_freedriver(driver); |
2402 | driver = NULL; | 2571 | driver = NULL; |
2403 | } | 2572 | } |
diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c index acd417197d03..aacedec4986f 100644 --- a/drivers/isdn/gigaset/common.c +++ b/drivers/isdn/gigaset/common.c | |||
@@ -31,7 +31,6 @@ MODULE_PARM_DESC(debug, "debug level"); | |||
31 | /* driver state flags */ | 31 | /* driver state flags */ |
32 | #define VALID_MINOR 0x01 | 32 | #define VALID_MINOR 0x01 |
33 | #define VALID_ID 0x02 | 33 | #define VALID_ID 0x02 |
34 | #define ASSIGNED 0x04 | ||
35 | 34 | ||
36 | void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg, | 35 | void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg, |
37 | size_t len, const unsigned char *buf) | 36 | size_t len, const unsigned char *buf) |
@@ -178,7 +177,7 @@ int gigaset_get_channel(struct bc_state *bcs) | |||
178 | unsigned long flags; | 177 | unsigned long flags; |
179 | 178 | ||
180 | spin_lock_irqsave(&bcs->cs->lock, flags); | 179 | spin_lock_irqsave(&bcs->cs->lock, flags); |
181 | if (bcs->use_count) { | 180 | if (bcs->use_count || !try_module_get(bcs->cs->driver->owner)) { |
182 | gig_dbg(DEBUG_ANY, "could not allocate channel %d", | 181 | gig_dbg(DEBUG_ANY, "could not allocate channel %d", |
183 | bcs->channel); | 182 | bcs->channel); |
184 | spin_unlock_irqrestore(&bcs->cs->lock, flags); | 183 | spin_unlock_irqrestore(&bcs->cs->lock, flags); |
@@ -203,6 +202,7 @@ void gigaset_free_channel(struct bc_state *bcs) | |||
203 | } | 202 | } |
204 | --bcs->use_count; | 203 | --bcs->use_count; |
205 | bcs->busy = 0; | 204 | bcs->busy = 0; |
205 | module_put(bcs->cs->driver->owner); | ||
206 | gig_dbg(DEBUG_ANY, "freed channel %d", bcs->channel); | 206 | gig_dbg(DEBUG_ANY, "freed channel %d", bcs->channel); |
207 | spin_unlock_irqrestore(&bcs->cs->lock, flags); | 207 | spin_unlock_irqrestore(&bcs->cs->lock, flags); |
208 | } | 208 | } |
@@ -356,31 +356,28 @@ static struct cardstate *alloc_cs(struct gigaset_driver *drv) | |||
356 | { | 356 | { |
357 | unsigned long flags; | 357 | unsigned long flags; |
358 | unsigned i; | 358 | unsigned i; |
359 | struct cardstate *cs; | ||
359 | struct cardstate *ret = NULL; | 360 | struct cardstate *ret = NULL; |
360 | 361 | ||
361 | spin_lock_irqsave(&drv->lock, flags); | 362 | spin_lock_irqsave(&drv->lock, flags); |
363 | if (drv->blocked) | ||
364 | goto exit; | ||
362 | for (i = 0; i < drv->minors; ++i) { | 365 | for (i = 0; i < drv->minors; ++i) { |
363 | if (!(drv->flags[i] & VALID_MINOR)) { | 366 | cs = drv->cs + i; |
364 | if (try_module_get(drv->owner)) { | 367 | if (!(cs->flags & VALID_MINOR)) { |
365 | drv->flags[i] = VALID_MINOR; | 368 | cs->flags = VALID_MINOR; |
366 | ret = drv->cs + i; | 369 | ret = cs; |
367 | } | ||
368 | break; | 370 | break; |
369 | } | 371 | } |
370 | } | 372 | } |
373 | exit: | ||
371 | spin_unlock_irqrestore(&drv->lock, flags); | 374 | spin_unlock_irqrestore(&drv->lock, flags); |
372 | return ret; | 375 | return ret; |
373 | } | 376 | } |
374 | 377 | ||
375 | static void free_cs(struct cardstate *cs) | 378 | static void free_cs(struct cardstate *cs) |
376 | { | 379 | { |
377 | unsigned long flags; | 380 | cs->flags = 0; |
378 | struct gigaset_driver *drv = cs->driver; | ||
379 | spin_lock_irqsave(&drv->lock, flags); | ||
380 | if (drv->flags[cs->minor_index] & VALID_MINOR) | ||
381 | module_put(drv->owner); | ||
382 | drv->flags[cs->minor_index] = 0; | ||
383 | spin_unlock_irqrestore(&drv->lock, flags); | ||
384 | } | 381 | } |
385 | 382 | ||
386 | static void make_valid(struct cardstate *cs, unsigned mask) | 383 | static void make_valid(struct cardstate *cs, unsigned mask) |
@@ -388,7 +385,7 @@ static void make_valid(struct cardstate *cs, unsigned mask) | |||
388 | unsigned long flags; | 385 | unsigned long flags; |
389 | struct gigaset_driver *drv = cs->driver; | 386 | struct gigaset_driver *drv = cs->driver; |
390 | spin_lock_irqsave(&drv->lock, flags); | 387 | spin_lock_irqsave(&drv->lock, flags); |
391 | drv->flags[cs->minor_index] |= mask; | 388 | cs->flags |= mask; |
392 | spin_unlock_irqrestore(&drv->lock, flags); | 389 | spin_unlock_irqrestore(&drv->lock, flags); |
393 | } | 390 | } |
394 | 391 | ||
@@ -397,7 +394,7 @@ static void make_invalid(struct cardstate *cs, unsigned mask) | |||
397 | unsigned long flags; | 394 | unsigned long flags; |
398 | struct gigaset_driver *drv = cs->driver; | 395 | struct gigaset_driver *drv = cs->driver; |
399 | spin_lock_irqsave(&drv->lock, flags); | 396 | spin_lock_irqsave(&drv->lock, flags); |
400 | drv->flags[cs->minor_index] &= ~mask; | 397 | cs->flags &= ~mask; |
401 | spin_unlock_irqrestore(&drv->lock, flags); | 398 | spin_unlock_irqrestore(&drv->lock, flags); |
402 | } | 399 | } |
403 | 400 | ||
@@ -501,11 +498,11 @@ static void gigaset_inbuf_init(struct inbuf_t *inbuf, struct bc_state *bcs, | |||
501 | struct cardstate *cs, int inputstate) | 498 | struct cardstate *cs, int inputstate) |
502 | /* inbuf->read must be allocated before! */ | 499 | /* inbuf->read must be allocated before! */ |
503 | { | 500 | { |
504 | atomic_set(&inbuf->head, 0); | 501 | inbuf->head = 0; |
505 | atomic_set(&inbuf->tail, 0); | 502 | inbuf->tail = 0; |
506 | inbuf->cs = cs; | 503 | inbuf->cs = cs; |
507 | inbuf->bcs = bcs; /*base driver: NULL*/ | 504 | inbuf->bcs = bcs; /*base driver: NULL*/ |
508 | inbuf->rcvbuf = NULL; //FIXME | 505 | inbuf->rcvbuf = NULL; |
509 | inbuf->inputstate = inputstate; | 506 | inbuf->inputstate = inputstate; |
510 | } | 507 | } |
511 | 508 | ||
@@ -521,8 +518,8 @@ int gigaset_fill_inbuf(struct inbuf_t *inbuf, const unsigned char *src, | |||
521 | return 0; | 518 | return 0; |
522 | 519 | ||
523 | bytesleft = numbytes; | 520 | bytesleft = numbytes; |
524 | tail = atomic_read(&inbuf->tail); | 521 | tail = inbuf->tail; |
525 | head = atomic_read(&inbuf->head); | 522 | head = inbuf->head; |
526 | gig_dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail); | 523 | gig_dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail); |
527 | 524 | ||
528 | while (bytesleft) { | 525 | while (bytesleft) { |
@@ -546,7 +543,7 @@ int gigaset_fill_inbuf(struct inbuf_t *inbuf, const unsigned char *src, | |||
546 | src += n; | 543 | src += n; |
547 | } | 544 | } |
548 | gig_dbg(DEBUG_INTR, "setting tail to %u", tail); | 545 | gig_dbg(DEBUG_INTR, "setting tail to %u", tail); |
549 | atomic_set(&inbuf->tail, tail); | 546 | inbuf->tail = tail; |
550 | return numbytes != bytesleft; | 547 | return numbytes != bytesleft; |
551 | } | 548 | } |
552 | EXPORT_SYMBOL_GPL(gigaset_fill_inbuf); | 549 | EXPORT_SYMBOL_GPL(gigaset_fill_inbuf); |
@@ -668,7 +665,7 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels, | |||
668 | 665 | ||
669 | tasklet_init(&cs->event_tasklet, &gigaset_handle_event, | 666 | tasklet_init(&cs->event_tasklet, &gigaset_handle_event, |
670 | (unsigned long) cs); | 667 | (unsigned long) cs); |
671 | atomic_set(&cs->commands_pending, 0); | 668 | cs->commands_pending = 0; |
672 | cs->cur_at_seq = 0; | 669 | cs->cur_at_seq = 0; |
673 | cs->gotfwver = -1; | 670 | cs->gotfwver = -1; |
674 | cs->open_count = 0; | 671 | cs->open_count = 0; |
@@ -688,8 +685,8 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels, | |||
688 | init_waitqueue_head(&cs->waitqueue); | 685 | init_waitqueue_head(&cs->waitqueue); |
689 | cs->waiting = 0; | 686 | cs->waiting = 0; |
690 | 687 | ||
691 | atomic_set(&cs->mode, M_UNKNOWN); | 688 | cs->mode = M_UNKNOWN; |
692 | atomic_set(&cs->mstate, MS_UNINITIALIZED); | 689 | cs->mstate = MS_UNINITIALIZED; |
693 | 690 | ||
694 | for (i = 0; i < channels; ++i) { | 691 | for (i = 0; i < channels; ++i) { |
695 | gig_dbg(DEBUG_INIT, "setting up bcs[%d].read", i); | 692 | gig_dbg(DEBUG_INIT, "setting up bcs[%d].read", i); |
@@ -806,8 +803,8 @@ static void cleanup_cs(struct cardstate *cs) | |||
806 | 803 | ||
807 | spin_lock_irqsave(&cs->lock, flags); | 804 | spin_lock_irqsave(&cs->lock, flags); |
808 | 805 | ||
809 | atomic_set(&cs->mode, M_UNKNOWN); | 806 | cs->mode = M_UNKNOWN; |
810 | atomic_set(&cs->mstate, MS_UNINITIALIZED); | 807 | cs->mstate = MS_UNINITIALIZED; |
811 | 808 | ||
812 | clear_at_state(&cs->at_state); | 809 | clear_at_state(&cs->at_state); |
813 | dealloc_at_states(cs); | 810 | dealloc_at_states(cs); |
@@ -817,8 +814,8 @@ static void cleanup_cs(struct cardstate *cs) | |||
817 | kfree(cs->inbuf->rcvbuf); | 814 | kfree(cs->inbuf->rcvbuf); |
818 | cs->inbuf->rcvbuf = NULL; | 815 | cs->inbuf->rcvbuf = NULL; |
819 | cs->inbuf->inputstate = INS_command; | 816 | cs->inbuf->inputstate = INS_command; |
820 | atomic_set(&cs->inbuf->head, 0); | 817 | cs->inbuf->head = 0; |
821 | atomic_set(&cs->inbuf->tail, 0); | 818 | cs->inbuf->tail = 0; |
822 | 819 | ||
823 | cb = cs->cmdbuf; | 820 | cb = cs->cmdbuf; |
824 | while (cb) { | 821 | while (cb) { |
@@ -832,7 +829,7 @@ static void cleanup_cs(struct cardstate *cs) | |||
832 | cs->gotfwver = -1; | 829 | cs->gotfwver = -1; |
833 | cs->dle = 0; | 830 | cs->dle = 0; |
834 | cs->cur_at_seq = 0; | 831 | cs->cur_at_seq = 0; |
835 | atomic_set(&cs->commands_pending, 0); | 832 | cs->commands_pending = 0; |
836 | cs->cbytes = 0; | 833 | cs->cbytes = 0; |
837 | 834 | ||
838 | spin_unlock_irqrestore(&cs->lock, flags); | 835 | spin_unlock_irqrestore(&cs->lock, flags); |
@@ -862,7 +859,7 @@ int gigaset_start(struct cardstate *cs) | |||
862 | cs->connected = 1; | 859 | cs->connected = 1; |
863 | spin_unlock_irqrestore(&cs->lock, flags); | 860 | spin_unlock_irqrestore(&cs->lock, flags); |
864 | 861 | ||
865 | if (atomic_read(&cs->mstate) != MS_LOCKED) { | 862 | if (cs->mstate != MS_LOCKED) { |
866 | cs->ops->set_modem_ctrl(cs, 0, TIOCM_DTR|TIOCM_RTS); | 863 | cs->ops->set_modem_ctrl(cs, 0, TIOCM_DTR|TIOCM_RTS); |
867 | cs->ops->baud_rate(cs, B115200); | 864 | cs->ops->baud_rate(cs, B115200); |
868 | cs->ops->set_line_ctrl(cs, CS8); | 865 | cs->ops->set_line_ctrl(cs, CS8); |
@@ -893,10 +890,17 @@ error: | |||
893 | } | 890 | } |
894 | EXPORT_SYMBOL_GPL(gigaset_start); | 891 | EXPORT_SYMBOL_GPL(gigaset_start); |
895 | 892 | ||
896 | void gigaset_shutdown(struct cardstate *cs) | 893 | /* gigaset_shutdown |
894 | * check if a device is associated to the cardstate structure and stop it | ||
895 | * return value: 0 if ok, -1 if no device was associated | ||
896 | */ | ||
897 | int gigaset_shutdown(struct cardstate *cs) | ||
897 | { | 898 | { |
898 | mutex_lock(&cs->mutex); | 899 | mutex_lock(&cs->mutex); |
899 | 900 | ||
901 | if (!(cs->flags & VALID_MINOR)) | ||
902 | return -1; | ||
903 | |||
900 | cs->waiting = 1; | 904 | cs->waiting = 1; |
901 | 905 | ||
902 | if (!gigaset_add_event(cs, &cs->at_state, EV_SHUTDOWN, NULL, 0, NULL)) { | 906 | if (!gigaset_add_event(cs, &cs->at_state, EV_SHUTDOWN, NULL, 0, NULL)) { |
@@ -913,6 +917,7 @@ void gigaset_shutdown(struct cardstate *cs) | |||
913 | 917 | ||
914 | exit: | 918 | exit: |
915 | mutex_unlock(&cs->mutex); | 919 | mutex_unlock(&cs->mutex); |
920 | return 0; | ||
916 | } | 921 | } |
917 | EXPORT_SYMBOL_GPL(gigaset_shutdown); | 922 | EXPORT_SYMBOL_GPL(gigaset_shutdown); |
918 | 923 | ||
@@ -954,13 +959,11 @@ struct cardstate *gigaset_get_cs_by_id(int id) | |||
954 | list_for_each_entry(drv, &drivers, list) { | 959 | list_for_each_entry(drv, &drivers, list) { |
955 | spin_lock(&drv->lock); | 960 | spin_lock(&drv->lock); |
956 | for (i = 0; i < drv->minors; ++i) { | 961 | for (i = 0; i < drv->minors; ++i) { |
957 | if (drv->flags[i] & VALID_ID) { | 962 | cs = drv->cs + i; |
958 | cs = drv->cs + i; | 963 | if ((cs->flags & VALID_ID) && cs->myid == id) { |
959 | if (cs->myid == id) | 964 | ret = cs; |
960 | ret = cs; | ||
961 | } | ||
962 | if (ret) | ||
963 | break; | 965 | break; |
966 | } | ||
964 | } | 967 | } |
965 | spin_unlock(&drv->lock); | 968 | spin_unlock(&drv->lock); |
966 | if (ret) | 969 | if (ret) |
@@ -983,10 +986,9 @@ void gigaset_debugdrivers(void) | |||
983 | spin_lock(&drv->lock); | 986 | spin_lock(&drv->lock); |
984 | for (i = 0; i < drv->minors; ++i) { | 987 | for (i = 0; i < drv->minors; ++i) { |
985 | gig_dbg(DEBUG_DRIVER, " index %u", i); | 988 | gig_dbg(DEBUG_DRIVER, " index %u", i); |
986 | gig_dbg(DEBUG_DRIVER, " flags 0x%02x", | ||
987 | drv->flags[i]); | ||
988 | cs = drv->cs + i; | 989 | cs = drv->cs + i; |
989 | gig_dbg(DEBUG_DRIVER, " cardstate %p", cs); | 990 | gig_dbg(DEBUG_DRIVER, " cardstate %p", cs); |
991 | gig_dbg(DEBUG_DRIVER, " flags 0x%02x", cs->flags); | ||
990 | gig_dbg(DEBUG_DRIVER, " minor_index %u", | 992 | gig_dbg(DEBUG_DRIVER, " minor_index %u", |
991 | cs->minor_index); | 993 | cs->minor_index); |
992 | gig_dbg(DEBUG_DRIVER, " driver %p", cs->driver); | 994 | gig_dbg(DEBUG_DRIVER, " driver %p", cs->driver); |
@@ -1010,7 +1012,7 @@ static struct cardstate *gigaset_get_cs_by_minor(unsigned minor) | |||
1010 | continue; | 1012 | continue; |
1011 | index = minor - drv->minor; | 1013 | index = minor - drv->minor; |
1012 | spin_lock(&drv->lock); | 1014 | spin_lock(&drv->lock); |
1013 | if (drv->flags[index] & VALID_MINOR) | 1015 | if (drv->cs[index].flags & VALID_MINOR) |
1014 | ret = drv->cs + index; | 1016 | ret = drv->cs + index; |
1015 | spin_unlock(&drv->lock); | 1017 | spin_unlock(&drv->lock); |
1016 | if (ret) | 1018 | if (ret) |
@@ -1038,7 +1040,6 @@ void gigaset_freedriver(struct gigaset_driver *drv) | |||
1038 | gigaset_if_freedriver(drv); | 1040 | gigaset_if_freedriver(drv); |
1039 | 1041 | ||
1040 | kfree(drv->cs); | 1042 | kfree(drv->cs); |
1041 | kfree(drv->flags); | ||
1042 | kfree(drv); | 1043 | kfree(drv); |
1043 | } | 1044 | } |
1044 | EXPORT_SYMBOL_GPL(gigaset_freedriver); | 1045 | EXPORT_SYMBOL_GPL(gigaset_freedriver); |
@@ -1080,12 +1081,8 @@ struct gigaset_driver *gigaset_initdriver(unsigned minor, unsigned minors, | |||
1080 | if (!drv->cs) | 1081 | if (!drv->cs) |
1081 | goto error; | 1082 | goto error; |
1082 | 1083 | ||
1083 | drv->flags = kmalloc(minors * sizeof *drv->flags, GFP_KERNEL); | ||
1084 | if (!drv->flags) | ||
1085 | goto error; | ||
1086 | |||
1087 | for (i = 0; i < minors; ++i) { | 1084 | for (i = 0; i < minors; ++i) { |
1088 | drv->flags[i] = 0; | 1085 | drv->cs[i].flags = 0; |
1089 | drv->cs[i].driver = drv; | 1086 | drv->cs[i].driver = drv; |
1090 | drv->cs[i].ops = drv->ops; | 1087 | drv->cs[i].ops = drv->ops; |
1091 | drv->cs[i].minor_index = i; | 1088 | drv->cs[i].minor_index = i; |
@@ -1106,53 +1103,9 @@ error: | |||
1106 | } | 1103 | } |
1107 | EXPORT_SYMBOL_GPL(gigaset_initdriver); | 1104 | EXPORT_SYMBOL_GPL(gigaset_initdriver); |
1108 | 1105 | ||
1109 | /* For drivers without fixed assignment device<->cardstate (usb) */ | ||
1110 | struct cardstate *gigaset_getunassignedcs(struct gigaset_driver *drv) | ||
1111 | { | ||
1112 | unsigned long flags; | ||
1113 | struct cardstate *cs = NULL; | ||
1114 | unsigned i; | ||
1115 | |||
1116 | spin_lock_irqsave(&drv->lock, flags); | ||
1117 | if (drv->blocked) | ||
1118 | goto exit; | ||
1119 | for (i = 0; i < drv->minors; ++i) { | ||
1120 | if ((drv->flags[i] & VALID_MINOR) && | ||
1121 | !(drv->flags[i] & ASSIGNED)) { | ||
1122 | drv->flags[i] |= ASSIGNED; | ||
1123 | cs = drv->cs + i; | ||
1124 | break; | ||
1125 | } | ||
1126 | } | ||
1127 | exit: | ||
1128 | spin_unlock_irqrestore(&drv->lock, flags); | ||
1129 | return cs; | ||
1130 | } | ||
1131 | EXPORT_SYMBOL_GPL(gigaset_getunassignedcs); | ||
1132 | |||
1133 | void gigaset_unassign(struct cardstate *cs) | ||
1134 | { | ||
1135 | unsigned long flags; | ||
1136 | unsigned *minor_flags; | ||
1137 | struct gigaset_driver *drv; | ||
1138 | |||
1139 | if (!cs) | ||
1140 | return; | ||
1141 | drv = cs->driver; | ||
1142 | spin_lock_irqsave(&drv->lock, flags); | ||
1143 | minor_flags = drv->flags + cs->minor_index; | ||
1144 | if (*minor_flags & VALID_MINOR) | ||
1145 | *minor_flags &= ~ASSIGNED; | ||
1146 | spin_unlock_irqrestore(&drv->lock, flags); | ||
1147 | } | ||
1148 | EXPORT_SYMBOL_GPL(gigaset_unassign); | ||
1149 | |||
1150 | void gigaset_blockdriver(struct gigaset_driver *drv) | 1106 | void gigaset_blockdriver(struct gigaset_driver *drv) |
1151 | { | 1107 | { |
1152 | unsigned long flags; | ||
1153 | spin_lock_irqsave(&drv->lock, flags); | ||
1154 | drv->blocked = 1; | 1108 | drv->blocked = 1; |
1155 | spin_unlock_irqrestore(&drv->lock, flags); | ||
1156 | } | 1109 | } |
1157 | EXPORT_SYMBOL_GPL(gigaset_blockdriver); | 1110 | EXPORT_SYMBOL_GPL(gigaset_blockdriver); |
1158 | 1111 | ||
diff --git a/drivers/isdn/gigaset/ev-layer.c b/drivers/isdn/gigaset/ev-layer.c index cec1ef342fcc..5cbf64d850ee 100644 --- a/drivers/isdn/gigaset/ev-layer.c +++ b/drivers/isdn/gigaset/ev-layer.c | |||
@@ -735,7 +735,7 @@ static void disconnect(struct at_state_t **at_state_p) | |||
735 | /* revert to selected idle mode */ | 735 | /* revert to selected idle mode */ |
736 | if (!cs->cidmode) { | 736 | if (!cs->cidmode) { |
737 | cs->at_state.pending_commands |= PC_UMMODE; | 737 | cs->at_state.pending_commands |= PC_UMMODE; |
738 | atomic_set(&cs->commands_pending, 1); //FIXME | 738 | cs->commands_pending = 1; |
739 | gig_dbg(DEBUG_CMD, "Scheduling PC_UMMODE"); | 739 | gig_dbg(DEBUG_CMD, "Scheduling PC_UMMODE"); |
740 | } | 740 | } |
741 | spin_unlock_irqrestore(&cs->lock, flags); | 741 | spin_unlock_irqrestore(&cs->lock, flags); |
@@ -793,15 +793,15 @@ static void init_failed(struct cardstate *cs, int mode) | |||
793 | struct at_state_t *at_state; | 793 | struct at_state_t *at_state; |
794 | 794 | ||
795 | cs->at_state.pending_commands &= ~PC_INIT; | 795 | cs->at_state.pending_commands &= ~PC_INIT; |
796 | atomic_set(&cs->mode, mode); | 796 | cs->mode = mode; |
797 | atomic_set(&cs->mstate, MS_UNINITIALIZED); | 797 | cs->mstate = MS_UNINITIALIZED; |
798 | gigaset_free_channels(cs); | 798 | gigaset_free_channels(cs); |
799 | for (i = 0; i < cs->channels; ++i) { | 799 | for (i = 0; i < cs->channels; ++i) { |
800 | at_state = &cs->bcs[i].at_state; | 800 | at_state = &cs->bcs[i].at_state; |
801 | if (at_state->pending_commands & PC_CID) { | 801 | if (at_state->pending_commands & PC_CID) { |
802 | at_state->pending_commands &= ~PC_CID; | 802 | at_state->pending_commands &= ~PC_CID; |
803 | at_state->pending_commands |= PC_NOCID; | 803 | at_state->pending_commands |= PC_NOCID; |
804 | atomic_set(&cs->commands_pending, 1); | 804 | cs->commands_pending = 1; |
805 | } | 805 | } |
806 | } | 806 | } |
807 | } | 807 | } |
@@ -812,11 +812,11 @@ static void schedule_init(struct cardstate *cs, int state) | |||
812 | gig_dbg(DEBUG_CMD, "not scheduling PC_INIT again"); | 812 | gig_dbg(DEBUG_CMD, "not scheduling PC_INIT again"); |
813 | return; | 813 | return; |
814 | } | 814 | } |
815 | atomic_set(&cs->mstate, state); | 815 | cs->mstate = state; |
816 | atomic_set(&cs->mode, M_UNKNOWN); | 816 | cs->mode = M_UNKNOWN; |
817 | gigaset_block_channels(cs); | 817 | gigaset_block_channels(cs); |
818 | cs->at_state.pending_commands |= PC_INIT; | 818 | cs->at_state.pending_commands |= PC_INIT; |
819 | atomic_set(&cs->commands_pending, 1); | 819 | cs->commands_pending = 1; |
820 | gig_dbg(DEBUG_CMD, "Scheduling PC_INIT"); | 820 | gig_dbg(DEBUG_CMD, "Scheduling PC_INIT"); |
821 | } | 821 | } |
822 | 822 | ||
@@ -953,13 +953,13 @@ static void start_dial(struct at_state_t *at_state, void *data, unsigned seq_ind | |||
953 | 953 | ||
954 | at_state->pending_commands |= PC_CID; | 954 | at_state->pending_commands |= PC_CID; |
955 | gig_dbg(DEBUG_CMD, "Scheduling PC_CID"); | 955 | gig_dbg(DEBUG_CMD, "Scheduling PC_CID"); |
956 | atomic_set(&cs->commands_pending, 1); | 956 | cs->commands_pending = 1; |
957 | return; | 957 | return; |
958 | 958 | ||
959 | error: | 959 | error: |
960 | at_state->pending_commands |= PC_NOCID; | 960 | at_state->pending_commands |= PC_NOCID; |
961 | gig_dbg(DEBUG_CMD, "Scheduling PC_NOCID"); | 961 | gig_dbg(DEBUG_CMD, "Scheduling PC_NOCID"); |
962 | atomic_set(&cs->commands_pending, 1); | 962 | cs->commands_pending = 1; |
963 | return; | 963 | return; |
964 | } | 964 | } |
965 | 965 | ||
@@ -973,12 +973,12 @@ static void start_accept(struct at_state_t *at_state) | |||
973 | if (retval == 0) { | 973 | if (retval == 0) { |
974 | at_state->pending_commands |= PC_ACCEPT; | 974 | at_state->pending_commands |= PC_ACCEPT; |
975 | gig_dbg(DEBUG_CMD, "Scheduling PC_ACCEPT"); | 975 | gig_dbg(DEBUG_CMD, "Scheduling PC_ACCEPT"); |
976 | atomic_set(&cs->commands_pending, 1); | 976 | cs->commands_pending = 1; |
977 | } else { | 977 | } else { |
978 | //FIXME | 978 | /* error reset */ |
979 | at_state->pending_commands |= PC_HUP; | 979 | at_state->pending_commands |= PC_HUP; |
980 | gig_dbg(DEBUG_CMD, "Scheduling PC_HUP"); | 980 | gig_dbg(DEBUG_CMD, "Scheduling PC_HUP"); |
981 | atomic_set(&cs->commands_pending, 1); | 981 | cs->commands_pending = 1; |
982 | } | 982 | } |
983 | } | 983 | } |
984 | 984 | ||
@@ -986,7 +986,7 @@ static void do_start(struct cardstate *cs) | |||
986 | { | 986 | { |
987 | gigaset_free_channels(cs); | 987 | gigaset_free_channels(cs); |
988 | 988 | ||
989 | if (atomic_read(&cs->mstate) != MS_LOCKED) | 989 | if (cs->mstate != MS_LOCKED) |
990 | schedule_init(cs, MS_INIT); | 990 | schedule_init(cs, MS_INIT); |
991 | 991 | ||
992 | cs->isdn_up = 1; | 992 | cs->isdn_up = 1; |
@@ -1000,9 +1000,9 @@ static void do_start(struct cardstate *cs) | |||
1000 | 1000 | ||
1001 | static void finish_shutdown(struct cardstate *cs) | 1001 | static void finish_shutdown(struct cardstate *cs) |
1002 | { | 1002 | { |
1003 | if (atomic_read(&cs->mstate) != MS_LOCKED) { | 1003 | if (cs->mstate != MS_LOCKED) { |
1004 | atomic_set(&cs->mstate, MS_UNINITIALIZED); | 1004 | cs->mstate = MS_UNINITIALIZED; |
1005 | atomic_set(&cs->mode, M_UNKNOWN); | 1005 | cs->mode = M_UNKNOWN; |
1006 | } | 1006 | } |
1007 | 1007 | ||
1008 | /* Tell the LL that the device is not available .. */ | 1008 | /* Tell the LL that the device is not available .. */ |
@@ -1022,10 +1022,10 @@ static void do_shutdown(struct cardstate *cs) | |||
1022 | { | 1022 | { |
1023 | gigaset_block_channels(cs); | 1023 | gigaset_block_channels(cs); |
1024 | 1024 | ||
1025 | if (atomic_read(&cs->mstate) == MS_READY) { | 1025 | if (cs->mstate == MS_READY) { |
1026 | atomic_set(&cs->mstate, MS_SHUTDOWN); | 1026 | cs->mstate = MS_SHUTDOWN; |
1027 | cs->at_state.pending_commands |= PC_SHUTDOWN; | 1027 | cs->at_state.pending_commands |= PC_SHUTDOWN; |
1028 | atomic_set(&cs->commands_pending, 1); | 1028 | cs->commands_pending = 1; |
1029 | gig_dbg(DEBUG_CMD, "Scheduling PC_SHUTDOWN"); | 1029 | gig_dbg(DEBUG_CMD, "Scheduling PC_SHUTDOWN"); |
1030 | } else | 1030 | } else |
1031 | finish_shutdown(cs); | 1031 | finish_shutdown(cs); |
@@ -1120,7 +1120,7 @@ static void handle_icall(struct cardstate *cs, struct bc_state *bcs, | |||
1120 | * In fact it doesn't. | 1120 | * In fact it doesn't. |
1121 | */ | 1121 | */ |
1122 | at_state->pending_commands |= PC_HUP; | 1122 | at_state->pending_commands |= PC_HUP; |
1123 | atomic_set(&cs->commands_pending, 1); | 1123 | cs->commands_pending = 1; |
1124 | break; | 1124 | break; |
1125 | } | 1125 | } |
1126 | } | 1126 | } |
@@ -1130,7 +1130,7 @@ static int do_lock(struct cardstate *cs) | |||
1130 | int mode; | 1130 | int mode; |
1131 | int i; | 1131 | int i; |
1132 | 1132 | ||
1133 | switch (atomic_read(&cs->mstate)) { | 1133 | switch (cs->mstate) { |
1134 | case MS_UNINITIALIZED: | 1134 | case MS_UNINITIALIZED: |
1135 | case MS_READY: | 1135 | case MS_READY: |
1136 | if (cs->cur_at_seq || !list_empty(&cs->temp_at_states) || | 1136 | if (cs->cur_at_seq || !list_empty(&cs->temp_at_states) || |
@@ -1152,20 +1152,20 @@ static int do_lock(struct cardstate *cs) | |||
1152 | return -EBUSY; | 1152 | return -EBUSY; |
1153 | } | 1153 | } |
1154 | 1154 | ||
1155 | mode = atomic_read(&cs->mode); | 1155 | mode = cs->mode; |
1156 | atomic_set(&cs->mstate, MS_LOCKED); | 1156 | cs->mstate = MS_LOCKED; |
1157 | atomic_set(&cs->mode, M_UNKNOWN); | 1157 | cs->mode = M_UNKNOWN; |
1158 | 1158 | ||
1159 | return mode; | 1159 | return mode; |
1160 | } | 1160 | } |
1161 | 1161 | ||
1162 | static int do_unlock(struct cardstate *cs) | 1162 | static int do_unlock(struct cardstate *cs) |
1163 | { | 1163 | { |
1164 | if (atomic_read(&cs->mstate) != MS_LOCKED) | 1164 | if (cs->mstate != MS_LOCKED) |
1165 | return -EINVAL; | 1165 | return -EINVAL; |
1166 | 1166 | ||
1167 | atomic_set(&cs->mstate, MS_UNINITIALIZED); | 1167 | cs->mstate = MS_UNINITIALIZED; |
1168 | atomic_set(&cs->mode, M_UNKNOWN); | 1168 | cs->mode = M_UNKNOWN; |
1169 | gigaset_free_channels(cs); | 1169 | gigaset_free_channels(cs); |
1170 | if (cs->connected) | 1170 | if (cs->connected) |
1171 | schedule_init(cs, MS_INIT); | 1171 | schedule_init(cs, MS_INIT); |
@@ -1198,17 +1198,17 @@ static void do_action(int action, struct cardstate *cs, | |||
1198 | case ACT_INIT: | 1198 | case ACT_INIT: |
1199 | cs->at_state.pending_commands &= ~PC_INIT; | 1199 | cs->at_state.pending_commands &= ~PC_INIT; |
1200 | cs->cur_at_seq = SEQ_NONE; | 1200 | cs->cur_at_seq = SEQ_NONE; |
1201 | atomic_set(&cs->mode, M_UNIMODEM); | 1201 | cs->mode = M_UNIMODEM; |
1202 | spin_lock_irqsave(&cs->lock, flags); | 1202 | spin_lock_irqsave(&cs->lock, flags); |
1203 | if (!cs->cidmode) { | 1203 | if (!cs->cidmode) { |
1204 | spin_unlock_irqrestore(&cs->lock, flags); | 1204 | spin_unlock_irqrestore(&cs->lock, flags); |
1205 | gigaset_free_channels(cs); | 1205 | gigaset_free_channels(cs); |
1206 | atomic_set(&cs->mstate, MS_READY); | 1206 | cs->mstate = MS_READY; |
1207 | break; | 1207 | break; |
1208 | } | 1208 | } |
1209 | spin_unlock_irqrestore(&cs->lock, flags); | 1209 | spin_unlock_irqrestore(&cs->lock, flags); |
1210 | cs->at_state.pending_commands |= PC_CIDMODE; | 1210 | cs->at_state.pending_commands |= PC_CIDMODE; |
1211 | atomic_set(&cs->commands_pending, 1); | 1211 | cs->commands_pending = 1; |
1212 | gig_dbg(DEBUG_CMD, "Scheduling PC_CIDMODE"); | 1212 | gig_dbg(DEBUG_CMD, "Scheduling PC_CIDMODE"); |
1213 | break; | 1213 | break; |
1214 | case ACT_FAILINIT: | 1214 | case ACT_FAILINIT: |
@@ -1234,22 +1234,20 @@ static void do_action(int action, struct cardstate *cs, | |||
1234 | | INS_command; | 1234 | | INS_command; |
1235 | break; | 1235 | break; |
1236 | case ACT_CMODESET: | 1236 | case ACT_CMODESET: |
1237 | if (atomic_read(&cs->mstate) == MS_INIT || | 1237 | if (cs->mstate == MS_INIT || cs->mstate == MS_RECOVER) { |
1238 | atomic_read(&cs->mstate) == MS_RECOVER) { | ||
1239 | gigaset_free_channels(cs); | 1238 | gigaset_free_channels(cs); |
1240 | atomic_set(&cs->mstate, MS_READY); | 1239 | cs->mstate = MS_READY; |
1241 | } | 1240 | } |
1242 | atomic_set(&cs->mode, M_CID); | 1241 | cs->mode = M_CID; |
1243 | cs->cur_at_seq = SEQ_NONE; | 1242 | cs->cur_at_seq = SEQ_NONE; |
1244 | break; | 1243 | break; |
1245 | case ACT_UMODESET: | 1244 | case ACT_UMODESET: |
1246 | atomic_set(&cs->mode, M_UNIMODEM); | 1245 | cs->mode = M_UNIMODEM; |
1247 | cs->cur_at_seq = SEQ_NONE; | 1246 | cs->cur_at_seq = SEQ_NONE; |
1248 | break; | 1247 | break; |
1249 | case ACT_FAILCMODE: | 1248 | case ACT_FAILCMODE: |
1250 | cs->cur_at_seq = SEQ_NONE; | 1249 | cs->cur_at_seq = SEQ_NONE; |
1251 | if (atomic_read(&cs->mstate) == MS_INIT || | 1250 | if (cs->mstate == MS_INIT || cs->mstate == MS_RECOVER) { |
1252 | atomic_read(&cs->mstate) == MS_RECOVER) { | ||
1253 | init_failed(cs, M_UNKNOWN); | 1251 | init_failed(cs, M_UNKNOWN); |
1254 | break; | 1252 | break; |
1255 | } | 1253 | } |
@@ -1307,7 +1305,7 @@ static void do_action(int action, struct cardstate *cs, | |||
1307 | case ACT_CONNECT: | 1305 | case ACT_CONNECT: |
1308 | if (cs->onechannel) { | 1306 | if (cs->onechannel) { |
1309 | at_state->pending_commands |= PC_DLE1; | 1307 | at_state->pending_commands |= PC_DLE1; |
1310 | atomic_set(&cs->commands_pending, 1); | 1308 | cs->commands_pending = 1; |
1311 | break; | 1309 | break; |
1312 | } | 1310 | } |
1313 | bcs->chstate |= CHS_D_UP; | 1311 | bcs->chstate |= CHS_D_UP; |
@@ -1333,7 +1331,7 @@ static void do_action(int action, struct cardstate *cs, | |||
1333 | * DLE only used for M10x with one B channel. | 1331 | * DLE only used for M10x with one B channel. |
1334 | */ | 1332 | */ |
1335 | at_state->pending_commands |= PC_DLE0; | 1333 | at_state->pending_commands |= PC_DLE0; |
1336 | atomic_set(&cs->commands_pending, 1); | 1334 | cs->commands_pending = 1; |
1337 | } else | 1335 | } else |
1338 | disconnect(p_at_state); | 1336 | disconnect(p_at_state); |
1339 | break; | 1337 | break; |
@@ -1369,7 +1367,7 @@ static void do_action(int action, struct cardstate *cs, | |||
1369 | "Could not enter DLE mode. Trying to hang up.\n"); | 1367 | "Could not enter DLE mode. Trying to hang up.\n"); |
1370 | channel = cs->curchannel; | 1368 | channel = cs->curchannel; |
1371 | cs->bcs[channel].at_state.pending_commands |= PC_HUP; | 1369 | cs->bcs[channel].at_state.pending_commands |= PC_HUP; |
1372 | atomic_set(&cs->commands_pending, 1); | 1370 | cs->commands_pending = 1; |
1373 | break; | 1371 | break; |
1374 | 1372 | ||
1375 | case ACT_CID: /* got cid; start dialing */ | 1373 | case ACT_CID: /* got cid; start dialing */ |
@@ -1379,7 +1377,7 @@ static void do_action(int action, struct cardstate *cs, | |||
1379 | cs->bcs[channel].at_state.cid = ev->parameter; | 1377 | cs->bcs[channel].at_state.cid = ev->parameter; |
1380 | cs->bcs[channel].at_state.pending_commands |= | 1378 | cs->bcs[channel].at_state.pending_commands |= |
1381 | PC_DIAL; | 1379 | PC_DIAL; |
1382 | atomic_set(&cs->commands_pending, 1); | 1380 | cs->commands_pending = 1; |
1383 | break; | 1381 | break; |
1384 | } | 1382 | } |
1385 | /* fall through */ | 1383 | /* fall through */ |
@@ -1411,14 +1409,14 @@ static void do_action(int action, struct cardstate *cs, | |||
1411 | case ACT_ABORTDIAL: /* error/timeout during dial preparation */ | 1409 | case ACT_ABORTDIAL: /* error/timeout during dial preparation */ |
1412 | cs->cur_at_seq = SEQ_NONE; | 1410 | cs->cur_at_seq = SEQ_NONE; |
1413 | at_state->pending_commands |= PC_HUP; | 1411 | at_state->pending_commands |= PC_HUP; |
1414 | atomic_set(&cs->commands_pending, 1); | 1412 | cs->commands_pending = 1; |
1415 | break; | 1413 | break; |
1416 | 1414 | ||
1417 | case ACT_REMOTEREJECT: /* DISCONNECT_IND after dialling */ | 1415 | case ACT_REMOTEREJECT: /* DISCONNECT_IND after dialling */ |
1418 | case ACT_CONNTIMEOUT: /* timeout waiting for ZSAU=ACTIVE */ | 1416 | case ACT_CONNTIMEOUT: /* timeout waiting for ZSAU=ACTIVE */ |
1419 | case ACT_REMOTEHUP: /* DISCONNECT_IND with established connection */ | 1417 | case ACT_REMOTEHUP: /* DISCONNECT_IND with established connection */ |
1420 | at_state->pending_commands |= PC_HUP; | 1418 | at_state->pending_commands |= PC_HUP; |
1421 | atomic_set(&cs->commands_pending, 1); | 1419 | cs->commands_pending = 1; |
1422 | break; | 1420 | break; |
1423 | case ACT_GETSTRING: /* warning: RING, ZDLE, ... | 1421 | case ACT_GETSTRING: /* warning: RING, ZDLE, ... |
1424 | are not handled properly anymore */ | 1422 | are not handled properly anymore */ |
@@ -1515,7 +1513,7 @@ static void do_action(int action, struct cardstate *cs, | |||
1515 | break; | 1513 | break; |
1516 | case ACT_HUP: | 1514 | case ACT_HUP: |
1517 | at_state->pending_commands |= PC_HUP; | 1515 | at_state->pending_commands |= PC_HUP; |
1518 | atomic_set(&cs->commands_pending, 1); | 1516 | cs->commands_pending = 1; |
1519 | gig_dbg(DEBUG_CMD, "Scheduling PC_HUP"); | 1517 | gig_dbg(DEBUG_CMD, "Scheduling PC_HUP"); |
1520 | break; | 1518 | break; |
1521 | 1519 | ||
@@ -1558,7 +1556,7 @@ static void do_action(int action, struct cardstate *cs, | |||
1558 | cs->at_state.pending_commands |= PC_UMMODE; | 1556 | cs->at_state.pending_commands |= PC_UMMODE; |
1559 | gig_dbg(DEBUG_CMD, "Scheduling PC_UMMODE"); | 1557 | gig_dbg(DEBUG_CMD, "Scheduling PC_UMMODE"); |
1560 | } | 1558 | } |
1561 | atomic_set(&cs->commands_pending, 1); | 1559 | cs->commands_pending = 1; |
1562 | } | 1560 | } |
1563 | spin_unlock_irqrestore(&cs->lock, flags); | 1561 | spin_unlock_irqrestore(&cs->lock, flags); |
1564 | cs->waiting = 0; | 1562 | cs->waiting = 0; |
@@ -1741,7 +1739,7 @@ static void process_command_flags(struct cardstate *cs) | |||
1741 | int sequence; | 1739 | int sequence; |
1742 | unsigned long flags; | 1740 | unsigned long flags; |
1743 | 1741 | ||
1744 | atomic_set(&cs->commands_pending, 0); | 1742 | cs->commands_pending = 0; |
1745 | 1743 | ||
1746 | if (cs->cur_at_seq) { | 1744 | if (cs->cur_at_seq) { |
1747 | gig_dbg(DEBUG_CMD, "not searching scheduled commands: busy"); | 1745 | gig_dbg(DEBUG_CMD, "not searching scheduled commands: busy"); |
@@ -1779,7 +1777,7 @@ static void process_command_flags(struct cardstate *cs) | |||
1779 | ~(PC_DLE1 | PC_ACCEPT | PC_DIAL); | 1777 | ~(PC_DLE1 | PC_ACCEPT | PC_DIAL); |
1780 | if (at_state->cid > 0) | 1778 | if (at_state->cid > 0) |
1781 | at_state->pending_commands |= PC_HUP; | 1779 | at_state->pending_commands |= PC_HUP; |
1782 | if (atomic_read(&cs->mstate) == MS_RECOVER) { | 1780 | if (cs->mstate == MS_RECOVER) { |
1783 | if (at_state->pending_commands & PC_CID) { | 1781 | if (at_state->pending_commands & PC_CID) { |
1784 | at_state->pending_commands |= PC_NOCID; | 1782 | at_state->pending_commands |= PC_NOCID; |
1785 | at_state->pending_commands &= ~PC_CID; | 1783 | at_state->pending_commands &= ~PC_CID; |
@@ -1793,7 +1791,7 @@ static void process_command_flags(struct cardstate *cs) | |||
1793 | if (cs->at_state.pending_commands == PC_UMMODE | 1791 | if (cs->at_state.pending_commands == PC_UMMODE |
1794 | && !cs->cidmode | 1792 | && !cs->cidmode |
1795 | && list_empty(&cs->temp_at_states) | 1793 | && list_empty(&cs->temp_at_states) |
1796 | && atomic_read(&cs->mode) == M_CID) { | 1794 | && cs->mode == M_CID) { |
1797 | sequence = SEQ_UMMODE; | 1795 | sequence = SEQ_UMMODE; |
1798 | at_state = &cs->at_state; | 1796 | at_state = &cs->at_state; |
1799 | for (i = 0; i < cs->channels; ++i) { | 1797 | for (i = 0; i < cs->channels; ++i) { |
@@ -1860,7 +1858,7 @@ static void process_command_flags(struct cardstate *cs) | |||
1860 | } | 1858 | } |
1861 | if (cs->at_state.pending_commands & PC_CIDMODE) { | 1859 | if (cs->at_state.pending_commands & PC_CIDMODE) { |
1862 | cs->at_state.pending_commands &= ~PC_CIDMODE; | 1860 | cs->at_state.pending_commands &= ~PC_CIDMODE; |
1863 | if (atomic_read(&cs->mode) == M_UNIMODEM) { | 1861 | if (cs->mode == M_UNIMODEM) { |
1864 | cs->retry_count = 1; | 1862 | cs->retry_count = 1; |
1865 | schedule_sequence(cs, &cs->at_state, SEQ_CIDMODE); | 1863 | schedule_sequence(cs, &cs->at_state, SEQ_CIDMODE); |
1866 | return; | 1864 | return; |
@@ -1886,11 +1884,11 @@ static void process_command_flags(struct cardstate *cs) | |||
1886 | return; | 1884 | return; |
1887 | } | 1885 | } |
1888 | if (bcs->at_state.pending_commands & PC_CID) { | 1886 | if (bcs->at_state.pending_commands & PC_CID) { |
1889 | switch (atomic_read(&cs->mode)) { | 1887 | switch (cs->mode) { |
1890 | case M_UNIMODEM: | 1888 | case M_UNIMODEM: |
1891 | cs->at_state.pending_commands |= PC_CIDMODE; | 1889 | cs->at_state.pending_commands |= PC_CIDMODE; |
1892 | gig_dbg(DEBUG_CMD, "Scheduling PC_CIDMODE"); | 1890 | gig_dbg(DEBUG_CMD, "Scheduling PC_CIDMODE"); |
1893 | atomic_set(&cs->commands_pending, 1); | 1891 | cs->commands_pending = 1; |
1894 | return; | 1892 | return; |
1895 | #ifdef GIG_MAYINITONDIAL | 1893 | #ifdef GIG_MAYINITONDIAL |
1896 | case M_UNKNOWN: | 1894 | case M_UNKNOWN: |
@@ -1926,7 +1924,7 @@ static void process_events(struct cardstate *cs) | |||
1926 | for (i = 0; i < 2 * MAX_EVENTS; ++i) { | 1924 | for (i = 0; i < 2 * MAX_EVENTS; ++i) { |
1927 | tail = cs->ev_tail; | 1925 | tail = cs->ev_tail; |
1928 | if (tail == head) { | 1926 | if (tail == head) { |
1929 | if (!check_flags && !atomic_read(&cs->commands_pending)) | 1927 | if (!check_flags && !cs->commands_pending) |
1930 | break; | 1928 | break; |
1931 | check_flags = 0; | 1929 | check_flags = 0; |
1932 | spin_unlock_irqrestore(&cs->ev_lock, flags); | 1930 | spin_unlock_irqrestore(&cs->ev_lock, flags); |
@@ -1934,7 +1932,7 @@ static void process_events(struct cardstate *cs) | |||
1934 | spin_lock_irqsave(&cs->ev_lock, flags); | 1932 | spin_lock_irqsave(&cs->ev_lock, flags); |
1935 | tail = cs->ev_tail; | 1933 | tail = cs->ev_tail; |
1936 | if (tail == head) { | 1934 | if (tail == head) { |
1937 | if (!atomic_read(&cs->commands_pending)) | 1935 | if (!cs->commands_pending) |
1938 | break; | 1936 | break; |
1939 | continue; | 1937 | continue; |
1940 | } | 1938 | } |
@@ -1971,7 +1969,7 @@ void gigaset_handle_event(unsigned long data) | |||
1971 | struct cardstate *cs = (struct cardstate *) data; | 1969 | struct cardstate *cs = (struct cardstate *) data; |
1972 | 1970 | ||
1973 | /* handle incoming data on control/common channel */ | 1971 | /* handle incoming data on control/common channel */ |
1974 | if (atomic_read(&cs->inbuf->head) != atomic_read(&cs->inbuf->tail)) { | 1972 | if (cs->inbuf->head != cs->inbuf->tail) { |
1975 | gig_dbg(DEBUG_INTR, "processing new data"); | 1973 | gig_dbg(DEBUG_INTR, "processing new data"); |
1976 | cs->ops->handle_input(cs->inbuf); | 1974 | cs->ops->handle_input(cs->inbuf); |
1977 | } | 1975 | } |
diff --git a/drivers/isdn/gigaset/gigaset.h b/drivers/isdn/gigaset/gigaset.h index 02bdaf22d7ea..f365993161fc 100644 --- a/drivers/isdn/gigaset/gigaset.h +++ b/drivers/isdn/gigaset/gigaset.h | |||
@@ -70,22 +70,13 @@ | |||
70 | 70 | ||
71 | extern int gigaset_debuglevel; /* "needs" cast to (enum debuglevel) */ | 71 | extern int gigaset_debuglevel; /* "needs" cast to (enum debuglevel) */ |
72 | 72 | ||
73 | /* any combination of these can be given with the 'debug=' parameter to insmod, | 73 | /* debug flags, combine by adding/bitwise OR */ |
74 | * e.g. 'insmod usb_gigaset.o debug=0x2c' will set DEBUG_OPEN, DEBUG_CMD and | ||
75 | * DEBUG_INTR. | ||
76 | */ | ||
77 | enum debuglevel { | 74 | enum debuglevel { |
78 | DEBUG_REG = 0x0002, /* serial port I/O register operations */ | 75 | DEBUG_INTR = 0x00008, /* interrupt processing */ |
79 | DEBUG_OPEN = 0x0004, /* open/close serial port */ | ||
80 | DEBUG_INTR = 0x0008, /* interrupt processing */ | ||
81 | DEBUG_INTR_DUMP = 0x0010, /* Activating hexdump debug output on | ||
82 | interrupt requests, not available as | ||
83 | run-time option */ | ||
84 | DEBUG_CMD = 0x00020, /* sent/received LL commands */ | 76 | DEBUG_CMD = 0x00020, /* sent/received LL commands */ |
85 | DEBUG_STREAM = 0x00040, /* application data stream I/O events */ | 77 | DEBUG_STREAM = 0x00040, /* application data stream I/O events */ |
86 | DEBUG_STREAM_DUMP = 0x00080, /* application data stream content */ | 78 | DEBUG_STREAM_DUMP = 0x00080, /* application data stream content */ |
87 | DEBUG_LLDATA = 0x00100, /* sent/received LL data */ | 79 | DEBUG_LLDATA = 0x00100, /* sent/received LL data */ |
88 | DEBUG_INTR_0 = 0x00200, /* serial port interrupt processing */ | ||
89 | DEBUG_DRIVER = 0x00400, /* driver structure */ | 80 | DEBUG_DRIVER = 0x00400, /* driver structure */ |
90 | DEBUG_HDLC = 0x00800, /* M10x HDLC processing */ | 81 | DEBUG_HDLC = 0x00800, /* M10x HDLC processing */ |
91 | DEBUG_WRITE = 0x01000, /* M105 data write */ | 82 | DEBUG_WRITE = 0x01000, /* M105 data write */ |
@@ -93,7 +84,7 @@ enum debuglevel { | |||
93 | DEBUG_MCMD = 0x04000, /* COMMANDS THAT ARE SENT VERY OFTEN */ | 84 | DEBUG_MCMD = 0x04000, /* COMMANDS THAT ARE SENT VERY OFTEN */ |
94 | DEBUG_INIT = 0x08000, /* (de)allocation+initialization of data | 85 | DEBUG_INIT = 0x08000, /* (de)allocation+initialization of data |
95 | structures */ | 86 | structures */ |
96 | DEBUG_LOCK = 0x10000, /* semaphore operations */ | 87 | DEBUG_SUSPEND = 0x10000, /* suspend/resume processing */ |
97 | DEBUG_OUTPUT = 0x20000, /* output to device */ | 88 | DEBUG_OUTPUT = 0x20000, /* output to device */ |
98 | DEBUG_ISO = 0x40000, /* isochronous transfers */ | 89 | DEBUG_ISO = 0x40000, /* isochronous transfers */ |
99 | DEBUG_IF = 0x80000, /* character device operations */ | 90 | DEBUG_IF = 0x80000, /* character device operations */ |
@@ -191,6 +182,9 @@ void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg, | |||
191 | #define HD_OPEN_ATCHANNEL (0x28) // 3070 | 182 | #define HD_OPEN_ATCHANNEL (0x28) // 3070 |
192 | #define HD_CLOSE_ATCHANNEL (0x29) // 3070 | 183 | #define HD_CLOSE_ATCHANNEL (0x29) // 3070 |
193 | 184 | ||
185 | /* number of B channels supported by base driver */ | ||
186 | #define BAS_CHANNELS 2 | ||
187 | |||
194 | /* USB frames for isochronous transfer */ | 188 | /* USB frames for isochronous transfer */ |
195 | #define BAS_FRAMETIME 1 /* number of milliseconds between frames */ | 189 | #define BAS_FRAMETIME 1 /* number of milliseconds between frames */ |
196 | #define BAS_NUMFRAMES 8 /* number of frames per URB */ | 190 | #define BAS_NUMFRAMES 8 /* number of frames per URB */ |
@@ -313,7 +307,7 @@ struct inbuf_t { | |||
313 | struct bc_state *bcs; | 307 | struct bc_state *bcs; |
314 | struct cardstate *cs; | 308 | struct cardstate *cs; |
315 | int inputstate; | 309 | int inputstate; |
316 | atomic_t head, tail; | 310 | int head, tail; |
317 | unsigned char data[RBUFSIZE]; | 311 | unsigned char data[RBUFSIZE]; |
318 | }; | 312 | }; |
319 | 313 | ||
@@ -335,9 +329,9 @@ struct inbuf_t { | |||
335 | * are also filled with that value | 329 | * are also filled with that value |
336 | */ | 330 | */ |
337 | struct isowbuf_t { | 331 | struct isowbuf_t { |
338 | atomic_t read; | 332 | int read; |
339 | atomic_t nextread; | 333 | int nextread; |
340 | atomic_t write; | 334 | int write; |
341 | atomic_t writesem; | 335 | atomic_t writesem; |
342 | int wbits; | 336 | int wbits; |
343 | unsigned char data[BAS_OUTBUFSIZE + BAS_OUTBUFPAD]; | 337 | unsigned char data[BAS_OUTBUFSIZE + BAS_OUTBUFPAD]; |
@@ -350,11 +344,13 @@ struct isowbuf_t { | |||
350 | * - urb: pointer to the URB itself | 344 | * - urb: pointer to the URB itself |
351 | * - bcs: pointer to the B Channel control structure | 345 | * - bcs: pointer to the B Channel control structure |
352 | * - limit: end of write buffer area covered by this URB | 346 | * - limit: end of write buffer area covered by this URB |
347 | * - status: URB completion status | ||
353 | */ | 348 | */ |
354 | struct isow_urbctx_t { | 349 | struct isow_urbctx_t { |
355 | struct urb *urb; | 350 | struct urb *urb; |
356 | struct bc_state *bcs; | 351 | struct bc_state *bcs; |
357 | int limit; | 352 | int limit; |
353 | int status; | ||
358 | }; | 354 | }; |
359 | 355 | ||
360 | /* AT state structure | 356 | /* AT state structure |
@@ -439,14 +435,15 @@ struct cardstate { | |||
439 | unsigned minor_index; | 435 | unsigned minor_index; |
440 | struct device *dev; | 436 | struct device *dev; |
441 | struct device *tty_dev; | 437 | struct device *tty_dev; |
438 | unsigned flags; | ||
442 | 439 | ||
443 | const struct gigaset_ops *ops; | 440 | const struct gigaset_ops *ops; |
444 | 441 | ||
445 | /* Stuff to handle communication */ | 442 | /* Stuff to handle communication */ |
446 | wait_queue_head_t waitqueue; | 443 | wait_queue_head_t waitqueue; |
447 | int waiting; | 444 | int waiting; |
448 | atomic_t mode; /* see M_XXXX */ | 445 | int mode; /* see M_XXXX */ |
449 | atomic_t mstate; /* Modem state: see MS_XXXX */ | 446 | int mstate; /* Modem state: see MS_XXXX */ |
450 | /* only changed by the event layer */ | 447 | /* only changed by the event layer */ |
451 | int cmd_result; | 448 | int cmd_result; |
452 | 449 | ||
@@ -503,7 +500,7 @@ struct cardstate { | |||
503 | processed */ | 500 | processed */ |
504 | int curchannel; /* channel those commands are meant | 501 | int curchannel; /* channel those commands are meant |
505 | for */ | 502 | for */ |
506 | atomic_t commands_pending; /* flag(s) in xxx.commands_pending have | 503 | int commands_pending; /* flag(s) in xxx.commands_pending have |
507 | been set */ | 504 | been set */ |
508 | struct tasklet_struct event_tasklet; | 505 | struct tasklet_struct event_tasklet; |
509 | /* tasklet for serializing AT commands. | 506 | /* tasklet for serializing AT commands. |
@@ -543,7 +540,6 @@ struct gigaset_driver { | |||
543 | unsigned minor; | 540 | unsigned minor; |
544 | unsigned minors; | 541 | unsigned minors; |
545 | struct cardstate *cs; | 542 | struct cardstate *cs; |
546 | unsigned *flags; | ||
547 | int blocked; | 543 | int blocked; |
548 | 544 | ||
549 | const struct gigaset_ops *ops; | 545 | const struct gigaset_ops *ops; |
@@ -559,7 +555,7 @@ struct cmdbuf_t { | |||
559 | 555 | ||
560 | struct bas_bc_state { | 556 | struct bas_bc_state { |
561 | /* isochronous output state */ | 557 | /* isochronous output state */ |
562 | atomic_t running; | 558 | int running; |
563 | atomic_t corrbytes; | 559 | atomic_t corrbytes; |
564 | spinlock_t isooutlock; | 560 | spinlock_t isooutlock; |
565 | struct isow_urbctx_t isoouturbs[BAS_OUTURBS]; | 561 | struct isow_urbctx_t isoouturbs[BAS_OUTURBS]; |
@@ -574,6 +570,7 @@ struct bas_bc_state { | |||
574 | struct urb *isoinurbs[BAS_INURBS]; | 570 | struct urb *isoinurbs[BAS_INURBS]; |
575 | unsigned char isoinbuf[BAS_INBUFSIZE * BAS_INURBS]; | 571 | unsigned char isoinbuf[BAS_INBUFSIZE * BAS_INURBS]; |
576 | struct urb *isoindone; /* completed isoc read URB */ | 572 | struct urb *isoindone; /* completed isoc read URB */ |
573 | int isoinstatus; /* status of completed URB */ | ||
577 | int loststatus; /* status of dropped URB */ | 574 | int loststatus; /* status of dropped URB */ |
578 | unsigned isoinlost; /* number of bytes lost */ | 575 | unsigned isoinlost; /* number of bytes lost */ |
579 | /* state of bit unstuffing algorithm | 576 | /* state of bit unstuffing algorithm |
@@ -770,10 +767,6 @@ void gigaset_freedriver(struct gigaset_driver *drv); | |||
770 | void gigaset_debugdrivers(void); | 767 | void gigaset_debugdrivers(void); |
771 | struct cardstate *gigaset_get_cs_by_tty(struct tty_struct *tty); | 768 | struct cardstate *gigaset_get_cs_by_tty(struct tty_struct *tty); |
772 | struct cardstate *gigaset_get_cs_by_id(int id); | 769 | struct cardstate *gigaset_get_cs_by_id(int id); |
773 | |||
774 | /* For drivers without fixed assignment device<->cardstate (usb) */ | ||
775 | struct cardstate *gigaset_getunassignedcs(struct gigaset_driver *drv); | ||
776 | void gigaset_unassign(struct cardstate *cs); | ||
777 | void gigaset_blockdriver(struct gigaset_driver *drv); | 770 | void gigaset_blockdriver(struct gigaset_driver *drv); |
778 | 771 | ||
779 | /* Allocate and initialize card state. Calls hardware dependent | 772 | /* Allocate and initialize card state. Calls hardware dependent |
@@ -792,7 +785,7 @@ int gigaset_start(struct cardstate *cs); | |||
792 | void gigaset_stop(struct cardstate *cs); | 785 | void gigaset_stop(struct cardstate *cs); |
793 | 786 | ||
794 | /* Tell common.c that the driver is being unloaded. */ | 787 | /* Tell common.c that the driver is being unloaded. */ |
795 | void gigaset_shutdown(struct cardstate *cs); | 788 | int gigaset_shutdown(struct cardstate *cs); |
796 | 789 | ||
797 | /* Tell common.c that an skb has been sent. */ | 790 | /* Tell common.c that an skb has been sent. */ |
798 | void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb); | 791 | void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb); |
diff --git a/drivers/isdn/gigaset/interface.c b/drivers/isdn/gigaset/interface.c index eb50f3dab5f7..af195b07c191 100644 --- a/drivers/isdn/gigaset/interface.c +++ b/drivers/isdn/gigaset/interface.c | |||
@@ -28,12 +28,11 @@ static int if_lock(struct cardstate *cs, int *arg) | |||
28 | return -EINVAL; | 28 | return -EINVAL; |
29 | 29 | ||
30 | if (cmd < 0) { | 30 | if (cmd < 0) { |
31 | *arg = atomic_read(&cs->mstate) == MS_LOCKED; //FIXME remove? | 31 | *arg = cs->mstate == MS_LOCKED; |
32 | return 0; | 32 | return 0; |
33 | } | 33 | } |
34 | 34 | ||
35 | if (!cmd && atomic_read(&cs->mstate) == MS_LOCKED | 35 | if (!cmd && cs->mstate == MS_LOCKED && cs->connected) { |
36 | && cs->connected) { | ||
37 | cs->ops->set_modem_ctrl(cs, 0, TIOCM_DTR|TIOCM_RTS); | 36 | cs->ops->set_modem_ctrl(cs, 0, TIOCM_DTR|TIOCM_RTS); |
38 | cs->ops->baud_rate(cs, B115200); | 37 | cs->ops->baud_rate(cs, B115200); |
39 | cs->ops->set_line_ctrl(cs, CS8); | 38 | cs->ops->set_line_ctrl(cs, CS8); |
@@ -104,7 +103,7 @@ static int if_config(struct cardstate *cs, int *arg) | |||
104 | if (*arg != 1) | 103 | if (*arg != 1) |
105 | return -EINVAL; | 104 | return -EINVAL; |
106 | 105 | ||
107 | if (atomic_read(&cs->mstate) != MS_LOCKED) | 106 | if (cs->mstate != MS_LOCKED) |
108 | return -EBUSY; | 107 | return -EBUSY; |
109 | 108 | ||
110 | if (!cs->connected) { | 109 | if (!cs->connected) { |
@@ -162,7 +161,7 @@ static int if_open(struct tty_struct *tty, struct file *filp) | |||
162 | tty->driver_data = NULL; | 161 | tty->driver_data = NULL; |
163 | 162 | ||
164 | cs = gigaset_get_cs_by_tty(tty); | 163 | cs = gigaset_get_cs_by_tty(tty); |
165 | if (!cs) | 164 | if (!cs || !try_module_get(cs->driver->owner)) |
166 | return -ENODEV; | 165 | return -ENODEV; |
167 | 166 | ||
168 | if (mutex_lock_interruptible(&cs->mutex)) | 167 | if (mutex_lock_interruptible(&cs->mutex)) |
@@ -208,6 +207,8 @@ static void if_close(struct tty_struct *tty, struct file *filp) | |||
208 | } | 207 | } |
209 | 208 | ||
210 | mutex_unlock(&cs->mutex); | 209 | mutex_unlock(&cs->mutex); |
210 | |||
211 | module_put(cs->driver->owner); | ||
211 | } | 212 | } |
212 | 213 | ||
213 | static int if_ioctl(struct tty_struct *tty, struct file *file, | 214 | static int if_ioctl(struct tty_struct *tty, struct file *file, |
@@ -364,7 +365,7 @@ static int if_write(struct tty_struct *tty, const unsigned char *buf, int count) | |||
364 | 365 | ||
365 | if (!cs->open_count) | 366 | if (!cs->open_count) |
366 | warn("%s: device not opened", __func__); | 367 | warn("%s: device not opened", __func__); |
367 | else if (atomic_read(&cs->mstate) != MS_LOCKED) { | 368 | else if (cs->mstate != MS_LOCKED) { |
368 | warn("can't write to unlocked device"); | 369 | warn("can't write to unlocked device"); |
369 | retval = -EBUSY; | 370 | retval = -EBUSY; |
370 | } else if (!cs->connected) { | 371 | } else if (!cs->connected) { |
@@ -398,9 +399,9 @@ static int if_write_room(struct tty_struct *tty) | |||
398 | 399 | ||
399 | if (!cs->open_count) | 400 | if (!cs->open_count) |
400 | warn("%s: device not opened", __func__); | 401 | warn("%s: device not opened", __func__); |
401 | else if (atomic_read(&cs->mstate) != MS_LOCKED) { | 402 | else if (cs->mstate != MS_LOCKED) { |
402 | warn("can't write to unlocked device"); | 403 | warn("can't write to unlocked device"); |
403 | retval = -EBUSY; //FIXME | 404 | retval = -EBUSY; |
404 | } else if (!cs->connected) { | 405 | } else if (!cs->connected) { |
405 | gig_dbg(DEBUG_ANY, "can't write to unplugged device"); | 406 | gig_dbg(DEBUG_ANY, "can't write to unplugged device"); |
406 | retval = -EBUSY; //FIXME | 407 | retval = -EBUSY; //FIXME |
@@ -430,7 +431,7 @@ static int if_chars_in_buffer(struct tty_struct *tty) | |||
430 | 431 | ||
431 | if (!cs->open_count) | 432 | if (!cs->open_count) |
432 | warn("%s: device not opened", __func__); | 433 | warn("%s: device not opened", __func__); |
433 | else if (atomic_read(&cs->mstate) != MS_LOCKED) { | 434 | else if (cs->mstate != MS_LOCKED) { |
434 | warn("can't write to unlocked device"); | 435 | warn("can't write to unlocked device"); |
435 | retval = -EBUSY; | 436 | retval = -EBUSY; |
436 | } else if (!cs->connected) { | 437 | } else if (!cs->connected) { |
diff --git a/drivers/isdn/gigaset/isocdata.c b/drivers/isdn/gigaset/isocdata.c index e0505f238807..e30a7773f93c 100644 --- a/drivers/isdn/gigaset/isocdata.c +++ b/drivers/isdn/gigaset/isocdata.c | |||
@@ -23,9 +23,9 @@ | |||
23 | */ | 23 | */ |
24 | void gigaset_isowbuf_init(struct isowbuf_t *iwb, unsigned char idle) | 24 | void gigaset_isowbuf_init(struct isowbuf_t *iwb, unsigned char idle) |
25 | { | 25 | { |
26 | atomic_set(&iwb->read, 0); | 26 | iwb->read = 0; |
27 | atomic_set(&iwb->nextread, 0); | 27 | iwb->nextread = 0; |
28 | atomic_set(&iwb->write, 0); | 28 | iwb->write = 0; |
29 | atomic_set(&iwb->writesem, 1); | 29 | atomic_set(&iwb->writesem, 1); |
30 | iwb->wbits = 0; | 30 | iwb->wbits = 0; |
31 | iwb->idle = idle; | 31 | iwb->idle = idle; |
@@ -39,8 +39,8 @@ static inline int isowbuf_freebytes(struct isowbuf_t *iwb) | |||
39 | { | 39 | { |
40 | int read, write, freebytes; | 40 | int read, write, freebytes; |
41 | 41 | ||
42 | read = atomic_read(&iwb->read); | 42 | read = iwb->read; |
43 | write = atomic_read(&iwb->write); | 43 | write = iwb->write; |
44 | if ((freebytes = read - write) > 0) { | 44 | if ((freebytes = read - write) > 0) { |
45 | /* no wraparound: need padding space within regular area */ | 45 | /* no wraparound: need padding space within regular area */ |
46 | return freebytes - BAS_OUTBUFPAD; | 46 | return freebytes - BAS_OUTBUFPAD; |
@@ -62,7 +62,7 @@ static inline int isowbuf_poscmp(struct isowbuf_t *iwb, int a, int b) | |||
62 | int read; | 62 | int read; |
63 | if (a == b) | 63 | if (a == b) |
64 | return 0; | 64 | return 0; |
65 | read = atomic_read(&iwb->read); | 65 | read = iwb->read; |
66 | if (a < b) { | 66 | if (a < b) { |
67 | if (a < read && read <= b) | 67 | if (a < read && read <= b) |
68 | return +1; | 68 | return +1; |
@@ -91,18 +91,18 @@ static inline int isowbuf_startwrite(struct isowbuf_t *iwb) | |||
91 | #ifdef CONFIG_GIGASET_DEBUG | 91 | #ifdef CONFIG_GIGASET_DEBUG |
92 | gig_dbg(DEBUG_ISO, | 92 | gig_dbg(DEBUG_ISO, |
93 | "%s: acquired iso write semaphore, data[write]=%02x, nbits=%d", | 93 | "%s: acquired iso write semaphore, data[write]=%02x, nbits=%d", |
94 | __func__, iwb->data[atomic_read(&iwb->write)], iwb->wbits); | 94 | __func__, iwb->data[iwb->write], iwb->wbits); |
95 | #endif | 95 | #endif |
96 | return 1; | 96 | return 1; |
97 | } | 97 | } |
98 | 98 | ||
99 | /* finish writing | 99 | /* finish writing |
100 | * release the write semaphore and update the maximum buffer fill level | 100 | * release the write semaphore |
101 | * returns the current write position | 101 | * returns the current write position |
102 | */ | 102 | */ |
103 | static inline int isowbuf_donewrite(struct isowbuf_t *iwb) | 103 | static inline int isowbuf_donewrite(struct isowbuf_t *iwb) |
104 | { | 104 | { |
105 | int write = atomic_read(&iwb->write); | 105 | int write = iwb->write; |
106 | atomic_inc(&iwb->writesem); | 106 | atomic_inc(&iwb->writesem); |
107 | return write; | 107 | return write; |
108 | } | 108 | } |
@@ -116,7 +116,7 @@ static inline int isowbuf_donewrite(struct isowbuf_t *iwb) | |||
116 | */ | 116 | */ |
117 | static inline void isowbuf_putbits(struct isowbuf_t *iwb, u32 data, int nbits) | 117 | static inline void isowbuf_putbits(struct isowbuf_t *iwb, u32 data, int nbits) |
118 | { | 118 | { |
119 | int write = atomic_read(&iwb->write); | 119 | int write = iwb->write; |
120 | data <<= iwb->wbits; | 120 | data <<= iwb->wbits; |
121 | data |= iwb->data[write]; | 121 | data |= iwb->data[write]; |
122 | nbits += iwb->wbits; | 122 | nbits += iwb->wbits; |
@@ -128,7 +128,7 @@ static inline void isowbuf_putbits(struct isowbuf_t *iwb, u32 data, int nbits) | |||
128 | } | 128 | } |
129 | iwb->wbits = nbits; | 129 | iwb->wbits = nbits; |
130 | iwb->data[write] = data & 0xff; | 130 | iwb->data[write] = data & 0xff; |
131 | atomic_set(&iwb->write, write); | 131 | iwb->write = write; |
132 | } | 132 | } |
133 | 133 | ||
134 | /* put final flag on HDLC bitstream | 134 | /* put final flag on HDLC bitstream |
@@ -142,7 +142,7 @@ static inline void isowbuf_putflag(struct isowbuf_t *iwb) | |||
142 | /* add two flags, thus reliably covering one byte */ | 142 | /* add two flags, thus reliably covering one byte */ |
143 | isowbuf_putbits(iwb, 0x7e7e, 8); | 143 | isowbuf_putbits(iwb, 0x7e7e, 8); |
144 | /* recover the idle flag byte */ | 144 | /* recover the idle flag byte */ |
145 | write = atomic_read(&iwb->write); | 145 | write = iwb->write; |
146 | iwb->idle = iwb->data[write]; | 146 | iwb->idle = iwb->data[write]; |
147 | gig_dbg(DEBUG_ISO, "idle fill byte %02x", iwb->idle); | 147 | gig_dbg(DEBUG_ISO, "idle fill byte %02x", iwb->idle); |
148 | /* mask extraneous bits in buffer */ | 148 | /* mask extraneous bits in buffer */ |
@@ -160,8 +160,8 @@ int gigaset_isowbuf_getbytes(struct isowbuf_t *iwb, int size) | |||
160 | int read, write, limit, src, dst; | 160 | int read, write, limit, src, dst; |
161 | unsigned char pbyte; | 161 | unsigned char pbyte; |
162 | 162 | ||
163 | read = atomic_read(&iwb->nextread); | 163 | read = iwb->nextread; |
164 | write = atomic_read(&iwb->write); | 164 | write = iwb->write; |
165 | if (likely(read == write)) { | 165 | if (likely(read == write)) { |
166 | /* return idle frame */ | 166 | /* return idle frame */ |
167 | return read < BAS_OUTBUFPAD ? | 167 | return read < BAS_OUTBUFPAD ? |
@@ -176,7 +176,7 @@ int gigaset_isowbuf_getbytes(struct isowbuf_t *iwb, int size) | |||
176 | err("invalid size %d", size); | 176 | err("invalid size %d", size); |
177 | return -EINVAL; | 177 | return -EINVAL; |
178 | } | 178 | } |
179 | src = atomic_read(&iwb->read); | 179 | src = iwb->read; |
180 | if (unlikely(limit > BAS_OUTBUFSIZE + BAS_OUTBUFPAD || | 180 | if (unlikely(limit > BAS_OUTBUFSIZE + BAS_OUTBUFPAD || |
181 | (read < src && limit >= src))) { | 181 | (read < src && limit >= src))) { |
182 | err("isoc write buffer frame reservation violated"); | 182 | err("isoc write buffer frame reservation violated"); |
@@ -191,7 +191,8 @@ int gigaset_isowbuf_getbytes(struct isowbuf_t *iwb, int size) | |||
191 | if (!isowbuf_startwrite(iwb)) | 191 | if (!isowbuf_startwrite(iwb)) |
192 | return -EBUSY; | 192 | return -EBUSY; |
193 | /* write position could have changed */ | 193 | /* write position could have changed */ |
194 | if (limit >= (write = atomic_read(&iwb->write))) { | 194 | write = iwb->write; |
195 | if (limit >= write) { | ||
195 | pbyte = iwb->data[write]; /* save | 196 | pbyte = iwb->data[write]; /* save |
196 | partial byte */ | 197 | partial byte */ |
197 | limit = write + BAS_OUTBUFPAD; | 198 | limit = write + BAS_OUTBUFPAD; |
@@ -213,7 +214,7 @@ int gigaset_isowbuf_getbytes(struct isowbuf_t *iwb, int size) | |||
213 | __func__, pbyte, limit); | 214 | __func__, pbyte, limit); |
214 | iwb->data[limit] = pbyte; /* restore | 215 | iwb->data[limit] = pbyte; /* restore |
215 | partial byte */ | 216 | partial byte */ |
216 | atomic_set(&iwb->write, limit); | 217 | iwb->write = limit; |
217 | } | 218 | } |
218 | isowbuf_donewrite(iwb); | 219 | isowbuf_donewrite(iwb); |
219 | } | 220 | } |
@@ -233,7 +234,7 @@ int gigaset_isowbuf_getbytes(struct isowbuf_t *iwb, int size) | |||
233 | limit = src; | 234 | limit = src; |
234 | } | 235 | } |
235 | } | 236 | } |
236 | atomic_set(&iwb->nextread, limit); | 237 | iwb->nextread = limit; |
237 | return read; | 238 | return read; |
238 | } | 239 | } |
239 | 240 | ||
@@ -477,7 +478,7 @@ static inline int trans_buildframe(struct isowbuf_t *iwb, | |||
477 | unsigned char c; | 478 | unsigned char c; |
478 | 479 | ||
479 | if (unlikely(count <= 0)) | 480 | if (unlikely(count <= 0)) |
480 | return atomic_read(&iwb->write); /* better ideas? */ | 481 | return iwb->write; |
481 | 482 | ||
482 | if (isowbuf_freebytes(iwb) < count || | 483 | if (isowbuf_freebytes(iwb) < count || |
483 | !isowbuf_startwrite(iwb)) { | 484 | !isowbuf_startwrite(iwb)) { |
@@ -486,13 +487,13 @@ static inline int trans_buildframe(struct isowbuf_t *iwb, | |||
486 | } | 487 | } |
487 | 488 | ||
488 | gig_dbg(DEBUG_STREAM, "put %d bytes", count); | 489 | gig_dbg(DEBUG_STREAM, "put %d bytes", count); |
489 | write = atomic_read(&iwb->write); | 490 | write = iwb->write; |
490 | do { | 491 | do { |
491 | c = bitrev8(*in++); | 492 | c = bitrev8(*in++); |
492 | iwb->data[write++] = c; | 493 | iwb->data[write++] = c; |
493 | write %= BAS_OUTBUFSIZE; | 494 | write %= BAS_OUTBUFSIZE; |
494 | } while (--count > 0); | 495 | } while (--count > 0); |
495 | atomic_set(&iwb->write, write); | 496 | iwb->write = write; |
496 | iwb->idle = c; | 497 | iwb->idle = c; |
497 | 498 | ||
498 | return isowbuf_donewrite(iwb); | 499 | return isowbuf_donewrite(iwb); |
@@ -947,8 +948,8 @@ void gigaset_isoc_input(struct inbuf_t *inbuf) | |||
947 | unsigned tail, head, numbytes; | 948 | unsigned tail, head, numbytes; |
948 | unsigned char *src; | 949 | unsigned char *src; |
949 | 950 | ||
950 | head = atomic_read(&inbuf->head); | 951 | head = inbuf->head; |
951 | while (head != (tail = atomic_read(&inbuf->tail))) { | 952 | while (head != (tail = inbuf->tail)) { |
952 | gig_dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail); | 953 | gig_dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail); |
953 | if (head > tail) | 954 | if (head > tail) |
954 | tail = RBUFSIZE; | 955 | tail = RBUFSIZE; |
@@ -956,7 +957,7 @@ void gigaset_isoc_input(struct inbuf_t *inbuf) | |||
956 | numbytes = tail - head; | 957 | numbytes = tail - head; |
957 | gig_dbg(DEBUG_INTR, "processing %u bytes", numbytes); | 958 | gig_dbg(DEBUG_INTR, "processing %u bytes", numbytes); |
958 | 959 | ||
959 | if (atomic_read(&cs->mstate) == MS_LOCKED) { | 960 | if (cs->mstate == MS_LOCKED) { |
960 | gigaset_dbg_buffer(DEBUG_LOCKCMD, "received response", | 961 | gigaset_dbg_buffer(DEBUG_LOCKCMD, "received response", |
961 | numbytes, src); | 962 | numbytes, src); |
962 | gigaset_if_receive(inbuf->cs, src, numbytes); | 963 | gigaset_if_receive(inbuf->cs, src, numbytes); |
@@ -970,7 +971,7 @@ void gigaset_isoc_input(struct inbuf_t *inbuf) | |||
970 | if (head == RBUFSIZE) | 971 | if (head == RBUFSIZE) |
971 | head = 0; | 972 | head = 0; |
972 | gig_dbg(DEBUG_INTR, "setting head to %u", head); | 973 | gig_dbg(DEBUG_INTR, "setting head to %u", head); |
973 | atomic_set(&inbuf->head, head); | 974 | inbuf->head = head; |
974 | } | 975 | } |
975 | } | 976 | } |
976 | 977 | ||
diff --git a/drivers/isdn/gigaset/ser-gigaset.c b/drivers/isdn/gigaset/ser-gigaset.c index ea44302e6e7e..fceeb1d57682 100644 --- a/drivers/isdn/gigaset/ser-gigaset.c +++ b/drivers/isdn/gigaset/ser-gigaset.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/platform_device.h> | 17 | #include <linux/platform_device.h> |
18 | #include <linux/tty.h> | 18 | #include <linux/tty.h> |
19 | #include <linux/poll.h> | 19 | #include <linux/poll.h> |
20 | #include <linux/completion.h> | ||
20 | 21 | ||
21 | /* Version Information */ | 22 | /* Version Information */ |
22 | #define DRIVER_AUTHOR "Tilman Schmidt" | 23 | #define DRIVER_AUTHOR "Tilman Schmidt" |
@@ -48,7 +49,7 @@ struct ser_cardstate { | |||
48 | struct platform_device dev; | 49 | struct platform_device dev; |
49 | struct tty_struct *tty; | 50 | struct tty_struct *tty; |
50 | atomic_t refcnt; | 51 | atomic_t refcnt; |
51 | struct mutex dead_mutex; | 52 | struct completion dead_cmp; |
52 | }; | 53 | }; |
53 | 54 | ||
54 | static struct platform_driver device_driver = { | 55 | static struct platform_driver device_driver = { |
@@ -240,7 +241,7 @@ static int gigaset_write_cmd(struct cardstate *cs, const unsigned char *buf, | |||
240 | struct cmdbuf_t *cb; | 241 | struct cmdbuf_t *cb; |
241 | unsigned long flags; | 242 | unsigned long flags; |
242 | 243 | ||
243 | gigaset_dbg_buffer(atomic_read(&cs->mstate) != MS_LOCKED ? | 244 | gigaset_dbg_buffer(cs->mstate != MS_LOCKED ? |
244 | DEBUG_TRANSCMD : DEBUG_LOCKCMD, | 245 | DEBUG_TRANSCMD : DEBUG_LOCKCMD, |
245 | "CMD Transmit", len, buf); | 246 | "CMD Transmit", len, buf); |
246 | 247 | ||
@@ -498,7 +499,7 @@ static struct cardstate *cs_get(struct tty_struct *tty) | |||
498 | static void cs_put(struct cardstate *cs) | 499 | static void cs_put(struct cardstate *cs) |
499 | { | 500 | { |
500 | if (atomic_dec_and_test(&cs->hw.ser->refcnt)) | 501 | if (atomic_dec_and_test(&cs->hw.ser->refcnt)) |
501 | mutex_unlock(&cs->hw.ser->dead_mutex); | 502 | complete(&cs->hw.ser->dead_cmp); |
502 | } | 503 | } |
503 | 504 | ||
504 | /* | 505 | /* |
@@ -527,8 +528,8 @@ gigaset_tty_open(struct tty_struct *tty) | |||
527 | 528 | ||
528 | cs->dev = &cs->hw.ser->dev.dev; | 529 | cs->dev = &cs->hw.ser->dev.dev; |
529 | cs->hw.ser->tty = tty; | 530 | cs->hw.ser->tty = tty; |
530 | mutex_init(&cs->hw.ser->dead_mutex); | ||
531 | atomic_set(&cs->hw.ser->refcnt, 1); | 531 | atomic_set(&cs->hw.ser->refcnt, 1); |
532 | init_completion(&cs->hw.ser->dead_cmp); | ||
532 | 533 | ||
533 | tty->disc_data = cs; | 534 | tty->disc_data = cs; |
534 | 535 | ||
@@ -536,14 +537,13 @@ gigaset_tty_open(struct tty_struct *tty) | |||
536 | * startup system and notify the LL that we are ready to run | 537 | * startup system and notify the LL that we are ready to run |
537 | */ | 538 | */ |
538 | if (startmode == SM_LOCKED) | 539 | if (startmode == SM_LOCKED) |
539 | atomic_set(&cs->mstate, MS_LOCKED); | 540 | cs->mstate = MS_LOCKED; |
540 | if (!gigaset_start(cs)) { | 541 | if (!gigaset_start(cs)) { |
541 | tasklet_kill(&cs->write_tasklet); | 542 | tasklet_kill(&cs->write_tasklet); |
542 | goto error; | 543 | goto error; |
543 | } | 544 | } |
544 | 545 | ||
545 | gig_dbg(DEBUG_INIT, "Startup of HLL done"); | 546 | gig_dbg(DEBUG_INIT, "Startup of HLL done"); |
546 | mutex_lock(&cs->hw.ser->dead_mutex); | ||
547 | return 0; | 547 | return 0; |
548 | 548 | ||
549 | error: | 549 | error: |
@@ -577,7 +577,7 @@ gigaset_tty_close(struct tty_struct *tty) | |||
577 | else { | 577 | else { |
578 | /* wait for running methods to finish */ | 578 | /* wait for running methods to finish */ |
579 | if (!atomic_dec_and_test(&cs->hw.ser->refcnt)) | 579 | if (!atomic_dec_and_test(&cs->hw.ser->refcnt)) |
580 | mutex_lock(&cs->hw.ser->dead_mutex); | 580 | wait_for_completion(&cs->hw.ser->dead_cmp); |
581 | } | 581 | } |
582 | 582 | ||
583 | /* stop operations */ | 583 | /* stop operations */ |
@@ -714,8 +714,8 @@ gigaset_tty_receive(struct tty_struct *tty, const unsigned char *buf, | |||
714 | return; | 714 | return; |
715 | } | 715 | } |
716 | 716 | ||
717 | tail = atomic_read(&inbuf->tail); | 717 | tail = inbuf->tail; |
718 | head = atomic_read(&inbuf->head); | 718 | head = inbuf->head; |
719 | gig_dbg(DEBUG_INTR, "buffer state: %u -> %u, receive %u bytes", | 719 | gig_dbg(DEBUG_INTR, "buffer state: %u -> %u, receive %u bytes", |
720 | head, tail, count); | 720 | head, tail, count); |
721 | 721 | ||
@@ -742,7 +742,7 @@ gigaset_tty_receive(struct tty_struct *tty, const unsigned char *buf, | |||
742 | } | 742 | } |
743 | 743 | ||
744 | gig_dbg(DEBUG_INTR, "setting tail to %u", tail); | 744 | gig_dbg(DEBUG_INTR, "setting tail to %u", tail); |
745 | atomic_set(&inbuf->tail, tail); | 745 | inbuf->tail = tail; |
746 | 746 | ||
747 | /* Everything was received .. Push data into handler */ | 747 | /* Everything was received .. Push data into handler */ |
748 | gig_dbg(DEBUG_INTR, "%s-->BH", __func__); | 748 | gig_dbg(DEBUG_INTR, "%s-->BH", __func__); |
diff --git a/drivers/isdn/gigaset/usb-gigaset.c b/drivers/isdn/gigaset/usb-gigaset.c index ca4bee173cfb..77d20ab0cd4d 100644 --- a/drivers/isdn/gigaset/usb-gigaset.c +++ b/drivers/isdn/gigaset/usb-gigaset.c | |||
@@ -104,12 +104,17 @@ MODULE_DEVICE_TABLE(usb, gigaset_table); | |||
104 | * flags per packet. | 104 | * flags per packet. |
105 | */ | 105 | */ |
106 | 106 | ||
107 | /* functions called if a device of this driver is connected/disconnected */ | ||
107 | static int gigaset_probe(struct usb_interface *interface, | 108 | static int gigaset_probe(struct usb_interface *interface, |
108 | const struct usb_device_id *id); | 109 | const struct usb_device_id *id); |
109 | static void gigaset_disconnect(struct usb_interface *interface); | 110 | static void gigaset_disconnect(struct usb_interface *interface); |
110 | 111 | ||
112 | /* functions called before/after suspend */ | ||
113 | static int gigaset_suspend(struct usb_interface *intf, pm_message_t message); | ||
114 | static int gigaset_resume(struct usb_interface *intf); | ||
115 | static int gigaset_pre_reset(struct usb_interface *intf); | ||
116 | |||
111 | static struct gigaset_driver *driver = NULL; | 117 | static struct gigaset_driver *driver = NULL; |
112 | static struct cardstate *cardstate = NULL; | ||
113 | 118 | ||
114 | /* usb specific object needed to register this driver with the usb subsystem */ | 119 | /* usb specific object needed to register this driver with the usb subsystem */ |
115 | static struct usb_driver gigaset_usb_driver = { | 120 | static struct usb_driver gigaset_usb_driver = { |
@@ -117,12 +122,17 @@ static struct usb_driver gigaset_usb_driver = { | |||
117 | .probe = gigaset_probe, | 122 | .probe = gigaset_probe, |
118 | .disconnect = gigaset_disconnect, | 123 | .disconnect = gigaset_disconnect, |
119 | .id_table = gigaset_table, | 124 | .id_table = gigaset_table, |
125 | .suspend = gigaset_suspend, | ||
126 | .resume = gigaset_resume, | ||
127 | .reset_resume = gigaset_resume, | ||
128 | .pre_reset = gigaset_pre_reset, | ||
129 | .post_reset = gigaset_resume, | ||
120 | }; | 130 | }; |
121 | 131 | ||
122 | struct usb_cardstate { | 132 | struct usb_cardstate { |
123 | struct usb_device *udev; /* usb device pointer */ | 133 | struct usb_device *udev; /* usb device pointer */ |
124 | struct usb_interface *interface; /* interface for this device */ | 134 | struct usb_interface *interface; /* interface for this device */ |
125 | atomic_t busy; /* bulk output in progress */ | 135 | int busy; /* bulk output in progress */ |
126 | 136 | ||
127 | /* Output buffer */ | 137 | /* Output buffer */ |
128 | unsigned char *bulk_out_buffer; | 138 | unsigned char *bulk_out_buffer; |
@@ -314,7 +324,7 @@ static void gigaset_modem_fill(unsigned long data) | |||
314 | 324 | ||
315 | gig_dbg(DEBUG_OUTPUT, "modem_fill"); | 325 | gig_dbg(DEBUG_OUTPUT, "modem_fill"); |
316 | 326 | ||
317 | if (atomic_read(&cs->hw.usb->busy)) { | 327 | if (cs->hw.usb->busy) { |
318 | gig_dbg(DEBUG_OUTPUT, "modem_fill: busy"); | 328 | gig_dbg(DEBUG_OUTPUT, "modem_fill: busy"); |
319 | return; | 329 | return; |
320 | } | 330 | } |
@@ -361,18 +371,13 @@ static void gigaset_read_int_callback(struct urb *urb) | |||
361 | { | 371 | { |
362 | struct inbuf_t *inbuf = urb->context; | 372 | struct inbuf_t *inbuf = urb->context; |
363 | struct cardstate *cs = inbuf->cs; | 373 | struct cardstate *cs = inbuf->cs; |
364 | int resubmit = 0; | 374 | int status = urb->status; |
365 | int r; | 375 | int r; |
366 | unsigned numbytes; | 376 | unsigned numbytes; |
367 | unsigned char *src; | 377 | unsigned char *src; |
368 | unsigned long flags; | 378 | unsigned long flags; |
369 | 379 | ||
370 | if (!urb->status) { | 380 | if (!status) { |
371 | if (!cs->connected) { | ||
372 | err("%s: disconnected", __func__); /* should never happen */ | ||
373 | return; | ||
374 | } | ||
375 | |||
376 | numbytes = urb->actual_length; | 381 | numbytes = urb->actual_length; |
377 | 382 | ||
378 | if (numbytes) { | 383 | if (numbytes) { |
@@ -389,28 +394,26 @@ static void gigaset_read_int_callback(struct urb *urb) | |||
389 | } | 394 | } |
390 | } else | 395 | } else |
391 | gig_dbg(DEBUG_INTR, "Received zero block length"); | 396 | gig_dbg(DEBUG_INTR, "Received zero block length"); |
392 | resubmit = 1; | ||
393 | } else { | 397 | } else { |
394 | /* The urb might have been killed. */ | 398 | /* The urb might have been killed. */ |
395 | gig_dbg(DEBUG_ANY, "%s - nonzero read bulk status received: %d", | 399 | gig_dbg(DEBUG_ANY, "%s - nonzero status received: %d", |
396 | __func__, urb->status); | 400 | __func__, status); |
397 | if (urb->status != -ENOENT) { /* not killed */ | 401 | if (status == -ENOENT || status == -ESHUTDOWN) |
398 | if (!cs->connected) { | 402 | /* killed or endpoint shutdown: don't resubmit */ |
399 | err("%s: disconnected", __func__); /* should never happen */ | 403 | return; |
400 | return; | ||
401 | } | ||
402 | resubmit = 1; | ||
403 | } | ||
404 | } | 404 | } |
405 | 405 | ||
406 | if (resubmit) { | 406 | /* resubmit URB */ |
407 | spin_lock_irqsave(&cs->lock, flags); | 407 | spin_lock_irqsave(&cs->lock, flags); |
408 | r = cs->connected ? usb_submit_urb(urb, GFP_ATOMIC) : -ENODEV; | 408 | if (!cs->connected) { |
409 | spin_unlock_irqrestore(&cs->lock, flags); | 409 | spin_unlock_irqrestore(&cs->lock, flags); |
410 | if (r) | 410 | err("%s: disconnected", __func__); |
411 | dev_err(cs->dev, "error %d when resubmitting urb.\n", | 411 | return; |
412 | -r); | ||
413 | } | 412 | } |
413 | r = usb_submit_urb(urb, GFP_ATOMIC); | ||
414 | spin_unlock_irqrestore(&cs->lock, flags); | ||
415 | if (r) | ||
416 | dev_err(cs->dev, "error %d resubmitting URB\n", -r); | ||
414 | } | 417 | } |
415 | 418 | ||
416 | 419 | ||
@@ -418,19 +421,28 @@ static void gigaset_read_int_callback(struct urb *urb) | |||
418 | static void gigaset_write_bulk_callback(struct urb *urb) | 421 | static void gigaset_write_bulk_callback(struct urb *urb) |
419 | { | 422 | { |
420 | struct cardstate *cs = urb->context; | 423 | struct cardstate *cs = urb->context; |
424 | int status = urb->status; | ||
421 | unsigned long flags; | 425 | unsigned long flags; |
422 | 426 | ||
423 | if (urb->status) | 427 | switch (status) { |
428 | case 0: /* normal completion */ | ||
429 | break; | ||
430 | case -ENOENT: /* killed */ | ||
431 | gig_dbg(DEBUG_ANY, "%s: killed", __func__); | ||
432 | cs->hw.usb->busy = 0; | ||
433 | return; | ||
434 | default: | ||
424 | dev_err(cs->dev, "bulk transfer failed (status %d)\n", | 435 | dev_err(cs->dev, "bulk transfer failed (status %d)\n", |
425 | -urb->status); | 436 | -status); |
426 | /* That's all we can do. Communication problems | 437 | /* That's all we can do. Communication problems |
427 | are handled by timeouts or network protocols. */ | 438 | are handled by timeouts or network protocols. */ |
439 | } | ||
428 | 440 | ||
429 | spin_lock_irqsave(&cs->lock, flags); | 441 | spin_lock_irqsave(&cs->lock, flags); |
430 | if (!cs->connected) { | 442 | if (!cs->connected) { |
431 | err("%s: not connected", __func__); | 443 | err("%s: not connected", __func__); |
432 | } else { | 444 | } else { |
433 | atomic_set(&cs->hw.usb->busy, 0); | 445 | cs->hw.usb->busy = 0; |
434 | tasklet_schedule(&cs->write_tasklet); | 446 | tasklet_schedule(&cs->write_tasklet); |
435 | } | 447 | } |
436 | spin_unlock_irqrestore(&cs->lock, flags); | 448 | spin_unlock_irqrestore(&cs->lock, flags); |
@@ -478,14 +490,14 @@ static int send_cb(struct cardstate *cs, struct cmdbuf_t *cb) | |||
478 | 490 | ||
479 | cb->offset += count; | 491 | cb->offset += count; |
480 | cb->len -= count; | 492 | cb->len -= count; |
481 | atomic_set(&ucs->busy, 1); | 493 | ucs->busy = 1; |
482 | 494 | ||
483 | spin_lock_irqsave(&cs->lock, flags); | 495 | spin_lock_irqsave(&cs->lock, flags); |
484 | status = cs->connected ? usb_submit_urb(ucs->bulk_out_urb, GFP_ATOMIC) : -ENODEV; | 496 | status = cs->connected ? usb_submit_urb(ucs->bulk_out_urb, GFP_ATOMIC) : -ENODEV; |
485 | spin_unlock_irqrestore(&cs->lock, flags); | 497 | spin_unlock_irqrestore(&cs->lock, flags); |
486 | 498 | ||
487 | if (status) { | 499 | if (status) { |
488 | atomic_set(&ucs->busy, 0); | 500 | ucs->busy = 0; |
489 | err("could not submit urb (error %d)\n", | 501 | err("could not submit urb (error %d)\n", |
490 | -status); | 502 | -status); |
491 | cb->len = 0; /* skip urb => remove cb+wakeup | 503 | cb->len = 0; /* skip urb => remove cb+wakeup |
@@ -504,7 +516,7 @@ static int gigaset_write_cmd(struct cardstate *cs, const unsigned char *buf, | |||
504 | struct cmdbuf_t *cb; | 516 | struct cmdbuf_t *cb; |
505 | unsigned long flags; | 517 | unsigned long flags; |
506 | 518 | ||
507 | gigaset_dbg_buffer(atomic_read(&cs->mstate) != MS_LOCKED ? | 519 | gigaset_dbg_buffer(cs->mstate != MS_LOCKED ? |
508 | DEBUG_TRANSCMD : DEBUG_LOCKCMD, | 520 | DEBUG_TRANSCMD : DEBUG_LOCKCMD, |
509 | "CMD Transmit", len, buf); | 521 | "CMD Transmit", len, buf); |
510 | 522 | ||
@@ -641,7 +653,7 @@ static int write_modem(struct cardstate *cs) | |||
641 | count = min(bcs->tx_skb->len, (unsigned) ucs->bulk_out_size); | 653 | count = min(bcs->tx_skb->len, (unsigned) ucs->bulk_out_size); |
642 | skb_copy_from_linear_data(bcs->tx_skb, ucs->bulk_out_buffer, count); | 654 | skb_copy_from_linear_data(bcs->tx_skb, ucs->bulk_out_buffer, count); |
643 | skb_pull(bcs->tx_skb, count); | 655 | skb_pull(bcs->tx_skb, count); |
644 | atomic_set(&ucs->busy, 1); | 656 | ucs->busy = 1; |
645 | gig_dbg(DEBUG_OUTPUT, "write_modem: send %d bytes", count); | 657 | gig_dbg(DEBUG_OUTPUT, "write_modem: send %d bytes", count); |
646 | 658 | ||
647 | spin_lock_irqsave(&cs->lock, flags); | 659 | spin_lock_irqsave(&cs->lock, flags); |
@@ -659,7 +671,7 @@ static int write_modem(struct cardstate *cs) | |||
659 | 671 | ||
660 | if (ret) { | 672 | if (ret) { |
661 | err("could not submit urb (error %d)\n", -ret); | 673 | err("could not submit urb (error %d)\n", -ret); |
662 | atomic_set(&ucs->busy, 0); | 674 | ucs->busy = 0; |
663 | } | 675 | } |
664 | 676 | ||
665 | if (!bcs->tx_skb->len) { | 677 | if (!bcs->tx_skb->len) { |
@@ -680,53 +692,44 @@ static int gigaset_probe(struct usb_interface *interface, | |||
680 | { | 692 | { |
681 | int retval; | 693 | int retval; |
682 | struct usb_device *udev = interface_to_usbdev(interface); | 694 | struct usb_device *udev = interface_to_usbdev(interface); |
683 | unsigned int ifnum; | 695 | struct usb_host_interface *hostif = interface->cur_altsetting; |
684 | struct usb_host_interface *hostif; | ||
685 | struct cardstate *cs = NULL; | 696 | struct cardstate *cs = NULL; |
686 | struct usb_cardstate *ucs = NULL; | 697 | struct usb_cardstate *ucs = NULL; |
687 | struct usb_endpoint_descriptor *endpoint; | 698 | struct usb_endpoint_descriptor *endpoint; |
688 | int buffer_size; | 699 | int buffer_size; |
689 | int alt; | ||
690 | 700 | ||
691 | gig_dbg(DEBUG_ANY, | 701 | gig_dbg(DEBUG_ANY, "%s: Check if device matches ...", __func__); |
692 | "%s: Check if device matches .. (Vendor: 0x%x, Product: 0x%x)", | ||
693 | __func__, le16_to_cpu(udev->descriptor.idVendor), | ||
694 | le16_to_cpu(udev->descriptor.idProduct)); | ||
695 | |||
696 | retval = -ENODEV; //FIXME | ||
697 | 702 | ||
698 | /* See if the device offered us matches what we can accept */ | 703 | /* See if the device offered us matches what we can accept */ |
699 | if ((le16_to_cpu(udev->descriptor.idVendor) != USB_M105_VENDOR_ID) || | 704 | if ((le16_to_cpu(udev->descriptor.idVendor) != USB_M105_VENDOR_ID) || |
700 | (le16_to_cpu(udev->descriptor.idProduct) != USB_M105_PRODUCT_ID)) | 705 | (le16_to_cpu(udev->descriptor.idProduct) != USB_M105_PRODUCT_ID)) { |
706 | gig_dbg(DEBUG_ANY, "device ID (0x%x, 0x%x) not for me - skip", | ||
707 | le16_to_cpu(udev->descriptor.idVendor), | ||
708 | le16_to_cpu(udev->descriptor.idProduct)); | ||
701 | return -ENODEV; | 709 | return -ENODEV; |
702 | 710 | } | |
703 | /* this starts to become ascii art... */ | 711 | if (hostif->desc.bInterfaceNumber != 0) { |
704 | hostif = interface->cur_altsetting; | 712 | gig_dbg(DEBUG_ANY, "interface %d not for me - skip", |
705 | alt = hostif->desc.bAlternateSetting; | 713 | hostif->desc.bInterfaceNumber); |
706 | ifnum = hostif->desc.bInterfaceNumber; // FIXME ? | 714 | return -ENODEV; |
707 | 715 | } | |
708 | if (alt != 0 || ifnum != 0) { | 716 | if (hostif->desc.bAlternateSetting != 0) { |
709 | dev_warn(&udev->dev, "ifnum %d, alt %d\n", ifnum, alt); | 717 | dev_notice(&udev->dev, "unsupported altsetting %d - skip", |
718 | hostif->desc.bAlternateSetting); | ||
710 | return -ENODEV; | 719 | return -ENODEV; |
711 | } | 720 | } |
712 | |||
713 | /* Reject application specific intefaces | ||
714 | * | ||
715 | */ | ||
716 | if (hostif->desc.bInterfaceClass != 255) { | 721 | if (hostif->desc.bInterfaceClass != 255) { |
717 | dev_info(&udev->dev, | 722 | dev_notice(&udev->dev, "unsupported interface class %d - skip", |
718 | "%s: Device matched but iface_desc[%d]->bInterfaceClass==%d!\n", | 723 | hostif->desc.bInterfaceClass); |
719 | __func__, ifnum, hostif->desc.bInterfaceClass); | ||
720 | return -ENODEV; | 724 | return -ENODEV; |
721 | } | 725 | } |
722 | 726 | ||
723 | dev_info(&udev->dev, "%s: Device matched ... !\n", __func__); | 727 | dev_info(&udev->dev, "%s: Device matched ... !\n", __func__); |
724 | 728 | ||
725 | cs = gigaset_getunassignedcs(driver); | 729 | /* allocate memory for our device state and intialize it */ |
726 | if (!cs) { | 730 | cs = gigaset_initcs(driver, 1, 1, 0, cidmode, GIGASET_MODULENAME); |
727 | dev_warn(&udev->dev, "no free cardstate\n"); | 731 | if (!cs) |
728 | return -ENODEV; | 732 | return -ENODEV; |
729 | } | ||
730 | ucs = cs->hw.usb; | 733 | ucs = cs->hw.usb; |
731 | 734 | ||
732 | /* save off device structure ptrs for later use */ | 735 | /* save off device structure ptrs for later use */ |
@@ -759,7 +762,7 @@ static int gigaset_probe(struct usb_interface *interface, | |||
759 | 762 | ||
760 | endpoint = &hostif->endpoint[1].desc; | 763 | endpoint = &hostif->endpoint[1].desc; |
761 | 764 | ||
762 | atomic_set(&ucs->busy, 0); | 765 | ucs->busy = 0; |
763 | 766 | ||
764 | ucs->read_urb = usb_alloc_urb(0, GFP_KERNEL); | 767 | ucs->read_urb = usb_alloc_urb(0, GFP_KERNEL); |
765 | if (!ucs->read_urb) { | 768 | if (!ucs->read_urb) { |
@@ -792,7 +795,7 @@ static int gigaset_probe(struct usb_interface *interface, | |||
792 | 795 | ||
793 | /* tell common part that the device is ready */ | 796 | /* tell common part that the device is ready */ |
794 | if (startmode == SM_LOCKED) | 797 | if (startmode == SM_LOCKED) |
795 | atomic_set(&cs->mstate, MS_LOCKED); | 798 | cs->mstate = MS_LOCKED; |
796 | 799 | ||
797 | if (!gigaset_start(cs)) { | 800 | if (!gigaset_start(cs)) { |
798 | tasklet_kill(&cs->write_tasklet); | 801 | tasklet_kill(&cs->write_tasklet); |
@@ -813,7 +816,7 @@ error: | |||
813 | usb_put_dev(ucs->udev); | 816 | usb_put_dev(ucs->udev); |
814 | ucs->udev = NULL; | 817 | ucs->udev = NULL; |
815 | ucs->interface = NULL; | 818 | ucs->interface = NULL; |
816 | gigaset_unassign(cs); | 819 | gigaset_freecs(cs); |
817 | return retval; | 820 | return retval; |
818 | } | 821 | } |
819 | 822 | ||
@@ -824,6 +827,9 @@ static void gigaset_disconnect(struct usb_interface *interface) | |||
824 | 827 | ||
825 | cs = usb_get_intfdata(interface); | 828 | cs = usb_get_intfdata(interface); |
826 | ucs = cs->hw.usb; | 829 | ucs = cs->hw.usb; |
830 | |||
831 | dev_info(cs->dev, "disconnecting Gigaset USB adapter\n"); | ||
832 | |||
827 | usb_kill_urb(ucs->read_urb); | 833 | usb_kill_urb(ucs->read_urb); |
828 | 834 | ||
829 | gigaset_stop(cs); | 835 | gigaset_stop(cs); |
@@ -831,7 +837,7 @@ static void gigaset_disconnect(struct usb_interface *interface) | |||
831 | usb_set_intfdata(interface, NULL); | 837 | usb_set_intfdata(interface, NULL); |
832 | tasklet_kill(&cs->write_tasklet); | 838 | tasklet_kill(&cs->write_tasklet); |
833 | 839 | ||
834 | usb_kill_urb(ucs->bulk_out_urb); /* FIXME: only if active? */ | 840 | usb_kill_urb(ucs->bulk_out_urb); |
835 | 841 | ||
836 | kfree(ucs->bulk_out_buffer); | 842 | kfree(ucs->bulk_out_buffer); |
837 | usb_free_urb(ucs->bulk_out_urb); | 843 | usb_free_urb(ucs->bulk_out_urb); |
@@ -844,7 +850,53 @@ static void gigaset_disconnect(struct usb_interface *interface) | |||
844 | ucs->interface = NULL; | 850 | ucs->interface = NULL; |
845 | ucs->udev = NULL; | 851 | ucs->udev = NULL; |
846 | cs->dev = NULL; | 852 | cs->dev = NULL; |
847 | gigaset_unassign(cs); | 853 | gigaset_freecs(cs); |
854 | } | ||
855 | |||
856 | /* gigaset_suspend | ||
857 | * This function is called before the USB connection is suspended or reset. | ||
858 | */ | ||
859 | static int gigaset_suspend(struct usb_interface *intf, pm_message_t message) | ||
860 | { | ||
861 | struct cardstate *cs = usb_get_intfdata(intf); | ||
862 | |||
863 | /* stop activity */ | ||
864 | cs->connected = 0; /* prevent rescheduling */ | ||
865 | usb_kill_urb(cs->hw.usb->read_urb); | ||
866 | tasklet_kill(&cs->write_tasklet); | ||
867 | usb_kill_urb(cs->hw.usb->bulk_out_urb); | ||
868 | |||
869 | gig_dbg(DEBUG_SUSPEND, "suspend complete"); | ||
870 | return 0; | ||
871 | } | ||
872 | |||
873 | /* gigaset_resume | ||
874 | * This function is called after the USB connection has been resumed or reset. | ||
875 | */ | ||
876 | static int gigaset_resume(struct usb_interface *intf) | ||
877 | { | ||
878 | struct cardstate *cs = usb_get_intfdata(intf); | ||
879 | int rc; | ||
880 | |||
881 | /* resubmit interrupt URB */ | ||
882 | cs->connected = 1; | ||
883 | rc = usb_submit_urb(cs->hw.usb->read_urb, GFP_KERNEL); | ||
884 | if (rc) { | ||
885 | dev_err(cs->dev, "Could not submit read URB (error %d)\n", -rc); | ||
886 | return rc; | ||
887 | } | ||
888 | |||
889 | gig_dbg(DEBUG_SUSPEND, "resume complete"); | ||
890 | return 0; | ||
891 | } | ||
892 | |||
893 | /* gigaset_pre_reset | ||
894 | * This function is called before the USB connection is reset. | ||
895 | */ | ||
896 | static int gigaset_pre_reset(struct usb_interface *intf) | ||
897 | { | ||
898 | /* same as suspend */ | ||
899 | return gigaset_suspend(intf, PMSG_ON); | ||
848 | } | 900 | } |
849 | 901 | ||
850 | static const struct gigaset_ops ops = { | 902 | static const struct gigaset_ops ops = { |
@@ -880,11 +932,6 @@ static int __init usb_gigaset_init(void) | |||
880 | &ops, THIS_MODULE)) == NULL) | 932 | &ops, THIS_MODULE)) == NULL) |
881 | goto error; | 933 | goto error; |
882 | 934 | ||
883 | /* allocate memory for our device state and intialize it */ | ||
884 | cardstate = gigaset_initcs(driver, 1, 1, 0, cidmode, GIGASET_MODULENAME); | ||
885 | if (!cardstate) | ||
886 | goto error; | ||
887 | |||
888 | /* register this driver with the USB subsystem */ | 935 | /* register this driver with the USB subsystem */ |
889 | result = usb_register(&gigaset_usb_driver); | 936 | result = usb_register(&gigaset_usb_driver); |
890 | if (result < 0) { | 937 | if (result < 0) { |
@@ -897,9 +944,7 @@ static int __init usb_gigaset_init(void) | |||
897 | info(DRIVER_DESC); | 944 | info(DRIVER_DESC); |
898 | return 0; | 945 | return 0; |
899 | 946 | ||
900 | error: if (cardstate) | 947 | error: |
901 | gigaset_freecs(cardstate); | ||
902 | cardstate = NULL; | ||
903 | if (driver) | 948 | if (driver) |
904 | gigaset_freedriver(driver); | 949 | gigaset_freedriver(driver); |
905 | driver = NULL; | 950 | driver = NULL; |
@@ -913,11 +958,16 @@ error: if (cardstate) | |||
913 | */ | 958 | */ |
914 | static void __exit usb_gigaset_exit(void) | 959 | static void __exit usb_gigaset_exit(void) |
915 | { | 960 | { |
961 | int i; | ||
962 | |||
916 | gigaset_blockdriver(driver); /* => probe will fail | 963 | gigaset_blockdriver(driver); /* => probe will fail |
917 | * => no gigaset_start any more | 964 | * => no gigaset_start any more |
918 | */ | 965 | */ |
919 | 966 | ||
920 | gigaset_shutdown(cardstate); | 967 | /* stop all connected devices */ |
968 | for (i = 0; i < driver->minors; i++) | ||
969 | gigaset_shutdown(driver->cs + i); | ||
970 | |||
921 | /* from now on, no isdn callback should be possible */ | 971 | /* from now on, no isdn callback should be possible */ |
922 | 972 | ||
923 | /* deregister this driver with the USB subsystem */ | 973 | /* deregister this driver with the USB subsystem */ |
@@ -925,8 +975,6 @@ static void __exit usb_gigaset_exit(void) | |||
925 | /* this will call the disconnect-callback */ | 975 | /* this will call the disconnect-callback */ |
926 | /* from now on, no disconnect/probe callback should be running */ | 976 | /* from now on, no disconnect/probe callback should be running */ |
927 | 977 | ||
928 | gigaset_freecs(cardstate); | ||
929 | cardstate = NULL; | ||
930 | gigaset_freedriver(driver); | 978 | gigaset_freedriver(driver); |
931 | driver = NULL; | 979 | driver = NULL; |
932 | } | 980 | } |
diff --git a/drivers/isdn/hardware/eicon/debug.c b/drivers/isdn/hardware/eicon/debug.c index 0db9cc661e28..84318ec8d13e 100644 --- a/drivers/isdn/hardware/eicon/debug.c +++ b/drivers/isdn/hardware/eicon/debug.c | |||
@@ -1188,7 +1188,7 @@ int SuperTraceASSIGN (void* AdapterHandle, byte* data) { | |||
1188 | 1188 | ||
1189 | if ((features[0] & DIVA_XDI_EXTENDED_FEATURES_VALID) && | 1189 | if ((features[0] & DIVA_XDI_EXTENDED_FEATURES_VALID) && |
1190 | (features[0] & DIVA_XDI_EXTENDED_FEATURE_MANAGEMENT_DMA)) { | 1190 | (features[0] & DIVA_XDI_EXTENDED_FEATURE_MANAGEMENT_DMA)) { |
1191 | dword rx_dma_magic; | 1191 | dword uninitialized_var(rx_dma_magic); |
1192 | if ((pC->dma_handle = diva_get_dma_descriptor (pC->request, &rx_dma_magic)) >= 0) { | 1192 | if ((pC->dma_handle = diva_get_dma_descriptor (pC->request, &rx_dma_magic)) >= 0) { |
1193 | pC->xbuffer[0] = LLI; | 1193 | pC->xbuffer[0] = LLI; |
1194 | pC->xbuffer[1] = 8; | 1194 | pC->xbuffer[1] = 8; |
diff --git a/drivers/isdn/hardware/eicon/diva.c b/drivers/isdn/hardware/eicon/diva.c index ffa2afa77c2f..1403a5458e68 100644 --- a/drivers/isdn/hardware/eicon/diva.c +++ b/drivers/isdn/hardware/eicon/diva.c | |||
@@ -515,12 +515,11 @@ diva_xdi_read(void *adapter, void *os_handle, void __user *dst, | |||
515 | 515 | ||
516 | irqreturn_t diva_os_irq_wrapper(int irq, void *context) | 516 | irqreturn_t diva_os_irq_wrapper(int irq, void *context) |
517 | { | 517 | { |
518 | diva_os_xdi_adapter_t *a = (diva_os_xdi_adapter_t *) context; | 518 | diva_os_xdi_adapter_t *a = context; |
519 | diva_xdi_clear_interrupts_proc_t clear_int_proc; | 519 | diva_xdi_clear_interrupts_proc_t clear_int_proc; |
520 | 520 | ||
521 | if (!a || !a->xdi_adapter.diva_isr_handler) { | 521 | if (!a || !a->xdi_adapter.diva_isr_handler) |
522 | return IRQ_NONE; | 522 | return IRQ_NONE; |
523 | } | ||
524 | 523 | ||
525 | if ((clear_int_proc = a->clear_interrupts_proc)) { | 524 | if ((clear_int_proc = a->clear_interrupts_proc)) { |
526 | (*clear_int_proc) (a); | 525 | (*clear_int_proc) (a); |
diff --git a/drivers/isdn/hardware/eicon/message.c b/drivers/isdn/hardware/eicon/message.c index b9177ca4369a..1ff98e7eb794 100644 --- a/drivers/isdn/hardware/eicon/message.c +++ b/drivers/isdn/hardware/eicon/message.c | |||
@@ -9027,7 +9027,7 @@ static byte AddInfo(byte **add_i, | |||
9027 | /* facility is a nested structure */ | 9027 | /* facility is a nested structure */ |
9028 | /* FTY can be more than once */ | 9028 | /* FTY can be more than once */ |
9029 | 9029 | ||
9030 | if(esc_chi[0] && !(esc_chi[esc_chi[0]])&0x7f ) | 9030 | if (esc_chi[0] && !(esc_chi[esc_chi[0]] & 0x7f)) |
9031 | { | 9031 | { |
9032 | add_i[0] = (byte *)"\x02\x02\x00"; /* use neither b nor d channel */ | 9032 | add_i[0] = (byte *)"\x02\x02\x00"; /* use neither b nor d channel */ |
9033 | } | 9033 | } |
diff --git a/drivers/isdn/hisax/avm_pci.c b/drivers/isdn/hisax/avm_pci.c index 035d158779df..0f1db1f669b2 100644 --- a/drivers/isdn/hisax/avm_pci.c +++ b/drivers/isdn/hisax/avm_pci.c | |||
@@ -263,11 +263,7 @@ hdlc_empty_fifo(struct BCState *bcs, int count) | |||
263 | outl(idx, cs->hw.avm.cfg_reg + 4); | 263 | outl(idx, cs->hw.avm.cfg_reg + 4); |
264 | while (cnt < count) { | 264 | while (cnt < count) { |
265 | #ifdef __powerpc__ | 265 | #ifdef __powerpc__ |
266 | #ifdef CONFIG_APUS | ||
267 | *ptr++ = in_le32((unsigned *)(cs->hw.avm.isac +_IO_BASE)); | ||
268 | #else | ||
269 | *ptr++ = in_be32((unsigned *)(cs->hw.avm.isac +_IO_BASE)); | 266 | *ptr++ = in_be32((unsigned *)(cs->hw.avm.isac +_IO_BASE)); |
270 | #endif /* CONFIG_APUS */ | ||
271 | #else | 267 | #else |
272 | *ptr++ = inl(cs->hw.avm.isac); | 268 | *ptr++ = inl(cs->hw.avm.isac); |
273 | #endif /* __powerpc__ */ | 269 | #endif /* __powerpc__ */ |
@@ -328,11 +324,7 @@ hdlc_fill_fifo(struct BCState *bcs) | |||
328 | if (cs->subtyp == AVM_FRITZ_PCI) { | 324 | if (cs->subtyp == AVM_FRITZ_PCI) { |
329 | while (cnt<count) { | 325 | while (cnt<count) { |
330 | #ifdef __powerpc__ | 326 | #ifdef __powerpc__ |
331 | #ifdef CONFIG_APUS | ||
332 | out_le32((unsigned *)(cs->hw.avm.isac +_IO_BASE), *ptr++); | ||
333 | #else | ||
334 | out_be32((unsigned *)(cs->hw.avm.isac +_IO_BASE), *ptr++); | 327 | out_be32((unsigned *)(cs->hw.avm.isac +_IO_BASE), *ptr++); |
335 | #endif /* CONFIG_APUS */ | ||
336 | #else | 328 | #else |
337 | outl(*ptr++, cs->hw.avm.isac); | 329 | outl(*ptr++, cs->hw.avm.isac); |
338 | #endif /* __powerpc__ */ | 330 | #endif /* __powerpc__ */ |
diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c index 9cb6e5021adb..133eb18e65cc 100644 --- a/drivers/isdn/i4l/isdn_tty.c +++ b/drivers/isdn/i4l/isdn_tty.c | |||
@@ -1917,7 +1917,6 @@ isdn_tty_modem_init(void) | |||
1917 | info->owner = THIS_MODULE; | 1917 | info->owner = THIS_MODULE; |
1918 | #endif | 1918 | #endif |
1919 | spin_lock_init(&info->readlock); | 1919 | spin_lock_init(&info->readlock); |
1920 | init_MUTEX(&info->write_sem); | ||
1921 | sprintf(info->last_cause, "0000"); | 1920 | sprintf(info->last_cause, "0000"); |
1922 | sprintf(info->last_num, "none"); | 1921 | sprintf(info->last_num, "none"); |
1923 | info->last_dir = 0; | 1922 | info->last_dir = 0; |
diff --git a/drivers/isdn/i4l/isdn_ttyfax.c b/drivers/isdn/i4l/isdn_ttyfax.c index a943d078bacc..f93de4a30355 100644 --- a/drivers/isdn/i4l/isdn_ttyfax.c +++ b/drivers/isdn/i4l/isdn_ttyfax.c | |||
@@ -834,7 +834,7 @@ isdn_tty_cmd_FCLASS2(char **p, modem_info * info) | |||
834 | char *rp = &f->resolution; | 834 | char *rp = &f->resolution; |
835 | 835 | ||
836 | p[0] += 2; | 836 | p[0] += 2; |
837 | if (!info->faxonline & 1) /* not outgoing connection */ | 837 | if (!(info->faxonline & 1)) /* not outgoing connection */ |
838 | PARSE_ERROR1; | 838 | PARSE_ERROR1; |
839 | 839 | ||
840 | for (i = 0; (((*p[0] >= '0') && (*p[0] <= '9')) || (*p[0] == ',')) && (i < 4); i++) { | 840 | for (i = 0; (((*p[0] >= '0') && (*p[0] <= '9')) || (*p[0] == ',')) && (i < 4); i++) { |
diff --git a/drivers/isdn/icn/icn.c b/drivers/isdn/icn/icn.c index 82d957bde299..bf7997abc4ac 100644 --- a/drivers/isdn/icn/icn.c +++ b/drivers/isdn/icn/icn.c | |||
@@ -1302,7 +1302,7 @@ icn_command(isdn_ctrl * c, icn_card * card) | |||
1302 | } | 1302 | } |
1303 | break; | 1303 | break; |
1304 | case ISDN_CMD_DIAL: | 1304 | case ISDN_CMD_DIAL: |
1305 | if (!card->flags & ICN_FLAGS_RUNNING) | 1305 | if (!(card->flags & ICN_FLAGS_RUNNING)) |
1306 | return -ENODEV; | 1306 | return -ENODEV; |
1307 | if (card->leased) | 1307 | if (card->leased) |
1308 | break; | 1308 | break; |
@@ -1328,7 +1328,7 @@ icn_command(isdn_ctrl * c, icn_card * card) | |||
1328 | } | 1328 | } |
1329 | break; | 1329 | break; |
1330 | case ISDN_CMD_ACCEPTD: | 1330 | case ISDN_CMD_ACCEPTD: |
1331 | if (!card->flags & ICN_FLAGS_RUNNING) | 1331 | if (!(card->flags & ICN_FLAGS_RUNNING)) |
1332 | return -ENODEV; | 1332 | return -ENODEV; |
1333 | if (c->arg < ICN_BCH) { | 1333 | if (c->arg < ICN_BCH) { |
1334 | a = c->arg + 1; | 1334 | a = c->arg + 1; |
@@ -1348,7 +1348,7 @@ icn_command(isdn_ctrl * c, icn_card * card) | |||
1348 | } | 1348 | } |
1349 | break; | 1349 | break; |
1350 | case ISDN_CMD_ACCEPTB: | 1350 | case ISDN_CMD_ACCEPTB: |
1351 | if (!card->flags & ICN_FLAGS_RUNNING) | 1351 | if (!(card->flags & ICN_FLAGS_RUNNING)) |
1352 | return -ENODEV; | 1352 | return -ENODEV; |
1353 | if (c->arg < ICN_BCH) { | 1353 | if (c->arg < ICN_BCH) { |
1354 | a = c->arg + 1; | 1354 | a = c->arg + 1; |
@@ -1366,7 +1366,7 @@ icn_command(isdn_ctrl * c, icn_card * card) | |||
1366 | } | 1366 | } |
1367 | break; | 1367 | break; |
1368 | case ISDN_CMD_HANGUP: | 1368 | case ISDN_CMD_HANGUP: |
1369 | if (!card->flags & ICN_FLAGS_RUNNING) | 1369 | if (!(card->flags & ICN_FLAGS_RUNNING)) |
1370 | return -ENODEV; | 1370 | return -ENODEV; |
1371 | if (c->arg < ICN_BCH) { | 1371 | if (c->arg < ICN_BCH) { |
1372 | a = c->arg + 1; | 1372 | a = c->arg + 1; |
@@ -1375,7 +1375,7 @@ icn_command(isdn_ctrl * c, icn_card * card) | |||
1375 | } | 1375 | } |
1376 | break; | 1376 | break; |
1377 | case ISDN_CMD_SETEAZ: | 1377 | case ISDN_CMD_SETEAZ: |
1378 | if (!card->flags & ICN_FLAGS_RUNNING) | 1378 | if (!(card->flags & ICN_FLAGS_RUNNING)) |
1379 | return -ENODEV; | 1379 | return -ENODEV; |
1380 | if (card->leased) | 1380 | if (card->leased) |
1381 | break; | 1381 | break; |
@@ -1391,7 +1391,7 @@ icn_command(isdn_ctrl * c, icn_card * card) | |||
1391 | } | 1391 | } |
1392 | break; | 1392 | break; |
1393 | case ISDN_CMD_CLREAZ: | 1393 | case ISDN_CMD_CLREAZ: |
1394 | if (!card->flags & ICN_FLAGS_RUNNING) | 1394 | if (!(card->flags & ICN_FLAGS_RUNNING)) |
1395 | return -ENODEV; | 1395 | return -ENODEV; |
1396 | if (card->leased) | 1396 | if (card->leased) |
1397 | break; | 1397 | break; |
@@ -1405,7 +1405,7 @@ icn_command(isdn_ctrl * c, icn_card * card) | |||
1405 | } | 1405 | } |
1406 | break; | 1406 | break; |
1407 | case ISDN_CMD_SETL2: | 1407 | case ISDN_CMD_SETL2: |
1408 | if (!card->flags & ICN_FLAGS_RUNNING) | 1408 | if (!(card->flags & ICN_FLAGS_RUNNING)) |
1409 | return -ENODEV; | 1409 | return -ENODEV; |
1410 | if ((c->arg & 255) < ICN_BCH) { | 1410 | if ((c->arg & 255) < ICN_BCH) { |
1411 | a = c->arg; | 1411 | a = c->arg; |
@@ -1424,7 +1424,7 @@ icn_command(isdn_ctrl * c, icn_card * card) | |||
1424 | } | 1424 | } |
1425 | break; | 1425 | break; |
1426 | case ISDN_CMD_SETL3: | 1426 | case ISDN_CMD_SETL3: |
1427 | if (!card->flags & ICN_FLAGS_RUNNING) | 1427 | if (!(card->flags & ICN_FLAGS_RUNNING)) |
1428 | return -ENODEV; | 1428 | return -ENODEV; |
1429 | return 0; | 1429 | return 0; |
1430 | default: | 1430 | default: |
@@ -1471,7 +1471,7 @@ if_writecmd(const u_char __user *buf, int len, int id, int channel) | |||
1471 | icn_card *card = icn_findcard(id); | 1471 | icn_card *card = icn_findcard(id); |
1472 | 1472 | ||
1473 | if (card) { | 1473 | if (card) { |
1474 | if (!card->flags & ICN_FLAGS_RUNNING) | 1474 | if (!(card->flags & ICN_FLAGS_RUNNING)) |
1475 | return -ENODEV; | 1475 | return -ENODEV; |
1476 | return (icn_writecmd(buf, len, 1, card)); | 1476 | return (icn_writecmd(buf, len, 1, card)); |
1477 | } | 1477 | } |
@@ -1486,7 +1486,7 @@ if_readstatus(u_char __user *buf, int len, int id, int channel) | |||
1486 | icn_card *card = icn_findcard(id); | 1486 | icn_card *card = icn_findcard(id); |
1487 | 1487 | ||
1488 | if (card) { | 1488 | if (card) { |
1489 | if (!card->flags & ICN_FLAGS_RUNNING) | 1489 | if (!(card->flags & ICN_FLAGS_RUNNING)) |
1490 | return -ENODEV; | 1490 | return -ENODEV; |
1491 | return (icn_readstatus(buf, len, card)); | 1491 | return (icn_readstatus(buf, len, card)); |
1492 | } | 1492 | } |
@@ -1501,7 +1501,7 @@ if_sendbuf(int id, int channel, int ack, struct sk_buff *skb) | |||
1501 | icn_card *card = icn_findcard(id); | 1501 | icn_card *card = icn_findcard(id); |
1502 | 1502 | ||
1503 | if (card) { | 1503 | if (card) { |
1504 | if (!card->flags & ICN_FLAGS_RUNNING) | 1504 | if (!(card->flags & ICN_FLAGS_RUNNING)) |
1505 | return -ENODEV; | 1505 | return -ENODEV; |
1506 | return (icn_sendbuf(channel, ack, skb, card)); | 1506 | return (icn_sendbuf(channel, ack, skb, card)); |
1507 | } | 1507 | } |
diff --git a/drivers/isdn/isdnloop/isdnloop.c b/drivers/isdn/isdnloop/isdnloop.c index bb92e3cd9334..655ef9a3f4df 100644 --- a/drivers/isdn/isdnloop/isdnloop.c +++ b/drivers/isdn/isdnloop/isdnloop.c | |||
@@ -1184,7 +1184,7 @@ isdnloop_command(isdn_ctrl * c, isdnloop_card * card) | |||
1184 | } | 1184 | } |
1185 | break; | 1185 | break; |
1186 | case ISDN_CMD_DIAL: | 1186 | case ISDN_CMD_DIAL: |
1187 | if (!card->flags & ISDNLOOP_FLAGS_RUNNING) | 1187 | if (!(card->flags & ISDNLOOP_FLAGS_RUNNING)) |
1188 | return -ENODEV; | 1188 | return -ENODEV; |
1189 | if (card->leased) | 1189 | if (card->leased) |
1190 | break; | 1190 | break; |
@@ -1210,7 +1210,7 @@ isdnloop_command(isdn_ctrl * c, isdnloop_card * card) | |||
1210 | } | 1210 | } |
1211 | break; | 1211 | break; |
1212 | case ISDN_CMD_ACCEPTD: | 1212 | case ISDN_CMD_ACCEPTD: |
1213 | if (!card->flags & ISDNLOOP_FLAGS_RUNNING) | 1213 | if (!(card->flags & ISDNLOOP_FLAGS_RUNNING)) |
1214 | return -ENODEV; | 1214 | return -ENODEV; |
1215 | if (c->arg < ISDNLOOP_BCH) { | 1215 | if (c->arg < ISDNLOOP_BCH) { |
1216 | a = c->arg + 1; | 1216 | a = c->arg + 1; |
@@ -1238,7 +1238,7 @@ isdnloop_command(isdn_ctrl * c, isdnloop_card * card) | |||
1238 | } | 1238 | } |
1239 | break; | 1239 | break; |
1240 | case ISDN_CMD_ACCEPTB: | 1240 | case ISDN_CMD_ACCEPTB: |
1241 | if (!card->flags & ISDNLOOP_FLAGS_RUNNING) | 1241 | if (!(card->flags & ISDNLOOP_FLAGS_RUNNING)) |
1242 | return -ENODEV; | 1242 | return -ENODEV; |
1243 | if (c->arg < ISDNLOOP_BCH) { | 1243 | if (c->arg < ISDNLOOP_BCH) { |
1244 | a = c->arg + 1; | 1244 | a = c->arg + 1; |
@@ -1264,7 +1264,7 @@ isdnloop_command(isdn_ctrl * c, isdnloop_card * card) | |||
1264 | i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card); | 1264 | i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card); |
1265 | break; | 1265 | break; |
1266 | case ISDN_CMD_HANGUP: | 1266 | case ISDN_CMD_HANGUP: |
1267 | if (!card->flags & ISDNLOOP_FLAGS_RUNNING) | 1267 | if (!(card->flags & ISDNLOOP_FLAGS_RUNNING)) |
1268 | return -ENODEV; | 1268 | return -ENODEV; |
1269 | if (c->arg < ISDNLOOP_BCH) { | 1269 | if (c->arg < ISDNLOOP_BCH) { |
1270 | a = c->arg + 1; | 1270 | a = c->arg + 1; |
@@ -1273,7 +1273,7 @@ isdnloop_command(isdn_ctrl * c, isdnloop_card * card) | |||
1273 | } | 1273 | } |
1274 | break; | 1274 | break; |
1275 | case ISDN_CMD_SETEAZ: | 1275 | case ISDN_CMD_SETEAZ: |
1276 | if (!card->flags & ISDNLOOP_FLAGS_RUNNING) | 1276 | if (!(card->flags & ISDNLOOP_FLAGS_RUNNING)) |
1277 | return -ENODEV; | 1277 | return -ENODEV; |
1278 | if (card->leased) | 1278 | if (card->leased) |
1279 | break; | 1279 | break; |
@@ -1303,7 +1303,7 @@ isdnloop_command(isdn_ctrl * c, isdnloop_card * card) | |||
1303 | } | 1303 | } |
1304 | break; | 1304 | break; |
1305 | case ISDN_CMD_SETL2: | 1305 | case ISDN_CMD_SETL2: |
1306 | if (!card->flags & ISDNLOOP_FLAGS_RUNNING) | 1306 | if (!(card->flags & ISDNLOOP_FLAGS_RUNNING)) |
1307 | return -ENODEV; | 1307 | return -ENODEV; |
1308 | if ((c->arg & 255) < ISDNLOOP_BCH) { | 1308 | if ((c->arg & 255) < ISDNLOOP_BCH) { |
1309 | a = c->arg; | 1309 | a = c->arg; |
@@ -1395,7 +1395,7 @@ if_readstatus(u_char __user *buf, int len, int id, int channel) | |||
1395 | isdnloop_card *card = isdnloop_findcard(id); | 1395 | isdnloop_card *card = isdnloop_findcard(id); |
1396 | 1396 | ||
1397 | if (card) { | 1397 | if (card) { |
1398 | if (!card->flags & ISDNLOOP_FLAGS_RUNNING) | 1398 | if (!(card->flags & ISDNLOOP_FLAGS_RUNNING)) |
1399 | return -ENODEV; | 1399 | return -ENODEV; |
1400 | return (isdnloop_readstatus(buf, len, card)); | 1400 | return (isdnloop_readstatus(buf, len, card)); |
1401 | } | 1401 | } |
@@ -1410,7 +1410,7 @@ if_sendbuf(int id, int channel, int ack, struct sk_buff *skb) | |||
1410 | isdnloop_card *card = isdnloop_findcard(id); | 1410 | isdnloop_card *card = isdnloop_findcard(id); |
1411 | 1411 | ||
1412 | if (card) { | 1412 | if (card) { |
1413 | if (!card->flags & ISDNLOOP_FLAGS_RUNNING) | 1413 | if (!(card->flags & ISDNLOOP_FLAGS_RUNNING)) |
1414 | return -ENODEV; | 1414 | return -ENODEV; |
1415 | /* ack request stored in skb scratch area */ | 1415 | /* ack request stored in skb scratch area */ |
1416 | *(skb->head) = ack; | 1416 | *(skb->head) = ack; |
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index 1b1ef3130e6e..a0585fb6da94 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c | |||
@@ -237,7 +237,7 @@ static struct page *read_sb_page(mddev_t *mddev, long offset, unsigned long inde | |||
237 | if (!page) | 237 | if (!page) |
238 | return ERR_PTR(-ENOMEM); | 238 | return ERR_PTR(-ENOMEM); |
239 | 239 | ||
240 | ITERATE_RDEV(mddev, rdev, tmp) { | 240 | rdev_for_each(rdev, tmp, mddev) { |
241 | if (! test_bit(In_sync, &rdev->flags) | 241 | if (! test_bit(In_sync, &rdev->flags) |
242 | || test_bit(Faulty, &rdev->flags)) | 242 | || test_bit(Faulty, &rdev->flags)) |
243 | continue; | 243 | continue; |
@@ -261,7 +261,7 @@ static int write_sb_page(struct bitmap *bitmap, struct page *page, int wait) | |||
261 | struct list_head *tmp; | 261 | struct list_head *tmp; |
262 | mddev_t *mddev = bitmap->mddev; | 262 | mddev_t *mddev = bitmap->mddev; |
263 | 263 | ||
264 | ITERATE_RDEV(mddev, rdev, tmp) | 264 | rdev_for_each(rdev, tmp, mddev) |
265 | if (test_bit(In_sync, &rdev->flags) | 265 | if (test_bit(In_sync, &rdev->flags) |
266 | && !test_bit(Faulty, &rdev->flags)) { | 266 | && !test_bit(Faulty, &rdev->flags)) { |
267 | int size = PAGE_SIZE; | 267 | int size = PAGE_SIZE; |
@@ -1348,14 +1348,38 @@ void bitmap_close_sync(struct bitmap *bitmap) | |||
1348 | */ | 1348 | */ |
1349 | sector_t sector = 0; | 1349 | sector_t sector = 0; |
1350 | int blocks; | 1350 | int blocks; |
1351 | if (!bitmap) return; | 1351 | if (!bitmap) |
1352 | return; | ||
1352 | while (sector < bitmap->mddev->resync_max_sectors) { | 1353 | while (sector < bitmap->mddev->resync_max_sectors) { |
1353 | bitmap_end_sync(bitmap, sector, &blocks, 0); | 1354 | bitmap_end_sync(bitmap, sector, &blocks, 0); |
1354 | /* | 1355 | sector += blocks; |
1355 | if (sector < 500) printk("bitmap_close_sync: sec %llu blks %d\n", | 1356 | } |
1356 | (unsigned long long)sector, blocks); | 1357 | } |
1357 | */ sector += blocks; | 1358 | |
1359 | void bitmap_cond_end_sync(struct bitmap *bitmap, sector_t sector) | ||
1360 | { | ||
1361 | sector_t s = 0; | ||
1362 | int blocks; | ||
1363 | |||
1364 | if (!bitmap) | ||
1365 | return; | ||
1366 | if (sector == 0) { | ||
1367 | bitmap->last_end_sync = jiffies; | ||
1368 | return; | ||
1369 | } | ||
1370 | if (time_before(jiffies, (bitmap->last_end_sync | ||
1371 | + bitmap->daemon_sleep * HZ))) | ||
1372 | return; | ||
1373 | wait_event(bitmap->mddev->recovery_wait, | ||
1374 | atomic_read(&bitmap->mddev->recovery_active) == 0); | ||
1375 | |||
1376 | sector &= ~((1ULL << CHUNK_BLOCK_SHIFT(bitmap)) - 1); | ||
1377 | s = 0; | ||
1378 | while (s < sector && s < bitmap->mddev->resync_max_sectors) { | ||
1379 | bitmap_end_sync(bitmap, s, &blocks, 0); | ||
1380 | s += blocks; | ||
1358 | } | 1381 | } |
1382 | bitmap->last_end_sync = jiffies; | ||
1359 | } | 1383 | } |
1360 | 1384 | ||
1361 | static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset, int needed) | 1385 | static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset, int needed) |
@@ -1565,3 +1589,4 @@ EXPORT_SYMBOL(bitmap_start_sync); | |||
1565 | EXPORT_SYMBOL(bitmap_end_sync); | 1589 | EXPORT_SYMBOL(bitmap_end_sync); |
1566 | EXPORT_SYMBOL(bitmap_unplug); | 1590 | EXPORT_SYMBOL(bitmap_unplug); |
1567 | EXPORT_SYMBOL(bitmap_close_sync); | 1591 | EXPORT_SYMBOL(bitmap_close_sync); |
1592 | EXPORT_SYMBOL(bitmap_cond_end_sync); | ||
diff --git a/drivers/md/faulty.c b/drivers/md/faulty.c index cf2ddce34118..d107ddceefcd 100644 --- a/drivers/md/faulty.c +++ b/drivers/md/faulty.c | |||
@@ -294,7 +294,7 @@ static int run(mddev_t *mddev) | |||
294 | } | 294 | } |
295 | conf->nfaults = 0; | 295 | conf->nfaults = 0; |
296 | 296 | ||
297 | ITERATE_RDEV(mddev, rdev, tmp) | 297 | rdev_for_each(rdev, tmp, mddev) |
298 | conf->rdev = rdev; | 298 | conf->rdev = rdev; |
299 | 299 | ||
300 | mddev->array_size = mddev->size; | 300 | mddev->array_size = mddev->size; |
diff --git a/drivers/md/linear.c b/drivers/md/linear.c index 3dac1cfb8189..0b8511776b3e 100644 --- a/drivers/md/linear.c +++ b/drivers/md/linear.c | |||
@@ -122,7 +122,7 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks) | |||
122 | cnt = 0; | 122 | cnt = 0; |
123 | conf->array_size = 0; | 123 | conf->array_size = 0; |
124 | 124 | ||
125 | ITERATE_RDEV(mddev,rdev,tmp) { | 125 | rdev_for_each(rdev, tmp, mddev) { |
126 | int j = rdev->raid_disk; | 126 | int j = rdev->raid_disk; |
127 | dev_info_t *disk = conf->disks + j; | 127 | dev_info_t *disk = conf->disks + j; |
128 | 128 | ||
diff --git a/drivers/md/md.c b/drivers/md/md.c index c28a120b4161..5fc326d3970e 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
@@ -195,7 +195,7 @@ static DEFINE_SPINLOCK(all_mddevs_lock); | |||
195 | * Any code which breaks out of this loop while own | 195 | * Any code which breaks out of this loop while own |
196 | * a reference to the current mddev and must mddev_put it. | 196 | * a reference to the current mddev and must mddev_put it. |
197 | */ | 197 | */ |
198 | #define ITERATE_MDDEV(mddev,tmp) \ | 198 | #define for_each_mddev(mddev,tmp) \ |
199 | \ | 199 | \ |
200 | for (({ spin_lock(&all_mddevs_lock); \ | 200 | for (({ spin_lock(&all_mddevs_lock); \ |
201 | tmp = all_mddevs.next; \ | 201 | tmp = all_mddevs.next; \ |
@@ -275,6 +275,7 @@ static mddev_t * mddev_find(dev_t unit) | |||
275 | spin_lock_init(&new->write_lock); | 275 | spin_lock_init(&new->write_lock); |
276 | init_waitqueue_head(&new->sb_wait); | 276 | init_waitqueue_head(&new->sb_wait); |
277 | new->reshape_position = MaxSector; | 277 | new->reshape_position = MaxSector; |
278 | new->resync_max = MaxSector; | ||
278 | 279 | ||
279 | new->queue = blk_alloc_queue(GFP_KERNEL); | 280 | new->queue = blk_alloc_queue(GFP_KERNEL); |
280 | if (!new->queue) { | 281 | if (!new->queue) { |
@@ -310,7 +311,7 @@ static mdk_rdev_t * find_rdev_nr(mddev_t *mddev, int nr) | |||
310 | mdk_rdev_t * rdev; | 311 | mdk_rdev_t * rdev; |
311 | struct list_head *tmp; | 312 | struct list_head *tmp; |
312 | 313 | ||
313 | ITERATE_RDEV(mddev,rdev,tmp) { | 314 | rdev_for_each(rdev, tmp, mddev) { |
314 | if (rdev->desc_nr == nr) | 315 | if (rdev->desc_nr == nr) |
315 | return rdev; | 316 | return rdev; |
316 | } | 317 | } |
@@ -322,7 +323,7 @@ static mdk_rdev_t * find_rdev(mddev_t * mddev, dev_t dev) | |||
322 | struct list_head *tmp; | 323 | struct list_head *tmp; |
323 | mdk_rdev_t *rdev; | 324 | mdk_rdev_t *rdev; |
324 | 325 | ||
325 | ITERATE_RDEV(mddev,rdev,tmp) { | 326 | rdev_for_each(rdev, tmp, mddev) { |
326 | if (rdev->bdev->bd_dev == dev) | 327 | if (rdev->bdev->bd_dev == dev) |
327 | return rdev; | 328 | return rdev; |
328 | } | 329 | } |
@@ -773,12 +774,16 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev) | |||
773 | __u64 ev1 = md_event(sb); | 774 | __u64 ev1 = md_event(sb); |
774 | 775 | ||
775 | rdev->raid_disk = -1; | 776 | rdev->raid_disk = -1; |
776 | rdev->flags = 0; | 777 | clear_bit(Faulty, &rdev->flags); |
778 | clear_bit(In_sync, &rdev->flags); | ||
779 | clear_bit(WriteMostly, &rdev->flags); | ||
780 | clear_bit(BarriersNotsupp, &rdev->flags); | ||
781 | |||
777 | if (mddev->raid_disks == 0) { | 782 | if (mddev->raid_disks == 0) { |
778 | mddev->major_version = 0; | 783 | mddev->major_version = 0; |
779 | mddev->minor_version = sb->minor_version; | 784 | mddev->minor_version = sb->minor_version; |
780 | mddev->patch_version = sb->patch_version; | 785 | mddev->patch_version = sb->patch_version; |
781 | mddev->persistent = ! sb->not_persistent; | 786 | mddev->external = 0; |
782 | mddev->chunk_size = sb->chunk_size; | 787 | mddev->chunk_size = sb->chunk_size; |
783 | mddev->ctime = sb->ctime; | 788 | mddev->ctime = sb->ctime; |
784 | mddev->utime = sb->utime; | 789 | mddev->utime = sb->utime; |
@@ -904,7 +909,7 @@ static void super_90_sync(mddev_t *mddev, mdk_rdev_t *rdev) | |||
904 | sb->size = mddev->size; | 909 | sb->size = mddev->size; |
905 | sb->raid_disks = mddev->raid_disks; | 910 | sb->raid_disks = mddev->raid_disks; |
906 | sb->md_minor = mddev->md_minor; | 911 | sb->md_minor = mddev->md_minor; |
907 | sb->not_persistent = !mddev->persistent; | 912 | sb->not_persistent = 0; |
908 | sb->utime = mddev->utime; | 913 | sb->utime = mddev->utime; |
909 | sb->state = 0; | 914 | sb->state = 0; |
910 | sb->events_hi = (mddev->events>>32); | 915 | sb->events_hi = (mddev->events>>32); |
@@ -938,7 +943,7 @@ static void super_90_sync(mddev_t *mddev, mdk_rdev_t *rdev) | |||
938 | sb->state |= (1<<MD_SB_BITMAP_PRESENT); | 943 | sb->state |= (1<<MD_SB_BITMAP_PRESENT); |
939 | 944 | ||
940 | sb->disks[0].state = (1<<MD_DISK_REMOVED); | 945 | sb->disks[0].state = (1<<MD_DISK_REMOVED); |
941 | ITERATE_RDEV(mddev,rdev2,tmp) { | 946 | rdev_for_each(rdev2, tmp, mddev) { |
942 | mdp_disk_t *d; | 947 | mdp_disk_t *d; |
943 | int desc_nr; | 948 | int desc_nr; |
944 | if (rdev2->raid_disk >= 0 && test_bit(In_sync, &rdev2->flags) | 949 | if (rdev2->raid_disk >= 0 && test_bit(In_sync, &rdev2->flags) |
@@ -1153,11 +1158,15 @@ static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev) | |||
1153 | __u64 ev1 = le64_to_cpu(sb->events); | 1158 | __u64 ev1 = le64_to_cpu(sb->events); |
1154 | 1159 | ||
1155 | rdev->raid_disk = -1; | 1160 | rdev->raid_disk = -1; |
1156 | rdev->flags = 0; | 1161 | clear_bit(Faulty, &rdev->flags); |
1162 | clear_bit(In_sync, &rdev->flags); | ||
1163 | clear_bit(WriteMostly, &rdev->flags); | ||
1164 | clear_bit(BarriersNotsupp, &rdev->flags); | ||
1165 | |||
1157 | if (mddev->raid_disks == 0) { | 1166 | if (mddev->raid_disks == 0) { |
1158 | mddev->major_version = 1; | 1167 | mddev->major_version = 1; |
1159 | mddev->patch_version = 0; | 1168 | mddev->patch_version = 0; |
1160 | mddev->persistent = 1; | 1169 | mddev->external = 0; |
1161 | mddev->chunk_size = le32_to_cpu(sb->chunksize) << 9; | 1170 | mddev->chunk_size = le32_to_cpu(sb->chunksize) << 9; |
1162 | mddev->ctime = le64_to_cpu(sb->ctime) & ((1ULL << 32)-1); | 1171 | mddev->ctime = le64_to_cpu(sb->ctime) & ((1ULL << 32)-1); |
1163 | mddev->utime = le64_to_cpu(sb->utime) & ((1ULL << 32)-1); | 1172 | mddev->utime = le64_to_cpu(sb->utime) & ((1ULL << 32)-1); |
@@ -1286,7 +1295,7 @@ static void super_1_sync(mddev_t *mddev, mdk_rdev_t *rdev) | |||
1286 | } | 1295 | } |
1287 | 1296 | ||
1288 | max_dev = 0; | 1297 | max_dev = 0; |
1289 | ITERATE_RDEV(mddev,rdev2,tmp) | 1298 | rdev_for_each(rdev2, tmp, mddev) |
1290 | if (rdev2->desc_nr+1 > max_dev) | 1299 | if (rdev2->desc_nr+1 > max_dev) |
1291 | max_dev = rdev2->desc_nr+1; | 1300 | max_dev = rdev2->desc_nr+1; |
1292 | 1301 | ||
@@ -1295,7 +1304,7 @@ static void super_1_sync(mddev_t *mddev, mdk_rdev_t *rdev) | |||
1295 | for (i=0; i<max_dev;i++) | 1304 | for (i=0; i<max_dev;i++) |
1296 | sb->dev_roles[i] = cpu_to_le16(0xfffe); | 1305 | sb->dev_roles[i] = cpu_to_le16(0xfffe); |
1297 | 1306 | ||
1298 | ITERATE_RDEV(mddev,rdev2,tmp) { | 1307 | rdev_for_each(rdev2, tmp, mddev) { |
1299 | i = rdev2->desc_nr; | 1308 | i = rdev2->desc_nr; |
1300 | if (test_bit(Faulty, &rdev2->flags)) | 1309 | if (test_bit(Faulty, &rdev2->flags)) |
1301 | sb->dev_roles[i] = cpu_to_le16(0xfffe); | 1310 | sb->dev_roles[i] = cpu_to_le16(0xfffe); |
@@ -1333,8 +1342,8 @@ static int match_mddev_units(mddev_t *mddev1, mddev_t *mddev2) | |||
1333 | struct list_head *tmp, *tmp2; | 1342 | struct list_head *tmp, *tmp2; |
1334 | mdk_rdev_t *rdev, *rdev2; | 1343 | mdk_rdev_t *rdev, *rdev2; |
1335 | 1344 | ||
1336 | ITERATE_RDEV(mddev1,rdev,tmp) | 1345 | rdev_for_each(rdev, tmp, mddev1) |
1337 | ITERATE_RDEV(mddev2, rdev2, tmp2) | 1346 | rdev_for_each(rdev2, tmp2, mddev2) |
1338 | if (rdev->bdev->bd_contains == | 1347 | if (rdev->bdev->bd_contains == |
1339 | rdev2->bdev->bd_contains) | 1348 | rdev2->bdev->bd_contains) |
1340 | return 1; | 1349 | return 1; |
@@ -1401,7 +1410,7 @@ static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev) | |||
1401 | goto fail; | 1410 | goto fail; |
1402 | } | 1411 | } |
1403 | list_add(&rdev->same_set, &mddev->disks); | 1412 | list_add(&rdev->same_set, &mddev->disks); |
1404 | bd_claim_by_disk(rdev->bdev, rdev, mddev->gendisk); | 1413 | bd_claim_by_disk(rdev->bdev, rdev->bdev->bd_holder, mddev->gendisk); |
1405 | return 0; | 1414 | return 0; |
1406 | 1415 | ||
1407 | fail: | 1416 | fail: |
@@ -1410,10 +1419,11 @@ static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev) | |||
1410 | return err; | 1419 | return err; |
1411 | } | 1420 | } |
1412 | 1421 | ||
1413 | static void delayed_delete(struct work_struct *ws) | 1422 | static void md_delayed_delete(struct work_struct *ws) |
1414 | { | 1423 | { |
1415 | mdk_rdev_t *rdev = container_of(ws, mdk_rdev_t, del_work); | 1424 | mdk_rdev_t *rdev = container_of(ws, mdk_rdev_t, del_work); |
1416 | kobject_del(&rdev->kobj); | 1425 | kobject_del(&rdev->kobj); |
1426 | kobject_put(&rdev->kobj); | ||
1417 | } | 1427 | } |
1418 | 1428 | ||
1419 | static void unbind_rdev_from_array(mdk_rdev_t * rdev) | 1429 | static void unbind_rdev_from_array(mdk_rdev_t * rdev) |
@@ -1432,7 +1442,8 @@ static void unbind_rdev_from_array(mdk_rdev_t * rdev) | |||
1432 | /* We need to delay this, otherwise we can deadlock when | 1442 | /* We need to delay this, otherwise we can deadlock when |
1433 | * writing to 'remove' to "dev/state" | 1443 | * writing to 'remove' to "dev/state" |
1434 | */ | 1444 | */ |
1435 | INIT_WORK(&rdev->del_work, delayed_delete); | 1445 | INIT_WORK(&rdev->del_work, md_delayed_delete); |
1446 | kobject_get(&rdev->kobj); | ||
1436 | schedule_work(&rdev->del_work); | 1447 | schedule_work(&rdev->del_work); |
1437 | } | 1448 | } |
1438 | 1449 | ||
@@ -1441,7 +1452,7 @@ static void unbind_rdev_from_array(mdk_rdev_t * rdev) | |||
1441 | * otherwise reused by a RAID array (or any other kernel | 1452 | * otherwise reused by a RAID array (or any other kernel |
1442 | * subsystem), by bd_claiming the device. | 1453 | * subsystem), by bd_claiming the device. |
1443 | */ | 1454 | */ |
1444 | static int lock_rdev(mdk_rdev_t *rdev, dev_t dev) | 1455 | static int lock_rdev(mdk_rdev_t *rdev, dev_t dev, int shared) |
1445 | { | 1456 | { |
1446 | int err = 0; | 1457 | int err = 0; |
1447 | struct block_device *bdev; | 1458 | struct block_device *bdev; |
@@ -1453,13 +1464,15 @@ static int lock_rdev(mdk_rdev_t *rdev, dev_t dev) | |||
1453 | __bdevname(dev, b)); | 1464 | __bdevname(dev, b)); |
1454 | return PTR_ERR(bdev); | 1465 | return PTR_ERR(bdev); |
1455 | } | 1466 | } |
1456 | err = bd_claim(bdev, rdev); | 1467 | err = bd_claim(bdev, shared ? (mdk_rdev_t *)lock_rdev : rdev); |
1457 | if (err) { | 1468 | if (err) { |
1458 | printk(KERN_ERR "md: could not bd_claim %s.\n", | 1469 | printk(KERN_ERR "md: could not bd_claim %s.\n", |
1459 | bdevname(bdev, b)); | 1470 | bdevname(bdev, b)); |
1460 | blkdev_put(bdev); | 1471 | blkdev_put(bdev); |
1461 | return err; | 1472 | return err; |
1462 | } | 1473 | } |
1474 | if (!shared) | ||
1475 | set_bit(AllReserved, &rdev->flags); | ||
1463 | rdev->bdev = bdev; | 1476 | rdev->bdev = bdev; |
1464 | return err; | 1477 | return err; |
1465 | } | 1478 | } |
@@ -1503,7 +1516,7 @@ static void export_array(mddev_t *mddev) | |||
1503 | struct list_head *tmp; | 1516 | struct list_head *tmp; |
1504 | mdk_rdev_t *rdev; | 1517 | mdk_rdev_t *rdev; |
1505 | 1518 | ||
1506 | ITERATE_RDEV(mddev,rdev,tmp) { | 1519 | rdev_for_each(rdev, tmp, mddev) { |
1507 | if (!rdev->mddev) { | 1520 | if (!rdev->mddev) { |
1508 | MD_BUG(); | 1521 | MD_BUG(); |
1509 | continue; | 1522 | continue; |
@@ -1581,17 +1594,17 @@ static void md_print_devices(void) | |||
1581 | printk("md: **********************************\n"); | 1594 | printk("md: **********************************\n"); |
1582 | printk("md: * <COMPLETE RAID STATE PRINTOUT> *\n"); | 1595 | printk("md: * <COMPLETE RAID STATE PRINTOUT> *\n"); |
1583 | printk("md: **********************************\n"); | 1596 | printk("md: **********************************\n"); |
1584 | ITERATE_MDDEV(mddev,tmp) { | 1597 | for_each_mddev(mddev, tmp) { |
1585 | 1598 | ||
1586 | if (mddev->bitmap) | 1599 | if (mddev->bitmap) |
1587 | bitmap_print_sb(mddev->bitmap); | 1600 | bitmap_print_sb(mddev->bitmap); |
1588 | else | 1601 | else |
1589 | printk("%s: ", mdname(mddev)); | 1602 | printk("%s: ", mdname(mddev)); |
1590 | ITERATE_RDEV(mddev,rdev,tmp2) | 1603 | rdev_for_each(rdev, tmp2, mddev) |
1591 | printk("<%s>", bdevname(rdev->bdev,b)); | 1604 | printk("<%s>", bdevname(rdev->bdev,b)); |
1592 | printk("\n"); | 1605 | printk("\n"); |
1593 | 1606 | ||
1594 | ITERATE_RDEV(mddev,rdev,tmp2) | 1607 | rdev_for_each(rdev, tmp2, mddev) |
1595 | print_rdev(rdev); | 1608 | print_rdev(rdev); |
1596 | } | 1609 | } |
1597 | printk("md: **********************************\n"); | 1610 | printk("md: **********************************\n"); |
@@ -1610,7 +1623,7 @@ static void sync_sbs(mddev_t * mddev, int nospares) | |||
1610 | mdk_rdev_t *rdev; | 1623 | mdk_rdev_t *rdev; |
1611 | struct list_head *tmp; | 1624 | struct list_head *tmp; |
1612 | 1625 | ||
1613 | ITERATE_RDEV(mddev,rdev,tmp) { | 1626 | rdev_for_each(rdev, tmp, mddev) { |
1614 | if (rdev->sb_events == mddev->events || | 1627 | if (rdev->sb_events == mddev->events || |
1615 | (nospares && | 1628 | (nospares && |
1616 | rdev->raid_disk < 0 && | 1629 | rdev->raid_disk < 0 && |
@@ -1696,18 +1709,20 @@ repeat: | |||
1696 | MD_BUG(); | 1709 | MD_BUG(); |
1697 | mddev->events --; | 1710 | mddev->events --; |
1698 | } | 1711 | } |
1699 | sync_sbs(mddev, nospares); | ||
1700 | 1712 | ||
1701 | /* | 1713 | /* |
1702 | * do not write anything to disk if using | 1714 | * do not write anything to disk if using |
1703 | * nonpersistent superblocks | 1715 | * nonpersistent superblocks |
1704 | */ | 1716 | */ |
1705 | if (!mddev->persistent) { | 1717 | if (!mddev->persistent) { |
1706 | clear_bit(MD_CHANGE_PENDING, &mddev->flags); | 1718 | if (!mddev->external) |
1719 | clear_bit(MD_CHANGE_PENDING, &mddev->flags); | ||
1720 | |||
1707 | spin_unlock_irq(&mddev->write_lock); | 1721 | spin_unlock_irq(&mddev->write_lock); |
1708 | wake_up(&mddev->sb_wait); | 1722 | wake_up(&mddev->sb_wait); |
1709 | return; | 1723 | return; |
1710 | } | 1724 | } |
1725 | sync_sbs(mddev, nospares); | ||
1711 | spin_unlock_irq(&mddev->write_lock); | 1726 | spin_unlock_irq(&mddev->write_lock); |
1712 | 1727 | ||
1713 | dprintk(KERN_INFO | 1728 | dprintk(KERN_INFO |
@@ -1715,7 +1730,7 @@ repeat: | |||
1715 | mdname(mddev),mddev->in_sync); | 1730 | mdname(mddev),mddev->in_sync); |
1716 | 1731 | ||
1717 | bitmap_update_sb(mddev->bitmap); | 1732 | bitmap_update_sb(mddev->bitmap); |
1718 | ITERATE_RDEV(mddev,rdev,tmp) { | 1733 | rdev_for_each(rdev, tmp, mddev) { |
1719 | char b[BDEVNAME_SIZE]; | 1734 | char b[BDEVNAME_SIZE]; |
1720 | dprintk(KERN_INFO "md: "); | 1735 | dprintk(KERN_INFO "md: "); |
1721 | if (rdev->sb_loaded != 1) | 1736 | if (rdev->sb_loaded != 1) |
@@ -1785,7 +1800,7 @@ static ssize_t | |||
1785 | state_show(mdk_rdev_t *rdev, char *page) | 1800 | state_show(mdk_rdev_t *rdev, char *page) |
1786 | { | 1801 | { |
1787 | char *sep = ""; | 1802 | char *sep = ""; |
1788 | int len=0; | 1803 | size_t len = 0; |
1789 | 1804 | ||
1790 | if (test_bit(Faulty, &rdev->flags)) { | 1805 | if (test_bit(Faulty, &rdev->flags)) { |
1791 | len+= sprintf(page+len, "%sfaulty",sep); | 1806 | len+= sprintf(page+len, "%sfaulty",sep); |
@@ -1887,20 +1902,45 @@ static ssize_t | |||
1887 | slot_store(mdk_rdev_t *rdev, const char *buf, size_t len) | 1902 | slot_store(mdk_rdev_t *rdev, const char *buf, size_t len) |
1888 | { | 1903 | { |
1889 | char *e; | 1904 | char *e; |
1905 | int err; | ||
1906 | char nm[20]; | ||
1890 | int slot = simple_strtoul(buf, &e, 10); | 1907 | int slot = simple_strtoul(buf, &e, 10); |
1891 | if (strncmp(buf, "none", 4)==0) | 1908 | if (strncmp(buf, "none", 4)==0) |
1892 | slot = -1; | 1909 | slot = -1; |
1893 | else if (e==buf || (*e && *e!= '\n')) | 1910 | else if (e==buf || (*e && *e!= '\n')) |
1894 | return -EINVAL; | 1911 | return -EINVAL; |
1895 | if (rdev->mddev->pers) | 1912 | if (rdev->mddev->pers) { |
1896 | /* Cannot set slot in active array (yet) */ | 1913 | /* Setting 'slot' on an active array requires also |
1897 | return -EBUSY; | 1914 | * updating the 'rd%d' link, and communicating |
1898 | if (slot >= rdev->mddev->raid_disks) | 1915 | * with the personality with ->hot_*_disk. |
1899 | return -ENOSPC; | 1916 | * For now we only support removing |
1900 | rdev->raid_disk = slot; | 1917 | * failed/spare devices. This normally happens automatically, |
1901 | /* assume it is working */ | 1918 | * but not when the metadata is externally managed. |
1902 | rdev->flags = 0; | 1919 | */ |
1903 | set_bit(In_sync, &rdev->flags); | 1920 | if (slot != -1) |
1921 | return -EBUSY; | ||
1922 | if (rdev->raid_disk == -1) | ||
1923 | return -EEXIST; | ||
1924 | /* personality does all needed checks */ | ||
1925 | if (rdev->mddev->pers->hot_add_disk == NULL) | ||
1926 | return -EINVAL; | ||
1927 | err = rdev->mddev->pers-> | ||
1928 | hot_remove_disk(rdev->mddev, rdev->raid_disk); | ||
1929 | if (err) | ||
1930 | return err; | ||
1931 | sprintf(nm, "rd%d", rdev->raid_disk); | ||
1932 | sysfs_remove_link(&rdev->mddev->kobj, nm); | ||
1933 | set_bit(MD_RECOVERY_NEEDED, &rdev->mddev->recovery); | ||
1934 | md_wakeup_thread(rdev->mddev->thread); | ||
1935 | } else { | ||
1936 | if (slot >= rdev->mddev->raid_disks) | ||
1937 | return -ENOSPC; | ||
1938 | rdev->raid_disk = slot; | ||
1939 | /* assume it is working */ | ||
1940 | clear_bit(Faulty, &rdev->flags); | ||
1941 | clear_bit(WriteMostly, &rdev->flags); | ||
1942 | set_bit(In_sync, &rdev->flags); | ||
1943 | } | ||
1904 | return len; | 1944 | return len; |
1905 | } | 1945 | } |
1906 | 1946 | ||
@@ -1923,6 +1963,10 @@ offset_store(mdk_rdev_t *rdev, const char *buf, size_t len) | |||
1923 | return -EINVAL; | 1963 | return -EINVAL; |
1924 | if (rdev->mddev->pers) | 1964 | if (rdev->mddev->pers) |
1925 | return -EBUSY; | 1965 | return -EBUSY; |
1966 | if (rdev->size && rdev->mddev->external) | ||
1967 | /* Must set offset before size, so overlap checks | ||
1968 | * can be sane */ | ||
1969 | return -EBUSY; | ||
1926 | rdev->data_offset = offset; | 1970 | rdev->data_offset = offset; |
1927 | return len; | 1971 | return len; |
1928 | } | 1972 | } |
@@ -1936,16 +1980,69 @@ rdev_size_show(mdk_rdev_t *rdev, char *page) | |||
1936 | return sprintf(page, "%llu\n", (unsigned long long)rdev->size); | 1980 | return sprintf(page, "%llu\n", (unsigned long long)rdev->size); |
1937 | } | 1981 | } |
1938 | 1982 | ||
1983 | static int overlaps(sector_t s1, sector_t l1, sector_t s2, sector_t l2) | ||
1984 | { | ||
1985 | /* check if two start/length pairs overlap */ | ||
1986 | if (s1+l1 <= s2) | ||
1987 | return 0; | ||
1988 | if (s2+l2 <= s1) | ||
1989 | return 0; | ||
1990 | return 1; | ||
1991 | } | ||
1992 | |||
1939 | static ssize_t | 1993 | static ssize_t |
1940 | rdev_size_store(mdk_rdev_t *rdev, const char *buf, size_t len) | 1994 | rdev_size_store(mdk_rdev_t *rdev, const char *buf, size_t len) |
1941 | { | 1995 | { |
1942 | char *e; | 1996 | char *e; |
1943 | unsigned long long size = simple_strtoull(buf, &e, 10); | 1997 | unsigned long long size = simple_strtoull(buf, &e, 10); |
1998 | unsigned long long oldsize = rdev->size; | ||
1944 | if (e==buf || (*e && *e != '\n')) | 1999 | if (e==buf || (*e && *e != '\n')) |
1945 | return -EINVAL; | 2000 | return -EINVAL; |
1946 | if (rdev->mddev->pers) | 2001 | if (rdev->mddev->pers) |
1947 | return -EBUSY; | 2002 | return -EBUSY; |
1948 | rdev->size = size; | 2003 | rdev->size = size; |
2004 | if (size > oldsize && rdev->mddev->external) { | ||
2005 | /* need to check that all other rdevs with the same ->bdev | ||
2006 | * do not overlap. We need to unlock the mddev to avoid | ||
2007 | * a deadlock. We have already changed rdev->size, and if | ||
2008 | * we have to change it back, we will have the lock again. | ||
2009 | */ | ||
2010 | mddev_t *mddev; | ||
2011 | int overlap = 0; | ||
2012 | struct list_head *tmp, *tmp2; | ||
2013 | |||
2014 | mddev_unlock(rdev->mddev); | ||
2015 | for_each_mddev(mddev, tmp) { | ||
2016 | mdk_rdev_t *rdev2; | ||
2017 | |||
2018 | mddev_lock(mddev); | ||
2019 | rdev_for_each(rdev2, tmp2, mddev) | ||
2020 | if (test_bit(AllReserved, &rdev2->flags) || | ||
2021 | (rdev->bdev == rdev2->bdev && | ||
2022 | rdev != rdev2 && | ||
2023 | overlaps(rdev->data_offset, rdev->size, | ||
2024 | rdev2->data_offset, rdev2->size))) { | ||
2025 | overlap = 1; | ||
2026 | break; | ||
2027 | } | ||
2028 | mddev_unlock(mddev); | ||
2029 | if (overlap) { | ||
2030 | mddev_put(mddev); | ||
2031 | break; | ||
2032 | } | ||
2033 | } | ||
2034 | mddev_lock(rdev->mddev); | ||
2035 | if (overlap) { | ||
2036 | /* Someone else could have slipped in a size | ||
2037 | * change here, but doing so is just silly. | ||
2038 | * We put oldsize back because we *know* it is | ||
2039 | * safe, and trust userspace not to race with | ||
2040 | * itself | ||
2041 | */ | ||
2042 | rdev->size = oldsize; | ||
2043 | return -EBUSY; | ||
2044 | } | ||
2045 | } | ||
1949 | if (size < rdev->mddev->size || rdev->mddev->size == 0) | 2046 | if (size < rdev->mddev->size || rdev->mddev->size == 0) |
1950 | rdev->mddev->size = size; | 2047 | rdev->mddev->size = size; |
1951 | return len; | 2048 | return len; |
@@ -1980,12 +2077,18 @@ rdev_attr_store(struct kobject *kobj, struct attribute *attr, | |||
1980 | { | 2077 | { |
1981 | struct rdev_sysfs_entry *entry = container_of(attr, struct rdev_sysfs_entry, attr); | 2078 | struct rdev_sysfs_entry *entry = container_of(attr, struct rdev_sysfs_entry, attr); |
1982 | mdk_rdev_t *rdev = container_of(kobj, mdk_rdev_t, kobj); | 2079 | mdk_rdev_t *rdev = container_of(kobj, mdk_rdev_t, kobj); |
2080 | int rv; | ||
1983 | 2081 | ||
1984 | if (!entry->store) | 2082 | if (!entry->store) |
1985 | return -EIO; | 2083 | return -EIO; |
1986 | if (!capable(CAP_SYS_ADMIN)) | 2084 | if (!capable(CAP_SYS_ADMIN)) |
1987 | return -EACCES; | 2085 | return -EACCES; |
1988 | return entry->store(rdev, page, length); | 2086 | rv = mddev_lock(rdev->mddev); |
2087 | if (!rv) { | ||
2088 | rv = entry->store(rdev, page, length); | ||
2089 | mddev_unlock(rdev->mddev); | ||
2090 | } | ||
2091 | return rv; | ||
1989 | } | 2092 | } |
1990 | 2093 | ||
1991 | static void rdev_free(struct kobject *ko) | 2094 | static void rdev_free(struct kobject *ko) |
@@ -2029,7 +2132,7 @@ static mdk_rdev_t *md_import_device(dev_t newdev, int super_format, int super_mi | |||
2029 | if ((err = alloc_disk_sb(rdev))) | 2132 | if ((err = alloc_disk_sb(rdev))) |
2030 | goto abort_free; | 2133 | goto abort_free; |
2031 | 2134 | ||
2032 | err = lock_rdev(rdev, newdev); | 2135 | err = lock_rdev(rdev, newdev, super_format == -2); |
2033 | if (err) | 2136 | if (err) |
2034 | goto abort_free; | 2137 | goto abort_free; |
2035 | 2138 | ||
@@ -2099,7 +2202,7 @@ static void analyze_sbs(mddev_t * mddev) | |||
2099 | char b[BDEVNAME_SIZE]; | 2202 | char b[BDEVNAME_SIZE]; |
2100 | 2203 | ||
2101 | freshest = NULL; | 2204 | freshest = NULL; |
2102 | ITERATE_RDEV(mddev,rdev,tmp) | 2205 | rdev_for_each(rdev, tmp, mddev) |
2103 | switch (super_types[mddev->major_version]. | 2206 | switch (super_types[mddev->major_version]. |
2104 | load_super(rdev, freshest, mddev->minor_version)) { | 2207 | load_super(rdev, freshest, mddev->minor_version)) { |
2105 | case 1: | 2208 | case 1: |
@@ -2120,7 +2223,7 @@ static void analyze_sbs(mddev_t * mddev) | |||
2120 | validate_super(mddev, freshest); | 2223 | validate_super(mddev, freshest); |
2121 | 2224 | ||
2122 | i = 0; | 2225 | i = 0; |
2123 | ITERATE_RDEV(mddev,rdev,tmp) { | 2226 | rdev_for_each(rdev, tmp, mddev) { |
2124 | if (rdev != freshest) | 2227 | if (rdev != freshest) |
2125 | if (super_types[mddev->major_version]. | 2228 | if (super_types[mddev->major_version]. |
2126 | validate_super(mddev, rdev)) { | 2229 | validate_super(mddev, rdev)) { |
@@ -2215,7 +2318,7 @@ level_show(mddev_t *mddev, char *page) | |||
2215 | static ssize_t | 2318 | static ssize_t |
2216 | level_store(mddev_t *mddev, const char *buf, size_t len) | 2319 | level_store(mddev_t *mddev, const char *buf, size_t len) |
2217 | { | 2320 | { |
2218 | int rv = len; | 2321 | ssize_t rv = len; |
2219 | if (mddev->pers) | 2322 | if (mddev->pers) |
2220 | return -EBUSY; | 2323 | return -EBUSY; |
2221 | if (len == 0) | 2324 | if (len == 0) |
@@ -2425,6 +2528,8 @@ array_state_show(mddev_t *mddev, char *page) | |||
2425 | case 0: | 2528 | case 0: |
2426 | if (mddev->in_sync) | 2529 | if (mddev->in_sync) |
2427 | st = clean; | 2530 | st = clean; |
2531 | else if (test_bit(MD_CHANGE_CLEAN, &mddev->flags)) | ||
2532 | st = write_pending; | ||
2428 | else if (mddev->safemode) | 2533 | else if (mddev->safemode) |
2429 | st = active_idle; | 2534 | st = active_idle; |
2430 | else | 2535 | else |
@@ -2455,11 +2560,9 @@ array_state_store(mddev_t *mddev, const char *buf, size_t len) | |||
2455 | break; | 2560 | break; |
2456 | case clear: | 2561 | case clear: |
2457 | /* stopping an active array */ | 2562 | /* stopping an active array */ |
2458 | if (mddev->pers) { | 2563 | if (atomic_read(&mddev->active) > 1) |
2459 | if (atomic_read(&mddev->active) > 1) | 2564 | return -EBUSY; |
2460 | return -EBUSY; | 2565 | err = do_md_stop(mddev, 0); |
2461 | err = do_md_stop(mddev, 0); | ||
2462 | } | ||
2463 | break; | 2566 | break; |
2464 | case inactive: | 2567 | case inactive: |
2465 | /* stopping an active array */ | 2568 | /* stopping an active array */ |
@@ -2467,7 +2570,8 @@ array_state_store(mddev_t *mddev, const char *buf, size_t len) | |||
2467 | if (atomic_read(&mddev->active) > 1) | 2570 | if (atomic_read(&mddev->active) > 1) |
2468 | return -EBUSY; | 2571 | return -EBUSY; |
2469 | err = do_md_stop(mddev, 2); | 2572 | err = do_md_stop(mddev, 2); |
2470 | } | 2573 | } else |
2574 | err = 0; /* already inactive */ | ||
2471 | break; | 2575 | break; |
2472 | case suspended: | 2576 | case suspended: |
2473 | break; /* not supported yet */ | 2577 | break; /* not supported yet */ |
@@ -2495,9 +2599,15 @@ array_state_store(mddev_t *mddev, const char *buf, size_t len) | |||
2495 | restart_array(mddev); | 2599 | restart_array(mddev); |
2496 | spin_lock_irq(&mddev->write_lock); | 2600 | spin_lock_irq(&mddev->write_lock); |
2497 | if (atomic_read(&mddev->writes_pending) == 0) { | 2601 | if (atomic_read(&mddev->writes_pending) == 0) { |
2498 | mddev->in_sync = 1; | 2602 | if (mddev->in_sync == 0) { |
2499 | set_bit(MD_CHANGE_CLEAN, &mddev->flags); | 2603 | mddev->in_sync = 1; |
2500 | } | 2604 | if (mddev->persistent) |
2605 | set_bit(MD_CHANGE_CLEAN, | ||
2606 | &mddev->flags); | ||
2607 | } | ||
2608 | err = 0; | ||
2609 | } else | ||
2610 | err = -EBUSY; | ||
2501 | spin_unlock_irq(&mddev->write_lock); | 2611 | spin_unlock_irq(&mddev->write_lock); |
2502 | } else { | 2612 | } else { |
2503 | mddev->ro = 0; | 2613 | mddev->ro = 0; |
@@ -2508,7 +2618,8 @@ array_state_store(mddev_t *mddev, const char *buf, size_t len) | |||
2508 | case active: | 2618 | case active: |
2509 | if (mddev->pers) { | 2619 | if (mddev->pers) { |
2510 | restart_array(mddev); | 2620 | restart_array(mddev); |
2511 | clear_bit(MD_CHANGE_CLEAN, &mddev->flags); | 2621 | if (mddev->external) |
2622 | clear_bit(MD_CHANGE_CLEAN, &mddev->flags); | ||
2512 | wake_up(&mddev->sb_wait); | 2623 | wake_up(&mddev->sb_wait); |
2513 | err = 0; | 2624 | err = 0; |
2514 | } else { | 2625 | } else { |
@@ -2574,7 +2685,9 @@ new_dev_store(mddev_t *mddev, const char *buf, size_t len) | |||
2574 | if (err < 0) | 2685 | if (err < 0) |
2575 | goto out; | 2686 | goto out; |
2576 | } | 2687 | } |
2577 | } else | 2688 | } else if (mddev->external) |
2689 | rdev = md_import_device(dev, -2, -1); | ||
2690 | else | ||
2578 | rdev = md_import_device(dev, -1, -1); | 2691 | rdev = md_import_device(dev, -1, -1); |
2579 | 2692 | ||
2580 | if (IS_ERR(rdev)) | 2693 | if (IS_ERR(rdev)) |
@@ -2659,7 +2772,9 @@ __ATTR(component_size, S_IRUGO|S_IWUSR, size_show, size_store); | |||
2659 | 2772 | ||
2660 | 2773 | ||
2661 | /* Metdata version. | 2774 | /* Metdata version. |
2662 | * This is either 'none' for arrays with externally managed metadata, | 2775 | * This is one of |
2776 | * 'none' for arrays with no metadata (good luck...) | ||
2777 | * 'external' for arrays with externally managed metadata, | ||
2663 | * or N.M for internally known formats | 2778 | * or N.M for internally known formats |
2664 | */ | 2779 | */ |
2665 | static ssize_t | 2780 | static ssize_t |
@@ -2668,6 +2783,8 @@ metadata_show(mddev_t *mddev, char *page) | |||
2668 | if (mddev->persistent) | 2783 | if (mddev->persistent) |
2669 | return sprintf(page, "%d.%d\n", | 2784 | return sprintf(page, "%d.%d\n", |
2670 | mddev->major_version, mddev->minor_version); | 2785 | mddev->major_version, mddev->minor_version); |
2786 | else if (mddev->external) | ||
2787 | return sprintf(page, "external:%s\n", mddev->metadata_type); | ||
2671 | else | 2788 | else |
2672 | return sprintf(page, "none\n"); | 2789 | return sprintf(page, "none\n"); |
2673 | } | 2790 | } |
@@ -2682,6 +2799,21 @@ metadata_store(mddev_t *mddev, const char *buf, size_t len) | |||
2682 | 2799 | ||
2683 | if (cmd_match(buf, "none")) { | 2800 | if (cmd_match(buf, "none")) { |
2684 | mddev->persistent = 0; | 2801 | mddev->persistent = 0; |
2802 | mddev->external = 0; | ||
2803 | mddev->major_version = 0; | ||
2804 | mddev->minor_version = 90; | ||
2805 | return len; | ||
2806 | } | ||
2807 | if (strncmp(buf, "external:", 9) == 0) { | ||
2808 | size_t namelen = len-9; | ||
2809 | if (namelen >= sizeof(mddev->metadata_type)) | ||
2810 | namelen = sizeof(mddev->metadata_type)-1; | ||
2811 | strncpy(mddev->metadata_type, buf+9, namelen); | ||
2812 | mddev->metadata_type[namelen] = 0; | ||
2813 | if (namelen && mddev->metadata_type[namelen-1] == '\n') | ||
2814 | mddev->metadata_type[--namelen] = 0; | ||
2815 | mddev->persistent = 0; | ||
2816 | mddev->external = 1; | ||
2685 | mddev->major_version = 0; | 2817 | mddev->major_version = 0; |
2686 | mddev->minor_version = 90; | 2818 | mddev->minor_version = 90; |
2687 | return len; | 2819 | return len; |
@@ -2698,6 +2830,7 @@ metadata_store(mddev_t *mddev, const char *buf, size_t len) | |||
2698 | mddev->major_version = major; | 2830 | mddev->major_version = major; |
2699 | mddev->minor_version = minor; | 2831 | mddev->minor_version = minor; |
2700 | mddev->persistent = 1; | 2832 | mddev->persistent = 1; |
2833 | mddev->external = 0; | ||
2701 | return len; | 2834 | return len; |
2702 | } | 2835 | } |
2703 | 2836 | ||
@@ -2865,6 +2998,43 @@ sync_completed_show(mddev_t *mddev, char *page) | |||
2865 | static struct md_sysfs_entry md_sync_completed = __ATTR_RO(sync_completed); | 2998 | static struct md_sysfs_entry md_sync_completed = __ATTR_RO(sync_completed); |
2866 | 2999 | ||
2867 | static ssize_t | 3000 | static ssize_t |
3001 | max_sync_show(mddev_t *mddev, char *page) | ||
3002 | { | ||
3003 | if (mddev->resync_max == MaxSector) | ||
3004 | return sprintf(page, "max\n"); | ||
3005 | else | ||
3006 | return sprintf(page, "%llu\n", | ||
3007 | (unsigned long long)mddev->resync_max); | ||
3008 | } | ||
3009 | static ssize_t | ||
3010 | max_sync_store(mddev_t *mddev, const char *buf, size_t len) | ||
3011 | { | ||
3012 | if (strncmp(buf, "max", 3) == 0) | ||
3013 | mddev->resync_max = MaxSector; | ||
3014 | else { | ||
3015 | char *ep; | ||
3016 | unsigned long long max = simple_strtoull(buf, &ep, 10); | ||
3017 | if (ep == buf || (*ep != 0 && *ep != '\n')) | ||
3018 | return -EINVAL; | ||
3019 | if (max < mddev->resync_max && | ||
3020 | test_bit(MD_RECOVERY_RUNNING, &mddev->recovery)) | ||
3021 | return -EBUSY; | ||
3022 | |||
3023 | /* Must be a multiple of chunk_size */ | ||
3024 | if (mddev->chunk_size) { | ||
3025 | if (max & (sector_t)((mddev->chunk_size>>9)-1)) | ||
3026 | return -EINVAL; | ||
3027 | } | ||
3028 | mddev->resync_max = max; | ||
3029 | } | ||
3030 | wake_up(&mddev->recovery_wait); | ||
3031 | return len; | ||
3032 | } | ||
3033 | |||
3034 | static struct md_sysfs_entry md_max_sync = | ||
3035 | __ATTR(sync_max, S_IRUGO|S_IWUSR, max_sync_show, max_sync_store); | ||
3036 | |||
3037 | static ssize_t | ||
2868 | suspend_lo_show(mddev_t *mddev, char *page) | 3038 | suspend_lo_show(mddev_t *mddev, char *page) |
2869 | { | 3039 | { |
2870 | return sprintf(page, "%llu\n", (unsigned long long)mddev->suspend_lo); | 3040 | return sprintf(page, "%llu\n", (unsigned long long)mddev->suspend_lo); |
@@ -2974,6 +3144,7 @@ static struct attribute *md_redundancy_attrs[] = { | |||
2974 | &md_sync_max.attr, | 3144 | &md_sync_max.attr, |
2975 | &md_sync_speed.attr, | 3145 | &md_sync_speed.attr, |
2976 | &md_sync_completed.attr, | 3146 | &md_sync_completed.attr, |
3147 | &md_max_sync.attr, | ||
2977 | &md_suspend_lo.attr, | 3148 | &md_suspend_lo.attr, |
2978 | &md_suspend_hi.attr, | 3149 | &md_suspend_hi.attr, |
2979 | &md_bitmap.attr, | 3150 | &md_bitmap.attr, |
@@ -3118,8 +3289,11 @@ static int do_md_run(mddev_t * mddev) | |||
3118 | /* | 3289 | /* |
3119 | * Analyze all RAID superblock(s) | 3290 | * Analyze all RAID superblock(s) |
3120 | */ | 3291 | */ |
3121 | if (!mddev->raid_disks) | 3292 | if (!mddev->raid_disks) { |
3293 | if (!mddev->persistent) | ||
3294 | return -EINVAL; | ||
3122 | analyze_sbs(mddev); | 3295 | analyze_sbs(mddev); |
3296 | } | ||
3123 | 3297 | ||
3124 | chunk_size = mddev->chunk_size; | 3298 | chunk_size = mddev->chunk_size; |
3125 | 3299 | ||
@@ -3143,7 +3317,7 @@ static int do_md_run(mddev_t * mddev) | |||
3143 | } | 3317 | } |
3144 | 3318 | ||
3145 | /* devices must have minimum size of one chunk */ | 3319 | /* devices must have minimum size of one chunk */ |
3146 | ITERATE_RDEV(mddev,rdev,tmp) { | 3320 | rdev_for_each(rdev, tmp, mddev) { |
3147 | if (test_bit(Faulty, &rdev->flags)) | 3321 | if (test_bit(Faulty, &rdev->flags)) |
3148 | continue; | 3322 | continue; |
3149 | if (rdev->size < chunk_size / 1024) { | 3323 | if (rdev->size < chunk_size / 1024) { |
@@ -3170,7 +3344,7 @@ static int do_md_run(mddev_t * mddev) | |||
3170 | * the only valid external interface is through the md | 3344 | * the only valid external interface is through the md |
3171 | * device. | 3345 | * device. |
3172 | */ | 3346 | */ |
3173 | ITERATE_RDEV(mddev,rdev,tmp) { | 3347 | rdev_for_each(rdev, tmp, mddev) { |
3174 | if (test_bit(Faulty, &rdev->flags)) | 3348 | if (test_bit(Faulty, &rdev->flags)) |
3175 | continue; | 3349 | continue; |
3176 | sync_blockdev(rdev->bdev); | 3350 | sync_blockdev(rdev->bdev); |
@@ -3236,8 +3410,8 @@ static int do_md_run(mddev_t * mddev) | |||
3236 | mdk_rdev_t *rdev2; | 3410 | mdk_rdev_t *rdev2; |
3237 | struct list_head *tmp2; | 3411 | struct list_head *tmp2; |
3238 | int warned = 0; | 3412 | int warned = 0; |
3239 | ITERATE_RDEV(mddev, rdev, tmp) { | 3413 | rdev_for_each(rdev, tmp, mddev) { |
3240 | ITERATE_RDEV(mddev, rdev2, tmp2) { | 3414 | rdev_for_each(rdev2, tmp2, mddev) { |
3241 | if (rdev < rdev2 && | 3415 | if (rdev < rdev2 && |
3242 | rdev->bdev->bd_contains == | 3416 | rdev->bdev->bd_contains == |
3243 | rdev2->bdev->bd_contains) { | 3417 | rdev2->bdev->bd_contains) { |
@@ -3297,7 +3471,7 @@ static int do_md_run(mddev_t * mddev) | |||
3297 | mddev->safemode_delay = (200 * HZ)/1000 +1; /* 200 msec delay */ | 3471 | mddev->safemode_delay = (200 * HZ)/1000 +1; /* 200 msec delay */ |
3298 | mddev->in_sync = 1; | 3472 | mddev->in_sync = 1; |
3299 | 3473 | ||
3300 | ITERATE_RDEV(mddev,rdev,tmp) | 3474 | rdev_for_each(rdev, tmp, mddev) |
3301 | if (rdev->raid_disk >= 0) { | 3475 | if (rdev->raid_disk >= 0) { |
3302 | char nm[20]; | 3476 | char nm[20]; |
3303 | sprintf(nm, "rd%d", rdev->raid_disk); | 3477 | sprintf(nm, "rd%d", rdev->raid_disk); |
@@ -3330,7 +3504,7 @@ static int do_md_run(mddev_t * mddev) | |||
3330 | if (mddev->degraded && !mddev->sync_thread) { | 3504 | if (mddev->degraded && !mddev->sync_thread) { |
3331 | struct list_head *rtmp; | 3505 | struct list_head *rtmp; |
3332 | int spares = 0; | 3506 | int spares = 0; |
3333 | ITERATE_RDEV(mddev,rdev,rtmp) | 3507 | rdev_for_each(rdev, rtmp, mddev) |
3334 | if (rdev->raid_disk >= 0 && | 3508 | if (rdev->raid_disk >= 0 && |
3335 | !test_bit(In_sync, &rdev->flags) && | 3509 | !test_bit(In_sync, &rdev->flags) && |
3336 | !test_bit(Faulty, &rdev->flags)) | 3510 | !test_bit(Faulty, &rdev->flags)) |
@@ -3507,14 +3681,14 @@ static int do_md_stop(mddev_t * mddev, int mode) | |||
3507 | } | 3681 | } |
3508 | mddev->bitmap_offset = 0; | 3682 | mddev->bitmap_offset = 0; |
3509 | 3683 | ||
3510 | ITERATE_RDEV(mddev,rdev,tmp) | 3684 | rdev_for_each(rdev, tmp, mddev) |
3511 | if (rdev->raid_disk >= 0) { | 3685 | if (rdev->raid_disk >= 0) { |
3512 | char nm[20]; | 3686 | char nm[20]; |
3513 | sprintf(nm, "rd%d", rdev->raid_disk); | 3687 | sprintf(nm, "rd%d", rdev->raid_disk); |
3514 | sysfs_remove_link(&mddev->kobj, nm); | 3688 | sysfs_remove_link(&mddev->kobj, nm); |
3515 | } | 3689 | } |
3516 | 3690 | ||
3517 | /* make sure all delayed_delete calls have finished */ | 3691 | /* make sure all md_delayed_delete calls have finished */ |
3518 | flush_scheduled_work(); | 3692 | flush_scheduled_work(); |
3519 | 3693 | ||
3520 | export_array(mddev); | 3694 | export_array(mddev); |
@@ -3523,7 +3697,10 @@ static int do_md_stop(mddev_t * mddev, int mode) | |||
3523 | mddev->size = 0; | 3697 | mddev->size = 0; |
3524 | mddev->raid_disks = 0; | 3698 | mddev->raid_disks = 0; |
3525 | mddev->recovery_cp = 0; | 3699 | mddev->recovery_cp = 0; |
3700 | mddev->resync_max = MaxSector; | ||
3526 | mddev->reshape_position = MaxSector; | 3701 | mddev->reshape_position = MaxSector; |
3702 | mddev->external = 0; | ||
3703 | mddev->persistent = 0; | ||
3527 | 3704 | ||
3528 | } else if (mddev->pers) | 3705 | } else if (mddev->pers) |
3529 | printk(KERN_INFO "md: %s switched to read-only mode.\n", | 3706 | printk(KERN_INFO "md: %s switched to read-only mode.\n", |
@@ -3546,7 +3723,7 @@ static void autorun_array(mddev_t *mddev) | |||
3546 | 3723 | ||
3547 | printk(KERN_INFO "md: running: "); | 3724 | printk(KERN_INFO "md: running: "); |
3548 | 3725 | ||
3549 | ITERATE_RDEV(mddev,rdev,tmp) { | 3726 | rdev_for_each(rdev, tmp, mddev) { |
3550 | char b[BDEVNAME_SIZE]; | 3727 | char b[BDEVNAME_SIZE]; |
3551 | printk("<%s>", bdevname(rdev->bdev,b)); | 3728 | printk("<%s>", bdevname(rdev->bdev,b)); |
3552 | } | 3729 | } |
@@ -3589,7 +3766,7 @@ static void autorun_devices(int part) | |||
3589 | printk(KERN_INFO "md: considering %s ...\n", | 3766 | printk(KERN_INFO "md: considering %s ...\n", |
3590 | bdevname(rdev0->bdev,b)); | 3767 | bdevname(rdev0->bdev,b)); |
3591 | INIT_LIST_HEAD(&candidates); | 3768 | INIT_LIST_HEAD(&candidates); |
3592 | ITERATE_RDEV_PENDING(rdev,tmp) | 3769 | rdev_for_each_list(rdev, tmp, pending_raid_disks) |
3593 | if (super_90_load(rdev, rdev0, 0) >= 0) { | 3770 | if (super_90_load(rdev, rdev0, 0) >= 0) { |
3594 | printk(KERN_INFO "md: adding %s ...\n", | 3771 | printk(KERN_INFO "md: adding %s ...\n", |
3595 | bdevname(rdev->bdev,b)); | 3772 | bdevname(rdev->bdev,b)); |
@@ -3632,7 +3809,8 @@ static void autorun_devices(int part) | |||
3632 | mddev_unlock(mddev); | 3809 | mddev_unlock(mddev); |
3633 | } else { | 3810 | } else { |
3634 | printk(KERN_INFO "md: created %s\n", mdname(mddev)); | 3811 | printk(KERN_INFO "md: created %s\n", mdname(mddev)); |
3635 | ITERATE_RDEV_GENERIC(candidates,rdev,tmp) { | 3812 | mddev->persistent = 1; |
3813 | rdev_for_each_list(rdev, tmp, candidates) { | ||
3636 | list_del_init(&rdev->same_set); | 3814 | list_del_init(&rdev->same_set); |
3637 | if (bind_rdev_to_array(rdev, mddev)) | 3815 | if (bind_rdev_to_array(rdev, mddev)) |
3638 | export_rdev(rdev); | 3816 | export_rdev(rdev); |
@@ -3643,7 +3821,7 @@ static void autorun_devices(int part) | |||
3643 | /* on success, candidates will be empty, on error | 3821 | /* on success, candidates will be empty, on error |
3644 | * it won't... | 3822 | * it won't... |
3645 | */ | 3823 | */ |
3646 | ITERATE_RDEV_GENERIC(candidates,rdev,tmp) | 3824 | rdev_for_each_list(rdev, tmp, candidates) |
3647 | export_rdev(rdev); | 3825 | export_rdev(rdev); |
3648 | mddev_put(mddev); | 3826 | mddev_put(mddev); |
3649 | } | 3827 | } |
@@ -3673,7 +3851,7 @@ static int get_array_info(mddev_t * mddev, void __user * arg) | |||
3673 | struct list_head *tmp; | 3851 | struct list_head *tmp; |
3674 | 3852 | ||
3675 | nr=working=active=failed=spare=0; | 3853 | nr=working=active=failed=spare=0; |
3676 | ITERATE_RDEV(mddev,rdev,tmp) { | 3854 | rdev_for_each(rdev, tmp, mddev) { |
3677 | nr++; | 3855 | nr++; |
3678 | if (test_bit(Faulty, &rdev->flags)) | 3856 | if (test_bit(Faulty, &rdev->flags)) |
3679 | failed++; | 3857 | failed++; |
@@ -3919,8 +4097,6 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info) | |||
3919 | else | 4097 | else |
3920 | rdev->raid_disk = -1; | 4098 | rdev->raid_disk = -1; |
3921 | 4099 | ||
3922 | rdev->flags = 0; | ||
3923 | |||
3924 | if (rdev->raid_disk < mddev->raid_disks) | 4100 | if (rdev->raid_disk < mddev->raid_disks) |
3925 | if (info->state & (1<<MD_DISK_SYNC)) | 4101 | if (info->state & (1<<MD_DISK_SYNC)) |
3926 | set_bit(In_sync, &rdev->flags); | 4102 | set_bit(In_sync, &rdev->flags); |
@@ -4165,13 +4341,15 @@ static int set_array_info(mddev_t * mddev, mdu_array_info_t *info) | |||
4165 | else | 4341 | else |
4166 | mddev->recovery_cp = 0; | 4342 | mddev->recovery_cp = 0; |
4167 | mddev->persistent = ! info->not_persistent; | 4343 | mddev->persistent = ! info->not_persistent; |
4344 | mddev->external = 0; | ||
4168 | 4345 | ||
4169 | mddev->layout = info->layout; | 4346 | mddev->layout = info->layout; |
4170 | mddev->chunk_size = info->chunk_size; | 4347 | mddev->chunk_size = info->chunk_size; |
4171 | 4348 | ||
4172 | mddev->max_disks = MD_SB_DISKS; | 4349 | mddev->max_disks = MD_SB_DISKS; |
4173 | 4350 | ||
4174 | mddev->flags = 0; | 4351 | if (mddev->persistent) |
4352 | mddev->flags = 0; | ||
4175 | set_bit(MD_CHANGE_DEVS, &mddev->flags); | 4353 | set_bit(MD_CHANGE_DEVS, &mddev->flags); |
4176 | 4354 | ||
4177 | mddev->default_bitmap_offset = MD_SB_BYTES >> 9; | 4355 | mddev->default_bitmap_offset = MD_SB_BYTES >> 9; |
@@ -4213,7 +4391,7 @@ static int update_size(mddev_t *mddev, unsigned long size) | |||
4213 | */ | 4391 | */ |
4214 | if (mddev->sync_thread) | 4392 | if (mddev->sync_thread) |
4215 | return -EBUSY; | 4393 | return -EBUSY; |
4216 | ITERATE_RDEV(mddev,rdev,tmp) { | 4394 | rdev_for_each(rdev, tmp, mddev) { |
4217 | sector_t avail; | 4395 | sector_t avail; |
4218 | avail = rdev->size * 2; | 4396 | avail = rdev->size * 2; |
4219 | 4397 | ||
@@ -4471,9 +4649,10 @@ static int md_ioctl(struct inode *inode, struct file *file, | |||
4471 | */ | 4649 | */ |
4472 | /* if we are not initialised yet, only ADD_NEW_DISK, STOP_ARRAY, | 4650 | /* if we are not initialised yet, only ADD_NEW_DISK, STOP_ARRAY, |
4473 | * RUN_ARRAY, and GET_ and SET_BITMAP_FILE are allowed */ | 4651 | * RUN_ARRAY, and GET_ and SET_BITMAP_FILE are allowed */ |
4474 | if (!mddev->raid_disks && cmd != ADD_NEW_DISK && cmd != STOP_ARRAY | 4652 | if ((!mddev->raid_disks && !mddev->external) |
4475 | && cmd != RUN_ARRAY && cmd != SET_BITMAP_FILE | 4653 | && cmd != ADD_NEW_DISK && cmd != STOP_ARRAY |
4476 | && cmd != GET_BITMAP_FILE) { | 4654 | && cmd != RUN_ARRAY && cmd != SET_BITMAP_FILE |
4655 | && cmd != GET_BITMAP_FILE) { | ||
4477 | err = -ENODEV; | 4656 | err = -ENODEV; |
4478 | goto abort_unlock; | 4657 | goto abort_unlock; |
4479 | } | 4658 | } |
@@ -4757,7 +4936,7 @@ static void status_unused(struct seq_file *seq) | |||
4757 | 4936 | ||
4758 | seq_printf(seq, "unused devices: "); | 4937 | seq_printf(seq, "unused devices: "); |
4759 | 4938 | ||
4760 | ITERATE_RDEV_PENDING(rdev,tmp) { | 4939 | rdev_for_each_list(rdev, tmp, pending_raid_disks) { |
4761 | char b[BDEVNAME_SIZE]; | 4940 | char b[BDEVNAME_SIZE]; |
4762 | i++; | 4941 | i++; |
4763 | seq_printf(seq, "%s ", | 4942 | seq_printf(seq, "%s ", |
@@ -4953,7 +5132,7 @@ static int md_seq_show(struct seq_file *seq, void *v) | |||
4953 | } | 5132 | } |
4954 | 5133 | ||
4955 | size = 0; | 5134 | size = 0; |
4956 | ITERATE_RDEV(mddev,rdev,tmp2) { | 5135 | rdev_for_each(rdev, tmp2, mddev) { |
4957 | char b[BDEVNAME_SIZE]; | 5136 | char b[BDEVNAME_SIZE]; |
4958 | seq_printf(seq, " %s[%d]", | 5137 | seq_printf(seq, " %s[%d]", |
4959 | bdevname(rdev->bdev,b), rdev->desc_nr); | 5138 | bdevname(rdev->bdev,b), rdev->desc_nr); |
@@ -4982,7 +5161,10 @@ static int md_seq_show(struct seq_file *seq, void *v) | |||
4982 | mddev->major_version, | 5161 | mddev->major_version, |
4983 | mddev->minor_version); | 5162 | mddev->minor_version); |
4984 | } | 5163 | } |
4985 | } else | 5164 | } else if (mddev->external) |
5165 | seq_printf(seq, " super external:%s", | ||
5166 | mddev->metadata_type); | ||
5167 | else | ||
4986 | seq_printf(seq, " super non-persistent"); | 5168 | seq_printf(seq, " super non-persistent"); |
4987 | 5169 | ||
4988 | if (mddev->pers) { | 5170 | if (mddev->pers) { |
@@ -5106,7 +5288,7 @@ static int is_mddev_idle(mddev_t *mddev) | |||
5106 | long curr_events; | 5288 | long curr_events; |
5107 | 5289 | ||
5108 | idle = 1; | 5290 | idle = 1; |
5109 | ITERATE_RDEV(mddev,rdev,tmp) { | 5291 | rdev_for_each(rdev, tmp, mddev) { |
5110 | struct gendisk *disk = rdev->bdev->bd_contains->bd_disk; | 5292 | struct gendisk *disk = rdev->bdev->bd_contains->bd_disk; |
5111 | curr_events = disk_stat_read(disk, sectors[0]) + | 5293 | curr_events = disk_stat_read(disk, sectors[0]) + |
5112 | disk_stat_read(disk, sectors[1]) - | 5294 | disk_stat_read(disk, sectors[1]) - |
@@ -5283,7 +5465,7 @@ void md_do_sync(mddev_t *mddev) | |||
5283 | set_bit(MD_RECOVERY_INTR, &mddev->recovery); | 5465 | set_bit(MD_RECOVERY_INTR, &mddev->recovery); |
5284 | goto skip; | 5466 | goto skip; |
5285 | } | 5467 | } |
5286 | ITERATE_MDDEV(mddev2,tmp) { | 5468 | for_each_mddev(mddev2, tmp) { |
5287 | if (mddev2 == mddev) | 5469 | if (mddev2 == mddev) |
5288 | continue; | 5470 | continue; |
5289 | if (mddev2->curr_resync && | 5471 | if (mddev2->curr_resync && |
@@ -5333,7 +5515,7 @@ void md_do_sync(mddev_t *mddev) | |||
5333 | /* recovery follows the physical size of devices */ | 5515 | /* recovery follows the physical size of devices */ |
5334 | max_sectors = mddev->size << 1; | 5516 | max_sectors = mddev->size << 1; |
5335 | j = MaxSector; | 5517 | j = MaxSector; |
5336 | ITERATE_RDEV(mddev,rdev,rtmp) | 5518 | rdev_for_each(rdev, rtmp, mddev) |
5337 | if (rdev->raid_disk >= 0 && | 5519 | if (rdev->raid_disk >= 0 && |
5338 | !test_bit(Faulty, &rdev->flags) && | 5520 | !test_bit(Faulty, &rdev->flags) && |
5339 | !test_bit(In_sync, &rdev->flags) && | 5521 | !test_bit(In_sync, &rdev->flags) && |
@@ -5381,8 +5563,16 @@ void md_do_sync(mddev_t *mddev) | |||
5381 | sector_t sectors; | 5563 | sector_t sectors; |
5382 | 5564 | ||
5383 | skipped = 0; | 5565 | skipped = 0; |
5566 | if (j >= mddev->resync_max) { | ||
5567 | sysfs_notify(&mddev->kobj, NULL, "sync_completed"); | ||
5568 | wait_event(mddev->recovery_wait, | ||
5569 | mddev->resync_max > j | ||
5570 | || kthread_should_stop()); | ||
5571 | } | ||
5572 | if (kthread_should_stop()) | ||
5573 | goto interrupted; | ||
5384 | sectors = mddev->pers->sync_request(mddev, j, &skipped, | 5574 | sectors = mddev->pers->sync_request(mddev, j, &skipped, |
5385 | currspeed < speed_min(mddev)); | 5575 | currspeed < speed_min(mddev)); |
5386 | if (sectors == 0) { | 5576 | if (sectors == 0) { |
5387 | set_bit(MD_RECOVERY_ERR, &mddev->recovery); | 5577 | set_bit(MD_RECOVERY_ERR, &mddev->recovery); |
5388 | goto out; | 5578 | goto out; |
@@ -5424,15 +5614,9 @@ void md_do_sync(mddev_t *mddev) | |||
5424 | } | 5614 | } |
5425 | 5615 | ||
5426 | 5616 | ||
5427 | if (kthread_should_stop()) { | 5617 | if (kthread_should_stop()) |
5428 | /* | 5618 | goto interrupted; |
5429 | * got a signal, exit. | 5619 | |
5430 | */ | ||
5431 | printk(KERN_INFO | ||
5432 | "md: md_do_sync() got signal ... exiting\n"); | ||
5433 | set_bit(MD_RECOVERY_INTR, &mddev->recovery); | ||
5434 | goto out; | ||
5435 | } | ||
5436 | 5620 | ||
5437 | /* | 5621 | /* |
5438 | * this loop exits only if either when we are slower than | 5622 | * this loop exits only if either when we are slower than |
@@ -5484,7 +5668,7 @@ void md_do_sync(mddev_t *mddev) | |||
5484 | } else { | 5668 | } else { |
5485 | if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery)) | 5669 | if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery)) |
5486 | mddev->curr_resync = MaxSector; | 5670 | mddev->curr_resync = MaxSector; |
5487 | ITERATE_RDEV(mddev,rdev,rtmp) | 5671 | rdev_for_each(rdev, rtmp, mddev) |
5488 | if (rdev->raid_disk >= 0 && | 5672 | if (rdev->raid_disk >= 0 && |
5489 | !test_bit(Faulty, &rdev->flags) && | 5673 | !test_bit(Faulty, &rdev->flags) && |
5490 | !test_bit(In_sync, &rdev->flags) && | 5674 | !test_bit(In_sync, &rdev->flags) && |
@@ -5496,9 +5680,22 @@ void md_do_sync(mddev_t *mddev) | |||
5496 | 5680 | ||
5497 | skip: | 5681 | skip: |
5498 | mddev->curr_resync = 0; | 5682 | mddev->curr_resync = 0; |
5683 | mddev->resync_max = MaxSector; | ||
5684 | sysfs_notify(&mddev->kobj, NULL, "sync_completed"); | ||
5499 | wake_up(&resync_wait); | 5685 | wake_up(&resync_wait); |
5500 | set_bit(MD_RECOVERY_DONE, &mddev->recovery); | 5686 | set_bit(MD_RECOVERY_DONE, &mddev->recovery); |
5501 | md_wakeup_thread(mddev->thread); | 5687 | md_wakeup_thread(mddev->thread); |
5688 | return; | ||
5689 | |||
5690 | interrupted: | ||
5691 | /* | ||
5692 | * got a signal, exit. | ||
5693 | */ | ||
5694 | printk(KERN_INFO | ||
5695 | "md: md_do_sync() got signal ... exiting\n"); | ||
5696 | set_bit(MD_RECOVERY_INTR, &mddev->recovery); | ||
5697 | goto out; | ||
5698 | |||
5502 | } | 5699 | } |
5503 | EXPORT_SYMBOL_GPL(md_do_sync); | 5700 | EXPORT_SYMBOL_GPL(md_do_sync); |
5504 | 5701 | ||
@@ -5509,8 +5706,9 @@ static int remove_and_add_spares(mddev_t *mddev) | |||
5509 | struct list_head *rtmp; | 5706 | struct list_head *rtmp; |
5510 | int spares = 0; | 5707 | int spares = 0; |
5511 | 5708 | ||
5512 | ITERATE_RDEV(mddev,rdev,rtmp) | 5709 | rdev_for_each(rdev, rtmp, mddev) |
5513 | if (rdev->raid_disk >= 0 && | 5710 | if (rdev->raid_disk >= 0 && |
5711 | !mddev->external && | ||
5514 | (test_bit(Faulty, &rdev->flags) || | 5712 | (test_bit(Faulty, &rdev->flags) || |
5515 | ! test_bit(In_sync, &rdev->flags)) && | 5713 | ! test_bit(In_sync, &rdev->flags)) && |
5516 | atomic_read(&rdev->nr_pending)==0) { | 5714 | atomic_read(&rdev->nr_pending)==0) { |
@@ -5524,7 +5722,7 @@ static int remove_and_add_spares(mddev_t *mddev) | |||
5524 | } | 5722 | } |
5525 | 5723 | ||
5526 | if (mddev->degraded) { | 5724 | if (mddev->degraded) { |
5527 | ITERATE_RDEV(mddev,rdev,rtmp) | 5725 | rdev_for_each(rdev, rtmp, mddev) |
5528 | if (rdev->raid_disk < 0 | 5726 | if (rdev->raid_disk < 0 |
5529 | && !test_bit(Faulty, &rdev->flags)) { | 5727 | && !test_bit(Faulty, &rdev->flags)) { |
5530 | rdev->recovery_offset = 0; | 5728 | rdev->recovery_offset = 0; |
@@ -5589,7 +5787,7 @@ void md_check_recovery(mddev_t *mddev) | |||
5589 | } | 5787 | } |
5590 | 5788 | ||
5591 | if ( ! ( | 5789 | if ( ! ( |
5592 | mddev->flags || | 5790 | (mddev->flags && !mddev->external) || |
5593 | test_bit(MD_RECOVERY_NEEDED, &mddev->recovery) || | 5791 | test_bit(MD_RECOVERY_NEEDED, &mddev->recovery) || |
5594 | test_bit(MD_RECOVERY_DONE, &mddev->recovery) || | 5792 | test_bit(MD_RECOVERY_DONE, &mddev->recovery) || |
5595 | (mddev->safemode == 1) || | 5793 | (mddev->safemode == 1) || |
@@ -5605,7 +5803,8 @@ void md_check_recovery(mddev_t *mddev) | |||
5605 | if (mddev->safemode && !atomic_read(&mddev->writes_pending) && | 5803 | if (mddev->safemode && !atomic_read(&mddev->writes_pending) && |
5606 | !mddev->in_sync && mddev->recovery_cp == MaxSector) { | 5804 | !mddev->in_sync && mddev->recovery_cp == MaxSector) { |
5607 | mddev->in_sync = 1; | 5805 | mddev->in_sync = 1; |
5608 | set_bit(MD_CHANGE_CLEAN, &mddev->flags); | 5806 | if (mddev->persistent) |
5807 | set_bit(MD_CHANGE_CLEAN, &mddev->flags); | ||
5609 | } | 5808 | } |
5610 | if (mddev->safemode == 1) | 5809 | if (mddev->safemode == 1) |
5611 | mddev->safemode = 0; | 5810 | mddev->safemode = 0; |
@@ -5637,7 +5836,7 @@ void md_check_recovery(mddev_t *mddev) | |||
5637 | * information must be scrapped | 5836 | * information must be scrapped |
5638 | */ | 5837 | */ |
5639 | if (!mddev->degraded) | 5838 | if (!mddev->degraded) |
5640 | ITERATE_RDEV(mddev,rdev,rtmp) | 5839 | rdev_for_each(rdev, rtmp, mddev) |
5641 | rdev->saved_raid_disk = -1; | 5840 | rdev->saved_raid_disk = -1; |
5642 | 5841 | ||
5643 | mddev->recovery = 0; | 5842 | mddev->recovery = 0; |
@@ -5714,7 +5913,7 @@ static int md_notify_reboot(struct notifier_block *this, | |||
5714 | 5913 | ||
5715 | printk(KERN_INFO "md: stopping all md devices.\n"); | 5914 | printk(KERN_INFO "md: stopping all md devices.\n"); |
5716 | 5915 | ||
5717 | ITERATE_MDDEV(mddev,tmp) | 5916 | for_each_mddev(mddev, tmp) |
5718 | if (mddev_trylock(mddev)) { | 5917 | if (mddev_trylock(mddev)) { |
5719 | do_md_stop (mddev, 1); | 5918 | do_md_stop (mddev, 1); |
5720 | mddev_unlock(mddev); | 5919 | mddev_unlock(mddev); |
@@ -5848,7 +6047,7 @@ static __exit void md_exit(void) | |||
5848 | unregister_reboot_notifier(&md_notifier); | 6047 | unregister_reboot_notifier(&md_notifier); |
5849 | unregister_sysctl_table(raid_table_header); | 6048 | unregister_sysctl_table(raid_table_header); |
5850 | remove_proc_entry("mdstat", NULL); | 6049 | remove_proc_entry("mdstat", NULL); |
5851 | ITERATE_MDDEV(mddev,tmp) { | 6050 | for_each_mddev(mddev, tmp) { |
5852 | struct gendisk *disk = mddev->gendisk; | 6051 | struct gendisk *disk = mddev->gendisk; |
5853 | if (!disk) | 6052 | if (!disk) |
5854 | continue; | 6053 | continue; |
diff --git a/drivers/md/mktables.c b/drivers/md/mktables.c index adef299908cf..b61d5767aae7 100644 --- a/drivers/md/mktables.c +++ b/drivers/md/mktables.c | |||
@@ -1,13 +1,10 @@ | |||
1 | #ident "$Id: mktables.c,v 1.2 2002/12/12 22:41:27 hpa Exp $" | 1 | /* -*- linux-c -*- ------------------------------------------------------- * |
2 | /* ----------------------------------------------------------------------- * | ||
3 | * | 2 | * |
4 | * Copyright 2002 H. Peter Anvin - All Rights Reserved | 3 | * Copyright 2002-2007 H. Peter Anvin - All Rights Reserved |
5 | * | 4 | * |
6 | * This program is free software; you can redistribute it and/or modify | 5 | * This file is part of the Linux kernel, and is made available under |
7 | * it under the terms of the GNU General Public License as published by | 6 | * the terms of the GNU General Public License version 2 or (at your |
8 | * the Free Software Foundation, Inc., 53 Temple Place Ste 330, | 7 | * option) any later version; incorporated herein by reference. |
9 | * Bostom MA 02111-1307, USA; either version 2 of the License, or | ||
10 | * (at your option) any later version; incorporated herein by reference. | ||
11 | * | 8 | * |
12 | * ----------------------------------------------------------------------- */ | 9 | * ----------------------------------------------------------------------- */ |
13 | 10 | ||
@@ -26,100 +23,98 @@ | |||
26 | 23 | ||
27 | static uint8_t gfmul(uint8_t a, uint8_t b) | 24 | static uint8_t gfmul(uint8_t a, uint8_t b) |
28 | { | 25 | { |
29 | uint8_t v = 0; | 26 | uint8_t v = 0; |
30 | 27 | ||
31 | while ( b ) { | 28 | while (b) { |
32 | if ( b & 1 ) v ^= a; | 29 | if (b & 1) |
33 | a = (a << 1) ^ (a & 0x80 ? 0x1d : 0); | 30 | v ^= a; |
34 | b >>= 1; | 31 | a = (a << 1) ^ (a & 0x80 ? 0x1d : 0); |
35 | } | 32 | b >>= 1; |
36 | return v; | 33 | } |
34 | |||
35 | return v; | ||
37 | } | 36 | } |
38 | 37 | ||
39 | static uint8_t gfpow(uint8_t a, int b) | 38 | static uint8_t gfpow(uint8_t a, int b) |
40 | { | 39 | { |
41 | uint8_t v = 1; | 40 | uint8_t v = 1; |
42 | 41 | ||
43 | b %= 255; | 42 | b %= 255; |
44 | if ( b < 0 ) | 43 | if (b < 0) |
45 | b += 255; | 44 | b += 255; |
46 | 45 | ||
47 | while ( b ) { | 46 | while (b) { |
48 | if ( b & 1 ) v = gfmul(v,a); | 47 | if (b & 1) |
49 | a = gfmul(a,a); | 48 | v = gfmul(v, a); |
50 | b >>= 1; | 49 | a = gfmul(a, a); |
51 | } | 50 | b >>= 1; |
52 | return v; | 51 | } |
52 | |||
53 | return v; | ||
53 | } | 54 | } |
54 | 55 | ||
55 | int main(int argc, char *argv[]) | 56 | int main(int argc, char *argv[]) |
56 | { | 57 | { |
57 | int i, j, k; | 58 | int i, j, k; |
58 | uint8_t v; | 59 | uint8_t v; |
59 | uint8_t exptbl[256], invtbl[256]; | 60 | uint8_t exptbl[256], invtbl[256]; |
60 | 61 | ||
61 | printf("#include \"raid6.h\"\n"); | 62 | printf("#include \"raid6.h\"\n"); |
62 | 63 | ||
63 | /* Compute multiplication table */ | 64 | /* Compute multiplication table */ |
64 | printf("\nconst u8 __attribute__((aligned(256)))\n" | 65 | printf("\nconst u8 __attribute__((aligned(256)))\n" |
65 | "raid6_gfmul[256][256] =\n" | 66 | "raid6_gfmul[256][256] =\n" |
66 | "{\n"); | 67 | "{\n"); |
67 | for ( i = 0 ; i < 256 ; i++ ) { | 68 | for (i = 0; i < 256; i++) { |
68 | printf("\t{\n"); | 69 | printf("\t{\n"); |
69 | for ( j = 0 ; j < 256 ; j += 8 ) { | 70 | for (j = 0; j < 256; j += 8) { |
70 | printf("\t\t"); | 71 | printf("\t\t"); |
71 | for ( k = 0 ; k < 8 ; k++ ) { | 72 | for (k = 0; k < 8; k++) |
72 | printf("0x%02x, ", gfmul(i,j+k)); | 73 | printf("0x%02x,%c", gfmul(i, j + k), |
73 | } | 74 | (k == 7) ? '\n' : ' '); |
74 | printf("\n"); | 75 | } |
75 | } | 76 | printf("\t},\n"); |
76 | printf("\t},\n"); | 77 | } |
77 | } | 78 | printf("};\n"); |
78 | printf("};\n"); | 79 | |
79 | 80 | /* Compute power-of-2 table (exponent) */ | |
80 | /* Compute power-of-2 table (exponent) */ | 81 | v = 1; |
81 | v = 1; | 82 | printf("\nconst u8 __attribute__((aligned(256)))\n" |
82 | printf("\nconst u8 __attribute__((aligned(256)))\n" | 83 | "raid6_gfexp[256] =\n" "{\n"); |
83 | "raid6_gfexp[256] =\n" | 84 | for (i = 0; i < 256; i += 8) { |
84 | "{\n"); | 85 | printf("\t"); |
85 | for ( i = 0 ; i < 256 ; i += 8 ) { | 86 | for (j = 0; j < 8; j++) { |
86 | printf("\t"); | 87 | exptbl[i + j] = v; |
87 | for ( j = 0 ; j < 8 ; j++ ) { | 88 | printf("0x%02x,%c", v, (j == 7) ? '\n' : ' '); |
88 | exptbl[i+j] = v; | 89 | v = gfmul(v, 2); |
89 | printf("0x%02x, ", v); | 90 | if (v == 1) |
90 | v = gfmul(v,2); | 91 | v = 0; /* For entry 255, not a real entry */ |
91 | if ( v == 1 ) v = 0; /* For entry 255, not a real entry */ | 92 | } |
92 | } | 93 | } |
93 | printf("\n"); | 94 | printf("};\n"); |
94 | } | 95 | |
95 | printf("};\n"); | 96 | /* Compute inverse table x^-1 == x^254 */ |
96 | 97 | printf("\nconst u8 __attribute__((aligned(256)))\n" | |
97 | /* Compute inverse table x^-1 == x^254 */ | 98 | "raid6_gfinv[256] =\n" "{\n"); |
98 | printf("\nconst u8 __attribute__((aligned(256)))\n" | 99 | for (i = 0; i < 256; i += 8) { |
99 | "raid6_gfinv[256] =\n" | 100 | printf("\t"); |
100 | "{\n"); | 101 | for (j = 0; j < 8; j++) { |
101 | for ( i = 0 ; i < 256 ; i += 8 ) { | 102 | invtbl[i + j] = v = gfpow(i + j, 254); |
102 | printf("\t"); | 103 | printf("0x%02x,%c", v, (j == 7) ? '\n' : ' '); |
103 | for ( j = 0 ; j < 8 ; j++ ) { | 104 | } |
104 | invtbl[i+j] = v = gfpow(i+j,254); | 105 | } |
105 | printf("0x%02x, ", v); | 106 | printf("};\n"); |
106 | } | 107 | |
107 | printf("\n"); | 108 | /* Compute inv(2^x + 1) (exponent-xor-inverse) table */ |
108 | } | 109 | printf("\nconst u8 __attribute__((aligned(256)))\n" |
109 | printf("};\n"); | 110 | "raid6_gfexi[256] =\n" "{\n"); |
110 | 111 | for (i = 0; i < 256; i += 8) { | |
111 | /* Compute inv(2^x + 1) (exponent-xor-inverse) table */ | 112 | printf("\t"); |
112 | printf("\nconst u8 __attribute__((aligned(256)))\n" | 113 | for (j = 0; j < 8; j++) |
113 | "raid6_gfexi[256] =\n" | 114 | printf("0x%02x,%c", invtbl[exptbl[i + j] ^ 1], |
114 | "{\n"); | 115 | (j == 7) ? '\n' : ' '); |
115 | for ( i = 0 ; i < 256 ; i += 8 ) { | 116 | } |
116 | printf("\t"); | 117 | printf("};\n"); |
117 | for ( j = 0 ; j < 8 ; j++ ) { | 118 | |
118 | printf("0x%02x, ", invtbl[exptbl[i+j]^1]); | 119 | return 0; |
119 | } | ||
120 | printf("\n"); | ||
121 | } | ||
122 | printf("};\n\n"); | ||
123 | |||
124 | return 0; | ||
125 | } | 120 | } |
diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c index eb631ebed686..3f299d835a2b 100644 --- a/drivers/md/multipath.c +++ b/drivers/md/multipath.c | |||
@@ -436,7 +436,7 @@ static int multipath_run (mddev_t *mddev) | |||
436 | } | 436 | } |
437 | 437 | ||
438 | conf->working_disks = 0; | 438 | conf->working_disks = 0; |
439 | ITERATE_RDEV(mddev,rdev,tmp) { | 439 | rdev_for_each(rdev, tmp, mddev) { |
440 | disk_idx = rdev->raid_disk; | 440 | disk_idx = rdev->raid_disk; |
441 | if (disk_idx < 0 || | 441 | if (disk_idx < 0 || |
442 | disk_idx >= mddev->raid_disks) | 442 | disk_idx >= mddev->raid_disks) |
diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c index f8e591708d1f..818b48284096 100644 --- a/drivers/md/raid0.c +++ b/drivers/md/raid0.c | |||
@@ -72,11 +72,11 @@ static int create_strip_zones (mddev_t *mddev) | |||
72 | */ | 72 | */ |
73 | conf->nr_strip_zones = 0; | 73 | conf->nr_strip_zones = 0; |
74 | 74 | ||
75 | ITERATE_RDEV(mddev,rdev1,tmp1) { | 75 | rdev_for_each(rdev1, tmp1, mddev) { |
76 | printk("raid0: looking at %s\n", | 76 | printk("raid0: looking at %s\n", |
77 | bdevname(rdev1->bdev,b)); | 77 | bdevname(rdev1->bdev,b)); |
78 | c = 0; | 78 | c = 0; |
79 | ITERATE_RDEV(mddev,rdev2,tmp2) { | 79 | rdev_for_each(rdev2, tmp2, mddev) { |
80 | printk("raid0: comparing %s(%llu)", | 80 | printk("raid0: comparing %s(%llu)", |
81 | bdevname(rdev1->bdev,b), | 81 | bdevname(rdev1->bdev,b), |
82 | (unsigned long long)rdev1->size); | 82 | (unsigned long long)rdev1->size); |
@@ -124,7 +124,7 @@ static int create_strip_zones (mddev_t *mddev) | |||
124 | cnt = 0; | 124 | cnt = 0; |
125 | smallest = NULL; | 125 | smallest = NULL; |
126 | zone->dev = conf->devlist; | 126 | zone->dev = conf->devlist; |
127 | ITERATE_RDEV(mddev, rdev1, tmp1) { | 127 | rdev_for_each(rdev1, tmp1, mddev) { |
128 | int j = rdev1->raid_disk; | 128 | int j = rdev1->raid_disk; |
129 | 129 | ||
130 | if (j < 0 || j >= mddev->raid_disks) { | 130 | if (j < 0 || j >= mddev->raid_disks) { |
@@ -293,7 +293,7 @@ static int raid0_run (mddev_t *mddev) | |||
293 | 293 | ||
294 | /* calculate array device size */ | 294 | /* calculate array device size */ |
295 | mddev->array_size = 0; | 295 | mddev->array_size = 0; |
296 | ITERATE_RDEV(mddev,rdev,tmp) | 296 | rdev_for_each(rdev, tmp, mddev) |
297 | mddev->array_size += rdev->size; | 297 | mddev->array_size += rdev->size; |
298 | 298 | ||
299 | printk("raid0 : md_size is %llu blocks.\n", | 299 | printk("raid0 : md_size is %llu blocks.\n", |
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 4a69c416e045..5c7fef091cec 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c | |||
@@ -1684,6 +1684,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i | |||
1684 | if (!go_faster && conf->nr_waiting) | 1684 | if (!go_faster && conf->nr_waiting) |
1685 | msleep_interruptible(1000); | 1685 | msleep_interruptible(1000); |
1686 | 1686 | ||
1687 | bitmap_cond_end_sync(mddev->bitmap, sector_nr); | ||
1687 | raise_barrier(conf); | 1688 | raise_barrier(conf); |
1688 | 1689 | ||
1689 | conf->next_resync = sector_nr; | 1690 | conf->next_resync = sector_nr; |
@@ -1766,6 +1767,8 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i | |||
1766 | return rv; | 1767 | return rv; |
1767 | } | 1768 | } |
1768 | 1769 | ||
1770 | if (max_sector > mddev->resync_max) | ||
1771 | max_sector = mddev->resync_max; /* Don't do IO beyond here */ | ||
1769 | nr_sectors = 0; | 1772 | nr_sectors = 0; |
1770 | sync_blocks = 0; | 1773 | sync_blocks = 0; |
1771 | do { | 1774 | do { |
@@ -1884,7 +1887,7 @@ static int run(mddev_t *mddev) | |||
1884 | if (!conf->r1bio_pool) | 1887 | if (!conf->r1bio_pool) |
1885 | goto out_no_mem; | 1888 | goto out_no_mem; |
1886 | 1889 | ||
1887 | ITERATE_RDEV(mddev, rdev, tmp) { | 1890 | rdev_for_each(rdev, tmp, mddev) { |
1888 | disk_idx = rdev->raid_disk; | 1891 | disk_idx = rdev->raid_disk; |
1889 | if (disk_idx >= mddev->raid_disks | 1892 | if (disk_idx >= mddev->raid_disks |
1890 | || disk_idx < 0) | 1893 | || disk_idx < 0) |
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 5cdcc9386200..017f58113c33 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c | |||
@@ -1657,6 +1657,9 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i | |||
1657 | return (max_sector - sector_nr) + sectors_skipped; | 1657 | return (max_sector - sector_nr) + sectors_skipped; |
1658 | } | 1658 | } |
1659 | 1659 | ||
1660 | if (max_sector > mddev->resync_max) | ||
1661 | max_sector = mddev->resync_max; /* Don't do IO beyond here */ | ||
1662 | |||
1660 | /* make sure whole request will fit in a chunk - if chunks | 1663 | /* make sure whole request will fit in a chunk - if chunks |
1661 | * are meaningful | 1664 | * are meaningful |
1662 | */ | 1665 | */ |
@@ -1670,6 +1673,8 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i | |||
1670 | if (!go_faster && conf->nr_waiting) | 1673 | if (!go_faster && conf->nr_waiting) |
1671 | msleep_interruptible(1000); | 1674 | msleep_interruptible(1000); |
1672 | 1675 | ||
1676 | bitmap_cond_end_sync(mddev->bitmap, sector_nr); | ||
1677 | |||
1673 | /* Again, very different code for resync and recovery. | 1678 | /* Again, very different code for resync and recovery. |
1674 | * Both must result in an r10bio with a list of bios that | 1679 | * Both must result in an r10bio with a list of bios that |
1675 | * have bi_end_io, bi_sector, bi_bdev set, | 1680 | * have bi_end_io, bi_sector, bi_bdev set, |
@@ -2021,7 +2026,7 @@ static int run(mddev_t *mddev) | |||
2021 | goto out_free_conf; | 2026 | goto out_free_conf; |
2022 | } | 2027 | } |
2023 | 2028 | ||
2024 | ITERATE_RDEV(mddev, rdev, tmp) { | 2029 | rdev_for_each(rdev, tmp, mddev) { |
2025 | disk_idx = rdev->raid_disk; | 2030 | disk_idx = rdev->raid_disk; |
2026 | if (disk_idx >= mddev->raid_disks | 2031 | if (disk_idx >= mddev->raid_disks |
2027 | || disk_idx < 0) | 2032 | || disk_idx < 0) |
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index e8c8157b02fc..2d6f1a51359c 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c | |||
@@ -3159,7 +3159,8 @@ static void raid5_activate_delayed(raid5_conf_t *conf) | |||
3159 | atomic_inc(&conf->preread_active_stripes); | 3159 | atomic_inc(&conf->preread_active_stripes); |
3160 | list_add_tail(&sh->lru, &conf->handle_list); | 3160 | list_add_tail(&sh->lru, &conf->handle_list); |
3161 | } | 3161 | } |
3162 | } | 3162 | } else |
3163 | blk_plug_device(conf->mddev->queue); | ||
3163 | } | 3164 | } |
3164 | 3165 | ||
3165 | static void activate_bit_delay(raid5_conf_t *conf) | 3166 | static void activate_bit_delay(raid5_conf_t *conf) |
@@ -3549,7 +3550,8 @@ static int make_request(struct request_queue *q, struct bio * bi) | |||
3549 | goto retry; | 3550 | goto retry; |
3550 | } | 3551 | } |
3551 | finish_wait(&conf->wait_for_overlap, &w); | 3552 | finish_wait(&conf->wait_for_overlap, &w); |
3552 | handle_stripe(sh, NULL); | 3553 | set_bit(STRIPE_HANDLE, &sh->state); |
3554 | clear_bit(STRIPE_DELAYED, &sh->state); | ||
3553 | release_stripe(sh); | 3555 | release_stripe(sh); |
3554 | } else { | 3556 | } else { |
3555 | /* cannot get stripe for read-ahead, just give-up */ | 3557 | /* cannot get stripe for read-ahead, just give-up */ |
@@ -3698,6 +3700,25 @@ static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped | |||
3698 | release_stripe(sh); | 3700 | release_stripe(sh); |
3699 | first_sector += STRIPE_SECTORS; | 3701 | first_sector += STRIPE_SECTORS; |
3700 | } | 3702 | } |
3703 | /* If this takes us to the resync_max point where we have to pause, | ||
3704 | * then we need to write out the superblock. | ||
3705 | */ | ||
3706 | sector_nr += conf->chunk_size>>9; | ||
3707 | if (sector_nr >= mddev->resync_max) { | ||
3708 | /* Cannot proceed until we've updated the superblock... */ | ||
3709 | wait_event(conf->wait_for_overlap, | ||
3710 | atomic_read(&conf->reshape_stripes) == 0); | ||
3711 | mddev->reshape_position = conf->expand_progress; | ||
3712 | set_bit(MD_CHANGE_DEVS, &mddev->flags); | ||
3713 | md_wakeup_thread(mddev->thread); | ||
3714 | wait_event(mddev->sb_wait, | ||
3715 | !test_bit(MD_CHANGE_DEVS, &mddev->flags) | ||
3716 | || kthread_should_stop()); | ||
3717 | spin_lock_irq(&conf->device_lock); | ||
3718 | conf->expand_lo = mddev->reshape_position; | ||
3719 | spin_unlock_irq(&conf->device_lock); | ||
3720 | wake_up(&conf->wait_for_overlap); | ||
3721 | } | ||
3701 | return conf->chunk_size>>9; | 3722 | return conf->chunk_size>>9; |
3702 | } | 3723 | } |
3703 | 3724 | ||
@@ -3734,6 +3755,12 @@ static inline sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *ski | |||
3734 | if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery)) | 3755 | if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery)) |
3735 | return reshape_request(mddev, sector_nr, skipped); | 3756 | return reshape_request(mddev, sector_nr, skipped); |
3736 | 3757 | ||
3758 | /* No need to check resync_max as we never do more than one | ||
3759 | * stripe, and as resync_max will always be on a chunk boundary, | ||
3760 | * if the check in md_do_sync didn't fire, there is no chance | ||
3761 | * of overstepping resync_max here | ||
3762 | */ | ||
3763 | |||
3737 | /* if there is too many failed drives and we are trying | 3764 | /* if there is too many failed drives and we are trying |
3738 | * to resync, then assert that we are finished, because there is | 3765 | * to resync, then assert that we are finished, because there is |
3739 | * nothing we can do. | 3766 | * nothing we can do. |
@@ -3753,6 +3780,9 @@ static inline sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *ski | |||
3753 | return sync_blocks * STRIPE_SECTORS; /* keep things rounded to whole stripes */ | 3780 | return sync_blocks * STRIPE_SECTORS; /* keep things rounded to whole stripes */ |
3754 | } | 3781 | } |
3755 | 3782 | ||
3783 | |||
3784 | bitmap_cond_end_sync(mddev->bitmap, sector_nr); | ||
3785 | |||
3756 | pd_idx = stripe_to_pdidx(sector_nr, conf, raid_disks); | 3786 | pd_idx = stripe_to_pdidx(sector_nr, conf, raid_disks); |
3757 | sh = get_active_stripe(conf, sector_nr, raid_disks, pd_idx, 1); | 3787 | sh = get_active_stripe(conf, sector_nr, raid_disks, pd_idx, 1); |
3758 | if (sh == NULL) { | 3788 | if (sh == NULL) { |
@@ -3864,7 +3894,7 @@ static int retry_aligned_read(raid5_conf_t *conf, struct bio *raid_bio) | |||
3864 | * During the scan, completed stripes are saved for us by the interrupt | 3894 | * During the scan, completed stripes are saved for us by the interrupt |
3865 | * handler, so that they will not have to wait for our next wakeup. | 3895 | * handler, so that they will not have to wait for our next wakeup. |
3866 | */ | 3896 | */ |
3867 | static void raid5d (mddev_t *mddev) | 3897 | static void raid5d(mddev_t *mddev) |
3868 | { | 3898 | { |
3869 | struct stripe_head *sh; | 3899 | struct stripe_head *sh; |
3870 | raid5_conf_t *conf = mddev_to_conf(mddev); | 3900 | raid5_conf_t *conf = mddev_to_conf(mddev); |
@@ -3889,12 +3919,6 @@ static void raid5d (mddev_t *mddev) | |||
3889 | activate_bit_delay(conf); | 3919 | activate_bit_delay(conf); |
3890 | } | 3920 | } |
3891 | 3921 | ||
3892 | if (list_empty(&conf->handle_list) && | ||
3893 | atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD && | ||
3894 | !blk_queue_plugged(mddev->queue) && | ||
3895 | !list_empty(&conf->delayed_list)) | ||
3896 | raid5_activate_delayed(conf); | ||
3897 | |||
3898 | while ((bio = remove_bio_from_retry(conf))) { | 3922 | while ((bio = remove_bio_from_retry(conf))) { |
3899 | int ok; | 3923 | int ok; |
3900 | spin_unlock_irq(&conf->device_lock); | 3924 | spin_unlock_irq(&conf->device_lock); |
@@ -4108,7 +4132,7 @@ static int run(mddev_t *mddev) | |||
4108 | 4132 | ||
4109 | pr_debug("raid5: run(%s) called.\n", mdname(mddev)); | 4133 | pr_debug("raid5: run(%s) called.\n", mdname(mddev)); |
4110 | 4134 | ||
4111 | ITERATE_RDEV(mddev,rdev,tmp) { | 4135 | rdev_for_each(rdev, tmp, mddev) { |
4112 | raid_disk = rdev->raid_disk; | 4136 | raid_disk = rdev->raid_disk; |
4113 | if (raid_disk >= conf->raid_disks | 4137 | if (raid_disk >= conf->raid_disks |
4114 | || raid_disk < 0) | 4138 | || raid_disk < 0) |
@@ -4521,7 +4545,7 @@ static int raid5_start_reshape(mddev_t *mddev) | |||
4521 | if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery)) | 4545 | if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery)) |
4522 | return -EBUSY; | 4546 | return -EBUSY; |
4523 | 4547 | ||
4524 | ITERATE_RDEV(mddev, rdev, rtmp) | 4548 | rdev_for_each(rdev, rtmp, mddev) |
4525 | if (rdev->raid_disk < 0 && | 4549 | if (rdev->raid_disk < 0 && |
4526 | !test_bit(Faulty, &rdev->flags)) | 4550 | !test_bit(Faulty, &rdev->flags)) |
4527 | spares++; | 4551 | spares++; |
@@ -4543,7 +4567,7 @@ static int raid5_start_reshape(mddev_t *mddev) | |||
4543 | /* Add some new drives, as many as will fit. | 4567 | /* Add some new drives, as many as will fit. |
4544 | * We know there are enough to make the newly sized array work. | 4568 | * We know there are enough to make the newly sized array work. |
4545 | */ | 4569 | */ |
4546 | ITERATE_RDEV(mddev, rdev, rtmp) | 4570 | rdev_for_each(rdev, rtmp, mddev) |
4547 | if (rdev->raid_disk < 0 && | 4571 | if (rdev->raid_disk < 0 && |
4548 | !test_bit(Faulty, &rdev->flags)) { | 4572 | !test_bit(Faulty, &rdev->flags)) { |
4549 | if (raid5_add_disk(mddev, rdev)) { | 4573 | if (raid5_add_disk(mddev, rdev)) { |
diff --git a/drivers/md/raid6test/test.c b/drivers/md/raid6test/test.c index 0d5cd57accd7..559cc41b2585 100644 --- a/drivers/md/raid6test/test.c +++ b/drivers/md/raid6test/test.c | |||
@@ -1,12 +1,10 @@ | |||
1 | /* -*- linux-c -*- ------------------------------------------------------- * | 1 | /* -*- linux-c -*- ------------------------------------------------------- * |
2 | * | 2 | * |
3 | * Copyright 2002 H. Peter Anvin - All Rights Reserved | 3 | * Copyright 2002-2007 H. Peter Anvin - All Rights Reserved |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify | 5 | * This file is part of the Linux kernel, and is made available under |
6 | * it under the terms of the GNU General Public License as published by | 6 | * the terms of the GNU General Public License version 2 or (at your |
7 | * the Free Software Foundation, Inc., 53 Temple Place Ste 330, | 7 | * option) any later version; incorporated herein by reference. |
8 | * Bostom MA 02111-1307, USA; either version 2 of the License, or | ||
9 | * (at your option) any later version; incorporated herein by reference. | ||
10 | * | 8 | * |
11 | * ----------------------------------------------------------------------- */ | 9 | * ----------------------------------------------------------------------- */ |
12 | 10 | ||
@@ -30,67 +28,87 @@ char *dataptrs[NDISKS]; | |||
30 | char data[NDISKS][PAGE_SIZE]; | 28 | char data[NDISKS][PAGE_SIZE]; |
31 | char recovi[PAGE_SIZE], recovj[PAGE_SIZE]; | 29 | char recovi[PAGE_SIZE], recovj[PAGE_SIZE]; |
32 | 30 | ||
33 | void makedata(void) | 31 | static void makedata(void) |
34 | { | 32 | { |
35 | int i, j; | 33 | int i, j; |
36 | 34 | ||
37 | for ( i = 0 ; i < NDISKS ; i++ ) { | 35 | for (i = 0; i < NDISKS; i++) { |
38 | for ( j = 0 ; j < PAGE_SIZE ; j++ ) { | 36 | for (j = 0; j < PAGE_SIZE; j++) |
39 | data[i][j] = rand(); | 37 | data[i][j] = rand(); |
40 | } | 38 | |
41 | dataptrs[i] = data[i]; | 39 | dataptrs[i] = data[i]; |
42 | } | 40 | } |
43 | } | 41 | } |
44 | 42 | ||
43 | static char disk_type(int d) | ||
44 | { | ||
45 | switch (d) { | ||
46 | case NDISKS-2: | ||
47 | return 'P'; | ||
48 | case NDISKS-1: | ||
49 | return 'Q'; | ||
50 | default: | ||
51 | return 'D'; | ||
52 | } | ||
53 | } | ||
54 | |||
55 | static int test_disks(int i, int j) | ||
56 | { | ||
57 | int erra, errb; | ||
58 | |||
59 | memset(recovi, 0xf0, PAGE_SIZE); | ||
60 | memset(recovj, 0xba, PAGE_SIZE); | ||
61 | |||
62 | dataptrs[i] = recovi; | ||
63 | dataptrs[j] = recovj; | ||
64 | |||
65 | raid6_dual_recov(NDISKS, PAGE_SIZE, i, j, (void **)&dataptrs); | ||
66 | |||
67 | erra = memcmp(data[i], recovi, PAGE_SIZE); | ||
68 | errb = memcmp(data[j], recovj, PAGE_SIZE); | ||
69 | |||
70 | if (i < NDISKS-2 && j == NDISKS-1) { | ||
71 | /* We don't implement the DQ failure scenario, since it's | ||
72 | equivalent to a RAID-5 failure (XOR, then recompute Q) */ | ||
73 | erra = errb = 0; | ||
74 | } else { | ||
75 | printf("algo=%-8s faila=%3d(%c) failb=%3d(%c) %s\n", | ||
76 | raid6_call.name, | ||
77 | i, disk_type(i), | ||
78 | j, disk_type(j), | ||
79 | (!erra && !errb) ? "OK" : | ||
80 | !erra ? "ERRB" : | ||
81 | !errb ? "ERRA" : "ERRAB"); | ||
82 | } | ||
83 | |||
84 | dataptrs[i] = data[i]; | ||
85 | dataptrs[j] = data[j]; | ||
86 | |||
87 | return erra || errb; | ||
88 | } | ||
89 | |||
45 | int main(int argc, char *argv[]) | 90 | int main(int argc, char *argv[]) |
46 | { | 91 | { |
47 | const struct raid6_calls * const * algo; | 92 | const struct raid6_calls *const *algo; |
48 | int i, j; | 93 | int i, j; |
49 | int erra, errb; | 94 | int err = 0; |
50 | 95 | ||
51 | makedata(); | 96 | makedata(); |
52 | 97 | ||
53 | for ( algo = raid6_algos ; *algo ; algo++ ) { | 98 | for (algo = raid6_algos; *algo; algo++) { |
54 | if ( !(*algo)->valid || (*algo)->valid() ) { | 99 | if (!(*algo)->valid || (*algo)->valid()) { |
55 | raid6_call = **algo; | 100 | raid6_call = **algo; |
56 | 101 | ||
57 | /* Nuke syndromes */ | 102 | /* Nuke syndromes */ |
58 | memset(data[NDISKS-2], 0xee, 2*PAGE_SIZE); | 103 | memset(data[NDISKS-2], 0xee, 2*PAGE_SIZE); |
59 | 104 | ||
60 | /* Generate assumed good syndrome */ | 105 | /* Generate assumed good syndrome */ |
61 | raid6_call.gen_syndrome(NDISKS, PAGE_SIZE, (void **)&dataptrs); | 106 | raid6_call.gen_syndrome(NDISKS, PAGE_SIZE, |
62 | 107 | (void **)&dataptrs); | |
63 | for ( i = 0 ; i < NDISKS-1 ; i++ ) { | 108 | |
64 | for ( j = i+1 ; j < NDISKS ; j++ ) { | 109 | for (i = 0; i < NDISKS-1; i++) |
65 | memset(recovi, 0xf0, PAGE_SIZE); | 110 | for (j = i+1; j < NDISKS; j++) |
66 | memset(recovj, 0xba, PAGE_SIZE); | 111 | err += test_disks(i, j); |
67 | |||
68 | dataptrs[i] = recovi; | ||
69 | dataptrs[j] = recovj; | ||
70 | |||
71 | raid6_dual_recov(NDISKS, PAGE_SIZE, i, j, (void **)&dataptrs); | ||
72 | |||
73 | erra = memcmp(data[i], recovi, PAGE_SIZE); | ||
74 | errb = memcmp(data[j], recovj, PAGE_SIZE); | ||
75 | |||
76 | if ( i < NDISKS-2 && j == NDISKS-1 ) { | ||
77 | /* We don't implement the DQ failure scenario, since it's | ||
78 | equivalent to a RAID-5 failure (XOR, then recompute Q) */ | ||
79 | } else { | ||
80 | printf("algo=%-8s faila=%3d(%c) failb=%3d(%c) %s\n", | ||
81 | raid6_call.name, | ||
82 | i, (i==NDISKS-2)?'P':'D', | ||
83 | j, (j==NDISKS-1)?'Q':(j==NDISKS-2)?'P':'D', | ||
84 | (!erra && !errb) ? "OK" : | ||
85 | !erra ? "ERRB" : | ||
86 | !errb ? "ERRA" : | ||
87 | "ERRAB"); | ||
88 | } | ||
89 | |||
90 | dataptrs[i] = data[i]; | ||
91 | dataptrs[j] = data[j]; | ||
92 | } | ||
93 | } | ||
94 | } | 112 | } |
95 | printf("\n"); | 113 | printf("\n"); |
96 | } | 114 | } |
@@ -99,5 +117,8 @@ int main(int argc, char *argv[]) | |||
99 | /* Pick the best algorithm test */ | 117 | /* Pick the best algorithm test */ |
100 | raid6_select_algo(); | 118 | raid6_select_algo(); |
101 | 119 | ||
102 | return 0; | 120 | if (err) |
121 | printf("\n*** ERRORS FOUND ***\n"); | ||
122 | |||
123 | return err; | ||
103 | } | 124 | } |
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index 28ddd146c1c5..850b8c6f4577 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile | |||
@@ -22,7 +22,6 @@ obj-$(CONFIG_VIDEO_IR_I2C) += ir-kbd-i2c.o | |||
22 | obj-$(CONFIG_VIDEO_TVAUDIO) += tvaudio.o | 22 | obj-$(CONFIG_VIDEO_TVAUDIO) += tvaudio.o |
23 | obj-$(CONFIG_VIDEO_TDA7432) += tda7432.o | 23 | obj-$(CONFIG_VIDEO_TDA7432) += tda7432.o |
24 | obj-$(CONFIG_VIDEO_TDA9875) += tda9875.o | 24 | obj-$(CONFIG_VIDEO_TDA9875) += tda9875.o |
25 | obj-$(CONFIG_SOUND_TVMIXER) += tvmixer.o | ||
26 | 25 | ||
27 | obj-$(CONFIG_VIDEO_SAA6588) += saa6588.o | 26 | obj-$(CONFIG_VIDEO_SAA6588) += saa6588.o |
28 | obj-$(CONFIG_VIDEO_SAA5246A) += saa5246a.o | 27 | obj-$(CONFIG_VIDEO_SAA5246A) += saa5246a.o |
diff --git a/drivers/media/video/tvmixer.c b/drivers/media/video/tvmixer.c deleted file mode 100644 index 9fa5b702e073..000000000000 --- a/drivers/media/video/tvmixer.c +++ /dev/null | |||
@@ -1,336 +0,0 @@ | |||
1 | /* | ||
2 | */ | ||
3 | |||
4 | #include <linux/module.h> | ||
5 | #include <linux/kernel.h> | ||
6 | #include <linux/string.h> | ||
7 | #include <linux/timer.h> | ||
8 | #include <linux/delay.h> | ||
9 | #include <linux/errno.h> | ||
10 | #include <linux/slab.h> | ||
11 | #include <linux/i2c.h> | ||
12 | #include <linux/videodev.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/kdev_t.h> | ||
15 | #include <linux/sound.h> | ||
16 | #include <linux/soundcard.h> | ||
17 | |||
18 | #include <asm/semaphore.h> | ||
19 | #include <asm/uaccess.h> | ||
20 | |||
21 | |||
22 | #define DEV_MAX 4 | ||
23 | |||
24 | static int devnr = -1; | ||
25 | module_param(devnr, int, 0644); | ||
26 | |||
27 | MODULE_AUTHOR("Gerd Knorr"); | ||
28 | MODULE_LICENSE("GPL"); | ||
29 | |||
30 | /* ----------------------------------------------------------------------- */ | ||
31 | |||
32 | struct TVMIXER { | ||
33 | struct i2c_client *dev; | ||
34 | int minor; | ||
35 | int count; | ||
36 | }; | ||
37 | |||
38 | static struct TVMIXER devices[DEV_MAX]; | ||
39 | |||
40 | static int tvmixer_adapters(struct i2c_adapter *adap); | ||
41 | static int tvmixer_clients(struct i2c_client *client); | ||
42 | |||
43 | /* ----------------------------------------------------------------------- */ | ||
44 | |||
45 | static int mix_to_v4l(int i) | ||
46 | { | ||
47 | int r; | ||
48 | |||
49 | r = ((i & 0xff) * 65536 + 50) / 100; | ||
50 | if (r > 65535) r = 65535; | ||
51 | if (r < 0) r = 0; | ||
52 | return r; | ||
53 | } | ||
54 | |||
55 | static int v4l_to_mix(int i) | ||
56 | { | ||
57 | int r; | ||
58 | |||
59 | r = (i * 100 + 32768) / 65536; | ||
60 | if (r > 100) r = 100; | ||
61 | if (r < 0) r = 0; | ||
62 | return r | (r << 8); | ||
63 | } | ||
64 | |||
65 | static int v4l_to_mix2(int l, int r) | ||
66 | { | ||
67 | r = (r * 100 + 32768) / 65536; | ||
68 | if (r > 100) r = 100; | ||
69 | if (r < 0) r = 0; | ||
70 | l = (l * 100 + 32768) / 65536; | ||
71 | if (l > 100) l = 100; | ||
72 | if (l < 0) l = 0; | ||
73 | return (r << 8) | l; | ||
74 | } | ||
75 | |||
76 | static int tvmixer_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) | ||
77 | { | ||
78 | struct video_audio va; | ||
79 | int left,right,ret,val = 0; | ||
80 | struct TVMIXER *mix = file->private_data; | ||
81 | struct i2c_client *client = mix->dev; | ||
82 | void __user *argp = (void __user *)arg; | ||
83 | int __user *p = argp; | ||
84 | |||
85 | if (NULL == client) | ||
86 | return -ENODEV; | ||
87 | |||
88 | if (cmd == SOUND_MIXER_INFO) { | ||
89 | mixer_info info; | ||
90 | strlcpy(info.id, "tv card", sizeof(info.id)); | ||
91 | strlcpy(info.name, client->name, sizeof(info.name)); | ||
92 | info.modify_counter = 42 /* FIXME */; | ||
93 | if (copy_to_user(argp, &info, sizeof(info))) | ||
94 | return -EFAULT; | ||
95 | return 0; | ||
96 | } | ||
97 | if (cmd == SOUND_OLD_MIXER_INFO) { | ||
98 | _old_mixer_info info; | ||
99 | strlcpy(info.id, "tv card", sizeof(info.id)); | ||
100 | strlcpy(info.name, client->name, sizeof(info.name)); | ||
101 | if (copy_to_user(argp, &info, sizeof(info))) | ||
102 | return -EFAULT; | ||
103 | return 0; | ||
104 | } | ||
105 | if (cmd == OSS_GETVERSION) | ||
106 | return put_user(SOUND_VERSION, p); | ||
107 | |||
108 | if (_SIOC_DIR(cmd) & _SIOC_WRITE) | ||
109 | if (get_user(val, p)) | ||
110 | return -EFAULT; | ||
111 | |||
112 | /* read state */ | ||
113 | memset(&va,0,sizeof(va)); | ||
114 | client->driver->command(client,VIDIOCGAUDIO,&va); | ||
115 | |||
116 | switch (cmd) { | ||
117 | case MIXER_READ(SOUND_MIXER_RECMASK): | ||
118 | case MIXER_READ(SOUND_MIXER_CAPS): | ||
119 | case MIXER_READ(SOUND_MIXER_RECSRC): | ||
120 | case MIXER_WRITE(SOUND_MIXER_RECSRC): | ||
121 | ret = 0; | ||
122 | break; | ||
123 | |||
124 | case MIXER_READ(SOUND_MIXER_STEREODEVS): | ||
125 | ret = SOUND_MASK_VOLUME; | ||
126 | break; | ||
127 | case MIXER_READ(SOUND_MIXER_DEVMASK): | ||
128 | ret = SOUND_MASK_VOLUME; | ||
129 | if (va.flags & VIDEO_AUDIO_BASS) | ||
130 | ret |= SOUND_MASK_BASS; | ||
131 | if (va.flags & VIDEO_AUDIO_TREBLE) | ||
132 | ret |= SOUND_MASK_TREBLE; | ||
133 | break; | ||
134 | |||
135 | case MIXER_WRITE(SOUND_MIXER_VOLUME): | ||
136 | left = mix_to_v4l(val); | ||
137 | right = mix_to_v4l(val >> 8); | ||
138 | va.volume = max(left,right); | ||
139 | va.balance = (32768*min(left,right)) / (va.volume ? va.volume : 1); | ||
140 | va.balance = (left<right) ? (65535-va.balance) : va.balance; | ||
141 | if (va.volume) | ||
142 | va.flags &= ~VIDEO_AUDIO_MUTE; | ||
143 | client->driver->command(client,VIDIOCSAUDIO,&va); | ||
144 | client->driver->command(client,VIDIOCGAUDIO,&va); | ||
145 | /* fall throuth */ | ||
146 | case MIXER_READ(SOUND_MIXER_VOLUME): | ||
147 | left = (min(65536 - va.balance,32768) * | ||
148 | va.volume) / 32768; | ||
149 | right = (min(va.balance,(u16)32768) * | ||
150 | va.volume) / 32768; | ||
151 | ret = v4l_to_mix2(left,right); | ||
152 | break; | ||
153 | |||
154 | case MIXER_WRITE(SOUND_MIXER_BASS): | ||
155 | va.bass = mix_to_v4l(val); | ||
156 | client->driver->command(client,VIDIOCSAUDIO,&va); | ||
157 | client->driver->command(client,VIDIOCGAUDIO,&va); | ||
158 | /* fall throuth */ | ||
159 | case MIXER_READ(SOUND_MIXER_BASS): | ||
160 | ret = v4l_to_mix(va.bass); | ||
161 | break; | ||
162 | |||
163 | case MIXER_WRITE(SOUND_MIXER_TREBLE): | ||
164 | va.treble = mix_to_v4l(val); | ||
165 | client->driver->command(client,VIDIOCSAUDIO,&va); | ||
166 | client->driver->command(client,VIDIOCGAUDIO,&va); | ||
167 | /* fall throuth */ | ||
168 | case MIXER_READ(SOUND_MIXER_TREBLE): | ||
169 | ret = v4l_to_mix(va.treble); | ||
170 | break; | ||
171 | |||
172 | default: | ||
173 | return -EINVAL; | ||
174 | } | ||
175 | if (put_user(ret, p)) | ||
176 | return -EFAULT; | ||
177 | return 0; | ||
178 | } | ||
179 | |||
180 | static int tvmixer_open(struct inode *inode, struct file *file) | ||
181 | { | ||
182 | int i, minor = iminor(inode); | ||
183 | struct TVMIXER *mix = NULL; | ||
184 | struct i2c_client *client = NULL; | ||
185 | |||
186 | for (i = 0; i < DEV_MAX; i++) { | ||
187 | if (devices[i].minor == minor) { | ||
188 | mix = devices+i; | ||
189 | client = mix->dev; | ||
190 | break; | ||
191 | } | ||
192 | } | ||
193 | |||
194 | if (NULL == client) | ||
195 | return -ENODEV; | ||
196 | |||
197 | /* lock bttv in memory while the mixer is in use */ | ||
198 | file->private_data = mix; | ||
199 | if (client->adapter->owner) | ||
200 | try_module_get(client->adapter->owner); | ||
201 | return 0; | ||
202 | } | ||
203 | |||
204 | static int tvmixer_release(struct inode *inode, struct file *file) | ||
205 | { | ||
206 | struct TVMIXER *mix = file->private_data; | ||
207 | struct i2c_client *client; | ||
208 | |||
209 | client = mix->dev; | ||
210 | if (NULL == client) { | ||
211 | return -ENODEV; | ||
212 | } | ||
213 | |||
214 | module_put(client->adapter->owner); | ||
215 | return 0; | ||
216 | } | ||
217 | |||
218 | static struct i2c_driver driver = { | ||
219 | .driver = { | ||
220 | .name = "tvmixer", | ||
221 | }, | ||
222 | .id = I2C_DRIVERID_TVMIXER, | ||
223 | .detach_adapter = tvmixer_adapters, | ||
224 | .attach_adapter = tvmixer_adapters, | ||
225 | .detach_client = tvmixer_clients, | ||
226 | }; | ||
227 | |||
228 | static const struct file_operations tvmixer_fops = { | ||
229 | .owner = THIS_MODULE, | ||
230 | .llseek = no_llseek, | ||
231 | .ioctl = tvmixer_ioctl, | ||
232 | .open = tvmixer_open, | ||
233 | .release = tvmixer_release, | ||
234 | }; | ||
235 | |||
236 | /* ----------------------------------------------------------------------- */ | ||
237 | |||
238 | static int tvmixer_adapters(struct i2c_adapter *adap) | ||
239 | { | ||
240 | struct i2c_client *client; | ||
241 | |||
242 | list_for_each_entry(client, &adap->clients, list) | ||
243 | tvmixer_clients(client); | ||
244 | return 0; | ||
245 | } | ||
246 | |||
247 | static int tvmixer_clients(struct i2c_client *client) | ||
248 | { | ||
249 | struct video_audio va; | ||
250 | int i,minor; | ||
251 | |||
252 | if (!(client->adapter->class & I2C_CLASS_TV_ANALOG)) | ||
253 | return -1; | ||
254 | |||
255 | /* unregister ?? */ | ||
256 | for (i = 0; i < DEV_MAX; i++) { | ||
257 | if (devices[i].dev == client) { | ||
258 | /* unregister */ | ||
259 | unregister_sound_mixer(devices[i].minor); | ||
260 | devices[i].dev = NULL; | ||
261 | devices[i].minor = -1; | ||
262 | printk("tvmixer: %s unregistered (#1)\n", | ||
263 | client->name); | ||
264 | return 0; | ||
265 | } | ||
266 | } | ||
267 | |||
268 | /* look for a free slot */ | ||
269 | for (i = 0; i < DEV_MAX; i++) | ||
270 | if (NULL == devices[i].dev) | ||
271 | break; | ||
272 | if (i == DEV_MAX) { | ||
273 | printk(KERN_WARNING "tvmixer: DEV_MAX too small\n"); | ||
274 | return -1; | ||
275 | } | ||
276 | |||
277 | /* audio chip with mixer ??? */ | ||
278 | if (NULL == client->driver->command) | ||
279 | return -1; | ||
280 | memset(&va,0,sizeof(va)); | ||
281 | if (0 != client->driver->command(client,VIDIOCGAUDIO,&va)) | ||
282 | return -1; | ||
283 | if (0 == (va.flags & VIDEO_AUDIO_VOLUME)) | ||
284 | return -1; | ||
285 | |||
286 | /* everything is fine, register */ | ||
287 | if ((minor = register_sound_mixer(&tvmixer_fops,devnr)) < 0) { | ||
288 | printk(KERN_ERR "tvmixer: cannot allocate mixer device\n"); | ||
289 | return -1; | ||
290 | } | ||
291 | |||
292 | devices[i].minor = minor; | ||
293 | devices[i].count = 0; | ||
294 | devices[i].dev = client; | ||
295 | printk("tvmixer: %s (%s) registered with minor %d\n", | ||
296 | client->name,client->adapter->name,minor); | ||
297 | |||
298 | return 0; | ||
299 | } | ||
300 | |||
301 | /* ----------------------------------------------------------------------- */ | ||
302 | |||
303 | static int __init tvmixer_init_module(void) | ||
304 | { | ||
305 | int i; | ||
306 | |||
307 | for (i = 0; i < DEV_MAX; i++) | ||
308 | devices[i].minor = -1; | ||
309 | |||
310 | return i2c_add_driver(&driver); | ||
311 | } | ||
312 | |||
313 | static void __exit tvmixer_cleanup_module(void) | ||
314 | { | ||
315 | int i; | ||
316 | |||
317 | i2c_del_driver(&driver); | ||
318 | for (i = 0; i < DEV_MAX; i++) { | ||
319 | if (devices[i].minor != -1) { | ||
320 | unregister_sound_mixer(devices[i].minor); | ||
321 | printk("tvmixer: %s unregistered (#2)\n", | ||
322 | devices[i].dev->name); | ||
323 | } | ||
324 | } | ||
325 | } | ||
326 | |||
327 | module_init(tvmixer_init_module); | ||
328 | module_exit(tvmixer_cleanup_module); | ||
329 | |||
330 | /* | ||
331 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
332 | * --------------------------------------------------------------------------- | ||
333 | * Local variables: | ||
334 | * c-basic-offset: 8 | ||
335 | * End: | ||
336 | */ | ||
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 25716193a534..0c886c882385 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig | |||
@@ -15,6 +15,13 @@ config MFD_SM501 | |||
15 | interface. The device may be connected by PCI or local bus with | 15 | interface. The device may be connected by PCI or local bus with |
16 | varying functions enabled. | 16 | varying functions enabled. |
17 | 17 | ||
18 | config MFD_ASIC3 | ||
19 | bool "Support for Compaq ASIC3" | ||
20 | depends on GENERIC_HARDIRQS && ARM | ||
21 | ---help--- | ||
22 | This driver supports the ASIC3 multifunction chip found on many | ||
23 | PDAs (mainly iPAQ and HTC based ones) | ||
24 | |||
18 | endmenu | 25 | endmenu |
19 | 26 | ||
20 | menu "Multimedia Capabilities Port drivers" | 27 | menu "Multimedia Capabilities Port drivers" |
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 51432091b323..521cd5cb68af 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile | |||
@@ -3,6 +3,7 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | obj-$(CONFIG_MFD_SM501) += sm501.o | 5 | obj-$(CONFIG_MFD_SM501) += sm501.o |
6 | obj-$(CONFIG_MFD_ASIC3) += asic3.o | ||
6 | 7 | ||
7 | obj-$(CONFIG_MCP) += mcp-core.o | 8 | obj-$(CONFIG_MCP) += mcp-core.o |
8 | obj-$(CONFIG_MCP_SA11X0) += mcp-sa11x0.o | 9 | obj-$(CONFIG_MCP_SA11X0) += mcp-sa11x0.o |
diff --git a/drivers/mfd/asic3.c b/drivers/mfd/asic3.c new file mode 100644 index 000000000000..63fb1ff3ad10 --- /dev/null +++ b/drivers/mfd/asic3.c | |||
@@ -0,0 +1,588 @@ | |||
1 | /* | ||
2 | * driver/mfd/asic3.c | ||
3 | * | ||
4 | * Compaq ASIC3 support. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | * Copyright 2001 Compaq Computer Corporation. | ||
11 | * Copyright 2004-2005 Phil Blundell | ||
12 | * Copyright 2007 OpenedHand Ltd. | ||
13 | * | ||
14 | * Authors: Phil Blundell <pb@handhelds.org>, | ||
15 | * Samuel Ortiz <sameo@openedhand.com> | ||
16 | * | ||
17 | */ | ||
18 | |||
19 | #include <linux/version.h> | ||
20 | #include <linux/kernel.h> | ||
21 | #include <linux/irq.h> | ||
22 | #include <linux/io.h> | ||
23 | #include <linux/spinlock.h> | ||
24 | #include <linux/platform_device.h> | ||
25 | |||
26 | #include <linux/mfd/asic3.h> | ||
27 | |||
28 | static inline void asic3_write_register(struct asic3 *asic, | ||
29 | unsigned int reg, u32 value) | ||
30 | { | ||
31 | iowrite16(value, (unsigned long)asic->mapping + | ||
32 | (reg >> asic->bus_shift)); | ||
33 | } | ||
34 | |||
35 | static inline u32 asic3_read_register(struct asic3 *asic, | ||
36 | unsigned int reg) | ||
37 | { | ||
38 | return ioread16((unsigned long)asic->mapping + | ||
39 | (reg >> asic->bus_shift)); | ||
40 | } | ||
41 | |||
42 | /* IRQs */ | ||
43 | #define MAX_ASIC_ISR_LOOPS 20 | ||
44 | #define ASIC3_GPIO_Base_INCR \ | ||
45 | (ASIC3_GPIO_B_Base - ASIC3_GPIO_A_Base) | ||
46 | |||
47 | static void asic3_irq_flip_edge(struct asic3 *asic, | ||
48 | u32 base, int bit) | ||
49 | { | ||
50 | u16 edge; | ||
51 | unsigned long flags; | ||
52 | |||
53 | spin_lock_irqsave(&asic->lock, flags); | ||
54 | edge = asic3_read_register(asic, | ||
55 | base + ASIC3_GPIO_EdgeTrigger); | ||
56 | edge ^= bit; | ||
57 | asic3_write_register(asic, | ||
58 | base + ASIC3_GPIO_EdgeTrigger, edge); | ||
59 | spin_unlock_irqrestore(&asic->lock, flags); | ||
60 | } | ||
61 | |||
62 | static void asic3_irq_demux(unsigned int irq, struct irq_desc *desc) | ||
63 | { | ||
64 | int iter, i; | ||
65 | unsigned long flags; | ||
66 | struct asic3 *asic; | ||
67 | |||
68 | desc->chip->ack(irq); | ||
69 | |||
70 | asic = desc->handler_data; | ||
71 | |||
72 | for (iter = 0 ; iter < MAX_ASIC_ISR_LOOPS; iter++) { | ||
73 | u32 status; | ||
74 | int bank; | ||
75 | |||
76 | spin_lock_irqsave(&asic->lock, flags); | ||
77 | status = asic3_read_register(asic, | ||
78 | ASIC3_OFFSET(INTR, PIntStat)); | ||
79 | spin_unlock_irqrestore(&asic->lock, flags); | ||
80 | |||
81 | /* Check all ten register bits */ | ||
82 | if ((status & 0x3ff) == 0) | ||
83 | break; | ||
84 | |||
85 | /* Handle GPIO IRQs */ | ||
86 | for (bank = 0; bank < ASIC3_NUM_GPIO_BANKS; bank++) { | ||
87 | if (status & (1 << bank)) { | ||
88 | unsigned long base, istat; | ||
89 | |||
90 | base = ASIC3_GPIO_A_Base | ||
91 | + bank * ASIC3_GPIO_Base_INCR; | ||
92 | |||
93 | spin_lock_irqsave(&asic->lock, flags); | ||
94 | istat = asic3_read_register(asic, | ||
95 | base + | ||
96 | ASIC3_GPIO_IntStatus); | ||
97 | /* Clearing IntStatus */ | ||
98 | asic3_write_register(asic, | ||
99 | base + | ||
100 | ASIC3_GPIO_IntStatus, 0); | ||
101 | spin_unlock_irqrestore(&asic->lock, flags); | ||
102 | |||
103 | for (i = 0; i < ASIC3_GPIOS_PER_BANK; i++) { | ||
104 | int bit = (1 << i); | ||
105 | unsigned int irqnr; | ||
106 | |||
107 | if (!(istat & bit)) | ||
108 | continue; | ||
109 | |||
110 | irqnr = asic->irq_base + | ||
111 | (ASIC3_GPIOS_PER_BANK * bank) | ||
112 | + i; | ||
113 | desc = irq_desc + irqnr; | ||
114 | desc->handle_irq(irqnr, desc); | ||
115 | if (asic->irq_bothedge[bank] & bit) | ||
116 | asic3_irq_flip_edge(asic, base, | ||
117 | bit); | ||
118 | } | ||
119 | } | ||
120 | } | ||
121 | |||
122 | /* Handle remaining IRQs in the status register */ | ||
123 | for (i = ASIC3_NUM_GPIOS; i < ASIC3_NR_IRQS; i++) { | ||
124 | /* They start at bit 4 and go up */ | ||
125 | if (status & (1 << (i - ASIC3_NUM_GPIOS + 4))) { | ||
126 | desc = irq_desc + + i; | ||
127 | desc->handle_irq(asic->irq_base + i, | ||
128 | desc); | ||
129 | } | ||
130 | } | ||
131 | } | ||
132 | |||
133 | if (iter >= MAX_ASIC_ISR_LOOPS) | ||
134 | printk(KERN_ERR "%s: interrupt processing overrun\n", | ||
135 | __FUNCTION__); | ||
136 | } | ||
137 | |||
138 | static inline int asic3_irq_to_bank(struct asic3 *asic, int irq) | ||
139 | { | ||
140 | int n; | ||
141 | |||
142 | n = (irq - asic->irq_base) >> 4; | ||
143 | |||
144 | return (n * (ASIC3_GPIO_B_Base - ASIC3_GPIO_A_Base)); | ||
145 | } | ||
146 | |||
147 | static inline int asic3_irq_to_index(struct asic3 *asic, int irq) | ||
148 | { | ||
149 | return (irq - asic->irq_base) & 0xf; | ||
150 | } | ||
151 | |||
152 | static void asic3_mask_gpio_irq(unsigned int irq) | ||
153 | { | ||
154 | struct asic3 *asic = get_irq_chip_data(irq); | ||
155 | u32 val, bank, index; | ||
156 | unsigned long flags; | ||
157 | |||
158 | bank = asic3_irq_to_bank(asic, irq); | ||
159 | index = asic3_irq_to_index(asic, irq); | ||
160 | |||
161 | spin_lock_irqsave(&asic->lock, flags); | ||
162 | val = asic3_read_register(asic, bank + ASIC3_GPIO_Mask); | ||
163 | val |= 1 << index; | ||
164 | asic3_write_register(asic, bank + ASIC3_GPIO_Mask, val); | ||
165 | spin_unlock_irqrestore(&asic->lock, flags); | ||
166 | } | ||
167 | |||
168 | static void asic3_mask_irq(unsigned int irq) | ||
169 | { | ||
170 | struct asic3 *asic = get_irq_chip_data(irq); | ||
171 | int regval; | ||
172 | unsigned long flags; | ||
173 | |||
174 | spin_lock_irqsave(&asic->lock, flags); | ||
175 | regval = asic3_read_register(asic, | ||
176 | ASIC3_INTR_Base + | ||
177 | ASIC3_INTR_IntMask); | ||
178 | |||
179 | regval &= ~(ASIC3_INTMASK_MASK0 << | ||
180 | (irq - (asic->irq_base + ASIC3_NUM_GPIOS))); | ||
181 | |||
182 | asic3_write_register(asic, | ||
183 | ASIC3_INTR_Base + | ||
184 | ASIC3_INTR_IntMask, | ||
185 | regval); | ||
186 | spin_unlock_irqrestore(&asic->lock, flags); | ||
187 | } | ||
188 | |||
189 | static void asic3_unmask_gpio_irq(unsigned int irq) | ||
190 | { | ||
191 | struct asic3 *asic = get_irq_chip_data(irq); | ||
192 | u32 val, bank, index; | ||
193 | unsigned long flags; | ||
194 | |||
195 | bank = asic3_irq_to_bank(asic, irq); | ||
196 | index = asic3_irq_to_index(asic, irq); | ||
197 | |||
198 | spin_lock_irqsave(&asic->lock, flags); | ||
199 | val = asic3_read_register(asic, bank + ASIC3_GPIO_Mask); | ||
200 | val &= ~(1 << index); | ||
201 | asic3_write_register(asic, bank + ASIC3_GPIO_Mask, val); | ||
202 | spin_unlock_irqrestore(&asic->lock, flags); | ||
203 | } | ||
204 | |||
205 | static void asic3_unmask_irq(unsigned int irq) | ||
206 | { | ||
207 | struct asic3 *asic = get_irq_chip_data(irq); | ||
208 | int regval; | ||
209 | unsigned long flags; | ||
210 | |||
211 | spin_lock_irqsave(&asic->lock, flags); | ||
212 | regval = asic3_read_register(asic, | ||
213 | ASIC3_INTR_Base + | ||
214 | ASIC3_INTR_IntMask); | ||
215 | |||
216 | regval |= (ASIC3_INTMASK_MASK0 << | ||
217 | (irq - (asic->irq_base + ASIC3_NUM_GPIOS))); | ||
218 | |||
219 | asic3_write_register(asic, | ||
220 | ASIC3_INTR_Base + | ||
221 | ASIC3_INTR_IntMask, | ||
222 | regval); | ||
223 | spin_unlock_irqrestore(&asic->lock, flags); | ||
224 | } | ||
225 | |||
226 | static int asic3_gpio_irq_type(unsigned int irq, unsigned int type) | ||
227 | { | ||
228 | struct asic3 *asic = get_irq_chip_data(irq); | ||
229 | u32 bank, index; | ||
230 | u16 trigger, level, edge, bit; | ||
231 | unsigned long flags; | ||
232 | |||
233 | bank = asic3_irq_to_bank(asic, irq); | ||
234 | index = asic3_irq_to_index(asic, irq); | ||
235 | bit = 1<<index; | ||
236 | |||
237 | spin_lock_irqsave(&asic->lock, flags); | ||
238 | level = asic3_read_register(asic, | ||
239 | bank + ASIC3_GPIO_LevelTrigger); | ||
240 | edge = asic3_read_register(asic, | ||
241 | bank + ASIC3_GPIO_EdgeTrigger); | ||
242 | trigger = asic3_read_register(asic, | ||
243 | bank + ASIC3_GPIO_TriggerType); | ||
244 | asic->irq_bothedge[(irq - asic->irq_base) >> 4] &= ~bit; | ||
245 | |||
246 | if (type == IRQT_RISING) { | ||
247 | trigger |= bit; | ||
248 | edge |= bit; | ||
249 | } else if (type == IRQT_FALLING) { | ||
250 | trigger |= bit; | ||
251 | edge &= ~bit; | ||
252 | } else if (type == IRQT_BOTHEDGE) { | ||
253 | trigger |= bit; | ||
254 | if (asic3_gpio_get_value(asic, irq - asic->irq_base)) | ||
255 | edge &= ~bit; | ||
256 | else | ||
257 | edge |= bit; | ||
258 | asic->irq_bothedge[(irq - asic->irq_base) >> 4] |= bit; | ||
259 | } else if (type == IRQT_LOW) { | ||
260 | trigger &= ~bit; | ||
261 | level &= ~bit; | ||
262 | } else if (type == IRQT_HIGH) { | ||
263 | trigger &= ~bit; | ||
264 | level |= bit; | ||
265 | } else { | ||
266 | /* | ||
267 | * if type == IRQT_NOEDGE, we should mask interrupts, but | ||
268 | * be careful to not unmask them if mask was also called. | ||
269 | * Probably need internal state for mask. | ||
270 | */ | ||
271 | printk(KERN_NOTICE "asic3: irq type not changed.\n"); | ||
272 | } | ||
273 | asic3_write_register(asic, bank + ASIC3_GPIO_LevelTrigger, | ||
274 | level); | ||
275 | asic3_write_register(asic, bank + ASIC3_GPIO_EdgeTrigger, | ||
276 | edge); | ||
277 | asic3_write_register(asic, bank + ASIC3_GPIO_TriggerType, | ||
278 | trigger); | ||
279 | spin_unlock_irqrestore(&asic->lock, flags); | ||
280 | return 0; | ||
281 | } | ||
282 | |||
283 | static struct irq_chip asic3_gpio_irq_chip = { | ||
284 | .name = "ASIC3-GPIO", | ||
285 | .ack = asic3_mask_gpio_irq, | ||
286 | .mask = asic3_mask_gpio_irq, | ||
287 | .unmask = asic3_unmask_gpio_irq, | ||
288 | .set_type = asic3_gpio_irq_type, | ||
289 | }; | ||
290 | |||
291 | static struct irq_chip asic3_irq_chip = { | ||
292 | .name = "ASIC3", | ||
293 | .ack = asic3_mask_irq, | ||
294 | .mask = asic3_mask_irq, | ||
295 | .unmask = asic3_unmask_irq, | ||
296 | }; | ||
297 | |||
298 | static int asic3_irq_probe(struct platform_device *pdev) | ||
299 | { | ||
300 | struct asic3 *asic = platform_get_drvdata(pdev); | ||
301 | unsigned long clksel = 0; | ||
302 | unsigned int irq, irq_base; | ||
303 | |||
304 | asic->irq_nr = platform_get_irq(pdev, 0); | ||
305 | if (asic->irq_nr < 0) | ||
306 | return asic->irq_nr; | ||
307 | |||
308 | /* turn on clock to IRQ controller */ | ||
309 | clksel |= CLOCK_SEL_CX; | ||
310 | asic3_write_register(asic, ASIC3_OFFSET(CLOCK, SEL), | ||
311 | clksel); | ||
312 | |||
313 | irq_base = asic->irq_base; | ||
314 | |||
315 | for (irq = irq_base; irq < irq_base + ASIC3_NR_IRQS; irq++) { | ||
316 | if (irq < asic->irq_base + ASIC3_NUM_GPIOS) | ||
317 | set_irq_chip(irq, &asic3_gpio_irq_chip); | ||
318 | else | ||
319 | set_irq_chip(irq, &asic3_irq_chip); | ||
320 | |||
321 | set_irq_chip_data(irq, asic); | ||
322 | set_irq_handler(irq, handle_level_irq); | ||
323 | set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); | ||
324 | } | ||
325 | |||
326 | asic3_write_register(asic, ASIC3_OFFSET(INTR, IntMask), | ||
327 | ASIC3_INTMASK_GINTMASK); | ||
328 | |||
329 | set_irq_chained_handler(asic->irq_nr, asic3_irq_demux); | ||
330 | set_irq_type(asic->irq_nr, IRQT_RISING); | ||
331 | set_irq_data(asic->irq_nr, asic); | ||
332 | |||
333 | return 0; | ||
334 | } | ||
335 | |||
336 | static void asic3_irq_remove(struct platform_device *pdev) | ||
337 | { | ||
338 | struct asic3 *asic = platform_get_drvdata(pdev); | ||
339 | unsigned int irq, irq_base; | ||
340 | |||
341 | irq_base = asic->irq_base; | ||
342 | |||
343 | for (irq = irq_base; irq < irq_base + ASIC3_NR_IRQS; irq++) { | ||
344 | set_irq_flags(irq, 0); | ||
345 | set_irq_handler(irq, NULL); | ||
346 | set_irq_chip(irq, NULL); | ||
347 | set_irq_chip_data(irq, NULL); | ||
348 | } | ||
349 | set_irq_chained_handler(asic->irq_nr, NULL); | ||
350 | } | ||
351 | |||
352 | /* GPIOs */ | ||
353 | static inline u32 asic3_get_gpio(struct asic3 *asic, unsigned int base, | ||
354 | unsigned int function) | ||
355 | { | ||
356 | return asic3_read_register(asic, base + function); | ||
357 | } | ||
358 | |||
359 | static void asic3_set_gpio(struct asic3 *asic, unsigned int base, | ||
360 | unsigned int function, u32 bits, u32 val) | ||
361 | { | ||
362 | unsigned long flags; | ||
363 | |||
364 | spin_lock_irqsave(&asic->lock, flags); | ||
365 | val |= (asic3_read_register(asic, base + function) & ~bits); | ||
366 | |||
367 | asic3_write_register(asic, base + function, val); | ||
368 | spin_unlock_irqrestore(&asic->lock, flags); | ||
369 | } | ||
370 | |||
371 | #define asic3_get_gpio_a(asic, fn) \ | ||
372 | asic3_get_gpio(asic, ASIC3_GPIO_A_Base, ASIC3_GPIO_##fn) | ||
373 | #define asic3_get_gpio_b(asic, fn) \ | ||
374 | asic3_get_gpio(asic, ASIC3_GPIO_B_Base, ASIC3_GPIO_##fn) | ||
375 | #define asic3_get_gpio_c(asic, fn) \ | ||
376 | asic3_get_gpio(asic, ASIC3_GPIO_C_Base, ASIC3_GPIO_##fn) | ||
377 | #define asic3_get_gpio_d(asic, fn) \ | ||
378 | asic3_get_gpio(asic, ASIC3_GPIO_D_Base, ASIC3_GPIO_##fn) | ||
379 | |||
380 | #define asic3_set_gpio_a(asic, fn, bits, val) \ | ||
381 | asic3_set_gpio(asic, ASIC3_GPIO_A_Base, ASIC3_GPIO_##fn, bits, val) | ||
382 | #define asic3_set_gpio_b(asic, fn, bits, val) \ | ||
383 | asic3_set_gpio(asic, ASIC3_GPIO_B_Base, ASIC3_GPIO_##fn, bits, val) | ||
384 | #define asic3_set_gpio_c(asic, fn, bits, val) \ | ||
385 | asic3_set_gpio(asic, ASIC3_GPIO_C_Base, ASIC3_GPIO_##fn, bits, val) | ||
386 | #define asic3_set_gpio_d(asic, fn, bits, val) \ | ||
387 | asic3_set_gpio(asic, ASIC3_GPIO_D_Base, ASIC3_GPIO_##fn, bits, val) | ||
388 | |||
389 | #define asic3_set_gpio_banks(asic, fn, bits, pdata, field) \ | ||
390 | do { \ | ||
391 | asic3_set_gpio_a((asic), fn, (bits), (pdata)->gpio_a.field); \ | ||
392 | asic3_set_gpio_b((asic), fn, (bits), (pdata)->gpio_b.field); \ | ||
393 | asic3_set_gpio_c((asic), fn, (bits), (pdata)->gpio_c.field); \ | ||
394 | asic3_set_gpio_d((asic), fn, (bits), (pdata)->gpio_d.field); \ | ||
395 | } while (0) | ||
396 | |||
397 | int asic3_gpio_get_value(struct asic3 *asic, unsigned gpio) | ||
398 | { | ||
399 | u32 mask = ASIC3_GPIO_bit(gpio); | ||
400 | |||
401 | switch (gpio >> 4) { | ||
402 | case ASIC3_GPIO_BANK_A: | ||
403 | return asic3_get_gpio_a(asic, Status) & mask; | ||
404 | case ASIC3_GPIO_BANK_B: | ||
405 | return asic3_get_gpio_b(asic, Status) & mask; | ||
406 | case ASIC3_GPIO_BANK_C: | ||
407 | return asic3_get_gpio_c(asic, Status) & mask; | ||
408 | case ASIC3_GPIO_BANK_D: | ||
409 | return asic3_get_gpio_d(asic, Status) & mask; | ||
410 | default: | ||
411 | printk(KERN_ERR "%s: invalid GPIO value 0x%x", | ||
412 | __FUNCTION__, gpio); | ||
413 | return -EINVAL; | ||
414 | } | ||
415 | } | ||
416 | EXPORT_SYMBOL(asic3_gpio_get_value); | ||
417 | |||
418 | void asic3_gpio_set_value(struct asic3 *asic, unsigned gpio, int val) | ||
419 | { | ||
420 | u32 mask = ASIC3_GPIO_bit(gpio); | ||
421 | u32 bitval = 0; | ||
422 | if (val) | ||
423 | bitval = mask; | ||
424 | |||
425 | switch (gpio >> 4) { | ||
426 | case ASIC3_GPIO_BANK_A: | ||
427 | asic3_set_gpio_a(asic, Out, mask, bitval); | ||
428 | return; | ||
429 | case ASIC3_GPIO_BANK_B: | ||
430 | asic3_set_gpio_b(asic, Out, mask, bitval); | ||
431 | return; | ||
432 | case ASIC3_GPIO_BANK_C: | ||
433 | asic3_set_gpio_c(asic, Out, mask, bitval); | ||
434 | return; | ||
435 | case ASIC3_GPIO_BANK_D: | ||
436 | asic3_set_gpio_d(asic, Out, mask, bitval); | ||
437 | return; | ||
438 | default: | ||
439 | printk(KERN_ERR "%s: invalid GPIO value 0x%x", | ||
440 | __FUNCTION__, gpio); | ||
441 | return; | ||
442 | } | ||
443 | } | ||
444 | EXPORT_SYMBOL(asic3_gpio_set_value); | ||
445 | |||
446 | static int asic3_gpio_probe(struct platform_device *pdev) | ||
447 | { | ||
448 | struct asic3_platform_data *pdata = pdev->dev.platform_data; | ||
449 | struct asic3 *asic = platform_get_drvdata(pdev); | ||
450 | |||
451 | asic3_write_register(asic, ASIC3_GPIO_OFFSET(A, Mask), 0xffff); | ||
452 | asic3_write_register(asic, ASIC3_GPIO_OFFSET(B, Mask), 0xffff); | ||
453 | asic3_write_register(asic, ASIC3_GPIO_OFFSET(C, Mask), 0xffff); | ||
454 | asic3_write_register(asic, ASIC3_GPIO_OFFSET(D, Mask), 0xffff); | ||
455 | |||
456 | asic3_set_gpio_a(asic, SleepMask, 0xffff, 0xffff); | ||
457 | asic3_set_gpio_b(asic, SleepMask, 0xffff, 0xffff); | ||
458 | asic3_set_gpio_c(asic, SleepMask, 0xffff, 0xffff); | ||
459 | asic3_set_gpio_d(asic, SleepMask, 0xffff, 0xffff); | ||
460 | |||
461 | if (pdata) { | ||
462 | asic3_set_gpio_banks(asic, Out, 0xffff, pdata, init); | ||
463 | asic3_set_gpio_banks(asic, Direction, 0xffff, pdata, dir); | ||
464 | asic3_set_gpio_banks(asic, SleepMask, 0xffff, pdata, | ||
465 | sleep_mask); | ||
466 | asic3_set_gpio_banks(asic, SleepOut, 0xffff, pdata, sleep_out); | ||
467 | asic3_set_gpio_banks(asic, BattFaultOut, 0xffff, pdata, | ||
468 | batt_fault_out); | ||
469 | asic3_set_gpio_banks(asic, SleepConf, 0xffff, pdata, | ||
470 | sleep_conf); | ||
471 | asic3_set_gpio_banks(asic, AltFunction, 0xffff, pdata, | ||
472 | alt_function); | ||
473 | } | ||
474 | |||
475 | return 0; | ||
476 | } | ||
477 | |||
478 | static void asic3_gpio_remove(struct platform_device *pdev) | ||
479 | { | ||
480 | return; | ||
481 | } | ||
482 | |||
483 | |||
484 | /* Core */ | ||
485 | static int asic3_probe(struct platform_device *pdev) | ||
486 | { | ||
487 | struct asic3_platform_data *pdata = pdev->dev.platform_data; | ||
488 | struct asic3 *asic; | ||
489 | struct resource *mem; | ||
490 | unsigned long clksel; | ||
491 | int ret; | ||
492 | |||
493 | asic = kzalloc(sizeof(struct asic3), GFP_KERNEL); | ||
494 | if (!asic) | ||
495 | return -ENOMEM; | ||
496 | |||
497 | spin_lock_init(&asic->lock); | ||
498 | platform_set_drvdata(pdev, asic); | ||
499 | asic->dev = &pdev->dev; | ||
500 | |||
501 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
502 | if (!mem) { | ||
503 | ret = -ENOMEM; | ||
504 | printk(KERN_ERR "asic3: no MEM resource\n"); | ||
505 | goto err_out_1; | ||
506 | } | ||
507 | |||
508 | asic->mapping = ioremap(mem->start, PAGE_SIZE); | ||
509 | if (!asic->mapping) { | ||
510 | ret = -ENOMEM; | ||
511 | printk(KERN_ERR "asic3: couldn't ioremap\n"); | ||
512 | goto err_out_1; | ||
513 | } | ||
514 | |||
515 | asic->irq_base = pdata->irq_base; | ||
516 | |||
517 | if (pdata && pdata->bus_shift) | ||
518 | asic->bus_shift = 2 - pdata->bus_shift; | ||
519 | else | ||
520 | asic->bus_shift = 0; | ||
521 | |||
522 | clksel = 0; | ||
523 | asic3_write_register(asic, ASIC3_OFFSET(CLOCK, SEL), clksel); | ||
524 | |||
525 | ret = asic3_irq_probe(pdev); | ||
526 | if (ret < 0) { | ||
527 | printk(KERN_ERR "asic3: couldn't probe IRQs\n"); | ||
528 | goto err_out_2; | ||
529 | } | ||
530 | asic3_gpio_probe(pdev); | ||
531 | |||
532 | if (pdata->children) { | ||
533 | int i; | ||
534 | for (i = 0; i < pdata->n_children; i++) { | ||
535 | pdata->children[i]->dev.parent = &pdev->dev; | ||
536 | platform_device_register(pdata->children[i]); | ||
537 | } | ||
538 | } | ||
539 | |||
540 | printk(KERN_INFO "ASIC3 Core driver\n"); | ||
541 | |||
542 | return 0; | ||
543 | |||
544 | err_out_2: | ||
545 | iounmap(asic->mapping); | ||
546 | err_out_1: | ||
547 | kfree(asic); | ||
548 | |||
549 | return ret; | ||
550 | } | ||
551 | |||
552 | static int asic3_remove(struct platform_device *pdev) | ||
553 | { | ||
554 | struct asic3 *asic = platform_get_drvdata(pdev); | ||
555 | |||
556 | asic3_gpio_remove(pdev); | ||
557 | asic3_irq_remove(pdev); | ||
558 | |||
559 | asic3_write_register(asic, ASIC3_OFFSET(CLOCK, SEL), 0); | ||
560 | |||
561 | iounmap(asic->mapping); | ||
562 | |||
563 | kfree(asic); | ||
564 | |||
565 | return 0; | ||
566 | } | ||
567 | |||
568 | static void asic3_shutdown(struct platform_device *pdev) | ||
569 | { | ||
570 | } | ||
571 | |||
572 | static struct platform_driver asic3_device_driver = { | ||
573 | .driver = { | ||
574 | .name = "asic3", | ||
575 | }, | ||
576 | .probe = asic3_probe, | ||
577 | .remove = __devexit_p(asic3_remove), | ||
578 | .shutdown = asic3_shutdown, | ||
579 | }; | ||
580 | |||
581 | static int __init asic3_init(void) | ||
582 | { | ||
583 | int retval = 0; | ||
584 | retval = platform_driver_register(&asic3_device_driver); | ||
585 | return retval; | ||
586 | } | ||
587 | |||
588 | subsys_initcall(asic3_init); | ||
diff --git a/drivers/misc/asus-laptop.c b/drivers/misc/asus-laptop.c index 7dce318df1bd..0846c33296bc 100644 --- a/drivers/misc/asus-laptop.c +++ b/drivers/misc/asus-laptop.c | |||
@@ -33,7 +33,6 @@ | |||
33 | * Sam Lin - GPS support | 33 | * Sam Lin - GPS support |
34 | */ | 34 | */ |
35 | 35 | ||
36 | #include <linux/autoconf.h> | ||
37 | #include <linux/kernel.h> | 36 | #include <linux/kernel.h> |
38 | #include <linux/module.h> | 37 | #include <linux/module.h> |
39 | #include <linux/init.h> | 38 | #include <linux/init.h> |
diff --git a/drivers/misc/fujitsu-laptop.c b/drivers/misc/fujitsu-laptop.c index c8d62c268b11..1cfd7f3f1294 100644 --- a/drivers/misc/fujitsu-laptop.c +++ b/drivers/misc/fujitsu-laptop.c | |||
@@ -50,7 +50,6 @@ | |||
50 | #include <linux/dmi.h> | 50 | #include <linux/dmi.h> |
51 | #include <linux/backlight.h> | 51 | #include <linux/backlight.h> |
52 | #include <linux/platform_device.h> | 52 | #include <linux/platform_device.h> |
53 | #include <linux/autoconf.h> | ||
54 | 53 | ||
55 | #define FUJITSU_DRIVER_VERSION "0.3" | 54 | #define FUJITSU_DRIVER_VERSION "0.3" |
56 | 55 | ||
diff --git a/drivers/misc/lkdtm.c b/drivers/misc/lkdtm.c index 552b7957a92a..c884730c5eaf 100644 --- a/drivers/misc/lkdtm.c +++ b/drivers/misc/lkdtm.c | |||
@@ -129,27 +129,28 @@ module_param(cpoint_count, int, 0644); | |||
129 | MODULE_PARM_DESC(cpoint_count, " Crash Point Count, number of times the "\ | 129 | MODULE_PARM_DESC(cpoint_count, " Crash Point Count, number of times the "\ |
130 | "crash point is to be hit to trigger action"); | 130 | "crash point is to be hit to trigger action"); |
131 | 131 | ||
132 | unsigned int jp_do_irq(unsigned int irq) | 132 | static unsigned int jp_do_irq(unsigned int irq) |
133 | { | 133 | { |
134 | lkdtm_handler(); | 134 | lkdtm_handler(); |
135 | jprobe_return(); | 135 | jprobe_return(); |
136 | return 0; | 136 | return 0; |
137 | } | 137 | } |
138 | 138 | ||
139 | irqreturn_t jp_handle_irq_event(unsigned int irq, struct irqaction *action) | 139 | static irqreturn_t jp_handle_irq_event(unsigned int irq, |
140 | struct irqaction *action) | ||
140 | { | 141 | { |
141 | lkdtm_handler(); | 142 | lkdtm_handler(); |
142 | jprobe_return(); | 143 | jprobe_return(); |
143 | return 0; | 144 | return 0; |
144 | } | 145 | } |
145 | 146 | ||
146 | void jp_tasklet_action(struct softirq_action *a) | 147 | static void jp_tasklet_action(struct softirq_action *a) |
147 | { | 148 | { |
148 | lkdtm_handler(); | 149 | lkdtm_handler(); |
149 | jprobe_return(); | 150 | jprobe_return(); |
150 | } | 151 | } |
151 | 152 | ||
152 | void jp_ll_rw_block(int rw, int nr, struct buffer_head *bhs[]) | 153 | static void jp_ll_rw_block(int rw, int nr, struct buffer_head *bhs[]) |
153 | { | 154 | { |
154 | lkdtm_handler(); | 155 | lkdtm_handler(); |
155 | jprobe_return(); | 156 | jprobe_return(); |
@@ -157,23 +158,24 @@ void jp_ll_rw_block(int rw, int nr, struct buffer_head *bhs[]) | |||
157 | 158 | ||
158 | struct scan_control; | 159 | struct scan_control; |
159 | 160 | ||
160 | unsigned long jp_shrink_inactive_list(unsigned long max_scan, | 161 | static unsigned long jp_shrink_inactive_list(unsigned long max_scan, |
161 | struct zone *zone, struct scan_control *sc) | 162 | struct zone *zone, |
163 | struct scan_control *sc) | ||
162 | { | 164 | { |
163 | lkdtm_handler(); | 165 | lkdtm_handler(); |
164 | jprobe_return(); | 166 | jprobe_return(); |
165 | return 0; | 167 | return 0; |
166 | } | 168 | } |
167 | 169 | ||
168 | int jp_hrtimer_start(struct hrtimer *timer, ktime_t tim, | 170 | static int jp_hrtimer_start(struct hrtimer *timer, ktime_t tim, |
169 | const enum hrtimer_mode mode) | 171 | const enum hrtimer_mode mode) |
170 | { | 172 | { |
171 | lkdtm_handler(); | 173 | lkdtm_handler(); |
172 | jprobe_return(); | 174 | jprobe_return(); |
173 | return 0; | 175 | return 0; |
174 | } | 176 | } |
175 | 177 | ||
176 | int jp_scsi_dispatch_cmd(struct scsi_cmnd *cmd) | 178 | static int jp_scsi_dispatch_cmd(struct scsi_cmnd *cmd) |
177 | { | 179 | { |
178 | lkdtm_handler(); | 180 | lkdtm_handler(); |
179 | jprobe_return(); | 181 | jprobe_return(); |
@@ -270,7 +272,7 @@ void lkdtm_handler(void) | |||
270 | } | 272 | } |
271 | } | 273 | } |
272 | 274 | ||
273 | int lkdtm_module_init(void) | 275 | static int __init lkdtm_module_init(void) |
274 | { | 276 | { |
275 | int ret; | 277 | int ret; |
276 | 278 | ||
@@ -331,7 +333,7 @@ int lkdtm_module_init(void) | |||
331 | return 0; | 333 | return 0; |
332 | } | 334 | } |
333 | 335 | ||
334 | void lkdtm_module_exit(void) | 336 | static void __exit lkdtm_module_exit(void) |
335 | { | 337 | { |
336 | unregister_jprobe(&lkdtm); | 338 | unregister_jprobe(&lkdtm); |
337 | printk(KERN_INFO "lkdtm : Crash point unregistered\n"); | 339 | printk(KERN_INFO "lkdtm : Crash point unregistered\n"); |
diff --git a/drivers/misc/msi-laptop.c b/drivers/misc/msi-laptop.c index 83679c762925..de898c6938f3 100644 --- a/drivers/misc/msi-laptop.c +++ b/drivers/misc/msi-laptop.c | |||
@@ -58,7 +58,6 @@ | |||
58 | #include <linux/dmi.h> | 58 | #include <linux/dmi.h> |
59 | #include <linux/backlight.h> | 59 | #include <linux/backlight.h> |
60 | #include <linux/platform_device.h> | 60 | #include <linux/platform_device.h> |
61 | #include <linux/autoconf.h> | ||
62 | 61 | ||
63 | #define MSI_DRIVER_VERSION "0.5" | 62 | #define MSI_DRIVER_VERSION "0.5" |
64 | 63 | ||
diff --git a/drivers/misc/phantom.c b/drivers/misc/phantom.c index cd221fd0fb94..7fa61e907e1c 100644 --- a/drivers/misc/phantom.c +++ b/drivers/misc/phantom.c | |||
@@ -25,7 +25,7 @@ | |||
25 | #include <asm/atomic.h> | 25 | #include <asm/atomic.h> |
26 | #include <asm/io.h> | 26 | #include <asm/io.h> |
27 | 27 | ||
28 | #define PHANTOM_VERSION "n0.9.7" | 28 | #define PHANTOM_VERSION "n0.9.8" |
29 | 29 | ||
30 | #define PHANTOM_MAX_MINORS 8 | 30 | #define PHANTOM_MAX_MINORS 8 |
31 | 31 | ||
@@ -456,8 +456,9 @@ static int phantom_resume(struct pci_dev *pdev) | |||
456 | #endif | 456 | #endif |
457 | 457 | ||
458 | static struct pci_device_id phantom_pci_tbl[] __devinitdata = { | 458 | static struct pci_device_id phantom_pci_tbl[] __devinitdata = { |
459 | { PCI_DEVICE(PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050), | 459 | { .vendor = PCI_VENDOR_ID_PLX, .device = PCI_DEVICE_ID_PLX_9050, |
460 | .class = PCI_CLASS_BRIDGE_OTHER << 8, .class_mask = 0xffff00 }, | 460 | .subvendor = PCI_VENDOR_ID_PLX, .subdevice = PCI_DEVICE_ID_PLX_9050, |
461 | .class = PCI_CLASS_BRIDGE_OTHER << 8, .class_mask = 0xffff00 }, | ||
461 | { 0, } | 462 | { 0, } |
462 | }; | 463 | }; |
463 | MODULE_DEVICE_TABLE(pci, phantom_pci_tbl); | 464 | MODULE_DEVICE_TABLE(pci, phantom_pci_tbl); |
diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c index be4b9948c762..eeaaa9dce6ef 100644 --- a/drivers/mtd/devices/block2mtd.c +++ b/drivers/mtd/devices/block2mtd.c | |||
@@ -4,7 +4,7 @@ | |||
4 | * block2mtd.c - create an mtd from a block device | 4 | * block2mtd.c - create an mtd from a block device |
5 | * | 5 | * |
6 | * Copyright (C) 2001,2002 Simon Evans <spse@secret.org.uk> | 6 | * Copyright (C) 2001,2002 Simon Evans <spse@secret.org.uk> |
7 | * Copyright (C) 2004-2006 Jörn Engel <joern@wh.fh-wedel.de> | 7 | * Copyright (C) 2004-2006 Joern Engel <joern@wh.fh-wedel.de> |
8 | * | 8 | * |
9 | * Licence: GPL | 9 | * Licence: GPL |
10 | */ | 10 | */ |
@@ -485,5 +485,5 @@ module_init(block2mtd_init); | |||
485 | module_exit(block2mtd_exit); | 485 | module_exit(block2mtd_exit); |
486 | 486 | ||
487 | MODULE_LICENSE("GPL"); | 487 | MODULE_LICENSE("GPL"); |
488 | MODULE_AUTHOR("Simon Evans <spse@secret.org.uk> and others"); | 488 | MODULE_AUTHOR("Joern Engel <joern@lazybastard.org>"); |
489 | MODULE_DESCRIPTION("Emulate an MTD using a block device"); | 489 | MODULE_DESCRIPTION("Emulate an MTD using a block device"); |
diff --git a/drivers/mtd/devices/phram.c b/drivers/mtd/devices/phram.c index 56cc1ca7ffd5..180298b92a7a 100644 --- a/drivers/mtd/devices/phram.c +++ b/drivers/mtd/devices/phram.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * $Id: phram.c,v 1.16 2005/11/07 11:14:25 gleixner Exp $ | 2 | * $Id: phram.c,v 1.16 2005/11/07 11:14:25 gleixner Exp $ |
3 | * | 3 | * |
4 | * Copyright (c) ???? Jochen Schäuble <psionic@psionic.de> | 4 | * Copyright (c) ???? Jochen Schäuble <psionic@psionic.de> |
5 | * Copyright (c) 2003-2004 Jörn Engel <joern@wh.fh-wedel.de> | 5 | * Copyright (c) 2003-2004 Joern Engel <joern@wh.fh-wedel.de> |
6 | * | 6 | * |
7 | * Usage: | 7 | * Usage: |
8 | * | 8 | * |
@@ -299,5 +299,5 @@ module_init(init_phram); | |||
299 | module_exit(cleanup_phram); | 299 | module_exit(cleanup_phram); |
300 | 300 | ||
301 | MODULE_LICENSE("GPL"); | 301 | MODULE_LICENSE("GPL"); |
302 | MODULE_AUTHOR("Jörn Engel <joern@wh.fh-wedel.de>"); | 302 | MODULE_AUTHOR("Joern Engel <joern@wh.fh-wedel.de>"); |
303 | MODULE_DESCRIPTION("MTD driver for physical RAM"); | 303 | MODULE_DESCRIPTION("MTD driver for physical RAM"); |
diff --git a/drivers/mtd/maps/mtx-1_flash.c b/drivers/mtd/maps/mtx-1_flash.c index d884f2be28f6..2a8fde9b92f0 100644 --- a/drivers/mtd/maps/mtx-1_flash.c +++ b/drivers/mtd/maps/mtx-1_flash.c | |||
@@ -4,7 +4,7 @@ | |||
4 | * $Id: mtx-1_flash.c,v 1.2 2005/11/07 11:14:27 gleixner Exp $ | 4 | * $Id: mtx-1_flash.c,v 1.2 2005/11/07 11:14:27 gleixner Exp $ |
5 | * | 5 | * |
6 | * (C) 2005 Bruno Randolf <bruno.randolf@4g-systems.biz> | 6 | * (C) 2005 Bruno Randolf <bruno.randolf@4g-systems.biz> |
7 | * (C) 2005 Jörn Engel <joern@wohnheim.fh-wedel.de> | 7 | * (C) 2005 Joern Engel <joern@wohnheim.fh-wedel.de> |
8 | * | 8 | * |
9 | */ | 9 | */ |
10 | 10 | ||
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 36342230a6de..d4843d014bc9 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c | |||
@@ -323,8 +323,8 @@ enum { | |||
323 | NvRegMIIStatus = 0x180, | 323 | NvRegMIIStatus = 0x180, |
324 | #define NVREG_MIISTAT_ERROR 0x0001 | 324 | #define NVREG_MIISTAT_ERROR 0x0001 |
325 | #define NVREG_MIISTAT_LINKCHANGE 0x0008 | 325 | #define NVREG_MIISTAT_LINKCHANGE 0x0008 |
326 | #define NVREG_MIISTAT_MASK 0x000f | 326 | #define NVREG_MIISTAT_MASK_RW 0x0007 |
327 | #define NVREG_MIISTAT_MASK2 0x000f | 327 | #define NVREG_MIISTAT_MASK_ALL 0x000f |
328 | NvRegMIIMask = 0x184, | 328 | NvRegMIIMask = 0x184, |
329 | #define NVREG_MII_LINKCHANGE 0x0008 | 329 | #define NVREG_MII_LINKCHANGE 0x0008 |
330 | 330 | ||
@@ -624,6 +624,9 @@ union ring_type { | |||
624 | #define NV_MSI_X_VECTOR_TX 0x1 | 624 | #define NV_MSI_X_VECTOR_TX 0x1 |
625 | #define NV_MSI_X_VECTOR_OTHER 0x2 | 625 | #define NV_MSI_X_VECTOR_OTHER 0x2 |
626 | 626 | ||
627 | #define NV_RESTART_TX 0x1 | ||
628 | #define NV_RESTART_RX 0x2 | ||
629 | |||
627 | /* statistics */ | 630 | /* statistics */ |
628 | struct nv_ethtool_str { | 631 | struct nv_ethtool_str { |
629 | char name[ETH_GSTRING_LEN]; | 632 | char name[ETH_GSTRING_LEN]; |
@@ -1061,7 +1064,7 @@ static int mii_rw(struct net_device *dev, int addr, int miireg, int value) | |||
1061 | u32 reg; | 1064 | u32 reg; |
1062 | int retval; | 1065 | int retval; |
1063 | 1066 | ||
1064 | writel(NVREG_MIISTAT_MASK, base + NvRegMIIStatus); | 1067 | writel(NVREG_MIISTAT_MASK_RW, base + NvRegMIIStatus); |
1065 | 1068 | ||
1066 | reg = readl(base + NvRegMIIControl); | 1069 | reg = readl(base + NvRegMIIControl); |
1067 | if (reg & NVREG_MIICTL_INUSE) { | 1070 | if (reg & NVREG_MIICTL_INUSE) { |
@@ -1432,16 +1435,30 @@ static void nv_mac_reset(struct net_device *dev) | |||
1432 | { | 1435 | { |
1433 | struct fe_priv *np = netdev_priv(dev); | 1436 | struct fe_priv *np = netdev_priv(dev); |
1434 | u8 __iomem *base = get_hwbase(dev); | 1437 | u8 __iomem *base = get_hwbase(dev); |
1438 | u32 temp1, temp2, temp3; | ||
1435 | 1439 | ||
1436 | dprintk(KERN_DEBUG "%s: nv_mac_reset\n", dev->name); | 1440 | dprintk(KERN_DEBUG "%s: nv_mac_reset\n", dev->name); |
1441 | |||
1437 | writel(NVREG_TXRXCTL_BIT2 | NVREG_TXRXCTL_RESET | np->txrxctl_bits, base + NvRegTxRxControl); | 1442 | writel(NVREG_TXRXCTL_BIT2 | NVREG_TXRXCTL_RESET | np->txrxctl_bits, base + NvRegTxRxControl); |
1438 | pci_push(base); | 1443 | pci_push(base); |
1444 | |||
1445 | /* save registers since they will be cleared on reset */ | ||
1446 | temp1 = readl(base + NvRegMacAddrA); | ||
1447 | temp2 = readl(base + NvRegMacAddrB); | ||
1448 | temp3 = readl(base + NvRegTransmitPoll); | ||
1449 | |||
1439 | writel(NVREG_MAC_RESET_ASSERT, base + NvRegMacReset); | 1450 | writel(NVREG_MAC_RESET_ASSERT, base + NvRegMacReset); |
1440 | pci_push(base); | 1451 | pci_push(base); |
1441 | udelay(NV_MAC_RESET_DELAY); | 1452 | udelay(NV_MAC_RESET_DELAY); |
1442 | writel(0, base + NvRegMacReset); | 1453 | writel(0, base + NvRegMacReset); |
1443 | pci_push(base); | 1454 | pci_push(base); |
1444 | udelay(NV_MAC_RESET_DELAY); | 1455 | udelay(NV_MAC_RESET_DELAY); |
1456 | |||
1457 | /* restore saved registers */ | ||
1458 | writel(temp1, base + NvRegMacAddrA); | ||
1459 | writel(temp2, base + NvRegMacAddrB); | ||
1460 | writel(temp3, base + NvRegTransmitPoll); | ||
1461 | |||
1445 | writel(NVREG_TXRXCTL_BIT2 | np->txrxctl_bits, base + NvRegTxRxControl); | 1462 | writel(NVREG_TXRXCTL_BIT2 | np->txrxctl_bits, base + NvRegTxRxControl); |
1446 | pci_push(base); | 1463 | pci_push(base); |
1447 | } | 1464 | } |
@@ -2767,6 +2784,7 @@ static int nv_update_linkspeed(struct net_device *dev) | |||
2767 | int mii_status; | 2784 | int mii_status; |
2768 | int retval = 0; | 2785 | int retval = 0; |
2769 | u32 control_1000, status_1000, phyreg, pause_flags, txreg; | 2786 | u32 control_1000, status_1000, phyreg, pause_flags, txreg; |
2787 | u32 txrxFlags = 0; | ||
2770 | 2788 | ||
2771 | /* BMSR_LSTATUS is latched, read it twice: | 2789 | /* BMSR_LSTATUS is latched, read it twice: |
2772 | * we want the current value. | 2790 | * we want the current value. |
@@ -2862,6 +2880,16 @@ set_speed: | |||
2862 | np->duplex = newdup; | 2880 | np->duplex = newdup; |
2863 | np->linkspeed = newls; | 2881 | np->linkspeed = newls; |
2864 | 2882 | ||
2883 | /* The transmitter and receiver must be restarted for safe update */ | ||
2884 | if (readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_START) { | ||
2885 | txrxFlags |= NV_RESTART_TX; | ||
2886 | nv_stop_tx(dev); | ||
2887 | } | ||
2888 | if (readl(base + NvRegReceiverControl) & NVREG_RCVCTL_START) { | ||
2889 | txrxFlags |= NV_RESTART_RX; | ||
2890 | nv_stop_rx(dev); | ||
2891 | } | ||
2892 | |||
2865 | if (np->gigabit == PHY_GIGABIT) { | 2893 | if (np->gigabit == PHY_GIGABIT) { |
2866 | phyreg = readl(base + NvRegRandomSeed); | 2894 | phyreg = readl(base + NvRegRandomSeed); |
2867 | phyreg &= ~(0x3FF00); | 2895 | phyreg &= ~(0x3FF00); |
@@ -2950,6 +2978,11 @@ set_speed: | |||
2950 | } | 2978 | } |
2951 | nv_update_pause(dev, pause_flags); | 2979 | nv_update_pause(dev, pause_flags); |
2952 | 2980 | ||
2981 | if (txrxFlags & NV_RESTART_TX) | ||
2982 | nv_start_tx(dev); | ||
2983 | if (txrxFlags & NV_RESTART_RX) | ||
2984 | nv_start_rx(dev); | ||
2985 | |||
2953 | return retval; | 2986 | return retval; |
2954 | } | 2987 | } |
2955 | 2988 | ||
@@ -2976,7 +3009,7 @@ static void nv_link_irq(struct net_device *dev) | |||
2976 | u32 miistat; | 3009 | u32 miistat; |
2977 | 3010 | ||
2978 | miistat = readl(base + NvRegMIIStatus); | 3011 | miistat = readl(base + NvRegMIIStatus); |
2979 | writel(NVREG_MIISTAT_MASK, base + NvRegMIIStatus); | 3012 | writel(NVREG_MIISTAT_LINKCHANGE, base + NvRegMIIStatus); |
2980 | dprintk(KERN_INFO "%s: link change irq, status 0x%x.\n", dev->name, miistat); | 3013 | dprintk(KERN_INFO "%s: link change irq, status 0x%x.\n", dev->name, miistat); |
2981 | 3014 | ||
2982 | if (miistat & (NVREG_MIISTAT_LINKCHANGE)) | 3015 | if (miistat & (NVREG_MIISTAT_LINKCHANGE)) |
@@ -4851,7 +4884,7 @@ static int nv_open(struct net_device *dev) | |||
4851 | 4884 | ||
4852 | writel(0, base + NvRegMIIMask); | 4885 | writel(0, base + NvRegMIIMask); |
4853 | writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus); | 4886 | writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus); |
4854 | writel(NVREG_MIISTAT_MASK2, base + NvRegMIIStatus); | 4887 | writel(NVREG_MIISTAT_MASK_ALL, base + NvRegMIIStatus); |
4855 | 4888 | ||
4856 | writel(NVREG_MISC1_FORCE | NVREG_MISC1_HD, base + NvRegMisc1); | 4889 | writel(NVREG_MISC1_FORCE | NVREG_MISC1_HD, base + NvRegMisc1); |
4857 | writel(readl(base + NvRegTransmitterStatus), base + NvRegTransmitterStatus); | 4890 | writel(readl(base + NvRegTransmitterStatus), base + NvRegTransmitterStatus); |
@@ -4889,7 +4922,7 @@ static int nv_open(struct net_device *dev) | |||
4889 | 4922 | ||
4890 | nv_disable_hw_interrupts(dev, np->irqmask); | 4923 | nv_disable_hw_interrupts(dev, np->irqmask); |
4891 | pci_push(base); | 4924 | pci_push(base); |
4892 | writel(NVREG_MIISTAT_MASK2, base + NvRegMIIStatus); | 4925 | writel(NVREG_MIISTAT_MASK_ALL, base + NvRegMIIStatus); |
4893 | writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus); | 4926 | writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus); |
4894 | pci_push(base); | 4927 | pci_push(base); |
4895 | 4928 | ||
@@ -4912,7 +4945,7 @@ static int nv_open(struct net_device *dev) | |||
4912 | { | 4945 | { |
4913 | u32 miistat; | 4946 | u32 miistat; |
4914 | miistat = readl(base + NvRegMIIStatus); | 4947 | miistat = readl(base + NvRegMIIStatus); |
4915 | writel(NVREG_MIISTAT_MASK, base + NvRegMIIStatus); | 4948 | writel(NVREG_MIISTAT_MASK_ALL, base + NvRegMIIStatus); |
4916 | dprintk(KERN_INFO "startup: got 0x%08x.\n", miistat); | 4949 | dprintk(KERN_INFO "startup: got 0x%08x.\n", miistat); |
4917 | } | 4950 | } |
4918 | /* set linkspeed to invalid value, thus force nv_update_linkspeed | 4951 | /* set linkspeed to invalid value, thus force nv_update_linkspeed |
@@ -5280,7 +5313,7 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i | |||
5280 | phystate &= ~NVREG_ADAPTCTL_RUNNING; | 5313 | phystate &= ~NVREG_ADAPTCTL_RUNNING; |
5281 | writel(phystate, base + NvRegAdapterControl); | 5314 | writel(phystate, base + NvRegAdapterControl); |
5282 | } | 5315 | } |
5283 | writel(NVREG_MIISTAT_MASK, base + NvRegMIIStatus); | 5316 | writel(NVREG_MIISTAT_MASK_ALL, base + NvRegMIIStatus); |
5284 | 5317 | ||
5285 | if (id->driver_data & DEV_HAS_MGMT_UNIT) { | 5318 | if (id->driver_data & DEV_HAS_MGMT_UNIT) { |
5286 | /* management unit running on the mac? */ | 5319 | /* management unit running on the mac? */ |
diff --git a/drivers/net/gianfar_mii.c b/drivers/net/gianfar_mii.c index 100bf410bf5f..6a647d95e6ea 100644 --- a/drivers/net/gianfar_mii.c +++ b/drivers/net/gianfar_mii.c | |||
@@ -127,7 +127,7 @@ int gfar_mdio_reset(struct mii_bus *bus) | |||
127 | struct gfar_mii __iomem *regs = (void __iomem *)bus->priv; | 127 | struct gfar_mii __iomem *regs = (void __iomem *)bus->priv; |
128 | unsigned int timeout = PHY_INIT_TIMEOUT; | 128 | unsigned int timeout = PHY_INIT_TIMEOUT; |
129 | 129 | ||
130 | spin_lock_bh(&bus->mdio_lock); | 130 | mutex_lock(&bus->mdio_lock); |
131 | 131 | ||
132 | /* Reset the management interface */ | 132 | /* Reset the management interface */ |
133 | gfar_write(®s->miimcfg, MIIMCFG_RESET); | 133 | gfar_write(®s->miimcfg, MIIMCFG_RESET); |
@@ -140,7 +140,7 @@ int gfar_mdio_reset(struct mii_bus *bus) | |||
140 | timeout--) | 140 | timeout--) |
141 | cpu_relax(); | 141 | cpu_relax(); |
142 | 142 | ||
143 | spin_unlock_bh(&bus->mdio_lock); | 143 | mutex_unlock(&bus->mdio_lock); |
144 | 144 | ||
145 | if(timeout <= 0) { | 145 | if(timeout <= 0) { |
146 | printk(KERN_ERR "%s: The MII Bus is stuck!\n", | 146 | printk(KERN_ERR "%s: The MII Bus is stuck!\n", |
diff --git a/drivers/net/iseries_veth.c b/drivers/net/iseries_veth.c index 419861cbc65e..58d3bb622da6 100644 --- a/drivers/net/iseries_veth.c +++ b/drivers/net/iseries_veth.c | |||
@@ -1020,7 +1020,7 @@ static const struct ethtool_ops ops = { | |||
1020 | .get_link = veth_get_link, | 1020 | .get_link = veth_get_link, |
1021 | }; | 1021 | }; |
1022 | 1022 | ||
1023 | static struct net_device * __init veth_probe_one(int vlan, | 1023 | static struct net_device *veth_probe_one(int vlan, |
1024 | struct vio_dev *vio_dev) | 1024 | struct vio_dev *vio_dev) |
1025 | { | 1025 | { |
1026 | struct net_device *dev; | 1026 | struct net_device *dev; |
diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h index a021a6e72641..d0bf206632ca 100644 --- a/drivers/net/ixgbe/ixgbe.h +++ b/drivers/net/ixgbe/ixgbe.h | |||
@@ -136,8 +136,6 @@ struct ixgbe_ring { | |||
136 | u16 head; | 136 | u16 head; |
137 | u16 tail; | 137 | u16 tail; |
138 | 138 | ||
139 | /* To protect race between sender and clean_tx_irq */ | ||
140 | spinlock_t tx_lock; | ||
141 | 139 | ||
142 | struct ixgbe_queue_stats stats; | 140 | struct ixgbe_queue_stats stats; |
143 | 141 | ||
@@ -174,7 +172,6 @@ struct ixgbe_adapter { | |||
174 | struct vlan_group *vlgrp; | 172 | struct vlan_group *vlgrp; |
175 | u16 bd_number; | 173 | u16 bd_number; |
176 | u16 rx_buf_len; | 174 | u16 rx_buf_len; |
177 | atomic_t irq_sem; | ||
178 | struct work_struct reset_task; | 175 | struct work_struct reset_task; |
179 | 176 | ||
180 | /* TX */ | 177 | /* TX */ |
@@ -244,6 +241,7 @@ extern const char ixgbe_driver_version[]; | |||
244 | 241 | ||
245 | extern int ixgbe_up(struct ixgbe_adapter *adapter); | 242 | extern int ixgbe_up(struct ixgbe_adapter *adapter); |
246 | extern void ixgbe_down(struct ixgbe_adapter *adapter); | 243 | extern void ixgbe_down(struct ixgbe_adapter *adapter); |
244 | extern void ixgbe_reinit_locked(struct ixgbe_adapter *adapter); | ||
247 | extern void ixgbe_reset(struct ixgbe_adapter *adapter); | 245 | extern void ixgbe_reset(struct ixgbe_adapter *adapter); |
248 | extern void ixgbe_update_stats(struct ixgbe_adapter *adapter); | 246 | extern void ixgbe_update_stats(struct ixgbe_adapter *adapter); |
249 | extern void ixgbe_set_ethtool_ops(struct net_device *netdev); | 247 | extern void ixgbe_set_ethtool_ops(struct net_device *netdev); |
diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c index 36353447716d..a119cbd8dbb8 100644 --- a/drivers/net/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ixgbe/ixgbe_ethtool.c | |||
@@ -103,21 +103,41 @@ static int ixgbe_get_settings(struct net_device *netdev, | |||
103 | struct ethtool_cmd *ecmd) | 103 | struct ethtool_cmd *ecmd) |
104 | { | 104 | { |
105 | struct ixgbe_adapter *adapter = netdev_priv(netdev); | 105 | struct ixgbe_adapter *adapter = netdev_priv(netdev); |
106 | struct ixgbe_hw *hw = &adapter->hw; | ||
107 | u32 link_speed = 0; | ||
108 | bool link_up; | ||
106 | 109 | ||
107 | ecmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE); | 110 | ecmd->supported = SUPPORTED_10000baseT_Full; |
108 | ecmd->advertising = (ADVERTISED_10000baseT_Full | ADVERTISED_FIBRE); | 111 | ecmd->autoneg = AUTONEG_ENABLE; |
109 | ecmd->port = PORT_FIBRE; | ||
110 | ecmd->transceiver = XCVR_EXTERNAL; | 112 | ecmd->transceiver = XCVR_EXTERNAL; |
113 | if (hw->phy.media_type == ixgbe_media_type_copper) { | ||
114 | ecmd->supported |= (SUPPORTED_1000baseT_Full | | ||
115 | SUPPORTED_TP | SUPPORTED_Autoneg); | ||
116 | |||
117 | ecmd->advertising = (ADVERTISED_TP | ADVERTISED_Autoneg); | ||
118 | if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_10GB_FULL) | ||
119 | ecmd->advertising |= ADVERTISED_10000baseT_Full; | ||
120 | if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_1GB_FULL) | ||
121 | ecmd->advertising |= ADVERTISED_1000baseT_Full; | ||
122 | |||
123 | ecmd->port = PORT_TP; | ||
124 | } else { | ||
125 | ecmd->supported |= SUPPORTED_FIBRE; | ||
126 | ecmd->advertising = (ADVERTISED_10000baseT_Full | | ||
127 | ADVERTISED_FIBRE); | ||
128 | ecmd->port = PORT_FIBRE; | ||
129 | } | ||
111 | 130 | ||
112 | if (netif_carrier_ok(adapter->netdev)) { | 131 | adapter->hw.mac.ops.check_link(hw, &(link_speed), &link_up); |
113 | ecmd->speed = SPEED_10000; | 132 | if (link_up) { |
133 | ecmd->speed = (link_speed == IXGBE_LINK_SPEED_10GB_FULL) ? | ||
134 | SPEED_10000 : SPEED_1000; | ||
114 | ecmd->duplex = DUPLEX_FULL; | 135 | ecmd->duplex = DUPLEX_FULL; |
115 | } else { | 136 | } else { |
116 | ecmd->speed = -1; | 137 | ecmd->speed = -1; |
117 | ecmd->duplex = -1; | 138 | ecmd->duplex = -1; |
118 | } | 139 | } |
119 | 140 | ||
120 | ecmd->autoneg = AUTONEG_DISABLE; | ||
121 | return 0; | 141 | return 0; |
122 | } | 142 | } |
123 | 143 | ||
@@ -125,17 +145,17 @@ static int ixgbe_set_settings(struct net_device *netdev, | |||
125 | struct ethtool_cmd *ecmd) | 145 | struct ethtool_cmd *ecmd) |
126 | { | 146 | { |
127 | struct ixgbe_adapter *adapter = netdev_priv(netdev); | 147 | struct ixgbe_adapter *adapter = netdev_priv(netdev); |
148 | struct ixgbe_hw *hw = &adapter->hw; | ||
128 | 149 | ||
129 | if (ecmd->autoneg == AUTONEG_ENABLE || | 150 | switch (hw->phy.media_type) { |
130 | ecmd->speed + ecmd->duplex != SPEED_10000 + DUPLEX_FULL) | 151 | case ixgbe_media_type_fiber: |
131 | return -EINVAL; | 152 | if ((ecmd->autoneg == AUTONEG_ENABLE) || |
132 | 153 | (ecmd->speed + ecmd->duplex != SPEED_10000 + DUPLEX_FULL)) | |
133 | if (netif_running(adapter->netdev)) { | 154 | return -EINVAL; |
134 | ixgbe_down(adapter); | 155 | /* in this case we currently only support 10Gb/FULL */ |
135 | ixgbe_reset(adapter); | 156 | break; |
136 | ixgbe_up(adapter); | 157 | default: |
137 | } else { | 158 | break; |
138 | ixgbe_reset(adapter); | ||
139 | } | 159 | } |
140 | 160 | ||
141 | return 0; | 161 | return 0; |
@@ -147,7 +167,7 @@ static void ixgbe_get_pauseparam(struct net_device *netdev, | |||
147 | struct ixgbe_adapter *adapter = netdev_priv(netdev); | 167 | struct ixgbe_adapter *adapter = netdev_priv(netdev); |
148 | struct ixgbe_hw *hw = &adapter->hw; | 168 | struct ixgbe_hw *hw = &adapter->hw; |
149 | 169 | ||
150 | pause->autoneg = AUTONEG_DISABLE; | 170 | pause->autoneg = (hw->fc.type == ixgbe_fc_full ? 1 : 0); |
151 | 171 | ||
152 | if (hw->fc.type == ixgbe_fc_rx_pause) { | 172 | if (hw->fc.type == ixgbe_fc_rx_pause) { |
153 | pause->rx_pause = 1; | 173 | pause->rx_pause = 1; |
@@ -165,10 +185,8 @@ static int ixgbe_set_pauseparam(struct net_device *netdev, | |||
165 | struct ixgbe_adapter *adapter = netdev_priv(netdev); | 185 | struct ixgbe_adapter *adapter = netdev_priv(netdev); |
166 | struct ixgbe_hw *hw = &adapter->hw; | 186 | struct ixgbe_hw *hw = &adapter->hw; |
167 | 187 | ||
168 | if (pause->autoneg == AUTONEG_ENABLE) | 188 | if ((pause->autoneg == AUTONEG_ENABLE) || |
169 | return -EINVAL; | 189 | (pause->rx_pause && pause->tx_pause)) |
170 | |||
171 | if (pause->rx_pause && pause->tx_pause) | ||
172 | hw->fc.type = ixgbe_fc_full; | 190 | hw->fc.type = ixgbe_fc_full; |
173 | else if (pause->rx_pause && !pause->tx_pause) | 191 | else if (pause->rx_pause && !pause->tx_pause) |
174 | hw->fc.type = ixgbe_fc_rx_pause; | 192 | hw->fc.type = ixgbe_fc_rx_pause; |
@@ -176,15 +194,15 @@ static int ixgbe_set_pauseparam(struct net_device *netdev, | |||
176 | hw->fc.type = ixgbe_fc_tx_pause; | 194 | hw->fc.type = ixgbe_fc_tx_pause; |
177 | else if (!pause->rx_pause && !pause->tx_pause) | 195 | else if (!pause->rx_pause && !pause->tx_pause) |
178 | hw->fc.type = ixgbe_fc_none; | 196 | hw->fc.type = ixgbe_fc_none; |
197 | else | ||
198 | return -EINVAL; | ||
179 | 199 | ||
180 | hw->fc.original_type = hw->fc.type; | 200 | hw->fc.original_type = hw->fc.type; |
181 | 201 | ||
182 | if (netif_running(adapter->netdev)) { | 202 | if (netif_running(netdev)) |
183 | ixgbe_down(adapter); | 203 | ixgbe_reinit_locked(adapter); |
184 | ixgbe_up(adapter); | 204 | else |
185 | } else { | ||
186 | ixgbe_reset(adapter); | 205 | ixgbe_reset(adapter); |
187 | } | ||
188 | 206 | ||
189 | return 0; | 207 | return 0; |
190 | } | 208 | } |
@@ -203,12 +221,10 @@ static int ixgbe_set_rx_csum(struct net_device *netdev, u32 data) | |||
203 | else | 221 | else |
204 | adapter->flags &= ~IXGBE_FLAG_RX_CSUM_ENABLED; | 222 | adapter->flags &= ~IXGBE_FLAG_RX_CSUM_ENABLED; |
205 | 223 | ||
206 | if (netif_running(netdev)) { | 224 | if (netif_running(netdev)) |
207 | ixgbe_down(adapter); | 225 | ixgbe_reinit_locked(adapter); |
208 | ixgbe_up(adapter); | 226 | else |
209 | } else { | ||
210 | ixgbe_reset(adapter); | 227 | ixgbe_reset(adapter); |
211 | } | ||
212 | 228 | ||
213 | return 0; | 229 | return 0; |
214 | } | 230 | } |
@@ -662,7 +678,10 @@ static int ixgbe_set_ringparam(struct net_device *netdev, | |||
662 | return 0; | 678 | return 0; |
663 | } | 679 | } |
664 | 680 | ||
665 | if (netif_running(adapter->netdev)) | 681 | while (test_and_set_bit(__IXGBE_RESETTING, &adapter->state)) |
682 | msleep(1); | ||
683 | |||
684 | if (netif_running(netdev)) | ||
666 | ixgbe_down(adapter); | 685 | ixgbe_down(adapter); |
667 | 686 | ||
668 | /* | 687 | /* |
@@ -733,6 +752,7 @@ err_setup: | |||
733 | if (netif_running(adapter->netdev)) | 752 | if (netif_running(adapter->netdev)) |
734 | ixgbe_up(adapter); | 753 | ixgbe_up(adapter); |
735 | 754 | ||
755 | clear_bit(__IXGBE_RESETTING, &adapter->state); | ||
736 | return err; | 756 | return err; |
737 | } | 757 | } |
738 | 758 | ||
@@ -820,11 +840,8 @@ static int ixgbe_nway_reset(struct net_device *netdev) | |||
820 | { | 840 | { |
821 | struct ixgbe_adapter *adapter = netdev_priv(netdev); | 841 | struct ixgbe_adapter *adapter = netdev_priv(netdev); |
822 | 842 | ||
823 | if (netif_running(netdev)) { | 843 | if (netif_running(netdev)) |
824 | ixgbe_down(adapter); | 844 | ixgbe_reinit_locked(adapter); |
825 | ixgbe_reset(adapter); | ||
826 | ixgbe_up(adapter); | ||
827 | } | ||
828 | 845 | ||
829 | return 0; | 846 | return 0; |
830 | } | 847 | } |
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 3732dd6c4b2a..ead49e54f31b 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c | |||
@@ -87,6 +87,25 @@ MODULE_VERSION(DRV_VERSION); | |||
87 | 87 | ||
88 | #define DEFAULT_DEBUG_LEVEL_SHIFT 3 | 88 | #define DEFAULT_DEBUG_LEVEL_SHIFT 3 |
89 | 89 | ||
90 | static void ixgbe_release_hw_control(struct ixgbe_adapter *adapter) | ||
91 | { | ||
92 | u32 ctrl_ext; | ||
93 | |||
94 | /* Let firmware take over control of h/w */ | ||
95 | ctrl_ext = IXGBE_READ_REG(&adapter->hw, IXGBE_CTRL_EXT); | ||
96 | IXGBE_WRITE_REG(&adapter->hw, IXGBE_CTRL_EXT, | ||
97 | ctrl_ext & ~IXGBE_CTRL_EXT_DRV_LOAD); | ||
98 | } | ||
99 | |||
100 | static void ixgbe_get_hw_control(struct ixgbe_adapter *adapter) | ||
101 | { | ||
102 | u32 ctrl_ext; | ||
103 | |||
104 | /* Let firmware know the driver has taken over */ | ||
105 | ctrl_ext = IXGBE_READ_REG(&adapter->hw, IXGBE_CTRL_EXT); | ||
106 | IXGBE_WRITE_REG(&adapter->hw, IXGBE_CTRL_EXT, | ||
107 | ctrl_ext | IXGBE_CTRL_EXT_DRV_LOAD); | ||
108 | } | ||
90 | 109 | ||
91 | #ifdef DEBUG | 110 | #ifdef DEBUG |
92 | /** | 111 | /** |
@@ -165,6 +184,15 @@ static inline bool ixgbe_check_tx_hang(struct ixgbe_adapter *adapter, | |||
165 | return false; | 184 | return false; |
166 | } | 185 | } |
167 | 186 | ||
187 | #define IXGBE_MAX_TXD_PWR 14 | ||
188 | #define IXGBE_MAX_DATA_PER_TXD (1 << IXGBE_MAX_TXD_PWR) | ||
189 | |||
190 | /* Tx Descriptors needed, worst case */ | ||
191 | #define TXD_USE_COUNT(S) (((S) >> IXGBE_MAX_TXD_PWR) + \ | ||
192 | (((S) & (IXGBE_MAX_DATA_PER_TXD - 1)) ? 1 : 0)) | ||
193 | #define DESC_NEEDED (TXD_USE_COUNT(IXGBE_MAX_DATA_PER_TXD) /* skb->data */ + \ | ||
194 | MAX_SKB_FRAGS * TXD_USE_COUNT(PAGE_SIZE) + 1) /* for context */ | ||
195 | |||
168 | /** | 196 | /** |
169 | * ixgbe_clean_tx_irq - Reclaim resources after transmit completes | 197 | * ixgbe_clean_tx_irq - Reclaim resources after transmit completes |
170 | * @adapter: board private structure | 198 | * @adapter: board private structure |
@@ -177,18 +205,34 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_adapter *adapter, | |||
177 | struct ixgbe_tx_buffer *tx_buffer_info; | 205 | struct ixgbe_tx_buffer *tx_buffer_info; |
178 | unsigned int i, eop; | 206 | unsigned int i, eop; |
179 | bool cleaned = false; | 207 | bool cleaned = false; |
180 | int count = 0; | 208 | unsigned int total_tx_bytes = 0, total_tx_packets = 0; |
181 | 209 | ||
182 | i = tx_ring->next_to_clean; | 210 | i = tx_ring->next_to_clean; |
183 | eop = tx_ring->tx_buffer_info[i].next_to_watch; | 211 | eop = tx_ring->tx_buffer_info[i].next_to_watch; |
184 | eop_desc = IXGBE_TX_DESC_ADV(*tx_ring, eop); | 212 | eop_desc = IXGBE_TX_DESC_ADV(*tx_ring, eop); |
185 | while (eop_desc->wb.status & cpu_to_le32(IXGBE_TXD_STAT_DD)) { | 213 | while (eop_desc->wb.status & cpu_to_le32(IXGBE_TXD_STAT_DD)) { |
186 | for (cleaned = false; !cleaned;) { | 214 | cleaned = false; |
215 | while (!cleaned) { | ||
187 | tx_desc = IXGBE_TX_DESC_ADV(*tx_ring, i); | 216 | tx_desc = IXGBE_TX_DESC_ADV(*tx_ring, i); |
188 | tx_buffer_info = &tx_ring->tx_buffer_info[i]; | 217 | tx_buffer_info = &tx_ring->tx_buffer_info[i]; |
189 | cleaned = (i == eop); | 218 | cleaned = (i == eop); |
190 | 219 | ||
191 | tx_ring->stats.bytes += tx_buffer_info->length; | 220 | tx_ring->stats.bytes += tx_buffer_info->length; |
221 | if (cleaned) { | ||
222 | struct sk_buff *skb = tx_buffer_info->skb; | ||
223 | #ifdef NETIF_F_TSO | ||
224 | unsigned int segs, bytecount; | ||
225 | segs = skb_shinfo(skb)->gso_segs ?: 1; | ||
226 | /* multiply data chunks by size of headers */ | ||
227 | bytecount = ((segs - 1) * skb_headlen(skb)) + | ||
228 | skb->len; | ||
229 | total_tx_packets += segs; | ||
230 | total_tx_bytes += bytecount; | ||
231 | #else | ||
232 | total_tx_packets++; | ||
233 | total_tx_bytes += skb->len; | ||
234 | #endif | ||
235 | } | ||
192 | ixgbe_unmap_and_free_tx_resource(adapter, | 236 | ixgbe_unmap_and_free_tx_resource(adapter, |
193 | tx_buffer_info); | 237 | tx_buffer_info); |
194 | tx_desc->wb.status = 0; | 238 | tx_desc->wb.status = 0; |
@@ -204,29 +248,36 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_adapter *adapter, | |||
204 | eop_desc = IXGBE_TX_DESC_ADV(*tx_ring, eop); | 248 | eop_desc = IXGBE_TX_DESC_ADV(*tx_ring, eop); |
205 | 249 | ||
206 | /* weight of a sort for tx, avoid endless transmit cleanup */ | 250 | /* weight of a sort for tx, avoid endless transmit cleanup */ |
207 | if (count++ >= tx_ring->work_limit) | 251 | if (total_tx_packets >= tx_ring->work_limit) |
208 | break; | 252 | break; |
209 | } | 253 | } |
210 | 254 | ||
211 | tx_ring->next_to_clean = i; | 255 | tx_ring->next_to_clean = i; |
212 | 256 | ||
213 | #define TX_WAKE_THRESHOLD 32 | 257 | #define TX_WAKE_THRESHOLD (DESC_NEEDED * 2) |
214 | spin_lock(&tx_ring->tx_lock); | 258 | if (total_tx_packets && netif_carrier_ok(netdev) && |
215 | 259 | (IXGBE_DESC_UNUSED(tx_ring) >= TX_WAKE_THRESHOLD)) { | |
216 | if (cleaned && netif_carrier_ok(netdev) && | 260 | /* Make sure that anybody stopping the queue after this |
217 | (IXGBE_DESC_UNUSED(tx_ring) >= TX_WAKE_THRESHOLD) && | 261 | * sees the new next_to_clean. |
218 | !test_bit(__IXGBE_DOWN, &adapter->state)) | 262 | */ |
219 | netif_wake_queue(netdev); | 263 | smp_mb(); |
220 | 264 | if (netif_queue_stopped(netdev) && | |
221 | spin_unlock(&tx_ring->tx_lock); | 265 | !test_bit(__IXGBE_DOWN, &adapter->state)) { |
266 | netif_wake_queue(netdev); | ||
267 | adapter->restart_queue++; | ||
268 | } | ||
269 | } | ||
222 | 270 | ||
223 | if (adapter->detect_tx_hung) | 271 | if (adapter->detect_tx_hung) |
224 | if (ixgbe_check_tx_hang(adapter, tx_ring, eop, eop_desc)) | 272 | if (ixgbe_check_tx_hang(adapter, tx_ring, eop, eop_desc)) |
225 | netif_stop_queue(netdev); | 273 | netif_stop_queue(netdev); |
226 | 274 | ||
227 | if (count >= tx_ring->work_limit) | 275 | if (total_tx_packets >= tx_ring->work_limit) |
228 | IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS, tx_ring->eims_value); | 276 | IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS, tx_ring->eims_value); |
229 | 277 | ||
278 | adapter->net_stats.tx_bytes += total_tx_bytes; | ||
279 | adapter->net_stats.tx_packets += total_tx_packets; | ||
280 | cleaned = total_tx_packets ? true : false; | ||
230 | return cleaned; | 281 | return cleaned; |
231 | } | 282 | } |
232 | 283 | ||
@@ -255,25 +306,40 @@ static void ixgbe_receive_skb(struct ixgbe_adapter *adapter, | |||
255 | } | 306 | } |
256 | } | 307 | } |
257 | 308 | ||
309 | /** | ||
310 | * ixgbe_rx_checksum - indicate in skb if hw indicated a good cksum | ||
311 | * @adapter: address of board private structure | ||
312 | * @status_err: hardware indication of status of receive | ||
313 | * @skb: skb currently being received and modified | ||
314 | **/ | ||
258 | static inline void ixgbe_rx_checksum(struct ixgbe_adapter *adapter, | 315 | static inline void ixgbe_rx_checksum(struct ixgbe_adapter *adapter, |
259 | u32 status_err, | 316 | u32 status_err, |
260 | struct sk_buff *skb) | 317 | struct sk_buff *skb) |
261 | { | 318 | { |
262 | skb->ip_summed = CHECKSUM_NONE; | 319 | skb->ip_summed = CHECKSUM_NONE; |
263 | 320 | ||
264 | /* Ignore Checksum bit is set */ | 321 | /* Ignore Checksum bit is set, or rx csum disabled */ |
265 | if ((status_err & IXGBE_RXD_STAT_IXSM) || | 322 | if ((status_err & IXGBE_RXD_STAT_IXSM) || |
266 | !(adapter->flags & IXGBE_FLAG_RX_CSUM_ENABLED)) | 323 | !(adapter->flags & IXGBE_FLAG_RX_CSUM_ENABLED)) |
267 | return; | 324 | return; |
268 | /* TCP/UDP checksum error bit is set */ | 325 | |
269 | if (status_err & (IXGBE_RXDADV_ERR_TCPE | IXGBE_RXDADV_ERR_IPE)) { | 326 | /* if IP and error */ |
270 | /* let the stack verify checksum errors */ | 327 | if ((status_err & IXGBE_RXD_STAT_IPCS) && |
328 | (status_err & IXGBE_RXDADV_ERR_IPE)) { | ||
271 | adapter->hw_csum_rx_error++; | 329 | adapter->hw_csum_rx_error++; |
272 | return; | 330 | return; |
273 | } | 331 | } |
332 | |||
333 | if (!(status_err & IXGBE_RXD_STAT_L4CS)) | ||
334 | return; | ||
335 | |||
336 | if (status_err & IXGBE_RXDADV_ERR_TCPE) { | ||
337 | adapter->hw_csum_rx_error++; | ||
338 | return; | ||
339 | } | ||
340 | |||
274 | /* It must be a TCP or UDP packet with a valid checksum */ | 341 | /* It must be a TCP or UDP packet with a valid checksum */ |
275 | if (status_err & (IXGBE_RXD_STAT_L4CS | IXGBE_RXD_STAT_UDPCS)) | 342 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
276 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
277 | adapter->hw_csum_rx_good++; | 343 | adapter->hw_csum_rx_good++; |
278 | } | 344 | } |
279 | 345 | ||
@@ -379,6 +445,7 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_adapter *adapter, | |||
379 | u16 hdr_info, vlan_tag; | 445 | u16 hdr_info, vlan_tag; |
380 | bool is_vlan, cleaned = false; | 446 | bool is_vlan, cleaned = false; |
381 | int cleaned_count = 0; | 447 | int cleaned_count = 0; |
448 | unsigned int total_rx_bytes = 0, total_rx_packets = 0; | ||
382 | 449 | ||
383 | i = rx_ring->next_to_clean; | 450 | i = rx_ring->next_to_clean; |
384 | upper_len = 0; | 451 | upper_len = 0; |
@@ -458,6 +525,11 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_adapter *adapter, | |||
458 | } | 525 | } |
459 | 526 | ||
460 | ixgbe_rx_checksum(adapter, staterr, skb); | 527 | ixgbe_rx_checksum(adapter, staterr, skb); |
528 | |||
529 | /* probably a little skewed due to removing CRC */ | ||
530 | total_rx_bytes += skb->len; | ||
531 | total_rx_packets++; | ||
532 | |||
461 | skb->protocol = eth_type_trans(skb, netdev); | 533 | skb->protocol = eth_type_trans(skb, netdev); |
462 | ixgbe_receive_skb(adapter, skb, is_vlan, vlan_tag); | 534 | ixgbe_receive_skb(adapter, skb, is_vlan, vlan_tag); |
463 | netdev->last_rx = jiffies; | 535 | netdev->last_rx = jiffies; |
@@ -486,6 +558,9 @@ next_desc: | |||
486 | if (cleaned_count) | 558 | if (cleaned_count) |
487 | ixgbe_alloc_rx_buffers(adapter, rx_ring, cleaned_count); | 559 | ixgbe_alloc_rx_buffers(adapter, rx_ring, cleaned_count); |
488 | 560 | ||
561 | adapter->net_stats.rx_bytes += total_rx_bytes; | ||
562 | adapter->net_stats.rx_packets += total_rx_packets; | ||
563 | |||
489 | return cleaned; | 564 | return cleaned; |
490 | } | 565 | } |
491 | 566 | ||
@@ -535,7 +610,9 @@ static irqreturn_t ixgbe_msix_lsc(int irq, void *data) | |||
535 | if (!test_bit(__IXGBE_DOWN, &adapter->state)) | 610 | if (!test_bit(__IXGBE_DOWN, &adapter->state)) |
536 | mod_timer(&adapter->watchdog_timer, jiffies); | 611 | mod_timer(&adapter->watchdog_timer, jiffies); |
537 | } | 612 | } |
538 | IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, IXGBE_EIMS_OTHER); | 613 | |
614 | if (!test_bit(__IXGBE_DOWN, &adapter->state)) | ||
615 | IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EIMS_OTHER); | ||
539 | 616 | ||
540 | return IRQ_HANDLED; | 617 | return IRQ_HANDLED; |
541 | } | 618 | } |
@@ -713,7 +790,6 @@ static irqreturn_t ixgbe_intr(int irq, void *data) | |||
713 | if (netif_rx_schedule_prep(netdev, &adapter->napi)) { | 790 | if (netif_rx_schedule_prep(netdev, &adapter->napi)) { |
714 | /* Disable interrupts and register for poll. The flush of the | 791 | /* Disable interrupts and register for poll. The flush of the |
715 | * posted write is intentionally left out. */ | 792 | * posted write is intentionally left out. */ |
716 | atomic_inc(&adapter->irq_sem); | ||
717 | IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, ~0); | 793 | IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, ~0); |
718 | __netif_rx_schedule(netdev, &adapter->napi); | 794 | __netif_rx_schedule(netdev, &adapter->napi); |
719 | } | 795 | } |
@@ -801,7 +877,6 @@ static void ixgbe_free_irq(struct ixgbe_adapter *adapter) | |||
801 | **/ | 877 | **/ |
802 | static inline void ixgbe_irq_disable(struct ixgbe_adapter *adapter) | 878 | static inline void ixgbe_irq_disable(struct ixgbe_adapter *adapter) |
803 | { | 879 | { |
804 | atomic_inc(&adapter->irq_sem); | ||
805 | IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, ~0); | 880 | IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, ~0); |
806 | IXGBE_WRITE_FLUSH(&adapter->hw); | 881 | IXGBE_WRITE_FLUSH(&adapter->hw); |
807 | synchronize_irq(adapter->pdev->irq); | 882 | synchronize_irq(adapter->pdev->irq); |
@@ -813,15 +888,13 @@ static inline void ixgbe_irq_disable(struct ixgbe_adapter *adapter) | |||
813 | **/ | 888 | **/ |
814 | static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter) | 889 | static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter) |
815 | { | 890 | { |
816 | if (atomic_dec_and_test(&adapter->irq_sem)) { | 891 | if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) |
817 | if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) | 892 | IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIAC, |
818 | IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIAC, | 893 | (IXGBE_EIMS_ENABLE_MASK & |
819 | (IXGBE_EIMS_ENABLE_MASK & | 894 | ~(IXGBE_EIMS_OTHER | IXGBE_EIMS_LSC))); |
820 | ~(IXGBE_EIMS_OTHER | IXGBE_EIMS_LSC))); | 895 | IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, |
821 | IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, | 896 | IXGBE_EIMS_ENABLE_MASK); |
822 | IXGBE_EIMS_ENABLE_MASK); | 897 | IXGBE_WRITE_FLUSH(&adapter->hw); |
823 | IXGBE_WRITE_FLUSH(&adapter->hw); | ||
824 | } | ||
825 | } | 898 | } |
826 | 899 | ||
827 | /** | 900 | /** |
@@ -1040,7 +1113,8 @@ static void ixgbe_vlan_rx_register(struct net_device *netdev, | |||
1040 | struct ixgbe_adapter *adapter = netdev_priv(netdev); | 1113 | struct ixgbe_adapter *adapter = netdev_priv(netdev); |
1041 | u32 ctrl; | 1114 | u32 ctrl; |
1042 | 1115 | ||
1043 | ixgbe_irq_disable(adapter); | 1116 | if (!test_bit(__IXGBE_DOWN, &adapter->state)) |
1117 | ixgbe_irq_disable(adapter); | ||
1044 | adapter->vlgrp = grp; | 1118 | adapter->vlgrp = grp; |
1045 | 1119 | ||
1046 | if (grp) { | 1120 | if (grp) { |
@@ -1051,7 +1125,8 @@ static void ixgbe_vlan_rx_register(struct net_device *netdev, | |||
1051 | IXGBE_WRITE_REG(&adapter->hw, IXGBE_VLNCTRL, ctrl); | 1125 | IXGBE_WRITE_REG(&adapter->hw, IXGBE_VLNCTRL, ctrl); |
1052 | } | 1126 | } |
1053 | 1127 | ||
1054 | ixgbe_irq_enable(adapter); | 1128 | if (!test_bit(__IXGBE_DOWN, &adapter->state)) |
1129 | ixgbe_irq_enable(adapter); | ||
1055 | } | 1130 | } |
1056 | 1131 | ||
1057 | static void ixgbe_vlan_rx_add_vid(struct net_device *netdev, u16 vid) | 1132 | static void ixgbe_vlan_rx_add_vid(struct net_device *netdev, u16 vid) |
@@ -1066,9 +1141,13 @@ static void ixgbe_vlan_rx_kill_vid(struct net_device *netdev, u16 vid) | |||
1066 | { | 1141 | { |
1067 | struct ixgbe_adapter *adapter = netdev_priv(netdev); | 1142 | struct ixgbe_adapter *adapter = netdev_priv(netdev); |
1068 | 1143 | ||
1069 | ixgbe_irq_disable(adapter); | 1144 | if (!test_bit(__IXGBE_DOWN, &adapter->state)) |
1145 | ixgbe_irq_disable(adapter); | ||
1146 | |||
1070 | vlan_group_set_device(adapter->vlgrp, vid, NULL); | 1147 | vlan_group_set_device(adapter->vlgrp, vid, NULL); |
1071 | ixgbe_irq_enable(adapter); | 1148 | |
1149 | if (!test_bit(__IXGBE_DOWN, &adapter->state)) | ||
1150 | ixgbe_irq_enable(adapter); | ||
1072 | 1151 | ||
1073 | /* remove VID from filter table */ | 1152 | /* remove VID from filter table */ |
1074 | ixgbe_set_vfta(&adapter->hw, vid, 0, false); | 1153 | ixgbe_set_vfta(&adapter->hw, vid, 0, false); |
@@ -1170,6 +1249,8 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter) | |||
1170 | u32 txdctl, rxdctl, mhadd; | 1249 | u32 txdctl, rxdctl, mhadd; |
1171 | int max_frame = netdev->mtu + ETH_HLEN + ETH_FCS_LEN; | 1250 | int max_frame = netdev->mtu + ETH_HLEN + ETH_FCS_LEN; |
1172 | 1251 | ||
1252 | ixgbe_get_hw_control(adapter); | ||
1253 | |||
1173 | if (adapter->flags & (IXGBE_FLAG_MSIX_ENABLED | | 1254 | if (adapter->flags & (IXGBE_FLAG_MSIX_ENABLED | |
1174 | IXGBE_FLAG_MSI_ENABLED)) { | 1255 | IXGBE_FLAG_MSI_ENABLED)) { |
1175 | if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) { | 1256 | if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) { |
@@ -1224,6 +1305,16 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter) | |||
1224 | return 0; | 1305 | return 0; |
1225 | } | 1306 | } |
1226 | 1307 | ||
1308 | void ixgbe_reinit_locked(struct ixgbe_adapter *adapter) | ||
1309 | { | ||
1310 | WARN_ON(in_interrupt()); | ||
1311 | while (test_and_set_bit(__IXGBE_RESETTING, &adapter->state)) | ||
1312 | msleep(1); | ||
1313 | ixgbe_down(adapter); | ||
1314 | ixgbe_up(adapter); | ||
1315 | clear_bit(__IXGBE_RESETTING, &adapter->state); | ||
1316 | } | ||
1317 | |||
1227 | int ixgbe_up(struct ixgbe_adapter *adapter) | 1318 | int ixgbe_up(struct ixgbe_adapter *adapter) |
1228 | { | 1319 | { |
1229 | /* hardware has been reset, we need to reload some things */ | 1320 | /* hardware has been reset, we need to reload some things */ |
@@ -1408,7 +1499,6 @@ void ixgbe_down(struct ixgbe_adapter *adapter) | |||
1408 | msleep(10); | 1499 | msleep(10); |
1409 | 1500 | ||
1410 | napi_disable(&adapter->napi); | 1501 | napi_disable(&adapter->napi); |
1411 | atomic_set(&adapter->irq_sem, 0); | ||
1412 | 1502 | ||
1413 | ixgbe_irq_disable(adapter); | 1503 | ixgbe_irq_disable(adapter); |
1414 | 1504 | ||
@@ -1447,6 +1537,8 @@ static int ixgbe_suspend(struct pci_dev *pdev, pm_message_t state) | |||
1447 | pci_enable_wake(pdev, PCI_D3hot, 0); | 1537 | pci_enable_wake(pdev, PCI_D3hot, 0); |
1448 | pci_enable_wake(pdev, PCI_D3cold, 0); | 1538 | pci_enable_wake(pdev, PCI_D3cold, 0); |
1449 | 1539 | ||
1540 | ixgbe_release_hw_control(adapter); | ||
1541 | |||
1450 | pci_disable_device(pdev); | 1542 | pci_disable_device(pdev); |
1451 | 1543 | ||
1452 | pci_set_power_state(pdev, pci_choose_state(pdev, state)); | 1544 | pci_set_power_state(pdev, pci_choose_state(pdev, state)); |
@@ -1481,7 +1573,8 @@ static int ixgbe_clean(struct napi_struct *napi, int budget) | |||
1481 | /* If budget not fully consumed, exit the polling mode */ | 1573 | /* If budget not fully consumed, exit the polling mode */ |
1482 | if (work_done < budget) { | 1574 | if (work_done < budget) { |
1483 | netif_rx_complete(netdev, napi); | 1575 | netif_rx_complete(netdev, napi); |
1484 | ixgbe_irq_enable(adapter); | 1576 | if (!test_bit(__IXGBE_DOWN, &adapter->state)) |
1577 | ixgbe_irq_enable(adapter); | ||
1485 | } | 1578 | } |
1486 | 1579 | ||
1487 | return work_done; | 1580 | return work_done; |
@@ -1506,8 +1599,7 @@ static void ixgbe_reset_task(struct work_struct *work) | |||
1506 | 1599 | ||
1507 | adapter->tx_timeout_count++; | 1600 | adapter->tx_timeout_count++; |
1508 | 1601 | ||
1509 | ixgbe_down(adapter); | 1602 | ixgbe_reinit_locked(adapter); |
1510 | ixgbe_up(adapter); | ||
1511 | } | 1603 | } |
1512 | 1604 | ||
1513 | /** | 1605 | /** |
@@ -1590,7 +1682,6 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter) | |||
1590 | return -ENOMEM; | 1682 | return -ENOMEM; |
1591 | } | 1683 | } |
1592 | 1684 | ||
1593 | atomic_set(&adapter->irq_sem, 1); | ||
1594 | set_bit(__IXGBE_DOWN, &adapter->state); | 1685 | set_bit(__IXGBE_DOWN, &adapter->state); |
1595 | 1686 | ||
1596 | return 0; | 1687 | return 0; |
@@ -1634,7 +1725,6 @@ int ixgbe_setup_tx_resources(struct ixgbe_adapter *adapter, | |||
1634 | txdr->next_to_use = 0; | 1725 | txdr->next_to_use = 0; |
1635 | txdr->next_to_clean = 0; | 1726 | txdr->next_to_clean = 0; |
1636 | txdr->work_limit = txdr->count; | 1727 | txdr->work_limit = txdr->count; |
1637 | spin_lock_init(&txdr->tx_lock); | ||
1638 | 1728 | ||
1639 | return 0; | 1729 | return 0; |
1640 | } | 1730 | } |
@@ -1828,10 +1918,8 @@ static int ixgbe_change_mtu(struct net_device *netdev, int new_mtu) | |||
1828 | 1918 | ||
1829 | netdev->mtu = new_mtu; | 1919 | netdev->mtu = new_mtu; |
1830 | 1920 | ||
1831 | if (netif_running(netdev)) { | 1921 | if (netif_running(netdev)) |
1832 | ixgbe_down(adapter); | 1922 | ixgbe_reinit_locked(adapter); |
1833 | ixgbe_up(adapter); | ||
1834 | } | ||
1835 | 1923 | ||
1836 | return 0; | 1924 | return 0; |
1837 | } | 1925 | } |
@@ -1852,14 +1940,8 @@ static int ixgbe_open(struct net_device *netdev) | |||
1852 | { | 1940 | { |
1853 | struct ixgbe_adapter *adapter = netdev_priv(netdev); | 1941 | struct ixgbe_adapter *adapter = netdev_priv(netdev); |
1854 | int err; | 1942 | int err; |
1855 | u32 ctrl_ext; | ||
1856 | u32 num_rx_queues = adapter->num_rx_queues; | 1943 | u32 num_rx_queues = adapter->num_rx_queues; |
1857 | 1944 | ||
1858 | /* Let firmware know the driver has taken over */ | ||
1859 | ctrl_ext = IXGBE_READ_REG(&adapter->hw, IXGBE_CTRL_EXT); | ||
1860 | IXGBE_WRITE_REG(&adapter->hw, IXGBE_CTRL_EXT, | ||
1861 | ctrl_ext | IXGBE_CTRL_EXT_DRV_LOAD); | ||
1862 | |||
1863 | try_intr_reinit: | 1945 | try_intr_reinit: |
1864 | /* allocate transmit descriptors */ | 1946 | /* allocate transmit descriptors */ |
1865 | err = ixgbe_setup_all_tx_resources(adapter); | 1947 | err = ixgbe_setup_all_tx_resources(adapter); |
@@ -1910,6 +1992,7 @@ try_intr_reinit: | |||
1910 | return 0; | 1992 | return 0; |
1911 | 1993 | ||
1912 | err_up: | 1994 | err_up: |
1995 | ixgbe_release_hw_control(adapter); | ||
1913 | ixgbe_free_irq(adapter); | 1996 | ixgbe_free_irq(adapter); |
1914 | err_req_irq: | 1997 | err_req_irq: |
1915 | ixgbe_free_all_rx_resources(adapter); | 1998 | ixgbe_free_all_rx_resources(adapter); |
@@ -1935,7 +2018,6 @@ err_setup_tx: | |||
1935 | static int ixgbe_close(struct net_device *netdev) | 2018 | static int ixgbe_close(struct net_device *netdev) |
1936 | { | 2019 | { |
1937 | struct ixgbe_adapter *adapter = netdev_priv(netdev); | 2020 | struct ixgbe_adapter *adapter = netdev_priv(netdev); |
1938 | u32 ctrl_ext; | ||
1939 | 2021 | ||
1940 | ixgbe_down(adapter); | 2022 | ixgbe_down(adapter); |
1941 | ixgbe_free_irq(adapter); | 2023 | ixgbe_free_irq(adapter); |
@@ -1943,9 +2025,7 @@ static int ixgbe_close(struct net_device *netdev) | |||
1943 | ixgbe_free_all_tx_resources(adapter); | 2025 | ixgbe_free_all_tx_resources(adapter); |
1944 | ixgbe_free_all_rx_resources(adapter); | 2026 | ixgbe_free_all_rx_resources(adapter); |
1945 | 2027 | ||
1946 | ctrl_ext = IXGBE_READ_REG(&adapter->hw, IXGBE_CTRL_EXT); | 2028 | ixgbe_release_hw_control(adapter); |
1947 | IXGBE_WRITE_REG(&adapter->hw, IXGBE_CTRL_EXT, | ||
1948 | ctrl_ext & ~IXGBE_CTRL_EXT_DRV_LOAD); | ||
1949 | 2029 | ||
1950 | return 0; | 2030 | return 0; |
1951 | } | 2031 | } |
@@ -1957,22 +2037,26 @@ static int ixgbe_close(struct net_device *netdev) | |||
1957 | void ixgbe_update_stats(struct ixgbe_adapter *adapter) | 2037 | void ixgbe_update_stats(struct ixgbe_adapter *adapter) |
1958 | { | 2038 | { |
1959 | struct ixgbe_hw *hw = &adapter->hw; | 2039 | struct ixgbe_hw *hw = &adapter->hw; |
1960 | u64 good_rx, missed_rx, bprc; | 2040 | u64 total_mpc = 0; |
2041 | u32 i, missed_rx = 0, mpc, bprc, lxon, lxoff, xon_off_tot; | ||
1961 | 2042 | ||
1962 | adapter->stats.crcerrs += IXGBE_READ_REG(hw, IXGBE_CRCERRS); | 2043 | adapter->stats.crcerrs += IXGBE_READ_REG(hw, IXGBE_CRCERRS); |
1963 | good_rx = IXGBE_READ_REG(hw, IXGBE_GPRC); | 2044 | for (i = 0; i < 8; i++) { |
1964 | missed_rx = IXGBE_READ_REG(hw, IXGBE_MPC(0)); | 2045 | /* for packet buffers not used, the register should read 0 */ |
1965 | missed_rx += IXGBE_READ_REG(hw, IXGBE_MPC(1)); | 2046 | mpc = IXGBE_READ_REG(hw, IXGBE_MPC(i)); |
1966 | missed_rx += IXGBE_READ_REG(hw, IXGBE_MPC(2)); | 2047 | missed_rx += mpc; |
1967 | missed_rx += IXGBE_READ_REG(hw, IXGBE_MPC(3)); | 2048 | adapter->stats.mpc[i] += mpc; |
1968 | missed_rx += IXGBE_READ_REG(hw, IXGBE_MPC(4)); | 2049 | total_mpc += adapter->stats.mpc[i]; |
1969 | missed_rx += IXGBE_READ_REG(hw, IXGBE_MPC(5)); | 2050 | adapter->stats.rnbc[i] += IXGBE_READ_REG(hw, IXGBE_RNBC(i)); |
1970 | missed_rx += IXGBE_READ_REG(hw, IXGBE_MPC(6)); | 2051 | } |
1971 | missed_rx += IXGBE_READ_REG(hw, IXGBE_MPC(7)); | 2052 | adapter->stats.gprc += IXGBE_READ_REG(hw, IXGBE_GPRC); |
1972 | adapter->stats.gprc += (good_rx - missed_rx); | 2053 | /* work around hardware counting issue */ |
1973 | 2054 | adapter->stats.gprc -= missed_rx; | |
1974 | adapter->stats.mpc[0] += missed_rx; | 2055 | |
2056 | /* 82598 hardware only has a 32 bit counter in the high register */ | ||
1975 | adapter->stats.gorc += IXGBE_READ_REG(hw, IXGBE_GORCH); | 2057 | adapter->stats.gorc += IXGBE_READ_REG(hw, IXGBE_GORCH); |
2058 | adapter->stats.gotc += IXGBE_READ_REG(hw, IXGBE_GOTCH); | ||
2059 | adapter->stats.tor += IXGBE_READ_REG(hw, IXGBE_TORH); | ||
1976 | bprc = IXGBE_READ_REG(hw, IXGBE_BPRC); | 2060 | bprc = IXGBE_READ_REG(hw, IXGBE_BPRC); |
1977 | adapter->stats.bprc += bprc; | 2061 | adapter->stats.bprc += bprc; |
1978 | adapter->stats.mprc += IXGBE_READ_REG(hw, IXGBE_MPRC); | 2062 | adapter->stats.mprc += IXGBE_READ_REG(hw, IXGBE_MPRC); |
@@ -1984,35 +2068,37 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter) | |||
1984 | adapter->stats.prc511 += IXGBE_READ_REG(hw, IXGBE_PRC511); | 2068 | adapter->stats.prc511 += IXGBE_READ_REG(hw, IXGBE_PRC511); |
1985 | adapter->stats.prc1023 += IXGBE_READ_REG(hw, IXGBE_PRC1023); | 2069 | adapter->stats.prc1023 += IXGBE_READ_REG(hw, IXGBE_PRC1023); |
1986 | adapter->stats.prc1522 += IXGBE_READ_REG(hw, IXGBE_PRC1522); | 2070 | adapter->stats.prc1522 += IXGBE_READ_REG(hw, IXGBE_PRC1522); |
1987 | |||
1988 | adapter->stats.rlec += IXGBE_READ_REG(hw, IXGBE_RLEC); | 2071 | adapter->stats.rlec += IXGBE_READ_REG(hw, IXGBE_RLEC); |
1989 | adapter->stats.lxonrxc += IXGBE_READ_REG(hw, IXGBE_LXONRXC); | 2072 | adapter->stats.lxonrxc += IXGBE_READ_REG(hw, IXGBE_LXONRXC); |
1990 | adapter->stats.lxontxc += IXGBE_READ_REG(hw, IXGBE_LXONTXC); | ||
1991 | adapter->stats.lxoffrxc += IXGBE_READ_REG(hw, IXGBE_LXOFFRXC); | 2073 | adapter->stats.lxoffrxc += IXGBE_READ_REG(hw, IXGBE_LXOFFRXC); |
1992 | adapter->stats.lxofftxc += IXGBE_READ_REG(hw, IXGBE_LXOFFTXC); | 2074 | lxon = IXGBE_READ_REG(hw, IXGBE_LXONTXC); |
2075 | adapter->stats.lxontxc += lxon; | ||
2076 | lxoff = IXGBE_READ_REG(hw, IXGBE_LXOFFTXC); | ||
2077 | adapter->stats.lxofftxc += lxoff; | ||
1993 | adapter->stats.ruc += IXGBE_READ_REG(hw, IXGBE_RUC); | 2078 | adapter->stats.ruc += IXGBE_READ_REG(hw, IXGBE_RUC); |
1994 | adapter->stats.gptc += IXGBE_READ_REG(hw, IXGBE_GPTC); | 2079 | adapter->stats.gptc += IXGBE_READ_REG(hw, IXGBE_GPTC); |
1995 | adapter->stats.gotc += IXGBE_READ_REG(hw, IXGBE_GOTCH); | 2080 | adapter->stats.mptc += IXGBE_READ_REG(hw, IXGBE_MPTC); |
1996 | adapter->stats.rnbc[0] += IXGBE_READ_REG(hw, IXGBE_RNBC(0)); | 2081 | /* |
2082 | * 82598 errata - tx of flow control packets is included in tx counters | ||
2083 | */ | ||
2084 | xon_off_tot = lxon + lxoff; | ||
2085 | adapter->stats.gptc -= xon_off_tot; | ||
2086 | adapter->stats.mptc -= xon_off_tot; | ||
2087 | adapter->stats.gotc -= (xon_off_tot * (ETH_ZLEN + ETH_FCS_LEN)); | ||
1997 | adapter->stats.ruc += IXGBE_READ_REG(hw, IXGBE_RUC); | 2088 | adapter->stats.ruc += IXGBE_READ_REG(hw, IXGBE_RUC); |
1998 | adapter->stats.rfc += IXGBE_READ_REG(hw, IXGBE_RFC); | 2089 | adapter->stats.rfc += IXGBE_READ_REG(hw, IXGBE_RFC); |
1999 | adapter->stats.rjc += IXGBE_READ_REG(hw, IXGBE_RJC); | 2090 | adapter->stats.rjc += IXGBE_READ_REG(hw, IXGBE_RJC); |
2000 | adapter->stats.tor += IXGBE_READ_REG(hw, IXGBE_TORH); | ||
2001 | adapter->stats.tpr += IXGBE_READ_REG(hw, IXGBE_TPR); | 2091 | adapter->stats.tpr += IXGBE_READ_REG(hw, IXGBE_TPR); |
2002 | adapter->stats.ptc64 += IXGBE_READ_REG(hw, IXGBE_PTC64); | 2092 | adapter->stats.ptc64 += IXGBE_READ_REG(hw, IXGBE_PTC64); |
2093 | adapter->stats.ptc64 -= xon_off_tot; | ||
2003 | adapter->stats.ptc127 += IXGBE_READ_REG(hw, IXGBE_PTC127); | 2094 | adapter->stats.ptc127 += IXGBE_READ_REG(hw, IXGBE_PTC127); |
2004 | adapter->stats.ptc255 += IXGBE_READ_REG(hw, IXGBE_PTC255); | 2095 | adapter->stats.ptc255 += IXGBE_READ_REG(hw, IXGBE_PTC255); |
2005 | adapter->stats.ptc511 += IXGBE_READ_REG(hw, IXGBE_PTC511); | 2096 | adapter->stats.ptc511 += IXGBE_READ_REG(hw, IXGBE_PTC511); |
2006 | adapter->stats.ptc1023 += IXGBE_READ_REG(hw, IXGBE_PTC1023); | 2097 | adapter->stats.ptc1023 += IXGBE_READ_REG(hw, IXGBE_PTC1023); |
2007 | adapter->stats.ptc1522 += IXGBE_READ_REG(hw, IXGBE_PTC1522); | 2098 | adapter->stats.ptc1522 += IXGBE_READ_REG(hw, IXGBE_PTC1522); |
2008 | adapter->stats.mptc += IXGBE_READ_REG(hw, IXGBE_MPTC); | ||
2009 | adapter->stats.bptc += IXGBE_READ_REG(hw, IXGBE_BPTC); | 2099 | adapter->stats.bptc += IXGBE_READ_REG(hw, IXGBE_BPTC); |
2010 | 2100 | ||
2011 | /* Fill out the OS statistics structure */ | 2101 | /* Fill out the OS statistics structure */ |
2012 | adapter->net_stats.rx_packets = adapter->stats.gprc; | ||
2013 | adapter->net_stats.tx_packets = adapter->stats.gptc; | ||
2014 | adapter->net_stats.rx_bytes = adapter->stats.gorc; | ||
2015 | adapter->net_stats.tx_bytes = adapter->stats.gotc; | ||
2016 | adapter->net_stats.multicast = adapter->stats.mprc; | 2102 | adapter->net_stats.multicast = adapter->stats.mprc; |
2017 | 2103 | ||
2018 | /* Rx Errors */ | 2104 | /* Rx Errors */ |
@@ -2021,8 +2107,7 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter) | |||
2021 | adapter->net_stats.rx_dropped = 0; | 2107 | adapter->net_stats.rx_dropped = 0; |
2022 | adapter->net_stats.rx_length_errors = adapter->stats.rlec; | 2108 | adapter->net_stats.rx_length_errors = adapter->stats.rlec; |
2023 | adapter->net_stats.rx_crc_errors = adapter->stats.crcerrs; | 2109 | adapter->net_stats.rx_crc_errors = adapter->stats.crcerrs; |
2024 | adapter->net_stats.rx_missed_errors = adapter->stats.mpc[0]; | 2110 | adapter->net_stats.rx_missed_errors = total_mpc; |
2025 | |||
2026 | } | 2111 | } |
2027 | 2112 | ||
2028 | /** | 2113 | /** |
@@ -2076,15 +2161,6 @@ static void ixgbe_watchdog(unsigned long data) | |||
2076 | round_jiffies(jiffies + 2 * HZ)); | 2161 | round_jiffies(jiffies + 2 * HZ)); |
2077 | } | 2162 | } |
2078 | 2163 | ||
2079 | #define IXGBE_MAX_TXD_PWR 14 | ||
2080 | #define IXGBE_MAX_DATA_PER_TXD (1 << IXGBE_MAX_TXD_PWR) | ||
2081 | |||
2082 | /* Tx Descriptors needed, worst case */ | ||
2083 | #define TXD_USE_COUNT(S) (((S) >> IXGBE_MAX_TXD_PWR) + \ | ||
2084 | (((S) & (IXGBE_MAX_DATA_PER_TXD - 1)) ? 1 : 0)) | ||
2085 | #define DESC_NEEDED (TXD_USE_COUNT(IXGBE_MAX_DATA_PER_TXD) /* skb->data */ + \ | ||
2086 | MAX_SKB_FRAGS * TXD_USE_COUNT(PAGE_SIZE) + 1) /* for context */ | ||
2087 | |||
2088 | static int ixgbe_tso(struct ixgbe_adapter *adapter, | 2164 | static int ixgbe_tso(struct ixgbe_adapter *adapter, |
2089 | struct ixgbe_ring *tx_ring, struct sk_buff *skb, | 2165 | struct ixgbe_ring *tx_ring, struct sk_buff *skb, |
2090 | u32 tx_flags, u8 *hdr_len) | 2166 | u32 tx_flags, u8 *hdr_len) |
@@ -2356,6 +2432,37 @@ static void ixgbe_tx_queue(struct ixgbe_adapter *adapter, | |||
2356 | writel(i, adapter->hw.hw_addr + tx_ring->tail); | 2432 | writel(i, adapter->hw.hw_addr + tx_ring->tail); |
2357 | } | 2433 | } |
2358 | 2434 | ||
2435 | static int __ixgbe_maybe_stop_tx(struct net_device *netdev, | ||
2436 | struct ixgbe_ring *tx_ring, int size) | ||
2437 | { | ||
2438 | struct ixgbe_adapter *adapter = netdev_priv(netdev); | ||
2439 | |||
2440 | netif_stop_queue(netdev); | ||
2441 | /* Herbert's original patch had: | ||
2442 | * smp_mb__after_netif_stop_queue(); | ||
2443 | * but since that doesn't exist yet, just open code it. */ | ||
2444 | smp_mb(); | ||
2445 | |||
2446 | /* We need to check again in a case another CPU has just | ||
2447 | * made room available. */ | ||
2448 | if (likely(IXGBE_DESC_UNUSED(tx_ring) < size)) | ||
2449 | return -EBUSY; | ||
2450 | |||
2451 | /* A reprieve! - use start_queue because it doesn't call schedule */ | ||
2452 | netif_wake_queue(netdev); | ||
2453 | ++adapter->restart_queue; | ||
2454 | return 0; | ||
2455 | } | ||
2456 | |||
2457 | static int ixgbe_maybe_stop_tx(struct net_device *netdev, | ||
2458 | struct ixgbe_ring *tx_ring, int size) | ||
2459 | { | ||
2460 | if (likely(IXGBE_DESC_UNUSED(tx_ring) >= size)) | ||
2461 | return 0; | ||
2462 | return __ixgbe_maybe_stop_tx(netdev, tx_ring, size); | ||
2463 | } | ||
2464 | |||
2465 | |||
2359 | static int ixgbe_xmit_frame(struct sk_buff *skb, struct net_device *netdev) | 2466 | static int ixgbe_xmit_frame(struct sk_buff *skb, struct net_device *netdev) |
2360 | { | 2467 | { |
2361 | struct ixgbe_adapter *adapter = netdev_priv(netdev); | 2468 | struct ixgbe_adapter *adapter = netdev_priv(netdev); |
@@ -2363,7 +2470,6 @@ static int ixgbe_xmit_frame(struct sk_buff *skb, struct net_device *netdev) | |||
2363 | unsigned int len = skb->len; | 2470 | unsigned int len = skb->len; |
2364 | unsigned int first; | 2471 | unsigned int first; |
2365 | unsigned int tx_flags = 0; | 2472 | unsigned int tx_flags = 0; |
2366 | unsigned long flags = 0; | ||
2367 | u8 hdr_len; | 2473 | u8 hdr_len; |
2368 | int tso; | 2474 | int tso; |
2369 | unsigned int mss = 0; | 2475 | unsigned int mss = 0; |
@@ -2389,14 +2495,10 @@ static int ixgbe_xmit_frame(struct sk_buff *skb, struct net_device *netdev) | |||
2389 | for (f = 0; f < nr_frags; f++) | 2495 | for (f = 0; f < nr_frags; f++) |
2390 | count += TXD_USE_COUNT(skb_shinfo(skb)->frags[f].size); | 2496 | count += TXD_USE_COUNT(skb_shinfo(skb)->frags[f].size); |
2391 | 2497 | ||
2392 | spin_lock_irqsave(&tx_ring->tx_lock, flags); | 2498 | if (ixgbe_maybe_stop_tx(netdev, tx_ring, count)) { |
2393 | if (IXGBE_DESC_UNUSED(tx_ring) < (count + 2)) { | ||
2394 | adapter->tx_busy++; | 2499 | adapter->tx_busy++; |
2395 | netif_stop_queue(netdev); | ||
2396 | spin_unlock_irqrestore(&tx_ring->tx_lock, flags); | ||
2397 | return NETDEV_TX_BUSY; | 2500 | return NETDEV_TX_BUSY; |
2398 | } | 2501 | } |
2399 | spin_unlock_irqrestore(&tx_ring->tx_lock, flags); | ||
2400 | if (adapter->vlgrp && vlan_tx_tag_present(skb)) { | 2502 | if (adapter->vlgrp && vlan_tx_tag_present(skb)) { |
2401 | tx_flags |= IXGBE_TX_FLAGS_VLAN; | 2503 | tx_flags |= IXGBE_TX_FLAGS_VLAN; |
2402 | tx_flags |= (vlan_tx_tag_get(skb) << IXGBE_TX_FLAGS_VLAN_SHIFT); | 2504 | tx_flags |= (vlan_tx_tag_get(skb) << IXGBE_TX_FLAGS_VLAN_SHIFT); |
@@ -2423,11 +2525,7 @@ static int ixgbe_xmit_frame(struct sk_buff *skb, struct net_device *netdev) | |||
2423 | 2525 | ||
2424 | netdev->trans_start = jiffies; | 2526 | netdev->trans_start = jiffies; |
2425 | 2527 | ||
2426 | spin_lock_irqsave(&tx_ring->tx_lock, flags); | 2528 | ixgbe_maybe_stop_tx(netdev, tx_ring, DESC_NEEDED); |
2427 | /* Make sure there is space in the ring for the next send. */ | ||
2428 | if (IXGBE_DESC_UNUSED(tx_ring) < DESC_NEEDED) | ||
2429 | netif_stop_queue(netdev); | ||
2430 | spin_unlock_irqrestore(&tx_ring->tx_lock, flags); | ||
2431 | 2529 | ||
2432 | return NETDEV_TX_OK; | 2530 | return NETDEV_TX_OK; |
2433 | } | 2531 | } |
@@ -2697,6 +2795,7 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, | |||
2697 | return 0; | 2795 | return 0; |
2698 | 2796 | ||
2699 | err_register: | 2797 | err_register: |
2798 | ixgbe_release_hw_control(adapter); | ||
2700 | err_hw_init: | 2799 | err_hw_init: |
2701 | err_sw_init: | 2800 | err_sw_init: |
2702 | err_eeprom: | 2801 | err_eeprom: |
@@ -2732,6 +2831,8 @@ static void __devexit ixgbe_remove(struct pci_dev *pdev) | |||
2732 | 2831 | ||
2733 | unregister_netdev(netdev); | 2832 | unregister_netdev(netdev); |
2734 | 2833 | ||
2834 | ixgbe_release_hw_control(adapter); | ||
2835 | |||
2735 | kfree(adapter->tx_ring); | 2836 | kfree(adapter->tx_ring); |
2736 | kfree(adapter->rx_ring); | 2837 | kfree(adapter->rx_ring); |
2737 | 2838 | ||
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 651c2699d5e1..b528ce77c406 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c | |||
@@ -1652,6 +1652,11 @@ static void eth_tx_fill_frag_descs(struct mv643xx_private *mp, | |||
1652 | } | 1652 | } |
1653 | } | 1653 | } |
1654 | 1654 | ||
1655 | static inline __be16 sum16_as_be(__sum16 sum) | ||
1656 | { | ||
1657 | return (__force __be16)sum; | ||
1658 | } | ||
1659 | |||
1655 | /** | 1660 | /** |
1656 | * eth_tx_submit_descs_for_skb - submit data from an skb to the tx hw | 1661 | * eth_tx_submit_descs_for_skb - submit data from an skb to the tx hw |
1657 | * | 1662 | * |
@@ -1689,7 +1694,7 @@ static void eth_tx_submit_descs_for_skb(struct mv643xx_private *mp, | |||
1689 | desc->buf_ptr = dma_map_single(NULL, skb->data, length, DMA_TO_DEVICE); | 1694 | desc->buf_ptr = dma_map_single(NULL, skb->data, length, DMA_TO_DEVICE); |
1690 | 1695 | ||
1691 | if (skb->ip_summed == CHECKSUM_PARTIAL) { | 1696 | if (skb->ip_summed == CHECKSUM_PARTIAL) { |
1692 | BUG_ON(skb->protocol != ETH_P_IP); | 1697 | BUG_ON(skb->protocol != htons(ETH_P_IP)); |
1693 | 1698 | ||
1694 | cmd_sts |= ETH_GEN_TCP_UDP_CHECKSUM | | 1699 | cmd_sts |= ETH_GEN_TCP_UDP_CHECKSUM | |
1695 | ETH_GEN_IP_V_4_CHECKSUM | | 1700 | ETH_GEN_IP_V_4_CHECKSUM | |
@@ -1698,10 +1703,10 @@ static void eth_tx_submit_descs_for_skb(struct mv643xx_private *mp, | |||
1698 | switch (ip_hdr(skb)->protocol) { | 1703 | switch (ip_hdr(skb)->protocol) { |
1699 | case IPPROTO_UDP: | 1704 | case IPPROTO_UDP: |
1700 | cmd_sts |= ETH_UDP_FRAME; | 1705 | cmd_sts |= ETH_UDP_FRAME; |
1701 | desc->l4i_chk = udp_hdr(skb)->check; | 1706 | desc->l4i_chk = ntohs(sum16_as_be(udp_hdr(skb)->check)); |
1702 | break; | 1707 | break; |
1703 | case IPPROTO_TCP: | 1708 | case IPPROTO_TCP: |
1704 | desc->l4i_chk = tcp_hdr(skb)->check; | 1709 | desc->l4i_chk = ntohs(sum16_as_be(tcp_hdr(skb)->check)); |
1705 | break; | 1710 | break; |
1706 | default: | 1711 | default: |
1707 | BUG(); | 1712 | BUG(); |
diff --git a/drivers/net/pppol2tp.c b/drivers/net/pppol2tp.c index 1b51bb668d39..5aa0a8089694 100644 --- a/drivers/net/pppol2tp.c +++ b/drivers/net/pppol2tp.c | |||
@@ -2468,9 +2468,10 @@ static int __init pppol2tp_init(void) | |||
2468 | 2468 | ||
2469 | out: | 2469 | out: |
2470 | return err; | 2470 | return err; |
2471 | 2471 | #ifdef CONFIG_PROC_FS | |
2472 | out_unregister_pppox_proto: | 2472 | out_unregister_pppox_proto: |
2473 | unregister_pppox_proto(PX_PROTO_OL2TP); | 2473 | unregister_pppox_proto(PX_PROTO_OL2TP); |
2474 | #endif | ||
2474 | out_unregister_pppol2tp_proto: | 2475 | out_unregister_pppol2tp_proto: |
2475 | proto_unregister(&pppol2tp_sk_proto); | 2476 | proto_unregister(&pppol2tp_sk_proto); |
2476 | goto out; | 2477 | goto out; |
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index dc062367a1c8..9a6295909e43 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c | |||
@@ -857,7 +857,7 @@ static void sky2_mac_init(struct sky2_hw *hw, unsigned port) | |||
857 | sky2_write16(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_OPER_ON); | 857 | sky2_write16(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_OPER_ON); |
858 | 858 | ||
859 | /* On chips without ram buffer, pause is controled by MAC level */ | 859 | /* On chips without ram buffer, pause is controled by MAC level */ |
860 | if (sky2_read8(hw, B2_E_0) == 0) { | 860 | if (!(hw->flags & SKY2_HW_RAM_BUFFER)) { |
861 | sky2_write8(hw, SK_REG(port, RX_GMF_LP_THR), 768/8); | 861 | sky2_write8(hw, SK_REG(port, RX_GMF_LP_THR), 768/8); |
862 | sky2_write8(hw, SK_REG(port, RX_GMF_UP_THR), 1024/8); | 862 | sky2_write8(hw, SK_REG(port, RX_GMF_UP_THR), 1024/8); |
863 | 863 | ||
@@ -1194,7 +1194,7 @@ static struct sk_buff *sky2_rx_alloc(struct sky2_port *sky2) | |||
1194 | struct sk_buff *skb; | 1194 | struct sk_buff *skb; |
1195 | int i; | 1195 | int i; |
1196 | 1196 | ||
1197 | if (sky2->hw->flags & SKY2_HW_FIFO_HANG_CHECK) { | 1197 | if (sky2->hw->flags & SKY2_HW_RAM_BUFFER) { |
1198 | unsigned char *start; | 1198 | unsigned char *start; |
1199 | /* | 1199 | /* |
1200 | * Workaround for a bug in FIFO that cause hang | 1200 | * Workaround for a bug in FIFO that cause hang |
@@ -1387,6 +1387,7 @@ static int sky2_up(struct net_device *dev) | |||
1387 | if (ramsize > 0) { | 1387 | if (ramsize > 0) { |
1388 | u32 rxspace; | 1388 | u32 rxspace; |
1389 | 1389 | ||
1390 | hw->flags |= SKY2_HW_RAM_BUFFER; | ||
1390 | pr_debug(PFX "%s: ram buffer %dK\n", dev->name, ramsize); | 1391 | pr_debug(PFX "%s: ram buffer %dK\n", dev->name, ramsize); |
1391 | if (ramsize < 16) | 1392 | if (ramsize < 16) |
1392 | rxspace = ramsize / 2; | 1393 | rxspace = ramsize / 2; |
@@ -2026,7 +2027,7 @@ static int sky2_change_mtu(struct net_device *dev, int new_mtu) | |||
2026 | 2027 | ||
2027 | synchronize_irq(hw->pdev->irq); | 2028 | synchronize_irq(hw->pdev->irq); |
2028 | 2029 | ||
2029 | if (sky2_read8(hw, B2_E_0) == 0) | 2030 | if (!(hw->flags & SKY2_HW_RAM_BUFFER)) |
2030 | sky2_set_tx_stfwd(hw, port); | 2031 | sky2_set_tx_stfwd(hw, port); |
2031 | 2032 | ||
2032 | ctl = gma_read16(hw, port, GM_GP_CTRL); | 2033 | ctl = gma_read16(hw, port, GM_GP_CTRL); |
@@ -2566,7 +2567,7 @@ static void sky2_watchdog(unsigned long arg) | |||
2566 | ++active; | 2567 | ++active; |
2567 | 2568 | ||
2568 | /* For chips with Rx FIFO, check if stuck */ | 2569 | /* For chips with Rx FIFO, check if stuck */ |
2569 | if ((hw->flags & SKY2_HW_FIFO_HANG_CHECK) && | 2570 | if ((hw->flags & SKY2_HW_RAM_BUFFER) && |
2570 | sky2_rx_hung(dev)) { | 2571 | sky2_rx_hung(dev)) { |
2571 | pr_info(PFX "%s: receiver hang detected\n", | 2572 | pr_info(PFX "%s: receiver hang detected\n", |
2572 | dev->name); | 2573 | dev->name); |
@@ -2722,11 +2723,7 @@ static int __devinit sky2_init(struct sky2_hw *hw) | |||
2722 | 2723 | ||
2723 | switch(hw->chip_id) { | 2724 | switch(hw->chip_id) { |
2724 | case CHIP_ID_YUKON_XL: | 2725 | case CHIP_ID_YUKON_XL: |
2725 | hw->flags = SKY2_HW_GIGABIT | 2726 | hw->flags = SKY2_HW_GIGABIT | SKY2_HW_NEWER_PHY; |
2726 | | SKY2_HW_NEWER_PHY; | ||
2727 | if (hw->chip_rev < 3) | ||
2728 | hw->flags |= SKY2_HW_FIFO_HANG_CHECK; | ||
2729 | |||
2730 | break; | 2727 | break; |
2731 | 2728 | ||
2732 | case CHIP_ID_YUKON_EC_U: | 2729 | case CHIP_ID_YUKON_EC_U: |
@@ -2752,7 +2749,7 @@ static int __devinit sky2_init(struct sky2_hw *hw) | |||
2752 | dev_err(&hw->pdev->dev, "unsupported revision Yukon-EC rev A1\n"); | 2749 | dev_err(&hw->pdev->dev, "unsupported revision Yukon-EC rev A1\n"); |
2753 | return -EOPNOTSUPP; | 2750 | return -EOPNOTSUPP; |
2754 | } | 2751 | } |
2755 | hw->flags = SKY2_HW_GIGABIT | SKY2_HW_FIFO_HANG_CHECK; | 2752 | hw->flags = SKY2_HW_GIGABIT; |
2756 | break; | 2753 | break; |
2757 | 2754 | ||
2758 | case CHIP_ID_YUKON_FE: | 2755 | case CHIP_ID_YUKON_FE: |
diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h index 2bced1a0898f..5ab5c1c7c5aa 100644 --- a/drivers/net/sky2.h +++ b/drivers/net/sky2.h | |||
@@ -2045,7 +2045,7 @@ struct sky2_hw { | |||
2045 | #define SKY2_HW_FIBRE_PHY 0x00000002 | 2045 | #define SKY2_HW_FIBRE_PHY 0x00000002 |
2046 | #define SKY2_HW_GIGABIT 0x00000004 | 2046 | #define SKY2_HW_GIGABIT 0x00000004 |
2047 | #define SKY2_HW_NEWER_PHY 0x00000008 | 2047 | #define SKY2_HW_NEWER_PHY 0x00000008 |
2048 | #define SKY2_HW_FIFO_HANG_CHECK 0x00000010 | 2048 | #define SKY2_HW_RAM_BUFFER 0x00000010 |
2049 | #define SKY2_HW_NEW_LE 0x00000020 /* new LSOv2 format */ | 2049 | #define SKY2_HW_NEW_LE 0x00000020 /* new LSOv2 format */ |
2050 | #define SKY2_HW_AUTO_TX_SUM 0x00000040 /* new IP decode for Tx */ | 2050 | #define SKY2_HW_AUTO_TX_SUM 0x00000040 /* new IP decode for Tx */ |
2051 | #define SKY2_HW_ADV_POWER_CTL 0x00000080 /* additional PHY power regs */ | 2051 | #define SKY2_HW_ADV_POWER_CTL 0x00000080 /* additional PHY power regs */ |
diff --git a/drivers/net/tlan.c b/drivers/net/tlan.c index c99ce74a7aff..3af5b92b48c8 100644 --- a/drivers/net/tlan.c +++ b/drivers/net/tlan.c | |||
@@ -465,7 +465,7 @@ static struct pci_driver tlan_driver = { | |||
465 | 465 | ||
466 | static int __init tlan_probe(void) | 466 | static int __init tlan_probe(void) |
467 | { | 467 | { |
468 | static int pad_allocated; | 468 | int rc = -ENODEV; |
469 | 469 | ||
470 | printk(KERN_INFO "%s", tlan_banner); | 470 | printk(KERN_INFO "%s", tlan_banner); |
471 | 471 | ||
@@ -473,17 +473,22 @@ static int __init tlan_probe(void) | |||
473 | 473 | ||
474 | if (TLanPadBuffer == NULL) { | 474 | if (TLanPadBuffer == NULL) { |
475 | printk(KERN_ERR "TLAN: Could not allocate memory for pad buffer.\n"); | 475 | printk(KERN_ERR "TLAN: Could not allocate memory for pad buffer.\n"); |
476 | return -ENOMEM; | 476 | rc = -ENOMEM; |
477 | goto err_out; | ||
477 | } | 478 | } |
478 | 479 | ||
479 | memset(TLanPadBuffer, 0, TLAN_MIN_FRAME_SIZE); | 480 | memset(TLanPadBuffer, 0, TLAN_MIN_FRAME_SIZE); |
480 | pad_allocated = 1; | ||
481 | 481 | ||
482 | TLAN_DBG(TLAN_DEBUG_PROBE, "Starting PCI Probe....\n"); | 482 | TLAN_DBG(TLAN_DEBUG_PROBE, "Starting PCI Probe....\n"); |
483 | 483 | ||
484 | /* Use new style PCI probing. Now the kernel will | 484 | /* Use new style PCI probing. Now the kernel will |
485 | do most of this for us */ | 485 | do most of this for us */ |
486 | pci_register_driver(&tlan_driver); | 486 | rc = pci_register_driver(&tlan_driver); |
487 | |||
488 | if (rc != 0) { | ||
489 | printk(KERN_ERR "TLAN: Could not register pci driver.\n"); | ||
490 | goto err_out_pci_free; | ||
491 | } | ||
487 | 492 | ||
488 | TLAN_DBG(TLAN_DEBUG_PROBE, "Starting EISA Probe....\n"); | 493 | TLAN_DBG(TLAN_DEBUG_PROBE, "Starting EISA Probe....\n"); |
489 | TLan_EisaProbe(); | 494 | TLan_EisaProbe(); |
@@ -493,11 +498,17 @@ static int __init tlan_probe(void) | |||
493 | tlan_have_pci, tlan_have_eisa); | 498 | tlan_have_pci, tlan_have_eisa); |
494 | 499 | ||
495 | if (TLanDevicesInstalled == 0) { | 500 | if (TLanDevicesInstalled == 0) { |
496 | pci_unregister_driver(&tlan_driver); | 501 | rc = -ENODEV; |
497 | pci_free_consistent(NULL, TLAN_MIN_FRAME_SIZE, TLanPadBuffer, TLanPadBufferDMA); | 502 | goto err_out_pci_unreg; |
498 | return -ENODEV; | ||
499 | } | 503 | } |
500 | return 0; | 504 | return 0; |
505 | |||
506 | err_out_pci_unreg: | ||
507 | pci_unregister_driver(&tlan_driver); | ||
508 | err_out_pci_free: | ||
509 | pci_free_consistent(NULL, TLAN_MIN_FRAME_SIZE, TLanPadBuffer, TLanPadBufferDMA); | ||
510 | err_out: | ||
511 | return rc; | ||
501 | } | 512 | } |
502 | 513 | ||
503 | 514 | ||
diff --git a/drivers/net/tulip/xircom_cb.c b/drivers/net/tulip/xircom_cb.c index 8fc7274642eb..6b93d0169116 100644 --- a/drivers/net/tulip/xircom_cb.c +++ b/drivers/net/tulip/xircom_cb.c | |||
@@ -441,7 +441,7 @@ static int xircom_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
441 | spin_unlock_irqrestore(&card->lock,flags); | 441 | spin_unlock_irqrestore(&card->lock,flags); |
442 | trigger_transmit(card); | 442 | trigger_transmit(card); |
443 | 443 | ||
444 | return -EIO; | 444 | return NETDEV_TX_BUSY; |
445 | } | 445 | } |
446 | 446 | ||
447 | 447 | ||
diff --git a/drivers/net/ucc_geth_mii.c b/drivers/net/ucc_geth_mii.c index e3ba14a19915..c69e654d539f 100644 --- a/drivers/net/ucc_geth_mii.c +++ b/drivers/net/ucc_geth_mii.c | |||
@@ -109,7 +109,7 @@ int uec_mdio_reset(struct mii_bus *bus) | |||
109 | struct ucc_mii_mng __iomem *regs = (void __iomem *)bus->priv; | 109 | struct ucc_mii_mng __iomem *regs = (void __iomem *)bus->priv; |
110 | unsigned int timeout = PHY_INIT_TIMEOUT; | 110 | unsigned int timeout = PHY_INIT_TIMEOUT; |
111 | 111 | ||
112 | spin_lock_bh(&bus->mdio_lock); | 112 | mutex_lock(&bus->mdio_lock); |
113 | 113 | ||
114 | /* Reset the management interface */ | 114 | /* Reset the management interface */ |
115 | out_be32(®s->miimcfg, MIIMCFG_RESET_MANAGEMENT); | 115 | out_be32(®s->miimcfg, MIIMCFG_RESET_MANAGEMENT); |
@@ -121,7 +121,7 @@ int uec_mdio_reset(struct mii_bus *bus) | |||
121 | while ((in_be32(®s->miimind) & MIIMIND_BUSY) && timeout--) | 121 | while ((in_be32(®s->miimind) & MIIMIND_BUSY) && timeout--) |
122 | cpu_relax(); | 122 | cpu_relax(); |
123 | 123 | ||
124 | spin_unlock_bh(&bus->mdio_lock); | 124 | mutex_unlock(&bus->mdio_lock); |
125 | 125 | ||
126 | if (timeout <= 0) { | 126 | if (timeout <= 0) { |
127 | printk(KERN_ERR "%s: The MII Bus is stuck!\n", bus->name); | 127 | printk(KERN_ERR "%s: The MII Bus is stuck!\n", bus->name); |
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index e66de0c12fc1..fdc23678117b 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c | |||
@@ -302,10 +302,12 @@ static int virtnet_open(struct net_device *dev) | |||
302 | 302 | ||
303 | /* If all buffers were filled by other side before we napi_enabled, we | 303 | /* If all buffers were filled by other side before we napi_enabled, we |
304 | * won't get another interrupt, so process any outstanding packets | 304 | * won't get another interrupt, so process any outstanding packets |
305 | * now. virtnet_poll wants re-enable the queue, so we disable here. */ | 305 | * now. virtnet_poll wants re-enable the queue, so we disable here. |
306 | vi->rvq->vq_ops->disable_cb(vi->rvq); | 306 | * We synchronize against interrupts via NAPI_STATE_SCHED */ |
307 | netif_rx_schedule(vi->dev, &vi->napi); | 307 | if (netif_rx_schedule_prep(dev, &vi->napi)) { |
308 | 308 | vi->rvq->vq_ops->disable_cb(vi->rvq); | |
309 | __netif_rx_schedule(dev, &vi->napi); | ||
310 | } | ||
309 | return 0; | 311 | return 0; |
310 | } | 312 | } |
311 | 313 | ||
diff --git a/drivers/net/wan/hdlc.c b/drivers/net/wan/hdlc.c index d553e6f32851..39951d0c34d6 100644 --- a/drivers/net/wan/hdlc.c +++ b/drivers/net/wan/hdlc.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Generic HDLC support routines for Linux | 2 | * Generic HDLC support routines for Linux |
3 | * | 3 | * |
4 | * Copyright (C) 1999 - 2006 Krzysztof Halasa <khc@pm.waw.pl> | 4 | * Copyright (C) 1999 - 2008 Krzysztof Halasa <khc@pm.waw.pl> |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify it | 6 | * This program is free software; you can redistribute it and/or modify it |
7 | * under the terms of version 2 of the GNU General Public License | 7 | * under the terms of version 2 of the GNU General Public License |
@@ -39,7 +39,7 @@ | |||
39 | #include <net/net_namespace.h> | 39 | #include <net/net_namespace.h> |
40 | 40 | ||
41 | 41 | ||
42 | static const char* version = "HDLC support module revision 1.21"; | 42 | static const char* version = "HDLC support module revision 1.22"; |
43 | 43 | ||
44 | #undef DEBUG_LINK | 44 | #undef DEBUG_LINK |
45 | 45 | ||
@@ -66,19 +66,15 @@ static struct net_device_stats *hdlc_get_stats(struct net_device *dev) | |||
66 | static int hdlc_rcv(struct sk_buff *skb, struct net_device *dev, | 66 | static int hdlc_rcv(struct sk_buff *skb, struct net_device *dev, |
67 | struct packet_type *p, struct net_device *orig_dev) | 67 | struct packet_type *p, struct net_device *orig_dev) |
68 | { | 68 | { |
69 | struct hdlc_device_desc *desc = dev_to_desc(dev); | 69 | struct hdlc_device *hdlc = dev_to_hdlc(dev); |
70 | 70 | ||
71 | if (dev->nd_net != &init_net) { | 71 | if (dev->nd_net != &init_net) { |
72 | kfree_skb(skb); | 72 | kfree_skb(skb); |
73 | return 0; | 73 | return 0; |
74 | } | 74 | } |
75 | 75 | ||
76 | if (desc->netif_rx) | 76 | BUG_ON(!hdlc->proto->netif_rx); |
77 | return desc->netif_rx(skb); | 77 | return hdlc->proto->netif_rx(skb); |
78 | |||
79 | desc->stats.rx_dropped++; /* Shouldn't happen */ | ||
80 | dev_kfree_skb(skb); | ||
81 | return NET_RX_DROP; | ||
82 | } | 78 | } |
83 | 79 | ||
84 | 80 | ||
@@ -87,7 +83,7 @@ static inline void hdlc_proto_start(struct net_device *dev) | |||
87 | { | 83 | { |
88 | hdlc_device *hdlc = dev_to_hdlc(dev); | 84 | hdlc_device *hdlc = dev_to_hdlc(dev); |
89 | if (hdlc->proto->start) | 85 | if (hdlc->proto->start) |
90 | return hdlc->proto->start(dev); | 86 | hdlc->proto->start(dev); |
91 | } | 87 | } |
92 | 88 | ||
93 | 89 | ||
@@ -96,7 +92,7 @@ static inline void hdlc_proto_stop(struct net_device *dev) | |||
96 | { | 92 | { |
97 | hdlc_device *hdlc = dev_to_hdlc(dev); | 93 | hdlc_device *hdlc = dev_to_hdlc(dev); |
98 | if (hdlc->proto->stop) | 94 | if (hdlc->proto->stop) |
99 | return hdlc->proto->stop(dev); | 95 | hdlc->proto->stop(dev); |
100 | } | 96 | } |
101 | 97 | ||
102 | 98 | ||
@@ -263,8 +259,7 @@ static void hdlc_setup(struct net_device *dev) | |||
263 | struct net_device *alloc_hdlcdev(void *priv) | 259 | struct net_device *alloc_hdlcdev(void *priv) |
264 | { | 260 | { |
265 | struct net_device *dev; | 261 | struct net_device *dev; |
266 | dev = alloc_netdev(sizeof(struct hdlc_device_desc) + | 262 | dev = alloc_netdev(sizeof(struct hdlc_device), "hdlc%d", hdlc_setup); |
267 | sizeof(hdlc_device), "hdlc%d", hdlc_setup); | ||
268 | if (dev) | 263 | if (dev) |
269 | dev_to_hdlc(dev)->priv = priv; | 264 | dev_to_hdlc(dev)->priv = priv; |
270 | return dev; | 265 | return dev; |
@@ -281,7 +276,7 @@ void unregister_hdlc_device(struct net_device *dev) | |||
281 | 276 | ||
282 | 277 | ||
283 | int attach_hdlc_protocol(struct net_device *dev, struct hdlc_proto *proto, | 278 | int attach_hdlc_protocol(struct net_device *dev, struct hdlc_proto *proto, |
284 | int (*rx)(struct sk_buff *skb), size_t size) | 279 | size_t size) |
285 | { | 280 | { |
286 | detach_hdlc_protocol(dev); | 281 | detach_hdlc_protocol(dev); |
287 | 282 | ||
@@ -297,7 +292,6 @@ int attach_hdlc_protocol(struct net_device *dev, struct hdlc_proto *proto, | |||
297 | return -ENOBUFS; | 292 | return -ENOBUFS; |
298 | } | 293 | } |
299 | dev_to_hdlc(dev)->proto = proto; | 294 | dev_to_hdlc(dev)->proto = proto; |
300 | dev_to_desc(dev)->netif_rx = rx; | ||
301 | return 0; | 295 | return 0; |
302 | } | 296 | } |
303 | 297 | ||
diff --git a/drivers/net/wan/hdlc_cisco.c b/drivers/net/wan/hdlc_cisco.c index 038a6e748bbf..7133c688cf20 100644 --- a/drivers/net/wan/hdlc_cisco.c +++ b/drivers/net/wan/hdlc_cisco.c | |||
@@ -250,7 +250,7 @@ static int cisco_rx(struct sk_buff *skb) | |||
250 | return NET_RX_DROP; | 250 | return NET_RX_DROP; |
251 | 251 | ||
252 | rx_error: | 252 | rx_error: |
253 | dev_to_desc(dev)->stats.rx_errors++; /* Mark error */ | 253 | dev_to_hdlc(dev)->stats.rx_errors++; /* Mark error */ |
254 | dev_kfree_skb_any(skb); | 254 | dev_kfree_skb_any(skb); |
255 | return NET_RX_DROP; | 255 | return NET_RX_DROP; |
256 | } | 256 | } |
@@ -314,6 +314,7 @@ static struct hdlc_proto proto = { | |||
314 | .stop = cisco_stop, | 314 | .stop = cisco_stop, |
315 | .type_trans = cisco_type_trans, | 315 | .type_trans = cisco_type_trans, |
316 | .ioctl = cisco_ioctl, | 316 | .ioctl = cisco_ioctl, |
317 | .netif_rx = cisco_rx, | ||
317 | .module = THIS_MODULE, | 318 | .module = THIS_MODULE, |
318 | }; | 319 | }; |
319 | 320 | ||
@@ -360,7 +361,7 @@ static int cisco_ioctl(struct net_device *dev, struct ifreq *ifr) | |||
360 | if (result) | 361 | if (result) |
361 | return result; | 362 | return result; |
362 | 363 | ||
363 | result = attach_hdlc_protocol(dev, &proto, cisco_rx, | 364 | result = attach_hdlc_protocol(dev, &proto, |
364 | sizeof(struct cisco_state)); | 365 | sizeof(struct cisco_state)); |
365 | if (result) | 366 | if (result) |
366 | return result; | 367 | return result; |
diff --git a/drivers/net/wan/hdlc_fr.c b/drivers/net/wan/hdlc_fr.c index 071a64cacd5c..c4ab0326f911 100644 --- a/drivers/net/wan/hdlc_fr.c +++ b/drivers/net/wan/hdlc_fr.c | |||
@@ -42,7 +42,6 @@ | |||
42 | #include <linux/init.h> | 42 | #include <linux/init.h> |
43 | #include <linux/skbuff.h> | 43 | #include <linux/skbuff.h> |
44 | #include <linux/pkt_sched.h> | 44 | #include <linux/pkt_sched.h> |
45 | #include <linux/random.h> | ||
46 | #include <linux/inetdevice.h> | 45 | #include <linux/inetdevice.h> |
47 | #include <linux/lapb.h> | 46 | #include <linux/lapb.h> |
48 | #include <linux/rtnetlink.h> | 47 | #include <linux/rtnetlink.h> |
@@ -136,6 +135,10 @@ typedef struct pvc_device_struct { | |||
136 | }state; | 135 | }state; |
137 | }pvc_device; | 136 | }pvc_device; |
138 | 137 | ||
138 | struct pvc_desc { | ||
139 | struct net_device_stats stats; | ||
140 | pvc_device *pvc; | ||
141 | }; | ||
139 | 142 | ||
140 | struct frad_state { | 143 | struct frad_state { |
141 | fr_proto settings; | 144 | fr_proto settings; |
@@ -171,17 +174,20 @@ static inline void dlci_to_q922(u8 *hdr, u16 dlci) | |||
171 | } | 174 | } |
172 | 175 | ||
173 | 176 | ||
174 | static inline struct frad_state * state(hdlc_device *hdlc) | 177 | static inline struct frad_state* state(hdlc_device *hdlc) |
175 | { | 178 | { |
176 | return(struct frad_state *)(hdlc->state); | 179 | return(struct frad_state *)(hdlc->state); |
177 | } | 180 | } |
178 | 181 | ||
179 | 182 | static inline struct pvc_desc* pvcdev_to_desc(struct net_device *dev) | |
180 | static __inline__ pvc_device* dev_to_pvc(struct net_device *dev) | ||
181 | { | 183 | { |
182 | return dev->priv; | 184 | return dev->priv; |
183 | } | 185 | } |
184 | 186 | ||
187 | static inline struct net_device_stats* pvc_get_stats(struct net_device *dev) | ||
188 | { | ||
189 | return &pvcdev_to_desc(dev)->stats; | ||
190 | } | ||
185 | 191 | ||
186 | static inline pvc_device* find_pvc(hdlc_device *hdlc, u16 dlci) | 192 | static inline pvc_device* find_pvc(hdlc_device *hdlc, u16 dlci) |
187 | { | 193 | { |
@@ -351,7 +357,7 @@ static int fr_hard_header(struct sk_buff **skb_p, u16 dlci) | |||
351 | 357 | ||
352 | static int pvc_open(struct net_device *dev) | 358 | static int pvc_open(struct net_device *dev) |
353 | { | 359 | { |
354 | pvc_device *pvc = dev_to_pvc(dev); | 360 | pvc_device *pvc = pvcdev_to_desc(dev)->pvc; |
355 | 361 | ||
356 | if ((pvc->frad->flags & IFF_UP) == 0) | 362 | if ((pvc->frad->flags & IFF_UP) == 0) |
357 | return -EIO; /* Frad must be UP in order to activate PVC */ | 363 | return -EIO; /* Frad must be UP in order to activate PVC */ |
@@ -371,7 +377,7 @@ static int pvc_open(struct net_device *dev) | |||
371 | 377 | ||
372 | static int pvc_close(struct net_device *dev) | 378 | static int pvc_close(struct net_device *dev) |
373 | { | 379 | { |
374 | pvc_device *pvc = dev_to_pvc(dev); | 380 | pvc_device *pvc = pvcdev_to_desc(dev)->pvc; |
375 | 381 | ||
376 | if (--pvc->open_count == 0) { | 382 | if (--pvc->open_count == 0) { |
377 | hdlc_device *hdlc = dev_to_hdlc(pvc->frad); | 383 | hdlc_device *hdlc = dev_to_hdlc(pvc->frad); |
@@ -390,7 +396,7 @@ static int pvc_close(struct net_device *dev) | |||
390 | 396 | ||
391 | static int pvc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | 397 | static int pvc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) |
392 | { | 398 | { |
393 | pvc_device *pvc = dev_to_pvc(dev); | 399 | pvc_device *pvc = pvcdev_to_desc(dev)->pvc; |
394 | fr_proto_pvc_info info; | 400 | fr_proto_pvc_info info; |
395 | 401 | ||
396 | if (ifr->ifr_settings.type == IF_GET_PROTO) { | 402 | if (ifr->ifr_settings.type == IF_GET_PROTO) { |
@@ -416,17 +422,9 @@ static int pvc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | |||
416 | return -EINVAL; | 422 | return -EINVAL; |
417 | } | 423 | } |
418 | 424 | ||
419 | |||
420 | static inline struct net_device_stats *pvc_get_stats(struct net_device *dev) | ||
421 | { | ||
422 | return &dev_to_desc(dev)->stats; | ||
423 | } | ||
424 | |||
425 | |||
426 | |||
427 | static int pvc_xmit(struct sk_buff *skb, struct net_device *dev) | 425 | static int pvc_xmit(struct sk_buff *skb, struct net_device *dev) |
428 | { | 426 | { |
429 | pvc_device *pvc = dev_to_pvc(dev); | 427 | pvc_device *pvc = pvcdev_to_desc(dev)->pvc; |
430 | struct net_device_stats *stats = pvc_get_stats(dev); | 428 | struct net_device_stats *stats = pvc_get_stats(dev); |
431 | 429 | ||
432 | if (pvc->state.active) { | 430 | if (pvc->state.active) { |
@@ -957,7 +955,7 @@ static int fr_rx(struct sk_buff *skb) | |||
957 | 955 | ||
958 | 956 | ||
959 | if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) { | 957 | if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) { |
960 | dev_to_desc(frad)->stats.rx_dropped++; | 958 | dev_to_hdlc(frad)->stats.rx_dropped++; |
961 | return NET_RX_DROP; | 959 | return NET_RX_DROP; |
962 | } | 960 | } |
963 | 961 | ||
@@ -1018,7 +1016,7 @@ static int fr_rx(struct sk_buff *skb) | |||
1018 | } | 1016 | } |
1019 | 1017 | ||
1020 | rx_error: | 1018 | rx_error: |
1021 | dev_to_desc(frad)->stats.rx_errors++; /* Mark error */ | 1019 | dev_to_hdlc(frad)->stats.rx_errors++; /* Mark error */ |
1022 | dev_kfree_skb_any(skb); | 1020 | dev_kfree_skb_any(skb); |
1023 | return NET_RX_DROP; | 1021 | return NET_RX_DROP; |
1024 | } | 1022 | } |
@@ -1109,11 +1107,10 @@ static int fr_add_pvc(struct net_device *frad, unsigned int dlci, int type) | |||
1109 | used = pvc_is_used(pvc); | 1107 | used = pvc_is_used(pvc); |
1110 | 1108 | ||
1111 | if (type == ARPHRD_ETHER) | 1109 | if (type == ARPHRD_ETHER) |
1112 | dev = alloc_netdev(sizeof(struct net_device_stats), | 1110 | dev = alloc_netdev(sizeof(struct pvc_desc), "pvceth%d", |
1113 | "pvceth%d", ether_setup); | 1111 | ether_setup); |
1114 | else | 1112 | else |
1115 | dev = alloc_netdev(sizeof(struct net_device_stats), | 1113 | dev = alloc_netdev(sizeof(struct pvc_desc), "pvc%d", pvc_setup); |
1116 | "pvc%d", pvc_setup); | ||
1117 | 1114 | ||
1118 | if (!dev) { | 1115 | if (!dev) { |
1119 | printk(KERN_WARNING "%s: Memory squeeze on fr_pvc()\n", | 1116 | printk(KERN_WARNING "%s: Memory squeeze on fr_pvc()\n", |
@@ -1122,10 +1119,9 @@ static int fr_add_pvc(struct net_device *frad, unsigned int dlci, int type) | |||
1122 | return -ENOBUFS; | 1119 | return -ENOBUFS; |
1123 | } | 1120 | } |
1124 | 1121 | ||
1125 | if (type == ARPHRD_ETHER) { | 1122 | if (type == ARPHRD_ETHER) |
1126 | memcpy(dev->dev_addr, "\x00\x01", 2); | 1123 | random_ether_addr(dev->dev_addr); |
1127 | get_random_bytes(dev->dev_addr + 2, ETH_ALEN - 2); | 1124 | else { |
1128 | } else { | ||
1129 | *(__be16*)dev->dev_addr = htons(dlci); | 1125 | *(__be16*)dev->dev_addr = htons(dlci); |
1130 | dlci_to_q922(dev->broadcast, dlci); | 1126 | dlci_to_q922(dev->broadcast, dlci); |
1131 | } | 1127 | } |
@@ -1137,7 +1133,7 @@ static int fr_add_pvc(struct net_device *frad, unsigned int dlci, int type) | |||
1137 | dev->change_mtu = pvc_change_mtu; | 1133 | dev->change_mtu = pvc_change_mtu; |
1138 | dev->mtu = HDLC_MAX_MTU; | 1134 | dev->mtu = HDLC_MAX_MTU; |
1139 | dev->tx_queue_len = 0; | 1135 | dev->tx_queue_len = 0; |
1140 | dev->priv = pvc; | 1136 | pvcdev_to_desc(dev)->pvc = pvc; |
1141 | 1137 | ||
1142 | result = dev_alloc_name(dev, dev->name); | 1138 | result = dev_alloc_name(dev, dev->name); |
1143 | if (result < 0) { | 1139 | if (result < 0) { |
@@ -1219,6 +1215,7 @@ static struct hdlc_proto proto = { | |||
1219 | .stop = fr_stop, | 1215 | .stop = fr_stop, |
1220 | .detach = fr_destroy, | 1216 | .detach = fr_destroy, |
1221 | .ioctl = fr_ioctl, | 1217 | .ioctl = fr_ioctl, |
1218 | .netif_rx = fr_rx, | ||
1222 | .module = THIS_MODULE, | 1219 | .module = THIS_MODULE, |
1223 | }; | 1220 | }; |
1224 | 1221 | ||
@@ -1277,7 +1274,7 @@ static int fr_ioctl(struct net_device *dev, struct ifreq *ifr) | |||
1277 | return result; | 1274 | return result; |
1278 | 1275 | ||
1279 | if (dev_to_hdlc(dev)->proto != &proto) { /* Different proto */ | 1276 | if (dev_to_hdlc(dev)->proto != &proto) { /* Different proto */ |
1280 | result = attach_hdlc_protocol(dev, &proto, fr_rx, | 1277 | result = attach_hdlc_protocol(dev, &proto, |
1281 | sizeof(struct frad_state)); | 1278 | sizeof(struct frad_state)); |
1282 | if (result) | 1279 | if (result) |
1283 | return result; | 1280 | return result; |
diff --git a/drivers/net/wan/hdlc_ppp.c b/drivers/net/wan/hdlc_ppp.c index 519e1550e2e7..10396d9686f4 100644 --- a/drivers/net/wan/hdlc_ppp.c +++ b/drivers/net/wan/hdlc_ppp.c | |||
@@ -122,7 +122,7 @@ static int ppp_ioctl(struct net_device *dev, struct ifreq *ifr) | |||
122 | if (result) | 122 | if (result) |
123 | return result; | 123 | return result; |
124 | 124 | ||
125 | result = attach_hdlc_protocol(dev, &proto, NULL, | 125 | result = attach_hdlc_protocol(dev, &proto, |
126 | sizeof(struct ppp_state)); | 126 | sizeof(struct ppp_state)); |
127 | if (result) | 127 | if (result) |
128 | return result; | 128 | return result; |
diff --git a/drivers/net/wan/hdlc_raw.c b/drivers/net/wan/hdlc_raw.c index e23bc6656267..bbbb819d764c 100644 --- a/drivers/net/wan/hdlc_raw.c +++ b/drivers/net/wan/hdlc_raw.c | |||
@@ -82,7 +82,7 @@ static int raw_ioctl(struct net_device *dev, struct ifreq *ifr) | |||
82 | if (result) | 82 | if (result) |
83 | return result; | 83 | return result; |
84 | 84 | ||
85 | result = attach_hdlc_protocol(dev, &proto, NULL, | 85 | result = attach_hdlc_protocol(dev, &proto, |
86 | sizeof(raw_hdlc_proto)); | 86 | sizeof(raw_hdlc_proto)); |
87 | if (result) | 87 | if (result) |
88 | return result; | 88 | return result; |
diff --git a/drivers/net/wan/hdlc_raw_eth.c b/drivers/net/wan/hdlc_raw_eth.c index 8895394e6006..d20c685f6711 100644 --- a/drivers/net/wan/hdlc_raw_eth.c +++ b/drivers/net/wan/hdlc_raw_eth.c | |||
@@ -18,7 +18,6 @@ | |||
18 | #include <linux/init.h> | 18 | #include <linux/init.h> |
19 | #include <linux/skbuff.h> | 19 | #include <linux/skbuff.h> |
20 | #include <linux/pkt_sched.h> | 20 | #include <linux/pkt_sched.h> |
21 | #include <linux/random.h> | ||
22 | #include <linux/inetdevice.h> | 21 | #include <linux/inetdevice.h> |
23 | #include <linux/lapb.h> | 22 | #include <linux/lapb.h> |
24 | #include <linux/rtnetlink.h> | 23 | #include <linux/rtnetlink.h> |
@@ -96,7 +95,7 @@ static int raw_eth_ioctl(struct net_device *dev, struct ifreq *ifr) | |||
96 | if (result) | 95 | if (result) |
97 | return result; | 96 | return result; |
98 | 97 | ||
99 | result = attach_hdlc_protocol(dev, &proto, NULL, | 98 | result = attach_hdlc_protocol(dev, &proto, |
100 | sizeof(raw_hdlc_proto)); | 99 | sizeof(raw_hdlc_proto)); |
101 | if (result) | 100 | if (result) |
102 | return result; | 101 | return result; |
@@ -107,8 +106,7 @@ static int raw_eth_ioctl(struct net_device *dev, struct ifreq *ifr) | |||
107 | ether_setup(dev); | 106 | ether_setup(dev); |
108 | dev->change_mtu = old_ch_mtu; | 107 | dev->change_mtu = old_ch_mtu; |
109 | dev->tx_queue_len = old_qlen; | 108 | dev->tx_queue_len = old_qlen; |
110 | memcpy(dev->dev_addr, "\x00\x01", 2); | 109 | random_ether_addr(dev->dev_addr); |
111 | get_random_bytes(dev->dev_addr + 2, ETH_ALEN - 2); | ||
112 | netif_dormant_off(dev); | 110 | netif_dormant_off(dev); |
113 | return 0; | 111 | return 0; |
114 | } | 112 | } |
diff --git a/drivers/net/wan/hdlc_x25.c b/drivers/net/wan/hdlc_x25.c index cd7b22f50edc..c15cc11e399b 100644 --- a/drivers/net/wan/hdlc_x25.c +++ b/drivers/net/wan/hdlc_x25.c | |||
@@ -164,17 +164,17 @@ static void x25_close(struct net_device *dev) | |||
164 | 164 | ||
165 | static int x25_rx(struct sk_buff *skb) | 165 | static int x25_rx(struct sk_buff *skb) |
166 | { | 166 | { |
167 | struct hdlc_device_desc *desc = dev_to_desc(skb->dev); | 167 | struct hdlc_device *hdlc = dev_to_hdlc(skb->dev); |
168 | 168 | ||
169 | if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) { | 169 | if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) { |
170 | desc->stats.rx_dropped++; | 170 | hdlc->stats.rx_dropped++; |
171 | return NET_RX_DROP; | 171 | return NET_RX_DROP; |
172 | } | 172 | } |
173 | 173 | ||
174 | if (lapb_data_received(skb->dev, skb) == LAPB_OK) | 174 | if (lapb_data_received(skb->dev, skb) == LAPB_OK) |
175 | return NET_RX_SUCCESS; | 175 | return NET_RX_SUCCESS; |
176 | 176 | ||
177 | desc->stats.rx_errors++; | 177 | hdlc->stats.rx_errors++; |
178 | dev_kfree_skb_any(skb); | 178 | dev_kfree_skb_any(skb); |
179 | return NET_RX_DROP; | 179 | return NET_RX_DROP; |
180 | } | 180 | } |
@@ -184,6 +184,7 @@ static struct hdlc_proto proto = { | |||
184 | .open = x25_open, | 184 | .open = x25_open, |
185 | .close = x25_close, | 185 | .close = x25_close, |
186 | .ioctl = x25_ioctl, | 186 | .ioctl = x25_ioctl, |
187 | .netif_rx = x25_rx, | ||
187 | .module = THIS_MODULE, | 188 | .module = THIS_MODULE, |
188 | }; | 189 | }; |
189 | 190 | ||
@@ -211,8 +212,7 @@ static int x25_ioctl(struct net_device *dev, struct ifreq *ifr) | |||
211 | if (result) | 212 | if (result) |
212 | return result; | 213 | return result; |
213 | 214 | ||
214 | if ((result = attach_hdlc_protocol(dev, &proto, | 215 | if ((result = attach_hdlc_protocol(dev, &proto, 0))) |
215 | x25_rx, 0)) != 0) | ||
216 | return result; | 216 | return result; |
217 | dev->hard_start_xmit = x25_xmit; | 217 | dev->hard_start_xmit = x25_xmit; |
218 | dev->type = ARPHRD_X25; | 218 | dev->type = ARPHRD_X25; |
diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c index 8a708b77925d..3dfb28a34be9 100644 --- a/drivers/net/wireless/b43/dma.c +++ b/drivers/net/wireless/b43/dma.c | |||
@@ -337,7 +337,7 @@ static inline int txring_to_priority(struct b43_dmaring *ring) | |||
337 | return idx_to_prio[index]; | 337 | return idx_to_prio[index]; |
338 | } | 338 | } |
339 | 339 | ||
340 | u16 b43_dmacontroller_base(int dma64bit, int controller_idx) | 340 | static u16 b43_dmacontroller_base(enum b43_dmatype type, int controller_idx) |
341 | { | 341 | { |
342 | static const u16 map64[] = { | 342 | static const u16 map64[] = { |
343 | B43_MMIO_DMA64_BASE0, | 343 | B43_MMIO_DMA64_BASE0, |
@@ -356,7 +356,7 @@ u16 b43_dmacontroller_base(int dma64bit, int controller_idx) | |||
356 | B43_MMIO_DMA32_BASE5, | 356 | B43_MMIO_DMA32_BASE5, |
357 | }; | 357 | }; |
358 | 358 | ||
359 | if (dma64bit) { | 359 | if (type == B43_DMA_64BIT) { |
360 | B43_WARN_ON(!(controller_idx >= 0 && | 360 | B43_WARN_ON(!(controller_idx >= 0 && |
361 | controller_idx < ARRAY_SIZE(map64))); | 361 | controller_idx < ARRAY_SIZE(map64))); |
362 | return map64[controller_idx]; | 362 | return map64[controller_idx]; |
@@ -437,7 +437,7 @@ static int alloc_ringmemory(struct b43_dmaring *ring) | |||
437 | * 02, which uses 64-bit DMA, needs the ring buffer in very low memory, | 437 | * 02, which uses 64-bit DMA, needs the ring buffer in very low memory, |
438 | * which accounts for the GFP_DMA flag below. | 438 | * which accounts for the GFP_DMA flag below. |
439 | */ | 439 | */ |
440 | if (ring->dma64) | 440 | if (ring->type == B43_DMA_64BIT) |
441 | flags |= GFP_DMA; | 441 | flags |= GFP_DMA; |
442 | ring->descbase = dma_alloc_coherent(dev, B43_DMA_RINGMEMSIZE, | 442 | ring->descbase = dma_alloc_coherent(dev, B43_DMA_RINGMEMSIZE, |
443 | &(ring->dmabase), flags); | 443 | &(ring->dmabase), flags); |
@@ -459,7 +459,8 @@ static void free_ringmemory(struct b43_dmaring *ring) | |||
459 | } | 459 | } |
460 | 460 | ||
461 | /* Reset the RX DMA channel */ | 461 | /* Reset the RX DMA channel */ |
462 | int b43_dmacontroller_rx_reset(struct b43_wldev *dev, u16 mmio_base, int dma64) | 462 | static int b43_dmacontroller_rx_reset(struct b43_wldev *dev, u16 mmio_base, |
463 | enum b43_dmatype type) | ||
463 | { | 464 | { |
464 | int i; | 465 | int i; |
465 | u32 value; | 466 | u32 value; |
@@ -467,12 +468,13 @@ int b43_dmacontroller_rx_reset(struct b43_wldev *dev, u16 mmio_base, int dma64) | |||
467 | 468 | ||
468 | might_sleep(); | 469 | might_sleep(); |
469 | 470 | ||
470 | offset = dma64 ? B43_DMA64_RXCTL : B43_DMA32_RXCTL; | 471 | offset = (type == B43_DMA_64BIT) ? B43_DMA64_RXCTL : B43_DMA32_RXCTL; |
471 | b43_write32(dev, mmio_base + offset, 0); | 472 | b43_write32(dev, mmio_base + offset, 0); |
472 | for (i = 0; i < 10; i++) { | 473 | for (i = 0; i < 10; i++) { |
473 | offset = dma64 ? B43_DMA64_RXSTATUS : B43_DMA32_RXSTATUS; | 474 | offset = (type == B43_DMA_64BIT) ? B43_DMA64_RXSTATUS : |
475 | B43_DMA32_RXSTATUS; | ||
474 | value = b43_read32(dev, mmio_base + offset); | 476 | value = b43_read32(dev, mmio_base + offset); |
475 | if (dma64) { | 477 | if (type == B43_DMA_64BIT) { |
476 | value &= B43_DMA64_RXSTAT; | 478 | value &= B43_DMA64_RXSTAT; |
477 | if (value == B43_DMA64_RXSTAT_DISABLED) { | 479 | if (value == B43_DMA64_RXSTAT_DISABLED) { |
478 | i = -1; | 480 | i = -1; |
@@ -496,7 +498,8 @@ int b43_dmacontroller_rx_reset(struct b43_wldev *dev, u16 mmio_base, int dma64) | |||
496 | } | 498 | } |
497 | 499 | ||
498 | /* Reset the TX DMA channel */ | 500 | /* Reset the TX DMA channel */ |
499 | int b43_dmacontroller_tx_reset(struct b43_wldev *dev, u16 mmio_base, int dma64) | 501 | static int b43_dmacontroller_tx_reset(struct b43_wldev *dev, u16 mmio_base, |
502 | enum b43_dmatype type) | ||
500 | { | 503 | { |
501 | int i; | 504 | int i; |
502 | u32 value; | 505 | u32 value; |
@@ -505,9 +508,10 @@ int b43_dmacontroller_tx_reset(struct b43_wldev *dev, u16 mmio_base, int dma64) | |||
505 | might_sleep(); | 508 | might_sleep(); |
506 | 509 | ||
507 | for (i = 0; i < 10; i++) { | 510 | for (i = 0; i < 10; i++) { |
508 | offset = dma64 ? B43_DMA64_TXSTATUS : B43_DMA32_TXSTATUS; | 511 | offset = (type == B43_DMA_64BIT) ? B43_DMA64_TXSTATUS : |
512 | B43_DMA32_TXSTATUS; | ||
509 | value = b43_read32(dev, mmio_base + offset); | 513 | value = b43_read32(dev, mmio_base + offset); |
510 | if (dma64) { | 514 | if (type == B43_DMA_64BIT) { |
511 | value &= B43_DMA64_TXSTAT; | 515 | value &= B43_DMA64_TXSTAT; |
512 | if (value == B43_DMA64_TXSTAT_DISABLED || | 516 | if (value == B43_DMA64_TXSTAT_DISABLED || |
513 | value == B43_DMA64_TXSTAT_IDLEWAIT || | 517 | value == B43_DMA64_TXSTAT_IDLEWAIT || |
@@ -522,12 +526,13 @@ int b43_dmacontroller_tx_reset(struct b43_wldev *dev, u16 mmio_base, int dma64) | |||
522 | } | 526 | } |
523 | msleep(1); | 527 | msleep(1); |
524 | } | 528 | } |
525 | offset = dma64 ? B43_DMA64_TXCTL : B43_DMA32_TXCTL; | 529 | offset = (type == B43_DMA_64BIT) ? B43_DMA64_TXCTL : B43_DMA32_TXCTL; |
526 | b43_write32(dev, mmio_base + offset, 0); | 530 | b43_write32(dev, mmio_base + offset, 0); |
527 | for (i = 0; i < 10; i++) { | 531 | for (i = 0; i < 10; i++) { |
528 | offset = dma64 ? B43_DMA64_TXSTATUS : B43_DMA32_TXSTATUS; | 532 | offset = (type == B43_DMA_64BIT) ? B43_DMA64_TXSTATUS : |
533 | B43_DMA32_TXSTATUS; | ||
529 | value = b43_read32(dev, mmio_base + offset); | 534 | value = b43_read32(dev, mmio_base + offset); |
530 | if (dma64) { | 535 | if (type == B43_DMA_64BIT) { |
531 | value &= B43_DMA64_TXSTAT; | 536 | value &= B43_DMA64_TXSTAT; |
532 | if (value == B43_DMA64_TXSTAT_DISABLED) { | 537 | if (value == B43_DMA64_TXSTAT_DISABLED) { |
533 | i = -1; | 538 | i = -1; |
@@ -552,6 +557,33 @@ int b43_dmacontroller_tx_reset(struct b43_wldev *dev, u16 mmio_base, int dma64) | |||
552 | return 0; | 557 | return 0; |
553 | } | 558 | } |
554 | 559 | ||
560 | /* Check if a DMA mapping address is invalid. */ | ||
561 | static bool b43_dma_mapping_error(struct b43_dmaring *ring, | ||
562 | dma_addr_t addr, | ||
563 | size_t buffersize) | ||
564 | { | ||
565 | if (unlikely(dma_mapping_error(addr))) | ||
566 | return 1; | ||
567 | |||
568 | switch (ring->type) { | ||
569 | case B43_DMA_30BIT: | ||
570 | if ((u64)addr + buffersize > (1ULL << 30)) | ||
571 | return 1; | ||
572 | break; | ||
573 | case B43_DMA_32BIT: | ||
574 | if ((u64)addr + buffersize > (1ULL << 32)) | ||
575 | return 1; | ||
576 | break; | ||
577 | case B43_DMA_64BIT: | ||
578 | /* Currently we can't have addresses beyond | ||
579 | * 64bit in the kernel. */ | ||
580 | break; | ||
581 | } | ||
582 | |||
583 | /* The address is OK. */ | ||
584 | return 0; | ||
585 | } | ||
586 | |||
555 | static int setup_rx_descbuffer(struct b43_dmaring *ring, | 587 | static int setup_rx_descbuffer(struct b43_dmaring *ring, |
556 | struct b43_dmadesc_generic *desc, | 588 | struct b43_dmadesc_generic *desc, |
557 | struct b43_dmadesc_meta *meta, gfp_t gfp_flags) | 589 | struct b43_dmadesc_meta *meta, gfp_t gfp_flags) |
@@ -567,7 +599,7 @@ static int setup_rx_descbuffer(struct b43_dmaring *ring, | |||
567 | if (unlikely(!skb)) | 599 | if (unlikely(!skb)) |
568 | return -ENOMEM; | 600 | return -ENOMEM; |
569 | dmaaddr = map_descbuffer(ring, skb->data, ring->rx_buffersize, 0); | 601 | dmaaddr = map_descbuffer(ring, skb->data, ring->rx_buffersize, 0); |
570 | if (dma_mapping_error(dmaaddr)) { | 602 | if (b43_dma_mapping_error(ring, dmaaddr, ring->rx_buffersize)) { |
571 | /* ugh. try to realloc in zone_dma */ | 603 | /* ugh. try to realloc in zone_dma */ |
572 | gfp_flags |= GFP_DMA; | 604 | gfp_flags |= GFP_DMA; |
573 | 605 | ||
@@ -580,7 +612,7 @@ static int setup_rx_descbuffer(struct b43_dmaring *ring, | |||
580 | ring->rx_buffersize, 0); | 612 | ring->rx_buffersize, 0); |
581 | } | 613 | } |
582 | 614 | ||
583 | if (dma_mapping_error(dmaaddr)) { | 615 | if (b43_dma_mapping_error(ring, dmaaddr, ring->rx_buffersize)) { |
584 | dev_kfree_skb_any(skb); | 616 | dev_kfree_skb_any(skb); |
585 | return -EIO; | 617 | return -EIO; |
586 | } | 618 | } |
@@ -645,7 +677,7 @@ static int dmacontroller_setup(struct b43_dmaring *ring) | |||
645 | u32 trans = ssb_dma_translation(ring->dev->dev); | 677 | u32 trans = ssb_dma_translation(ring->dev->dev); |
646 | 678 | ||
647 | if (ring->tx) { | 679 | if (ring->tx) { |
648 | if (ring->dma64) { | 680 | if (ring->type == B43_DMA_64BIT) { |
649 | u64 ringbase = (u64) (ring->dmabase); | 681 | u64 ringbase = (u64) (ring->dmabase); |
650 | 682 | ||
651 | addrext = ((ringbase >> 32) & SSB_DMA_TRANSLATION_MASK) | 683 | addrext = ((ringbase >> 32) & SSB_DMA_TRANSLATION_MASK) |
@@ -677,7 +709,7 @@ static int dmacontroller_setup(struct b43_dmaring *ring) | |||
677 | err = alloc_initial_descbuffers(ring); | 709 | err = alloc_initial_descbuffers(ring); |
678 | if (err) | 710 | if (err) |
679 | goto out; | 711 | goto out; |
680 | if (ring->dma64) { | 712 | if (ring->type == B43_DMA_64BIT) { |
681 | u64 ringbase = (u64) (ring->dmabase); | 713 | u64 ringbase = (u64) (ring->dmabase); |
682 | 714 | ||
683 | addrext = ((ringbase >> 32) & SSB_DMA_TRANSLATION_MASK) | 715 | addrext = ((ringbase >> 32) & SSB_DMA_TRANSLATION_MASK) |
@@ -722,16 +754,16 @@ static void dmacontroller_cleanup(struct b43_dmaring *ring) | |||
722 | { | 754 | { |
723 | if (ring->tx) { | 755 | if (ring->tx) { |
724 | b43_dmacontroller_tx_reset(ring->dev, ring->mmio_base, | 756 | b43_dmacontroller_tx_reset(ring->dev, ring->mmio_base, |
725 | ring->dma64); | 757 | ring->type); |
726 | if (ring->dma64) { | 758 | if (ring->type == B43_DMA_64BIT) { |
727 | b43_dma_write(ring, B43_DMA64_TXRINGLO, 0); | 759 | b43_dma_write(ring, B43_DMA64_TXRINGLO, 0); |
728 | b43_dma_write(ring, B43_DMA64_TXRINGHI, 0); | 760 | b43_dma_write(ring, B43_DMA64_TXRINGHI, 0); |
729 | } else | 761 | } else |
730 | b43_dma_write(ring, B43_DMA32_TXRING, 0); | 762 | b43_dma_write(ring, B43_DMA32_TXRING, 0); |
731 | } else { | 763 | } else { |
732 | b43_dmacontroller_rx_reset(ring->dev, ring->mmio_base, | 764 | b43_dmacontroller_rx_reset(ring->dev, ring->mmio_base, |
733 | ring->dma64); | 765 | ring->type); |
734 | if (ring->dma64) { | 766 | if (ring->type == B43_DMA_64BIT) { |
735 | b43_dma_write(ring, B43_DMA64_RXRINGLO, 0); | 767 | b43_dma_write(ring, B43_DMA64_RXRINGLO, 0); |
736 | b43_dma_write(ring, B43_DMA64_RXRINGHI, 0); | 768 | b43_dma_write(ring, B43_DMA64_RXRINGHI, 0); |
737 | } else | 769 | } else |
@@ -786,7 +818,8 @@ static u64 supported_dma_mask(struct b43_wldev *dev) | |||
786 | static | 818 | static |
787 | struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev, | 819 | struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev, |
788 | int controller_index, | 820 | int controller_index, |
789 | int for_tx, int dma64) | 821 | int for_tx, |
822 | enum b43_dmatype type) | ||
790 | { | 823 | { |
791 | struct b43_dmaring *ring; | 824 | struct b43_dmaring *ring; |
792 | int err; | 825 | int err; |
@@ -796,6 +829,7 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev, | |||
796 | ring = kzalloc(sizeof(*ring), GFP_KERNEL); | 829 | ring = kzalloc(sizeof(*ring), GFP_KERNEL); |
797 | if (!ring) | 830 | if (!ring) |
798 | goto out; | 831 | goto out; |
832 | ring->type = type; | ||
799 | 833 | ||
800 | nr_slots = B43_RXRING_SLOTS; | 834 | nr_slots = B43_RXRING_SLOTS; |
801 | if (for_tx) | 835 | if (for_tx) |
@@ -818,7 +852,7 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev, | |||
818 | b43_txhdr_size(dev), | 852 | b43_txhdr_size(dev), |
819 | DMA_TO_DEVICE); | 853 | DMA_TO_DEVICE); |
820 | 854 | ||
821 | if (dma_mapping_error(dma_test)) { | 855 | if (b43_dma_mapping_error(ring, dma_test, b43_txhdr_size(dev))) { |
822 | /* ugh realloc */ | 856 | /* ugh realloc */ |
823 | kfree(ring->txhdr_cache); | 857 | kfree(ring->txhdr_cache); |
824 | ring->txhdr_cache = kcalloc(nr_slots, | 858 | ring->txhdr_cache = kcalloc(nr_slots, |
@@ -832,7 +866,8 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev, | |||
832 | b43_txhdr_size(dev), | 866 | b43_txhdr_size(dev), |
833 | DMA_TO_DEVICE); | 867 | DMA_TO_DEVICE); |
834 | 868 | ||
835 | if (dma_mapping_error(dma_test)) | 869 | if (b43_dma_mapping_error(ring, dma_test, |
870 | b43_txhdr_size(dev))) | ||
836 | goto err_kfree_txhdr_cache; | 871 | goto err_kfree_txhdr_cache; |
837 | } | 872 | } |
838 | 873 | ||
@@ -843,10 +878,9 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev, | |||
843 | 878 | ||
844 | ring->dev = dev; | 879 | ring->dev = dev; |
845 | ring->nr_slots = nr_slots; | 880 | ring->nr_slots = nr_slots; |
846 | ring->mmio_base = b43_dmacontroller_base(dma64, controller_index); | 881 | ring->mmio_base = b43_dmacontroller_base(type, controller_index); |
847 | ring->index = controller_index; | 882 | ring->index = controller_index; |
848 | ring->dma64 = !!dma64; | 883 | if (type == B43_DMA_64BIT) |
849 | if (dma64) | ||
850 | ring->ops = &dma64_ops; | 884 | ring->ops = &dma64_ops; |
851 | else | 885 | else |
852 | ring->ops = &dma32_ops; | 886 | ring->ops = &dma32_ops; |
@@ -896,8 +930,8 @@ static void b43_destroy_dmaring(struct b43_dmaring *ring) | |||
896 | if (!ring) | 930 | if (!ring) |
897 | return; | 931 | return; |
898 | 932 | ||
899 | b43dbg(ring->dev->wl, "DMA-%s 0x%04X (%s) max used slots: %d/%d\n", | 933 | b43dbg(ring->dev->wl, "DMA-%u 0x%04X (%s) max used slots: %d/%d\n", |
900 | (ring->dma64) ? "64" : "32", | 934 | (unsigned int)(ring->type), |
901 | ring->mmio_base, | 935 | ring->mmio_base, |
902 | (ring->tx) ? "TX" : "RX", ring->max_used_slots, ring->nr_slots); | 936 | (ring->tx) ? "TX" : "RX", ring->max_used_slots, ring->nr_slots); |
903 | /* Device IRQs are disabled prior entering this function, | 937 | /* Device IRQs are disabled prior entering this function, |
@@ -941,12 +975,22 @@ int b43_dma_init(struct b43_wldev *dev) | |||
941 | struct b43_dmaring *ring; | 975 | struct b43_dmaring *ring; |
942 | int err; | 976 | int err; |
943 | u64 dmamask; | 977 | u64 dmamask; |
944 | int dma64 = 0; | 978 | enum b43_dmatype type; |
945 | 979 | ||
946 | dmamask = supported_dma_mask(dev); | 980 | dmamask = supported_dma_mask(dev); |
947 | if (dmamask == DMA_64BIT_MASK) | 981 | switch (dmamask) { |
948 | dma64 = 1; | 982 | default: |
949 | 983 | B43_WARN_ON(1); | |
984 | case DMA_30BIT_MASK: | ||
985 | type = B43_DMA_30BIT; | ||
986 | break; | ||
987 | case DMA_32BIT_MASK: | ||
988 | type = B43_DMA_32BIT; | ||
989 | break; | ||
990 | case DMA_64BIT_MASK: | ||
991 | type = B43_DMA_64BIT; | ||
992 | break; | ||
993 | } | ||
950 | err = ssb_dma_set_mask(dev->dev, dmamask); | 994 | err = ssb_dma_set_mask(dev->dev, dmamask); |
951 | if (err) { | 995 | if (err) { |
952 | b43err(dev->wl, "The machine/kernel does not support " | 996 | b43err(dev->wl, "The machine/kernel does not support " |
@@ -958,52 +1002,51 @@ int b43_dma_init(struct b43_wldev *dev) | |||
958 | 1002 | ||
959 | err = -ENOMEM; | 1003 | err = -ENOMEM; |
960 | /* setup TX DMA channels. */ | 1004 | /* setup TX DMA channels. */ |
961 | ring = b43_setup_dmaring(dev, 0, 1, dma64); | 1005 | ring = b43_setup_dmaring(dev, 0, 1, type); |
962 | if (!ring) | 1006 | if (!ring) |
963 | goto out; | 1007 | goto out; |
964 | dma->tx_ring0 = ring; | 1008 | dma->tx_ring0 = ring; |
965 | 1009 | ||
966 | ring = b43_setup_dmaring(dev, 1, 1, dma64); | 1010 | ring = b43_setup_dmaring(dev, 1, 1, type); |
967 | if (!ring) | 1011 | if (!ring) |
968 | goto err_destroy_tx0; | 1012 | goto err_destroy_tx0; |
969 | dma->tx_ring1 = ring; | 1013 | dma->tx_ring1 = ring; |
970 | 1014 | ||
971 | ring = b43_setup_dmaring(dev, 2, 1, dma64); | 1015 | ring = b43_setup_dmaring(dev, 2, 1, type); |
972 | if (!ring) | 1016 | if (!ring) |
973 | goto err_destroy_tx1; | 1017 | goto err_destroy_tx1; |
974 | dma->tx_ring2 = ring; | 1018 | dma->tx_ring2 = ring; |
975 | 1019 | ||
976 | ring = b43_setup_dmaring(dev, 3, 1, dma64); | 1020 | ring = b43_setup_dmaring(dev, 3, 1, type); |
977 | if (!ring) | 1021 | if (!ring) |
978 | goto err_destroy_tx2; | 1022 | goto err_destroy_tx2; |
979 | dma->tx_ring3 = ring; | 1023 | dma->tx_ring3 = ring; |
980 | 1024 | ||
981 | ring = b43_setup_dmaring(dev, 4, 1, dma64); | 1025 | ring = b43_setup_dmaring(dev, 4, 1, type); |
982 | if (!ring) | 1026 | if (!ring) |
983 | goto err_destroy_tx3; | 1027 | goto err_destroy_tx3; |
984 | dma->tx_ring4 = ring; | 1028 | dma->tx_ring4 = ring; |
985 | 1029 | ||
986 | ring = b43_setup_dmaring(dev, 5, 1, dma64); | 1030 | ring = b43_setup_dmaring(dev, 5, 1, type); |
987 | if (!ring) | 1031 | if (!ring) |
988 | goto err_destroy_tx4; | 1032 | goto err_destroy_tx4; |
989 | dma->tx_ring5 = ring; | 1033 | dma->tx_ring5 = ring; |
990 | 1034 | ||
991 | /* setup RX DMA channels. */ | 1035 | /* setup RX DMA channels. */ |
992 | ring = b43_setup_dmaring(dev, 0, 0, dma64); | 1036 | ring = b43_setup_dmaring(dev, 0, 0, type); |
993 | if (!ring) | 1037 | if (!ring) |
994 | goto err_destroy_tx5; | 1038 | goto err_destroy_tx5; |
995 | dma->rx_ring0 = ring; | 1039 | dma->rx_ring0 = ring; |
996 | 1040 | ||
997 | if (dev->dev->id.revision < 5) { | 1041 | if (dev->dev->id.revision < 5) { |
998 | ring = b43_setup_dmaring(dev, 3, 0, dma64); | 1042 | ring = b43_setup_dmaring(dev, 3, 0, type); |
999 | if (!ring) | 1043 | if (!ring) |
1000 | goto err_destroy_rx0; | 1044 | goto err_destroy_rx0; |
1001 | dma->rx_ring3 = ring; | 1045 | dma->rx_ring3 = ring; |
1002 | } | 1046 | } |
1003 | 1047 | ||
1004 | b43dbg(dev->wl, "%d-bit DMA initialized\n", | 1048 | b43dbg(dev->wl, "%u-bit DMA initialized\n", |
1005 | (dmamask == DMA_64BIT_MASK) ? 64 : | 1049 | (unsigned int)type); |
1006 | (dmamask == DMA_32BIT_MASK) ? 32 : 30); | ||
1007 | err = 0; | 1050 | err = 0; |
1008 | out: | 1051 | out: |
1009 | return err; | 1052 | return err; |
@@ -1146,7 +1189,7 @@ static int dma_tx_fragment(struct b43_dmaring *ring, | |||
1146 | 1189 | ||
1147 | meta_hdr->dmaaddr = map_descbuffer(ring, (unsigned char *)header, | 1190 | meta_hdr->dmaaddr = map_descbuffer(ring, (unsigned char *)header, |
1148 | hdrsize, 1); | 1191 | hdrsize, 1); |
1149 | if (dma_mapping_error(meta_hdr->dmaaddr)) { | 1192 | if (b43_dma_mapping_error(ring, meta_hdr->dmaaddr, hdrsize)) { |
1150 | ring->current_slot = old_top_slot; | 1193 | ring->current_slot = old_top_slot; |
1151 | ring->used_slots = old_used_slots; | 1194 | ring->used_slots = old_used_slots; |
1152 | return -EIO; | 1195 | return -EIO; |
@@ -1165,7 +1208,7 @@ static int dma_tx_fragment(struct b43_dmaring *ring, | |||
1165 | 1208 | ||
1166 | meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1); | 1209 | meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1); |
1167 | /* create a bounce buffer in zone_dma on mapping failure. */ | 1210 | /* create a bounce buffer in zone_dma on mapping failure. */ |
1168 | if (dma_mapping_error(meta->dmaaddr)) { | 1211 | if (b43_dma_mapping_error(ring, meta->dmaaddr, skb->len)) { |
1169 | bounce_skb = __dev_alloc_skb(skb->len, GFP_ATOMIC | GFP_DMA); | 1212 | bounce_skb = __dev_alloc_skb(skb->len, GFP_ATOMIC | GFP_DMA); |
1170 | if (!bounce_skb) { | 1213 | if (!bounce_skb) { |
1171 | ring->current_slot = old_top_slot; | 1214 | ring->current_slot = old_top_slot; |
@@ -1179,7 +1222,7 @@ static int dma_tx_fragment(struct b43_dmaring *ring, | |||
1179 | skb = bounce_skb; | 1222 | skb = bounce_skb; |
1180 | meta->skb = skb; | 1223 | meta->skb = skb; |
1181 | meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1); | 1224 | meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1); |
1182 | if (dma_mapping_error(meta->dmaaddr)) { | 1225 | if (b43_dma_mapping_error(ring, meta->dmaaddr, skb->len)) { |
1183 | ring->current_slot = old_top_slot; | 1226 | ring->current_slot = old_top_slot; |
1184 | ring->used_slots = old_used_slots; | 1227 | ring->used_slots = old_used_slots; |
1185 | err = -EIO; | 1228 | err = -EIO; |
diff --git a/drivers/net/wireless/b43/dma.h b/drivers/net/wireless/b43/dma.h index 58db03ac536e..c0d6b69e6501 100644 --- a/drivers/net/wireless/b43/dma.h +++ b/drivers/net/wireless/b43/dma.h | |||
@@ -203,6 +203,12 @@ struct b43_dma_ops { | |||
203 | void (*set_current_rxslot) (struct b43_dmaring * ring, int slot); | 203 | void (*set_current_rxslot) (struct b43_dmaring * ring, int slot); |
204 | }; | 204 | }; |
205 | 205 | ||
206 | enum b43_dmatype { | ||
207 | B43_DMA_30BIT = 30, | ||
208 | B43_DMA_32BIT = 32, | ||
209 | B43_DMA_64BIT = 64, | ||
210 | }; | ||
211 | |||
206 | struct b43_dmaring { | 212 | struct b43_dmaring { |
207 | /* Lowlevel DMA ops. */ | 213 | /* Lowlevel DMA ops. */ |
208 | const struct b43_dma_ops *ops; | 214 | const struct b43_dma_ops *ops; |
@@ -235,8 +241,8 @@ struct b43_dmaring { | |||
235 | int index; | 241 | int index; |
236 | /* Boolean. Is this a TX ring? */ | 242 | /* Boolean. Is this a TX ring? */ |
237 | bool tx; | 243 | bool tx; |
238 | /* Boolean. 64bit DMA if true, 32bit DMA otherwise. */ | 244 | /* The type of DMA engine used. */ |
239 | bool dma64; | 245 | enum b43_dmatype type; |
240 | /* Boolean. Is this ring stopped at ieee80211 level? */ | 246 | /* Boolean. Is this ring stopped at ieee80211 level? */ |
241 | bool stopped; | 247 | bool stopped; |
242 | /* Lock, only used for TX. */ | 248 | /* Lock, only used for TX. */ |
@@ -255,8 +261,7 @@ static inline u32 b43_dma_read(struct b43_dmaring *ring, u16 offset) | |||
255 | return b43_read32(ring->dev, ring->mmio_base + offset); | 261 | return b43_read32(ring->dev, ring->mmio_base + offset); |
256 | } | 262 | } |
257 | 263 | ||
258 | static inline | 264 | static inline void b43_dma_write(struct b43_dmaring *ring, u16 offset, u32 value) |
259 | void b43_dma_write(struct b43_dmaring *ring, u16 offset, u32 value) | ||
260 | { | 265 | { |
261 | b43_write32(ring->dev, ring->mmio_base + offset, value); | 266 | b43_write32(ring->dev, ring->mmio_base + offset, value); |
262 | } | 267 | } |
@@ -264,13 +269,6 @@ static inline | |||
264 | int b43_dma_init(struct b43_wldev *dev); | 269 | int b43_dma_init(struct b43_wldev *dev); |
265 | void b43_dma_free(struct b43_wldev *dev); | 270 | void b43_dma_free(struct b43_wldev *dev); |
266 | 271 | ||
267 | int b43_dmacontroller_rx_reset(struct b43_wldev *dev, | ||
268 | u16 dmacontroller_mmio_base, int dma64); | ||
269 | int b43_dmacontroller_tx_reset(struct b43_wldev *dev, | ||
270 | u16 dmacontroller_mmio_base, int dma64); | ||
271 | |||
272 | u16 b43_dmacontroller_base(int dma64bit, int dmacontroller_idx); | ||
273 | |||
274 | void b43_dma_tx_suspend(struct b43_wldev *dev); | 272 | void b43_dma_tx_suspend(struct b43_wldev *dev); |
275 | void b43_dma_tx_resume(struct b43_wldev *dev); | 273 | void b43_dma_tx_resume(struct b43_wldev *dev); |
276 | 274 | ||
diff --git a/drivers/net/wireless/b43legacy/dma.c b/drivers/net/wireless/b43legacy/dma.c index 83161d9af813..6e08405e8026 100644 --- a/drivers/net/wireless/b43legacy/dma.c +++ b/drivers/net/wireless/b43legacy/dma.c | |||
@@ -1164,7 +1164,7 @@ static int dma_tx_fragment(struct b43legacy_dmaring *ring, | |||
1164 | { | 1164 | { |
1165 | const struct b43legacy_dma_ops *ops = ring->ops; | 1165 | const struct b43legacy_dma_ops *ops = ring->ops; |
1166 | u8 *header; | 1166 | u8 *header; |
1167 | int slot; | 1167 | int slot, old_top_slot, old_used_slots; |
1168 | int err; | 1168 | int err; |
1169 | struct b43legacy_dmadesc_generic *desc; | 1169 | struct b43legacy_dmadesc_generic *desc; |
1170 | struct b43legacy_dmadesc_meta *meta; | 1170 | struct b43legacy_dmadesc_meta *meta; |
@@ -1174,6 +1174,9 @@ static int dma_tx_fragment(struct b43legacy_dmaring *ring, | |||
1174 | #define SLOTS_PER_PACKET 2 | 1174 | #define SLOTS_PER_PACKET 2 |
1175 | B43legacy_WARN_ON(skb_shinfo(skb)->nr_frags != 0); | 1175 | B43legacy_WARN_ON(skb_shinfo(skb)->nr_frags != 0); |
1176 | 1176 | ||
1177 | old_top_slot = ring->current_slot; | ||
1178 | old_used_slots = ring->used_slots; | ||
1179 | |||
1177 | /* Get a slot for the header. */ | 1180 | /* Get a slot for the header. */ |
1178 | slot = request_slot(ring); | 1181 | slot = request_slot(ring); |
1179 | desc = ops->idx2desc(ring, slot, &meta_hdr); | 1182 | desc = ops->idx2desc(ring, slot, &meta_hdr); |
@@ -1181,9 +1184,14 @@ static int dma_tx_fragment(struct b43legacy_dmaring *ring, | |||
1181 | 1184 | ||
1182 | header = &(ring->txhdr_cache[slot * sizeof( | 1185 | header = &(ring->txhdr_cache[slot * sizeof( |
1183 | struct b43legacy_txhdr_fw3)]); | 1186 | struct b43legacy_txhdr_fw3)]); |
1184 | b43legacy_generate_txhdr(ring->dev, header, | 1187 | err = b43legacy_generate_txhdr(ring->dev, header, |
1185 | skb->data, skb->len, ctl, | 1188 | skb->data, skb->len, ctl, |
1186 | generate_cookie(ring, slot)); | 1189 | generate_cookie(ring, slot)); |
1190 | if (unlikely(err)) { | ||
1191 | ring->current_slot = old_top_slot; | ||
1192 | ring->used_slots = old_used_slots; | ||
1193 | return err; | ||
1194 | } | ||
1187 | 1195 | ||
1188 | meta_hdr->dmaaddr = map_descbuffer(ring, (unsigned char *)header, | 1196 | meta_hdr->dmaaddr = map_descbuffer(ring, (unsigned char *)header, |
1189 | sizeof(struct b43legacy_txhdr_fw3), 1); | 1197 | sizeof(struct b43legacy_txhdr_fw3), 1); |
@@ -1206,6 +1214,8 @@ static int dma_tx_fragment(struct b43legacy_dmaring *ring, | |||
1206 | if (dma_mapping_error(meta->dmaaddr)) { | 1214 | if (dma_mapping_error(meta->dmaaddr)) { |
1207 | bounce_skb = __dev_alloc_skb(skb->len, GFP_ATOMIC | GFP_DMA); | 1215 | bounce_skb = __dev_alloc_skb(skb->len, GFP_ATOMIC | GFP_DMA); |
1208 | if (!bounce_skb) { | 1216 | if (!bounce_skb) { |
1217 | ring->current_slot = old_top_slot; | ||
1218 | ring->used_slots = old_used_slots; | ||
1209 | err = -ENOMEM; | 1219 | err = -ENOMEM; |
1210 | goto out_unmap_hdr; | 1220 | goto out_unmap_hdr; |
1211 | } | 1221 | } |
@@ -1216,6 +1226,8 @@ static int dma_tx_fragment(struct b43legacy_dmaring *ring, | |||
1216 | meta->skb = skb; | 1226 | meta->skb = skb; |
1217 | meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1); | 1227 | meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1); |
1218 | if (dma_mapping_error(meta->dmaaddr)) { | 1228 | if (dma_mapping_error(meta->dmaaddr)) { |
1229 | ring->current_slot = old_top_slot; | ||
1230 | ring->used_slots = old_used_slots; | ||
1219 | err = -EIO; | 1231 | err = -EIO; |
1220 | goto out_free_bounce; | 1232 | goto out_free_bounce; |
1221 | } | 1233 | } |
@@ -1282,6 +1294,13 @@ int b43legacy_dma_tx(struct b43legacy_wldev *dev, | |||
1282 | B43legacy_BUG_ON(ring->stopped); | 1294 | B43legacy_BUG_ON(ring->stopped); |
1283 | 1295 | ||
1284 | err = dma_tx_fragment(ring, skb, ctl); | 1296 | err = dma_tx_fragment(ring, skb, ctl); |
1297 | if (unlikely(err == -ENOKEY)) { | ||
1298 | /* Drop this packet, as we don't have the encryption key | ||
1299 | * anymore and must not transmit it unencrypted. */ | ||
1300 | dev_kfree_skb_any(skb); | ||
1301 | err = 0; | ||
1302 | goto out_unlock; | ||
1303 | } | ||
1285 | if (unlikely(err)) { | 1304 | if (unlikely(err)) { |
1286 | b43legacyerr(dev->wl, "DMA tx mapping failure\n"); | 1305 | b43legacyerr(dev->wl, "DMA tx mapping failure\n"); |
1287 | goto out_unlock; | 1306 | goto out_unlock; |
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index aa20d5d56e2f..53f7f2e97615 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c | |||
@@ -3160,8 +3160,6 @@ static int b43legacy_wireless_core_init(struct b43legacy_wldev *dev) | |||
3160 | b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x0414, 0x01F4); | 3160 | b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x0414, 0x01F4); |
3161 | 3161 | ||
3162 | ssb_bus_powerup(bus, 1); /* Enable dynamic PCTL */ | 3162 | ssb_bus_powerup(bus, 1); /* Enable dynamic PCTL */ |
3163 | memset(wl->bssid, 0, ETH_ALEN); | ||
3164 | memset(wl->mac_addr, 0, ETH_ALEN); | ||
3165 | b43legacy_upload_card_macaddress(dev); | 3163 | b43legacy_upload_card_macaddress(dev); |
3166 | b43legacy_security_init(dev); | 3164 | b43legacy_security_init(dev); |
3167 | b43legacy_rng_init(wl); | 3165 | b43legacy_rng_init(wl); |
@@ -3263,6 +3261,13 @@ static int b43legacy_op_start(struct ieee80211_hw *hw) | |||
3263 | * LEDs that are registered later depend on it. */ | 3261 | * LEDs that are registered later depend on it. */ |
3264 | b43legacy_rfkill_init(dev); | 3262 | b43legacy_rfkill_init(dev); |
3265 | 3263 | ||
3264 | /* Kill all old instance specific information to make sure | ||
3265 | * the card won't use it in the short timeframe between start | ||
3266 | * and mac80211 reconfiguring it. */ | ||
3267 | memset(wl->bssid, 0, ETH_ALEN); | ||
3268 | memset(wl->mac_addr, 0, ETH_ALEN); | ||
3269 | wl->filter_flags = 0; | ||
3270 | |||
3266 | mutex_lock(&wl->mutex); | 3271 | mutex_lock(&wl->mutex); |
3267 | 3272 | ||
3268 | if (b43legacy_status(dev) < B43legacy_STAT_INITIALIZED) { | 3273 | if (b43legacy_status(dev) < B43legacy_STAT_INITIALIZED) { |
diff --git a/drivers/net/wireless/b43legacy/pio.c b/drivers/net/wireless/b43legacy/pio.c index e4f4c5c39e33..bcdd54eb2edb 100644 --- a/drivers/net/wireless/b43legacy/pio.c +++ b/drivers/net/wireless/b43legacy/pio.c | |||
@@ -181,7 +181,7 @@ union txhdr_union { | |||
181 | struct b43legacy_txhdr_fw3 txhdr_fw3; | 181 | struct b43legacy_txhdr_fw3 txhdr_fw3; |
182 | }; | 182 | }; |
183 | 183 | ||
184 | static void pio_tx_write_fragment(struct b43legacy_pioqueue *queue, | 184 | static int pio_tx_write_fragment(struct b43legacy_pioqueue *queue, |
185 | struct sk_buff *skb, | 185 | struct sk_buff *skb, |
186 | struct b43legacy_pio_txpacket *packet, | 186 | struct b43legacy_pio_txpacket *packet, |
187 | size_t txhdr_size) | 187 | size_t txhdr_size) |
@@ -189,14 +189,17 @@ static void pio_tx_write_fragment(struct b43legacy_pioqueue *queue, | |||
189 | union txhdr_union txhdr_data; | 189 | union txhdr_union txhdr_data; |
190 | u8 *txhdr = NULL; | 190 | u8 *txhdr = NULL; |
191 | unsigned int octets; | 191 | unsigned int octets; |
192 | int err; | ||
192 | 193 | ||
193 | txhdr = (u8 *)(&txhdr_data.txhdr_fw3); | 194 | txhdr = (u8 *)(&txhdr_data.txhdr_fw3); |
194 | 195 | ||
195 | B43legacy_WARN_ON(skb_shinfo(skb)->nr_frags != 0); | 196 | B43legacy_WARN_ON(skb_shinfo(skb)->nr_frags != 0); |
196 | b43legacy_generate_txhdr(queue->dev, | 197 | err = b43legacy_generate_txhdr(queue->dev, |
197 | txhdr, skb->data, skb->len, | 198 | txhdr, skb->data, skb->len, |
198 | &packet->txstat.control, | 199 | &packet->txstat.control, |
199 | generate_cookie(queue, packet)); | 200 | generate_cookie(queue, packet)); |
201 | if (err) | ||
202 | return err; | ||
200 | 203 | ||
201 | tx_start(queue); | 204 | tx_start(queue); |
202 | octets = skb->len + txhdr_size; | 205 | octets = skb->len + txhdr_size; |
@@ -204,6 +207,8 @@ static void pio_tx_write_fragment(struct b43legacy_pioqueue *queue, | |||
204 | octets--; | 207 | octets--; |
205 | tx_data(queue, txhdr, (u8 *)skb->data, octets); | 208 | tx_data(queue, txhdr, (u8 *)skb->data, octets); |
206 | tx_complete(queue, skb); | 209 | tx_complete(queue, skb); |
210 | |||
211 | return 0; | ||
207 | } | 212 | } |
208 | 213 | ||
209 | static void free_txpacket(struct b43legacy_pio_txpacket *packet, | 214 | static void free_txpacket(struct b43legacy_pio_txpacket *packet, |
@@ -226,6 +231,7 @@ static int pio_tx_packet(struct b43legacy_pio_txpacket *packet) | |||
226 | struct b43legacy_pioqueue *queue = packet->queue; | 231 | struct b43legacy_pioqueue *queue = packet->queue; |
227 | struct sk_buff *skb = packet->skb; | 232 | struct sk_buff *skb = packet->skb; |
228 | u16 octets; | 233 | u16 octets; |
234 | int err; | ||
229 | 235 | ||
230 | octets = (u16)skb->len + sizeof(struct b43legacy_txhdr_fw3); | 236 | octets = (u16)skb->len + sizeof(struct b43legacy_txhdr_fw3); |
231 | if (queue->tx_devq_size < octets) { | 237 | if (queue->tx_devq_size < octets) { |
@@ -247,8 +253,14 @@ static int pio_tx_packet(struct b43legacy_pio_txpacket *packet) | |||
247 | if (queue->tx_devq_used + octets > queue->tx_devq_size) | 253 | if (queue->tx_devq_used + octets > queue->tx_devq_size) |
248 | return -EBUSY; | 254 | return -EBUSY; |
249 | /* Now poke the device. */ | 255 | /* Now poke the device. */ |
250 | pio_tx_write_fragment(queue, skb, packet, | 256 | err = pio_tx_write_fragment(queue, skb, packet, |
251 | sizeof(struct b43legacy_txhdr_fw3)); | 257 | sizeof(struct b43legacy_txhdr_fw3)); |
258 | if (unlikely(err == -ENOKEY)) { | ||
259 | /* Drop this packet, as we don't have the encryption key | ||
260 | * anymore and must not transmit it unencrypted. */ | ||
261 | free_txpacket(packet, 1); | ||
262 | return 0; | ||
263 | } | ||
252 | 264 | ||
253 | /* Account for the packet size. | 265 | /* Account for the packet size. |
254 | * (We must not overflow the device TX queue) | 266 | * (We must not overflow the device TX queue) |
@@ -486,6 +498,9 @@ void b43legacy_pio_handle_txstatus(struct b43legacy_wldev *dev, | |||
486 | queue = parse_cookie(dev, status->cookie, &packet); | 498 | queue = parse_cookie(dev, status->cookie, &packet); |
487 | B43legacy_WARN_ON(!queue); | 499 | B43legacy_WARN_ON(!queue); |
488 | 500 | ||
501 | if (!packet->skb) | ||
502 | return; | ||
503 | |||
489 | queue->tx_devq_packets--; | 504 | queue->tx_devq_packets--; |
490 | queue->tx_devq_used -= (packet->skb->len + | 505 | queue->tx_devq_used -= (packet->skb->len + |
491 | sizeof(struct b43legacy_txhdr_fw3)); | 506 | sizeof(struct b43legacy_txhdr_fw3)); |
diff --git a/drivers/net/wireless/b43legacy/xmit.c b/drivers/net/wireless/b43legacy/xmit.c index e20c552442d5..d84408a82db9 100644 --- a/drivers/net/wireless/b43legacy/xmit.c +++ b/drivers/net/wireless/b43legacy/xmit.c | |||
@@ -181,7 +181,7 @@ static u8 b43legacy_calc_fallback_rate(u8 bitrate) | |||
181 | return 0; | 181 | return 0; |
182 | } | 182 | } |
183 | 183 | ||
184 | static void generate_txhdr_fw3(struct b43legacy_wldev *dev, | 184 | static int generate_txhdr_fw3(struct b43legacy_wldev *dev, |
185 | struct b43legacy_txhdr_fw3 *txhdr, | 185 | struct b43legacy_txhdr_fw3 *txhdr, |
186 | const unsigned char *fragment_data, | 186 | const unsigned char *fragment_data, |
187 | unsigned int fragment_len, | 187 | unsigned int fragment_len, |
@@ -252,6 +252,13 @@ static void generate_txhdr_fw3(struct b43legacy_wldev *dev, | |||
252 | iv_len = min((size_t)txctl->iv_len, | 252 | iv_len = min((size_t)txctl->iv_len, |
253 | ARRAY_SIZE(txhdr->iv)); | 253 | ARRAY_SIZE(txhdr->iv)); |
254 | memcpy(txhdr->iv, ((u8 *)wlhdr) + wlhdr_len, iv_len); | 254 | memcpy(txhdr->iv, ((u8 *)wlhdr) + wlhdr_len, iv_len); |
255 | } else { | ||
256 | /* This key is invalid. This might only happen | ||
257 | * in a short timeframe after machine resume before | ||
258 | * we were able to reconfigure keys. | ||
259 | * Drop this packet completely. Do not transmit it | ||
260 | * unencrypted to avoid leaking information. */ | ||
261 | return -ENOKEY; | ||
255 | } | 262 | } |
256 | } | 263 | } |
257 | b43legacy_generate_plcp_hdr((struct b43legacy_plcp_hdr4 *) | 264 | b43legacy_generate_plcp_hdr((struct b43legacy_plcp_hdr4 *) |
@@ -345,16 +352,18 @@ static void generate_txhdr_fw3(struct b43legacy_wldev *dev, | |||
345 | /* Apply the bitfields */ | 352 | /* Apply the bitfields */ |
346 | txhdr->mac_ctl = cpu_to_le32(mac_ctl); | 353 | txhdr->mac_ctl = cpu_to_le32(mac_ctl); |
347 | txhdr->phy_ctl = cpu_to_le16(phy_ctl); | 354 | txhdr->phy_ctl = cpu_to_le16(phy_ctl); |
355 | |||
356 | return 0; | ||
348 | } | 357 | } |
349 | 358 | ||
350 | void b43legacy_generate_txhdr(struct b43legacy_wldev *dev, | 359 | int b43legacy_generate_txhdr(struct b43legacy_wldev *dev, |
351 | u8 *txhdr, | 360 | u8 *txhdr, |
352 | const unsigned char *fragment_data, | 361 | const unsigned char *fragment_data, |
353 | unsigned int fragment_len, | 362 | unsigned int fragment_len, |
354 | const struct ieee80211_tx_control *txctl, | 363 | const struct ieee80211_tx_control *txctl, |
355 | u16 cookie) | 364 | u16 cookie) |
356 | { | 365 | { |
357 | generate_txhdr_fw3(dev, (struct b43legacy_txhdr_fw3 *)txhdr, | 366 | return generate_txhdr_fw3(dev, (struct b43legacy_txhdr_fw3 *)txhdr, |
358 | fragment_data, fragment_len, | 367 | fragment_data, fragment_len, |
359 | txctl, cookie); | 368 | txctl, cookie); |
360 | } | 369 | } |
diff --git a/drivers/net/wireless/b43legacy/xmit.h b/drivers/net/wireless/b43legacy/xmit.h index 8a155d0a5d1f..bab47928a0c9 100644 --- a/drivers/net/wireless/b43legacy/xmit.h +++ b/drivers/net/wireless/b43legacy/xmit.h | |||
@@ -76,7 +76,7 @@ struct b43legacy_txhdr_fw3 { | |||
76 | 76 | ||
77 | 77 | ||
78 | 78 | ||
79 | void b43legacy_generate_txhdr(struct b43legacy_wldev *dev, | 79 | int b43legacy_generate_txhdr(struct b43legacy_wldev *dev, |
80 | u8 *txhdr, | 80 | u8 *txhdr, |
81 | const unsigned char *fragment_data, | 81 | const unsigned char *fragment_data, |
82 | unsigned int fragment_len, | 82 | unsigned int fragment_len, |
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index f55c75712b55..5ee1ad69898b 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c | |||
@@ -4207,13 +4207,13 @@ static u8 ratio2dB[100] = { | |||
4207 | * Conversion assumes that levels are voltages (20*log), not powers (10*log). */ | 4207 | * Conversion assumes that levels are voltages (20*log), not powers (10*log). */ |
4208 | int iwl3945_calc_db_from_ratio(int sig_ratio) | 4208 | int iwl3945_calc_db_from_ratio(int sig_ratio) |
4209 | { | 4209 | { |
4210 | /* Anything above 1000:1 just report as 60 dB */ | 4210 | /* 1000:1 or higher just report as 60 dB */ |
4211 | if (sig_ratio > 1000) | 4211 | if (sig_ratio >= 1000) |
4212 | return 60; | 4212 | return 60; |
4213 | 4213 | ||
4214 | /* Above 100:1, divide by 10 and use table, | 4214 | /* 100:1 or higher, divide by 10 and use table, |
4215 | * add 20 dB to make up for divide by 10 */ | 4215 | * add 20 dB to make up for divide by 10 */ |
4216 | if (sig_ratio > 100) | 4216 | if (sig_ratio >= 100) |
4217 | return (20 + (int)ratio2dB[sig_ratio/10]); | 4217 | return (20 + (int)ratio2dB[sig_ratio/10]); |
4218 | 4218 | ||
4219 | /* We shouldn't see this */ | 4219 | /* We shouldn't see this */ |
diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c index e9743d3efaf6..238628d3a854 100644 --- a/drivers/parport/parport_pc.c +++ b/drivers/parport/parport_pc.c | |||
@@ -1540,6 +1540,38 @@ static void __devinit detect_and_report_smsc (void) | |||
1540 | smsc_check(0x3f0,0x44); | 1540 | smsc_check(0x3f0,0x44); |
1541 | smsc_check(0x370,0x44); | 1541 | smsc_check(0x370,0x44); |
1542 | } | 1542 | } |
1543 | |||
1544 | static void __devinit detect_and_report_it87(void) | ||
1545 | { | ||
1546 | u16 dev; | ||
1547 | u8 r; | ||
1548 | if (verbose_probing) | ||
1549 | printk(KERN_DEBUG "IT8705 Super-IO detection, now testing port 2E ...\n"); | ||
1550 | if (!request_region(0x2e, 1, __FUNCTION__)) | ||
1551 | return; | ||
1552 | outb(0x87, 0x2e); | ||
1553 | outb(0x01, 0x2e); | ||
1554 | outb(0x55, 0x2e); | ||
1555 | outb(0x55, 0x2e); | ||
1556 | outb(0x20, 0x2e); | ||
1557 | dev = inb(0x2f) << 8; | ||
1558 | outb(0x21, 0x2e); | ||
1559 | dev |= inb(0x2f); | ||
1560 | if (dev == 0x8712 || dev == 0x8705 || dev == 0x8715 || | ||
1561 | dev == 0x8716 || dev == 0x8718 || dev == 0x8726) { | ||
1562 | printk(KERN_INFO "IT%04X SuperIO detected.\n", dev); | ||
1563 | outb(0x07, 0x2E); /* Parallel Port */ | ||
1564 | outb(0x03, 0x2F); | ||
1565 | outb(0xF0, 0x2E); /* BOOT 0x80 off */ | ||
1566 | r = inb(0x2f); | ||
1567 | outb(0xF0, 0x2E); | ||
1568 | outb(r | 8, 0x2F); | ||
1569 | outb(0x02, 0x2E); /* Lock */ | ||
1570 | outb(0x02, 0x2F); | ||
1571 | |||
1572 | release_region(0x2e, 1); | ||
1573 | } | ||
1574 | } | ||
1543 | #endif /* CONFIG_PARPORT_PC_SUPERIO */ | 1575 | #endif /* CONFIG_PARPORT_PC_SUPERIO */ |
1544 | 1576 | ||
1545 | static int get_superio_dma (struct parport *p) | 1577 | static int get_superio_dma (struct parport *p) |
@@ -2767,6 +2799,7 @@ enum parport_pc_pci_cards { | |||
2767 | netmos_9755, | 2799 | netmos_9755, |
2768 | netmos_9805, | 2800 | netmos_9805, |
2769 | netmos_9815, | 2801 | netmos_9815, |
2802 | quatech_sppxp100, | ||
2770 | }; | 2803 | }; |
2771 | 2804 | ||
2772 | 2805 | ||
@@ -2843,6 +2876,7 @@ static struct parport_pc_pci { | |||
2843 | /* netmos_9755 */ { 2, { { 0, 1 }, { 2, 3 },} }, /* untested */ | 2876 | /* netmos_9755 */ { 2, { { 0, 1 }, { 2, 3 },} }, /* untested */ |
2844 | /* netmos_9805 */ { 1, { { 0, -1 }, } }, /* untested */ | 2877 | /* netmos_9805 */ { 1, { { 0, -1 }, } }, /* untested */ |
2845 | /* netmos_9815 */ { 2, { { 0, -1 }, { 2, -1 }, } }, /* untested */ | 2878 | /* netmos_9815 */ { 2, { { 0, -1 }, { 2, -1 }, } }, /* untested */ |
2879 | /* quatech_sppxp100 */ { 1, { { 0, 1 }, } }, | ||
2846 | }; | 2880 | }; |
2847 | 2881 | ||
2848 | static const struct pci_device_id parport_pc_pci_tbl[] = { | 2882 | static const struct pci_device_id parport_pc_pci_tbl[] = { |
@@ -2926,6 +2960,9 @@ static const struct pci_device_id parport_pc_pci_tbl[] = { | |||
2926 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9805 }, | 2960 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9805 }, |
2927 | { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9815, | 2961 | { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9815, |
2928 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9815 }, | 2962 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9815 }, |
2963 | /* Quatech SPPXP-100 Parallel port PCI ExpressCard */ | ||
2964 | { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_SPPXP_100, | ||
2965 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, quatech_sppxp100 }, | ||
2929 | { 0, } /* terminate list */ | 2966 | { 0, } /* terminate list */ |
2930 | }; | 2967 | }; |
2931 | MODULE_DEVICE_TABLE(pci,parport_pc_pci_tbl); | 2968 | MODULE_DEVICE_TABLE(pci,parport_pc_pci_tbl); |
@@ -3159,24 +3196,25 @@ static void __init parport_pc_find_ports (int autoirq, int autodma) | |||
3159 | int count = 0, err; | 3196 | int count = 0, err; |
3160 | 3197 | ||
3161 | #ifdef CONFIG_PARPORT_PC_SUPERIO | 3198 | #ifdef CONFIG_PARPORT_PC_SUPERIO |
3162 | detect_and_report_winbond (); | 3199 | detect_and_report_it87(); |
3163 | detect_and_report_smsc (); | 3200 | detect_and_report_winbond(); |
3201 | detect_and_report_smsc(); | ||
3164 | #endif | 3202 | #endif |
3165 | 3203 | ||
3166 | /* Onboard SuperIO chipsets that show themselves on the PCI bus. */ | 3204 | /* Onboard SuperIO chipsets that show themselves on the PCI bus. */ |
3167 | count += parport_pc_init_superio (autoirq, autodma); | 3205 | count += parport_pc_init_superio(autoirq, autodma); |
3168 | 3206 | ||
3169 | /* PnP ports, skip detection if SuperIO already found them */ | 3207 | /* PnP ports, skip detection if SuperIO already found them */ |
3170 | if (!count) { | 3208 | if (!count) { |
3171 | err = pnp_register_driver (&parport_pc_pnp_driver); | 3209 | err = pnp_register_driver(&parport_pc_pnp_driver); |
3172 | if (!err) | 3210 | if (!err) |
3173 | pnp_registered_parport = 1; | 3211 | pnp_registered_parport = 1; |
3174 | } | 3212 | } |
3175 | 3213 | ||
3176 | /* ISA ports and whatever (see asm/parport.h). */ | 3214 | /* ISA ports and whatever (see asm/parport.h). */ |
3177 | parport_pc_find_nonpci_ports (autoirq, autodma); | 3215 | parport_pc_find_nonpci_ports(autoirq, autodma); |
3178 | 3216 | ||
3179 | err = pci_register_driver (&parport_pc_pci_driver); | 3217 | err = pci_register_driver(&parport_pc_pci_driver); |
3180 | if (!err) | 3218 | if (!err) |
3181 | pci_registered_parport = 1; | 3219 | pci_registered_parport = 1; |
3182 | } | 3220 | } |
diff --git a/drivers/parport/parport_serial.c b/drivers/parport/parport_serial.c index bd6ad8b38168..e2e95b36a603 100644 --- a/drivers/parport/parport_serial.c +++ b/drivers/parport/parport_serial.c | |||
@@ -77,7 +77,7 @@ static struct parport_pc_pci cards[] __devinitdata = { | |||
77 | /* titan_110l */ { 1, { { 3, -1 }, } }, | 77 | /* titan_110l */ { 1, { { 3, -1 }, } }, |
78 | /* titan_210l */ { 1, { { 3, -1 }, } }, | 78 | /* titan_210l */ { 1, { { 3, -1 }, } }, |
79 | /* netmos_9xx5_combo */ { 1, { { 2, -1 }, }, netmos_parallel_init }, | 79 | /* netmos_9xx5_combo */ { 1, { { 2, -1 }, }, netmos_parallel_init }, |
80 | /* netmos_9855 */ { 1, { { 0, -1 }, }, netmos_parallel_init }, | 80 | /* netmos_9855 */ { 1, { { 2, -1 }, }, netmos_parallel_init }, |
81 | /* avlab_1s1p */ { 1, { { 1, 2}, } }, | 81 | /* avlab_1s1p */ { 1, { { 1, 2}, } }, |
82 | /* avlab_1s2p */ { 2, { { 1, 2}, { 3, 4 },} }, | 82 | /* avlab_1s2p */ { 2, { { 1, 2}, { 3, 4 },} }, |
83 | /* avlab_2s1p */ { 1, { { 2, 3}, } }, | 83 | /* avlab_2s1p */ { 1, { { 2, 3}, } }, |
@@ -185,7 +185,7 @@ static struct pciserial_board pci_parport_serial_boards[] __devinitdata = { | |||
185 | .uart_offset = 8, | 185 | .uart_offset = 8, |
186 | }, | 186 | }, |
187 | [netmos_9855] = { | 187 | [netmos_9855] = { |
188 | .flags = FL_BASE2 | FL_BASE_BARS, | 188 | .flags = FL_BASE4 | FL_BASE_BARS, |
189 | .num_ports = 1, | 189 | .num_ports = 1, |
190 | .base_baud = 115200, | 190 | .base_baud = 115200, |
191 | .uart_offset = 8, | 191 | .uart_offset = 8, |
diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c index 91b2dc956be5..8ed26480371f 100644 --- a/drivers/pci/dmar.c +++ b/drivers/pci/dmar.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/pci.h> | 26 | #include <linux/pci.h> |
27 | #include <linux/dmar.h> | 27 | #include <linux/dmar.h> |
28 | #include "iova.h" | 28 | #include "iova.h" |
29 | #include "intel-iommu.h" | ||
29 | 30 | ||
30 | #undef PREFIX | 31 | #undef PREFIX |
31 | #define PREFIX "DMAR:" | 32 | #define PREFIX "DMAR:" |
diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 4e01df99681a..31fa6c92aa5e 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c | |||
@@ -1088,7 +1088,7 @@ static void dmar_init_reserved_ranges(void) | |||
1088 | int i; | 1088 | int i; |
1089 | u64 addr, size; | 1089 | u64 addr, size; |
1090 | 1090 | ||
1091 | init_iova_domain(&reserved_iova_list); | 1091 | init_iova_domain(&reserved_iova_list, DMA_32BIT_PFN); |
1092 | 1092 | ||
1093 | /* IOAPIC ranges shouldn't be accessed by DMA */ | 1093 | /* IOAPIC ranges shouldn't be accessed by DMA */ |
1094 | iova = reserve_iova(&reserved_iova_list, IOVA_PFN(IOAPIC_RANGE_START), | 1094 | iova = reserve_iova(&reserved_iova_list, IOVA_PFN(IOAPIC_RANGE_START), |
@@ -1142,7 +1142,7 @@ static int domain_init(struct dmar_domain *domain, int guest_width) | |||
1142 | int adjust_width, agaw; | 1142 | int adjust_width, agaw; |
1143 | unsigned long sagaw; | 1143 | unsigned long sagaw; |
1144 | 1144 | ||
1145 | init_iova_domain(&domain->iovad); | 1145 | init_iova_domain(&domain->iovad, DMA_32BIT_PFN); |
1146 | spin_lock_init(&domain->mapping_lock); | 1146 | spin_lock_init(&domain->mapping_lock); |
1147 | 1147 | ||
1148 | domain_reserve_special_ranges(domain); | 1148 | domain_reserve_special_ranges(domain); |
diff --git a/drivers/pci/intel-iommu.h b/drivers/pci/intel-iommu.h index 459ad1f9dc54..0e4862675ad2 100644 --- a/drivers/pci/intel-iommu.h +++ b/drivers/pci/intel-iommu.h | |||
@@ -23,10 +23,24 @@ | |||
23 | 23 | ||
24 | #include <linux/types.h> | 24 | #include <linux/types.h> |
25 | #include <linux/msi.h> | 25 | #include <linux/msi.h> |
26 | #include <linux/sysdev.h> | ||
26 | #include "iova.h" | 27 | #include "iova.h" |
27 | #include <linux/io.h> | 28 | #include <linux/io.h> |
28 | 29 | ||
29 | /* | 30 | /* |
31 | * We need a fixed PAGE_SIZE of 4K irrespective of | ||
32 | * arch PAGE_SIZE for IOMMU page tables. | ||
33 | */ | ||
34 | #define PAGE_SHIFT_4K (12) | ||
35 | #define PAGE_SIZE_4K (1UL << PAGE_SHIFT_4K) | ||
36 | #define PAGE_MASK_4K (((u64)-1) << PAGE_SHIFT_4K) | ||
37 | #define PAGE_ALIGN_4K(addr) (((addr) + PAGE_SIZE_4K - 1) & PAGE_MASK_4K) | ||
38 | |||
39 | #define IOVA_PFN(addr) ((addr) >> PAGE_SHIFT_4K) | ||
40 | #define DMA_32BIT_PFN IOVA_PFN(DMA_32BIT_MASK) | ||
41 | #define DMA_64BIT_PFN IOVA_PFN(DMA_64BIT_MASK) | ||
42 | |||
43 | /* | ||
30 | * Intel IOMMU register specification per version 1.0 public spec. | 44 | * Intel IOMMU register specification per version 1.0 public spec. |
31 | */ | 45 | */ |
32 | 46 | ||
diff --git a/drivers/pci/iova.c b/drivers/pci/iova.c index a84571c29360..8de7ab6c6d0c 100644 --- a/drivers/pci/iova.c +++ b/drivers/pci/iova.c | |||
@@ -9,19 +9,19 @@ | |||
9 | #include "iova.h" | 9 | #include "iova.h" |
10 | 10 | ||
11 | void | 11 | void |
12 | init_iova_domain(struct iova_domain *iovad) | 12 | init_iova_domain(struct iova_domain *iovad, unsigned long pfn_32bit) |
13 | { | 13 | { |
14 | spin_lock_init(&iovad->iova_alloc_lock); | 14 | spin_lock_init(&iovad->iova_alloc_lock); |
15 | spin_lock_init(&iovad->iova_rbtree_lock); | 15 | spin_lock_init(&iovad->iova_rbtree_lock); |
16 | iovad->rbroot = RB_ROOT; | 16 | iovad->rbroot = RB_ROOT; |
17 | iovad->cached32_node = NULL; | 17 | iovad->cached32_node = NULL; |
18 | 18 | iovad->dma_32bit_pfn = pfn_32bit; | |
19 | } | 19 | } |
20 | 20 | ||
21 | static struct rb_node * | 21 | static struct rb_node * |
22 | __get_cached_rbnode(struct iova_domain *iovad, unsigned long *limit_pfn) | 22 | __get_cached_rbnode(struct iova_domain *iovad, unsigned long *limit_pfn) |
23 | { | 23 | { |
24 | if ((*limit_pfn != DMA_32BIT_PFN) || | 24 | if ((*limit_pfn != iovad->dma_32bit_pfn) || |
25 | (iovad->cached32_node == NULL)) | 25 | (iovad->cached32_node == NULL)) |
26 | return rb_last(&iovad->rbroot); | 26 | return rb_last(&iovad->rbroot); |
27 | else { | 27 | else { |
@@ -37,7 +37,7 @@ static void | |||
37 | __cached_rbnode_insert_update(struct iova_domain *iovad, | 37 | __cached_rbnode_insert_update(struct iova_domain *iovad, |
38 | unsigned long limit_pfn, struct iova *new) | 38 | unsigned long limit_pfn, struct iova *new) |
39 | { | 39 | { |
40 | if (limit_pfn != DMA_32BIT_PFN) | 40 | if (limit_pfn != iovad->dma_32bit_pfn) |
41 | return; | 41 | return; |
42 | iovad->cached32_node = &new->node; | 42 | iovad->cached32_node = &new->node; |
43 | } | 43 | } |
diff --git a/drivers/pci/iova.h b/drivers/pci/iova.h index ae3028d5a941..d521b5b7319c 100644 --- a/drivers/pci/iova.h +++ b/drivers/pci/iova.h | |||
@@ -15,22 +15,9 @@ | |||
15 | #include <linux/rbtree.h> | 15 | #include <linux/rbtree.h> |
16 | #include <linux/dma-mapping.h> | 16 | #include <linux/dma-mapping.h> |
17 | 17 | ||
18 | /* | ||
19 | * We need a fixed PAGE_SIZE of 4K irrespective of | ||
20 | * arch PAGE_SIZE for IOMMU page tables. | ||
21 | */ | ||
22 | #define PAGE_SHIFT_4K (12) | ||
23 | #define PAGE_SIZE_4K (1UL << PAGE_SHIFT_4K) | ||
24 | #define PAGE_MASK_4K (((u64)-1) << PAGE_SHIFT_4K) | ||
25 | #define PAGE_ALIGN_4K(addr) (((addr) + PAGE_SIZE_4K - 1) & PAGE_MASK_4K) | ||
26 | |||
27 | /* IO virtual address start page frame number */ | 18 | /* IO virtual address start page frame number */ |
28 | #define IOVA_START_PFN (1) | 19 | #define IOVA_START_PFN (1) |
29 | 20 | ||
30 | #define IOVA_PFN(addr) ((addr) >> PAGE_SHIFT_4K) | ||
31 | #define DMA_32BIT_PFN IOVA_PFN(DMA_32BIT_MASK) | ||
32 | #define DMA_64BIT_PFN IOVA_PFN(DMA_64BIT_MASK) | ||
33 | |||
34 | /* iova structure */ | 21 | /* iova structure */ |
35 | struct iova { | 22 | struct iova { |
36 | struct rb_node node; | 23 | struct rb_node node; |
@@ -44,6 +31,7 @@ struct iova_domain { | |||
44 | spinlock_t iova_rbtree_lock; /* Lock to protect update of rbtree */ | 31 | spinlock_t iova_rbtree_lock; /* Lock to protect update of rbtree */ |
45 | struct rb_root rbroot; /* iova domain rbtree root */ | 32 | struct rb_root rbroot; /* iova domain rbtree root */ |
46 | struct rb_node *cached32_node; /* Save last alloced node */ | 33 | struct rb_node *cached32_node; /* Save last alloced node */ |
34 | unsigned long dma_32bit_pfn; | ||
47 | }; | 35 | }; |
48 | 36 | ||
49 | struct iova *alloc_iova_mem(void); | 37 | struct iova *alloc_iova_mem(void); |
@@ -56,7 +44,7 @@ struct iova *alloc_iova(struct iova_domain *iovad, unsigned long size, | |||
56 | struct iova *reserve_iova(struct iova_domain *iovad, unsigned long pfn_lo, | 44 | struct iova *reserve_iova(struct iova_domain *iovad, unsigned long pfn_lo, |
57 | unsigned long pfn_hi); | 45 | unsigned long pfn_hi); |
58 | void copy_reserved_iova(struct iova_domain *from, struct iova_domain *to); | 46 | void copy_reserved_iova(struct iova_domain *from, struct iova_domain *to); |
59 | void init_iova_domain(struct iova_domain *iovad); | 47 | void init_iova_domain(struct iova_domain *iovad, unsigned long pfn_32bit); |
60 | struct iova *find_iova(struct iova_domain *iovad, unsigned long pfn); | 48 | struct iova *find_iova(struct iova_domain *iovad, unsigned long pfn); |
61 | void put_iova_domain(struct iova_domain *iovad); | 49 | void put_iova_domain(struct iova_domain *iovad); |
62 | 50 | ||
diff --git a/drivers/pnp/driver.c b/drivers/pnp/driver.c index a262762c5b88..12a1645a2e43 100644 --- a/drivers/pnp/driver.c +++ b/drivers/pnp/driver.c | |||
@@ -161,8 +161,7 @@ static int pnp_bus_suspend(struct device *dev, pm_message_t state) | |||
161 | return error; | 161 | return error; |
162 | } | 162 | } |
163 | 163 | ||
164 | if (!(pnp_drv->flags & PNP_DRIVER_RES_DO_NOT_CHANGE) && | 164 | if (pnp_can_disable(pnp_dev)) { |
165 | pnp_can_disable(pnp_dev)) { | ||
166 | error = pnp_stop_dev(pnp_dev); | 165 | error = pnp_stop_dev(pnp_dev); |
167 | if (error) | 166 | if (error) |
168 | return error; | 167 | return error; |
@@ -185,14 +184,17 @@ static int pnp_bus_resume(struct device *dev) | |||
185 | if (pnp_dev->protocol && pnp_dev->protocol->resume) | 184 | if (pnp_dev->protocol && pnp_dev->protocol->resume) |
186 | pnp_dev->protocol->resume(pnp_dev); | 185 | pnp_dev->protocol->resume(pnp_dev); |
187 | 186 | ||
188 | if (!(pnp_drv->flags & PNP_DRIVER_RES_DO_NOT_CHANGE)) { | 187 | if (pnp_can_write(pnp_dev)) { |
189 | error = pnp_start_dev(pnp_dev); | 188 | error = pnp_start_dev(pnp_dev); |
190 | if (error) | 189 | if (error) |
191 | return error; | 190 | return error; |
192 | } | 191 | } |
193 | 192 | ||
194 | if (pnp_drv->resume) | 193 | if (pnp_drv->resume) { |
195 | return pnp_drv->resume(pnp_dev); | 194 | error = pnp_drv->resume(pnp_dev); |
195 | if (error) | ||
196 | return error; | ||
197 | } | ||
196 | 198 | ||
197 | return 0; | 199 | return 0; |
198 | } | 200 | } |
diff --git a/drivers/pnp/interface.c b/drivers/pnp/interface.c index 31548044fdde..982658477a58 100644 --- a/drivers/pnp/interface.c +++ b/drivers/pnp/interface.c | |||
@@ -10,9 +10,12 @@ | |||
10 | #include <linux/errno.h> | 10 | #include <linux/errno.h> |
11 | #include <linux/list.h> | 11 | #include <linux/list.h> |
12 | #include <linux/types.h> | 12 | #include <linux/types.h> |
13 | #include <linux/pnp.h> | ||
13 | #include <linux/stat.h> | 14 | #include <linux/stat.h> |
14 | #include <linux/ctype.h> | 15 | #include <linux/ctype.h> |
15 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
17 | #include <linux/mutex.h> | ||
18 | |||
16 | #include <asm/uaccess.h> | 19 | #include <asm/uaccess.h> |
17 | 20 | ||
18 | #include "base.h" | 21 | #include "base.h" |
@@ -315,8 +318,6 @@ static ssize_t pnp_show_current_resources(struct device *dmdev, | |||
315 | return ret; | 318 | return ret; |
316 | } | 319 | } |
317 | 320 | ||
318 | extern struct semaphore pnp_res_mutex; | ||
319 | |||
320 | static ssize_t | 321 | static ssize_t |
321 | pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr, | 322 | pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr, |
322 | const char *ubuf, size_t count) | 323 | const char *ubuf, size_t count) |
@@ -361,10 +362,10 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr, | |||
361 | goto done; | 362 | goto done; |
362 | } | 363 | } |
363 | if (!strnicmp(buf, "get", 3)) { | 364 | if (!strnicmp(buf, "get", 3)) { |
364 | down(&pnp_res_mutex); | 365 | mutex_lock(&pnp_res_mutex); |
365 | if (pnp_can_read(dev)) | 366 | if (pnp_can_read(dev)) |
366 | dev->protocol->get(dev, &dev->res); | 367 | dev->protocol->get(dev, &dev->res); |
367 | up(&pnp_res_mutex); | 368 | mutex_unlock(&pnp_res_mutex); |
368 | goto done; | 369 | goto done; |
369 | } | 370 | } |
370 | if (!strnicmp(buf, "set", 3)) { | 371 | if (!strnicmp(buf, "set", 3)) { |
@@ -373,7 +374,7 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr, | |||
373 | goto done; | 374 | goto done; |
374 | buf += 3; | 375 | buf += 3; |
375 | pnp_init_resource_table(&dev->res); | 376 | pnp_init_resource_table(&dev->res); |
376 | down(&pnp_res_mutex); | 377 | mutex_lock(&pnp_res_mutex); |
377 | while (1) { | 378 | while (1) { |
378 | while (isspace(*buf)) | 379 | while (isspace(*buf)) |
379 | ++buf; | 380 | ++buf; |
@@ -455,7 +456,7 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr, | |||
455 | } | 456 | } |
456 | break; | 457 | break; |
457 | } | 458 | } |
458 | up(&pnp_res_mutex); | 459 | mutex_unlock(&pnp_res_mutex); |
459 | goto done; | 460 | goto done; |
460 | } | 461 | } |
461 | 462 | ||
diff --git a/drivers/pnp/manager.c b/drivers/pnp/manager.c index c6b3d4e63ccc..c28caf272c11 100644 --- a/drivers/pnp/manager.c +++ b/drivers/pnp/manager.c | |||
@@ -12,9 +12,10 @@ | |||
12 | #include <linux/pnp.h> | 12 | #include <linux/pnp.h> |
13 | #include <linux/slab.h> | 13 | #include <linux/slab.h> |
14 | #include <linux/bitmap.h> | 14 | #include <linux/bitmap.h> |
15 | #include <linux/mutex.h> | ||
15 | #include "base.h" | 16 | #include "base.h" |
16 | 17 | ||
17 | DECLARE_MUTEX(pnp_res_mutex); | 18 | DEFINE_MUTEX(pnp_res_mutex); |
18 | 19 | ||
19 | static int pnp_assign_port(struct pnp_dev *dev, struct pnp_port *rule, int idx) | 20 | static int pnp_assign_port(struct pnp_dev *dev, struct pnp_port *rule, int idx) |
20 | { | 21 | { |
@@ -297,7 +298,7 @@ static int pnp_assign_resources(struct pnp_dev *dev, int depnum) | |||
297 | if (!pnp_can_configure(dev)) | 298 | if (!pnp_can_configure(dev)) |
298 | return -ENODEV; | 299 | return -ENODEV; |
299 | 300 | ||
300 | down(&pnp_res_mutex); | 301 | mutex_lock(&pnp_res_mutex); |
301 | pnp_clean_resource_table(&dev->res); /* start with a fresh slate */ | 302 | pnp_clean_resource_table(&dev->res); /* start with a fresh slate */ |
302 | if (dev->independent) { | 303 | if (dev->independent) { |
303 | port = dev->independent->port; | 304 | port = dev->independent->port; |
@@ -366,12 +367,12 @@ static int pnp_assign_resources(struct pnp_dev *dev, int depnum) | |||
366 | } else if (dev->dependent) | 367 | } else if (dev->dependent) |
367 | goto fail; | 368 | goto fail; |
368 | 369 | ||
369 | up(&pnp_res_mutex); | 370 | mutex_unlock(&pnp_res_mutex); |
370 | return 1; | 371 | return 1; |
371 | 372 | ||
372 | fail: | 373 | fail: |
373 | pnp_clean_resource_table(&dev->res); | 374 | pnp_clean_resource_table(&dev->res); |
374 | up(&pnp_res_mutex); | 375 | mutex_unlock(&pnp_res_mutex); |
375 | return 0; | 376 | return 0; |
376 | } | 377 | } |
377 | 378 | ||
@@ -396,7 +397,7 @@ int pnp_manual_config_dev(struct pnp_dev *dev, struct pnp_resource_table *res, | |||
396 | return -ENOMEM; | 397 | return -ENOMEM; |
397 | *bak = dev->res; | 398 | *bak = dev->res; |
398 | 399 | ||
399 | down(&pnp_res_mutex); | 400 | mutex_lock(&pnp_res_mutex); |
400 | dev->res = *res; | 401 | dev->res = *res; |
401 | if (!(mode & PNP_CONFIG_FORCE)) { | 402 | if (!(mode & PNP_CONFIG_FORCE)) { |
402 | for (i = 0; i < PNP_MAX_PORT; i++) { | 403 | for (i = 0; i < PNP_MAX_PORT; i++) { |
@@ -416,14 +417,14 @@ int pnp_manual_config_dev(struct pnp_dev *dev, struct pnp_resource_table *res, | |||
416 | goto fail; | 417 | goto fail; |
417 | } | 418 | } |
418 | } | 419 | } |
419 | up(&pnp_res_mutex); | 420 | mutex_unlock(&pnp_res_mutex); |
420 | 421 | ||
421 | kfree(bak); | 422 | kfree(bak); |
422 | return 0; | 423 | return 0; |
423 | 424 | ||
424 | fail: | 425 | fail: |
425 | dev->res = *bak; | 426 | dev->res = *bak; |
426 | up(&pnp_res_mutex); | 427 | mutex_unlock(&pnp_res_mutex); |
427 | kfree(bak); | 428 | kfree(bak); |
428 | return -EINVAL; | 429 | return -EINVAL; |
429 | } | 430 | } |
@@ -513,7 +514,7 @@ int pnp_activate_dev(struct pnp_dev *dev) | |||
513 | int error; | 514 | int error; |
514 | 515 | ||
515 | if (dev->active) | 516 | if (dev->active) |
516 | return 0; /* the device is already active */ | 517 | return 0; |
517 | 518 | ||
518 | /* ensure resources are allocated */ | 519 | /* ensure resources are allocated */ |
519 | if (pnp_auto_config_dev(dev)) | 520 | if (pnp_auto_config_dev(dev)) |
@@ -524,7 +525,7 @@ int pnp_activate_dev(struct pnp_dev *dev) | |||
524 | return error; | 525 | return error; |
525 | 526 | ||
526 | dev->active = 1; | 527 | dev->active = 1; |
527 | return 1; | 528 | return 0; |
528 | } | 529 | } |
529 | 530 | ||
530 | /** | 531 | /** |
@@ -538,7 +539,7 @@ int pnp_disable_dev(struct pnp_dev *dev) | |||
538 | int error; | 539 | int error; |
539 | 540 | ||
540 | if (!dev->active) | 541 | if (!dev->active) |
541 | return 0; /* the device is already disabled */ | 542 | return 0; |
542 | 543 | ||
543 | error = pnp_stop_dev(dev); | 544 | error = pnp_stop_dev(dev); |
544 | if (error) | 545 | if (error) |
@@ -547,11 +548,11 @@ int pnp_disable_dev(struct pnp_dev *dev) | |||
547 | dev->active = 0; | 548 | dev->active = 0; |
548 | 549 | ||
549 | /* release the resources so that other devices can use them */ | 550 | /* release the resources so that other devices can use them */ |
550 | down(&pnp_res_mutex); | 551 | mutex_lock(&pnp_res_mutex); |
551 | pnp_clean_resource_table(&dev->res); | 552 | pnp_clean_resource_table(&dev->res); |
552 | up(&pnp_res_mutex); | 553 | mutex_unlock(&pnp_res_mutex); |
553 | 554 | ||
554 | return 1; | 555 | return 0; |
555 | } | 556 | } |
556 | 557 | ||
557 | /** | 558 | /** |
diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c index 6b9840cce0f4..6aa231ef642d 100644 --- a/drivers/pnp/pnpacpi/rsparser.c +++ b/drivers/pnp/pnpacpi/rsparser.c | |||
@@ -391,8 +391,8 @@ acpi_status pnpacpi_parse_allocated_resource(acpi_handle handle, | |||
391 | pnpacpi_allocated_resource, res); | 391 | pnpacpi_allocated_resource, res); |
392 | } | 392 | } |
393 | 393 | ||
394 | static void pnpacpi_parse_dma_option(struct pnp_option *option, | 394 | static __init void pnpacpi_parse_dma_option(struct pnp_option *option, |
395 | struct acpi_resource_dma *p) | 395 | struct acpi_resource_dma *p) |
396 | { | 396 | { |
397 | int i; | 397 | int i; |
398 | struct pnp_dma *dma; | 398 | struct pnp_dma *dma; |
@@ -411,8 +411,8 @@ static void pnpacpi_parse_dma_option(struct pnp_option *option, | |||
411 | pnp_register_dma_resource(option, dma); | 411 | pnp_register_dma_resource(option, dma); |
412 | } | 412 | } |
413 | 413 | ||
414 | static void pnpacpi_parse_irq_option(struct pnp_option *option, | 414 | static __init void pnpacpi_parse_irq_option(struct pnp_option *option, |
415 | struct acpi_resource_irq *p) | 415 | struct acpi_resource_irq *p) |
416 | { | 416 | { |
417 | int i; | 417 | int i; |
418 | struct pnp_irq *irq; | 418 | struct pnp_irq *irq; |
@@ -431,8 +431,8 @@ static void pnpacpi_parse_irq_option(struct pnp_option *option, | |||
431 | pnp_register_irq_resource(option, irq); | 431 | pnp_register_irq_resource(option, irq); |
432 | } | 432 | } |
433 | 433 | ||
434 | static void pnpacpi_parse_ext_irq_option(struct pnp_option *option, | 434 | static __init void pnpacpi_parse_ext_irq_option(struct pnp_option *option, |
435 | struct acpi_resource_extended_irq *p) | 435 | struct acpi_resource_extended_irq *p) |
436 | { | 436 | { |
437 | int i; | 437 | int i; |
438 | struct pnp_irq *irq; | 438 | struct pnp_irq *irq; |
@@ -451,8 +451,8 @@ static void pnpacpi_parse_ext_irq_option(struct pnp_option *option, | |||
451 | pnp_register_irq_resource(option, irq); | 451 | pnp_register_irq_resource(option, irq); |
452 | } | 452 | } |
453 | 453 | ||
454 | static void pnpacpi_parse_port_option(struct pnp_option *option, | 454 | static __init void pnpacpi_parse_port_option(struct pnp_option *option, |
455 | struct acpi_resource_io *io) | 455 | struct acpi_resource_io *io) |
456 | { | 456 | { |
457 | struct pnp_port *port; | 457 | struct pnp_port *port; |
458 | 458 | ||
@@ -470,8 +470,8 @@ static void pnpacpi_parse_port_option(struct pnp_option *option, | |||
470 | pnp_register_port_resource(option, port); | 470 | pnp_register_port_resource(option, port); |
471 | } | 471 | } |
472 | 472 | ||
473 | static void pnpacpi_parse_fixed_port_option(struct pnp_option *option, | 473 | static __init void pnpacpi_parse_fixed_port_option(struct pnp_option *option, |
474 | struct acpi_resource_fixed_io *io) | 474 | struct acpi_resource_fixed_io *io) |
475 | { | 475 | { |
476 | struct pnp_port *port; | 476 | struct pnp_port *port; |
477 | 477 | ||
@@ -487,8 +487,8 @@ static void pnpacpi_parse_fixed_port_option(struct pnp_option *option, | |||
487 | pnp_register_port_resource(option, port); | 487 | pnp_register_port_resource(option, port); |
488 | } | 488 | } |
489 | 489 | ||
490 | static void pnpacpi_parse_mem24_option(struct pnp_option *option, | 490 | static __init void pnpacpi_parse_mem24_option(struct pnp_option *option, |
491 | struct acpi_resource_memory24 *p) | 491 | struct acpi_resource_memory24 *p) |
492 | { | 492 | { |
493 | struct pnp_mem *mem; | 493 | struct pnp_mem *mem; |
494 | 494 | ||
@@ -508,8 +508,8 @@ static void pnpacpi_parse_mem24_option(struct pnp_option *option, | |||
508 | pnp_register_mem_resource(option, mem); | 508 | pnp_register_mem_resource(option, mem); |
509 | } | 509 | } |
510 | 510 | ||
511 | static void pnpacpi_parse_mem32_option(struct pnp_option *option, | 511 | static __init void pnpacpi_parse_mem32_option(struct pnp_option *option, |
512 | struct acpi_resource_memory32 *p) | 512 | struct acpi_resource_memory32 *p) |
513 | { | 513 | { |
514 | struct pnp_mem *mem; | 514 | struct pnp_mem *mem; |
515 | 515 | ||
@@ -529,8 +529,8 @@ static void pnpacpi_parse_mem32_option(struct pnp_option *option, | |||
529 | pnp_register_mem_resource(option, mem); | 529 | pnp_register_mem_resource(option, mem); |
530 | } | 530 | } |
531 | 531 | ||
532 | static void pnpacpi_parse_fixed_mem32_option(struct pnp_option *option, | 532 | static __init void pnpacpi_parse_fixed_mem32_option(struct pnp_option *option, |
533 | struct acpi_resource_fixed_memory32 *p) | 533 | struct acpi_resource_fixed_memory32 *p) |
534 | { | 534 | { |
535 | struct pnp_mem *mem; | 535 | struct pnp_mem *mem; |
536 | 536 | ||
@@ -549,8 +549,8 @@ static void pnpacpi_parse_fixed_mem32_option(struct pnp_option *option, | |||
549 | pnp_register_mem_resource(option, mem); | 549 | pnp_register_mem_resource(option, mem); |
550 | } | 550 | } |
551 | 551 | ||
552 | static void pnpacpi_parse_address_option(struct pnp_option *option, | 552 | static __init void pnpacpi_parse_address_option(struct pnp_option *option, |
553 | struct acpi_resource *r) | 553 | struct acpi_resource *r) |
554 | { | 554 | { |
555 | struct acpi_resource_address64 addr, *p = &addr; | 555 | struct acpi_resource_address64 addr, *p = &addr; |
556 | acpi_status status; | 556 | acpi_status status; |
@@ -596,8 +596,8 @@ struct acpipnp_parse_option_s { | |||
596 | struct pnp_dev *dev; | 596 | struct pnp_dev *dev; |
597 | }; | 597 | }; |
598 | 598 | ||
599 | static acpi_status pnpacpi_option_resource(struct acpi_resource *res, | 599 | static __init acpi_status pnpacpi_option_resource(struct acpi_resource *res, |
600 | void *data) | 600 | void *data) |
601 | { | 601 | { |
602 | int priority = 0; | 602 | int priority = 0; |
603 | struct acpipnp_parse_option_s *parse_data = data; | 603 | struct acpipnp_parse_option_s *parse_data = data; |
@@ -696,8 +696,8 @@ static acpi_status pnpacpi_option_resource(struct acpi_resource *res, | |||
696 | return AE_OK; | 696 | return AE_OK; |
697 | } | 697 | } |
698 | 698 | ||
699 | acpi_status pnpacpi_parse_resource_option_data(acpi_handle handle, | 699 | acpi_status __init pnpacpi_parse_resource_option_data(acpi_handle handle, |
700 | struct pnp_dev * dev) | 700 | struct pnp_dev *dev) |
701 | { | 701 | { |
702 | acpi_status status; | 702 | acpi_status status; |
703 | struct acpipnp_parse_option_s parse_data; | 703 | struct acpipnp_parse_option_s parse_data; |
diff --git a/drivers/pnp/pnpbios/core.c b/drivers/pnp/pnpbios/core.c index e33e03f71084..f7e67197a568 100644 --- a/drivers/pnp/pnpbios/core.c +++ b/drivers/pnp/pnpbios/core.c | |||
@@ -315,7 +315,7 @@ struct pnp_protocol pnpbios_protocol = { | |||
315 | .disable = pnpbios_disable_resources, | 315 | .disable = pnpbios_disable_resources, |
316 | }; | 316 | }; |
317 | 317 | ||
318 | static int insert_device(struct pnp_bios_node *node) | 318 | static int __init insert_device(struct pnp_bios_node *node) |
319 | { | 319 | { |
320 | struct list_head *pos; | 320 | struct list_head *pos; |
321 | struct pnp_dev *dev; | 321 | struct pnp_dev *dev; |
diff --git a/drivers/pnp/pnpbios/rsparser.c b/drivers/pnp/pnpbios/rsparser.c index 3fabf11b0027..caade3531416 100644 --- a/drivers/pnp/pnpbios/rsparser.c +++ b/drivers/pnp/pnpbios/rsparser.c | |||
@@ -262,8 +262,8 @@ len_err: | |||
262 | * Resource Configuration Options | 262 | * Resource Configuration Options |
263 | */ | 263 | */ |
264 | 264 | ||
265 | static void pnpbios_parse_mem_option(unsigned char *p, int size, | 265 | static __init void pnpbios_parse_mem_option(unsigned char *p, int size, |
266 | struct pnp_option *option) | 266 | struct pnp_option *option) |
267 | { | 267 | { |
268 | struct pnp_mem *mem; | 268 | struct pnp_mem *mem; |
269 | 269 | ||
@@ -278,8 +278,8 @@ static void pnpbios_parse_mem_option(unsigned char *p, int size, | |||
278 | pnp_register_mem_resource(option, mem); | 278 | pnp_register_mem_resource(option, mem); |
279 | } | 279 | } |
280 | 280 | ||
281 | static void pnpbios_parse_mem32_option(unsigned char *p, int size, | 281 | static __init void pnpbios_parse_mem32_option(unsigned char *p, int size, |
282 | struct pnp_option *option) | 282 | struct pnp_option *option) |
283 | { | 283 | { |
284 | struct pnp_mem *mem; | 284 | struct pnp_mem *mem; |
285 | 285 | ||
@@ -294,8 +294,8 @@ static void pnpbios_parse_mem32_option(unsigned char *p, int size, | |||
294 | pnp_register_mem_resource(option, mem); | 294 | pnp_register_mem_resource(option, mem); |
295 | } | 295 | } |
296 | 296 | ||
297 | static void pnpbios_parse_fixed_mem32_option(unsigned char *p, int size, | 297 | static __init void pnpbios_parse_fixed_mem32_option(unsigned char *p, int size, |
298 | struct pnp_option *option) | 298 | struct pnp_option *option) |
299 | { | 299 | { |
300 | struct pnp_mem *mem; | 300 | struct pnp_mem *mem; |
301 | 301 | ||
@@ -309,7 +309,7 @@ static void pnpbios_parse_fixed_mem32_option(unsigned char *p, int size, | |||
309 | pnp_register_mem_resource(option, mem); | 309 | pnp_register_mem_resource(option, mem); |
310 | } | 310 | } |
311 | 311 | ||
312 | static void pnpbios_parse_irq_option(unsigned char *p, int size, | 312 | static __init void pnpbios_parse_irq_option(unsigned char *p, int size, |
313 | struct pnp_option *option) | 313 | struct pnp_option *option) |
314 | { | 314 | { |
315 | struct pnp_irq *irq; | 315 | struct pnp_irq *irq; |
@@ -327,7 +327,7 @@ static void pnpbios_parse_irq_option(unsigned char *p, int size, | |||
327 | pnp_register_irq_resource(option, irq); | 327 | pnp_register_irq_resource(option, irq); |
328 | } | 328 | } |
329 | 329 | ||
330 | static void pnpbios_parse_dma_option(unsigned char *p, int size, | 330 | static __init void pnpbios_parse_dma_option(unsigned char *p, int size, |
331 | struct pnp_option *option) | 331 | struct pnp_option *option) |
332 | { | 332 | { |
333 | struct pnp_dma *dma; | 333 | struct pnp_dma *dma; |
@@ -340,8 +340,8 @@ static void pnpbios_parse_dma_option(unsigned char *p, int size, | |||
340 | pnp_register_dma_resource(option, dma); | 340 | pnp_register_dma_resource(option, dma); |
341 | } | 341 | } |
342 | 342 | ||
343 | static void pnpbios_parse_port_option(unsigned char *p, int size, | 343 | static __init void pnpbios_parse_port_option(unsigned char *p, int size, |
344 | struct pnp_option *option) | 344 | struct pnp_option *option) |
345 | { | 345 | { |
346 | struct pnp_port *port; | 346 | struct pnp_port *port; |
347 | 347 | ||
@@ -356,8 +356,8 @@ static void pnpbios_parse_port_option(unsigned char *p, int size, | |||
356 | pnp_register_port_resource(option, port); | 356 | pnp_register_port_resource(option, port); |
357 | } | 357 | } |
358 | 358 | ||
359 | static void pnpbios_parse_fixed_port_option(unsigned char *p, int size, | 359 | static __init void pnpbios_parse_fixed_port_option(unsigned char *p, int size, |
360 | struct pnp_option *option) | 360 | struct pnp_option *option) |
361 | { | 361 | { |
362 | struct pnp_port *port; | 362 | struct pnp_port *port; |
363 | 363 | ||
@@ -371,9 +371,9 @@ static void pnpbios_parse_fixed_port_option(unsigned char *p, int size, | |||
371 | pnp_register_port_resource(option, port); | 371 | pnp_register_port_resource(option, port); |
372 | } | 372 | } |
373 | 373 | ||
374 | static unsigned char *pnpbios_parse_resource_option_data(unsigned char *p, | 374 | static __init unsigned char * |
375 | unsigned char *end, | 375 | pnpbios_parse_resource_option_data(unsigned char *p, unsigned char *end, |
376 | struct pnp_dev *dev) | 376 | struct pnp_dev *dev) |
377 | { | 377 | { |
378 | unsigned int len, tag; | 378 | unsigned int len, tag; |
379 | int priority = 0; | 379 | int priority = 0; |
@@ -781,7 +781,8 @@ len_err: | |||
781 | * Core Parsing Functions | 781 | * Core Parsing Functions |
782 | */ | 782 | */ |
783 | 783 | ||
784 | int pnpbios_parse_data_stream(struct pnp_dev *dev, struct pnp_bios_node *node) | 784 | int __init pnpbios_parse_data_stream(struct pnp_dev *dev, |
785 | struct pnp_bios_node *node) | ||
785 | { | 786 | { |
786 | unsigned char *p = (char *)node->data; | 787 | unsigned char *p = (char *)node->data; |
787 | unsigned char *end = (char *)(node->data + node->size); | 788 | unsigned char *end = (char *)(node->data + node->size); |
diff --git a/drivers/pnp/quirks.c b/drivers/pnp/quirks.c index e903b8c2b1fa..4065139753b6 100644 --- a/drivers/pnp/quirks.c +++ b/drivers/pnp/quirks.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
18 | #include <linux/pnp.h> | 18 | #include <linux/pnp.h> |
19 | #include <linux/io.h> | 19 | #include <linux/io.h> |
20 | #include <linux/dmi.h> | ||
20 | #include <linux/kallsyms.h> | 21 | #include <linux/kallsyms.h> |
21 | #include "base.h" | 22 | #include "base.h" |
22 | 23 | ||
@@ -108,6 +109,46 @@ static void quirk_sb16audio_resources(struct pnp_dev *dev) | |||
108 | "pnp: SB audio device quirk - increasing port range\n"); | 109 | "pnp: SB audio device quirk - increasing port range\n"); |
109 | } | 110 | } |
110 | 111 | ||
112 | static void quirk_supermicro_h8dce_system(struct pnp_dev *dev) | ||
113 | { | ||
114 | int i; | ||
115 | static struct dmi_system_id supermicro_h8dce[] = { | ||
116 | { | ||
117 | .ident = "Supermicro H8DCE", | ||
118 | .matches = { | ||
119 | DMI_MATCH(DMI_SYS_VENDOR, "Supermicro"), | ||
120 | DMI_MATCH(DMI_PRODUCT_NAME, "H8DCE"), | ||
121 | }, | ||
122 | }, | ||
123 | { } | ||
124 | }; | ||
125 | |||
126 | if (!dmi_check_system(supermicro_h8dce)) | ||
127 | return; | ||
128 | |||
129 | /* | ||
130 | * On the Supermicro H8DCE, there's a system device with resources | ||
131 | * that overlap BAR 6 of the built-in SATA PCI adapter. If the PNP | ||
132 | * system device claims them, the sata_nv driver won't be able to. | ||
133 | * More details at: | ||
134 | * https://bugzilla.redhat.com/show_bug.cgi?id=280641 | ||
135 | * https://bugzilla.redhat.com/show_bug.cgi?id=313491 | ||
136 | * http://lkml.org/lkml/2008/1/9/449 | ||
137 | * http://thread.gmane.org/gmane.linux.acpi.devel/27312 | ||
138 | */ | ||
139 | for (i = 0; i < PNP_MAX_MEM; i++) { | ||
140 | if (pnp_mem_valid(dev, i) && pnp_mem_len(dev, i) && | ||
141 | (pnp_mem_start(dev, i) & 0xdfef0000) == 0xdfef0000) { | ||
142 | dev_warn(&dev->dev, "disabling 0x%llx-0x%llx to prevent" | ||
143 | " conflict with sata_nv PCI device\n", | ||
144 | (unsigned long long) pnp_mem_start(dev, i), | ||
145 | (unsigned long long) (pnp_mem_start(dev, i) + | ||
146 | pnp_mem_len(dev, i) - 1)); | ||
147 | pnp_mem_flags(dev, i) = 0; | ||
148 | } | ||
149 | } | ||
150 | } | ||
151 | |||
111 | /* | 152 | /* |
112 | * PnP Quirks | 153 | * PnP Quirks |
113 | * Cards or devices that need some tweaking due to incomplete resource info | 154 | * Cards or devices that need some tweaking due to incomplete resource info |
@@ -128,6 +169,8 @@ static struct pnp_fixup pnp_fixups[] = { | |||
128 | {"CTL0043", quirk_sb16audio_resources}, | 169 | {"CTL0043", quirk_sb16audio_resources}, |
129 | {"CTL0044", quirk_sb16audio_resources}, | 170 | {"CTL0044", quirk_sb16audio_resources}, |
130 | {"CTL0045", quirk_sb16audio_resources}, | 171 | {"CTL0045", quirk_sb16audio_resources}, |
172 | {"PNP0c01", quirk_supermicro_h8dce_system}, | ||
173 | {"PNP0c02", quirk_supermicro_h8dce_system}, | ||
131 | {""} | 174 | {""} |
132 | }; | 175 | }; |
133 | 176 | ||
diff --git a/drivers/power/power_supply_sysfs.c b/drivers/power/power_supply_sysfs.c index d4824840c5bf..13399d133b94 100644 --- a/drivers/power/power_supply_sysfs.c +++ b/drivers/power/power_supply_sysfs.c | |||
@@ -106,7 +106,6 @@ static struct device_attribute power_supply_attrs[] = { | |||
106 | POWER_SUPPLY_ATTR(energy_now), | 106 | POWER_SUPPLY_ATTR(energy_now), |
107 | POWER_SUPPLY_ATTR(energy_avg), | 107 | POWER_SUPPLY_ATTR(energy_avg), |
108 | POWER_SUPPLY_ATTR(capacity), | 108 | POWER_SUPPLY_ATTR(capacity), |
109 | POWER_SUPPLY_ATTR(capacity_level), | ||
110 | POWER_SUPPLY_ATTR(temp), | 109 | POWER_SUPPLY_ATTR(temp), |
111 | POWER_SUPPLY_ATTR(temp_ambient), | 110 | POWER_SUPPLY_ATTR(temp_ambient), |
112 | POWER_SUPPLY_ATTR(time_to_empty_now), | 111 | POWER_SUPPLY_ATTR(time_to_empty_now), |
diff --git a/drivers/ps3/ps3av.c b/drivers/ps3/ps3av.c index 87b3493d88e5..6f2f90ebb020 100644 --- a/drivers/ps3/ps3av.c +++ b/drivers/ps3/ps3av.c | |||
@@ -78,23 +78,21 @@ static const struct avset_video_mode { | |||
78 | u32 aspect; | 78 | u32 aspect; |
79 | u32 x; | 79 | u32 x; |
80 | u32 y; | 80 | u32 y; |
81 | u32 interlace; | ||
82 | u32 freq; | ||
83 | } video_mode_table[] = { | 81 | } video_mode_table[] = { |
84 | { 0, }, /* auto */ | 82 | { 0, }, /* auto */ |
85 | {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_480I, A_N, 720, 480, 1, 60}, | 83 | {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_480I, A_N, 720, 480}, |
86 | {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_480P, A_N, 720, 480, 0, 60}, | 84 | {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_480P, A_N, 720, 480}, |
87 | {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_720P_60HZ, A_N, 1280, 720, 0, 60}, | 85 | {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_720P_60HZ, A_N, 1280, 720}, |
88 | {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080I_60HZ, A_W, 1920, 1080, 1, 60}, | 86 | {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080I_60HZ, A_W, 1920, 1080}, |
89 | {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080P_60HZ, A_W, 1920, 1080, 0, 60}, | 87 | {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080P_60HZ, A_W, 1920, 1080}, |
90 | {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_576I, A_N, 720, 576, 1, 50}, | 88 | {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_576I, A_N, 720, 576}, |
91 | {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_576P, A_N, 720, 576, 0, 50}, | 89 | {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_576P, A_N, 720, 576}, |
92 | {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_720P_50HZ, A_N, 1280, 720, 0, 50}, | 90 | {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_720P_50HZ, A_N, 1280, 720}, |
93 | {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080I_50HZ, A_W, 1920, 1080, 1, 50}, | 91 | {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080I_50HZ, A_W, 1920, 1080}, |
94 | {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080P_50HZ, A_W, 1920, 1080, 0, 50}, | 92 | {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080P_50HZ, A_W, 1920, 1080}, |
95 | { RGB8, XRGB, PS3AV_CMD_VIDEO_VID_WXGA, A_W, 1280, 768, 0, 60}, | 93 | { RGB8, XRGB, PS3AV_CMD_VIDEO_VID_WXGA, A_W, 1280, 768}, |
96 | { RGB8, XRGB, PS3AV_CMD_VIDEO_VID_SXGA, A_N, 1280, 1024, 0, 60}, | 94 | { RGB8, XRGB, PS3AV_CMD_VIDEO_VID_SXGA, A_N, 1280, 1024}, |
97 | { RGB8, XRGB, PS3AV_CMD_VIDEO_VID_WUXGA, A_W, 1920, 1200, 0, 60}, | 95 | { RGB8, XRGB, PS3AV_CMD_VIDEO_VID_WUXGA, A_W, 1920, 1200}, |
98 | }; | 96 | }; |
99 | 97 | ||
100 | /* supported CIDs */ | 98 | /* supported CIDs */ |
@@ -544,7 +542,7 @@ static void ps3av_set_videomode_packet(u32 id) | |||
544 | 542 | ||
545 | static void ps3av_set_videomode_cont(u32 id, u32 old_id) | 543 | static void ps3av_set_videomode_cont(u32 id, u32 old_id) |
546 | { | 544 | { |
547 | static int vesa = 0; | 545 | static int vesa; |
548 | int res; | 546 | int res; |
549 | 547 | ||
550 | /* video signal off */ | 548 | /* video signal off */ |
@@ -554,9 +552,9 @@ static void ps3av_set_videomode_cont(u32 id, u32 old_id) | |||
554 | * AV backend needs non-VESA mode setting at least one time | 552 | * AV backend needs non-VESA mode setting at least one time |
555 | * when VESA mode is used. | 553 | * when VESA mode is used. |
556 | */ | 554 | */ |
557 | if (vesa == 0 && (id & PS3AV_MODE_MASK) >= 11) { | 555 | if (vesa == 0 && (id & PS3AV_MODE_MASK) >= PS3AV_MODE_WXGA) { |
558 | /* vesa mode */ | 556 | /* vesa mode */ |
559 | ps3av_set_videomode_packet(2); /* 480P */ | 557 | ps3av_set_videomode_packet(PS3AV_MODE_480P); |
560 | } | 558 | } |
561 | vesa = 1; | 559 | vesa = 1; |
562 | 560 | ||
@@ -596,20 +594,21 @@ static const struct { | |||
596 | unsigned mask : 19; | 594 | unsigned mask : 19; |
597 | unsigned id : 4; | 595 | unsigned id : 4; |
598 | } ps3av_preferred_modes[] = { | 596 | } ps3av_preferred_modes[] = { |
599 | { .mask = PS3AV_RESBIT_WUXGA << SHIFT_VESA, .id = 13 }, | 597 | { PS3AV_RESBIT_WUXGA << SHIFT_VESA, PS3AV_MODE_WUXGA }, |
600 | { .mask = PS3AV_RESBIT_1920x1080P << SHIFT_60, .id = 5 }, | 598 | { PS3AV_RESBIT_1920x1080P << SHIFT_60, PS3AV_MODE_1080P60 }, |
601 | { .mask = PS3AV_RESBIT_1920x1080P << SHIFT_50, .id = 10 }, | 599 | { PS3AV_RESBIT_1920x1080P << SHIFT_50, PS3AV_MODE_1080P50 }, |
602 | { .mask = PS3AV_RESBIT_1920x1080I << SHIFT_60, .id = 4 }, | 600 | { PS3AV_RESBIT_1920x1080I << SHIFT_60, PS3AV_MODE_1080I60 }, |
603 | { .mask = PS3AV_RESBIT_1920x1080I << SHIFT_50, .id = 9 }, | 601 | { PS3AV_RESBIT_1920x1080I << SHIFT_50, PS3AV_MODE_1080I50 }, |
604 | { .mask = PS3AV_RESBIT_SXGA << SHIFT_VESA, .id = 12 }, | 602 | { PS3AV_RESBIT_SXGA << SHIFT_VESA, PS3AV_MODE_SXGA }, |
605 | { .mask = PS3AV_RESBIT_WXGA << SHIFT_VESA, .id = 11 }, | 603 | { PS3AV_RESBIT_WXGA << SHIFT_VESA, PS3AV_MODE_WXGA }, |
606 | { .mask = PS3AV_RESBIT_1280x720P << SHIFT_60, .id = 3 }, | 604 | { PS3AV_RESBIT_1280x720P << SHIFT_60, PS3AV_MODE_720P60 }, |
607 | { .mask = PS3AV_RESBIT_1280x720P << SHIFT_50, .id = 8 }, | 605 | { PS3AV_RESBIT_1280x720P << SHIFT_50, PS3AV_MODE_720P50 }, |
608 | { .mask = PS3AV_RESBIT_720x480P << SHIFT_60, .id = 2 }, | 606 | { PS3AV_RESBIT_720x480P << SHIFT_60, PS3AV_MODE_480P }, |
609 | { .mask = PS3AV_RESBIT_720x576P << SHIFT_50, .id = 7 }, | 607 | { PS3AV_RESBIT_720x576P << SHIFT_50, PS3AV_MODE_576P }, |
610 | }; | 608 | }; |
611 | 609 | ||
612 | static int ps3av_resbit2id(u32 res_50, u32 res_60, u32 res_vesa) | 610 | static enum ps3av_mode_num ps3av_resbit2id(u32 res_50, u32 res_60, |
611 | u32 res_vesa) | ||
613 | { | 612 | { |
614 | unsigned int i; | 613 | unsigned int i; |
615 | u32 res_all; | 614 | u32 res_all; |
@@ -638,9 +637,9 @@ static int ps3av_resbit2id(u32 res_50, u32 res_60, u32 res_vesa) | |||
638 | return 0; | 637 | return 0; |
639 | } | 638 | } |
640 | 639 | ||
641 | static int ps3av_hdmi_get_id(struct ps3av_info_monitor *info) | 640 | static enum ps3av_mode_num ps3av_hdmi_get_id(struct ps3av_info_monitor *info) |
642 | { | 641 | { |
643 | int id; | 642 | enum ps3av_mode_num id; |
644 | 643 | ||
645 | if (safe_mode) | 644 | if (safe_mode) |
646 | return PS3AV_DEFAULT_HDMI_MODE_ID_REG_60; | 645 | return PS3AV_DEFAULT_HDMI_MODE_ID_REG_60; |
@@ -854,7 +853,7 @@ int ps3av_set_video_mode(u32 id) | |||
854 | 853 | ||
855 | /* auto mode */ | 854 | /* auto mode */ |
856 | option = id & ~PS3AV_MODE_MASK; | 855 | option = id & ~PS3AV_MODE_MASK; |
857 | if ((id & PS3AV_MODE_MASK) == 0) { | 856 | if ((id & PS3AV_MODE_MASK) == PS3AV_MODE_AUTO) { |
858 | id = ps3av_auto_videomode(&ps3av->av_hw_conf); | 857 | id = ps3av_auto_videomode(&ps3av->av_hw_conf); |
859 | if (id < 1) { | 858 | if (id < 1) { |
860 | printk(KERN_ERR "%s: invalid id :%d\n", __func__, id); | 859 | printk(KERN_ERR "%s: invalid id :%d\n", __func__, id); |
@@ -889,36 +888,6 @@ int ps3av_get_mode(void) | |||
889 | 888 | ||
890 | EXPORT_SYMBOL_GPL(ps3av_get_mode); | 889 | EXPORT_SYMBOL_GPL(ps3av_get_mode); |
891 | 890 | ||
892 | int ps3av_get_scanmode(int id) | ||
893 | { | ||
894 | int size; | ||
895 | |||
896 | id = id & PS3AV_MODE_MASK; | ||
897 | size = ARRAY_SIZE(video_mode_table); | ||
898 | if (id > size - 1 || id < 0) { | ||
899 | printk(KERN_ERR "%s: invalid mode %d\n", __func__, id); | ||
900 | return -EINVAL; | ||
901 | } | ||
902 | return video_mode_table[id].interlace; | ||
903 | } | ||
904 | |||
905 | EXPORT_SYMBOL_GPL(ps3av_get_scanmode); | ||
906 | |||
907 | int ps3av_get_refresh_rate(int id) | ||
908 | { | ||
909 | int size; | ||
910 | |||
911 | id = id & PS3AV_MODE_MASK; | ||
912 | size = ARRAY_SIZE(video_mode_table); | ||
913 | if (id > size - 1 || id < 0) { | ||
914 | printk(KERN_ERR "%s: invalid mode %d\n", __func__, id); | ||
915 | return -EINVAL; | ||
916 | } | ||
917 | return video_mode_table[id].freq; | ||
918 | } | ||
919 | |||
920 | EXPORT_SYMBOL_GPL(ps3av_get_refresh_rate); | ||
921 | |||
922 | /* get resolution by video_mode */ | 891 | /* get resolution by video_mode */ |
923 | int ps3av_video_mode2res(u32 id, u32 *xres, u32 *yres) | 892 | int ps3av_video_mode2res(u32 id, u32 *xres, u32 *yres) |
924 | { | 893 | { |
@@ -990,7 +959,7 @@ static int ps3av_probe(struct ps3_system_bus_device *dev) | |||
990 | return -ENOMEM; | 959 | return -ENOMEM; |
991 | 960 | ||
992 | mutex_init(&ps3av->mutex); | 961 | mutex_init(&ps3av->mutex); |
993 | ps3av->ps3av_mode = 0; | 962 | ps3av->ps3av_mode = PS3AV_MODE_AUTO; |
994 | ps3av->dev = dev; | 963 | ps3av->dev = dev; |
995 | 964 | ||
996 | INIT_WORK(&ps3av->work, ps3avd); | 965 | INIT_WORK(&ps3av->work, ps3avd); |
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 45e4b9648176..6402d699072b 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig | |||
@@ -20,6 +20,10 @@ menuconfig RTC_CLASS | |||
20 | 20 | ||
21 | if RTC_CLASS | 21 | if RTC_CLASS |
22 | 22 | ||
23 | if GEN_RTC || RTC | ||
24 | comment "Conflicting RTC option has been selected, check GEN_RTC and RTC" | ||
25 | endif | ||
26 | |||
23 | config RTC_HCTOSYS | 27 | config RTC_HCTOSYS |
24 | bool "Set system time from RTC on startup and resume" | 28 | bool "Set system time from RTC on startup and resume" |
25 | depends on RTC_CLASS = y | 29 | depends on RTC_CLASS = y |
@@ -49,7 +53,7 @@ config RTC_HCTOSYS_DEVICE | |||
49 | 53 | ||
50 | If the clock you specify here is not battery backed, it may still | 54 | If the clock you specify here is not battery backed, it may still |
51 | be useful to reinitialize system time when resuming from system | 55 | be useful to reinitialize system time when resuming from system |
52 | sleep states. Do not specify an RTC here unless it stays powered | 56 | sleep states. Do not specify an RTC here unless it stays powered |
53 | during all this system's supported sleep states. | 57 | during all this system's supported sleep states. |
54 | 58 | ||
55 | config RTC_DEBUG | 59 | config RTC_DEBUG |
@@ -142,7 +146,7 @@ config RTC_DRV_DS1307 | |||
142 | will be called rtc-ds1307. | 146 | will be called rtc-ds1307. |
143 | 147 | ||
144 | config RTC_DRV_DS1374 | 148 | config RTC_DRV_DS1374 |
145 | tristate "Maxim/Dallas Semiconductor DS1374 Real Time Clock" | 149 | tristate "Dallas/Maxim DS1374" |
146 | depends on RTC_CLASS && I2C | 150 | depends on RTC_CLASS && I2C |
147 | help | 151 | help |
148 | If you say yes here you get support for Dallas Semiconductor | 152 | If you say yes here you get support for Dallas Semiconductor |
@@ -162,7 +166,7 @@ config RTC_DRV_DS1672 | |||
162 | will be called rtc-ds1672. | 166 | will be called rtc-ds1672. |
163 | 167 | ||
164 | config RTC_DRV_MAX6900 | 168 | config RTC_DRV_MAX6900 |
165 | tristate "Maxim 6900" | 169 | tristate "Maxim MAX6900" |
166 | help | 170 | help |
167 | If you say yes here you will get support for the | 171 | If you say yes here you will get support for the |
168 | Maxim MAX6900 I2C RTC chip. | 172 | Maxim MAX6900 I2C RTC chip. |
@@ -180,10 +184,10 @@ config RTC_DRV_RS5C372 | |||
180 | will be called rtc-rs5c372. | 184 | will be called rtc-rs5c372. |
181 | 185 | ||
182 | config RTC_DRV_ISL1208 | 186 | config RTC_DRV_ISL1208 |
183 | tristate "Intersil 1208" | 187 | tristate "Intersil ISL1208" |
184 | help | 188 | help |
185 | If you say yes here you get support for the | 189 | If you say yes here you get support for the |
186 | Intersil 1208 RTC chip. | 190 | Intersil ISL1208 RTC chip. |
187 | 191 | ||
188 | This driver can also be built as a module. If so, the module | 192 | This driver can also be built as a module. If so, the module |
189 | will be called rtc-isl1208. | 193 | will be called rtc-isl1208. |
@@ -220,7 +224,7 @@ config RTC_DRV_PCF8583 | |||
220 | will be called rtc-pcf8583. | 224 | will be called rtc-pcf8583. |
221 | 225 | ||
222 | config RTC_DRV_M41T80 | 226 | config RTC_DRV_M41T80 |
223 | tristate "ST M41T80 series RTC" | 227 | tristate "ST M41T80/81/82/83/84/85/87" |
224 | help | 228 | help |
225 | If you say Y here you will get support for the | 229 | If you say Y here you will get support for the |
226 | ST M41T80 RTC chips series. Currently following chips are | 230 | ST M41T80 RTC chips series. Currently following chips are |
@@ -252,23 +256,32 @@ comment "SPI RTC drivers" | |||
252 | 256 | ||
253 | if SPI_MASTER | 257 | if SPI_MASTER |
254 | 258 | ||
255 | config RTC_DRV_RS5C348 | 259 | config RTC_DRV_MAX6902 |
256 | tristate "Ricoh RS5C348A/B" | 260 | tristate "Maxim MAX6902" |
257 | help | 261 | help |
258 | If you say yes here you get support for the | 262 | If you say yes here you will get support for the |
259 | Ricoh RS5C348A and RS5C348B RTC chips. | 263 | Maxim MAX6902 SPI RTC chip. |
260 | 264 | ||
261 | This driver can also be built as a module. If so, the module | 265 | This driver can also be built as a module. If so, the module |
262 | will be called rtc-rs5c348. | 266 | will be called rtc-max6902. |
263 | 267 | ||
264 | config RTC_DRV_MAX6902 | 268 | config RTC_DRV_R9701 |
265 | tristate "Maxim 6902" | 269 | tristate "Epson RTC-9701JE" |
266 | help | 270 | help |
267 | If you say yes here you will get support for the | 271 | If you say yes here you will get support for the |
268 | Maxim MAX6902 SPI RTC chip. | 272 | Epson RTC-9701JE SPI RTC chip. |
269 | 273 | ||
270 | This driver can also be built as a module. If so, the module | 274 | This driver can also be built as a module. If so, the module |
271 | will be called rtc-max6902. | 275 | will be called rtc-r9701. |
276 | |||
277 | config RTC_DRV_RS5C348 | ||
278 | tristate "Ricoh RS5C348A/B" | ||
279 | help | ||
280 | If you say yes here you get support for the | ||
281 | Ricoh RS5C348A and RS5C348B RTC chips. | ||
282 | |||
283 | This driver can also be built as a module. If so, the module | ||
284 | will be called rtc-rs5c348. | ||
272 | 285 | ||
273 | endif # SPI_MASTER | 286 | endif # SPI_MASTER |
274 | 287 | ||
@@ -302,34 +315,50 @@ config RTC_DRV_DS1216 | |||
302 | help | 315 | help |
303 | If you say yes here you get support for the Dallas DS1216 RTC chips. | 316 | If you say yes here you get support for the Dallas DS1216 RTC chips. |
304 | 317 | ||
305 | config RTC_DRV_DS1553 | 318 | config RTC_DRV_DS1302 |
306 | tristate "Dallas DS1553" | 319 | tristate "Dallas DS1302" |
320 | depends on SH_SECUREEDGE5410 | ||
321 | help | ||
322 | If you say yes here you get support for the Dallas DS1302 RTC chips. | ||
323 | |||
324 | config RTC_DRV_DS1511 | ||
325 | tristate "Dallas DS1511" | ||
326 | depends on RTC_CLASS | ||
307 | help | 327 | help |
308 | If you say yes here you get support for the | 328 | If you say yes here you get support for the |
309 | Dallas DS1553 timekeeping chip. | 329 | Dallas DS1511 timekeeping/watchdog chip. |
310 | 330 | ||
311 | This driver can also be built as a module. If so, the module | 331 | This driver can also be built as a module. If so, the module |
312 | will be called rtc-ds1553. | 332 | will be called rtc-ds1511. |
313 | 333 | ||
314 | config RTC_DRV_STK17TA8 | 334 | config RTC_DRV_DS1553 |
315 | tristate "Simtek STK17TA8" | 335 | tristate "Maxim/Dallas DS1553" |
316 | depends on RTC_CLASS | ||
317 | help | 336 | help |
318 | If you say yes here you get support for the | 337 | If you say yes here you get support for the |
319 | Simtek STK17TA8 timekeeping chip. | 338 | Maxim/Dallas DS1553 timekeeping chip. |
320 | 339 | ||
321 | This driver can also be built as a module. If so, the module | 340 | This driver can also be built as a module. If so, the module |
322 | will be called rtc-stk17ta8. | 341 | will be called rtc-ds1553. |
323 | 342 | ||
324 | config RTC_DRV_DS1742 | 343 | config RTC_DRV_DS1742 |
325 | tristate "Dallas DS1742/1743" | 344 | tristate "Maxim/Dallas DS1742/1743" |
326 | help | 345 | help |
327 | If you say yes here you get support for the | 346 | If you say yes here you get support for the |
328 | Dallas DS1742/1743 timekeeping chip. | 347 | Maxim/Dallas DS1742/1743 timekeeping chip. |
329 | 348 | ||
330 | This driver can also be built as a module. If so, the module | 349 | This driver can also be built as a module. If so, the module |
331 | will be called rtc-ds1742. | 350 | will be called rtc-ds1742. |
332 | 351 | ||
352 | config RTC_DRV_STK17TA8 | ||
353 | tristate "Simtek STK17TA8" | ||
354 | depends on RTC_CLASS | ||
355 | help | ||
356 | If you say yes here you get support for the | ||
357 | Simtek STK17TA8 timekeeping chip. | ||
358 | |||
359 | This driver can also be built as a module. If so, the module | ||
360 | will be called rtc-stk17ta8. | ||
361 | |||
333 | config RTC_DRV_M48T86 | 362 | config RTC_DRV_M48T86 |
334 | tristate "ST M48T86/Dallas DS12887" | 363 | tristate "ST M48T86/Dallas DS12887" |
335 | help | 364 | help |
@@ -440,10 +469,47 @@ config RTC_DRV_AT32AP700X | |||
440 | AT32AP700x family processors. | 469 | AT32AP700x family processors. |
441 | 470 | ||
442 | config RTC_DRV_AT91RM9200 | 471 | config RTC_DRV_AT91RM9200 |
443 | tristate "AT91RM9200" | 472 | tristate "AT91RM9200 or AT91SAM9RL" |
444 | depends on ARCH_AT91RM9200 | 473 | depends on ARCH_AT91RM9200 || ARCH_AT91SAM9RL |
445 | help | 474 | help |
446 | Driver for the Atmel AT91RM9200's internal RTC (Realtime Clock). | 475 | Driver for the internal RTC (Realtime Clock) module found on |
476 | Atmel AT91RM9200's and AT91SAM9RL chips. On SAM9RL chips | ||
477 | this is powered by the backup power supply. | ||
478 | |||
479 | config RTC_DRV_AT91SAM9 | ||
480 | tristate "AT91SAM9x" | ||
481 | depends on ARCH_AT91 && !(ARCH_AT91RM9200 || ARCH_AT91X40) | ||
482 | help | ||
483 | RTC driver for the Atmel AT91SAM9x internal RTT (Real Time Timer). | ||
484 | These timers are powered by the backup power supply (such as a | ||
485 | small coin cell battery), but do not need to be used as RTCs. | ||
486 | |||
487 | (On AT91SAM9rl chips you probably want to use the dedicated RTC | ||
488 | module and leave the RTT available for other uses.) | ||
489 | |||
490 | config RTC_DRV_AT91SAM9_RTT | ||
491 | int | ||
492 | range 0 1 | ||
493 | default 0 | ||
494 | prompt "RTT module Number" if ARCH_AT91SAM9263 | ||
495 | depends on RTC_DRV_AT91SAM9 | ||
496 | help | ||
497 | More than one RTT module is available. You can choose which | ||
498 | one will be used as an RTC. The default of zero is normally | ||
499 | OK to use, though some systems use that for non-RTC purposes. | ||
500 | |||
501 | config RTC_DRV_AT91SAM9_GPBR | ||
502 | int | ||
503 | range 0 3 if !ARCH_AT91SAM9263 | ||
504 | range 0 15 if ARCH_AT91SAM9263 | ||
505 | default 0 | ||
506 | prompt "Backup Register Number" | ||
507 | depends on RTC_DRV_AT91SAM9 | ||
508 | help | ||
509 | The RTC driver needs to use one of the General Purpose Backup | ||
510 | Registers (GPBRs) as well as the RTT. You can choose which one | ||
511 | will be used. The default of zero is normally OK to use, but | ||
512 | on some systems other software needs to use that register. | ||
447 | 513 | ||
448 | config RTC_DRV_BFIN | 514 | config RTC_DRV_BFIN |
449 | tristate "Blackfin On-Chip RTC" | 515 | tristate "Blackfin On-Chip RTC" |
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 465db4dd50b2..ec703f34ab86 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile | |||
@@ -19,11 +19,14 @@ rtc-core-$(CONFIG_RTC_INTF_SYSFS) += rtc-sysfs.o | |||
19 | 19 | ||
20 | obj-$(CONFIG_RTC_DRV_AT32AP700X)+= rtc-at32ap700x.o | 20 | obj-$(CONFIG_RTC_DRV_AT32AP700X)+= rtc-at32ap700x.o |
21 | obj-$(CONFIG_RTC_DRV_AT91RM9200)+= rtc-at91rm9200.o | 21 | obj-$(CONFIG_RTC_DRV_AT91RM9200)+= rtc-at91rm9200.o |
22 | obj-$(CONFIG_RTC_DRV_AT91SAM9) += rtc-at91sam9.o | ||
22 | obj-$(CONFIG_RTC_DRV_BFIN) += rtc-bfin.o | 23 | obj-$(CONFIG_RTC_DRV_BFIN) += rtc-bfin.o |
23 | obj-$(CONFIG_RTC_DRV_CMOS) += rtc-cmos.o | 24 | obj-$(CONFIG_RTC_DRV_CMOS) += rtc-cmos.o |
24 | obj-$(CONFIG_RTC_DRV_DS1216) += rtc-ds1216.o | 25 | obj-$(CONFIG_RTC_DRV_DS1216) += rtc-ds1216.o |
26 | obj-$(CONFIG_RTC_DRV_DS1302) += rtc-ds1302.o | ||
25 | obj-$(CONFIG_RTC_DRV_DS1307) += rtc-ds1307.o | 27 | obj-$(CONFIG_RTC_DRV_DS1307) += rtc-ds1307.o |
26 | obj-$(CONFIG_RTC_DRV_DS1374) += rtc-ds1374.o | 28 | obj-$(CONFIG_RTC_DRV_DS1374) += rtc-ds1374.o |
29 | obj-$(CONFIG_RTC_DRV_DS1511) += rtc-ds1511.o | ||
27 | obj-$(CONFIG_RTC_DRV_DS1553) += rtc-ds1553.o | 30 | obj-$(CONFIG_RTC_DRV_DS1553) += rtc-ds1553.o |
28 | obj-$(CONFIG_RTC_DRV_DS1672) += rtc-ds1672.o | 31 | obj-$(CONFIG_RTC_DRV_DS1672) += rtc-ds1672.o |
29 | obj-$(CONFIG_RTC_DRV_DS1742) += rtc-ds1742.o | 32 | obj-$(CONFIG_RTC_DRV_DS1742) += rtc-ds1742.o |
@@ -38,6 +41,7 @@ obj-$(CONFIG_RTC_DRV_OMAP) += rtc-omap.o | |||
38 | obj-$(CONFIG_RTC_DRV_PCF8563) += rtc-pcf8563.o | 41 | obj-$(CONFIG_RTC_DRV_PCF8563) += rtc-pcf8563.o |
39 | obj-$(CONFIG_RTC_DRV_PCF8583) += rtc-pcf8583.o | 42 | obj-$(CONFIG_RTC_DRV_PCF8583) += rtc-pcf8583.o |
40 | obj-$(CONFIG_RTC_DRV_PL031) += rtc-pl031.o | 43 | obj-$(CONFIG_RTC_DRV_PL031) += rtc-pl031.o |
44 | obj-$(CONFIG_RTC_DRV_R9701) += rtc-r9701.o | ||
41 | obj-$(CONFIG_RTC_DRV_RS5C313) += rtc-rs5c313.o | 45 | obj-$(CONFIG_RTC_DRV_RS5C313) += rtc-rs5c313.o |
42 | obj-$(CONFIG_RTC_DRV_RS5C348) += rtc-rs5c348.o | 46 | obj-$(CONFIG_RTC_DRV_RS5C348) += rtc-rs5c348.o |
43 | obj-$(CONFIG_RTC_DRV_RS5C372) += rtc-rs5c372.o | 47 | obj-$(CONFIG_RTC_DRV_RS5C372) += rtc-rs5c372.o |
diff --git a/drivers/rtc/rtc-at91sam9.c b/drivers/rtc/rtc-at91sam9.c new file mode 100644 index 000000000000..bbf10ecf416c --- /dev/null +++ b/drivers/rtc/rtc-at91sam9.c | |||
@@ -0,0 +1,520 @@ | |||
1 | /* | ||
2 | * "RTT as Real Time Clock" driver for AT91SAM9 SoC family | ||
3 | * | ||
4 | * (C) 2007 Michel Benoit | ||
5 | * | ||
6 | * Based on rtc-at91rm9200.c by Rick Bronson | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * as published by the Free Software Foundation; either version | ||
11 | * 2 of the License, or (at your option) any later version. | ||
12 | */ | ||
13 | |||
14 | #include <linux/module.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/platform_device.h> | ||
17 | #include <linux/time.h> | ||
18 | #include <linux/rtc.h> | ||
19 | #include <linux/interrupt.h> | ||
20 | #include <linux/ioctl.h> | ||
21 | |||
22 | #include <asm/mach/time.h> | ||
23 | #include <asm/arch/board.h> | ||
24 | #include <asm/arch/at91_rtt.h> | ||
25 | |||
26 | |||
27 | /* | ||
28 | * This driver uses two configurable hardware resources that live in the | ||
29 | * AT91SAM9 backup power domain (intended to be powered at all times) | ||
30 | * to implement the Real Time Clock interfaces | ||
31 | * | ||
32 | * - A "Real-time Timer" (RTT) counts up in seconds from a base time. | ||
33 | * We can't assign the counter value (CRTV) ... but we can reset it. | ||
34 | * | ||
35 | * - One of the "General Purpose Backup Registers" (GPBRs) holds the | ||
36 | * base time, normally an offset from the beginning of the POSIX | ||
37 | * epoch (1970-Jan-1 00:00:00 UTC). Some systems also include the | ||
38 | * local timezone's offset. | ||
39 | * | ||
40 | * The RTC's value is the RTT counter plus that offset. The RTC's alarm | ||
41 | * is likewise a base (ALMV) plus that offset. | ||
42 | * | ||
43 | * Not all RTTs will be used as RTCs; some systems have multiple RTTs to | ||
44 | * choose from, or a "real" RTC module. All systems have multiple GPBR | ||
45 | * registers available, likewise usable for more than "RTC" support. | ||
46 | */ | ||
47 | |||
48 | /* | ||
49 | * We store ALARM_DISABLED in ALMV to record that no alarm is set. | ||
50 | * It's also the reset value for that field. | ||
51 | */ | ||
52 | #define ALARM_DISABLED ((u32)~0) | ||
53 | |||
54 | |||
55 | struct sam9_rtc { | ||
56 | void __iomem *rtt; | ||
57 | struct rtc_device *rtcdev; | ||
58 | u32 imr; | ||
59 | }; | ||
60 | |||
61 | #define rtt_readl(rtc, field) \ | ||
62 | __raw_readl((rtc)->rtt + AT91_RTT_ ## field) | ||
63 | #define rtt_writel(rtc, field, val) \ | ||
64 | __raw_writel((val), (rtc)->rtt + AT91_RTT_ ## field) | ||
65 | |||
66 | #define gpbr_readl(rtc) \ | ||
67 | at91_sys_read(AT91_GPBR + 4 * CONFIG_RTC_DRV_AT91SAM9_GPBR) | ||
68 | #define gpbr_writel(rtc, val) \ | ||
69 | at91_sys_write(AT91_GPBR + 4 * CONFIG_RTC_DRV_AT91SAM9_GPBR, (val)) | ||
70 | |||
71 | /* | ||
72 | * Read current time and date in RTC | ||
73 | */ | ||
74 | static int at91_rtc_readtime(struct device *dev, struct rtc_time *tm) | ||
75 | { | ||
76 | struct sam9_rtc *rtc = dev_get_drvdata(dev); | ||
77 | u32 secs, secs2; | ||
78 | u32 offset; | ||
79 | |||
80 | /* read current time offset */ | ||
81 | offset = gpbr_readl(rtc); | ||
82 | if (offset == 0) | ||
83 | return -EILSEQ; | ||
84 | |||
85 | /* reread the counter to help sync the two clock domains */ | ||
86 | secs = rtt_readl(rtc, VR); | ||
87 | secs2 = rtt_readl(rtc, VR); | ||
88 | if (secs != secs2) | ||
89 | secs = rtt_readl(rtc, VR); | ||
90 | |||
91 | rtc_time_to_tm(offset + secs, tm); | ||
92 | |||
93 | dev_dbg(dev, "%s: %4d-%02d-%02d %02d:%02d:%02d\n", "readtime", | ||
94 | 1900 + tm->tm_year, tm->tm_mon, tm->tm_mday, | ||
95 | tm->tm_hour, tm->tm_min, tm->tm_sec); | ||
96 | |||
97 | return 0; | ||
98 | } | ||
99 | |||
100 | /* | ||
101 | * Set current time and date in RTC | ||
102 | */ | ||
103 | static int at91_rtc_settime(struct device *dev, struct rtc_time *tm) | ||
104 | { | ||
105 | struct sam9_rtc *rtc = dev_get_drvdata(dev); | ||
106 | int err; | ||
107 | u32 offset, alarm, mr; | ||
108 | unsigned long secs; | ||
109 | |||
110 | dev_dbg(dev, "%s: %4d-%02d-%02d %02d:%02d:%02d\n", "settime", | ||
111 | 1900 + tm->tm_year, tm->tm_mon, tm->tm_mday, | ||
112 | tm->tm_hour, tm->tm_min, tm->tm_sec); | ||
113 | |||
114 | err = rtc_tm_to_time(tm, &secs); | ||
115 | if (err != 0) | ||
116 | return err; | ||
117 | |||
118 | mr = rtt_readl(rtc, MR); | ||
119 | |||
120 | /* disable interrupts */ | ||
121 | rtt_writel(rtc, MR, mr & ~(AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN)); | ||
122 | |||
123 | /* read current time offset */ | ||
124 | offset = gpbr_readl(rtc); | ||
125 | |||
126 | /* store the new base time in a battery backup register */ | ||
127 | secs += 1; | ||
128 | gpbr_writel(rtc, secs); | ||
129 | |||
130 | /* adjust the alarm time for the new base */ | ||
131 | alarm = rtt_readl(rtc, AR); | ||
132 | if (alarm != ALARM_DISABLED) { | ||
133 | if (offset > secs) { | ||
134 | /* time jumped backwards, increase time until alarm */ | ||
135 | alarm += (offset - secs); | ||
136 | } else if ((alarm + offset) > secs) { | ||
137 | /* time jumped forwards, decrease time until alarm */ | ||
138 | alarm -= (secs - offset); | ||
139 | } else { | ||
140 | /* time jumped past the alarm, disable alarm */ | ||
141 | alarm = ALARM_DISABLED; | ||
142 | mr &= ~AT91_RTT_ALMIEN; | ||
143 | } | ||
144 | rtt_writel(rtc, AR, alarm); | ||
145 | } | ||
146 | |||
147 | /* reset the timer, and re-enable interrupts */ | ||
148 | rtt_writel(rtc, MR, mr | AT91_RTT_RTTRST); | ||
149 | |||
150 | return 0; | ||
151 | } | ||
152 | |||
153 | static int at91_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
154 | { | ||
155 | struct sam9_rtc *rtc = dev_get_drvdata(dev); | ||
156 | struct rtc_time *tm = &alrm->time; | ||
157 | u32 alarm = rtt_readl(rtc, AR); | ||
158 | u32 offset; | ||
159 | |||
160 | offset = gpbr_readl(rtc); | ||
161 | if (offset == 0) | ||
162 | return -EILSEQ; | ||
163 | |||
164 | memset(alrm, 0, sizeof(alrm)); | ||
165 | if (alarm != ALARM_DISABLED && offset != 0) { | ||
166 | rtc_time_to_tm(offset + alarm, tm); | ||
167 | |||
168 | dev_dbg(dev, "%s: %4d-%02d-%02d %02d:%02d:%02d\n", "readalarm", | ||
169 | 1900 + tm->tm_year, tm->tm_mon, tm->tm_mday, | ||
170 | tm->tm_hour, tm->tm_min, tm->tm_sec); | ||
171 | |||
172 | if (rtt_readl(rtc, MR) & AT91_RTT_ALMIEN) | ||
173 | alrm->enabled = 1; | ||
174 | } | ||
175 | |||
176 | return 0; | ||
177 | } | ||
178 | |||
179 | static int at91_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
180 | { | ||
181 | struct sam9_rtc *rtc = dev_get_drvdata(dev); | ||
182 | struct rtc_time *tm = &alrm->time; | ||
183 | unsigned long secs; | ||
184 | u32 offset; | ||
185 | u32 mr; | ||
186 | int err; | ||
187 | |||
188 | err = rtc_tm_to_time(tm, &secs); | ||
189 | if (err != 0) | ||
190 | return err; | ||
191 | |||
192 | offset = gpbr_readl(rtc); | ||
193 | if (offset == 0) { | ||
194 | /* time is not set */ | ||
195 | return -EILSEQ; | ||
196 | } | ||
197 | mr = rtt_readl(rtc, MR); | ||
198 | rtt_writel(rtc, MR, mr & ~AT91_RTT_ALMIEN); | ||
199 | |||
200 | /* alarm in the past? finish and leave disabled */ | ||
201 | if (secs <= offset) { | ||
202 | rtt_writel(rtc, AR, ALARM_DISABLED); | ||
203 | return 0; | ||
204 | } | ||
205 | |||
206 | /* else set alarm and maybe enable it */ | ||
207 | rtt_writel(rtc, AR, secs - offset); | ||
208 | if (alrm->enabled) | ||
209 | rtt_writel(rtc, MR, mr | AT91_RTT_ALMIEN); | ||
210 | |||
211 | dev_dbg(dev, "%s: %4d-%02d-%02d %02d:%02d:%02d\n", "setalarm", | ||
212 | tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour, | ||
213 | tm->tm_min, tm->tm_sec); | ||
214 | |||
215 | return 0; | ||
216 | } | ||
217 | |||
218 | /* | ||
219 | * Handle commands from user-space | ||
220 | */ | ||
221 | static int at91_rtc_ioctl(struct device *dev, unsigned int cmd, | ||
222 | unsigned long arg) | ||
223 | { | ||
224 | struct sam9_rtc *rtc = dev_get_drvdata(dev); | ||
225 | int ret = 0; | ||
226 | u32 mr = rtt_readl(rtc, MR); | ||
227 | |||
228 | dev_dbg(dev, "ioctl: cmd=%08x, arg=%08lx, mr %08x\n", cmd, arg, mr); | ||
229 | |||
230 | switch (cmd) { | ||
231 | case RTC_AIE_OFF: /* alarm off */ | ||
232 | rtt_writel(rtc, MR, mr & ~AT91_RTT_ALMIEN); | ||
233 | break; | ||
234 | case RTC_AIE_ON: /* alarm on */ | ||
235 | rtt_writel(rtc, MR, mr | AT91_RTT_ALMIEN); | ||
236 | break; | ||
237 | case RTC_UIE_OFF: /* update off */ | ||
238 | rtt_writel(rtc, MR, mr & ~AT91_RTT_RTTINCIEN); | ||
239 | break; | ||
240 | case RTC_UIE_ON: /* update on */ | ||
241 | rtt_writel(rtc, MR, mr | AT91_RTT_RTTINCIEN); | ||
242 | break; | ||
243 | default: | ||
244 | ret = -ENOIOCTLCMD; | ||
245 | break; | ||
246 | } | ||
247 | |||
248 | return ret; | ||
249 | } | ||
250 | |||
251 | /* | ||
252 | * Provide additional RTC information in /proc/driver/rtc | ||
253 | */ | ||
254 | static int at91_rtc_proc(struct device *dev, struct seq_file *seq) | ||
255 | { | ||
256 | struct sam9_rtc *rtc = dev_get_drvdata(dev); | ||
257 | u32 mr = mr = rtt_readl(rtc, MR); | ||
258 | |||
259 | seq_printf(seq, "update_IRQ\t: %s\n", | ||
260 | (mr & AT91_RTT_RTTINCIEN) ? "yes" : "no"); | ||
261 | return 0; | ||
262 | } | ||
263 | |||
264 | /* | ||
265 | * IRQ handler for the RTC | ||
266 | */ | ||
267 | static irqreturn_t at91_rtc_interrupt(int irq, void *_rtc) | ||
268 | { | ||
269 | struct sam9_rtc *rtc = _rtc; | ||
270 | u32 sr, mr; | ||
271 | unsigned long events = 0; | ||
272 | |||
273 | /* Shared interrupt may be for another device. Note: reading | ||
274 | * SR clears it, so we must only read it in this irq handler! | ||
275 | */ | ||
276 | mr = rtt_readl(rtc, MR) & (AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN); | ||
277 | sr = rtt_readl(rtc, SR) & mr; | ||
278 | if (!sr) | ||
279 | return IRQ_NONE; | ||
280 | |||
281 | /* alarm status */ | ||
282 | if (sr & AT91_RTT_ALMS) | ||
283 | events |= (RTC_AF | RTC_IRQF); | ||
284 | |||
285 | /* timer update/increment */ | ||
286 | if (sr & AT91_RTT_RTTINC) | ||
287 | events |= (RTC_UF | RTC_IRQF); | ||
288 | |||
289 | rtc_update_irq(rtc->rtcdev, 1, events); | ||
290 | |||
291 | pr_debug("%s: num=%ld, events=0x%02lx\n", __FUNCTION__, | ||
292 | events >> 8, events & 0x000000FF); | ||
293 | |||
294 | return IRQ_HANDLED; | ||
295 | } | ||
296 | |||
297 | static const struct rtc_class_ops at91_rtc_ops = { | ||
298 | .ioctl = at91_rtc_ioctl, | ||
299 | .read_time = at91_rtc_readtime, | ||
300 | .set_time = at91_rtc_settime, | ||
301 | .read_alarm = at91_rtc_readalarm, | ||
302 | .set_alarm = at91_rtc_setalarm, | ||
303 | .proc = at91_rtc_proc, | ||
304 | }; | ||
305 | |||
306 | /* | ||
307 | * Initialize and install RTC driver | ||
308 | */ | ||
309 | static int __init at91_rtc_probe(struct platform_device *pdev) | ||
310 | { | ||
311 | struct resource *r; | ||
312 | struct sam9_rtc *rtc; | ||
313 | int ret; | ||
314 | u32 mr; | ||
315 | |||
316 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
317 | if (!r) | ||
318 | return -ENODEV; | ||
319 | |||
320 | rtc = kzalloc(sizeof *rtc, GFP_KERNEL); | ||
321 | if (!rtc) | ||
322 | return -ENOMEM; | ||
323 | |||
324 | platform_set_drvdata(pdev, rtc); | ||
325 | rtc->rtt = (void __force __iomem *) (AT91_VA_BASE_SYS - AT91_BASE_SYS); | ||
326 | rtc->rtt += r->start; | ||
327 | |||
328 | mr = rtt_readl(rtc, MR); | ||
329 | |||
330 | /* unless RTT is counting at 1 Hz, re-initialize it */ | ||
331 | if ((mr & AT91_RTT_RTPRES) != AT91_SLOW_CLOCK) { | ||
332 | mr = AT91_RTT_RTTRST | (AT91_SLOW_CLOCK & AT91_RTT_RTPRES); | ||
333 | gpbr_writel(rtc, 0); | ||
334 | } | ||
335 | |||
336 | /* disable all interrupts (same as on shutdown path) */ | ||
337 | mr &= ~(AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN); | ||
338 | rtt_writel(rtc, MR, mr); | ||
339 | |||
340 | rtc->rtcdev = rtc_device_register(pdev->name, &pdev->dev, | ||
341 | &at91_rtc_ops, THIS_MODULE); | ||
342 | if (IS_ERR(rtc->rtcdev)) { | ||
343 | ret = PTR_ERR(rtc->rtcdev); | ||
344 | goto fail; | ||
345 | } | ||
346 | |||
347 | /* register irq handler after we know what name we'll use */ | ||
348 | ret = request_irq(AT91_ID_SYS, at91_rtc_interrupt, | ||
349 | IRQF_DISABLED | IRQF_SHARED, | ||
350 | rtc->rtcdev->dev.bus_id, rtc); | ||
351 | if (ret) { | ||
352 | dev_dbg(&pdev->dev, "can't share IRQ %d?\n", AT91_ID_SYS); | ||
353 | rtc_device_unregister(rtc->rtcdev); | ||
354 | goto fail; | ||
355 | } | ||
356 | |||
357 | /* NOTE: sam9260 rev A silicon has a ROM bug which resets the | ||
358 | * RTT on at least some reboots. If you have that chip, you must | ||
359 | * initialize the time from some external source like a GPS, wall | ||
360 | * clock, discrete RTC, etc | ||
361 | */ | ||
362 | |||
363 | if (gpbr_readl(rtc) == 0) | ||
364 | dev_warn(&pdev->dev, "%s: SET TIME!\n", | ||
365 | rtc->rtcdev->dev.bus_id); | ||
366 | |||
367 | return 0; | ||
368 | |||
369 | fail: | ||
370 | platform_set_drvdata(pdev, NULL); | ||
371 | kfree(rtc); | ||
372 | return ret; | ||
373 | } | ||
374 | |||
375 | /* | ||
376 | * Disable and remove the RTC driver | ||
377 | */ | ||
378 | static int __exit at91_rtc_remove(struct platform_device *pdev) | ||
379 | { | ||
380 | struct sam9_rtc *rtc = platform_get_drvdata(pdev); | ||
381 | u32 mr = rtt_readl(rtc, MR); | ||
382 | |||
383 | /* disable all interrupts */ | ||
384 | rtt_writel(rtc, MR, mr & ~(AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN)); | ||
385 | free_irq(AT91_ID_SYS, rtc); | ||
386 | |||
387 | rtc_device_unregister(rtc->rtcdev); | ||
388 | |||
389 | platform_set_drvdata(pdev, NULL); | ||
390 | kfree(rtc); | ||
391 | return 0; | ||
392 | } | ||
393 | |||
394 | static void at91_rtc_shutdown(struct platform_device *pdev) | ||
395 | { | ||
396 | struct sam9_rtc *rtc = platform_get_drvdata(pdev); | ||
397 | u32 mr = rtt_readl(rtc, MR); | ||
398 | |||
399 | rtc->imr = mr & (AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN); | ||
400 | rtt_writel(rtc, MR, mr & ~rtc->imr); | ||
401 | } | ||
402 | |||
403 | #ifdef CONFIG_PM | ||
404 | |||
405 | /* AT91SAM9 RTC Power management control */ | ||
406 | |||
407 | static int at91_rtc_suspend(struct platform_device *pdev, | ||
408 | pm_message_t state) | ||
409 | { | ||
410 | struct sam9_rtc *rtc = platform_get_drvdata(pdev); | ||
411 | u32 mr = rtt_readl(rtc, MR); | ||
412 | |||
413 | /* | ||
414 | * This IRQ is shared with DBGU and other hardware which isn't | ||
415 | * necessarily a wakeup event source. | ||
416 | */ | ||
417 | rtc->imr = mr & (AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN); | ||
418 | if (rtc->imr) { | ||
419 | if (device_may_wakeup(&pdev->dev) && (mr & AT91_RTT_ALMIEN)) { | ||
420 | enable_irq_wake(AT91_ID_SYS); | ||
421 | /* don't let RTTINC cause wakeups */ | ||
422 | if (mr & AT91_RTT_RTTINCIEN) | ||
423 | rtt_writel(rtc, MR, mr & ~AT91_RTT_RTTINCIEN); | ||
424 | } else | ||
425 | rtt_writel(rtc, MR, mr & ~rtc->imr); | ||
426 | } | ||
427 | |||
428 | return 0; | ||
429 | } | ||
430 | |||
431 | static int at91_rtc_resume(struct platform_device *pdev) | ||
432 | { | ||
433 | struct sam9_rtc *rtc = platform_get_drvdata(pdev); | ||
434 | u32 mr; | ||
435 | |||
436 | if (rtc->imr) { | ||
437 | if (device_may_wakeup(&pdev->dev)) | ||
438 | disable_irq_wake(AT91_ID_SYS); | ||
439 | mr = rtt_readl(rtc, MR); | ||
440 | rtt_writel(rtc, MR, mr | rtc->imr); | ||
441 | } | ||
442 | |||
443 | return 0; | ||
444 | } | ||
445 | #else | ||
446 | #define at91_rtc_suspend NULL | ||
447 | #define at91_rtc_resume NULL | ||
448 | #endif | ||
449 | |||
450 | static struct platform_driver at91_rtc_driver = { | ||
451 | .driver.name = "rtc-at91sam9", | ||
452 | .driver.owner = THIS_MODULE, | ||
453 | .remove = __exit_p(at91_rtc_remove), | ||
454 | .shutdown = at91_rtc_shutdown, | ||
455 | .suspend = at91_rtc_suspend, | ||
456 | .resume = at91_rtc_resume, | ||
457 | }; | ||
458 | |||
459 | /* Chips can have more than one RTT module, and they can be used for more | ||
460 | * than just RTCs. So we can't just register as "the" RTT driver. | ||
461 | * | ||
462 | * A normal approach in such cases is to create a library to allocate and | ||
463 | * free the modules. Here we just use bus_find_device() as like such a | ||
464 | * library, binding directly ... no runtime "library" footprint is needed. | ||
465 | */ | ||
466 | static int __init at91_rtc_match(struct device *dev, void *v) | ||
467 | { | ||
468 | struct platform_device *pdev = to_platform_device(dev); | ||
469 | int ret; | ||
470 | |||
471 | /* continue searching if this isn't the RTT we need */ | ||
472 | if (strcmp("at91_rtt", pdev->name) != 0 | ||
473 | || pdev->id != CONFIG_RTC_DRV_AT91SAM9_RTT) | ||
474 | goto fail; | ||
475 | |||
476 | /* else we found it ... but fail unless we can bind to the RTC driver */ | ||
477 | if (dev->driver) { | ||
478 | dev_dbg(dev, "busy, can't use as RTC!\n"); | ||
479 | goto fail; | ||
480 | } | ||
481 | dev->driver = &at91_rtc_driver.driver; | ||
482 | if (device_attach(dev) == 0) { | ||
483 | dev_dbg(dev, "can't attach RTC!\n"); | ||
484 | goto fail; | ||
485 | } | ||
486 | ret = at91_rtc_probe(pdev); | ||
487 | if (ret == 0) | ||
488 | return true; | ||
489 | |||
490 | dev_dbg(dev, "RTC probe err %d!\n", ret); | ||
491 | fail: | ||
492 | return false; | ||
493 | } | ||
494 | |||
495 | static int __init at91_rtc_init(void) | ||
496 | { | ||
497 | int status; | ||
498 | struct device *rtc; | ||
499 | |||
500 | status = platform_driver_register(&at91_rtc_driver); | ||
501 | if (status) | ||
502 | return status; | ||
503 | rtc = bus_find_device(&platform_bus_type, NULL, | ||
504 | NULL, at91_rtc_match); | ||
505 | if (!rtc) | ||
506 | platform_driver_unregister(&at91_rtc_driver); | ||
507 | return rtc ? 0 : -ENODEV; | ||
508 | } | ||
509 | module_init(at91_rtc_init); | ||
510 | |||
511 | static void __exit at91_rtc_exit(void) | ||
512 | { | ||
513 | platform_driver_unregister(&at91_rtc_driver); | ||
514 | } | ||
515 | module_exit(at91_rtc_exit); | ||
516 | |||
517 | |||
518 | MODULE_AUTHOR("Michel Benoit"); | ||
519 | MODULE_DESCRIPTION("RTC driver for Atmel AT91SAM9x"); | ||
520 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/rtc/rtc-bfin.c b/drivers/rtc/rtc-bfin.c index 1aa709dda0d6..d90ba860d216 100644 --- a/drivers/rtc/rtc-bfin.c +++ b/drivers/rtc/rtc-bfin.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Blackfin On-Chip Real Time Clock Driver | 2 | * Blackfin On-Chip Real Time Clock Driver |
3 | * Supports BF53[123]/BF53[467]/BF54[2489] | 3 | * Supports BF52[257]/BF53[123]/BF53[467]/BF54[24789] |
4 | * | 4 | * |
5 | * Copyright 2004-2007 Analog Devices Inc. | 5 | * Copyright 2004-2007 Analog Devices Inc. |
6 | * | 6 | * |
@@ -32,26 +32,25 @@ | |||
32 | * writes to clear status registers complete immediately. | 32 | * writes to clear status registers complete immediately. |
33 | */ | 33 | */ |
34 | 34 | ||
35 | #include <linux/module.h> | ||
36 | #include <linux/kernel.h> | ||
37 | #include <linux/bcd.h> | 35 | #include <linux/bcd.h> |
38 | #include <linux/rtc.h> | 36 | #include <linux/completion.h> |
37 | #include <linux/delay.h> | ||
39 | #include <linux/init.h> | 38 | #include <linux/init.h> |
39 | #include <linux/interrupt.h> | ||
40 | #include <linux/kernel.h> | ||
41 | #include <linux/module.h> | ||
40 | #include <linux/platform_device.h> | 42 | #include <linux/platform_device.h> |
43 | #include <linux/rtc.h> | ||
41 | #include <linux/seq_file.h> | 44 | #include <linux/seq_file.h> |
42 | #include <linux/interrupt.h> | ||
43 | #include <linux/spinlock.h> | ||
44 | #include <linux/delay.h> | ||
45 | 45 | ||
46 | #include <asm/blackfin.h> | 46 | #include <asm/blackfin.h> |
47 | 47 | ||
48 | #define stamp(fmt, args...) pr_debug("%s:%i: " fmt "\n", __FUNCTION__, __LINE__, ## args) | 48 | #define dev_dbg_stamp(dev) dev_dbg(dev, "%s:%i: here i am\n", __func__, __LINE__) |
49 | #define stampit() stamp("here i am") | ||
50 | 49 | ||
51 | struct bfin_rtc { | 50 | struct bfin_rtc { |
52 | struct rtc_device *rtc_dev; | 51 | struct rtc_device *rtc_dev; |
53 | struct rtc_time rtc_alarm; | 52 | struct rtc_time rtc_alarm; |
54 | spinlock_t lock; | 53 | u16 rtc_wrote_regs; |
55 | }; | 54 | }; |
56 | 55 | ||
57 | /* Bit values for the ISTAT / ICTL registers */ | 56 | /* Bit values for the ISTAT / ICTL registers */ |
@@ -72,7 +71,7 @@ struct bfin_rtc { | |||
72 | #define SEC_BITS_OFF 0 | 71 | #define SEC_BITS_OFF 0 |
73 | 72 | ||
74 | /* Some helper functions to convert between the common RTC notion of time | 73 | /* Some helper functions to convert between the common RTC notion of time |
75 | * and the internal Blackfin notion that is stored in 32bits. | 74 | * and the internal Blackfin notion that is encoded in 32bits. |
76 | */ | 75 | */ |
77 | static inline u32 rtc_time_to_bfin(unsigned long now) | 76 | static inline u32 rtc_time_to_bfin(unsigned long now) |
78 | { | 77 | { |
@@ -97,7 +96,10 @@ static inline void rtc_bfin_to_tm(u32 rtc_bfin, struct rtc_time *tm) | |||
97 | rtc_time_to_tm(rtc_bfin_to_time(rtc_bfin), tm); | 96 | rtc_time_to_tm(rtc_bfin_to_time(rtc_bfin), tm); |
98 | } | 97 | } |
99 | 98 | ||
100 | /* Wait for the previous write to a RTC register to complete. | 99 | /** |
100 | * bfin_rtc_sync_pending - make sure pending writes have complete | ||
101 | * | ||
102 | * Wait for the previous write to a RTC register to complete. | ||
101 | * Unfortunately, we can't sleep here as that introduces a race condition when | 103 | * Unfortunately, we can't sleep here as that introduces a race condition when |
102 | * turning on interrupt events. Consider this: | 104 | * turning on interrupt events. Consider this: |
103 | * - process sets alarm | 105 | * - process sets alarm |
@@ -112,188 +114,202 @@ static inline void rtc_bfin_to_tm(u32 rtc_bfin, struct rtc_time *tm) | |||
112 | * If anyone can point out the obvious solution here, i'm listening :). This | 114 | * If anyone can point out the obvious solution here, i'm listening :). This |
113 | * shouldn't be an issue on an SMP or preempt system as this function should | 115 | * shouldn't be an issue on an SMP or preempt system as this function should |
114 | * only be called with the rtc lock held. | 116 | * only be called with the rtc lock held. |
117 | * | ||
118 | * Other options: | ||
119 | * - disable PREN so the sync happens at 32.768kHZ ... but this changes the | ||
120 | * inc rate for all RTC registers from 1HZ to 32.768kHZ ... | ||
121 | * - use the write complete IRQ | ||
115 | */ | 122 | */ |
116 | static void rtc_bfin_sync_pending(void) | 123 | /* |
124 | static void bfin_rtc_sync_pending_polled(void) | ||
117 | { | 125 | { |
118 | stampit(); | 126 | while (!(bfin_read_RTC_ISTAT() & RTC_ISTAT_WRITE_COMPLETE)) |
119 | while (!(bfin_read_RTC_ISTAT() & RTC_ISTAT_WRITE_COMPLETE)) { | ||
120 | if (!(bfin_read_RTC_ISTAT() & RTC_ISTAT_WRITE_PENDING)) | 127 | if (!(bfin_read_RTC_ISTAT() & RTC_ISTAT_WRITE_PENDING)) |
121 | break; | 128 | break; |
122 | } | ||
123 | bfin_write_RTC_ISTAT(RTC_ISTAT_WRITE_COMPLETE); | 129 | bfin_write_RTC_ISTAT(RTC_ISTAT_WRITE_COMPLETE); |
124 | } | 130 | } |
131 | */ | ||
132 | static DECLARE_COMPLETION(bfin_write_complete); | ||
133 | static void bfin_rtc_sync_pending(struct device *dev) | ||
134 | { | ||
135 | dev_dbg_stamp(dev); | ||
136 | while (bfin_read_RTC_ISTAT() & RTC_ISTAT_WRITE_PENDING) | ||
137 | wait_for_completion_timeout(&bfin_write_complete, HZ * 5); | ||
138 | dev_dbg_stamp(dev); | ||
139 | } | ||
125 | 140 | ||
126 | static void rtc_bfin_reset(struct bfin_rtc *rtc) | 141 | /** |
142 | * bfin_rtc_reset - set RTC to sane/known state | ||
143 | * | ||
144 | * Initialize the RTC. Enable pre-scaler to scale RTC clock | ||
145 | * to 1Hz and clear interrupt/status registers. | ||
146 | */ | ||
147 | static void bfin_rtc_reset(struct device *dev) | ||
127 | { | 148 | { |
128 | /* Initialize the RTC. Enable pre-scaler to scale RTC clock | 149 | struct bfin_rtc *rtc = dev_get_drvdata(dev); |
129 | * to 1Hz and clear interrupt/status registers. */ | 150 | dev_dbg_stamp(dev); |
130 | spin_lock_irq(&rtc->lock); | 151 | bfin_rtc_sync_pending(dev); |
131 | rtc_bfin_sync_pending(); | ||
132 | bfin_write_RTC_PREN(0x1); | 152 | bfin_write_RTC_PREN(0x1); |
133 | bfin_write_RTC_ICTL(0); | 153 | bfin_write_RTC_ICTL(RTC_ISTAT_WRITE_COMPLETE); |
134 | bfin_write_RTC_SWCNT(0); | 154 | bfin_write_RTC_SWCNT(0); |
135 | bfin_write_RTC_ALARM(0); | 155 | bfin_write_RTC_ALARM(0); |
136 | bfin_write_RTC_ISTAT(0xFFFF); | 156 | bfin_write_RTC_ISTAT(0xFFFF); |
137 | spin_unlock_irq(&rtc->lock); | 157 | rtc->rtc_wrote_regs = 0; |
138 | } | 158 | } |
139 | 159 | ||
160 | /** | ||
161 | * bfin_rtc_interrupt - handle interrupt from RTC | ||
162 | * | ||
163 | * Since we handle all RTC events here, we have to make sure the requested | ||
164 | * interrupt is enabled (in RTC_ICTL) as the event status register (RTC_ISTAT) | ||
165 | * always gets updated regardless of the interrupt being enabled. So when one | ||
166 | * even we care about (e.g. stopwatch) goes off, we don't want to turn around | ||
167 | * and say that other events have happened as well (e.g. second). We do not | ||
168 | * have to worry about pending writes to the RTC_ICTL register as interrupts | ||
169 | * only fire if they are enabled in the RTC_ICTL register. | ||
170 | */ | ||
140 | static irqreturn_t bfin_rtc_interrupt(int irq, void *dev_id) | 171 | static irqreturn_t bfin_rtc_interrupt(int irq, void *dev_id) |
141 | { | 172 | { |
142 | struct platform_device *pdev = to_platform_device(dev_id); | 173 | struct device *dev = dev_id; |
143 | struct bfin_rtc *rtc = platform_get_drvdata(pdev); | 174 | struct bfin_rtc *rtc = dev_get_drvdata(dev); |
144 | unsigned long events = 0; | 175 | unsigned long events = 0; |
145 | u16 rtc_istat; | 176 | bool write_complete = false; |
146 | 177 | u16 rtc_istat, rtc_ictl; | |
147 | stampit(); | ||
148 | 178 | ||
149 | spin_lock_irq(&rtc->lock); | 179 | dev_dbg_stamp(dev); |
150 | 180 | ||
151 | rtc_istat = bfin_read_RTC_ISTAT(); | 181 | rtc_istat = bfin_read_RTC_ISTAT(); |
182 | rtc_ictl = bfin_read_RTC_ICTL(); | ||
152 | 183 | ||
153 | if (rtc_istat & (RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY)) { | 184 | if (rtc_istat & RTC_ISTAT_WRITE_COMPLETE) { |
154 | bfin_write_RTC_ISTAT(RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY); | 185 | bfin_write_RTC_ISTAT(RTC_ISTAT_WRITE_COMPLETE); |
155 | events |= RTC_AF | RTC_IRQF; | 186 | write_complete = true; |
187 | complete(&bfin_write_complete); | ||
156 | } | 188 | } |
157 | 189 | ||
158 | if (rtc_istat & RTC_ISTAT_STOPWATCH) { | 190 | if (rtc_ictl & (RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY)) { |
159 | bfin_write_RTC_ISTAT(RTC_ISTAT_STOPWATCH); | 191 | if (rtc_istat & (RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY)) { |
160 | events |= RTC_PF | RTC_IRQF; | 192 | bfin_write_RTC_ISTAT(RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY); |
161 | bfin_write_RTC_SWCNT(rtc->rtc_dev->irq_freq); | 193 | events |= RTC_AF | RTC_IRQF; |
194 | } | ||
162 | } | 195 | } |
163 | 196 | ||
164 | if (rtc_istat & RTC_ISTAT_SEC) { | 197 | if (rtc_ictl & RTC_ISTAT_STOPWATCH) { |
165 | bfin_write_RTC_ISTAT(RTC_ISTAT_SEC); | 198 | if (rtc_istat & RTC_ISTAT_STOPWATCH) { |
166 | events |= RTC_UF | RTC_IRQF; | 199 | bfin_write_RTC_ISTAT(RTC_ISTAT_STOPWATCH); |
200 | events |= RTC_PF | RTC_IRQF; | ||
201 | bfin_write_RTC_SWCNT(rtc->rtc_dev->irq_freq); | ||
202 | } | ||
167 | } | 203 | } |
168 | 204 | ||
169 | rtc_update_irq(rtc->rtc_dev, 1, events); | 205 | if (rtc_ictl & RTC_ISTAT_SEC) { |
206 | if (rtc_istat & RTC_ISTAT_SEC) { | ||
207 | bfin_write_RTC_ISTAT(RTC_ISTAT_SEC); | ||
208 | events |= RTC_UF | RTC_IRQF; | ||
209 | } | ||
210 | } | ||
170 | 211 | ||
171 | spin_unlock_irq(&rtc->lock); | 212 | if (events) |
213 | rtc_update_irq(rtc->rtc_dev, 1, events); | ||
172 | 214 | ||
173 | return IRQ_HANDLED; | 215 | if (write_complete || events) |
216 | return IRQ_HANDLED; | ||
217 | else | ||
218 | return IRQ_NONE; | ||
174 | } | 219 | } |
175 | 220 | ||
176 | static int bfin_rtc_open(struct device *dev) | 221 | static int bfin_rtc_open(struct device *dev) |
177 | { | 222 | { |
178 | struct bfin_rtc *rtc = dev_get_drvdata(dev); | ||
179 | int ret; | 223 | int ret; |
180 | 224 | ||
181 | stampit(); | 225 | dev_dbg_stamp(dev); |
182 | 226 | ||
183 | ret = request_irq(IRQ_RTC, bfin_rtc_interrupt, IRQF_DISABLED, "rtc-bfin", dev); | 227 | ret = request_irq(IRQ_RTC, bfin_rtc_interrupt, IRQF_SHARED, to_platform_device(dev)->name, dev); |
184 | if (unlikely(ret)) { | 228 | if (!ret) |
185 | dev_err(dev, "request RTC IRQ failed with %d\n", ret); | 229 | bfin_rtc_reset(dev); |
186 | return ret; | ||
187 | } | ||
188 | |||
189 | rtc_bfin_reset(rtc); | ||
190 | 230 | ||
191 | return ret; | 231 | return ret; |
192 | } | 232 | } |
193 | 233 | ||
194 | static void bfin_rtc_release(struct device *dev) | 234 | static void bfin_rtc_release(struct device *dev) |
195 | { | 235 | { |
196 | struct bfin_rtc *rtc = dev_get_drvdata(dev); | 236 | dev_dbg_stamp(dev); |
197 | stampit(); | 237 | bfin_rtc_reset(dev); |
198 | rtc_bfin_reset(rtc); | ||
199 | free_irq(IRQ_RTC, dev); | 238 | free_irq(IRQ_RTC, dev); |
200 | } | 239 | } |
201 | 240 | ||
241 | static void bfin_rtc_int_set(struct bfin_rtc *rtc, u16 rtc_int) | ||
242 | { | ||
243 | bfin_write_RTC_ISTAT(rtc_int); | ||
244 | bfin_write_RTC_ICTL(bfin_read_RTC_ICTL() | rtc_int); | ||
245 | } | ||
246 | static void bfin_rtc_int_clear(struct bfin_rtc *rtc, u16 rtc_int) | ||
247 | { | ||
248 | bfin_write_RTC_ICTL(bfin_read_RTC_ICTL() & rtc_int); | ||
249 | } | ||
250 | static void bfin_rtc_int_set_alarm(struct bfin_rtc *rtc) | ||
251 | { | ||
252 | /* Blackfin has different bits for whether the alarm is | ||
253 | * more than 24 hours away. | ||
254 | */ | ||
255 | bfin_rtc_int_set(rtc, (rtc->rtc_alarm.tm_yday == -1 ? RTC_ISTAT_ALARM : RTC_ISTAT_ALARM_DAY)); | ||
256 | } | ||
202 | static int bfin_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | 257 | static int bfin_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) |
203 | { | 258 | { |
204 | struct bfin_rtc *rtc = dev_get_drvdata(dev); | 259 | struct bfin_rtc *rtc = dev_get_drvdata(dev); |
260 | int ret = 0; | ||
261 | |||
262 | dev_dbg_stamp(dev); | ||
205 | 263 | ||
206 | stampit(); | 264 | bfin_rtc_sync_pending(dev); |
207 | 265 | ||
208 | switch (cmd) { | 266 | switch (cmd) { |
209 | case RTC_PIE_ON: | 267 | case RTC_PIE_ON: |
210 | stampit(); | 268 | dev_dbg_stamp(dev); |
211 | spin_lock_irq(&rtc->lock); | 269 | bfin_rtc_int_set(rtc, RTC_ISTAT_STOPWATCH); |
212 | rtc_bfin_sync_pending(); | ||
213 | bfin_write_RTC_ISTAT(RTC_ISTAT_STOPWATCH); | ||
214 | bfin_write_RTC_SWCNT(rtc->rtc_dev->irq_freq); | 270 | bfin_write_RTC_SWCNT(rtc->rtc_dev->irq_freq); |
215 | bfin_write_RTC_ICTL(bfin_read_RTC_ICTL() | RTC_ISTAT_STOPWATCH); | 271 | break; |
216 | spin_unlock_irq(&rtc->lock); | ||
217 | return 0; | ||
218 | case RTC_PIE_OFF: | 272 | case RTC_PIE_OFF: |
219 | stampit(); | 273 | dev_dbg_stamp(dev); |
220 | spin_lock_irq(&rtc->lock); | 274 | bfin_rtc_int_clear(rtc, ~RTC_ISTAT_STOPWATCH); |
221 | rtc_bfin_sync_pending(); | 275 | break; |
222 | bfin_write_RTC_SWCNT(0); | ||
223 | bfin_write_RTC_ICTL(bfin_read_RTC_ICTL() & ~RTC_ISTAT_STOPWATCH); | ||
224 | spin_unlock_irq(&rtc->lock); | ||
225 | return 0; | ||
226 | 276 | ||
227 | case RTC_UIE_ON: | 277 | case RTC_UIE_ON: |
228 | stampit(); | 278 | dev_dbg_stamp(dev); |
229 | spin_lock_irq(&rtc->lock); | 279 | bfin_rtc_int_set(rtc, RTC_ISTAT_SEC); |
230 | rtc_bfin_sync_pending(); | 280 | break; |
231 | bfin_write_RTC_ISTAT(RTC_ISTAT_SEC); | ||
232 | bfin_write_RTC_ICTL(bfin_read_RTC_ICTL() | RTC_ISTAT_SEC); | ||
233 | spin_unlock_irq(&rtc->lock); | ||
234 | return 0; | ||
235 | case RTC_UIE_OFF: | 281 | case RTC_UIE_OFF: |
236 | stampit(); | 282 | dev_dbg_stamp(dev); |
237 | spin_lock_irq(&rtc->lock); | 283 | bfin_rtc_int_clear(rtc, ~RTC_ISTAT_SEC); |
238 | rtc_bfin_sync_pending(); | 284 | break; |
239 | bfin_write_RTC_ICTL(bfin_read_RTC_ICTL() & ~RTC_ISTAT_SEC); | 285 | |
240 | spin_unlock_irq(&rtc->lock); | 286 | case RTC_AIE_ON: |
241 | return 0; | 287 | dev_dbg_stamp(dev); |
242 | 288 | bfin_rtc_int_set_alarm(rtc); | |
243 | case RTC_AIE_ON: { | 289 | break; |
244 | unsigned long rtc_alarm; | ||
245 | u16 which_alarm; | ||
246 | int ret = 0; | ||
247 | |||
248 | stampit(); | ||
249 | |||
250 | spin_lock_irq(&rtc->lock); | ||
251 | |||
252 | rtc_bfin_sync_pending(); | ||
253 | if (rtc->rtc_alarm.tm_yday == -1) { | ||
254 | struct rtc_time now; | ||
255 | rtc_bfin_to_tm(bfin_read_RTC_STAT(), &now); | ||
256 | now.tm_sec = rtc->rtc_alarm.tm_sec; | ||
257 | now.tm_min = rtc->rtc_alarm.tm_min; | ||
258 | now.tm_hour = rtc->rtc_alarm.tm_hour; | ||
259 | ret = rtc_tm_to_time(&now, &rtc_alarm); | ||
260 | which_alarm = RTC_ISTAT_ALARM; | ||
261 | } else { | ||
262 | ret = rtc_tm_to_time(&rtc->rtc_alarm, &rtc_alarm); | ||
263 | which_alarm = RTC_ISTAT_ALARM_DAY; | ||
264 | } | ||
265 | if (ret == 0) { | ||
266 | bfin_write_RTC_ISTAT(which_alarm); | ||
267 | bfin_write_RTC_ALARM(rtc_time_to_bfin(rtc_alarm)); | ||
268 | bfin_write_RTC_ICTL(bfin_read_RTC_ICTL() | which_alarm); | ||
269 | } | ||
270 | |||
271 | spin_unlock_irq(&rtc->lock); | ||
272 | |||
273 | return ret; | ||
274 | } | ||
275 | case RTC_AIE_OFF: | 290 | case RTC_AIE_OFF: |
276 | stampit(); | 291 | dev_dbg_stamp(dev); |
277 | spin_lock_irq(&rtc->lock); | 292 | bfin_rtc_int_clear(rtc, ~(RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY)); |
278 | rtc_bfin_sync_pending(); | 293 | break; |
279 | bfin_write_RTC_ICTL(bfin_read_RTC_ICTL() & ~(RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY)); | 294 | |
280 | spin_unlock_irq(&rtc->lock); | 295 | default: |
281 | return 0; | 296 | dev_dbg_stamp(dev); |
297 | ret = -ENOIOCTLCMD; | ||
282 | } | 298 | } |
283 | 299 | ||
284 | return -ENOIOCTLCMD; | 300 | return ret; |
285 | } | 301 | } |
286 | 302 | ||
287 | static int bfin_rtc_read_time(struct device *dev, struct rtc_time *tm) | 303 | static int bfin_rtc_read_time(struct device *dev, struct rtc_time *tm) |
288 | { | 304 | { |
289 | struct bfin_rtc *rtc = dev_get_drvdata(dev); | 305 | struct bfin_rtc *rtc = dev_get_drvdata(dev); |
290 | 306 | ||
291 | stampit(); | 307 | dev_dbg_stamp(dev); |
308 | |||
309 | if (rtc->rtc_wrote_regs & 0x1) | ||
310 | bfin_rtc_sync_pending(dev); | ||
292 | 311 | ||
293 | spin_lock_irq(&rtc->lock); | ||
294 | rtc_bfin_sync_pending(); | ||
295 | rtc_bfin_to_tm(bfin_read_RTC_STAT(), tm); | 312 | rtc_bfin_to_tm(bfin_read_RTC_STAT(), tm); |
296 | spin_unlock_irq(&rtc->lock); | ||
297 | 313 | ||
298 | return 0; | 314 | return 0; |
299 | } | 315 | } |
@@ -304,64 +320,79 @@ static int bfin_rtc_set_time(struct device *dev, struct rtc_time *tm) | |||
304 | int ret; | 320 | int ret; |
305 | unsigned long now; | 321 | unsigned long now; |
306 | 322 | ||
307 | stampit(); | 323 | dev_dbg_stamp(dev); |
308 | |||
309 | spin_lock_irq(&rtc->lock); | ||
310 | 324 | ||
311 | ret = rtc_tm_to_time(tm, &now); | 325 | ret = rtc_tm_to_time(tm, &now); |
312 | if (ret == 0) { | 326 | if (ret == 0) { |
313 | rtc_bfin_sync_pending(); | 327 | if (rtc->rtc_wrote_regs & 0x1) |
328 | bfin_rtc_sync_pending(dev); | ||
314 | bfin_write_RTC_STAT(rtc_time_to_bfin(now)); | 329 | bfin_write_RTC_STAT(rtc_time_to_bfin(now)); |
330 | rtc->rtc_wrote_regs = 0x1; | ||
315 | } | 331 | } |
316 | 332 | ||
317 | spin_unlock_irq(&rtc->lock); | ||
318 | |||
319 | return ret; | 333 | return ret; |
320 | } | 334 | } |
321 | 335 | ||
322 | static int bfin_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | 336 | static int bfin_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) |
323 | { | 337 | { |
324 | struct bfin_rtc *rtc = dev_get_drvdata(dev); | 338 | struct bfin_rtc *rtc = dev_get_drvdata(dev); |
325 | stampit(); | 339 | dev_dbg_stamp(dev); |
326 | memcpy(&alrm->time, &rtc->rtc_alarm, sizeof(struct rtc_time)); | 340 | alrm->time = rtc->rtc_alarm; |
327 | alrm->pending = !!(bfin_read_RTC_ICTL() & (RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY)); | 341 | bfin_rtc_sync_pending(dev); |
342 | alrm->enabled = !!(bfin_read_RTC_ICTL() & (RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY)); | ||
328 | return 0; | 343 | return 0; |
329 | } | 344 | } |
330 | 345 | ||
331 | static int bfin_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | 346 | static int bfin_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) |
332 | { | 347 | { |
333 | struct bfin_rtc *rtc = dev_get_drvdata(dev); | 348 | struct bfin_rtc *rtc = dev_get_drvdata(dev); |
334 | stampit(); | 349 | unsigned long rtc_alarm; |
335 | memcpy(&rtc->rtc_alarm, &alrm->time, sizeof(struct rtc_time)); | 350 | |
351 | dev_dbg_stamp(dev); | ||
352 | |||
353 | if (rtc_tm_to_time(&alrm->time, &rtc_alarm)) | ||
354 | return -EINVAL; | ||
355 | |||
356 | rtc->rtc_alarm = alrm->time; | ||
357 | |||
358 | bfin_rtc_sync_pending(dev); | ||
359 | bfin_write_RTC_ALARM(rtc_time_to_bfin(rtc_alarm)); | ||
360 | if (alrm->enabled) | ||
361 | bfin_rtc_int_set_alarm(rtc); | ||
362 | |||
336 | return 0; | 363 | return 0; |
337 | } | 364 | } |
338 | 365 | ||
339 | static int bfin_rtc_proc(struct device *dev, struct seq_file *seq) | 366 | static int bfin_rtc_proc(struct device *dev, struct seq_file *seq) |
340 | { | 367 | { |
341 | #define yesno(x) (x ? "yes" : "no") | 368 | #define yesno(x) ((x) ? "yes" : "no") |
342 | u16 ictl = bfin_read_RTC_ICTL(); | 369 | u16 ictl = bfin_read_RTC_ICTL(); |
343 | stampit(); | 370 | dev_dbg_stamp(dev); |
344 | seq_printf(seq, "alarm_IRQ\t: %s\n", yesno(ictl & RTC_ISTAT_ALARM)); | 371 | seq_printf(seq, |
345 | seq_printf(seq, "wkalarm_IRQ\t: %s\n", yesno(ictl & RTC_ISTAT_ALARM_DAY)); | 372 | "alarm_IRQ\t: %s\n" |
346 | seq_printf(seq, "seconds_IRQ\t: %s\n", yesno(ictl & RTC_ISTAT_SEC)); | 373 | "wkalarm_IRQ\t: %s\n" |
347 | seq_printf(seq, "periodic_IRQ\t: %s\n", yesno(ictl & RTC_ISTAT_STOPWATCH)); | 374 | "seconds_IRQ\t: %s\n" |
348 | #ifdef DEBUG | 375 | "periodic_IRQ\t: %s\n", |
349 | seq_printf(seq, "RTC_STAT\t: 0x%08X\n", bfin_read_RTC_STAT()); | 376 | yesno(ictl & RTC_ISTAT_ALARM), |
350 | seq_printf(seq, "RTC_ICTL\t: 0x%04X\n", bfin_read_RTC_ICTL()); | 377 | yesno(ictl & RTC_ISTAT_ALARM_DAY), |
351 | seq_printf(seq, "RTC_ISTAT\t: 0x%04X\n", bfin_read_RTC_ISTAT()); | 378 | yesno(ictl & RTC_ISTAT_SEC), |
352 | seq_printf(seq, "RTC_SWCNT\t: 0x%04X\n", bfin_read_RTC_SWCNT()); | 379 | yesno(ictl & RTC_ISTAT_STOPWATCH)); |
353 | seq_printf(seq, "RTC_ALARM\t: 0x%08X\n", bfin_read_RTC_ALARM()); | ||
354 | seq_printf(seq, "RTC_PREN\t: 0x%04X\n", bfin_read_RTC_PREN()); | ||
355 | #endif | ||
356 | return 0; | 380 | return 0; |
381 | #undef yesno | ||
357 | } | 382 | } |
358 | 383 | ||
384 | /** | ||
385 | * bfin_irq_set_freq - make sure hardware supports requested freq | ||
386 | * @dev: pointer to RTC device structure | ||
387 | * @freq: requested frequency rate | ||
388 | * | ||
389 | * The Blackfin RTC can only generate periodic events at 1 per | ||
390 | * second (1 Hz), so reject any attempt at changing it. | ||
391 | */ | ||
359 | static int bfin_irq_set_freq(struct device *dev, int freq) | 392 | static int bfin_irq_set_freq(struct device *dev, int freq) |
360 | { | 393 | { |
361 | struct bfin_rtc *rtc = dev_get_drvdata(dev); | 394 | dev_dbg_stamp(dev); |
362 | stampit(); | 395 | return -ENOTTY; |
363 | rtc->rtc_dev->irq_freq = freq; | ||
364 | return 0; | ||
365 | } | 396 | } |
366 | 397 | ||
367 | static struct rtc_class_ops bfin_rtc_ops = { | 398 | static struct rtc_class_ops bfin_rtc_ops = { |
@@ -381,27 +412,24 @@ static int __devinit bfin_rtc_probe(struct platform_device *pdev) | |||
381 | struct bfin_rtc *rtc; | 412 | struct bfin_rtc *rtc; |
382 | int ret = 0; | 413 | int ret = 0; |
383 | 414 | ||
384 | stampit(); | 415 | dev_dbg_stamp(&pdev->dev); |
385 | 416 | ||
386 | rtc = kzalloc(sizeof(*rtc), GFP_KERNEL); | 417 | rtc = kzalloc(sizeof(*rtc), GFP_KERNEL); |
387 | if (unlikely(!rtc)) | 418 | if (unlikely(!rtc)) |
388 | return -ENOMEM; | 419 | return -ENOMEM; |
389 | 420 | ||
390 | spin_lock_init(&rtc->lock); | ||
391 | |||
392 | rtc->rtc_dev = rtc_device_register(pdev->name, &pdev->dev, &bfin_rtc_ops, THIS_MODULE); | 421 | rtc->rtc_dev = rtc_device_register(pdev->name, &pdev->dev, &bfin_rtc_ops, THIS_MODULE); |
393 | if (unlikely(IS_ERR(rtc))) { | 422 | if (unlikely(IS_ERR(rtc))) { |
394 | ret = PTR_ERR(rtc->rtc_dev); | 423 | ret = PTR_ERR(rtc->rtc_dev); |
395 | goto err; | 424 | goto err; |
396 | } | 425 | } |
397 | rtc->rtc_dev->irq_freq = 0; | 426 | rtc->rtc_dev->irq_freq = 1; |
398 | rtc->rtc_dev->max_user_freq = (2 << 16); /* stopwatch is an unsigned 16 bit reg */ | ||
399 | 427 | ||
400 | platform_set_drvdata(pdev, rtc); | 428 | platform_set_drvdata(pdev, rtc); |
401 | 429 | ||
402 | return 0; | 430 | return 0; |
403 | 431 | ||
404 | err: | 432 | err: |
405 | kfree(rtc); | 433 | kfree(rtc); |
406 | return ret; | 434 | return ret; |
407 | } | 435 | } |
@@ -428,7 +456,6 @@ static struct platform_driver bfin_rtc_driver = { | |||
428 | 456 | ||
429 | static int __init bfin_rtc_init(void) | 457 | static int __init bfin_rtc_init(void) |
430 | { | 458 | { |
431 | stampit(); | ||
432 | return platform_driver_register(&bfin_rtc_driver); | 459 | return platform_driver_register(&bfin_rtc_driver); |
433 | } | 460 | } |
434 | 461 | ||
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index 29cf1457ca10..e059f94c79eb 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c | |||
@@ -36,9 +36,24 @@ | |||
36 | #include <linux/platform_device.h> | 36 | #include <linux/platform_device.h> |
37 | #include <linux/mod_devicetable.h> | 37 | #include <linux/mod_devicetable.h> |
38 | 38 | ||
39 | #ifdef CONFIG_HPET_EMULATE_RTC | ||
40 | #include <asm/hpet.h> | ||
41 | #endif | ||
42 | |||
39 | /* this is for "generic access to PC-style RTC" using CMOS_READ/CMOS_WRITE */ | 43 | /* this is for "generic access to PC-style RTC" using CMOS_READ/CMOS_WRITE */ |
40 | #include <asm-generic/rtc.h> | 44 | #include <asm-generic/rtc.h> |
41 | 45 | ||
46 | #ifndef CONFIG_HPET_EMULATE_RTC | ||
47 | #define is_hpet_enabled() 0 | ||
48 | #define hpet_set_alarm_time(hrs, min, sec) do { } while (0) | ||
49 | #define hpet_set_periodic_freq(arg) 0 | ||
50 | #define hpet_mask_rtc_irq_bit(arg) do { } while (0) | ||
51 | #define hpet_set_rtc_irq_bit(arg) do { } while (0) | ||
52 | #define hpet_rtc_timer_init() do { } while (0) | ||
53 | #define hpet_register_irq_handler(h) 0 | ||
54 | #define hpet_unregister_irq_handler(h) do { } while (0) | ||
55 | extern irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id); | ||
56 | #endif | ||
42 | 57 | ||
43 | struct cmos_rtc { | 58 | struct cmos_rtc { |
44 | struct rtc_device *rtc; | 59 | struct rtc_device *rtc; |
@@ -199,6 +214,7 @@ static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t) | |||
199 | sec = t->time.tm_sec; | 214 | sec = t->time.tm_sec; |
200 | sec = (sec < 60) ? BIN2BCD(sec) : 0xff; | 215 | sec = (sec < 60) ? BIN2BCD(sec) : 0xff; |
201 | 216 | ||
217 | hpet_set_alarm_time(t->time.tm_hour, t->time.tm_min, t->time.tm_sec); | ||
202 | spin_lock_irq(&rtc_lock); | 218 | spin_lock_irq(&rtc_lock); |
203 | 219 | ||
204 | /* next rtc irq must not be from previous alarm setting */ | 220 | /* next rtc irq must not be from previous alarm setting */ |
@@ -252,7 +268,8 @@ static int cmos_irq_set_freq(struct device *dev, int freq) | |||
252 | f = 16 - f; | 268 | f = 16 - f; |
253 | 269 | ||
254 | spin_lock_irqsave(&rtc_lock, flags); | 270 | spin_lock_irqsave(&rtc_lock, flags); |
255 | CMOS_WRITE(RTC_REF_CLCK_32KHZ | f, RTC_FREQ_SELECT); | 271 | if (!hpet_set_periodic_freq(freq)) |
272 | CMOS_WRITE(RTC_REF_CLCK_32KHZ | f, RTC_FREQ_SELECT); | ||
256 | spin_unlock_irqrestore(&rtc_lock, flags); | 273 | spin_unlock_irqrestore(&rtc_lock, flags); |
257 | 274 | ||
258 | return 0; | 275 | return 0; |
@@ -314,28 +331,37 @@ cmos_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | |||
314 | switch (cmd) { | 331 | switch (cmd) { |
315 | case RTC_AIE_OFF: /* alarm off */ | 332 | case RTC_AIE_OFF: /* alarm off */ |
316 | rtc_control &= ~RTC_AIE; | 333 | rtc_control &= ~RTC_AIE; |
334 | hpet_mask_rtc_irq_bit(RTC_AIE); | ||
317 | break; | 335 | break; |
318 | case RTC_AIE_ON: /* alarm on */ | 336 | case RTC_AIE_ON: /* alarm on */ |
319 | rtc_control |= RTC_AIE; | 337 | rtc_control |= RTC_AIE; |
338 | hpet_set_rtc_irq_bit(RTC_AIE); | ||
320 | break; | 339 | break; |
321 | case RTC_UIE_OFF: /* update off */ | 340 | case RTC_UIE_OFF: /* update off */ |
322 | rtc_control &= ~RTC_UIE; | 341 | rtc_control &= ~RTC_UIE; |
342 | hpet_mask_rtc_irq_bit(RTC_UIE); | ||
323 | break; | 343 | break; |
324 | case RTC_UIE_ON: /* update on */ | 344 | case RTC_UIE_ON: /* update on */ |
325 | rtc_control |= RTC_UIE; | 345 | rtc_control |= RTC_UIE; |
346 | hpet_set_rtc_irq_bit(RTC_UIE); | ||
326 | break; | 347 | break; |
327 | case RTC_PIE_OFF: /* periodic off */ | 348 | case RTC_PIE_OFF: /* periodic off */ |
328 | rtc_control &= ~RTC_PIE; | 349 | rtc_control &= ~RTC_PIE; |
350 | hpet_mask_rtc_irq_bit(RTC_PIE); | ||
329 | break; | 351 | break; |
330 | case RTC_PIE_ON: /* periodic on */ | 352 | case RTC_PIE_ON: /* periodic on */ |
331 | rtc_control |= RTC_PIE; | 353 | rtc_control |= RTC_PIE; |
354 | hpet_set_rtc_irq_bit(RTC_PIE); | ||
332 | break; | 355 | break; |
333 | } | 356 | } |
334 | CMOS_WRITE(rtc_control, RTC_CONTROL); | 357 | if (!is_hpet_enabled()) |
358 | CMOS_WRITE(rtc_control, RTC_CONTROL); | ||
359 | |||
335 | rtc_intr = CMOS_READ(RTC_INTR_FLAGS); | 360 | rtc_intr = CMOS_READ(RTC_INTR_FLAGS); |
336 | rtc_intr &= (rtc_control & RTC_IRQMASK) | RTC_IRQF; | 361 | rtc_intr &= (rtc_control & RTC_IRQMASK) | RTC_IRQF; |
337 | if (is_intr(rtc_intr)) | 362 | if (is_intr(rtc_intr)) |
338 | rtc_update_irq(cmos->rtc, 1, rtc_intr); | 363 | rtc_update_irq(cmos->rtc, 1, rtc_intr); |
364 | |||
339 | spin_unlock_irqrestore(&rtc_lock, flags); | 365 | spin_unlock_irqrestore(&rtc_lock, flags); |
340 | return 0; | 366 | return 0; |
341 | } | 367 | } |
@@ -393,15 +419,111 @@ static const struct rtc_class_ops cmos_rtc_ops = { | |||
393 | 419 | ||
394 | /*----------------------------------------------------------------*/ | 420 | /*----------------------------------------------------------------*/ |
395 | 421 | ||
422 | /* | ||
423 | * All these chips have at least 64 bytes of address space, shared by | ||
424 | * RTC registers and NVRAM. Most of those bytes of NVRAM are used | ||
425 | * by boot firmware. Modern chips have 128 or 256 bytes. | ||
426 | */ | ||
427 | |||
428 | #define NVRAM_OFFSET (RTC_REG_D + 1) | ||
429 | |||
430 | static ssize_t | ||
431 | cmos_nvram_read(struct kobject *kobj, struct bin_attribute *attr, | ||
432 | char *buf, loff_t off, size_t count) | ||
433 | { | ||
434 | int retval; | ||
435 | |||
436 | if (unlikely(off >= attr->size)) | ||
437 | return 0; | ||
438 | if ((off + count) > attr->size) | ||
439 | count = attr->size - off; | ||
440 | |||
441 | spin_lock_irq(&rtc_lock); | ||
442 | for (retval = 0, off += NVRAM_OFFSET; count--; retval++, off++) | ||
443 | *buf++ = CMOS_READ(off); | ||
444 | spin_unlock_irq(&rtc_lock); | ||
445 | |||
446 | return retval; | ||
447 | } | ||
448 | |||
449 | static ssize_t | ||
450 | cmos_nvram_write(struct kobject *kobj, struct bin_attribute *attr, | ||
451 | char *buf, loff_t off, size_t count) | ||
452 | { | ||
453 | struct cmos_rtc *cmos; | ||
454 | int retval; | ||
455 | |||
456 | cmos = dev_get_drvdata(container_of(kobj, struct device, kobj)); | ||
457 | if (unlikely(off >= attr->size)) | ||
458 | return -EFBIG; | ||
459 | if ((off + count) > attr->size) | ||
460 | count = attr->size - off; | ||
461 | |||
462 | /* NOTE: on at least PCs and Ataris, the boot firmware uses a | ||
463 | * checksum on part of the NVRAM data. That's currently ignored | ||
464 | * here. If userspace is smart enough to know what fields of | ||
465 | * NVRAM to update, updating checksums is also part of its job. | ||
466 | */ | ||
467 | spin_lock_irq(&rtc_lock); | ||
468 | for (retval = 0, off += NVRAM_OFFSET; count--; retval++, off++) { | ||
469 | /* don't trash RTC registers */ | ||
470 | if (off == cmos->day_alrm | ||
471 | || off == cmos->mon_alrm | ||
472 | || off == cmos->century) | ||
473 | buf++; | ||
474 | else | ||
475 | CMOS_WRITE(*buf++, off); | ||
476 | } | ||
477 | spin_unlock_irq(&rtc_lock); | ||
478 | |||
479 | return retval; | ||
480 | } | ||
481 | |||
482 | static struct bin_attribute nvram = { | ||
483 | .attr = { | ||
484 | .name = "nvram", | ||
485 | .mode = S_IRUGO | S_IWUSR, | ||
486 | .owner = THIS_MODULE, | ||
487 | }, | ||
488 | |||
489 | .read = cmos_nvram_read, | ||
490 | .write = cmos_nvram_write, | ||
491 | /* size gets set up later */ | ||
492 | }; | ||
493 | |||
494 | /*----------------------------------------------------------------*/ | ||
495 | |||
396 | static struct cmos_rtc cmos_rtc; | 496 | static struct cmos_rtc cmos_rtc; |
397 | 497 | ||
398 | static irqreturn_t cmos_interrupt(int irq, void *p) | 498 | static irqreturn_t cmos_interrupt(int irq, void *p) |
399 | { | 499 | { |
400 | u8 irqstat; | 500 | u8 irqstat; |
501 | u8 rtc_control; | ||
401 | 502 | ||
402 | spin_lock(&rtc_lock); | 503 | spin_lock(&rtc_lock); |
403 | irqstat = CMOS_READ(RTC_INTR_FLAGS); | 504 | /* |
404 | irqstat &= (CMOS_READ(RTC_CONTROL) & RTC_IRQMASK) | RTC_IRQF; | 505 | * In this case it is HPET RTC interrupt handler |
506 | * calling us, with the interrupt information | ||
507 | * passed as arg1, instead of irq. | ||
508 | */ | ||
509 | if (is_hpet_enabled()) | ||
510 | irqstat = (unsigned long)irq & 0xF0; | ||
511 | else { | ||
512 | irqstat = CMOS_READ(RTC_INTR_FLAGS); | ||
513 | rtc_control = CMOS_READ(RTC_CONTROL); | ||
514 | irqstat &= (rtc_control & RTC_IRQMASK) | RTC_IRQF; | ||
515 | } | ||
516 | |||
517 | /* All Linux RTC alarms should be treated as if they were oneshot. | ||
518 | * Similar code may be needed in system wakeup paths, in case the | ||
519 | * alarm woke the system. | ||
520 | */ | ||
521 | if (irqstat & RTC_AIE) { | ||
522 | rtc_control = CMOS_READ(RTC_CONTROL); | ||
523 | rtc_control &= ~RTC_AIE; | ||
524 | CMOS_WRITE(rtc_control, RTC_CONTROL); | ||
525 | CMOS_READ(RTC_INTR_FLAGS); | ||
526 | } | ||
405 | spin_unlock(&rtc_lock); | 527 | spin_unlock(&rtc_lock); |
406 | 528 | ||
407 | if (is_intr(irqstat)) { | 529 | if (is_intr(irqstat)) { |
@@ -412,11 +534,9 @@ static irqreturn_t cmos_interrupt(int irq, void *p) | |||
412 | } | 534 | } |
413 | 535 | ||
414 | #ifdef CONFIG_PNP | 536 | #ifdef CONFIG_PNP |
415 | #define is_pnp() 1 | ||
416 | #define INITSECTION | 537 | #define INITSECTION |
417 | 538 | ||
418 | #else | 539 | #else |
419 | #define is_pnp() 0 | ||
420 | #define INITSECTION __init | 540 | #define INITSECTION __init |
421 | #endif | 541 | #endif |
422 | 542 | ||
@@ -426,6 +546,7 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) | |||
426 | struct cmos_rtc_board_info *info = dev->platform_data; | 546 | struct cmos_rtc_board_info *info = dev->platform_data; |
427 | int retval = 0; | 547 | int retval = 0; |
428 | unsigned char rtc_control; | 548 | unsigned char rtc_control; |
549 | unsigned address_space; | ||
429 | 550 | ||
430 | /* there can be only one ... */ | 551 | /* there can be only one ... */ |
431 | if (cmos_rtc.dev) | 552 | if (cmos_rtc.dev) |
@@ -450,15 +571,36 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) | |||
450 | cmos_rtc.irq = rtc_irq; | 571 | cmos_rtc.irq = rtc_irq; |
451 | cmos_rtc.iomem = ports; | 572 | cmos_rtc.iomem = ports; |
452 | 573 | ||
574 | /* Heuristic to deduce NVRAM size ... do what the legacy NVRAM | ||
575 | * driver did, but don't reject unknown configs. Old hardware | ||
576 | * won't address 128 bytes, and for now we ignore the way newer | ||
577 | * chips can address 256 bytes (using two more i/o ports). | ||
578 | */ | ||
579 | #if defined(CONFIG_ATARI) | ||
580 | address_space = 64; | ||
581 | #elif defined(__i386__) || defined(__x86_64__) || defined(__arm__) | ||
582 | address_space = 128; | ||
583 | #else | ||
584 | #warning Assuming 128 bytes of RTC+NVRAM address space, not 64 bytes. | ||
585 | address_space = 128; | ||
586 | #endif | ||
587 | |||
453 | /* For ACPI systems extension info comes from the FADT. On others, | 588 | /* For ACPI systems extension info comes from the FADT. On others, |
454 | * board specific setup provides it as appropriate. Systems where | 589 | * board specific setup provides it as appropriate. Systems where |
455 | * the alarm IRQ isn't automatically a wakeup IRQ (like ACPI, and | 590 | * the alarm IRQ isn't automatically a wakeup IRQ (like ACPI, and |
456 | * some almost-clones) can provide hooks to make that behave. | 591 | * some almost-clones) can provide hooks to make that behave. |
592 | * | ||
593 | * Note that ACPI doesn't preclude putting these registers into | ||
594 | * "extended" areas of the chip, including some that we won't yet | ||
595 | * expect CMOS_READ and friends to handle. | ||
457 | */ | 596 | */ |
458 | if (info) { | 597 | if (info) { |
459 | cmos_rtc.day_alrm = info->rtc_day_alarm; | 598 | if (info->rtc_day_alarm && info->rtc_day_alarm < 128) |
460 | cmos_rtc.mon_alrm = info->rtc_mon_alarm; | 599 | cmos_rtc.day_alrm = info->rtc_day_alarm; |
461 | cmos_rtc.century = info->rtc_century; | 600 | if (info->rtc_mon_alarm && info->rtc_mon_alarm < 128) |
601 | cmos_rtc.mon_alrm = info->rtc_mon_alarm; | ||
602 | if (info->rtc_century && info->rtc_century < 128) | ||
603 | cmos_rtc.century = info->rtc_century; | ||
462 | 604 | ||
463 | if (info->wake_on && info->wake_off) { | 605 | if (info->wake_on && info->wake_off) { |
464 | cmos_rtc.wake_on = info->wake_on; | 606 | cmos_rtc.wake_on = info->wake_on; |
@@ -485,8 +627,9 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) | |||
485 | * doesn't use 32KHz here ... for portability we might need to | 627 | * doesn't use 32KHz here ... for portability we might need to |
486 | * do something about other clock frequencies. | 628 | * do something about other clock frequencies. |
487 | */ | 629 | */ |
488 | CMOS_WRITE(RTC_REF_CLCK_32KHZ | 0x06, RTC_FREQ_SELECT); | ||
489 | cmos_rtc.rtc->irq_freq = 1024; | 630 | cmos_rtc.rtc->irq_freq = 1024; |
631 | if (!hpet_set_periodic_freq(cmos_rtc.rtc->irq_freq)) | ||
632 | CMOS_WRITE(RTC_REF_CLCK_32KHZ | 0x06, RTC_FREQ_SELECT); | ||
490 | 633 | ||
491 | /* disable irqs. | 634 | /* disable irqs. |
492 | * | 635 | * |
@@ -509,19 +652,39 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) | |||
509 | goto cleanup1; | 652 | goto cleanup1; |
510 | } | 653 | } |
511 | 654 | ||
512 | if (is_valid_irq(rtc_irq)) | 655 | if (is_valid_irq(rtc_irq)) { |
513 | retval = request_irq(rtc_irq, cmos_interrupt, IRQF_DISABLED, | 656 | irq_handler_t rtc_cmos_int_handler; |
514 | cmos_rtc.rtc->dev.bus_id, | 657 | |
658 | if (is_hpet_enabled()) { | ||
659 | int err; | ||
660 | |||
661 | rtc_cmos_int_handler = hpet_rtc_interrupt; | ||
662 | err = hpet_register_irq_handler(cmos_interrupt); | ||
663 | if (err != 0) { | ||
664 | printk(KERN_WARNING "hpet_register_irq_handler " | ||
665 | " failed in rtc_init()."); | ||
666 | goto cleanup1; | ||
667 | } | ||
668 | } else | ||
669 | rtc_cmos_int_handler = cmos_interrupt; | ||
670 | |||
671 | retval = request_irq(rtc_irq, rtc_cmos_int_handler, | ||
672 | IRQF_DISABLED, cmos_rtc.rtc->dev.bus_id, | ||
515 | cmos_rtc.rtc); | 673 | cmos_rtc.rtc); |
516 | if (retval < 0) { | 674 | if (retval < 0) { |
517 | dev_dbg(dev, "IRQ %d is already in use\n", rtc_irq); | 675 | dev_dbg(dev, "IRQ %d is already in use\n", rtc_irq); |
518 | goto cleanup1; | 676 | goto cleanup1; |
677 | } | ||
519 | } | 678 | } |
679 | hpet_rtc_timer_init(); | ||
520 | 680 | ||
521 | /* REVISIT optionally make 50 or 114 bytes NVRAM available, | 681 | /* export at least the first block of NVRAM */ |
522 | * like rtc-ds1553, rtc-ds1742 ... this will often include | 682 | nvram.size = address_space - NVRAM_OFFSET; |
523 | * registers for century, and day/month alarm. | 683 | retval = sysfs_create_bin_file(&dev->kobj, &nvram); |
524 | */ | 684 | if (retval < 0) { |
685 | dev_dbg(dev, "can't create nvram file? %d\n", retval); | ||
686 | goto cleanup2; | ||
687 | } | ||
525 | 688 | ||
526 | pr_info("%s: alarms up to one %s%s\n", | 689 | pr_info("%s: alarms up to one %s%s\n", |
527 | cmos_rtc.rtc->dev.bus_id, | 690 | cmos_rtc.rtc->dev.bus_id, |
@@ -536,6 +699,9 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) | |||
536 | 699 | ||
537 | return 0; | 700 | return 0; |
538 | 701 | ||
702 | cleanup2: | ||
703 | if (is_valid_irq(rtc_irq)) | ||
704 | free_irq(rtc_irq, cmos_rtc.rtc); | ||
539 | cleanup1: | 705 | cleanup1: |
540 | cmos_rtc.dev = NULL; | 706 | cmos_rtc.dev = NULL; |
541 | rtc_device_unregister(cmos_rtc.rtc); | 707 | rtc_device_unregister(cmos_rtc.rtc); |
@@ -563,8 +729,12 @@ static void __exit cmos_do_remove(struct device *dev) | |||
563 | 729 | ||
564 | cmos_do_shutdown(); | 730 | cmos_do_shutdown(); |
565 | 731 | ||
566 | if (is_valid_irq(cmos->irq)) | 732 | sysfs_remove_bin_file(&dev->kobj, &nvram); |
733 | |||
734 | if (is_valid_irq(cmos->irq)) { | ||
567 | free_irq(cmos->irq, cmos->rtc); | 735 | free_irq(cmos->irq, cmos->rtc); |
736 | hpet_unregister_irq_handler(cmos_interrupt); | ||
737 | } | ||
568 | 738 | ||
569 | rtc_device_unregister(cmos->rtc); | 739 | rtc_device_unregister(cmos->rtc); |
570 | cmos->rtc = NULL; | 740 | cmos->rtc = NULL; |
@@ -659,9 +829,12 @@ static int cmos_resume(struct device *dev) | |||
659 | 829 | ||
660 | /*----------------------------------------------------------------*/ | 830 | /*----------------------------------------------------------------*/ |
661 | 831 | ||
662 | /* The "CMOS" RTC normally lives on the platform_bus. On ACPI systems, | 832 | /* On non-x86 systems, a "CMOS" RTC lives most naturally on platform_bus. |
663 | * the device node will always be created as a PNPACPI device. Plus | 833 | * ACPI systems always list these as PNPACPI devices, and pre-ACPI PCs |
664 | * pre-ACPI PCs probably list it in the PNPBIOS tables. | 834 | * probably list them in similar PNPBIOS tables; so PNP is more common. |
835 | * | ||
836 | * We don't use legacy "poke at the hardware" probing. Ancient PCs that | ||
837 | * predate even PNPBIOS should set up platform_bus devices. | ||
665 | */ | 838 | */ |
666 | 839 | ||
667 | #ifdef CONFIG_PNP | 840 | #ifdef CONFIG_PNP |
diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c index 025c60a17a4a..90dfa0df747a 100644 --- a/drivers/rtc/rtc-dev.c +++ b/drivers/rtc/rtc-dev.c | |||
@@ -246,6 +246,15 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file, | |||
246 | /* if the driver does not provide the ioctl interface | 246 | /* if the driver does not provide the ioctl interface |
247 | * or if that particular ioctl was not implemented | 247 | * or if that particular ioctl was not implemented |
248 | * (-ENOIOCTLCMD), we will try to emulate here. | 248 | * (-ENOIOCTLCMD), we will try to emulate here. |
249 | * | ||
250 | * Drivers *SHOULD NOT* provide ioctl implementations | ||
251 | * for these requests. Instead, provide methods to | ||
252 | * support the following code, so that the RTC's main | ||
253 | * features are accessible without using ioctls. | ||
254 | * | ||
255 | * RTC and alarm times will be in UTC, by preference, | ||
256 | * but dual-booting with MS-Windows implies RTCs must | ||
257 | * use the local wall clock time. | ||
249 | */ | 258 | */ |
250 | 259 | ||
251 | switch (cmd) { | 260 | switch (cmd) { |
diff --git a/drivers/rtc/rtc-ds1302.c b/drivers/rtc/rtc-ds1302.c new file mode 100644 index 000000000000..7b002ceeaa7d --- /dev/null +++ b/drivers/rtc/rtc-ds1302.c | |||
@@ -0,0 +1,262 @@ | |||
1 | /* | ||
2 | * Dallas DS1302 RTC Support | ||
3 | * | ||
4 | * Copyright (C) 2002 David McCullough | ||
5 | * Copyright (C) 2003 - 2007 Paul Mundt | ||
6 | * | ||
7 | * This file is subject to the terms and conditions of the GNU General Public | ||
8 | * License version 2. See the file "COPYING" in the main directory of | ||
9 | * this archive for more details. | ||
10 | */ | ||
11 | #include <linux/init.h> | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/platform_device.h> | ||
15 | #include <linux/time.h> | ||
16 | #include <linux/rtc.h> | ||
17 | #include <linux/spinlock.h> | ||
18 | #include <linux/io.h> | ||
19 | #include <linux/bcd.h> | ||
20 | #include <asm/rtc.h> | ||
21 | |||
22 | #define DRV_NAME "rtc-ds1302" | ||
23 | #define DRV_VERSION "0.1.0" | ||
24 | |||
25 | #define RTC_CMD_READ 0x81 /* Read command */ | ||
26 | #define RTC_CMD_WRITE 0x80 /* Write command */ | ||
27 | |||
28 | #define RTC_ADDR_RAM0 0x20 /* Address of RAM0 */ | ||
29 | #define RTC_ADDR_TCR 0x08 /* Address of trickle charge register */ | ||
30 | #define RTC_ADDR_YEAR 0x06 /* Address of year register */ | ||
31 | #define RTC_ADDR_DAY 0x05 /* Address of day of week register */ | ||
32 | #define RTC_ADDR_MON 0x04 /* Address of month register */ | ||
33 | #define RTC_ADDR_DATE 0x03 /* Address of day of month register */ | ||
34 | #define RTC_ADDR_HOUR 0x02 /* Address of hour register */ | ||
35 | #define RTC_ADDR_MIN 0x01 /* Address of minute register */ | ||
36 | #define RTC_ADDR_SEC 0x00 /* Address of second register */ | ||
37 | |||
38 | #define RTC_RESET 0x1000 | ||
39 | #define RTC_IODATA 0x0800 | ||
40 | #define RTC_SCLK 0x0400 | ||
41 | |||
42 | #ifdef CONFIG_SH_SECUREEDGE5410 | ||
43 | #include <asm/snapgear.h> | ||
44 | #define set_dp(x) SECUREEDGE_WRITE_IOPORT(x, 0x1c00) | ||
45 | #define get_dp() SECUREEDGE_READ_IOPORT() | ||
46 | #else | ||
47 | #error "Add support for your platform" | ||
48 | #endif | ||
49 | |||
50 | struct ds1302_rtc { | ||
51 | struct rtc_device *rtc_dev; | ||
52 | spinlock_t lock; | ||
53 | }; | ||
54 | |||
55 | static void ds1302_sendbits(unsigned int val) | ||
56 | { | ||
57 | int i; | ||
58 | |||
59 | for (i = 8; (i); i--, val >>= 1) { | ||
60 | set_dp((get_dp() & ~RTC_IODATA) | ((val & 0x1) ? | ||
61 | RTC_IODATA : 0)); | ||
62 | set_dp(get_dp() | RTC_SCLK); /* clock high */ | ||
63 | set_dp(get_dp() & ~RTC_SCLK); /* clock low */ | ||
64 | } | ||
65 | } | ||
66 | |||
67 | static unsigned int ds1302_recvbits(void) | ||
68 | { | ||
69 | unsigned int val; | ||
70 | int i; | ||
71 | |||
72 | for (i = 0, val = 0; (i < 8); i++) { | ||
73 | val |= (((get_dp() & RTC_IODATA) ? 1 : 0) << i); | ||
74 | set_dp(get_dp() | RTC_SCLK); /* clock high */ | ||
75 | set_dp(get_dp() & ~RTC_SCLK); /* clock low */ | ||
76 | } | ||
77 | |||
78 | return val; | ||
79 | } | ||
80 | |||
81 | static unsigned int ds1302_readbyte(unsigned int addr) | ||
82 | { | ||
83 | unsigned int val; | ||
84 | |||
85 | set_dp(get_dp() & ~(RTC_RESET | RTC_IODATA | RTC_SCLK)); | ||
86 | |||
87 | set_dp(get_dp() | RTC_RESET); | ||
88 | ds1302_sendbits(((addr & 0x3f) << 1) | RTC_CMD_READ); | ||
89 | val = ds1302_recvbits(); | ||
90 | set_dp(get_dp() & ~RTC_RESET); | ||
91 | |||
92 | return val; | ||
93 | } | ||
94 | |||
95 | static void ds1302_writebyte(unsigned int addr, unsigned int val) | ||
96 | { | ||
97 | set_dp(get_dp() & ~(RTC_RESET | RTC_IODATA | RTC_SCLK)); | ||
98 | set_dp(get_dp() | RTC_RESET); | ||
99 | ds1302_sendbits(((addr & 0x3f) << 1) | RTC_CMD_WRITE); | ||
100 | ds1302_sendbits(val); | ||
101 | set_dp(get_dp() & ~RTC_RESET); | ||
102 | } | ||
103 | |||
104 | static int ds1302_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
105 | { | ||
106 | struct ds1302_rtc *rtc = dev_get_drvdata(dev); | ||
107 | |||
108 | spin_lock_irq(&rtc->lock); | ||
109 | |||
110 | tm->tm_sec = BCD2BIN(ds1302_readbyte(RTC_ADDR_SEC)); | ||
111 | tm->tm_min = BCD2BIN(ds1302_readbyte(RTC_ADDR_MIN)); | ||
112 | tm->tm_hour = BCD2BIN(ds1302_readbyte(RTC_ADDR_HOUR)); | ||
113 | tm->tm_wday = BCD2BIN(ds1302_readbyte(RTC_ADDR_DAY)); | ||
114 | tm->tm_mday = BCD2BIN(ds1302_readbyte(RTC_ADDR_DATE)); | ||
115 | tm->tm_mon = BCD2BIN(ds1302_readbyte(RTC_ADDR_MON)) - 1; | ||
116 | tm->tm_year = BCD2BIN(ds1302_readbyte(RTC_ADDR_YEAR)); | ||
117 | |||
118 | if (tm->tm_year < 70) | ||
119 | tm->tm_year += 100; | ||
120 | |||
121 | spin_unlock_irq(&rtc->lock); | ||
122 | |||
123 | dev_dbg(dev, "%s: tm is secs=%d, mins=%d, hours=%d, " | ||
124 | "mday=%d, mon=%d, year=%d, wday=%d\n", | ||
125 | __FUNCTION__, | ||
126 | tm->tm_sec, tm->tm_min, tm->tm_hour, | ||
127 | tm->tm_mday, tm->tm_mon + 1, tm->tm_year, tm->tm_wday); | ||
128 | |||
129 | if (rtc_valid_tm(tm) < 0) | ||
130 | dev_err(dev, "invalid date\n"); | ||
131 | |||
132 | return 0; | ||
133 | } | ||
134 | |||
135 | static int ds1302_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
136 | { | ||
137 | struct ds1302_rtc *rtc = dev_get_drvdata(dev); | ||
138 | |||
139 | spin_lock_irq(&rtc->lock); | ||
140 | |||
141 | /* Stop RTC */ | ||
142 | ds1302_writebyte(RTC_ADDR_SEC, ds1302_readbyte(RTC_ADDR_SEC) | 0x80); | ||
143 | |||
144 | ds1302_writebyte(RTC_ADDR_SEC, BIN2BCD(tm->tm_sec)); | ||
145 | ds1302_writebyte(RTC_ADDR_MIN, BIN2BCD(tm->tm_min)); | ||
146 | ds1302_writebyte(RTC_ADDR_HOUR, BIN2BCD(tm->tm_hour)); | ||
147 | ds1302_writebyte(RTC_ADDR_DAY, BIN2BCD(tm->tm_wday)); | ||
148 | ds1302_writebyte(RTC_ADDR_DATE, BIN2BCD(tm->tm_mday)); | ||
149 | ds1302_writebyte(RTC_ADDR_MON, BIN2BCD(tm->tm_mon + 1)); | ||
150 | ds1302_writebyte(RTC_ADDR_YEAR, BIN2BCD(tm->tm_year % 100)); | ||
151 | |||
152 | /* Start RTC */ | ||
153 | ds1302_writebyte(RTC_ADDR_SEC, ds1302_readbyte(RTC_ADDR_SEC) & ~0x80); | ||
154 | |||
155 | spin_unlock_irq(&rtc->lock); | ||
156 | |||
157 | return 0; | ||
158 | } | ||
159 | |||
160 | static int ds1302_rtc_ioctl(struct device *dev, unsigned int cmd, | ||
161 | unsigned long arg) | ||
162 | { | ||
163 | switch (cmd) { | ||
164 | #ifdef RTC_SET_CHARGE | ||
165 | case RTC_SET_CHARGE: | ||
166 | { | ||
167 | struct ds1302_rtc *rtc = dev_get_drvdata(dev); | ||
168 | int tcs_val; | ||
169 | |||
170 | if (copy_from_user(&tcs_val, (int __user *)arg, sizeof(int))) | ||
171 | return -EFAULT; | ||
172 | |||
173 | spin_lock_irq(&rtc->lock); | ||
174 | ds1302_writebyte(RTC_ADDR_TCR, (0xa0 | tcs_val * 0xf)); | ||
175 | spin_unlock_irq(&rtc->lock); | ||
176 | return 0; | ||
177 | } | ||
178 | #endif | ||
179 | } | ||
180 | |||
181 | return -ENOIOCTLCMD; | ||
182 | } | ||
183 | |||
184 | static struct rtc_class_ops ds1302_rtc_ops = { | ||
185 | .read_time = ds1302_rtc_read_time, | ||
186 | .set_time = ds1302_rtc_set_time, | ||
187 | .ioctl = ds1302_rtc_ioctl, | ||
188 | }; | ||
189 | |||
190 | static int __devinit ds1302_rtc_probe(struct platform_device *pdev) | ||
191 | { | ||
192 | struct ds1302_rtc *rtc; | ||
193 | int ret; | ||
194 | |||
195 | /* Reset */ | ||
196 | set_dp(get_dp() & ~(RTC_RESET | RTC_IODATA | RTC_SCLK)); | ||
197 | |||
198 | /* Write a magic value to the DS1302 RAM, and see if it sticks. */ | ||
199 | ds1302_writebyte(RTC_ADDR_RAM0, 0x42); | ||
200 | if (ds1302_readbyte(RTC_ADDR_RAM0) != 0x42) | ||
201 | return -ENODEV; | ||
202 | |||
203 | rtc = kzalloc(sizeof(struct ds1302_rtc), GFP_KERNEL); | ||
204 | if (unlikely(!rtc)) | ||
205 | return -ENOMEM; | ||
206 | |||
207 | spin_lock_init(&rtc->lock); | ||
208 | rtc->rtc_dev = rtc_device_register("ds1302", &pdev->dev, | ||
209 | &ds1302_rtc_ops, THIS_MODULE); | ||
210 | if (IS_ERR(rtc->rtc_dev)) { | ||
211 | ret = PTR_ERR(rtc->rtc_dev); | ||
212 | goto out; | ||
213 | } | ||
214 | |||
215 | platform_set_drvdata(pdev, rtc); | ||
216 | |||
217 | return 0; | ||
218 | out: | ||
219 | kfree(rtc); | ||
220 | return ret; | ||
221 | } | ||
222 | |||
223 | static int __devexit ds1302_rtc_remove(struct platform_device *pdev) | ||
224 | { | ||
225 | struct ds1302_rtc *rtc = platform_get_drvdata(pdev); | ||
226 | |||
227 | if (likely(rtc->rtc_dev)) | ||
228 | rtc_device_unregister(rtc->rtc_dev); | ||
229 | |||
230 | platform_set_drvdata(pdev, NULL); | ||
231 | |||
232 | kfree(rtc); | ||
233 | |||
234 | return 0; | ||
235 | } | ||
236 | |||
237 | static struct platform_driver ds1302_platform_driver = { | ||
238 | .driver = { | ||
239 | .name = DRV_NAME, | ||
240 | .owner = THIS_MODULE, | ||
241 | }, | ||
242 | .probe = ds1302_rtc_probe, | ||
243 | .remove = __devexit_p(ds1302_rtc_remove), | ||
244 | }; | ||
245 | |||
246 | static int __init ds1302_rtc_init(void) | ||
247 | { | ||
248 | return platform_driver_register(&ds1302_platform_driver); | ||
249 | } | ||
250 | |||
251 | static void __exit ds1302_rtc_exit(void) | ||
252 | { | ||
253 | platform_driver_unregister(&ds1302_platform_driver); | ||
254 | } | ||
255 | |||
256 | module_init(ds1302_rtc_init); | ||
257 | module_exit(ds1302_rtc_exit); | ||
258 | |||
259 | MODULE_DESCRIPTION("Dallas DS1302 RTC driver"); | ||
260 | MODULE_VERSION(DRV_VERSION); | ||
261 | MODULE_AUTHOR("Paul Mundt, David McCullough"); | ||
262 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c index bc1c7fe94ad3..f389a28720d2 100644 --- a/drivers/rtc/rtc-ds1307.c +++ b/drivers/rtc/rtc-ds1307.c | |||
@@ -256,7 +256,7 @@ ds1307_nvram_read(struct kobject *kobj, struct bin_attribute *attr, | |||
256 | struct i2c_msg msg[2]; | 256 | struct i2c_msg msg[2]; |
257 | int result; | 257 | int result; |
258 | 258 | ||
259 | client = to_i2c_client(container_of(kobj, struct device, kobj)); | 259 | client = kobj_to_i2c_client(kobj); |
260 | ds1307 = i2c_get_clientdata(client); | 260 | ds1307 = i2c_get_clientdata(client); |
261 | 261 | ||
262 | if (unlikely(off >= NVRAM_SIZE)) | 262 | if (unlikely(off >= NVRAM_SIZE)) |
@@ -294,7 +294,7 @@ ds1307_nvram_write(struct kobject *kobj, struct bin_attribute *attr, | |||
294 | u8 buffer[NVRAM_SIZE + 1]; | 294 | u8 buffer[NVRAM_SIZE + 1]; |
295 | int ret; | 295 | int ret; |
296 | 296 | ||
297 | client = to_i2c_client(container_of(kobj, struct device, kobj)); | 297 | client = kobj_to_i2c_client(kobj); |
298 | 298 | ||
299 | if (unlikely(off >= NVRAM_SIZE)) | 299 | if (unlikely(off >= NVRAM_SIZE)) |
300 | return -EFBIG; | 300 | return -EFBIG; |
@@ -412,11 +412,6 @@ read_rtc: | |||
412 | */ | 412 | */ |
413 | tmp = ds1307->regs[DS1307_REG_SECS]; | 413 | tmp = ds1307->regs[DS1307_REG_SECS]; |
414 | switch (ds1307->type) { | 414 | switch (ds1307->type) { |
415 | case ds_1340: | ||
416 | /* FIXME read register with DS1340_BIT_OSF, use that to | ||
417 | * trigger the "set time" warning (*after* restarting the | ||
418 | * oscillator!) instead of this weaker ds1307/m41t00 test. | ||
419 | */ | ||
420 | case ds_1307: | 415 | case ds_1307: |
421 | case m41t00: | 416 | case m41t00: |
422 | /* clock halted? turn it on, so clock can tick. */ | 417 | /* clock halted? turn it on, so clock can tick. */ |
@@ -440,6 +435,24 @@ read_rtc: | |||
440 | goto read_rtc; | 435 | goto read_rtc; |
441 | } | 436 | } |
442 | break; | 437 | break; |
438 | case ds_1340: | ||
439 | /* clock halted? turn it on, so clock can tick. */ | ||
440 | if (tmp & DS1340_BIT_nEOSC) | ||
441 | i2c_smbus_write_byte_data(client, DS1307_REG_SECS, 0); | ||
442 | |||
443 | tmp = i2c_smbus_read_byte_data(client, DS1340_REG_FLAG); | ||
444 | if (tmp < 0) { | ||
445 | pr_debug("read error %d\n", tmp); | ||
446 | err = -EIO; | ||
447 | goto exit_free; | ||
448 | } | ||
449 | |||
450 | /* oscillator fault? clear flag, and warn */ | ||
451 | if (tmp & DS1340_BIT_OSF) { | ||
452 | i2c_smbus_write_byte_data(client, DS1340_REG_FLAG, 0); | ||
453 | dev_warn(&client->dev, "SET TIME!\n"); | ||
454 | } | ||
455 | break; | ||
443 | case ds_1337: | 456 | case ds_1337: |
444 | case ds_1339: | 457 | case ds_1339: |
445 | break; | 458 | break; |
diff --git a/drivers/rtc/rtc-ds1511.c b/drivers/rtc/rtc-ds1511.c new file mode 100644 index 000000000000..d74b8086fa31 --- /dev/null +++ b/drivers/rtc/rtc-ds1511.c | |||
@@ -0,0 +1,656 @@ | |||
1 | /* | ||
2 | * An rtc driver for the Dallas DS1511 | ||
3 | * | ||
4 | * Copyright (C) 2006 Atsushi Nemoto <anemo@mba.ocn.ne.jp> | ||
5 | * Copyright (C) 2007 Andrew Sharp <andy.sharp@onstor.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * Real time clock driver for the Dallas 1511 chip, which also | ||
12 | * contains a watchdog timer. There is a tiny amount of code that | ||
13 | * platform code could use to mess with the watchdog device a little | ||
14 | * bit, but not a full watchdog driver. | ||
15 | */ | ||
16 | |||
17 | #include <linux/bcd.h> | ||
18 | #include <linux/init.h> | ||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/delay.h> | ||
21 | #include <linux/interrupt.h> | ||
22 | #include <linux/rtc.h> | ||
23 | #include <linux/platform_device.h> | ||
24 | #include <linux/io.h> | ||
25 | |||
26 | #define DRV_VERSION "0.6" | ||
27 | |||
28 | enum ds1511reg { | ||
29 | DS1511_SEC = 0x0, | ||
30 | DS1511_MIN = 0x1, | ||
31 | DS1511_HOUR = 0x2, | ||
32 | DS1511_DOW = 0x3, | ||
33 | DS1511_DOM = 0x4, | ||
34 | DS1511_MONTH = 0x5, | ||
35 | DS1511_YEAR = 0x6, | ||
36 | DS1511_CENTURY = 0x7, | ||
37 | DS1511_AM1_SEC = 0x8, | ||
38 | DS1511_AM2_MIN = 0x9, | ||
39 | DS1511_AM3_HOUR = 0xa, | ||
40 | DS1511_AM4_DATE = 0xb, | ||
41 | DS1511_WD_MSEC = 0xc, | ||
42 | DS1511_WD_SEC = 0xd, | ||
43 | DS1511_CONTROL_A = 0xe, | ||
44 | DS1511_CONTROL_B = 0xf, | ||
45 | DS1511_RAMADDR_LSB = 0x10, | ||
46 | DS1511_RAMDATA = 0x13 | ||
47 | }; | ||
48 | |||
49 | #define DS1511_BLF1 0x80 | ||
50 | #define DS1511_BLF2 0x40 | ||
51 | #define DS1511_PRS 0x20 | ||
52 | #define DS1511_PAB 0x10 | ||
53 | #define DS1511_TDF 0x08 | ||
54 | #define DS1511_KSF 0x04 | ||
55 | #define DS1511_WDF 0x02 | ||
56 | #define DS1511_IRQF 0x01 | ||
57 | #define DS1511_TE 0x80 | ||
58 | #define DS1511_CS 0x40 | ||
59 | #define DS1511_BME 0x20 | ||
60 | #define DS1511_TPE 0x10 | ||
61 | #define DS1511_TIE 0x08 | ||
62 | #define DS1511_KIE 0x04 | ||
63 | #define DS1511_WDE 0x02 | ||
64 | #define DS1511_WDS 0x01 | ||
65 | #define DS1511_RAM_MAX 0xff | ||
66 | |||
67 | #define RTC_CMD DS1511_CONTROL_B | ||
68 | #define RTC_CMD1 DS1511_CONTROL_A | ||
69 | |||
70 | #define RTC_ALARM_SEC DS1511_AM1_SEC | ||
71 | #define RTC_ALARM_MIN DS1511_AM2_MIN | ||
72 | #define RTC_ALARM_HOUR DS1511_AM3_HOUR | ||
73 | #define RTC_ALARM_DATE DS1511_AM4_DATE | ||
74 | |||
75 | #define RTC_SEC DS1511_SEC | ||
76 | #define RTC_MIN DS1511_MIN | ||
77 | #define RTC_HOUR DS1511_HOUR | ||
78 | #define RTC_DOW DS1511_DOW | ||
79 | #define RTC_DOM DS1511_DOM | ||
80 | #define RTC_MON DS1511_MONTH | ||
81 | #define RTC_YEAR DS1511_YEAR | ||
82 | #define RTC_CENTURY DS1511_CENTURY | ||
83 | |||
84 | #define RTC_TIE DS1511_TIE | ||
85 | #define RTC_TE DS1511_TE | ||
86 | |||
87 | struct rtc_plat_data { | ||
88 | struct rtc_device *rtc; | ||
89 | void __iomem *ioaddr; /* virtual base address */ | ||
90 | unsigned long baseaddr; /* physical base address */ | ||
91 | int size; /* amount of memory mapped */ | ||
92 | int irq; | ||
93 | unsigned int irqen; | ||
94 | int alrm_sec; | ||
95 | int alrm_min; | ||
96 | int alrm_hour; | ||
97 | int alrm_mday; | ||
98 | }; | ||
99 | |||
100 | static DEFINE_SPINLOCK(ds1511_lock); | ||
101 | |||
102 | static __iomem char *ds1511_base; | ||
103 | static u32 reg_spacing = 1; | ||
104 | |||
105 | static noinline void | ||
106 | rtc_write(uint8_t val, uint32_t reg) | ||
107 | { | ||
108 | writeb(val, ds1511_base + (reg * reg_spacing)); | ||
109 | } | ||
110 | |||
111 | static inline void | ||
112 | rtc_write_alarm(uint8_t val, enum ds1511reg reg) | ||
113 | { | ||
114 | rtc_write((val | 0x80), reg); | ||
115 | } | ||
116 | |||
117 | static noinline uint8_t | ||
118 | rtc_read(enum ds1511reg reg) | ||
119 | { | ||
120 | return readb(ds1511_base + (reg * reg_spacing)); | ||
121 | } | ||
122 | |||
123 | static inline void | ||
124 | rtc_disable_update(void) | ||
125 | { | ||
126 | rtc_write((rtc_read(RTC_CMD) & ~RTC_TE), RTC_CMD); | ||
127 | } | ||
128 | |||
129 | static void | ||
130 | rtc_enable_update(void) | ||
131 | { | ||
132 | rtc_write((rtc_read(RTC_CMD) | RTC_TE), RTC_CMD); | ||
133 | } | ||
134 | |||
135 | /* | ||
136 | * #define DS1511_WDOG_RESET_SUPPORT | ||
137 | * | ||
138 | * Uncomment this if you want to use these routines in | ||
139 | * some platform code. | ||
140 | */ | ||
141 | #ifdef DS1511_WDOG_RESET_SUPPORT | ||
142 | /* | ||
143 | * just enough code to set the watchdog timer so that it | ||
144 | * will reboot the system | ||
145 | */ | ||
146 | void | ||
147 | ds1511_wdog_set(unsigned long deciseconds) | ||
148 | { | ||
149 | /* | ||
150 | * the wdog timer can take 99.99 seconds | ||
151 | */ | ||
152 | deciseconds %= 10000; | ||
153 | /* | ||
154 | * set the wdog values in the wdog registers | ||
155 | */ | ||
156 | rtc_write(BIN2BCD(deciseconds % 100), DS1511_WD_MSEC); | ||
157 | rtc_write(BIN2BCD(deciseconds / 100), DS1511_WD_SEC); | ||
158 | /* | ||
159 | * set wdog enable and wdog 'steering' bit to issue a reset | ||
160 | */ | ||
161 | rtc_write(DS1511_WDE | DS1511_WDS, RTC_CMD); | ||
162 | } | ||
163 | |||
164 | void | ||
165 | ds1511_wdog_disable(void) | ||
166 | { | ||
167 | /* | ||
168 | * clear wdog enable and wdog 'steering' bits | ||
169 | */ | ||
170 | rtc_write(rtc_read(RTC_CMD) & ~(DS1511_WDE | DS1511_WDS), RTC_CMD); | ||
171 | /* | ||
172 | * clear the wdog counter | ||
173 | */ | ||
174 | rtc_write(0, DS1511_WD_MSEC); | ||
175 | rtc_write(0, DS1511_WD_SEC); | ||
176 | } | ||
177 | #endif | ||
178 | |||
179 | /* | ||
180 | * set the rtc chip's idea of the time. | ||
181 | * stupidly, some callers call with year unmolested; | ||
182 | * and some call with year = year - 1900. thanks. | ||
183 | */ | ||
184 | int | ||
185 | ds1511_rtc_set_time(struct device *dev, struct rtc_time *rtc_tm) | ||
186 | { | ||
187 | u8 mon, day, dow, hrs, min, sec, yrs, cen; | ||
188 | unsigned int flags; | ||
189 | |||
190 | /* | ||
191 | * won't have to change this for a while | ||
192 | */ | ||
193 | if (rtc_tm->tm_year < 1900) { | ||
194 | rtc_tm->tm_year += 1900; | ||
195 | } | ||
196 | |||
197 | if (rtc_tm->tm_year < 1970) { | ||
198 | return -EINVAL; | ||
199 | } | ||
200 | yrs = rtc_tm->tm_year % 100; | ||
201 | cen = rtc_tm->tm_year / 100; | ||
202 | mon = rtc_tm->tm_mon + 1; /* tm_mon starts at zero */ | ||
203 | day = rtc_tm->tm_mday; | ||
204 | dow = rtc_tm->tm_wday & 0x7; /* automatic BCD */ | ||
205 | hrs = rtc_tm->tm_hour; | ||
206 | min = rtc_tm->tm_min; | ||
207 | sec = rtc_tm->tm_sec; | ||
208 | |||
209 | if ((mon > 12) || (day == 0)) { | ||
210 | return -EINVAL; | ||
211 | } | ||
212 | |||
213 | if (day > rtc_month_days(rtc_tm->tm_mon, rtc_tm->tm_year)) { | ||
214 | return -EINVAL; | ||
215 | } | ||
216 | |||
217 | if ((hrs >= 24) || (min >= 60) || (sec >= 60)) { | ||
218 | return -EINVAL; | ||
219 | } | ||
220 | |||
221 | /* | ||
222 | * each register is a different number of valid bits | ||
223 | */ | ||
224 | sec = BIN2BCD(sec) & 0x7f; | ||
225 | min = BIN2BCD(min) & 0x7f; | ||
226 | hrs = BIN2BCD(hrs) & 0x3f; | ||
227 | day = BIN2BCD(day) & 0x3f; | ||
228 | mon = BIN2BCD(mon) & 0x1f; | ||
229 | yrs = BIN2BCD(yrs) & 0xff; | ||
230 | cen = BIN2BCD(cen) & 0xff; | ||
231 | |||
232 | spin_lock_irqsave(&ds1511_lock, flags); | ||
233 | rtc_disable_update(); | ||
234 | rtc_write(cen, RTC_CENTURY); | ||
235 | rtc_write(yrs, RTC_YEAR); | ||
236 | rtc_write((rtc_read(RTC_MON) & 0xe0) | mon, RTC_MON); | ||
237 | rtc_write(day, RTC_DOM); | ||
238 | rtc_write(hrs, RTC_HOUR); | ||
239 | rtc_write(min, RTC_MIN); | ||
240 | rtc_write(sec, RTC_SEC); | ||
241 | rtc_write(dow, RTC_DOW); | ||
242 | rtc_enable_update(); | ||
243 | spin_unlock_irqrestore(&ds1511_lock, flags); | ||
244 | |||
245 | return 0; | ||
246 | } | ||
247 | |||
248 | int | ||
249 | ds1511_rtc_read_time(struct device *dev, struct rtc_time *rtc_tm) | ||
250 | { | ||
251 | unsigned int century; | ||
252 | unsigned int flags; | ||
253 | |||
254 | spin_lock_irqsave(&ds1511_lock, flags); | ||
255 | rtc_disable_update(); | ||
256 | |||
257 | rtc_tm->tm_sec = rtc_read(RTC_SEC) & 0x7f; | ||
258 | rtc_tm->tm_min = rtc_read(RTC_MIN) & 0x7f; | ||
259 | rtc_tm->tm_hour = rtc_read(RTC_HOUR) & 0x3f; | ||
260 | rtc_tm->tm_mday = rtc_read(RTC_DOM) & 0x3f; | ||
261 | rtc_tm->tm_wday = rtc_read(RTC_DOW) & 0x7; | ||
262 | rtc_tm->tm_mon = rtc_read(RTC_MON) & 0x1f; | ||
263 | rtc_tm->tm_year = rtc_read(RTC_YEAR) & 0x7f; | ||
264 | century = rtc_read(RTC_CENTURY); | ||
265 | |||
266 | rtc_enable_update(); | ||
267 | spin_unlock_irqrestore(&ds1511_lock, flags); | ||
268 | |||
269 | rtc_tm->tm_sec = BCD2BIN(rtc_tm->tm_sec); | ||
270 | rtc_tm->tm_min = BCD2BIN(rtc_tm->tm_min); | ||
271 | rtc_tm->tm_hour = BCD2BIN(rtc_tm->tm_hour); | ||
272 | rtc_tm->tm_mday = BCD2BIN(rtc_tm->tm_mday); | ||
273 | rtc_tm->tm_wday = BCD2BIN(rtc_tm->tm_wday); | ||
274 | rtc_tm->tm_mon = BCD2BIN(rtc_tm->tm_mon); | ||
275 | rtc_tm->tm_year = BCD2BIN(rtc_tm->tm_year); | ||
276 | century = BCD2BIN(century) * 100; | ||
277 | |||
278 | /* | ||
279 | * Account for differences between how the RTC uses the values | ||
280 | * and how they are defined in a struct rtc_time; | ||
281 | */ | ||
282 | century += rtc_tm->tm_year; | ||
283 | rtc_tm->tm_year = century - 1900; | ||
284 | |||
285 | rtc_tm->tm_mon--; | ||
286 | |||
287 | if (rtc_valid_tm(rtc_tm) < 0) { | ||
288 | dev_err(dev, "retrieved date/time is not valid.\n"); | ||
289 | rtc_time_to_tm(0, rtc_tm); | ||
290 | } | ||
291 | return 0; | ||
292 | } | ||
293 | |||
294 | /* | ||
295 | * write the alarm register settings | ||
296 | * | ||
297 | * we only have the use to interrupt every second, otherwise | ||
298 | * known as the update interrupt, or the interrupt if the whole | ||
299 | * date/hours/mins/secs matches. the ds1511 has many more | ||
300 | * permutations, but the kernel doesn't. | ||
301 | */ | ||
302 | static void | ||
303 | ds1511_rtc_update_alarm(struct rtc_plat_data *pdata) | ||
304 | { | ||
305 | unsigned long flags; | ||
306 | |||
307 | spin_lock_irqsave(&pdata->rtc->irq_lock, flags); | ||
308 | rtc_write(pdata->alrm_mday < 0 || (pdata->irqen & RTC_UF) ? | ||
309 | 0x80 : BIN2BCD(pdata->alrm_mday) & 0x3f, | ||
310 | RTC_ALARM_DATE); | ||
311 | rtc_write(pdata->alrm_hour < 0 || (pdata->irqen & RTC_UF) ? | ||
312 | 0x80 : BIN2BCD(pdata->alrm_hour) & 0x3f, | ||
313 | RTC_ALARM_HOUR); | ||
314 | rtc_write(pdata->alrm_min < 0 || (pdata->irqen & RTC_UF) ? | ||
315 | 0x80 : BIN2BCD(pdata->alrm_min) & 0x7f, | ||
316 | RTC_ALARM_MIN); | ||
317 | rtc_write(pdata->alrm_sec < 0 || (pdata->irqen & RTC_UF) ? | ||
318 | 0x80 : BIN2BCD(pdata->alrm_sec) & 0x7f, | ||
319 | RTC_ALARM_SEC); | ||
320 | rtc_write(rtc_read(RTC_CMD) | (pdata->irqen ? RTC_TIE : 0), RTC_CMD); | ||
321 | rtc_read(RTC_CMD1); /* clear interrupts */ | ||
322 | spin_unlock_irqrestore(&pdata->rtc->irq_lock, flags); | ||
323 | } | ||
324 | |||
325 | static int | ||
326 | ds1511_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
327 | { | ||
328 | struct platform_device *pdev = to_platform_device(dev); | ||
329 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | ||
330 | |||
331 | if (pdata->irq < 0) { | ||
332 | return -EINVAL; | ||
333 | } | ||
334 | pdata->alrm_mday = alrm->time.tm_mday; | ||
335 | pdata->alrm_hour = alrm->time.tm_hour; | ||
336 | pdata->alrm_min = alrm->time.tm_min; | ||
337 | pdata->alrm_sec = alrm->time.tm_sec; | ||
338 | if (alrm->enabled) { | ||
339 | pdata->irqen |= RTC_AF; | ||
340 | } | ||
341 | ds1511_rtc_update_alarm(pdata); | ||
342 | return 0; | ||
343 | } | ||
344 | |||
345 | static int | ||
346 | ds1511_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) | ||
347 | { | ||
348 | struct platform_device *pdev = to_platform_device(dev); | ||
349 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | ||
350 | |||
351 | if (pdata->irq < 0) { | ||
352 | return -EINVAL; | ||
353 | } | ||
354 | alrm->time.tm_mday = pdata->alrm_mday < 0 ? 0 : pdata->alrm_mday; | ||
355 | alrm->time.tm_hour = pdata->alrm_hour < 0 ? 0 : pdata->alrm_hour; | ||
356 | alrm->time.tm_min = pdata->alrm_min < 0 ? 0 : pdata->alrm_min; | ||
357 | alrm->time.tm_sec = pdata->alrm_sec < 0 ? 0 : pdata->alrm_sec; | ||
358 | alrm->enabled = (pdata->irqen & RTC_AF) ? 1 : 0; | ||
359 | return 0; | ||
360 | } | ||
361 | |||
362 | static irqreturn_t | ||
363 | ds1511_interrupt(int irq, void *dev_id) | ||
364 | { | ||
365 | struct platform_device *pdev = dev_id; | ||
366 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | ||
367 | unsigned long events = RTC_IRQF; | ||
368 | |||
369 | /* | ||
370 | * read and clear interrupt | ||
371 | */ | ||
372 | if (!(rtc_read(RTC_CMD1) & DS1511_IRQF)) { | ||
373 | return IRQ_NONE; | ||
374 | } | ||
375 | if (rtc_read(RTC_ALARM_SEC) & 0x80) { | ||
376 | events |= RTC_UF; | ||
377 | } else { | ||
378 | events |= RTC_AF; | ||
379 | } | ||
380 | rtc_update_irq(pdata->rtc, 1, events); | ||
381 | return IRQ_HANDLED; | ||
382 | } | ||
383 | |||
384 | static void | ||
385 | ds1511_rtc_release(struct device *dev) | ||
386 | { | ||
387 | struct platform_device *pdev = to_platform_device(dev); | ||
388 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | ||
389 | |||
390 | if (pdata->irq >= 0) { | ||
391 | pdata->irqen = 0; | ||
392 | ds1511_rtc_update_alarm(pdata); | ||
393 | } | ||
394 | } | ||
395 | |||
396 | static int | ||
397 | ds1511_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) | ||
398 | { | ||
399 | struct platform_device *pdev = to_platform_device(dev); | ||
400 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | ||
401 | |||
402 | if (pdata->irq < 0) { | ||
403 | return -ENOIOCTLCMD; /* fall back into rtc-dev's emulation */ | ||
404 | } | ||
405 | switch (cmd) { | ||
406 | case RTC_AIE_OFF: | ||
407 | pdata->irqen &= ~RTC_AF; | ||
408 | ds1511_rtc_update_alarm(pdata); | ||
409 | break; | ||
410 | case RTC_AIE_ON: | ||
411 | pdata->irqen |= RTC_AF; | ||
412 | ds1511_rtc_update_alarm(pdata); | ||
413 | break; | ||
414 | case RTC_UIE_OFF: | ||
415 | pdata->irqen &= ~RTC_UF; | ||
416 | ds1511_rtc_update_alarm(pdata); | ||
417 | break; | ||
418 | case RTC_UIE_ON: | ||
419 | pdata->irqen |= RTC_UF; | ||
420 | ds1511_rtc_update_alarm(pdata); | ||
421 | break; | ||
422 | default: | ||
423 | return -ENOIOCTLCMD; | ||
424 | } | ||
425 | return 0; | ||
426 | } | ||
427 | |||
428 | static const struct rtc_class_ops ds1511_rtc_ops = { | ||
429 | .read_time = ds1511_rtc_read_time, | ||
430 | .set_time = ds1511_rtc_set_time, | ||
431 | .read_alarm = ds1511_rtc_read_alarm, | ||
432 | .set_alarm = ds1511_rtc_set_alarm, | ||
433 | .release = ds1511_rtc_release, | ||
434 | .ioctl = ds1511_rtc_ioctl, | ||
435 | }; | ||
436 | |||
437 | static ssize_t | ||
438 | ds1511_nvram_read(struct kobject *kobj, struct bin_attribute *ba, | ||
439 | char *buf, loff_t pos, size_t size) | ||
440 | { | ||
441 | ssize_t count; | ||
442 | |||
443 | /* | ||
444 | * if count is more than one, turn on "burst" mode | ||
445 | * turn it off when you're done | ||
446 | */ | ||
447 | if (size > 1) { | ||
448 | rtc_write((rtc_read(RTC_CMD) | DS1511_BME), RTC_CMD); | ||
449 | } | ||
450 | if (pos > DS1511_RAM_MAX) { | ||
451 | pos = DS1511_RAM_MAX; | ||
452 | } | ||
453 | if (size + pos > DS1511_RAM_MAX + 1) { | ||
454 | size = DS1511_RAM_MAX - pos + 1; | ||
455 | } | ||
456 | rtc_write(pos, DS1511_RAMADDR_LSB); | ||
457 | for (count = 0; size > 0; count++, size--) { | ||
458 | *buf++ = rtc_read(DS1511_RAMDATA); | ||
459 | } | ||
460 | if (count > 1) { | ||
461 | rtc_write((rtc_read(RTC_CMD) & ~DS1511_BME), RTC_CMD); | ||
462 | } | ||
463 | return count; | ||
464 | } | ||
465 | |||
466 | static ssize_t | ||
467 | ds1511_nvram_write(struct kobject *kobj, struct bin_attribute *bin_attr, | ||
468 | char *buf, loff_t pos, size_t size) | ||
469 | { | ||
470 | ssize_t count; | ||
471 | |||
472 | /* | ||
473 | * if count is more than one, turn on "burst" mode | ||
474 | * turn it off when you're done | ||
475 | */ | ||
476 | if (size > 1) { | ||
477 | rtc_write((rtc_read(RTC_CMD) | DS1511_BME), RTC_CMD); | ||
478 | } | ||
479 | if (pos > DS1511_RAM_MAX) { | ||
480 | pos = DS1511_RAM_MAX; | ||
481 | } | ||
482 | if (size + pos > DS1511_RAM_MAX + 1) { | ||
483 | size = DS1511_RAM_MAX - pos + 1; | ||
484 | } | ||
485 | rtc_write(pos, DS1511_RAMADDR_LSB); | ||
486 | for (count = 0; size > 0; count++, size--) { | ||
487 | rtc_write(*buf++, DS1511_RAMDATA); | ||
488 | } | ||
489 | if (count > 1) { | ||
490 | rtc_write((rtc_read(RTC_CMD) & ~DS1511_BME), RTC_CMD); | ||
491 | } | ||
492 | return count; | ||
493 | } | ||
494 | |||
495 | static struct bin_attribute ds1511_nvram_attr = { | ||
496 | .attr = { | ||
497 | .name = "nvram", | ||
498 | .mode = S_IRUGO | S_IWUGO, | ||
499 | .owner = THIS_MODULE, | ||
500 | }, | ||
501 | .size = DS1511_RAM_MAX, | ||
502 | .read = ds1511_nvram_read, | ||
503 | .write = ds1511_nvram_write, | ||
504 | }; | ||
505 | |||
506 | static int __devinit | ||
507 | ds1511_rtc_probe(struct platform_device *pdev) | ||
508 | { | ||
509 | struct rtc_device *rtc; | ||
510 | struct resource *res; | ||
511 | struct rtc_plat_data *pdata = NULL; | ||
512 | int ret = 0; | ||
513 | |||
514 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
515 | if (!res) { | ||
516 | return -ENODEV; | ||
517 | } | ||
518 | pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); | ||
519 | if (!pdata) { | ||
520 | return -ENOMEM; | ||
521 | } | ||
522 | pdata->irq = -1; | ||
523 | pdata->size = res->end - res->start + 1; | ||
524 | if (!request_mem_region(res->start, pdata->size, pdev->name)) { | ||
525 | ret = -EBUSY; | ||
526 | goto out; | ||
527 | } | ||
528 | pdata->baseaddr = res->start; | ||
529 | pdata->size = pdata->size; | ||
530 | ds1511_base = ioremap(pdata->baseaddr, pdata->size); | ||
531 | if (!ds1511_base) { | ||
532 | ret = -ENOMEM; | ||
533 | goto out; | ||
534 | } | ||
535 | pdata->ioaddr = ds1511_base; | ||
536 | pdata->irq = platform_get_irq(pdev, 0); | ||
537 | |||
538 | /* | ||
539 | * turn on the clock and the crystal, etc. | ||
540 | */ | ||
541 | rtc_write(0, RTC_CMD); | ||
542 | rtc_write(0, RTC_CMD1); | ||
543 | /* | ||
544 | * clear the wdog counter | ||
545 | */ | ||
546 | rtc_write(0, DS1511_WD_MSEC); | ||
547 | rtc_write(0, DS1511_WD_SEC); | ||
548 | /* | ||
549 | * start the clock | ||
550 | */ | ||
551 | rtc_enable_update(); | ||
552 | |||
553 | /* | ||
554 | * check for a dying bat-tree | ||
555 | */ | ||
556 | if (rtc_read(RTC_CMD1) & DS1511_BLF1) { | ||
557 | dev_warn(&pdev->dev, "voltage-low detected.\n"); | ||
558 | } | ||
559 | |||
560 | /* | ||
561 | * if the platform has an interrupt in mind for this device, | ||
562 | * then by all means, set it | ||
563 | */ | ||
564 | if (pdata->irq >= 0) { | ||
565 | rtc_read(RTC_CMD1); | ||
566 | if (request_irq(pdata->irq, ds1511_interrupt, | ||
567 | IRQF_DISABLED | IRQF_SHARED, pdev->name, pdev) < 0) { | ||
568 | |||
569 | dev_warn(&pdev->dev, "interrupt not available.\n"); | ||
570 | pdata->irq = -1; | ||
571 | } | ||
572 | } | ||
573 | |||
574 | rtc = rtc_device_register(pdev->name, &pdev->dev, &ds1511_rtc_ops, | ||
575 | THIS_MODULE); | ||
576 | if (IS_ERR(rtc)) { | ||
577 | ret = PTR_ERR(rtc); | ||
578 | goto out; | ||
579 | } | ||
580 | pdata->rtc = rtc; | ||
581 | platform_set_drvdata(pdev, pdata); | ||
582 | ret = sysfs_create_bin_file(&pdev->dev.kobj, &ds1511_nvram_attr); | ||
583 | if (ret) { | ||
584 | goto out; | ||
585 | } | ||
586 | return 0; | ||
587 | out: | ||
588 | if (pdata->rtc) { | ||
589 | rtc_device_unregister(pdata->rtc); | ||
590 | } | ||
591 | if (pdata->irq >= 0) { | ||
592 | free_irq(pdata->irq, pdev); | ||
593 | } | ||
594 | if (ds1511_base) { | ||
595 | iounmap(ds1511_base); | ||
596 | ds1511_base = NULL; | ||
597 | } | ||
598 | if (pdata->baseaddr) { | ||
599 | release_mem_region(pdata->baseaddr, pdata->size); | ||
600 | } | ||
601 | |||
602 | kfree(pdata); | ||
603 | return ret; | ||
604 | } | ||
605 | |||
606 | static int __devexit | ||
607 | ds1511_rtc_remove(struct platform_device *pdev) | ||
608 | { | ||
609 | struct rtc_plat_data *pdata = platform_get_drvdata(pdev); | ||
610 | |||
611 | sysfs_remove_bin_file(&pdev->dev.kobj, &ds1511_nvram_attr); | ||
612 | rtc_device_unregister(pdata->rtc); | ||
613 | pdata->rtc = NULL; | ||
614 | if (pdata->irq >= 0) { | ||
615 | /* | ||
616 | * disable the alarm interrupt | ||
617 | */ | ||
618 | rtc_write(rtc_read(RTC_CMD) & ~RTC_TIE, RTC_CMD); | ||
619 | rtc_read(RTC_CMD1); | ||
620 | free_irq(pdata->irq, pdev); | ||
621 | } | ||
622 | iounmap(pdata->ioaddr); | ||
623 | ds1511_base = NULL; | ||
624 | release_mem_region(pdata->baseaddr, pdata->size); | ||
625 | kfree(pdata); | ||
626 | return 0; | ||
627 | } | ||
628 | |||
629 | static struct platform_driver ds1511_rtc_driver = { | ||
630 | .probe = ds1511_rtc_probe, | ||
631 | .remove = __devexit_p(ds1511_rtc_remove), | ||
632 | .driver = { | ||
633 | .name = "ds1511", | ||
634 | .owner = THIS_MODULE, | ||
635 | }, | ||
636 | }; | ||
637 | |||
638 | static int __init | ||
639 | ds1511_rtc_init(void) | ||
640 | { | ||
641 | return platform_driver_register(&ds1511_rtc_driver); | ||
642 | } | ||
643 | |||
644 | static void __exit | ||
645 | ds1511_rtc_exit(void) | ||
646 | { | ||
647 | return platform_driver_unregister(&ds1511_rtc_driver); | ||
648 | } | ||
649 | |||
650 | module_init(ds1511_rtc_init); | ||
651 | module_exit(ds1511_rtc_exit); | ||
652 | |||
653 | MODULE_AUTHOR("Andrew Sharp <andy.sharp@onstor.com>"); | ||
654 | MODULE_DESCRIPTION("Dallas DS1511 RTC driver"); | ||
655 | MODULE_LICENSE("GPL"); | ||
656 | MODULE_VERSION(DRV_VERSION); | ||
diff --git a/drivers/rtc/rtc-pcf8583.c b/drivers/rtc/rtc-pcf8583.c index c973ba94c422..8b3997007506 100644 --- a/drivers/rtc/rtc-pcf8583.c +++ b/drivers/rtc/rtc-pcf8583.c | |||
@@ -163,27 +163,17 @@ static int pcf8583_read_mem(struct i2c_client *client, struct rtc_mem *mem) | |||
163 | 163 | ||
164 | static int pcf8583_write_mem(struct i2c_client *client, struct rtc_mem *mem) | 164 | static int pcf8583_write_mem(struct i2c_client *client, struct rtc_mem *mem) |
165 | { | 165 | { |
166 | unsigned char addr[1]; | 166 | unsigned char buf[9]; |
167 | struct i2c_msg msgs[2] = { | 167 | int ret; |
168 | { | ||
169 | .addr = client->addr, | ||
170 | .flags = 0, | ||
171 | .len = 1, | ||
172 | .buf = addr, | ||
173 | }, { | ||
174 | .addr = client->addr, | ||
175 | .flags = I2C_M_NOSTART, | ||
176 | .len = mem->nr, | ||
177 | .buf = mem->data, | ||
178 | } | ||
179 | }; | ||
180 | 168 | ||
181 | if (mem->loc < 8) | 169 | if (mem->loc < 8 || mem->nr > 8) |
182 | return -EINVAL; | 170 | return -EINVAL; |
183 | 171 | ||
184 | addr[0] = mem->loc; | 172 | buf[0] = mem->loc; |
173 | memcpy(buf + 1, mem->data, mem->nr); | ||
185 | 174 | ||
186 | return i2c_transfer(client->adapter, msgs, 2) == 2 ? 0 : -EIO; | 175 | ret = i2c_master_send(client, buf, mem->nr + 1); |
176 | return ret == mem->nr + 1 ? 0 : -EIO; | ||
187 | } | 177 | } |
188 | 178 | ||
189 | static int pcf8583_rtc_read_time(struct device *dev, struct rtc_time *tm) | 179 | static int pcf8583_rtc_read_time(struct device *dev, struct rtc_time *tm) |
diff --git a/drivers/rtc/rtc-r9701.c b/drivers/rtc/rtc-r9701.c new file mode 100644 index 000000000000..a64626a82d0b --- /dev/null +++ b/drivers/rtc/rtc-r9701.c | |||
@@ -0,0 +1,178 @@ | |||
1 | /* | ||
2 | * Driver for Epson RTC-9701JE | ||
3 | * | ||
4 | * Copyright (C) 2008 Magnus Damm | ||
5 | * | ||
6 | * Based on rtc-max6902.c | ||
7 | * | ||
8 | * Copyright (C) 2006 8D Technologies inc. | ||
9 | * Copyright (C) 2004 Compulab Ltd. | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License version 2 as | ||
13 | * published by the Free Software Foundation. | ||
14 | */ | ||
15 | |||
16 | #include <linux/module.h> | ||
17 | #include <linux/version.h> | ||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/platform_device.h> | ||
20 | #include <linux/device.h> | ||
21 | #include <linux/init.h> | ||
22 | #include <linux/rtc.h> | ||
23 | #include <linux/spi/spi.h> | ||
24 | #include <linux/bcd.h> | ||
25 | #include <linux/delay.h> | ||
26 | #include <linux/bitops.h> | ||
27 | |||
28 | #define RSECCNT 0x00 /* Second Counter */ | ||
29 | #define RMINCNT 0x01 /* Minute Counter */ | ||
30 | #define RHRCNT 0x02 /* Hour Counter */ | ||
31 | #define RWKCNT 0x03 /* Week Counter */ | ||
32 | #define RDAYCNT 0x04 /* Day Counter */ | ||
33 | #define RMONCNT 0x05 /* Month Counter */ | ||
34 | #define RYRCNT 0x06 /* Year Counter */ | ||
35 | #define R100CNT 0x07 /* Y100 Counter */ | ||
36 | #define RMINAR 0x08 /* Minute Alarm */ | ||
37 | #define RHRAR 0x09 /* Hour Alarm */ | ||
38 | #define RWKAR 0x0a /* Week/Day Alarm */ | ||
39 | #define RTIMCNT 0x0c /* Interval Timer */ | ||
40 | #define REXT 0x0d /* Extension Register */ | ||
41 | #define RFLAG 0x0e /* RTC Flag Register */ | ||
42 | #define RCR 0x0f /* RTC Control Register */ | ||
43 | |||
44 | static int write_reg(struct device *dev, int address, unsigned char data) | ||
45 | { | ||
46 | struct spi_device *spi = to_spi_device(dev); | ||
47 | unsigned char buf[2]; | ||
48 | |||
49 | buf[0] = address & 0x7f; | ||
50 | buf[1] = data; | ||
51 | |||
52 | return spi_write(spi, buf, ARRAY_SIZE(buf)); | ||
53 | } | ||
54 | |||
55 | static int read_regs(struct device *dev, unsigned char *regs, int no_regs) | ||
56 | { | ||
57 | struct spi_device *spi = to_spi_device(dev); | ||
58 | u8 txbuf[1], rxbuf[1]; | ||
59 | int k, ret; | ||
60 | |||
61 | ret = 0; | ||
62 | |||
63 | for (k = 0; ret == 0 && k < no_regs; k++) { | ||
64 | txbuf[0] = 0x80 | regs[k]; | ||
65 | ret = spi_write_then_read(spi, txbuf, 1, rxbuf, 1); | ||
66 | regs[k] = rxbuf[0]; | ||
67 | } | ||
68 | |||
69 | return ret; | ||
70 | } | ||
71 | |||
72 | static int r9701_get_datetime(struct device *dev, struct rtc_time *dt) | ||
73 | { | ||
74 | unsigned long time; | ||
75 | int ret; | ||
76 | unsigned char buf[] = { RSECCNT, RMINCNT, RHRCNT, | ||
77 | RDAYCNT, RMONCNT, RYRCNT }; | ||
78 | |||
79 | ret = read_regs(dev, buf, ARRAY_SIZE(buf)); | ||
80 | if (ret) | ||
81 | return ret; | ||
82 | |||
83 | memset(dt, 0, sizeof(*dt)); | ||
84 | |||
85 | dt->tm_sec = BCD2BIN(buf[0]); /* RSECCNT */ | ||
86 | dt->tm_min = BCD2BIN(buf[1]); /* RMINCNT */ | ||
87 | dt->tm_hour = BCD2BIN(buf[2]); /* RHRCNT */ | ||
88 | |||
89 | dt->tm_mday = BCD2BIN(buf[3]); /* RDAYCNT */ | ||
90 | dt->tm_mon = BCD2BIN(buf[4]) - 1; /* RMONCNT */ | ||
91 | dt->tm_year = BCD2BIN(buf[5]) + 100; /* RYRCNT */ | ||
92 | |||
93 | /* the rtc device may contain illegal values on power up | ||
94 | * according to the data sheet. make sure they are valid. | ||
95 | */ | ||
96 | |||
97 | return rtc_valid_tm(dt); | ||
98 | } | ||
99 | |||
100 | static int r9701_set_datetime(struct device *dev, struct rtc_time *dt) | ||
101 | { | ||
102 | int ret, year; | ||
103 | |||
104 | year = dt->tm_year + 1900; | ||
105 | if (year >= 2100 || year < 2000) | ||
106 | return -EINVAL; | ||
107 | |||
108 | ret = write_reg(dev, RHRCNT, BIN2BCD(dt->tm_hour)); | ||
109 | ret = ret ? ret : write_reg(dev, RMINCNT, BIN2BCD(dt->tm_min)); | ||
110 | ret = ret ? ret : write_reg(dev, RSECCNT, BIN2BCD(dt->tm_sec)); | ||
111 | ret = ret ? ret : write_reg(dev, RDAYCNT, BIN2BCD(dt->tm_mday)); | ||
112 | ret = ret ? ret : write_reg(dev, RMONCNT, BIN2BCD(dt->tm_mon + 1)); | ||
113 | ret = ret ? ret : write_reg(dev, RYRCNT, BIN2BCD(dt->tm_year - 100)); | ||
114 | ret = ret ? ret : write_reg(dev, RWKCNT, 1 << dt->tm_wday); | ||
115 | |||
116 | return ret; | ||
117 | } | ||
118 | |||
119 | static const struct rtc_class_ops r9701_rtc_ops = { | ||
120 | .read_time = r9701_get_datetime, | ||
121 | .set_time = r9701_set_datetime, | ||
122 | }; | ||
123 | |||
124 | static int __devinit r9701_probe(struct spi_device *spi) | ||
125 | { | ||
126 | struct rtc_device *rtc; | ||
127 | unsigned char tmp; | ||
128 | int res; | ||
129 | |||
130 | rtc = rtc_device_register("r9701", | ||
131 | &spi->dev, &r9701_rtc_ops, THIS_MODULE); | ||
132 | if (IS_ERR(rtc)) | ||
133 | return PTR_ERR(rtc); | ||
134 | |||
135 | dev_set_drvdata(&spi->dev, rtc); | ||
136 | |||
137 | tmp = R100CNT; | ||
138 | res = read_regs(&spi->dev, &tmp, 1); | ||
139 | if (res || tmp != 0x20) { | ||
140 | rtc_device_unregister(rtc); | ||
141 | return res; | ||
142 | } | ||
143 | |||
144 | return 0; | ||
145 | } | ||
146 | |||
147 | static int __devexit r9701_remove(struct spi_device *spi) | ||
148 | { | ||
149 | struct rtc_device *rtc = dev_get_drvdata(&spi->dev); | ||
150 | |||
151 | rtc_device_unregister(rtc); | ||
152 | return 0; | ||
153 | } | ||
154 | |||
155 | static struct spi_driver r9701_driver = { | ||
156 | .driver = { | ||
157 | .name = "rtc-r9701", | ||
158 | .owner = THIS_MODULE, | ||
159 | }, | ||
160 | .probe = r9701_probe, | ||
161 | .remove = __devexit_p(r9701_remove), | ||
162 | }; | ||
163 | |||
164 | static __init int r9701_init(void) | ||
165 | { | ||
166 | return spi_register_driver(&r9701_driver); | ||
167 | } | ||
168 | module_init(r9701_init); | ||
169 | |||
170 | static __exit void r9701_exit(void) | ||
171 | { | ||
172 | spi_unregister_driver(&r9701_driver); | ||
173 | } | ||
174 | module_exit(r9701_exit); | ||
175 | |||
176 | MODULE_DESCRIPTION("r9701 spi RTC driver"); | ||
177 | MODULE_AUTHOR("Magnus Damm <damm@opensource.se>"); | ||
178 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c index e2041b4d0c85..86766f1f2496 100644 --- a/drivers/rtc/rtc-s3c.c +++ b/drivers/rtc/rtc-s3c.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/rtc.h> | 20 | #include <linux/rtc.h> |
21 | #include <linux/bcd.h> | 21 | #include <linux/bcd.h> |
22 | #include <linux/clk.h> | 22 | #include <linux/clk.h> |
23 | #include <linux/log2.h> | ||
23 | 24 | ||
24 | #include <asm/hardware.h> | 25 | #include <asm/hardware.h> |
25 | #include <asm/uaccess.h> | 26 | #include <asm/uaccess.h> |
@@ -309,9 +310,7 @@ static int s3c_rtc_ioctl(struct device *dev, | |||
309 | break; | 310 | break; |
310 | 311 | ||
311 | case RTC_IRQP_SET: | 312 | case RTC_IRQP_SET: |
312 | /* check for power of 2 */ | 313 | if (!is_power_of_2(arg)) { |
313 | |||
314 | if ((arg & (arg-1)) != 0 || arg < 1) { | ||
315 | ret = -EINVAL; | 314 | ret = -EINVAL; |
316 | goto exit; | 315 | goto exit; |
317 | } | 316 | } |
diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c index 2eb38520f0c8..ee253cc45de1 100644 --- a/drivers/rtc/rtc-sa1100.c +++ b/drivers/rtc/rtc-sa1100.c | |||
@@ -357,23 +357,15 @@ static int sa1100_rtc_remove(struct platform_device *pdev) | |||
357 | #ifdef CONFIG_PM | 357 | #ifdef CONFIG_PM |
358 | static int sa1100_rtc_suspend(struct platform_device *pdev, pm_message_t state) | 358 | static int sa1100_rtc_suspend(struct platform_device *pdev, pm_message_t state) |
359 | { | 359 | { |
360 | if (pdev->dev.power.power_state.event != state.event) { | 360 | if (device_may_wakeup(&pdev->dev)) |
361 | if (state.event == PM_EVENT_SUSPEND && | 361 | enable_irq_wake(IRQ_RTCAlrm); |
362 | device_may_wakeup(&pdev->dev)) | ||
363 | enable_irq_wake(IRQ_RTCAlrm); | ||
364 | |||
365 | pdev->dev.power.power_state = state; | ||
366 | } | ||
367 | return 0; | 362 | return 0; |
368 | } | 363 | } |
369 | 364 | ||
370 | static int sa1100_rtc_resume(struct platform_device *pdev) | 365 | static int sa1100_rtc_resume(struct platform_device *pdev) |
371 | { | 366 | { |
372 | if (pdev->dev.power.power_state.event != PM_EVENT_ON) { | 367 | if (device_may_wakeup(&pdev->dev)) |
373 | if (device_may_wakeup(&pdev->dev)) | 368 | disable_irq_wake(IRQ_RTCAlrm); |
374 | disable_irq_wake(IRQ_RTCAlrm); | ||
375 | pdev->dev.power.power_state = PMSG_ON; | ||
376 | } | ||
377 | return 0; | 369 | return 0; |
378 | } | 370 | } |
379 | #else | 371 | #else |
diff --git a/drivers/rtc/rtc-sysfs.c b/drivers/rtc/rtc-sysfs.c index 2ae0e8304d3a..4d27ccc4fc06 100644 --- a/drivers/rtc/rtc-sysfs.c +++ b/drivers/rtc/rtc-sysfs.c | |||
@@ -17,6 +17,13 @@ | |||
17 | 17 | ||
18 | /* device attributes */ | 18 | /* device attributes */ |
19 | 19 | ||
20 | /* | ||
21 | * NOTE: RTC times displayed in sysfs use the RTC's timezone. That's | ||
22 | * ideally UTC. However, PCs that also boot to MS-Windows normally use | ||
23 | * the local time and change to match daylight savings time. That affects | ||
24 | * attributes including date, time, since_epoch, and wakealarm. | ||
25 | */ | ||
26 | |||
20 | static ssize_t | 27 | static ssize_t |
21 | rtc_sysfs_show_name(struct device *dev, struct device_attribute *attr, | 28 | rtc_sysfs_show_name(struct device *dev, struct device_attribute *attr, |
22 | char *buf) | 29 | char *buf) |
@@ -113,13 +120,13 @@ rtc_sysfs_show_wakealarm(struct device *dev, struct device_attribute *attr, | |||
113 | unsigned long alarm; | 120 | unsigned long alarm; |
114 | struct rtc_wkalrm alm; | 121 | struct rtc_wkalrm alm; |
115 | 122 | ||
116 | /* Don't show disabled alarms; but the RTC could leave the | 123 | /* Don't show disabled alarms. For uniformity, RTC alarms are |
117 | * alarm enabled after it's already triggered. Alarms are | 124 | * conceptually one-shot, even though some common RTCs (on PCs) |
118 | * conceptually one-shot, even though some common hardware | 125 | * don't actually work that way. |
119 | * (PCs) doesn't actually work that way. | ||
120 | * | 126 | * |
121 | * REVISIT maybe we should require RTC implementations to | 127 | * NOTE: RTC implementations where the alarm doesn't match an |
122 | * disable the RTC alarm after it triggers, for uniformity. | 128 | * exact YYYY-MM-DD HH:MM[:SS] date *must* disable their RTC |
129 | * alarms after they trigger, to ensure one-shot semantics. | ||
123 | */ | 130 | */ |
124 | retval = rtc_read_alarm(to_rtc_device(dev), &alm); | 131 | retval = rtc_read_alarm(to_rtc_device(dev), &alm); |
125 | if (retval == 0 && alm.enabled) { | 132 | if (retval == 0 && alm.enabled) { |
diff --git a/drivers/s390/sysinfo.c b/drivers/s390/sysinfo.c index 19343f9675c3..291ff6235fe2 100644 --- a/drivers/s390/sysinfo.c +++ b/drivers/s390/sysinfo.c | |||
@@ -422,7 +422,7 @@ void s390_adjust_jiffies(void) | |||
422 | /* | 422 | /* |
423 | * calibrate the delay loop | 423 | * calibrate the delay loop |
424 | */ | 424 | */ |
425 | void __init calibrate_delay(void) | 425 | void __cpuinit calibrate_delay(void) |
426 | { | 426 | { |
427 | s390_adjust_jiffies(); | 427 | s390_adjust_jiffies(); |
428 | /* Print the good old Bogomips line .. */ | 428 | /* Print the good old Bogomips line .. */ |
diff --git a/drivers/scsi/a2091.c b/drivers/scsi/a2091.c index 23f27c9c9895..5ac3a3e8dfaf 100644 --- a/drivers/scsi/a2091.c +++ b/drivers/scsi/a2091.c | |||
@@ -46,8 +46,7 @@ static int dma_setup(struct scsi_cmnd *cmd, int dir_in) | |||
46 | struct Scsi_Host *instance = cmd->device->host; | 46 | struct Scsi_Host *instance = cmd->device->host; |
47 | 47 | ||
48 | /* don't allow DMA if the physical address is bad */ | 48 | /* don't allow DMA if the physical address is bad */ |
49 | if (addr & A2091_XFER_MASK || | 49 | if (addr & A2091_XFER_MASK) |
50 | (!dir_in && mm_end_of_chunk (addr, cmd->SCp.this_residual))) | ||
51 | { | 50 | { |
52 | HDATA(instance)->dma_bounce_len = (cmd->SCp.this_residual + 511) | 51 | HDATA(instance)->dma_bounce_len = (cmd->SCp.this_residual + 511) |
53 | & ~0x1ff; | 52 | & ~0x1ff; |
diff --git a/drivers/scsi/a3000.c b/drivers/scsi/a3000.c index d7255c8bf281..3aeec963940b 100644 --- a/drivers/scsi/a3000.c +++ b/drivers/scsi/a3000.c | |||
@@ -54,8 +54,7 @@ static int dma_setup(struct scsi_cmnd *cmd, int dir_in) | |||
54 | * end of a physical memory chunk, then allocate a bounce | 54 | * end of a physical memory chunk, then allocate a bounce |
55 | * buffer | 55 | * buffer |
56 | */ | 56 | */ |
57 | if (addr & A3000_XFER_MASK || | 57 | if (addr & A3000_XFER_MASK) |
58 | (!dir_in && mm_end_of_chunk (addr, cmd->SCp.this_residual))) | ||
59 | { | 58 | { |
60 | HDATA(a3000_host)->dma_bounce_len = (cmd->SCp.this_residual + 511) | 59 | HDATA(a3000_host)->dma_bounce_len = (cmd->SCp.this_residual + 511) |
61 | & ~0x1ff; | 60 | & ~0x1ff; |
diff --git a/drivers/scsi/aic7xxx_old.c b/drivers/scsi/aic7xxx_old.c index 3bfd9296bbfa..93984c9dfe14 100644 --- a/drivers/scsi/aic7xxx_old.c +++ b/drivers/scsi/aic7xxx_old.c | |||
@@ -6472,7 +6472,7 @@ do_aic7xxx_isr(int irq, void *dev_id) | |||
6472 | unsigned long cpu_flags; | 6472 | unsigned long cpu_flags; |
6473 | struct aic7xxx_host *p; | 6473 | struct aic7xxx_host *p; |
6474 | 6474 | ||
6475 | p = (struct aic7xxx_host *)dev_id; | 6475 | p = dev_id; |
6476 | if(!p) | 6476 | if(!p) |
6477 | return IRQ_NONE; | 6477 | return IRQ_NONE; |
6478 | spin_lock_irqsave(p->host->host_lock, cpu_flags); | 6478 | spin_lock_irqsave(p->host->host_lock, cpu_flags); |
diff --git a/drivers/scsi/gvp11.c b/drivers/scsi/gvp11.c index 37741e9b5c3b..91f85226d08f 100644 --- a/drivers/scsi/gvp11.c +++ b/drivers/scsi/gvp11.c | |||
@@ -54,8 +54,7 @@ static int dma_setup(struct scsi_cmnd *cmd, int dir_in) | |||
54 | static int scsi_alloc_out_of_range = 0; | 54 | static int scsi_alloc_out_of_range = 0; |
55 | 55 | ||
56 | /* use bounce buffer if the physical address is bad */ | 56 | /* use bounce buffer if the physical address is bad */ |
57 | if (addr & HDATA(cmd->device->host)->dma_xfer_mask || | 57 | if (addr & HDATA(cmd->device->host)->dma_xfer_mask) |
58 | (!dir_in && mm_end_of_chunk (addr, cmd->SCp.this_residual))) | ||
59 | { | 58 | { |
60 | HDATA(cmd->device->host)->dma_bounce_len = (cmd->SCp.this_residual + 511) | 59 | HDATA(cmd->device->host)->dma_bounce_len = (cmd->SCp.this_residual + 511) |
61 | & ~0x1ff; | 60 | & ~0x1ff; |
diff --git a/drivers/scsi/ibmvscsi/ibmvstgt.c b/drivers/scsi/ibmvscsi/ibmvstgt.c index d63f11e95abf..bd62131b97a1 100644 --- a/drivers/scsi/ibmvscsi/ibmvstgt.c +++ b/drivers/scsi/ibmvscsi/ibmvstgt.c | |||
@@ -539,9 +539,9 @@ out: | |||
539 | srp_iu_put(iue); | 539 | srp_iu_put(iue); |
540 | } | 540 | } |
541 | 541 | ||
542 | static irqreturn_t ibmvstgt_interrupt(int irq, void *data) | 542 | static irqreturn_t ibmvstgt_interrupt(int dummy, void *data) |
543 | { | 543 | { |
544 | struct srp_target *target = (struct srp_target *) data; | 544 | struct srp_target *target = data; |
545 | struct vio_port *vport = target_to_port(target); | 545 | struct vio_port *vport = target_to_port(target); |
546 | 546 | ||
547 | vio_disable_interrupts(vport->dma_dev); | 547 | vio_disable_interrupts(vport->dma_dev); |
diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c index 672c759ac24d..77a62a1b12c3 100644 --- a/drivers/scsi/megaraid/megaraid_sas.c +++ b/drivers/scsi/megaraid/megaraid_sas.c | |||
@@ -31,7 +31,6 @@ | |||
31 | #include <linux/moduleparam.h> | 31 | #include <linux/moduleparam.h> |
32 | #include <linux/module.h> | 32 | #include <linux/module.h> |
33 | #include <linux/spinlock.h> | 33 | #include <linux/spinlock.h> |
34 | #include <linux/mutex.h> | ||
35 | #include <linux/interrupt.h> | 34 | #include <linux/interrupt.h> |
36 | #include <linux/delay.h> | 35 | #include <linux/delay.h> |
37 | #include <linux/uio.h> | 36 | #include <linux/uio.h> |
diff --git a/drivers/serial/68328serial.c b/drivers/serial/68328serial.c index 0d99120ab5a2..2b8a410e0959 100644 --- a/drivers/serial/68328serial.c +++ b/drivers/serial/68328serial.c | |||
@@ -84,9 +84,6 @@ extern wait_queue_head_t keypress_wait; | |||
84 | 84 | ||
85 | struct tty_driver *serial_driver; | 85 | struct tty_driver *serial_driver; |
86 | 86 | ||
87 | /* serial subtype definitions */ | ||
88 | #define SERIAL_TYPE_NORMAL 1 | ||
89 | |||
90 | /* number of characters left in xmit buffer before we ask for more */ | 87 | /* number of characters left in xmit buffer before we ask for more */ |
91 | #define WAKEUP_CHARS 256 | 88 | #define WAKEUP_CHARS 256 |
92 | 89 | ||
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index ddfb1eab7363..84a054d7e986 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig | |||
@@ -465,20 +465,24 @@ config SERIAL_DZ | |||
465 | bool "DECstation DZ serial driver" | 465 | bool "DECstation DZ serial driver" |
466 | depends on MACH_DECSTATION && 32BIT | 466 | depends on MACH_DECSTATION && 32BIT |
467 | select SERIAL_CORE | 467 | select SERIAL_CORE |
468 | help | 468 | default y |
469 | DZ11-family serial controllers for VAXstations, including the | 469 | ---help--- |
470 | DC7085, M7814, and M7819. | 470 | DZ11-family serial controllers for DECstations and VAXstations, |
471 | including the DC7085, M7814, and M7819. | ||
471 | 472 | ||
472 | config SERIAL_DZ_CONSOLE | 473 | config SERIAL_DZ_CONSOLE |
473 | bool "Support console on DECstation DZ serial driver" | 474 | bool "Support console on DECstation DZ serial driver" |
474 | depends on SERIAL_DZ=y | 475 | depends on SERIAL_DZ=y |
475 | select SERIAL_CORE_CONSOLE | 476 | select SERIAL_CORE_CONSOLE |
476 | help | 477 | default y |
478 | ---help--- | ||
477 | If you say Y here, it will be possible to use a serial port as the | 479 | If you say Y here, it will be possible to use a serial port as the |
478 | system console (the system console is the device which receives all | 480 | system console (the system console is the device which receives all |
479 | kernel messages and warnings and which allows logins in single user | 481 | kernel messages and warnings and which allows logins in single user |
480 | mode). Note that the firmware uses ttyS0 as the serial console on | 482 | mode). |
481 | the Maxine and ttyS2 on the others. | 483 | |
484 | Note that the firmware uses ttyS3 as the serial console on | ||
485 | DECstations that use this driver. | ||
482 | 486 | ||
483 | If unsure, say Y. | 487 | If unsure, say Y. |
484 | 488 | ||
@@ -877,15 +881,15 @@ config SERIAL_SUNHV | |||
877 | systems. Say Y if you want to be able to use this device. | 881 | systems. Say Y if you want to be able to use this device. |
878 | 882 | ||
879 | config SERIAL_IP22_ZILOG | 883 | config SERIAL_IP22_ZILOG |
880 | tristate "IP22 Zilog8530 serial support" | 884 | tristate "SGI Zilog8530 serial support" |
881 | depends on SGI_IP22 | 885 | depends on SGI_HAS_ZILOG |
882 | select SERIAL_CORE | 886 | select SERIAL_CORE |
883 | help | 887 | help |
884 | This driver supports the Zilog8530 serial ports found on SGI IP22 | 888 | This driver supports the Zilog8530 serial ports found on SGI |
885 | systems. Say Y or M if you want to be able to these serial ports. | 889 | systems. Say Y or M if you want to be able to these serial ports. |
886 | 890 | ||
887 | config SERIAL_IP22_ZILOG_CONSOLE | 891 | config SERIAL_IP22_ZILOG_CONSOLE |
888 | bool "Console on IP22 Zilog8530 serial port" | 892 | bool "Console on SGI Zilog8530 serial port" |
889 | depends on SERIAL_IP22_ZILOG=y | 893 | depends on SERIAL_IP22_ZILOG=y |
890 | select SERIAL_CORE_CONSOLE | 894 | select SERIAL_CORE_CONSOLE |
891 | 895 | ||
@@ -1318,4 +1322,19 @@ config SERIAL_QE | |||
1318 | This driver supports the QE serial ports on Freescale embedded | 1322 | This driver supports the QE serial ports on Freescale embedded |
1319 | PowerPC that contain a QUICC Engine. | 1323 | PowerPC that contain a QUICC Engine. |
1320 | 1324 | ||
1325 | config SERIAL_SC26XX | ||
1326 | tristate "SC2681/SC2692 serial port support" | ||
1327 | depends on SNI_RM | ||
1328 | select SERIAL_CORE | ||
1329 | help | ||
1330 | This is a driver for the onboard serial ports of | ||
1331 | older RM400 machines. | ||
1332 | |||
1333 | config SERIAL_SC26XX_CONSOLE | ||
1334 | bool "Console on SC2681/SC2692 serial port" | ||
1335 | depends on SERIAL_SC26XX | ||
1336 | select SERIAL_CORE_CONSOLE | ||
1337 | help | ||
1338 | Support for Console on SC2681/SC2692 serial ports. | ||
1339 | |||
1321 | endmenu | 1340 | endmenu |
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index 2dd41b4cc8db..640cfe44a56d 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile | |||
@@ -55,6 +55,7 @@ obj-$(CONFIG_SERIAL_M32R_SIO) += m32r_sio.o | |||
55 | obj-$(CONFIG_SERIAL_MPSC) += mpsc.o | 55 | obj-$(CONFIG_SERIAL_MPSC) += mpsc.o |
56 | obj-$(CONFIG_SERIAL_SB1250_DUART) += sb1250-duart.o | 56 | obj-$(CONFIG_SERIAL_SB1250_DUART) += sb1250-duart.o |
57 | obj-$(CONFIG_ETRAX_SERIAL) += crisv10.o | 57 | obj-$(CONFIG_ETRAX_SERIAL) += crisv10.o |
58 | obj-$(CONFIG_SERIAL_SC26XX) += sc26xx.o | ||
58 | obj-$(CONFIG_SERIAL_JSM) += jsm/ | 59 | obj-$(CONFIG_SERIAL_JSM) += jsm/ |
59 | obj-$(CONFIG_SERIAL_TXX9) += serial_txx9.o | 60 | obj-$(CONFIG_SERIAL_TXX9) += serial_txx9.o |
60 | obj-$(CONFIG_SERIAL_VR41XX) += vr41xx_siu.o | 61 | obj-$(CONFIG_SERIAL_VR41XX) += vr41xx_siu.o |
diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c index b5e4478de0e3..236af9d33851 100644 --- a/drivers/serial/cpm_uart/cpm_uart_core.c +++ b/drivers/serial/cpm_uart/cpm_uart_core.c | |||
@@ -380,7 +380,7 @@ static void cpm_uart_int_rx(struct uart_port *port) | |||
380 | static irqreturn_t cpm_uart_int(int irq, void *data) | 380 | static irqreturn_t cpm_uart_int(int irq, void *data) |
381 | { | 381 | { |
382 | u8 events; | 382 | u8 events; |
383 | struct uart_port *port = (struct uart_port *)data; | 383 | struct uart_port *port = data; |
384 | struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port; | 384 | struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port; |
385 | smc_t __iomem *smcp = pinfo->smcp; | 385 | smc_t __iomem *smcp = pinfo->smcp; |
386 | scc_t __iomem *sccp = pinfo->sccp; | 386 | scc_t __iomem *sccp = pinfo->sccp; |
diff --git a/drivers/serial/crisv10.c b/drivers/serial/crisv10.c index a4e23cf47906..383c4e660cd5 100644 --- a/drivers/serial/crisv10.c +++ b/drivers/serial/crisv10.c | |||
@@ -68,11 +68,6 @@ static char *serial_version = "$Revision: 1.25 $"; | |||
68 | 68 | ||
69 | struct tty_driver *serial_driver; | 69 | struct tty_driver *serial_driver; |
70 | 70 | ||
71 | /* serial subtype definitions */ | ||
72 | #ifndef SERIAL_TYPE_NORMAL | ||
73 | #define SERIAL_TYPE_NORMAL 1 | ||
74 | #endif | ||
75 | |||
76 | /* number of characters left in xmit buffer before we ask for more */ | 71 | /* number of characters left in xmit buffer before we ask for more */ |
77 | #define WAKEUP_CHARS 256 | 72 | #define WAKEUP_CHARS 256 |
78 | 73 | ||
diff --git a/drivers/serial/dz.c b/drivers/serial/dz.c index d31721f2744d..116211fcd36f 100644 --- a/drivers/serial/dz.c +++ b/drivers/serial/dz.c | |||
@@ -6,7 +6,7 @@ | |||
6 | * | 6 | * |
7 | * Email: olivier.lebaillif@ifrsys.com | 7 | * Email: olivier.lebaillif@ifrsys.com |
8 | * | 8 | * |
9 | * Copyright (C) 2004, 2006 Maciej W. Rozycki | 9 | * Copyright (C) 2004, 2006, 2007 Maciej W. Rozycki |
10 | * | 10 | * |
11 | * [31-AUG-98] triemer | 11 | * [31-AUG-98] triemer |
12 | * Changed IRQ to use Harald's dec internals interrupts.h | 12 | * Changed IRQ to use Harald's dec internals interrupts.h |
@@ -32,38 +32,63 @@ | |||
32 | #define SUPPORT_SYSRQ | 32 | #define SUPPORT_SYSRQ |
33 | #endif | 33 | #endif |
34 | 34 | ||
35 | #include <linux/bitops.h> | ||
36 | #include <linux/compiler.h> | ||
37 | #include <linux/console.h> | ||
35 | #include <linux/delay.h> | 38 | #include <linux/delay.h> |
36 | #include <linux/module.h> | 39 | #include <linux/errno.h> |
37 | #include <linux/interrupt.h> | ||
38 | #include <linux/init.h> | 40 | #include <linux/init.h> |
39 | #include <linux/console.h> | 41 | #include <linux/interrupt.h> |
42 | #include <linux/ioport.h> | ||
43 | #include <linux/kernel.h> | ||
44 | #include <linux/major.h> | ||
45 | #include <linux/module.h> | ||
46 | #include <linux/serial.h> | ||
47 | #include <linux/serial_core.h> | ||
40 | #include <linux/sysrq.h> | 48 | #include <linux/sysrq.h> |
41 | #include <linux/tty.h> | 49 | #include <linux/tty.h> |
42 | #include <linux/tty_flip.h> | ||
43 | #include <linux/serial_core.h> | ||
44 | #include <linux/serial.h> | ||
45 | 50 | ||
51 | #include <asm/atomic.h> | ||
46 | #include <asm/bootinfo.h> | 52 | #include <asm/bootinfo.h> |
53 | #include <asm/io.h> | ||
54 | #include <asm/system.h> | ||
55 | |||
47 | #include <asm/dec/interrupts.h> | 56 | #include <asm/dec/interrupts.h> |
48 | #include <asm/dec/kn01.h> | 57 | #include <asm/dec/kn01.h> |
49 | #include <asm/dec/kn02.h> | 58 | #include <asm/dec/kn02.h> |
50 | #include <asm/dec/machtype.h> | 59 | #include <asm/dec/machtype.h> |
51 | #include <asm/dec/prom.h> | 60 | #include <asm/dec/prom.h> |
52 | #include <asm/irq.h> | 61 | #include <asm/dec/system.h> |
53 | #include <asm/system.h> | ||
54 | #include <asm/uaccess.h> | ||
55 | 62 | ||
56 | #include "dz.h" | 63 | #include "dz.h" |
57 | 64 | ||
58 | static char *dz_name = "DECstation DZ serial driver version "; | 65 | |
59 | static char *dz_version = "1.03"; | 66 | MODULE_DESCRIPTION("DECstation DZ serial driver"); |
67 | MODULE_LICENSE("GPL"); | ||
68 | |||
69 | |||
70 | static char dz_name[] __initdata = "DECstation DZ serial driver version "; | ||
71 | static char dz_version[] __initdata = "1.04"; | ||
60 | 72 | ||
61 | struct dz_port { | 73 | struct dz_port { |
74 | struct dz_mux *mux; | ||
62 | struct uart_port port; | 75 | struct uart_port port; |
63 | unsigned int cflag; | 76 | unsigned int cflag; |
64 | }; | 77 | }; |
65 | 78 | ||
66 | static struct dz_port dz_ports[DZ_NB_PORT]; | 79 | struct dz_mux { |
80 | struct dz_port dport[DZ_NB_PORT]; | ||
81 | atomic_t map_guard; | ||
82 | atomic_t irq_guard; | ||
83 | int initialised; | ||
84 | }; | ||
85 | |||
86 | static struct dz_mux dz_mux; | ||
87 | |||
88 | static inline struct dz_port *to_dport(struct uart_port *uport) | ||
89 | { | ||
90 | return container_of(uport, struct dz_port, port); | ||
91 | } | ||
67 | 92 | ||
68 | /* | 93 | /* |
69 | * ------------------------------------------------------------ | 94 | * ------------------------------------------------------------ |
@@ -74,21 +99,18 @@ static struct dz_port dz_ports[DZ_NB_PORT]; | |||
74 | * ------------------------------------------------------------ | 99 | * ------------------------------------------------------------ |
75 | */ | 100 | */ |
76 | 101 | ||
77 | static inline unsigned short dz_in(struct dz_port *dport, unsigned offset) | 102 | static u16 dz_in(struct dz_port *dport, unsigned offset) |
78 | { | 103 | { |
79 | volatile unsigned short *addr = | 104 | void __iomem *addr = dport->port.membase + offset; |
80 | (volatile unsigned short *) (dport->port.membase + offset); | ||
81 | 105 | ||
82 | return *addr; | 106 | return readw(addr); |
83 | } | 107 | } |
84 | 108 | ||
85 | static inline void dz_out(struct dz_port *dport, unsigned offset, | 109 | static void dz_out(struct dz_port *dport, unsigned offset, u16 value) |
86 | unsigned short value) | ||
87 | { | 110 | { |
88 | volatile unsigned short *addr = | 111 | void __iomem *addr = dport->port.membase + offset; |
89 | (volatile unsigned short *) (dport->port.membase + offset); | ||
90 | 112 | ||
91 | *addr = value; | 113 | writew(value, addr); |
92 | } | 114 | } |
93 | 115 | ||
94 | /* | 116 | /* |
@@ -103,42 +125,33 @@ static inline void dz_out(struct dz_port *dport, unsigned offset, | |||
103 | 125 | ||
104 | static void dz_stop_tx(struct uart_port *uport) | 126 | static void dz_stop_tx(struct uart_port *uport) |
105 | { | 127 | { |
106 | struct dz_port *dport = (struct dz_port *)uport; | 128 | struct dz_port *dport = to_dport(uport); |
107 | unsigned short tmp, mask = 1 << dport->port.line; | 129 | u16 tmp, mask = 1 << dport->port.line; |
108 | unsigned long flags; | ||
109 | 130 | ||
110 | spin_lock_irqsave(&dport->port.lock, flags); | ||
111 | tmp = dz_in(dport, DZ_TCR); /* read the TX flag */ | 131 | tmp = dz_in(dport, DZ_TCR); /* read the TX flag */ |
112 | tmp &= ~mask; /* clear the TX flag */ | 132 | tmp &= ~mask; /* clear the TX flag */ |
113 | dz_out(dport, DZ_TCR, tmp); | 133 | dz_out(dport, DZ_TCR, tmp); |
114 | spin_unlock_irqrestore(&dport->port.lock, flags); | ||
115 | } | 134 | } |
116 | 135 | ||
117 | static void dz_start_tx(struct uart_port *uport) | 136 | static void dz_start_tx(struct uart_port *uport) |
118 | { | 137 | { |
119 | struct dz_port *dport = (struct dz_port *)uport; | 138 | struct dz_port *dport = to_dport(uport); |
120 | unsigned short tmp, mask = 1 << dport->port.line; | 139 | u16 tmp, mask = 1 << dport->port.line; |
121 | unsigned long flags; | ||
122 | 140 | ||
123 | spin_lock_irqsave(&dport->port.lock, flags); | ||
124 | tmp = dz_in(dport, DZ_TCR); /* read the TX flag */ | 141 | tmp = dz_in(dport, DZ_TCR); /* read the TX flag */ |
125 | tmp |= mask; /* set the TX flag */ | 142 | tmp |= mask; /* set the TX flag */ |
126 | dz_out(dport, DZ_TCR, tmp); | 143 | dz_out(dport, DZ_TCR, tmp); |
127 | spin_unlock_irqrestore(&dport->port.lock, flags); | ||
128 | } | 144 | } |
129 | 145 | ||
130 | static void dz_stop_rx(struct uart_port *uport) | 146 | static void dz_stop_rx(struct uart_port *uport) |
131 | { | 147 | { |
132 | struct dz_port *dport = (struct dz_port *)uport; | 148 | struct dz_port *dport = to_dport(uport); |
133 | unsigned long flags; | ||
134 | 149 | ||
135 | spin_lock_irqsave(&dport->port.lock, flags); | 150 | dport->cflag &= ~DZ_RXENAB; |
136 | dport->cflag &= ~DZ_CREAD; | 151 | dz_out(dport, DZ_LPR, dport->cflag); |
137 | dz_out(dport, DZ_LPR, dport->cflag | dport->port.line); | ||
138 | spin_unlock_irqrestore(&dport->port.lock, flags); | ||
139 | } | 152 | } |
140 | 153 | ||
141 | static void dz_enable_ms(struct uart_port *port) | 154 | static void dz_enable_ms(struct uart_port *uport) |
142 | { | 155 | { |
143 | /* nothing to do */ | 156 | /* nothing to do */ |
144 | } | 157 | } |
@@ -170,73 +183,73 @@ static void dz_enable_ms(struct uart_port *port) | |||
170 | * This routine deals with inputs from any lines. | 183 | * This routine deals with inputs from any lines. |
171 | * ------------------------------------------------------------ | 184 | * ------------------------------------------------------------ |
172 | */ | 185 | */ |
173 | static inline void dz_receive_chars(struct dz_port *dport_in) | 186 | static inline void dz_receive_chars(struct dz_mux *mux) |
174 | { | 187 | { |
175 | struct dz_port *dport; | 188 | struct uart_port *uport; |
189 | struct dz_port *dport = &mux->dport[0]; | ||
176 | struct tty_struct *tty = NULL; | 190 | struct tty_struct *tty = NULL; |
177 | struct uart_icount *icount; | 191 | struct uart_icount *icount; |
178 | int lines_rx[DZ_NB_PORT] = { [0 ... DZ_NB_PORT - 1] = 0 }; | 192 | int lines_rx[DZ_NB_PORT] = { [0 ... DZ_NB_PORT - 1] = 0 }; |
179 | unsigned short status; | ||
180 | unsigned char ch, flag; | 193 | unsigned char ch, flag; |
194 | u16 status; | ||
181 | int i; | 195 | int i; |
182 | 196 | ||
183 | while ((status = dz_in(dport_in, DZ_RBUF)) & DZ_DVAL) { | 197 | while ((status = dz_in(dport, DZ_RBUF)) & DZ_DVAL) { |
184 | dport = &dz_ports[LINE(status)]; | 198 | dport = &mux->dport[LINE(status)]; |
185 | tty = dport->port.info->tty; /* point to the proper dev */ | 199 | uport = &dport->port; |
200 | tty = uport->info->tty; /* point to the proper dev */ | ||
186 | 201 | ||
187 | ch = UCHAR(status); /* grab the char */ | 202 | ch = UCHAR(status); /* grab the char */ |
203 | flag = TTY_NORMAL; | ||
188 | 204 | ||
189 | icount = &dport->port.icount; | 205 | icount = &uport->icount; |
190 | icount->rx++; | 206 | icount->rx++; |
191 | 207 | ||
192 | flag = TTY_NORMAL; | 208 | if (unlikely(status & (DZ_OERR | DZ_FERR | DZ_PERR))) { |
193 | if (status & DZ_FERR) { /* frame error */ | 209 | |
194 | /* | 210 | /* |
195 | * There is no separate BREAK status bit, so | 211 | * There is no separate BREAK status bit, so treat |
196 | * treat framing errors as BREAKs for Magic SysRq | 212 | * null characters with framing errors as BREAKs; |
197 | * and SAK; normally, otherwise. | 213 | * normally, otherwise. For this move the Framing |
214 | * Error bit to a simulated BREAK bit. | ||
198 | */ | 215 | */ |
199 | if (uart_handle_break(&dport->port)) | 216 | if (!ch) { |
200 | continue; | 217 | status |= (status & DZ_FERR) >> |
201 | if (dport->port.flags & UPF_SAK) | 218 | (ffs(DZ_FERR) - ffs(DZ_BREAK)); |
219 | status &= ~DZ_FERR; | ||
220 | } | ||
221 | |||
222 | /* Handle SysRq/SAK & keep track of the statistics. */ | ||
223 | if (status & DZ_BREAK) { | ||
224 | icount->brk++; | ||
225 | if (uart_handle_break(uport)) | ||
226 | continue; | ||
227 | } else if (status & DZ_FERR) | ||
228 | icount->frame++; | ||
229 | else if (status & DZ_PERR) | ||
230 | icount->parity++; | ||
231 | if (status & DZ_OERR) | ||
232 | icount->overrun++; | ||
233 | |||
234 | status &= uport->read_status_mask; | ||
235 | if (status & DZ_BREAK) | ||
202 | flag = TTY_BREAK; | 236 | flag = TTY_BREAK; |
203 | else | 237 | else if (status & DZ_FERR) |
204 | flag = TTY_FRAME; | 238 | flag = TTY_FRAME; |
205 | } else if (status & DZ_OERR) /* overrun error */ | 239 | else if (status & DZ_PERR) |
206 | flag = TTY_OVERRUN; | 240 | flag = TTY_PARITY; |
207 | else if (status & DZ_PERR) /* parity error */ | 241 | |
208 | flag = TTY_PARITY; | ||
209 | |||
210 | /* keep track of the statistics */ | ||
211 | switch (flag) { | ||
212 | case TTY_FRAME: | ||
213 | icount->frame++; | ||
214 | break; | ||
215 | case TTY_PARITY: | ||
216 | icount->parity++; | ||
217 | break; | ||
218 | case TTY_OVERRUN: | ||
219 | icount->overrun++; | ||
220 | break; | ||
221 | case TTY_BREAK: | ||
222 | icount->brk++; | ||
223 | break; | ||
224 | default: | ||
225 | break; | ||
226 | } | 242 | } |
227 | 243 | ||
228 | if (uart_handle_sysrq_char(&dport->port, ch)) | 244 | if (uart_handle_sysrq_char(uport, ch)) |
229 | continue; | 245 | continue; |
230 | 246 | ||
231 | if ((status & dport->port.ignore_status_mask) == 0) { | 247 | uart_insert_char(uport, status, DZ_OERR, ch, flag); |
232 | uart_insert_char(&dport->port, | 248 | lines_rx[LINE(status)] = 1; |
233 | status, DZ_OERR, ch, flag); | ||
234 | lines_rx[LINE(status)] = 1; | ||
235 | } | ||
236 | } | 249 | } |
237 | for (i = 0; i < DZ_NB_PORT; i++) | 250 | for (i = 0; i < DZ_NB_PORT; i++) |
238 | if (lines_rx[i]) | 251 | if (lines_rx[i]) |
239 | tty_flip_buffer_push(dz_ports[i].port.info->tty); | 252 | tty_flip_buffer_push(mux->dport[i].port.info->tty); |
240 | } | 253 | } |
241 | 254 | ||
242 | /* | 255 | /* |
@@ -246,15 +259,15 @@ static inline void dz_receive_chars(struct dz_port *dport_in) | |||
246 | * This routine deals with outputs to any lines. | 259 | * This routine deals with outputs to any lines. |
247 | * ------------------------------------------------------------ | 260 | * ------------------------------------------------------------ |
248 | */ | 261 | */ |
249 | static inline void dz_transmit_chars(struct dz_port *dport_in) | 262 | static inline void dz_transmit_chars(struct dz_mux *mux) |
250 | { | 263 | { |
251 | struct dz_port *dport; | 264 | struct dz_port *dport = &mux->dport[0]; |
252 | struct circ_buf *xmit; | 265 | struct circ_buf *xmit; |
253 | unsigned short status; | ||
254 | unsigned char tmp; | 266 | unsigned char tmp; |
267 | u16 status; | ||
255 | 268 | ||
256 | status = dz_in(dport_in, DZ_CSR); | 269 | status = dz_in(dport, DZ_CSR); |
257 | dport = &dz_ports[LINE(status)]; | 270 | dport = &mux->dport[LINE(status)]; |
258 | xmit = &dport->port.info->xmit; | 271 | xmit = &dport->port.info->xmit; |
259 | 272 | ||
260 | if (dport->port.x_char) { /* XON/XOFF chars */ | 273 | if (dport->port.x_char) { /* XON/XOFF chars */ |
@@ -265,7 +278,9 @@ static inline void dz_transmit_chars(struct dz_port *dport_in) | |||
265 | } | 278 | } |
266 | /* If nothing to do or stopped or hardware stopped. */ | 279 | /* If nothing to do or stopped or hardware stopped. */ |
267 | if (uart_circ_empty(xmit) || uart_tx_stopped(&dport->port)) { | 280 | if (uart_circ_empty(xmit) || uart_tx_stopped(&dport->port)) { |
281 | spin_lock(&dport->port.lock); | ||
268 | dz_stop_tx(&dport->port); | 282 | dz_stop_tx(&dport->port); |
283 | spin_unlock(&dport->port.lock); | ||
269 | return; | 284 | return; |
270 | } | 285 | } |
271 | 286 | ||
@@ -282,8 +297,11 @@ static inline void dz_transmit_chars(struct dz_port *dport_in) | |||
282 | uart_write_wakeup(&dport->port); | 297 | uart_write_wakeup(&dport->port); |
283 | 298 | ||
284 | /* Are we are done. */ | 299 | /* Are we are done. */ |
285 | if (uart_circ_empty(xmit)) | 300 | if (uart_circ_empty(xmit)) { |
301 | spin_lock(&dport->port.lock); | ||
286 | dz_stop_tx(&dport->port); | 302 | dz_stop_tx(&dport->port); |
303 | spin_unlock(&dport->port.lock); | ||
304 | } | ||
287 | } | 305 | } |
288 | 306 | ||
289 | /* | 307 | /* |
@@ -301,7 +319,7 @@ static inline void check_modem_status(struct dz_port *dport) | |||
301 | * 1. No status change interrupt; use a timer. | 319 | * 1. No status change interrupt; use a timer. |
302 | * 2. Handle the 3100/5000 as appropriate. --macro | 320 | * 2. Handle the 3100/5000 as appropriate. --macro |
303 | */ | 321 | */ |
304 | unsigned short status; | 322 | u16 status; |
305 | 323 | ||
306 | /* If not the modem line just return. */ | 324 | /* If not the modem line just return. */ |
307 | if (dport->port.line != DZ_MODEM) | 325 | if (dport->port.line != DZ_MODEM) |
@@ -322,19 +340,20 @@ static inline void check_modem_status(struct dz_port *dport) | |||
322 | * It deals with the multiple ports. | 340 | * It deals with the multiple ports. |
323 | * ------------------------------------------------------------ | 341 | * ------------------------------------------------------------ |
324 | */ | 342 | */ |
325 | static irqreturn_t dz_interrupt(int irq, void *dev) | 343 | static irqreturn_t dz_interrupt(int irq, void *dev_id) |
326 | { | 344 | { |
327 | struct dz_port *dport = (struct dz_port *)dev; | 345 | struct dz_mux *mux = dev_id; |
328 | unsigned short status; | 346 | struct dz_port *dport = &mux->dport[0]; |
347 | u16 status; | ||
329 | 348 | ||
330 | /* get the reason why we just got an irq */ | 349 | /* get the reason why we just got an irq */ |
331 | status = dz_in(dport, DZ_CSR); | 350 | status = dz_in(dport, DZ_CSR); |
332 | 351 | ||
333 | if ((status & (DZ_RDONE | DZ_RIE)) == (DZ_RDONE | DZ_RIE)) | 352 | if ((status & (DZ_RDONE | DZ_RIE)) == (DZ_RDONE | DZ_RIE)) |
334 | dz_receive_chars(dport); | 353 | dz_receive_chars(mux); |
335 | 354 | ||
336 | if ((status & (DZ_TRDY | DZ_TIE)) == (DZ_TRDY | DZ_TIE)) | 355 | if ((status & (DZ_TRDY | DZ_TIE)) == (DZ_TRDY | DZ_TIE)) |
337 | dz_transmit_chars(dport); | 356 | dz_transmit_chars(mux); |
338 | 357 | ||
339 | return IRQ_HANDLED; | 358 | return IRQ_HANDLED; |
340 | } | 359 | } |
@@ -350,7 +369,7 @@ static unsigned int dz_get_mctrl(struct uart_port *uport) | |||
350 | /* | 369 | /* |
351 | * FIXME: Handle the 3100/5000 as appropriate. --macro | 370 | * FIXME: Handle the 3100/5000 as appropriate. --macro |
352 | */ | 371 | */ |
353 | struct dz_port *dport = (struct dz_port *)uport; | 372 | struct dz_port *dport = to_dport(uport); |
354 | unsigned int mctrl = TIOCM_CAR | TIOCM_DSR | TIOCM_CTS; | 373 | unsigned int mctrl = TIOCM_CAR | TIOCM_DSR | TIOCM_CTS; |
355 | 374 | ||
356 | if (dport->port.line == DZ_MODEM) { | 375 | if (dport->port.line == DZ_MODEM) { |
@@ -366,8 +385,8 @@ static void dz_set_mctrl(struct uart_port *uport, unsigned int mctrl) | |||
366 | /* | 385 | /* |
367 | * FIXME: Handle the 3100/5000 as appropriate. --macro | 386 | * FIXME: Handle the 3100/5000 as appropriate. --macro |
368 | */ | 387 | */ |
369 | struct dz_port *dport = (struct dz_port *)uport; | 388 | struct dz_port *dport = to_dport(uport); |
370 | unsigned short tmp; | 389 | u16 tmp; |
371 | 390 | ||
372 | if (dport->port.line == DZ_MODEM) { | 391 | if (dport->port.line == DZ_MODEM) { |
373 | tmp = dz_in(dport, DZ_TCR); | 392 | tmp = dz_in(dport, DZ_TCR); |
@@ -388,15 +407,30 @@ static void dz_set_mctrl(struct uart_port *uport, unsigned int mctrl) | |||
388 | */ | 407 | */ |
389 | static int dz_startup(struct uart_port *uport) | 408 | static int dz_startup(struct uart_port *uport) |
390 | { | 409 | { |
391 | struct dz_port *dport = (struct dz_port *)uport; | 410 | struct dz_port *dport = to_dport(uport); |
411 | struct dz_mux *mux = dport->mux; | ||
392 | unsigned long flags; | 412 | unsigned long flags; |
393 | unsigned short tmp; | 413 | int irq_guard; |
414 | int ret; | ||
415 | u16 tmp; | ||
416 | |||
417 | irq_guard = atomic_add_return(1, &mux->irq_guard); | ||
418 | if (irq_guard != 1) | ||
419 | return 0; | ||
420 | |||
421 | ret = request_irq(dport->port.irq, dz_interrupt, | ||
422 | IRQF_SHARED, "dz", mux); | ||
423 | if (ret) { | ||
424 | atomic_add(-1, &mux->irq_guard); | ||
425 | printk(KERN_ERR "dz: Cannot get IRQ %d!\n", dport->port.irq); | ||
426 | return ret; | ||
427 | } | ||
394 | 428 | ||
395 | spin_lock_irqsave(&dport->port.lock, flags); | 429 | spin_lock_irqsave(&dport->port.lock, flags); |
396 | 430 | ||
397 | /* enable the interrupt and the scanning */ | 431 | /* Enable interrupts. */ |
398 | tmp = dz_in(dport, DZ_CSR); | 432 | tmp = dz_in(dport, DZ_CSR); |
399 | tmp |= DZ_RIE | DZ_TIE | DZ_MSE; | 433 | tmp |= DZ_RIE | DZ_TIE; |
400 | dz_out(dport, DZ_CSR, tmp); | 434 | dz_out(dport, DZ_CSR, tmp); |
401 | 435 | ||
402 | spin_unlock_irqrestore(&dport->port.lock, flags); | 436 | spin_unlock_irqrestore(&dport->port.lock, flags); |
@@ -414,7 +448,25 @@ static int dz_startup(struct uart_port *uport) | |||
414 | */ | 448 | */ |
415 | static void dz_shutdown(struct uart_port *uport) | 449 | static void dz_shutdown(struct uart_port *uport) |
416 | { | 450 | { |
417 | dz_stop_tx(uport); | 451 | struct dz_port *dport = to_dport(uport); |
452 | struct dz_mux *mux = dport->mux; | ||
453 | unsigned long flags; | ||
454 | int irq_guard; | ||
455 | u16 tmp; | ||
456 | |||
457 | spin_lock_irqsave(&dport->port.lock, flags); | ||
458 | dz_stop_tx(&dport->port); | ||
459 | spin_unlock_irqrestore(&dport->port.lock, flags); | ||
460 | |||
461 | irq_guard = atomic_add_return(-1, &mux->irq_guard); | ||
462 | if (!irq_guard) { | ||
463 | /* Disable interrupts. */ | ||
464 | tmp = dz_in(dport, DZ_CSR); | ||
465 | tmp &= ~(DZ_RIE | DZ_TIE); | ||
466 | dz_out(dport, DZ_CSR, tmp); | ||
467 | |||
468 | free_irq(dport->port.irq, mux); | ||
469 | } | ||
418 | } | 470 | } |
419 | 471 | ||
420 | /* | 472 | /* |
@@ -431,7 +483,7 @@ static void dz_shutdown(struct uart_port *uport) | |||
431 | */ | 483 | */ |
432 | static unsigned int dz_tx_empty(struct uart_port *uport) | 484 | static unsigned int dz_tx_empty(struct uart_port *uport) |
433 | { | 485 | { |
434 | struct dz_port *dport = (struct dz_port *)uport; | 486 | struct dz_port *dport = to_dport(uport); |
435 | unsigned short tmp, mask = 1 << dport->port.line; | 487 | unsigned short tmp, mask = 1 << dport->port.line; |
436 | 488 | ||
437 | tmp = dz_in(dport, DZ_TCR); | 489 | tmp = dz_in(dport, DZ_TCR); |
@@ -446,7 +498,7 @@ static void dz_break_ctl(struct uart_port *uport, int break_state) | |||
446 | * FIXME: Can't access BREAK bits in TDR easily; | 498 | * FIXME: Can't access BREAK bits in TDR easily; |
447 | * reuse the code for polled TX. --macro | 499 | * reuse the code for polled TX. --macro |
448 | */ | 500 | */ |
449 | struct dz_port *dport = (struct dz_port *)uport; | 501 | struct dz_port *dport = to_dport(uport); |
450 | unsigned long flags; | 502 | unsigned long flags; |
451 | unsigned short tmp, mask = 1 << dport->port.line; | 503 | unsigned short tmp, mask = 1 << dport->port.line; |
452 | 504 | ||
@@ -460,12 +512,69 @@ static void dz_break_ctl(struct uart_port *uport, int break_state) | |||
460 | spin_unlock_irqrestore(&uport->lock, flags); | 512 | spin_unlock_irqrestore(&uport->lock, flags); |
461 | } | 513 | } |
462 | 514 | ||
515 | static int dz_encode_baud_rate(unsigned int baud) | ||
516 | { | ||
517 | switch (baud) { | ||
518 | case 50: | ||
519 | return DZ_B50; | ||
520 | case 75: | ||
521 | return DZ_B75; | ||
522 | case 110: | ||
523 | return DZ_B110; | ||
524 | case 134: | ||
525 | return DZ_B134; | ||
526 | case 150: | ||
527 | return DZ_B150; | ||
528 | case 300: | ||
529 | return DZ_B300; | ||
530 | case 600: | ||
531 | return DZ_B600; | ||
532 | case 1200: | ||
533 | return DZ_B1200; | ||
534 | case 1800: | ||
535 | return DZ_B1800; | ||
536 | case 2000: | ||
537 | return DZ_B2000; | ||
538 | case 2400: | ||
539 | return DZ_B2400; | ||
540 | case 3600: | ||
541 | return DZ_B3600; | ||
542 | case 4800: | ||
543 | return DZ_B4800; | ||
544 | case 7200: | ||
545 | return DZ_B7200; | ||
546 | case 9600: | ||
547 | return DZ_B9600; | ||
548 | default: | ||
549 | return -1; | ||
550 | } | ||
551 | } | ||
552 | |||
553 | |||
554 | static void dz_reset(struct dz_port *dport) | ||
555 | { | ||
556 | struct dz_mux *mux = dport->mux; | ||
557 | |||
558 | if (mux->initialised) | ||
559 | return; | ||
560 | |||
561 | dz_out(dport, DZ_CSR, DZ_CLR); | ||
562 | while (dz_in(dport, DZ_CSR) & DZ_CLR); | ||
563 | iob(); | ||
564 | |||
565 | /* Enable scanning. */ | ||
566 | dz_out(dport, DZ_CSR, DZ_MSE); | ||
567 | |||
568 | mux->initialised = 1; | ||
569 | } | ||
570 | |||
463 | static void dz_set_termios(struct uart_port *uport, struct ktermios *termios, | 571 | static void dz_set_termios(struct uart_port *uport, struct ktermios *termios, |
464 | struct ktermios *old_termios) | 572 | struct ktermios *old_termios) |
465 | { | 573 | { |
466 | struct dz_port *dport = (struct dz_port *)uport; | 574 | struct dz_port *dport = to_dport(uport); |
467 | unsigned long flags; | 575 | unsigned long flags; |
468 | unsigned int cflag, baud; | 576 | unsigned int cflag, baud; |
577 | int bflag; | ||
469 | 578 | ||
470 | cflag = dport->port.line; | 579 | cflag = dport->port.line; |
471 | 580 | ||
@@ -492,105 +601,127 @@ static void dz_set_termios(struct uart_port *uport, struct ktermios *termios, | |||
492 | cflag |= DZ_PARODD; | 601 | cflag |= DZ_PARODD; |
493 | 602 | ||
494 | baud = uart_get_baud_rate(uport, termios, old_termios, 50, 9600); | 603 | baud = uart_get_baud_rate(uport, termios, old_termios, 50, 9600); |
495 | switch (baud) { | 604 | bflag = dz_encode_baud_rate(baud); |
496 | case 50: | 605 | if (bflag < 0) { /* Try to keep unchanged. */ |
497 | cflag |= DZ_B50; | 606 | baud = uart_get_baud_rate(uport, old_termios, NULL, 50, 9600); |
498 | break; | 607 | bflag = dz_encode_baud_rate(baud); |
499 | case 75: | 608 | if (bflag < 0) { /* Resort to 9600. */ |
500 | cflag |= DZ_B75; | 609 | baud = 9600; |
501 | break; | 610 | bflag = DZ_B9600; |
502 | case 110: | 611 | } |
503 | cflag |= DZ_B110; | 612 | tty_termios_encode_baud_rate(termios, baud, baud); |
504 | break; | ||
505 | case 134: | ||
506 | cflag |= DZ_B134; | ||
507 | break; | ||
508 | case 150: | ||
509 | cflag |= DZ_B150; | ||
510 | break; | ||
511 | case 300: | ||
512 | cflag |= DZ_B300; | ||
513 | break; | ||
514 | case 600: | ||
515 | cflag |= DZ_B600; | ||
516 | break; | ||
517 | case 1200: | ||
518 | cflag |= DZ_B1200; | ||
519 | break; | ||
520 | case 1800: | ||
521 | cflag |= DZ_B1800; | ||
522 | break; | ||
523 | case 2000: | ||
524 | cflag |= DZ_B2000; | ||
525 | break; | ||
526 | case 2400: | ||
527 | cflag |= DZ_B2400; | ||
528 | break; | ||
529 | case 3600: | ||
530 | cflag |= DZ_B3600; | ||
531 | break; | ||
532 | case 4800: | ||
533 | cflag |= DZ_B4800; | ||
534 | break; | ||
535 | case 7200: | ||
536 | cflag |= DZ_B7200; | ||
537 | break; | ||
538 | case 9600: | ||
539 | default: | ||
540 | cflag |= DZ_B9600; | ||
541 | } | 613 | } |
614 | cflag |= bflag; | ||
542 | 615 | ||
543 | if (termios->c_cflag & CREAD) | 616 | if (termios->c_cflag & CREAD) |
544 | cflag |= DZ_RXENAB; | 617 | cflag |= DZ_RXENAB; |
545 | 618 | ||
546 | spin_lock_irqsave(&dport->port.lock, flags); | 619 | spin_lock_irqsave(&dport->port.lock, flags); |
547 | 620 | ||
548 | dz_out(dport, DZ_LPR, cflag | dport->port.line); | 621 | uart_update_timeout(uport, termios->c_cflag, baud); |
622 | |||
623 | dz_out(dport, DZ_LPR, cflag); | ||
549 | dport->cflag = cflag; | 624 | dport->cflag = cflag; |
550 | 625 | ||
551 | /* setup accept flag */ | 626 | /* setup accept flag */ |
552 | dport->port.read_status_mask = DZ_OERR; | 627 | dport->port.read_status_mask = DZ_OERR; |
553 | if (termios->c_iflag & INPCK) | 628 | if (termios->c_iflag & INPCK) |
554 | dport->port.read_status_mask |= DZ_FERR | DZ_PERR; | 629 | dport->port.read_status_mask |= DZ_FERR | DZ_PERR; |
630 | if (termios->c_iflag & (BRKINT | PARMRK)) | ||
631 | dport->port.read_status_mask |= DZ_BREAK; | ||
555 | 632 | ||
556 | /* characters to ignore */ | 633 | /* characters to ignore */ |
557 | uport->ignore_status_mask = 0; | 634 | uport->ignore_status_mask = 0; |
635 | if ((termios->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK)) | ||
636 | dport->port.ignore_status_mask |= DZ_OERR; | ||
558 | if (termios->c_iflag & IGNPAR) | 637 | if (termios->c_iflag & IGNPAR) |
559 | dport->port.ignore_status_mask |= DZ_FERR | DZ_PERR; | 638 | dport->port.ignore_status_mask |= DZ_FERR | DZ_PERR; |
639 | if (termios->c_iflag & IGNBRK) | ||
640 | dport->port.ignore_status_mask |= DZ_BREAK; | ||
560 | 641 | ||
561 | spin_unlock_irqrestore(&dport->port.lock, flags); | 642 | spin_unlock_irqrestore(&dport->port.lock, flags); |
562 | } | 643 | } |
563 | 644 | ||
564 | static const char *dz_type(struct uart_port *port) | 645 | static const char *dz_type(struct uart_port *uport) |
565 | { | 646 | { |
566 | return "DZ"; | 647 | return "DZ"; |
567 | } | 648 | } |
568 | 649 | ||
569 | static void dz_release_port(struct uart_port *port) | 650 | static void dz_release_port(struct uart_port *uport) |
570 | { | 651 | { |
571 | /* nothing to do */ | 652 | struct dz_mux *mux = to_dport(uport)->mux; |
653 | int map_guard; | ||
654 | |||
655 | iounmap(uport->membase); | ||
656 | uport->membase = NULL; | ||
657 | |||
658 | map_guard = atomic_add_return(-1, &mux->map_guard); | ||
659 | if (!map_guard) | ||
660 | release_mem_region(uport->mapbase, dec_kn_slot_size); | ||
572 | } | 661 | } |
573 | 662 | ||
574 | static int dz_request_port(struct uart_port *port) | 663 | static int dz_map_port(struct uart_port *uport) |
575 | { | 664 | { |
665 | if (!uport->membase) | ||
666 | uport->membase = ioremap_nocache(uport->mapbase, | ||
667 | dec_kn_slot_size); | ||
668 | if (!uport->membase) { | ||
669 | printk(KERN_ERR "dz: Cannot map MMIO\n"); | ||
670 | return -ENOMEM; | ||
671 | } | ||
576 | return 0; | 672 | return 0; |
577 | } | 673 | } |
578 | 674 | ||
579 | static void dz_config_port(struct uart_port *port, int flags) | 675 | static int dz_request_port(struct uart_port *uport) |
580 | { | 676 | { |
581 | if (flags & UART_CONFIG_TYPE) | 677 | struct dz_mux *mux = to_dport(uport)->mux; |
582 | port->type = PORT_DZ; | 678 | int map_guard; |
679 | int ret; | ||
680 | |||
681 | map_guard = atomic_add_return(1, &mux->map_guard); | ||
682 | if (map_guard == 1) { | ||
683 | if (!request_mem_region(uport->mapbase, dec_kn_slot_size, | ||
684 | "dz")) { | ||
685 | atomic_add(-1, &mux->map_guard); | ||
686 | printk(KERN_ERR | ||
687 | "dz: Unable to reserve MMIO resource\n"); | ||
688 | return -EBUSY; | ||
689 | } | ||
690 | } | ||
691 | ret = dz_map_port(uport); | ||
692 | if (ret) { | ||
693 | map_guard = atomic_add_return(-1, &mux->map_guard); | ||
694 | if (!map_guard) | ||
695 | release_mem_region(uport->mapbase, dec_kn_slot_size); | ||
696 | return ret; | ||
697 | } | ||
698 | return 0; | ||
699 | } | ||
700 | |||
701 | static void dz_config_port(struct uart_port *uport, int flags) | ||
702 | { | ||
703 | struct dz_port *dport = to_dport(uport); | ||
704 | |||
705 | if (flags & UART_CONFIG_TYPE) { | ||
706 | if (dz_request_port(uport)) | ||
707 | return; | ||
708 | |||
709 | uport->type = PORT_DZ; | ||
710 | |||
711 | dz_reset(dport); | ||
712 | } | ||
583 | } | 713 | } |
584 | 714 | ||
585 | /* | 715 | /* |
586 | * verify the new serial_struct (for TIOCSSERIAL). | 716 | * Verify the new serial_struct (for TIOCSSERIAL). |
587 | */ | 717 | */ |
588 | static int dz_verify_port(struct uart_port *port, struct serial_struct *ser) | 718 | static int dz_verify_port(struct uart_port *uport, struct serial_struct *ser) |
589 | { | 719 | { |
590 | int ret = 0; | 720 | int ret = 0; |
721 | |||
591 | if (ser->type != PORT_UNKNOWN && ser->type != PORT_DZ) | 722 | if (ser->type != PORT_UNKNOWN && ser->type != PORT_DZ) |
592 | ret = -EINVAL; | 723 | ret = -EINVAL; |
593 | if (ser->irq != port->irq) | 724 | if (ser->irq != uport->irq) |
594 | ret = -EINVAL; | 725 | ret = -EINVAL; |
595 | return ret; | 726 | return ret; |
596 | } | 727 | } |
@@ -617,40 +748,32 @@ static struct uart_ops dz_ops = { | |||
617 | static void __init dz_init_ports(void) | 748 | static void __init dz_init_ports(void) |
618 | { | 749 | { |
619 | static int first = 1; | 750 | static int first = 1; |
620 | struct dz_port *dport; | ||
621 | unsigned long base; | 751 | unsigned long base; |
622 | int i; | 752 | int line; |
623 | 753 | ||
624 | if (!first) | 754 | if (!first) |
625 | return; | 755 | return; |
626 | first = 0; | 756 | first = 0; |
627 | 757 | ||
628 | if (mips_machtype == MACH_DS23100 || | 758 | if (mips_machtype == MACH_DS23100 || mips_machtype == MACH_DS5100) |
629 | mips_machtype == MACH_DS5100) | 759 | base = dec_kn_slot_base + KN01_DZ11; |
630 | base = CKSEG1ADDR(KN01_SLOT_BASE + KN01_DZ11); | ||
631 | else | 760 | else |
632 | base = CKSEG1ADDR(KN02_SLOT_BASE + KN02_DZ11); | 761 | base = dec_kn_slot_base + KN02_DZ11; |
633 | |||
634 | for (i = 0, dport = dz_ports; i < DZ_NB_PORT; i++, dport++) { | ||
635 | spin_lock_init(&dport->port.lock); | ||
636 | dport->port.membase = (char *) base; | ||
637 | dport->port.iotype = UPIO_MEM; | ||
638 | dport->port.irq = dec_interrupt[DEC_IRQ_DZ11]; | ||
639 | dport->port.line = i; | ||
640 | dport->port.fifosize = 1; | ||
641 | dport->port.ops = &dz_ops; | ||
642 | dport->port.flags = UPF_BOOT_AUTOCONF; | ||
643 | } | ||
644 | } | ||
645 | 762 | ||
646 | static void dz_reset(struct dz_port *dport) | 763 | for (line = 0; line < DZ_NB_PORT; line++) { |
647 | { | 764 | struct dz_port *dport = &dz_mux.dport[line]; |
648 | dz_out(dport, DZ_CSR, DZ_CLR); | 765 | struct uart_port *uport = &dport->port; |
649 | while (dz_in(dport, DZ_CSR) & DZ_CLR); | ||
650 | iob(); | ||
651 | 766 | ||
652 | /* enable scanning */ | 767 | dport->mux = &dz_mux; |
653 | dz_out(dport, DZ_CSR, DZ_MSE); | 768 | |
769 | uport->irq = dec_interrupt[DEC_IRQ_DZ11]; | ||
770 | uport->fifosize = 1; | ||
771 | uport->iotype = UPIO_MEM; | ||
772 | uport->flags = UPF_BOOT_AUTOCONF; | ||
773 | uport->ops = &dz_ops; | ||
774 | uport->line = line; | ||
775 | uport->mapbase = base; | ||
776 | } | ||
654 | } | 777 | } |
655 | 778 | ||
656 | #ifdef CONFIG_SERIAL_DZ_CONSOLE | 779 | #ifdef CONFIG_SERIAL_DZ_CONSOLE |
@@ -670,7 +793,7 @@ static void dz_reset(struct dz_port *dport) | |||
670 | */ | 793 | */ |
671 | static void dz_console_putchar(struct uart_port *uport, int ch) | 794 | static void dz_console_putchar(struct uart_port *uport, int ch) |
672 | { | 795 | { |
673 | struct dz_port *dport = (struct dz_port *)uport; | 796 | struct dz_port *dport = to_dport(uport); |
674 | unsigned long flags; | 797 | unsigned long flags; |
675 | unsigned short csr, tcr, trdy, mask; | 798 | unsigned short csr, tcr, trdy, mask; |
676 | int loops = 10000; | 799 | int loops = 10000; |
@@ -685,7 +808,7 @@ static void dz_console_putchar(struct uart_port *uport, int ch) | |||
685 | iob(); | 808 | iob(); |
686 | spin_unlock_irqrestore(&dport->port.lock, flags); | 809 | spin_unlock_irqrestore(&dport->port.lock, flags); |
687 | 810 | ||
688 | while (loops--) { | 811 | do { |
689 | trdy = dz_in(dport, DZ_CSR); | 812 | trdy = dz_in(dport, DZ_CSR); |
690 | if (!(trdy & DZ_TRDY)) | 813 | if (!(trdy & DZ_TRDY)) |
691 | continue; | 814 | continue; |
@@ -696,7 +819,7 @@ static void dz_console_putchar(struct uart_port *uport, int ch) | |||
696 | dz_out(dport, DZ_TCR, mask); | 819 | dz_out(dport, DZ_TCR, mask); |
697 | iob(); | 820 | iob(); |
698 | udelay(2); | 821 | udelay(2); |
699 | } | 822 | } while (loops--); |
700 | 823 | ||
701 | if (loops) /* Cannot send otherwise. */ | 824 | if (loops) /* Cannot send otherwise. */ |
702 | dz_out(dport, DZ_TDR, ch); | 825 | dz_out(dport, DZ_TDR, ch); |
@@ -717,7 +840,7 @@ static void dz_console_print(struct console *co, | |||
717 | const char *str, | 840 | const char *str, |
718 | unsigned int count) | 841 | unsigned int count) |
719 | { | 842 | { |
720 | struct dz_port *dport = &dz_ports[co->index]; | 843 | struct dz_port *dport = &dz_mux.dport[co->index]; |
721 | #ifdef DEBUG_DZ | 844 | #ifdef DEBUG_DZ |
722 | prom_printf((char *) str); | 845 | prom_printf((char *) str); |
723 | #endif | 846 | #endif |
@@ -726,22 +849,28 @@ static void dz_console_print(struct console *co, | |||
726 | 849 | ||
727 | static int __init dz_console_setup(struct console *co, char *options) | 850 | static int __init dz_console_setup(struct console *co, char *options) |
728 | { | 851 | { |
729 | struct dz_port *dport = &dz_ports[co->index]; | 852 | struct dz_port *dport = &dz_mux.dport[co->index]; |
853 | struct uart_port *uport = &dport->port; | ||
730 | int baud = 9600; | 854 | int baud = 9600; |
731 | int bits = 8; | 855 | int bits = 8; |
732 | int parity = 'n'; | 856 | int parity = 'n'; |
733 | int flow = 'n'; | 857 | int flow = 'n'; |
858 | int ret; | ||
734 | 859 | ||
735 | if (options) | 860 | ret = dz_map_port(uport); |
736 | uart_parse_options(options, &baud, &parity, &bits, &flow); | 861 | if (ret) |
862 | return ret; | ||
737 | 863 | ||
738 | dz_reset(dport); | 864 | dz_reset(dport); |
739 | 865 | ||
866 | if (options) | ||
867 | uart_parse_options(options, &baud, &parity, &bits, &flow); | ||
868 | |||
740 | return uart_set_options(&dport->port, co, baud, parity, bits, flow); | 869 | return uart_set_options(&dport->port, co, baud, parity, bits, flow); |
741 | } | 870 | } |
742 | 871 | ||
743 | static struct uart_driver dz_reg; | 872 | static struct uart_driver dz_reg; |
744 | static struct console dz_sercons = { | 873 | static struct console dz_console = { |
745 | .name = "ttyS", | 874 | .name = "ttyS", |
746 | .write = dz_console_print, | 875 | .write = dz_console_print, |
747 | .device = uart_console_device, | 876 | .device = uart_console_device, |
@@ -755,7 +884,7 @@ static int __init dz_serial_console_init(void) | |||
755 | { | 884 | { |
756 | if (!IOASIC) { | 885 | if (!IOASIC) { |
757 | dz_init_ports(); | 886 | dz_init_ports(); |
758 | register_console(&dz_sercons); | 887 | register_console(&dz_console); |
759 | return 0; | 888 | return 0; |
760 | } else | 889 | } else |
761 | return -ENXIO; | 890 | return -ENXIO; |
@@ -763,7 +892,7 @@ static int __init dz_serial_console_init(void) | |||
763 | 892 | ||
764 | console_initcall(dz_serial_console_init); | 893 | console_initcall(dz_serial_console_init); |
765 | 894 | ||
766 | #define SERIAL_DZ_CONSOLE &dz_sercons | 895 | #define SERIAL_DZ_CONSOLE &dz_console |
767 | #else | 896 | #else |
768 | #define SERIAL_DZ_CONSOLE NULL | 897 | #define SERIAL_DZ_CONSOLE NULL |
769 | #endif /* CONFIG_SERIAL_DZ_CONSOLE */ | 898 | #endif /* CONFIG_SERIAL_DZ_CONSOLE */ |
@@ -789,26 +918,14 @@ static int __init dz_init(void) | |||
789 | 918 | ||
790 | dz_init_ports(); | 919 | dz_init_ports(); |
791 | 920 | ||
792 | #ifndef CONFIG_SERIAL_DZ_CONSOLE | ||
793 | /* reset the chip */ | ||
794 | dz_reset(&dz_ports[0]); | ||
795 | #endif | ||
796 | |||
797 | if (request_irq(dz_ports[0].port.irq, dz_interrupt, | ||
798 | IRQF_DISABLED, "DZ", &dz_ports[0])) | ||
799 | panic("Unable to register DZ interrupt"); | ||
800 | |||
801 | ret = uart_register_driver(&dz_reg); | 921 | ret = uart_register_driver(&dz_reg); |
802 | if (ret != 0) | 922 | if (ret) |
803 | return ret; | 923 | return ret; |
804 | 924 | ||
805 | for (i = 0; i < DZ_NB_PORT; i++) | 925 | for (i = 0; i < DZ_NB_PORT; i++) |
806 | uart_add_one_port(&dz_reg, &dz_ports[i].port); | 926 | uart_add_one_port(&dz_reg, &dz_mux.dport[i].port); |
807 | 927 | ||
808 | return ret; | 928 | return 0; |
809 | } | 929 | } |
810 | 930 | ||
811 | module_init(dz_init); | 931 | module_init(dz_init); |
812 | |||
813 | MODULE_DESCRIPTION("DECstation DZ serial driver"); | ||
814 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/serial/dz.h b/drivers/serial/dz.h index 9674d4e49872..faf169ed27b3 100644 --- a/drivers/serial/dz.h +++ b/drivers/serial/dz.h | |||
@@ -33,6 +33,8 @@ | |||
33 | #define DZ_FERR 0x2000 /* Frame error indicator */ | 33 | #define DZ_FERR 0x2000 /* Frame error indicator */ |
34 | #define DZ_PERR 0x1000 /* Parity error indicator */ | 34 | #define DZ_PERR 0x1000 /* Parity error indicator */ |
35 | 35 | ||
36 | #define DZ_BREAK 0x0800 /* BREAK event software flag */ | ||
37 | |||
36 | #define LINE(x) ((x & DZ_LINE_MASK) >> 8) /* Get the line number | 38 | #define LINE(x) ((x & DZ_LINE_MASK) >> 8) /* Get the line number |
37 | from the input buffer */ | 39 | from the input buffer */ |
38 | #define UCHAR(x) ((unsigned char)(x & DZ_RBUF_MASK)) | 40 | #define UCHAR(x) ((unsigned char)(x & DZ_RBUF_MASK)) |
@@ -107,8 +109,8 @@ | |||
107 | #define DZ_B7200 0x0D00 | 109 | #define DZ_B7200 0x0D00 |
108 | #define DZ_B9600 0x0E00 | 110 | #define DZ_B9600 0x0E00 |
109 | 111 | ||
110 | #define DZ_CREAD 0x1000 /* Enable receiver */ | 112 | #define DZ_RXENAB 0x1000 /* Receiver Enable */ |
111 | #define DZ_RXENAB 0x1000 /* enable receive char */ | 113 | |
112 | /* | 114 | /* |
113 | * Addresses for the DZ registers | 115 | * Addresses for the DZ registers |
114 | */ | 116 | */ |
@@ -124,9 +126,4 @@ | |||
124 | #define DZ_XMIT_SIZE 4096 /* buffer size */ | 126 | #define DZ_XMIT_SIZE 4096 /* buffer size */ |
125 | #define DZ_WAKEUP_CHARS DZ_XMIT_SIZE/4 | 127 | #define DZ_WAKEUP_CHARS DZ_XMIT_SIZE/4 |
126 | 128 | ||
127 | #ifdef MODULE | ||
128 | int init_module (void) | ||
129 | void cleanup_module (void) | ||
130 | #endif | ||
131 | |||
132 | #endif /* DZ_SERIAL_H */ | 129 | #endif /* DZ_SERIAL_H */ |
diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c index dc1967176fe2..56af1f566a4c 100644 --- a/drivers/serial/imx.c +++ b/drivers/serial/imx.c | |||
@@ -308,7 +308,7 @@ static void imx_start_tx(struct uart_port *port) | |||
308 | 308 | ||
309 | static irqreturn_t imx_rtsint(int irq, void *dev_id) | 309 | static irqreturn_t imx_rtsint(int irq, void *dev_id) |
310 | { | 310 | { |
311 | struct imx_port *sport = (struct imx_port *)dev_id; | 311 | struct imx_port *sport = dev_id; |
312 | unsigned int val = readl(sport->port.membase + USR1) & USR1_RTSS; | 312 | unsigned int val = readl(sport->port.membase + USR1) & USR1_RTSS; |
313 | unsigned long flags; | 313 | unsigned long flags; |
314 | 314 | ||
@@ -324,7 +324,7 @@ static irqreturn_t imx_rtsint(int irq, void *dev_id) | |||
324 | 324 | ||
325 | static irqreturn_t imx_txint(int irq, void *dev_id) | 325 | static irqreturn_t imx_txint(int irq, void *dev_id) |
326 | { | 326 | { |
327 | struct imx_port *sport = (struct imx_port *)dev_id; | 327 | struct imx_port *sport = dev_id; |
328 | struct circ_buf *xmit = &sport->port.info->xmit; | 328 | struct circ_buf *xmit = &sport->port.info->xmit; |
329 | unsigned long flags; | 329 | unsigned long flags; |
330 | 330 | ||
diff --git a/drivers/serial/sc26xx.c b/drivers/serial/sc26xx.c new file mode 100644 index 000000000000..a350b6d2a181 --- /dev/null +++ b/drivers/serial/sc26xx.c | |||
@@ -0,0 +1,755 @@ | |||
1 | /* | ||
2 | * SC268xx.c: Serial driver for Philiphs SC2681/SC2692 devices. | ||
3 | * | ||
4 | * Copyright (C) 2006,2007 Thomas Bogendörfer (tsbogend@alpha.franken.de) | ||
5 | */ | ||
6 | |||
7 | #include <linux/module.h> | ||
8 | #include <linux/kernel.h> | ||
9 | #include <linux/errno.h> | ||
10 | #include <linux/tty.h> | ||
11 | #include <linux/tty_flip.h> | ||
12 | #include <linux/major.h> | ||
13 | #include <linux/circ_buf.h> | ||
14 | #include <linux/serial.h> | ||
15 | #include <linux/sysrq.h> | ||
16 | #include <linux/console.h> | ||
17 | #include <linux/spinlock.h> | ||
18 | #include <linux/slab.h> | ||
19 | #include <linux/delay.h> | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/platform_device.h> | ||
22 | #include <linux/irq.h> | ||
23 | |||
24 | #if defined(CONFIG_MAGIC_SYSRQ) | ||
25 | #define SUPPORT_SYSRQ | ||
26 | #endif | ||
27 | |||
28 | #include <linux/serial_core.h> | ||
29 | |||
30 | #define SC26XX_MAJOR 204 | ||
31 | #define SC26XX_MINOR_START 205 | ||
32 | #define SC26XX_NR 2 | ||
33 | |||
34 | struct uart_sc26xx_port { | ||
35 | struct uart_port port[2]; | ||
36 | u8 dsr_mask[2]; | ||
37 | u8 cts_mask[2]; | ||
38 | u8 dcd_mask[2]; | ||
39 | u8 ri_mask[2]; | ||
40 | u8 dtr_mask[2]; | ||
41 | u8 rts_mask[2]; | ||
42 | u8 imr; | ||
43 | }; | ||
44 | |||
45 | /* register common to both ports */ | ||
46 | #define RD_ISR 0x14 | ||
47 | #define RD_IPR 0x34 | ||
48 | |||
49 | #define WR_ACR 0x10 | ||
50 | #define WR_IMR 0x14 | ||
51 | #define WR_OPCR 0x34 | ||
52 | #define WR_OPR_SET 0x38 | ||
53 | #define WR_OPR_CLR 0x3C | ||
54 | |||
55 | /* access common register */ | ||
56 | #define READ_SC(p, r) readb((p)->membase + RD_##r) | ||
57 | #define WRITE_SC(p, r, v) writeb((v), (p)->membase + WR_##r) | ||
58 | |||
59 | /* register per port */ | ||
60 | #define RD_PORT_MRx 0x00 | ||
61 | #define RD_PORT_SR 0x04 | ||
62 | #define RD_PORT_RHR 0x0c | ||
63 | |||
64 | #define WR_PORT_MRx 0x00 | ||
65 | #define WR_PORT_CSR 0x04 | ||
66 | #define WR_PORT_CR 0x08 | ||
67 | #define WR_PORT_THR 0x0c | ||
68 | |||
69 | /* SR bits */ | ||
70 | #define SR_BREAK (1 << 7) | ||
71 | #define SR_FRAME (1 << 6) | ||
72 | #define SR_PARITY (1 << 5) | ||
73 | #define SR_OVERRUN (1 << 4) | ||
74 | #define SR_TXRDY (1 << 2) | ||
75 | #define SR_RXRDY (1 << 0) | ||
76 | |||
77 | #define CR_RES_MR (1 << 4) | ||
78 | #define CR_RES_RX (2 << 4) | ||
79 | #define CR_RES_TX (3 << 4) | ||
80 | #define CR_STRT_BRK (6 << 4) | ||
81 | #define CR_STOP_BRK (7 << 4) | ||
82 | #define CR_DIS_TX (1 << 3) | ||
83 | #define CR_ENA_TX (1 << 2) | ||
84 | #define CR_DIS_RX (1 << 1) | ||
85 | #define CR_ENA_RX (1 << 0) | ||
86 | |||
87 | /* ISR bits */ | ||
88 | #define ISR_RXRDYB (1 << 5) | ||
89 | #define ISR_TXRDYB (1 << 4) | ||
90 | #define ISR_RXRDYA (1 << 1) | ||
91 | #define ISR_TXRDYA (1 << 0) | ||
92 | |||
93 | /* IMR bits */ | ||
94 | #define IMR_RXRDY (1 << 1) | ||
95 | #define IMR_TXRDY (1 << 0) | ||
96 | |||
97 | /* access port register */ | ||
98 | static inline u8 read_sc_port(struct uart_port *p, u8 reg) | ||
99 | { | ||
100 | return readb(p->membase + p->line * 0x20 + reg); | ||
101 | } | ||
102 | |||
103 | static inline void write_sc_port(struct uart_port *p, u8 reg, u8 val) | ||
104 | { | ||
105 | writeb(val, p->membase + p->line * 0x20 + reg); | ||
106 | } | ||
107 | |||
108 | #define READ_SC_PORT(p, r) read_sc_port(p, RD_PORT_##r) | ||
109 | #define WRITE_SC_PORT(p, r, v) write_sc_port(p, WR_PORT_##r, v) | ||
110 | |||
111 | static void sc26xx_enable_irq(struct uart_port *port, int mask) | ||
112 | { | ||
113 | struct uart_sc26xx_port *up; | ||
114 | int line = port->line; | ||
115 | |||
116 | port -= line; | ||
117 | up = container_of(port, struct uart_sc26xx_port, port[0]); | ||
118 | |||
119 | up->imr |= mask << (line * 4); | ||
120 | WRITE_SC(port, IMR, up->imr); | ||
121 | } | ||
122 | |||
123 | static void sc26xx_disable_irq(struct uart_port *port, int mask) | ||
124 | { | ||
125 | struct uart_sc26xx_port *up; | ||
126 | int line = port->line; | ||
127 | |||
128 | port -= line; | ||
129 | up = container_of(port, struct uart_sc26xx_port, port[0]); | ||
130 | |||
131 | up->imr &= ~(mask << (line * 4)); | ||
132 | WRITE_SC(port, IMR, up->imr); | ||
133 | } | ||
134 | |||
135 | static struct tty_struct *receive_chars(struct uart_port *port) | ||
136 | { | ||
137 | struct tty_struct *tty = NULL; | ||
138 | int limit = 10000; | ||
139 | unsigned char ch; | ||
140 | char flag; | ||
141 | u8 status; | ||
142 | |||
143 | if (port->info != NULL) /* Unopened serial console */ | ||
144 | tty = port->info->tty; | ||
145 | |||
146 | while (limit-- > 0) { | ||
147 | status = READ_SC_PORT(port, SR); | ||
148 | if (!(status & SR_RXRDY)) | ||
149 | break; | ||
150 | ch = READ_SC_PORT(port, RHR); | ||
151 | |||
152 | flag = TTY_NORMAL; | ||
153 | port->icount.rx++; | ||
154 | |||
155 | if (unlikely(status & (SR_BREAK | SR_FRAME | | ||
156 | SR_PARITY | SR_OVERRUN))) { | ||
157 | if (status & SR_BREAK) { | ||
158 | status &= ~(SR_PARITY | SR_FRAME); | ||
159 | port->icount.brk++; | ||
160 | if (uart_handle_break(port)) | ||
161 | continue; | ||
162 | } else if (status & SR_PARITY) | ||
163 | port->icount.parity++; | ||
164 | else if (status & SR_FRAME) | ||
165 | port->icount.frame++; | ||
166 | if (status & SR_OVERRUN) | ||
167 | port->icount.overrun++; | ||
168 | |||
169 | status &= port->read_status_mask; | ||
170 | if (status & SR_BREAK) | ||
171 | flag = TTY_BREAK; | ||
172 | else if (status & SR_PARITY) | ||
173 | flag = TTY_PARITY; | ||
174 | else if (status & SR_FRAME) | ||
175 | flag = TTY_FRAME; | ||
176 | } | ||
177 | |||
178 | if (uart_handle_sysrq_char(port, ch)) | ||
179 | continue; | ||
180 | |||
181 | if (status & port->ignore_status_mask) | ||
182 | continue; | ||
183 | |||
184 | tty_insert_flip_char(tty, ch, flag); | ||
185 | } | ||
186 | return tty; | ||
187 | } | ||
188 | |||
189 | static void transmit_chars(struct uart_port *port) | ||
190 | { | ||
191 | struct circ_buf *xmit; | ||
192 | |||
193 | if (!port->info) | ||
194 | return; | ||
195 | |||
196 | xmit = &port->info->xmit; | ||
197 | if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { | ||
198 | sc26xx_disable_irq(port, IMR_TXRDY); | ||
199 | return; | ||
200 | } | ||
201 | while (!uart_circ_empty(xmit)) { | ||
202 | if (!(READ_SC_PORT(port, SR) & SR_TXRDY)) | ||
203 | break; | ||
204 | |||
205 | WRITE_SC_PORT(port, THR, xmit->buf[xmit->tail]); | ||
206 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); | ||
207 | port->icount.tx++; | ||
208 | } | ||
209 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) | ||
210 | uart_write_wakeup(port); | ||
211 | } | ||
212 | |||
213 | static irqreturn_t sc26xx_interrupt(int irq, void *dev_id) | ||
214 | { | ||
215 | struct uart_sc26xx_port *up = dev_id; | ||
216 | struct tty_struct *tty; | ||
217 | unsigned long flags; | ||
218 | u8 isr; | ||
219 | |||
220 | spin_lock_irqsave(&up->port[0].lock, flags); | ||
221 | |||
222 | tty = NULL; | ||
223 | isr = READ_SC(&up->port[0], ISR); | ||
224 | if (isr & ISR_TXRDYA) | ||
225 | transmit_chars(&up->port[0]); | ||
226 | if (isr & ISR_RXRDYA) | ||
227 | tty = receive_chars(&up->port[0]); | ||
228 | |||
229 | spin_unlock(&up->port[0].lock); | ||
230 | |||
231 | if (tty) | ||
232 | tty_flip_buffer_push(tty); | ||
233 | |||
234 | spin_lock(&up->port[1].lock); | ||
235 | |||
236 | tty = NULL; | ||
237 | if (isr & ISR_TXRDYB) | ||
238 | transmit_chars(&up->port[1]); | ||
239 | if (isr & ISR_RXRDYB) | ||
240 | tty = receive_chars(&up->port[1]); | ||
241 | |||
242 | spin_unlock_irqrestore(&up->port[1].lock, flags); | ||
243 | |||
244 | if (tty) | ||
245 | tty_flip_buffer_push(tty); | ||
246 | |||
247 | return IRQ_HANDLED; | ||
248 | } | ||
249 | |||
250 | /* port->lock is not held. */ | ||
251 | static unsigned int sc26xx_tx_empty(struct uart_port *port) | ||
252 | { | ||
253 | return (READ_SC_PORT(port, SR) & SR_TXRDY) ? TIOCSER_TEMT : 0; | ||
254 | } | ||
255 | |||
256 | /* port->lock held by caller. */ | ||
257 | static void sc26xx_set_mctrl(struct uart_port *port, unsigned int mctrl) | ||
258 | { | ||
259 | struct uart_sc26xx_port *up; | ||
260 | int line = port->line; | ||
261 | |||
262 | port -= line; | ||
263 | up = container_of(port, struct uart_sc26xx_port, port[0]); | ||
264 | |||
265 | if (up->dtr_mask[line]) { | ||
266 | if (mctrl & TIOCM_DTR) | ||
267 | WRITE_SC(port, OPR_SET, up->dtr_mask[line]); | ||
268 | else | ||
269 | WRITE_SC(port, OPR_CLR, up->dtr_mask[line]); | ||
270 | } | ||
271 | if (up->rts_mask[line]) { | ||
272 | if (mctrl & TIOCM_RTS) | ||
273 | WRITE_SC(port, OPR_SET, up->rts_mask[line]); | ||
274 | else | ||
275 | WRITE_SC(port, OPR_CLR, up->rts_mask[line]); | ||
276 | } | ||
277 | } | ||
278 | |||
279 | /* port->lock is held by caller and interrupts are disabled. */ | ||
280 | static unsigned int sc26xx_get_mctrl(struct uart_port *port) | ||
281 | { | ||
282 | struct uart_sc26xx_port *up; | ||
283 | int line = port->line; | ||
284 | unsigned int mctrl = TIOCM_DSR | TIOCM_CTS | TIOCM_CAR; | ||
285 | u8 ipr; | ||
286 | |||
287 | port -= line; | ||
288 | up = container_of(port, struct uart_sc26xx_port, port[0]); | ||
289 | ipr = READ_SC(port, IPR) ^ 0xff; | ||
290 | |||
291 | if (up->dsr_mask[line]) { | ||
292 | mctrl &= ~TIOCM_DSR; | ||
293 | mctrl |= ipr & up->dsr_mask[line] ? TIOCM_DSR : 0; | ||
294 | } | ||
295 | if (up->cts_mask[line]) { | ||
296 | mctrl &= ~TIOCM_CTS; | ||
297 | mctrl |= ipr & up->cts_mask[line] ? TIOCM_CTS : 0; | ||
298 | } | ||
299 | if (up->dcd_mask[line]) { | ||
300 | mctrl &= ~TIOCM_CAR; | ||
301 | mctrl |= ipr & up->dcd_mask[line] ? TIOCM_CAR : 0; | ||
302 | } | ||
303 | if (up->ri_mask[line]) { | ||
304 | mctrl &= ~TIOCM_RNG; | ||
305 | mctrl |= ipr & up->ri_mask[line] ? TIOCM_RNG : 0; | ||
306 | } | ||
307 | return mctrl; | ||
308 | } | ||
309 | |||
310 | /* port->lock held by caller. */ | ||
311 | static void sc26xx_stop_tx(struct uart_port *port) | ||
312 | { | ||
313 | return; | ||
314 | } | ||
315 | |||
316 | /* port->lock held by caller. */ | ||
317 | static void sc26xx_start_tx(struct uart_port *port) | ||
318 | { | ||
319 | struct circ_buf *xmit = &port->info->xmit; | ||
320 | |||
321 | while (!uart_circ_empty(xmit)) { | ||
322 | if (!(READ_SC_PORT(port, SR) & SR_TXRDY)) { | ||
323 | sc26xx_enable_irq(port, IMR_TXRDY); | ||
324 | break; | ||
325 | } | ||
326 | WRITE_SC_PORT(port, THR, xmit->buf[xmit->tail]); | ||
327 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); | ||
328 | port->icount.tx++; | ||
329 | } | ||
330 | } | ||
331 | |||
332 | /* port->lock held by caller. */ | ||
333 | static void sc26xx_stop_rx(struct uart_port *port) | ||
334 | { | ||
335 | } | ||
336 | |||
337 | /* port->lock held by caller. */ | ||
338 | static void sc26xx_enable_ms(struct uart_port *port) | ||
339 | { | ||
340 | } | ||
341 | |||
342 | /* port->lock is not held. */ | ||
343 | static void sc26xx_break_ctl(struct uart_port *port, int break_state) | ||
344 | { | ||
345 | if (break_state == -1) | ||
346 | WRITE_SC_PORT(port, CR, CR_STRT_BRK); | ||
347 | else | ||
348 | WRITE_SC_PORT(port, CR, CR_STOP_BRK); | ||
349 | } | ||
350 | |||
351 | /* port->lock is not held. */ | ||
352 | static int sc26xx_startup(struct uart_port *port) | ||
353 | { | ||
354 | sc26xx_disable_irq(port, IMR_TXRDY | IMR_RXRDY); | ||
355 | WRITE_SC(port, OPCR, 0); | ||
356 | |||
357 | /* reset tx and rx */ | ||
358 | WRITE_SC_PORT(port, CR, CR_RES_RX); | ||
359 | WRITE_SC_PORT(port, CR, CR_RES_TX); | ||
360 | |||
361 | /* start rx/tx */ | ||
362 | WRITE_SC_PORT(port, CR, CR_ENA_TX | CR_ENA_RX); | ||
363 | |||
364 | /* enable irqs */ | ||
365 | sc26xx_enable_irq(port, IMR_RXRDY); | ||
366 | return 0; | ||
367 | } | ||
368 | |||
369 | /* port->lock is not held. */ | ||
370 | static void sc26xx_shutdown(struct uart_port *port) | ||
371 | { | ||
372 | /* disable interrupst */ | ||
373 | sc26xx_disable_irq(port, IMR_TXRDY | IMR_RXRDY); | ||
374 | |||
375 | /* stop tx/rx */ | ||
376 | WRITE_SC_PORT(port, CR, CR_DIS_TX | CR_DIS_RX); | ||
377 | } | ||
378 | |||
379 | /* port->lock is not held. */ | ||
380 | static void sc26xx_set_termios(struct uart_port *port, struct ktermios *termios, | ||
381 | struct ktermios *old) | ||
382 | { | ||
383 | unsigned int baud = uart_get_baud_rate(port, termios, old, 0, 4000000); | ||
384 | unsigned int quot = uart_get_divisor(port, baud); | ||
385 | unsigned int iflag, cflag; | ||
386 | unsigned long flags; | ||
387 | u8 mr1, mr2, csr; | ||
388 | |||
389 | spin_lock_irqsave(&port->lock, flags); | ||
390 | |||
391 | while ((READ_SC_PORT(port, SR) & ((1 << 3) | (1 << 2))) != 0xc) | ||
392 | udelay(2); | ||
393 | |||
394 | WRITE_SC_PORT(port, CR, CR_DIS_TX | CR_DIS_RX); | ||
395 | |||
396 | iflag = termios->c_iflag; | ||
397 | cflag = termios->c_cflag; | ||
398 | |||
399 | port->read_status_mask = SR_OVERRUN; | ||
400 | if (iflag & INPCK) | ||
401 | port->read_status_mask |= SR_PARITY | SR_FRAME; | ||
402 | if (iflag & (BRKINT | PARMRK)) | ||
403 | port->read_status_mask |= SR_BREAK; | ||
404 | |||
405 | port->ignore_status_mask = 0; | ||
406 | if (iflag & IGNBRK) | ||
407 | port->ignore_status_mask |= SR_BREAK; | ||
408 | if ((cflag & CREAD) == 0) | ||
409 | port->ignore_status_mask |= SR_BREAK | SR_FRAME | | ||
410 | SR_PARITY | SR_OVERRUN; | ||
411 | |||
412 | switch (cflag & CSIZE) { | ||
413 | case CS5: | ||
414 | mr1 = 0x00; | ||
415 | break; | ||
416 | case CS6: | ||
417 | mr1 = 0x01; | ||
418 | break; | ||
419 | case CS7: | ||
420 | mr1 = 0x02; | ||
421 | break; | ||
422 | default: | ||
423 | case CS8: | ||
424 | mr1 = 0x03; | ||
425 | break; | ||
426 | } | ||
427 | mr2 = 0x07; | ||
428 | if (cflag & CSTOPB) | ||
429 | mr2 = 0x0f; | ||
430 | if (cflag & PARENB) { | ||
431 | if (cflag & PARODD) | ||
432 | mr1 |= (1 << 2); | ||
433 | } else | ||
434 | mr1 |= (2 << 3); | ||
435 | |||
436 | switch (baud) { | ||
437 | case 50: | ||
438 | csr = 0x00; | ||
439 | break; | ||
440 | case 110: | ||
441 | csr = 0x11; | ||
442 | break; | ||
443 | case 134: | ||
444 | csr = 0x22; | ||
445 | break; | ||
446 | case 200: | ||
447 | csr = 0x33; | ||
448 | break; | ||
449 | case 300: | ||
450 | csr = 0x44; | ||
451 | break; | ||
452 | case 600: | ||
453 | csr = 0x55; | ||
454 | break; | ||
455 | case 1200: | ||
456 | csr = 0x66; | ||
457 | break; | ||
458 | case 2400: | ||
459 | csr = 0x88; | ||
460 | break; | ||
461 | case 4800: | ||
462 | csr = 0x99; | ||
463 | break; | ||
464 | default: | ||
465 | case 9600: | ||
466 | csr = 0xbb; | ||
467 | break; | ||
468 | case 19200: | ||
469 | csr = 0xcc; | ||
470 | break; | ||
471 | } | ||
472 | |||
473 | WRITE_SC_PORT(port, CR, CR_RES_MR); | ||
474 | WRITE_SC_PORT(port, MRx, mr1); | ||
475 | WRITE_SC_PORT(port, MRx, mr2); | ||
476 | |||
477 | WRITE_SC(port, ACR, 0x80); | ||
478 | WRITE_SC_PORT(port, CSR, csr); | ||
479 | |||
480 | /* reset tx and rx */ | ||
481 | WRITE_SC_PORT(port, CR, CR_RES_RX); | ||
482 | WRITE_SC_PORT(port, CR, CR_RES_TX); | ||
483 | |||
484 | WRITE_SC_PORT(port, CR, CR_ENA_TX | CR_ENA_RX); | ||
485 | while ((READ_SC_PORT(port, SR) & ((1 << 3) | (1 << 2))) != 0xc) | ||
486 | udelay(2); | ||
487 | |||
488 | /* XXX */ | ||
489 | uart_update_timeout(port, cflag, | ||
490 | (port->uartclk / (16 * quot))); | ||
491 | |||
492 | spin_unlock_irqrestore(&port->lock, flags); | ||
493 | } | ||
494 | |||
495 | static const char *sc26xx_type(struct uart_port *port) | ||
496 | { | ||
497 | return "SC26XX"; | ||
498 | } | ||
499 | |||
500 | static void sc26xx_release_port(struct uart_port *port) | ||
501 | { | ||
502 | } | ||
503 | |||
504 | static int sc26xx_request_port(struct uart_port *port) | ||
505 | { | ||
506 | return 0; | ||
507 | } | ||
508 | |||
509 | static void sc26xx_config_port(struct uart_port *port, int flags) | ||
510 | { | ||
511 | } | ||
512 | |||
513 | static int sc26xx_verify_port(struct uart_port *port, struct serial_struct *ser) | ||
514 | { | ||
515 | return -EINVAL; | ||
516 | } | ||
517 | |||
518 | static struct uart_ops sc26xx_ops = { | ||
519 | .tx_empty = sc26xx_tx_empty, | ||
520 | .set_mctrl = sc26xx_set_mctrl, | ||
521 | .get_mctrl = sc26xx_get_mctrl, | ||
522 | .stop_tx = sc26xx_stop_tx, | ||
523 | .start_tx = sc26xx_start_tx, | ||
524 | .stop_rx = sc26xx_stop_rx, | ||
525 | .enable_ms = sc26xx_enable_ms, | ||
526 | .break_ctl = sc26xx_break_ctl, | ||
527 | .startup = sc26xx_startup, | ||
528 | .shutdown = sc26xx_shutdown, | ||
529 | .set_termios = sc26xx_set_termios, | ||
530 | .type = sc26xx_type, | ||
531 | .release_port = sc26xx_release_port, | ||
532 | .request_port = sc26xx_request_port, | ||
533 | .config_port = sc26xx_config_port, | ||
534 | .verify_port = sc26xx_verify_port, | ||
535 | }; | ||
536 | |||
537 | static struct uart_port *sc26xx_port; | ||
538 | |||
539 | #ifdef CONFIG_SERIAL_SC26XX_CONSOLE | ||
540 | static void sc26xx_console_putchar(struct uart_port *port, char c) | ||
541 | { | ||
542 | unsigned long flags; | ||
543 | int limit = 1000000; | ||
544 | |||
545 | spin_lock_irqsave(&port->lock, flags); | ||
546 | |||
547 | while (limit-- > 0) { | ||
548 | if (READ_SC_PORT(port, SR) & SR_TXRDY) { | ||
549 | WRITE_SC_PORT(port, THR, c); | ||
550 | break; | ||
551 | } | ||
552 | udelay(2); | ||
553 | } | ||
554 | |||
555 | spin_unlock_irqrestore(&port->lock, flags); | ||
556 | } | ||
557 | |||
558 | static void sc26xx_console_write(struct console *con, const char *s, unsigned n) | ||
559 | { | ||
560 | struct uart_port *port = sc26xx_port; | ||
561 | int i; | ||
562 | |||
563 | for (i = 0; i < n; i++) { | ||
564 | if (*s == '\n') | ||
565 | sc26xx_console_putchar(port, '\r'); | ||
566 | sc26xx_console_putchar(port, *s++); | ||
567 | } | ||
568 | } | ||
569 | |||
570 | static int __init sc26xx_console_setup(struct console *con, char *options) | ||
571 | { | ||
572 | struct uart_port *port = sc26xx_port; | ||
573 | int baud = 9600; | ||
574 | int bits = 8; | ||
575 | int parity = 'n'; | ||
576 | int flow = 'n'; | ||
577 | |||
578 | if (port->type != PORT_SC26XX) | ||
579 | return -1; | ||
580 | |||
581 | printk(KERN_INFO "Console: ttySC%d (SC26XX)\n", con->index); | ||
582 | if (options) | ||
583 | uart_parse_options(options, &baud, &parity, &bits, &flow); | ||
584 | |||
585 | return uart_set_options(port, con, baud, parity, bits, flow); | ||
586 | } | ||
587 | |||
588 | static struct uart_driver sc26xx_reg; | ||
589 | static struct console sc26xx_console = { | ||
590 | .name = "ttySC", | ||
591 | .write = sc26xx_console_write, | ||
592 | .device = uart_console_device, | ||
593 | .setup = sc26xx_console_setup, | ||
594 | .flags = CON_PRINTBUFFER, | ||
595 | .index = -1, | ||
596 | .data = &sc26xx_reg, | ||
597 | }; | ||
598 | #define SC26XX_CONSOLE &sc26xx_console | ||
599 | #else | ||
600 | #define SC26XX_CONSOLE NULL | ||
601 | #endif | ||
602 | |||
603 | static struct uart_driver sc26xx_reg = { | ||
604 | .owner = THIS_MODULE, | ||
605 | .driver_name = "SC26xx", | ||
606 | .dev_name = "ttySC", | ||
607 | .major = SC26XX_MAJOR, | ||
608 | .minor = SC26XX_MINOR_START, | ||
609 | .nr = SC26XX_NR, | ||
610 | .cons = SC26XX_CONSOLE, | ||
611 | }; | ||
612 | |||
613 | static u8 sc26xx_flags2mask(unsigned int flags, unsigned int bitpos) | ||
614 | { | ||
615 | unsigned int bit = (flags >> bitpos) & 15; | ||
616 | |||
617 | return bit ? (1 << (bit - 1)) : 0; | ||
618 | } | ||
619 | |||
620 | static void __devinit sc26xx_init_masks(struct uart_sc26xx_port *up, | ||
621 | int line, unsigned int data) | ||
622 | { | ||
623 | up->dtr_mask[line] = sc26xx_flags2mask(data, 0); | ||
624 | up->rts_mask[line] = sc26xx_flags2mask(data, 4); | ||
625 | up->dsr_mask[line] = sc26xx_flags2mask(data, 8); | ||
626 | up->cts_mask[line] = sc26xx_flags2mask(data, 12); | ||
627 | up->dcd_mask[line] = sc26xx_flags2mask(data, 16); | ||
628 | up->ri_mask[line] = sc26xx_flags2mask(data, 20); | ||
629 | } | ||
630 | |||
631 | static int __devinit sc26xx_probe(struct platform_device *dev) | ||
632 | { | ||
633 | struct resource *res; | ||
634 | struct uart_sc26xx_port *up; | ||
635 | unsigned int *sc26xx_data = dev->dev.platform_data; | ||
636 | int err; | ||
637 | |||
638 | res = platform_get_resource(dev, IORESOURCE_MEM, 0); | ||
639 | if (!res) | ||
640 | return -ENODEV; | ||
641 | |||
642 | up = kzalloc(sizeof *up, GFP_KERNEL); | ||
643 | if (unlikely(!up)) | ||
644 | return -ENOMEM; | ||
645 | |||
646 | up->port[0].line = 0; | ||
647 | up->port[0].ops = &sc26xx_ops; | ||
648 | up->port[0].type = PORT_SC26XX; | ||
649 | up->port[0].uartclk = (29491200 / 16); /* arbitrary */ | ||
650 | |||
651 | up->port[0].mapbase = res->start; | ||
652 | up->port[0].membase = ioremap_nocache(up->port[0].mapbase, 0x40); | ||
653 | up->port[0].iotype = UPIO_MEM; | ||
654 | up->port[0].irq = platform_get_irq(dev, 0); | ||
655 | |||
656 | up->port[0].dev = &dev->dev; | ||
657 | |||
658 | sc26xx_init_masks(up, 0, sc26xx_data[0]); | ||
659 | |||
660 | sc26xx_port = &up->port[0]; | ||
661 | |||
662 | up->port[1].line = 1; | ||
663 | up->port[1].ops = &sc26xx_ops; | ||
664 | up->port[1].type = PORT_SC26XX; | ||
665 | up->port[1].uartclk = (29491200 / 16); /* arbitrary */ | ||
666 | |||
667 | up->port[1].mapbase = up->port[0].mapbase; | ||
668 | up->port[1].membase = up->port[0].membase; | ||
669 | up->port[1].iotype = UPIO_MEM; | ||
670 | up->port[1].irq = up->port[0].irq; | ||
671 | |||
672 | up->port[1].dev = &dev->dev; | ||
673 | |||
674 | sc26xx_init_masks(up, 1, sc26xx_data[1]); | ||
675 | |||
676 | err = uart_register_driver(&sc26xx_reg); | ||
677 | if (err) | ||
678 | goto out_free_port; | ||
679 | |||
680 | sc26xx_reg.tty_driver->name_base = sc26xx_reg.minor; | ||
681 | |||
682 | err = uart_add_one_port(&sc26xx_reg, &up->port[0]); | ||
683 | if (err) | ||
684 | goto out_unregister_driver; | ||
685 | |||
686 | err = uart_add_one_port(&sc26xx_reg, &up->port[1]); | ||
687 | if (err) | ||
688 | goto out_remove_port0; | ||
689 | |||
690 | err = request_irq(up->port[0].irq, sc26xx_interrupt, 0, "sc26xx", up); | ||
691 | if (err) | ||
692 | goto out_remove_ports; | ||
693 | |||
694 | dev_set_drvdata(&dev->dev, up); | ||
695 | return 0; | ||
696 | |||
697 | out_remove_ports: | ||
698 | uart_remove_one_port(&sc26xx_reg, &up->port[1]); | ||
699 | out_remove_port0: | ||
700 | uart_remove_one_port(&sc26xx_reg, &up->port[0]); | ||
701 | |||
702 | out_unregister_driver: | ||
703 | uart_unregister_driver(&sc26xx_reg); | ||
704 | |||
705 | out_free_port: | ||
706 | kfree(up); | ||
707 | sc26xx_port = NULL; | ||
708 | return err; | ||
709 | } | ||
710 | |||
711 | |||
712 | static int __exit sc26xx_driver_remove(struct platform_device *dev) | ||
713 | { | ||
714 | struct uart_sc26xx_port *up = dev_get_drvdata(&dev->dev); | ||
715 | |||
716 | free_irq(up->port[0].irq, up); | ||
717 | |||
718 | uart_remove_one_port(&sc26xx_reg, &up->port[0]); | ||
719 | uart_remove_one_port(&sc26xx_reg, &up->port[1]); | ||
720 | |||
721 | uart_unregister_driver(&sc26xx_reg); | ||
722 | |||
723 | kfree(up); | ||
724 | sc26xx_port = NULL; | ||
725 | |||
726 | dev_set_drvdata(&dev->dev, NULL); | ||
727 | return 0; | ||
728 | } | ||
729 | |||
730 | static struct platform_driver sc26xx_driver = { | ||
731 | .probe = sc26xx_probe, | ||
732 | .remove = __devexit_p(sc26xx_driver_remove), | ||
733 | .driver = { | ||
734 | .name = "SC26xx", | ||
735 | }, | ||
736 | }; | ||
737 | |||
738 | static int __init sc26xx_init(void) | ||
739 | { | ||
740 | return platform_driver_register(&sc26xx_driver); | ||
741 | } | ||
742 | |||
743 | static void __exit sc26xx_exit(void) | ||
744 | { | ||
745 | platform_driver_unregister(&sc26xx_driver); | ||
746 | } | ||
747 | |||
748 | module_init(sc26xx_init); | ||
749 | module_exit(sc26xx_exit); | ||
750 | |||
751 | |||
752 | MODULE_AUTHOR("Thomas Bogendörfer"); | ||
753 | MODULE_DESCRIPTION("SC681/SC2692 serial driver"); | ||
754 | MODULE_VERSION("1.0"); | ||
755 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/serial/uartlite.c b/drivers/serial/uartlite.c index 1a7bccebd503..4e06ab6bcb6e 100644 --- a/drivers/serial/uartlite.c +++ b/drivers/serial/uartlite.c | |||
@@ -153,7 +153,7 @@ static int ulite_transmit(struct uart_port *port, int stat) | |||
153 | 153 | ||
154 | static irqreturn_t ulite_isr(int irq, void *dev_id) | 154 | static irqreturn_t ulite_isr(int irq, void *dev_id) |
155 | { | 155 | { |
156 | struct uart_port *port = (struct uart_port *)dev_id; | 156 | struct uart_port *port = dev_id; |
157 | int busy; | 157 | int busy; |
158 | 158 | ||
159 | do { | 159 | do { |
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index aaaea81e412a..d8107890db15 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig | |||
@@ -144,10 +144,10 @@ config SPI_OMAP_UWIRE | |||
144 | This hooks up to the MicroWire controller on OMAP1 chips. | 144 | This hooks up to the MicroWire controller on OMAP1 chips. |
145 | 145 | ||
146 | config SPI_OMAP24XX | 146 | config SPI_OMAP24XX |
147 | tristate "McSPI driver for OMAP24xx" | 147 | tristate "McSPI driver for OMAP24xx/OMAP34xx" |
148 | depends on SPI_MASTER && ARCH_OMAP24XX | 148 | depends on SPI_MASTER && (ARCH_OMAP24XX || ARCH_OMAP34XX) |
149 | help | 149 | help |
150 | SPI master controller for OMAP24xx Multichannel SPI | 150 | SPI master controller for OMAP24xx/OMAP34xx Multichannel SPI |
151 | (McSPI) modules. | 151 | (McSPI) modules. |
152 | 152 | ||
153 | config SPI_PXA2XX | 153 | config SPI_PXA2XX |
@@ -176,6 +176,13 @@ config SPI_S3C24XX_GPIO | |||
176 | the inbuilt hardware cannot provide the transfer mode, or | 176 | the inbuilt hardware cannot provide the transfer mode, or |
177 | where the board is using non hardware connected pins. | 177 | where the board is using non hardware connected pins. |
178 | 178 | ||
179 | config SPI_SH_SCI | ||
180 | tristate "SuperH SCI SPI controller" | ||
181 | depends on SPI_MASTER && SUPERH | ||
182 | select SPI_BITBANG | ||
183 | help | ||
184 | SPI driver for SuperH SCI blocks. | ||
185 | |||
179 | config SPI_TXX9 | 186 | config SPI_TXX9 |
180 | tristate "Toshiba TXx9 SPI controller" | 187 | tristate "Toshiba TXx9 SPI controller" |
181 | depends on SPI_MASTER && GENERIC_GPIO && CPU_TX49XX | 188 | depends on SPI_MASTER && GENERIC_GPIO && CPU_TX49XX |
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 41fbac45c323..7fca043ce723 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile | |||
@@ -27,6 +27,7 @@ obj-$(CONFIG_SPI_S3C24XX_GPIO) += spi_s3c24xx_gpio.o | |||
27 | obj-$(CONFIG_SPI_S3C24XX) += spi_s3c24xx.o | 27 | obj-$(CONFIG_SPI_S3C24XX) += spi_s3c24xx.o |
28 | obj-$(CONFIG_SPI_TXX9) += spi_txx9.o | 28 | obj-$(CONFIG_SPI_TXX9) += spi_txx9.o |
29 | obj-$(CONFIG_SPI_XILINX) += xilinx_spi.o | 29 | obj-$(CONFIG_SPI_XILINX) += xilinx_spi.o |
30 | obj-$(CONFIG_SPI_SH_SCI) += spi_sh_sci.o | ||
30 | # ... add above this line ... | 31 | # ... add above this line ... |
31 | 32 | ||
32 | # SPI protocol drivers (device/link on bus) | 33 | # SPI protocol drivers (device/link on bus) |
diff --git a/drivers/spi/atmel_spi.c b/drivers/spi/atmel_spi.c index ff10808183a3..293b7cab3e57 100644 --- a/drivers/spi/atmel_spi.c +++ b/drivers/spi/atmel_spi.c | |||
@@ -51,7 +51,9 @@ struct atmel_spi { | |||
51 | u8 stopping; | 51 | u8 stopping; |
52 | struct list_head queue; | 52 | struct list_head queue; |
53 | struct spi_transfer *current_transfer; | 53 | struct spi_transfer *current_transfer; |
54 | unsigned long remaining_bytes; | 54 | unsigned long current_remaining_bytes; |
55 | struct spi_transfer *next_transfer; | ||
56 | unsigned long next_remaining_bytes; | ||
55 | 57 | ||
56 | void *buffer; | 58 | void *buffer; |
57 | dma_addr_t buffer_dma; | 59 | dma_addr_t buffer_dma; |
@@ -121,6 +123,48 @@ static void cs_deactivate(struct atmel_spi *as, struct spi_device *spi) | |||
121 | gpio_set_value(gpio, !active); | 123 | gpio_set_value(gpio, !active); |
122 | } | 124 | } |
123 | 125 | ||
126 | static inline int atmel_spi_xfer_is_last(struct spi_message *msg, | ||
127 | struct spi_transfer *xfer) | ||
128 | { | ||
129 | return msg->transfers.prev == &xfer->transfer_list; | ||
130 | } | ||
131 | |||
132 | static inline int atmel_spi_xfer_can_be_chained(struct spi_transfer *xfer) | ||
133 | { | ||
134 | return xfer->delay_usecs == 0 && !xfer->cs_change; | ||
135 | } | ||
136 | |||
137 | static void atmel_spi_next_xfer_data(struct spi_master *master, | ||
138 | struct spi_transfer *xfer, | ||
139 | dma_addr_t *tx_dma, | ||
140 | dma_addr_t *rx_dma, | ||
141 | u32 *plen) | ||
142 | { | ||
143 | struct atmel_spi *as = spi_master_get_devdata(master); | ||
144 | u32 len = *plen; | ||
145 | |||
146 | /* use scratch buffer only when rx or tx data is unspecified */ | ||
147 | if (xfer->rx_buf) | ||
148 | *rx_dma = xfer->rx_dma + xfer->len - len; | ||
149 | else { | ||
150 | *rx_dma = as->buffer_dma; | ||
151 | if (len > BUFFER_SIZE) | ||
152 | len = BUFFER_SIZE; | ||
153 | } | ||
154 | if (xfer->tx_buf) | ||
155 | *tx_dma = xfer->tx_dma + xfer->len - len; | ||
156 | else { | ||
157 | *tx_dma = as->buffer_dma; | ||
158 | if (len > BUFFER_SIZE) | ||
159 | len = BUFFER_SIZE; | ||
160 | memset(as->buffer, 0, len); | ||
161 | dma_sync_single_for_device(&as->pdev->dev, | ||
162 | as->buffer_dma, len, DMA_TO_DEVICE); | ||
163 | } | ||
164 | |||
165 | *plen = len; | ||
166 | } | ||
167 | |||
124 | /* | 168 | /* |
125 | * Submit next transfer for DMA. | 169 | * Submit next transfer for DMA. |
126 | * lock is held, spi irq is blocked | 170 | * lock is held, spi irq is blocked |
@@ -130,53 +174,78 @@ static void atmel_spi_next_xfer(struct spi_master *master, | |||
130 | { | 174 | { |
131 | struct atmel_spi *as = spi_master_get_devdata(master); | 175 | struct atmel_spi *as = spi_master_get_devdata(master); |
132 | struct spi_transfer *xfer; | 176 | struct spi_transfer *xfer; |
133 | u32 len; | 177 | u32 len, remaining, total; |
134 | dma_addr_t tx_dma, rx_dma; | 178 | dma_addr_t tx_dma, rx_dma; |
135 | 179 | ||
136 | xfer = as->current_transfer; | 180 | if (!as->current_transfer) |
137 | if (!xfer || as->remaining_bytes == 0) { | 181 | xfer = list_entry(msg->transfers.next, |
138 | if (xfer) | 182 | struct spi_transfer, transfer_list); |
139 | xfer = list_entry(xfer->transfer_list.next, | 183 | else if (!as->next_transfer) |
140 | struct spi_transfer, transfer_list); | 184 | xfer = list_entry(as->current_transfer->transfer_list.next, |
141 | else | 185 | struct spi_transfer, transfer_list); |
142 | xfer = list_entry(msg->transfers.next, | 186 | else |
143 | struct spi_transfer, transfer_list); | 187 | xfer = NULL; |
144 | as->remaining_bytes = xfer->len; | ||
145 | as->current_transfer = xfer; | ||
146 | } | ||
147 | 188 | ||
148 | len = as->remaining_bytes; | 189 | if (xfer) { |
190 | len = xfer->len; | ||
191 | atmel_spi_next_xfer_data(master, xfer, &tx_dma, &rx_dma, &len); | ||
192 | remaining = xfer->len - len; | ||
149 | 193 | ||
150 | tx_dma = xfer->tx_dma + xfer->len - len; | 194 | spi_writel(as, RPR, rx_dma); |
151 | rx_dma = xfer->rx_dma + xfer->len - len; | 195 | spi_writel(as, TPR, tx_dma); |
152 | 196 | ||
153 | /* use scratch buffer only when rx or tx data is unspecified */ | 197 | if (msg->spi->bits_per_word > 8) |
154 | if (!xfer->rx_buf) { | 198 | len >>= 1; |
155 | rx_dma = as->buffer_dma; | 199 | spi_writel(as, RCR, len); |
156 | if (len > BUFFER_SIZE) | 200 | spi_writel(as, TCR, len); |
157 | len = BUFFER_SIZE; | 201 | |
158 | } | 202 | dev_dbg(&msg->spi->dev, |
159 | if (!xfer->tx_buf) { | 203 | " start xfer %p: len %u tx %p/%08x rx %p/%08x\n", |
160 | tx_dma = as->buffer_dma; | 204 | xfer, xfer->len, xfer->tx_buf, xfer->tx_dma, |
161 | if (len > BUFFER_SIZE) | 205 | xfer->rx_buf, xfer->rx_dma); |
162 | len = BUFFER_SIZE; | 206 | } else { |
163 | memset(as->buffer, 0, len); | 207 | xfer = as->next_transfer; |
164 | dma_sync_single_for_device(&as->pdev->dev, | 208 | remaining = as->next_remaining_bytes; |
165 | as->buffer_dma, len, DMA_TO_DEVICE); | ||
166 | } | 209 | } |
167 | 210 | ||
168 | spi_writel(as, RPR, rx_dma); | 211 | as->current_transfer = xfer; |
169 | spi_writel(as, TPR, tx_dma); | 212 | as->current_remaining_bytes = remaining; |
170 | 213 | ||
171 | as->remaining_bytes -= len; | 214 | if (remaining > 0) |
172 | if (msg->spi->bits_per_word > 8) | 215 | len = remaining; |
173 | len >>= 1; | 216 | else if (!atmel_spi_xfer_is_last(msg, xfer) |
217 | && atmel_spi_xfer_can_be_chained(xfer)) { | ||
218 | xfer = list_entry(xfer->transfer_list.next, | ||
219 | struct spi_transfer, transfer_list); | ||
220 | len = xfer->len; | ||
221 | } else | ||
222 | xfer = NULL; | ||
174 | 223 | ||
175 | /* REVISIT: when xfer->delay_usecs == 0, the PDC "next transfer" | 224 | as->next_transfer = xfer; |
176 | * mechanism might help avoid the IRQ latency between transfers | 225 | |
177 | * (and improve the nCS0 errata handling on at91rm9200 chips) | 226 | if (xfer) { |
178 | * | 227 | total = len; |
179 | * We're also waiting for ENDRX before we start the next | 228 | atmel_spi_next_xfer_data(master, xfer, &tx_dma, &rx_dma, &len); |
229 | as->next_remaining_bytes = total - len; | ||
230 | |||
231 | spi_writel(as, RNPR, rx_dma); | ||
232 | spi_writel(as, TNPR, tx_dma); | ||
233 | |||
234 | if (msg->spi->bits_per_word > 8) | ||
235 | len >>= 1; | ||
236 | spi_writel(as, RNCR, len); | ||
237 | spi_writel(as, TNCR, len); | ||
238 | |||
239 | dev_dbg(&msg->spi->dev, | ||
240 | " next xfer %p: len %u tx %p/%08x rx %p/%08x\n", | ||
241 | xfer, xfer->len, xfer->tx_buf, xfer->tx_dma, | ||
242 | xfer->rx_buf, xfer->rx_dma); | ||
243 | } else { | ||
244 | spi_writel(as, RNCR, 0); | ||
245 | spi_writel(as, TNCR, 0); | ||
246 | } | ||
247 | |||
248 | /* REVISIT: We're waiting for ENDRX before we start the next | ||
180 | * transfer because we need to handle some difficult timing | 249 | * transfer because we need to handle some difficult timing |
181 | * issues otherwise. If we wait for ENDTX in one transfer and | 250 | * issues otherwise. If we wait for ENDTX in one transfer and |
182 | * then starts waiting for ENDRX in the next, it's difficult | 251 | * then starts waiting for ENDRX in the next, it's difficult |
@@ -186,17 +255,7 @@ static void atmel_spi_next_xfer(struct spi_master *master, | |||
186 | * | 255 | * |
187 | * It should be doable, though. Just not now... | 256 | * It should be doable, though. Just not now... |
188 | */ | 257 | */ |
189 | spi_writel(as, TNCR, 0); | ||
190 | spi_writel(as, RNCR, 0); | ||
191 | spi_writel(as, IER, SPI_BIT(ENDRX) | SPI_BIT(OVRES)); | 258 | spi_writel(as, IER, SPI_BIT(ENDRX) | SPI_BIT(OVRES)); |
192 | |||
193 | dev_dbg(&msg->spi->dev, | ||
194 | " start xfer %p: len %u tx %p/%08x rx %p/%08x imr %03x\n", | ||
195 | xfer, xfer->len, xfer->tx_buf, xfer->tx_dma, | ||
196 | xfer->rx_buf, xfer->rx_dma, spi_readl(as, IMR)); | ||
197 | |||
198 | spi_writel(as, RCR, len); | ||
199 | spi_writel(as, TCR, len); | ||
200 | spi_writel(as, PTCR, SPI_BIT(TXTEN) | SPI_BIT(RXTEN)); | 259 | spi_writel(as, PTCR, SPI_BIT(TXTEN) | SPI_BIT(RXTEN)); |
201 | } | 260 | } |
202 | 261 | ||
@@ -294,6 +353,7 @@ atmel_spi_msg_done(struct spi_master *master, struct atmel_spi *as, | |||
294 | spin_lock(&as->lock); | 353 | spin_lock(&as->lock); |
295 | 354 | ||
296 | as->current_transfer = NULL; | 355 | as->current_transfer = NULL; |
356 | as->next_transfer = NULL; | ||
297 | 357 | ||
298 | /* continue if needed */ | 358 | /* continue if needed */ |
299 | if (list_empty(&as->queue) || as->stopping) | 359 | if (list_empty(&as->queue) || as->stopping) |
@@ -377,7 +437,7 @@ atmel_spi_interrupt(int irq, void *dev_id) | |||
377 | 437 | ||
378 | spi_writel(as, IDR, pending); | 438 | spi_writel(as, IDR, pending); |
379 | 439 | ||
380 | if (as->remaining_bytes == 0) { | 440 | if (as->current_remaining_bytes == 0) { |
381 | msg->actual_length += xfer->len; | 441 | msg->actual_length += xfer->len; |
382 | 442 | ||
383 | if (!msg->is_dma_mapped) | 443 | if (!msg->is_dma_mapped) |
@@ -387,7 +447,7 @@ atmel_spi_interrupt(int irq, void *dev_id) | |||
387 | if (xfer->delay_usecs) | 447 | if (xfer->delay_usecs) |
388 | udelay(xfer->delay_usecs); | 448 | udelay(xfer->delay_usecs); |
389 | 449 | ||
390 | if (msg->transfers.prev == &xfer->transfer_list) { | 450 | if (atmel_spi_xfer_is_last(msg, xfer)) { |
391 | /* report completed message */ | 451 | /* report completed message */ |
392 | atmel_spi_msg_done(master, as, msg, 0, | 452 | atmel_spi_msg_done(master, as, msg, 0, |
393 | xfer->cs_change); | 453 | xfer->cs_change); |
@@ -490,9 +550,14 @@ static int atmel_spi_setup(struct spi_device *spi) | |||
490 | if (!(spi->mode & SPI_CPHA)) | 550 | if (!(spi->mode & SPI_CPHA)) |
491 | csr |= SPI_BIT(NCPHA); | 551 | csr |= SPI_BIT(NCPHA); |
492 | 552 | ||
493 | /* TODO: DLYBS and DLYBCT */ | 553 | /* DLYBS is mostly irrelevant since we manage chipselect using GPIOs. |
494 | csr |= SPI_BF(DLYBS, 10); | 554 | * |
495 | csr |= SPI_BF(DLYBCT, 10); | 555 | * DLYBCT would add delays between words, slowing down transfers. |
556 | * It could potentially be useful to cope with DMA bottlenecks, but | ||
557 | * in those cases it's probably best to just use a lower bitrate. | ||
558 | */ | ||
559 | csr |= SPI_BF(DLYBS, 0); | ||
560 | csr |= SPI_BF(DLYBCT, 0); | ||
496 | 561 | ||
497 | /* chipselect must have been muxed as GPIO (e.g. in board setup) */ | 562 | /* chipselect must have been muxed as GPIO (e.g. in board setup) */ |
498 | npcs_pin = (unsigned int)spi->controller_data; | 563 | npcs_pin = (unsigned int)spi->controller_data; |
diff --git a/drivers/spi/omap2_mcspi.c b/drivers/spi/omap2_mcspi.c index ea61724ae225..a6ba11afb03f 100644 --- a/drivers/spi/omap2_mcspi.c +++ b/drivers/spi/omap2_mcspi.c | |||
@@ -915,6 +915,28 @@ static u8 __initdata spi2_txdma_id[] = { | |||
915 | OMAP24XX_DMA_SPI2_TX1, | 915 | OMAP24XX_DMA_SPI2_TX1, |
916 | }; | 916 | }; |
917 | 917 | ||
918 | #if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP34XX) | ||
919 | static u8 __initdata spi3_rxdma_id[] = { | ||
920 | OMAP24XX_DMA_SPI3_RX0, | ||
921 | OMAP24XX_DMA_SPI3_RX1, | ||
922 | }; | ||
923 | |||
924 | static u8 __initdata spi3_txdma_id[] = { | ||
925 | OMAP24XX_DMA_SPI3_TX0, | ||
926 | OMAP24XX_DMA_SPI3_TX1, | ||
927 | }; | ||
928 | #endif | ||
929 | |||
930 | #ifdef CONFIG_ARCH_OMAP3 | ||
931 | static u8 __initdata spi4_rxdma_id[] = { | ||
932 | OMAP34XX_DMA_SPI4_RX0, | ||
933 | }; | ||
934 | |||
935 | static u8 __initdata spi4_txdma_id[] = { | ||
936 | OMAP34XX_DMA_SPI4_TX0, | ||
937 | }; | ||
938 | #endif | ||
939 | |||
918 | static int __init omap2_mcspi_probe(struct platform_device *pdev) | 940 | static int __init omap2_mcspi_probe(struct platform_device *pdev) |
919 | { | 941 | { |
920 | struct spi_master *master; | 942 | struct spi_master *master; |
@@ -935,7 +957,20 @@ static int __init omap2_mcspi_probe(struct platform_device *pdev) | |||
935 | txdma_id = spi2_txdma_id; | 957 | txdma_id = spi2_txdma_id; |
936 | num_chipselect = 2; | 958 | num_chipselect = 2; |
937 | break; | 959 | break; |
938 | /* REVISIT omap2430 has a third McSPI ... */ | 960 | #if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3) |
961 | case 3: | ||
962 | rxdma_id = spi3_rxdma_id; | ||
963 | txdma_id = spi3_txdma_id; | ||
964 | num_chipselect = 2; | ||
965 | break; | ||
966 | #endif | ||
967 | #ifdef CONFIG_ARCH_OMAP3 | ||
968 | case 4: | ||
969 | rxdma_id = spi4_rxdma_id; | ||
970 | txdma_id = spi4_txdma_id; | ||
971 | num_chipselect = 1; | ||
972 | break; | ||
973 | #endif | ||
939 | default: | 974 | default: |
940 | return -EINVAL; | 975 | return -EINVAL; |
941 | } | 976 | } |
diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c index eb817b8eb024..365e0e355aea 100644 --- a/drivers/spi/pxa2xx_spi.c +++ b/drivers/spi/pxa2xx_spi.c | |||
@@ -1526,17 +1526,6 @@ static void pxa2xx_spi_shutdown(struct platform_device *pdev) | |||
1526 | } | 1526 | } |
1527 | 1527 | ||
1528 | #ifdef CONFIG_PM | 1528 | #ifdef CONFIG_PM |
1529 | static int suspend_devices(struct device *dev, void *pm_message) | ||
1530 | { | ||
1531 | pm_message_t *state = pm_message; | ||
1532 | |||
1533 | if (dev->power.power_state.event != state->event) { | ||
1534 | dev_warn(dev, "pm state does not match request\n"); | ||
1535 | return -1; | ||
1536 | } | ||
1537 | |||
1538 | return 0; | ||
1539 | } | ||
1540 | 1529 | ||
1541 | static int pxa2xx_spi_suspend(struct platform_device *pdev, pm_message_t state) | 1530 | static int pxa2xx_spi_suspend(struct platform_device *pdev, pm_message_t state) |
1542 | { | 1531 | { |
@@ -1544,12 +1533,6 @@ static int pxa2xx_spi_suspend(struct platform_device *pdev, pm_message_t state) | |||
1544 | struct ssp_device *ssp = drv_data->ssp; | 1533 | struct ssp_device *ssp = drv_data->ssp; |
1545 | int status = 0; | 1534 | int status = 0; |
1546 | 1535 | ||
1547 | /* Check all childern for current power state */ | ||
1548 | if (device_for_each_child(&pdev->dev, &state, suspend_devices) != 0) { | ||
1549 | dev_warn(&pdev->dev, "suspend aborted\n"); | ||
1550 | return -1; | ||
1551 | } | ||
1552 | |||
1553 | status = stop_queue(drv_data); | 1536 | status = stop_queue(drv_data); |
1554 | if (status != 0) | 1537 | if (status != 0) |
1555 | return status; | 1538 | return status; |
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 682a6a48fec3..1ad12afc6ba0 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c | |||
@@ -18,7 +18,6 @@ | |||
18 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 18 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
19 | */ | 19 | */ |
20 | 20 | ||
21 | #include <linux/autoconf.h> | ||
22 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
23 | #include <linux/device.h> | 22 | #include <linux/device.h> |
24 | #include <linux/init.h> | 23 | #include <linux/init.h> |
@@ -77,39 +76,33 @@ static int spi_uevent(struct device *dev, struct kobj_uevent_env *env) | |||
77 | 76 | ||
78 | #ifdef CONFIG_PM | 77 | #ifdef CONFIG_PM |
79 | 78 | ||
80 | /* | ||
81 | * NOTE: the suspend() method for an spi_master controller driver | ||
82 | * should verify that all its child devices are marked as suspended; | ||
83 | * suspend requests delivered through sysfs power/state files don't | ||
84 | * enforce such constraints. | ||
85 | */ | ||
86 | static int spi_suspend(struct device *dev, pm_message_t message) | 79 | static int spi_suspend(struct device *dev, pm_message_t message) |
87 | { | 80 | { |
88 | int value; | 81 | int value = 0; |
89 | struct spi_driver *drv = to_spi_driver(dev->driver); | 82 | struct spi_driver *drv = to_spi_driver(dev->driver); |
90 | 83 | ||
91 | if (!drv || !drv->suspend) | ||
92 | return 0; | ||
93 | |||
94 | /* suspend will stop irqs and dma; no more i/o */ | 84 | /* suspend will stop irqs and dma; no more i/o */ |
95 | value = drv->suspend(to_spi_device(dev), message); | 85 | if (drv) { |
96 | if (value == 0) | 86 | if (drv->suspend) |
97 | dev->power.power_state = message; | 87 | value = drv->suspend(to_spi_device(dev), message); |
88 | else | ||
89 | dev_dbg(dev, "... can't suspend\n"); | ||
90 | } | ||
98 | return value; | 91 | return value; |
99 | } | 92 | } |
100 | 93 | ||
101 | static int spi_resume(struct device *dev) | 94 | static int spi_resume(struct device *dev) |
102 | { | 95 | { |
103 | int value; | 96 | int value = 0; |
104 | struct spi_driver *drv = to_spi_driver(dev->driver); | 97 | struct spi_driver *drv = to_spi_driver(dev->driver); |
105 | 98 | ||
106 | if (!drv || !drv->resume) | ||
107 | return 0; | ||
108 | |||
109 | /* resume may restart the i/o queue */ | 99 | /* resume may restart the i/o queue */ |
110 | value = drv->resume(to_spi_device(dev)); | 100 | if (drv) { |
111 | if (value == 0) | 101 | if (drv->resume) |
112 | dev->power.power_state = PMSG_ON; | 102 | value = drv->resume(to_spi_device(dev)); |
103 | else | ||
104 | dev_dbg(dev, "... can't resume\n"); | ||
105 | } | ||
113 | return value; | 106 | return value; |
114 | } | 107 | } |
115 | 108 | ||
diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi_bfin5xx.c index 7ef39a6e8c06..d853fceb6bf0 100644 --- a/drivers/spi/spi_bfin5xx.c +++ b/drivers/spi/spi_bfin5xx.c | |||
@@ -1,37 +1,11 @@ | |||
1 | /* | 1 | /* |
2 | * File: drivers/spi/bfin5xx_spi.c | 2 | * Blackfin On-Chip SPI Driver |
3 | * Maintainer: | ||
4 | * Bryan Wu <bryan.wu@analog.com> | ||
5 | * Original Author: | ||
6 | * Luke Yang (Analog Devices Inc.) | ||
7 | * | ||
8 | * Created: March. 10th 2006 | ||
9 | * Description: SPI controller driver for Blackfin BF5xx | ||
10 | * Bugs: Enter bugs at http://blackfin.uclinux.org/ | ||
11 | * | ||
12 | * Modified: | ||
13 | * March 10, 2006 bfin5xx_spi.c Created. (Luke Yang) | ||
14 | * August 7, 2006 added full duplex mode (Axel Weiss & Luke Yang) | ||
15 | * July 17, 2007 add support for BF54x SPI0 controller (Bryan Wu) | ||
16 | * July 30, 2007 add platfrom_resource interface to support multi-port | ||
17 | * SPI controller (Bryan Wu) | ||
18 | * | 3 | * |
19 | * Copyright 2004-2007 Analog Devices Inc. | 4 | * Copyright 2004-2007 Analog Devices Inc. |
20 | * | 5 | * |
21 | * This program is free software ; you can redistribute it and/or modify | 6 | * Enter bugs at http://blackfin.uclinux.org/ |
22 | * it under the terms of the GNU General Public License as published by | ||
23 | * the Free Software Foundation ; either version 2, or (at your option) | ||
24 | * any later version. | ||
25 | * | ||
26 | * This program is distributed in the hope that it will be useful, | ||
27 | * but WITHOUT ANY WARRANTY ; without even the implied warranty of | ||
28 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
29 | * GNU General Public License for more details. | ||
30 | * | 7 | * |
31 | * You should have received a copy of the GNU General Public License | 8 | * Licensed under the GPL-2 or later. |
32 | * along with this program ; see the file COPYING. | ||
33 | * If not, write to the Free Software Foundation, | ||
34 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
35 | */ | 9 | */ |
36 | 10 | ||
37 | #include <linux/init.h> | 11 | #include <linux/init.h> |
@@ -223,10 +197,9 @@ static void cs_deactive(struct driver_data *drv_data, struct chip_data *chip) | |||
223 | #define MAX_SPI_SSEL 7 | 197 | #define MAX_SPI_SSEL 7 |
224 | 198 | ||
225 | /* stop controller and re-config current chip*/ | 199 | /* stop controller and re-config current chip*/ |
226 | static int restore_state(struct driver_data *drv_data) | 200 | static void restore_state(struct driver_data *drv_data) |
227 | { | 201 | { |
228 | struct chip_data *chip = drv_data->cur_chip; | 202 | struct chip_data *chip = drv_data->cur_chip; |
229 | int ret = 0; | ||
230 | 203 | ||
231 | /* Clear status and disable clock */ | 204 | /* Clear status and disable clock */ |
232 | write_STAT(drv_data, BIT_STAT_CLR); | 205 | write_STAT(drv_data, BIT_STAT_CLR); |
@@ -239,13 +212,6 @@ static int restore_state(struct driver_data *drv_data) | |||
239 | 212 | ||
240 | bfin_spi_enable(drv_data); | 213 | bfin_spi_enable(drv_data); |
241 | cs_active(drv_data, chip); | 214 | cs_active(drv_data, chip); |
242 | |||
243 | if (ret) | ||
244 | dev_dbg(&drv_data->pdev->dev, | ||
245 | ": request chip select number %d failed\n", | ||
246 | chip->chip_select_num); | ||
247 | |||
248 | return ret; | ||
249 | } | 215 | } |
250 | 216 | ||
251 | /* used to kick off transfer in rx mode */ | 217 | /* used to kick off transfer in rx mode */ |
@@ -286,32 +252,30 @@ static void u8_writer(struct driver_data *drv_data) | |||
286 | dev_dbg(&drv_data->pdev->dev, | 252 | dev_dbg(&drv_data->pdev->dev, |
287 | "cr8-s is 0x%x\n", read_STAT(drv_data)); | 253 | "cr8-s is 0x%x\n", read_STAT(drv_data)); |
288 | 254 | ||
289 | /* poll for SPI completion before start */ | ||
290 | while (!(read_STAT(drv_data) & BIT_STAT_SPIF)) | ||
291 | cpu_relax(); | ||
292 | |||
293 | while (drv_data->tx < drv_data->tx_end) { | 255 | while (drv_data->tx < drv_data->tx_end) { |
294 | write_TDBR(drv_data, (*(u8 *) (drv_data->tx))); | 256 | write_TDBR(drv_data, (*(u8 *) (drv_data->tx))); |
295 | while (read_STAT(drv_data) & BIT_STAT_TXS) | 257 | while (read_STAT(drv_data) & BIT_STAT_TXS) |
296 | cpu_relax(); | 258 | cpu_relax(); |
297 | ++drv_data->tx; | 259 | ++drv_data->tx; |
298 | } | 260 | } |
261 | |||
262 | /* poll for SPI completion before return */ | ||
263 | while (!(read_STAT(drv_data) & BIT_STAT_SPIF)) | ||
264 | cpu_relax(); | ||
299 | } | 265 | } |
300 | 266 | ||
301 | static void u8_cs_chg_writer(struct driver_data *drv_data) | 267 | static void u8_cs_chg_writer(struct driver_data *drv_data) |
302 | { | 268 | { |
303 | struct chip_data *chip = drv_data->cur_chip; | 269 | struct chip_data *chip = drv_data->cur_chip; |
304 | 270 | ||
305 | /* poll for SPI completion before start */ | ||
306 | while (!(read_STAT(drv_data) & BIT_STAT_SPIF)) | ||
307 | cpu_relax(); | ||
308 | |||
309 | while (drv_data->tx < drv_data->tx_end) { | 271 | while (drv_data->tx < drv_data->tx_end) { |
310 | cs_active(drv_data, chip); | 272 | cs_active(drv_data, chip); |
311 | 273 | ||
312 | write_TDBR(drv_data, (*(u8 *) (drv_data->tx))); | 274 | write_TDBR(drv_data, (*(u8 *) (drv_data->tx))); |
313 | while (read_STAT(drv_data) & BIT_STAT_TXS) | 275 | while (read_STAT(drv_data) & BIT_STAT_TXS) |
314 | cpu_relax(); | 276 | cpu_relax(); |
277 | while (!(read_STAT(drv_data) & BIT_STAT_SPIF)) | ||
278 | cpu_relax(); | ||
315 | 279 | ||
316 | cs_deactive(drv_data, chip); | 280 | cs_deactive(drv_data, chip); |
317 | 281 | ||
@@ -350,43 +314,28 @@ static void u8_cs_chg_reader(struct driver_data *drv_data) | |||
350 | { | 314 | { |
351 | struct chip_data *chip = drv_data->cur_chip; | 315 | struct chip_data *chip = drv_data->cur_chip; |
352 | 316 | ||
353 | /* poll for SPI completion before start */ | 317 | while (drv_data->rx < drv_data->rx_end) { |
354 | while (!(read_STAT(drv_data) & BIT_STAT_SPIF)) | 318 | cs_active(drv_data, chip); |
355 | cpu_relax(); | 319 | read_RDBR(drv_data); /* kick off */ |
356 | |||
357 | /* clear TDBR buffer before read(else it will be shifted out) */ | ||
358 | write_TDBR(drv_data, 0xFFFF); | ||
359 | 320 | ||
360 | cs_active(drv_data, chip); | 321 | while (!(read_STAT(drv_data) & BIT_STAT_RXS)) |
361 | dummy_read(drv_data); | 322 | cpu_relax(); |
323 | while (!(read_STAT(drv_data) & BIT_STAT_SPIF)) | ||
324 | cpu_relax(); | ||
362 | 325 | ||
363 | while (drv_data->rx < drv_data->rx_end - 1) { | 326 | *(u8 *) (drv_data->rx) = read_SHAW(drv_data); |
364 | cs_deactive(drv_data, chip); | 327 | cs_deactive(drv_data, chip); |
365 | 328 | ||
366 | while (!(read_STAT(drv_data) & BIT_STAT_RXS)) | ||
367 | cpu_relax(); | ||
368 | cs_active(drv_data, chip); | ||
369 | *(u8 *) (drv_data->rx) = read_RDBR(drv_data); | ||
370 | ++drv_data->rx; | 329 | ++drv_data->rx; |
371 | } | 330 | } |
372 | cs_deactive(drv_data, chip); | ||
373 | |||
374 | while (!(read_STAT(drv_data) & BIT_STAT_RXS)) | ||
375 | cpu_relax(); | ||
376 | *(u8 *) (drv_data->rx) = read_SHAW(drv_data); | ||
377 | ++drv_data->rx; | ||
378 | } | 331 | } |
379 | 332 | ||
380 | static void u8_duplex(struct driver_data *drv_data) | 333 | static void u8_duplex(struct driver_data *drv_data) |
381 | { | 334 | { |
382 | /* poll for SPI completion before start */ | ||
383 | while (!(read_STAT(drv_data) & BIT_STAT_SPIF)) | ||
384 | cpu_relax(); | ||
385 | |||
386 | /* in duplex mode, clk is triggered by writing of TDBR */ | 335 | /* in duplex mode, clk is triggered by writing of TDBR */ |
387 | while (drv_data->rx < drv_data->rx_end) { | 336 | while (drv_data->rx < drv_data->rx_end) { |
388 | write_TDBR(drv_data, (*(u8 *) (drv_data->tx))); | 337 | write_TDBR(drv_data, (*(u8 *) (drv_data->tx))); |
389 | while (read_STAT(drv_data) & BIT_STAT_TXS) | 338 | while (!(read_STAT(drv_data) & BIT_STAT_SPIF)) |
390 | cpu_relax(); | 339 | cpu_relax(); |
391 | while (!(read_STAT(drv_data) & BIT_STAT_RXS)) | 340 | while (!(read_STAT(drv_data) & BIT_STAT_RXS)) |
392 | cpu_relax(); | 341 | cpu_relax(); |
@@ -400,15 +349,12 @@ static void u8_cs_chg_duplex(struct driver_data *drv_data) | |||
400 | { | 349 | { |
401 | struct chip_data *chip = drv_data->cur_chip; | 350 | struct chip_data *chip = drv_data->cur_chip; |
402 | 351 | ||
403 | /* poll for SPI completion before start */ | ||
404 | while (!(read_STAT(drv_data) & BIT_STAT_SPIF)) | ||
405 | cpu_relax(); | ||
406 | |||
407 | while (drv_data->rx < drv_data->rx_end) { | 352 | while (drv_data->rx < drv_data->rx_end) { |
408 | cs_active(drv_data, chip); | 353 | cs_active(drv_data, chip); |
409 | 354 | ||
410 | write_TDBR(drv_data, (*(u8 *) (drv_data->tx))); | 355 | write_TDBR(drv_data, (*(u8 *) (drv_data->tx))); |
411 | while (read_STAT(drv_data) & BIT_STAT_TXS) | 356 | |
357 | while (!(read_STAT(drv_data) & BIT_STAT_SPIF)) | ||
412 | cpu_relax(); | 358 | cpu_relax(); |
413 | while (!(read_STAT(drv_data) & BIT_STAT_RXS)) | 359 | while (!(read_STAT(drv_data) & BIT_STAT_RXS)) |
414 | cpu_relax(); | 360 | cpu_relax(); |
@@ -426,32 +372,30 @@ static void u16_writer(struct driver_data *drv_data) | |||
426 | dev_dbg(&drv_data->pdev->dev, | 372 | dev_dbg(&drv_data->pdev->dev, |
427 | "cr16 is 0x%x\n", read_STAT(drv_data)); | 373 | "cr16 is 0x%x\n", read_STAT(drv_data)); |
428 | 374 | ||
429 | /* poll for SPI completion before start */ | ||
430 | while (!(read_STAT(drv_data) & BIT_STAT_SPIF)) | ||
431 | cpu_relax(); | ||
432 | |||
433 | while (drv_data->tx < drv_data->tx_end) { | 375 | while (drv_data->tx < drv_data->tx_end) { |
434 | write_TDBR(drv_data, (*(u16 *) (drv_data->tx))); | 376 | write_TDBR(drv_data, (*(u16 *) (drv_data->tx))); |
435 | while ((read_STAT(drv_data) & BIT_STAT_TXS)) | 377 | while ((read_STAT(drv_data) & BIT_STAT_TXS)) |
436 | cpu_relax(); | 378 | cpu_relax(); |
437 | drv_data->tx += 2; | 379 | drv_data->tx += 2; |
438 | } | 380 | } |
381 | |||
382 | /* poll for SPI completion before return */ | ||
383 | while (!(read_STAT(drv_data) & BIT_STAT_SPIF)) | ||
384 | cpu_relax(); | ||
439 | } | 385 | } |
440 | 386 | ||
441 | static void u16_cs_chg_writer(struct driver_data *drv_data) | 387 | static void u16_cs_chg_writer(struct driver_data *drv_data) |
442 | { | 388 | { |
443 | struct chip_data *chip = drv_data->cur_chip; | 389 | struct chip_data *chip = drv_data->cur_chip; |
444 | 390 | ||
445 | /* poll for SPI completion before start */ | ||
446 | while (!(read_STAT(drv_data) & BIT_STAT_SPIF)) | ||
447 | cpu_relax(); | ||
448 | |||
449 | while (drv_data->tx < drv_data->tx_end) { | 391 | while (drv_data->tx < drv_data->tx_end) { |
450 | cs_active(drv_data, chip); | 392 | cs_active(drv_data, chip); |
451 | 393 | ||
452 | write_TDBR(drv_data, (*(u16 *) (drv_data->tx))); | 394 | write_TDBR(drv_data, (*(u16 *) (drv_data->tx))); |
453 | while ((read_STAT(drv_data) & BIT_STAT_TXS)) | 395 | while ((read_STAT(drv_data) & BIT_STAT_TXS)) |
454 | cpu_relax(); | 396 | cpu_relax(); |
397 | while (!(read_STAT(drv_data) & BIT_STAT_SPIF)) | ||
398 | cpu_relax(); | ||
455 | 399 | ||
456 | cs_deactive(drv_data, chip); | 400 | cs_deactive(drv_data, chip); |
457 | 401 | ||
@@ -519,14 +463,10 @@ static void u16_cs_chg_reader(struct driver_data *drv_data) | |||
519 | 463 | ||
520 | static void u16_duplex(struct driver_data *drv_data) | 464 | static void u16_duplex(struct driver_data *drv_data) |
521 | { | 465 | { |
522 | /* poll for SPI completion before start */ | ||
523 | while (!(read_STAT(drv_data) & BIT_STAT_SPIF)) | ||
524 | cpu_relax(); | ||
525 | |||
526 | /* in duplex mode, clk is triggered by writing of TDBR */ | 466 | /* in duplex mode, clk is triggered by writing of TDBR */ |
527 | while (drv_data->tx < drv_data->tx_end) { | 467 | while (drv_data->tx < drv_data->tx_end) { |
528 | write_TDBR(drv_data, (*(u16 *) (drv_data->tx))); | 468 | write_TDBR(drv_data, (*(u16 *) (drv_data->tx))); |
529 | while (read_STAT(drv_data) & BIT_STAT_TXS) | 469 | while (!(read_STAT(drv_data) & BIT_STAT_SPIF)) |
530 | cpu_relax(); | 470 | cpu_relax(); |
531 | while (!(read_STAT(drv_data) & BIT_STAT_RXS)) | 471 | while (!(read_STAT(drv_data) & BIT_STAT_RXS)) |
532 | cpu_relax(); | 472 | cpu_relax(); |
@@ -540,15 +480,11 @@ static void u16_cs_chg_duplex(struct driver_data *drv_data) | |||
540 | { | 480 | { |
541 | struct chip_data *chip = drv_data->cur_chip; | 481 | struct chip_data *chip = drv_data->cur_chip; |
542 | 482 | ||
543 | /* poll for SPI completion before start */ | ||
544 | while (!(read_STAT(drv_data) & BIT_STAT_SPIF)) | ||
545 | cpu_relax(); | ||
546 | |||
547 | while (drv_data->tx < drv_data->tx_end) { | 483 | while (drv_data->tx < drv_data->tx_end) { |
548 | cs_active(drv_data, chip); | 484 | cs_active(drv_data, chip); |
549 | 485 | ||
550 | write_TDBR(drv_data, (*(u16 *) (drv_data->tx))); | 486 | write_TDBR(drv_data, (*(u16 *) (drv_data->tx))); |
551 | while (read_STAT(drv_data) & BIT_STAT_TXS) | 487 | while (!(read_STAT(drv_data) & BIT_STAT_SPIF)) |
552 | cpu_relax(); | 488 | cpu_relax(); |
553 | while (!(read_STAT(drv_data) & BIT_STAT_RXS)) | 489 | while (!(read_STAT(drv_data) & BIT_STAT_RXS)) |
554 | cpu_relax(); | 490 | cpu_relax(); |
@@ -616,7 +552,7 @@ static void giveback(struct driver_data *drv_data) | |||
616 | 552 | ||
617 | static irqreturn_t dma_irq_handler(int irq, void *dev_id) | 553 | static irqreturn_t dma_irq_handler(int irq, void *dev_id) |
618 | { | 554 | { |
619 | struct driver_data *drv_data = (struct driver_data *)dev_id; | 555 | struct driver_data *drv_data = dev_id; |
620 | struct chip_data *chip = drv_data->cur_chip; | 556 | struct chip_data *chip = drv_data->cur_chip; |
621 | struct spi_message *msg = drv_data->cur_msg; | 557 | struct spi_message *msg = drv_data->cur_msg; |
622 | 558 | ||
@@ -978,10 +914,7 @@ static void pump_messages(struct work_struct *work) | |||
978 | 914 | ||
979 | /* Setup the SSP using the per chip configuration */ | 915 | /* Setup the SSP using the per chip configuration */ |
980 | drv_data->cur_chip = spi_get_ctldata(drv_data->cur_msg->spi); | 916 | drv_data->cur_chip = spi_get_ctldata(drv_data->cur_msg->spi); |
981 | if (restore_state(drv_data)) { | 917 | restore_state(drv_data); |
982 | spin_unlock_irqrestore(&drv_data->lock, flags); | ||
983 | return; | ||
984 | }; | ||
985 | 918 | ||
986 | list_del_init(&drv_data->cur_msg->queue); | 919 | list_del_init(&drv_data->cur_msg->queue); |
987 | 920 | ||
@@ -1187,7 +1120,7 @@ static int setup(struct spi_device *spi) | |||
1187 | if ((chip->chip_select_num > 0) | 1120 | if ((chip->chip_select_num > 0) |
1188 | && (chip->chip_select_num <= spi->master->num_chipselect)) | 1121 | && (chip->chip_select_num <= spi->master->num_chipselect)) |
1189 | peripheral_request(ssel[spi->master->bus_num] | 1122 | peripheral_request(ssel[spi->master->bus_num] |
1190 | [chip->chip_select_num-1], DRV_NAME); | 1123 | [chip->chip_select_num-1], spi->modalias); |
1191 | 1124 | ||
1192 | cs_deactive(drv_data, chip); | 1125 | cs_deactive(drv_data, chip); |
1193 | 1126 | ||
diff --git a/drivers/spi/spi_imx.c b/drivers/spi/spi_imx.c index 639963eb1ac1..1b0647124933 100644 --- a/drivers/spi/spi_imx.c +++ b/drivers/spi/spi_imx.c | |||
@@ -1686,17 +1686,6 @@ static void spi_imx_shutdown(struct platform_device *pdev) | |||
1686 | } | 1686 | } |
1687 | 1687 | ||
1688 | #ifdef CONFIG_PM | 1688 | #ifdef CONFIG_PM |
1689 | static int suspend_devices(struct device *dev, void *pm_message) | ||
1690 | { | ||
1691 | pm_message_t *state = pm_message; | ||
1692 | |||
1693 | if (dev->power.power_state.event != state->event) { | ||
1694 | dev_warn(dev, "pm state does not match request\n"); | ||
1695 | return -1; | ||
1696 | } | ||
1697 | |||
1698 | return 0; | ||
1699 | } | ||
1700 | 1689 | ||
1701 | static int spi_imx_suspend(struct platform_device *pdev, pm_message_t state) | 1690 | static int spi_imx_suspend(struct platform_device *pdev, pm_message_t state) |
1702 | { | 1691 | { |
diff --git a/drivers/spi/spi_s3c24xx.c b/drivers/spi/spi_s3c24xx.c index 89d6685a5ca4..6e834b8b9d27 100644 --- a/drivers/spi/spi_s3c24xx.c +++ b/drivers/spi/spi_s3c24xx.c | |||
@@ -237,10 +237,8 @@ static int __init s3c24xx_spi_probe(struct platform_device *pdev) | |||
237 | { | 237 | { |
238 | struct s3c24xx_spi *hw; | 238 | struct s3c24xx_spi *hw; |
239 | struct spi_master *master; | 239 | struct spi_master *master; |
240 | struct spi_board_info *bi; | ||
241 | struct resource *res; | 240 | struct resource *res; |
242 | int err = 0; | 241 | int err = 0; |
243 | int i; | ||
244 | 242 | ||
245 | master = spi_alloc_master(&pdev->dev, sizeof(struct s3c24xx_spi)); | 243 | master = spi_alloc_master(&pdev->dev, sizeof(struct s3c24xx_spi)); |
246 | if (master == NULL) { | 244 | if (master == NULL) { |
@@ -348,16 +346,6 @@ static int __init s3c24xx_spi_probe(struct platform_device *pdev) | |||
348 | goto err_register; | 346 | goto err_register; |
349 | } | 347 | } |
350 | 348 | ||
351 | /* register all the devices associated */ | ||
352 | |||
353 | bi = &hw->pdata->board_info[0]; | ||
354 | for (i = 0; i < hw->pdata->board_size; i++, bi++) { | ||
355 | dev_info(hw->dev, "registering %s\n", bi->modalias); | ||
356 | |||
357 | bi->controller_data = hw; | ||
358 | spi_new_device(master, bi); | ||
359 | } | ||
360 | |||
361 | return 0; | 349 | return 0; |
362 | 350 | ||
363 | err_register: | 351 | err_register: |
diff --git a/drivers/spi/spi_s3c24xx_gpio.c b/drivers/spi/spi_s3c24xx_gpio.c index 109d82c1abc0..82ae7d7eca38 100644 --- a/drivers/spi/spi_s3c24xx_gpio.c +++ b/drivers/spi/spi_s3c24xx_gpio.c | |||
@@ -100,7 +100,6 @@ static int s3c2410_spigpio_probe(struct platform_device *dev) | |||
100 | struct spi_master *master; | 100 | struct spi_master *master; |
101 | struct s3c2410_spigpio *sp; | 101 | struct s3c2410_spigpio *sp; |
102 | int ret; | 102 | int ret; |
103 | int i; | ||
104 | 103 | ||
105 | master = spi_alloc_master(&dev->dev, sizeof(struct s3c2410_spigpio)); | 104 | master = spi_alloc_master(&dev->dev, sizeof(struct s3c2410_spigpio)); |
106 | if (master == NULL) { | 105 | if (master == NULL) { |
@@ -143,17 +142,6 @@ static int s3c2410_spigpio_probe(struct platform_device *dev) | |||
143 | if (ret) | 142 | if (ret) |
144 | goto err_no_bitbang; | 143 | goto err_no_bitbang; |
145 | 144 | ||
146 | /* register the chips to go with the board */ | ||
147 | |||
148 | for (i = 0; i < sp->info->board_size; i++) { | ||
149 | dev_info(&dev->dev, "registering %p: %s\n", | ||
150 | &sp->info->board_info[i], | ||
151 | sp->info->board_info[i].modalias); | ||
152 | |||
153 | sp->info->board_info[i].controller_data = sp; | ||
154 | spi_new_device(master, sp->info->board_info + i); | ||
155 | } | ||
156 | |||
157 | return 0; | 145 | return 0; |
158 | 146 | ||
159 | err_no_bitbang: | 147 | err_no_bitbang: |
diff --git a/drivers/spi/spi_sh_sci.c b/drivers/spi/spi_sh_sci.c new file mode 100644 index 000000000000..3dbe71b16d60 --- /dev/null +++ b/drivers/spi/spi_sh_sci.c | |||
@@ -0,0 +1,205 @@ | |||
1 | /* | ||
2 | * SH SCI SPI interface | ||
3 | * | ||
4 | * Copyright (c) 2008 Magnus Damm | ||
5 | * | ||
6 | * Based on S3C24XX GPIO based SPI driver, which is: | ||
7 | * Copyright (c) 2006 Ben Dooks | ||
8 | * Copyright (c) 2006 Simtec Electronics | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | */ | ||
15 | |||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/init.h> | ||
18 | #include <linux/delay.h> | ||
19 | #include <linux/spinlock.h> | ||
20 | #include <linux/workqueue.h> | ||
21 | #include <linux/platform_device.h> | ||
22 | |||
23 | #include <linux/spi/spi.h> | ||
24 | #include <linux/spi/spi_bitbang.h> | ||
25 | |||
26 | #include <asm/spi.h> | ||
27 | #include <asm/io.h> | ||
28 | |||
29 | struct sh_sci_spi { | ||
30 | struct spi_bitbang bitbang; | ||
31 | |||
32 | void __iomem *membase; | ||
33 | unsigned char val; | ||
34 | struct sh_spi_info *info; | ||
35 | struct platform_device *dev; | ||
36 | }; | ||
37 | |||
38 | #define SCSPTR(sp) (sp->membase + 0x1c) | ||
39 | #define PIN_SCK (1 << 2) | ||
40 | #define PIN_TXD (1 << 0) | ||
41 | #define PIN_RXD PIN_TXD | ||
42 | #define PIN_INIT ((1 << 1) | (1 << 3) | PIN_SCK | PIN_TXD) | ||
43 | |||
44 | static inline void setbits(struct sh_sci_spi *sp, int bits, int on) | ||
45 | { | ||
46 | /* | ||
47 | * We are the only user of SCSPTR so no locking is required. | ||
48 | * Reading bit 2 and 0 in SCSPTR gives pin state as input. | ||
49 | * Writing the same bits sets the output value. | ||
50 | * This makes regular read-modify-write difficult so we | ||
51 | * use sp->val to keep track of the latest register value. | ||
52 | */ | ||
53 | |||
54 | if (on) | ||
55 | sp->val |= bits; | ||
56 | else | ||
57 | sp->val &= ~bits; | ||
58 | |||
59 | iowrite8(sp->val, SCSPTR(sp)); | ||
60 | } | ||
61 | |||
62 | static inline void setsck(struct spi_device *dev, int on) | ||
63 | { | ||
64 | setbits(spi_master_get_devdata(dev->master), PIN_SCK, on); | ||
65 | } | ||
66 | |||
67 | static inline void setmosi(struct spi_device *dev, int on) | ||
68 | { | ||
69 | setbits(spi_master_get_devdata(dev->master), PIN_TXD, on); | ||
70 | } | ||
71 | |||
72 | static inline u32 getmiso(struct spi_device *dev) | ||
73 | { | ||
74 | struct sh_sci_spi *sp = spi_master_get_devdata(dev->master); | ||
75 | |||
76 | return (ioread8(SCSPTR(sp)) & PIN_RXD) ? 1 : 0; | ||
77 | } | ||
78 | |||
79 | #define spidelay(x) ndelay(x) | ||
80 | |||
81 | #define EXPAND_BITBANG_TXRX | ||
82 | #include <linux/spi/spi_bitbang.h> | ||
83 | |||
84 | static u32 sh_sci_spi_txrx_mode0(struct spi_device *spi, | ||
85 | unsigned nsecs, u32 word, u8 bits) | ||
86 | { | ||
87 | return bitbang_txrx_be_cpha0(spi, nsecs, 0, word, bits); | ||
88 | } | ||
89 | |||
90 | static u32 sh_sci_spi_txrx_mode1(struct spi_device *spi, | ||
91 | unsigned nsecs, u32 word, u8 bits) | ||
92 | { | ||
93 | return bitbang_txrx_be_cpha1(spi, nsecs, 0, word, bits); | ||
94 | } | ||
95 | |||
96 | static u32 sh_sci_spi_txrx_mode2(struct spi_device *spi, | ||
97 | unsigned nsecs, u32 word, u8 bits) | ||
98 | { | ||
99 | return bitbang_txrx_be_cpha0(spi, nsecs, 1, word, bits); | ||
100 | } | ||
101 | |||
102 | static u32 sh_sci_spi_txrx_mode3(struct spi_device *spi, | ||
103 | unsigned nsecs, u32 word, u8 bits) | ||
104 | { | ||
105 | return bitbang_txrx_be_cpha1(spi, nsecs, 1, word, bits); | ||
106 | } | ||
107 | |||
108 | static void sh_sci_spi_chipselect(struct spi_device *dev, int value) | ||
109 | { | ||
110 | struct sh_sci_spi *sp = spi_master_get_devdata(dev->master); | ||
111 | |||
112 | if (sp->info && sp->info->chip_select) | ||
113 | (sp->info->chip_select)(sp->info, dev->chip_select, value); | ||
114 | } | ||
115 | |||
116 | static int sh_sci_spi_probe(struct platform_device *dev) | ||
117 | { | ||
118 | struct resource *r; | ||
119 | struct spi_master *master; | ||
120 | struct sh_sci_spi *sp; | ||
121 | int ret; | ||
122 | |||
123 | master = spi_alloc_master(&dev->dev, sizeof(struct sh_sci_spi)); | ||
124 | if (master == NULL) { | ||
125 | dev_err(&dev->dev, "failed to allocate spi master\n"); | ||
126 | ret = -ENOMEM; | ||
127 | goto err0; | ||
128 | } | ||
129 | |||
130 | sp = spi_master_get_devdata(master); | ||
131 | |||
132 | platform_set_drvdata(dev, sp); | ||
133 | sp->info = dev->dev.platform_data; | ||
134 | |||
135 | /* setup spi bitbang adaptor */ | ||
136 | sp->bitbang.master = spi_master_get(master); | ||
137 | sp->bitbang.master->bus_num = sp->info->bus_num; | ||
138 | sp->bitbang.master->num_chipselect = sp->info->num_chipselect; | ||
139 | sp->bitbang.chipselect = sh_sci_spi_chipselect; | ||
140 | |||
141 | sp->bitbang.txrx_word[SPI_MODE_0] = sh_sci_spi_txrx_mode0; | ||
142 | sp->bitbang.txrx_word[SPI_MODE_1] = sh_sci_spi_txrx_mode1; | ||
143 | sp->bitbang.txrx_word[SPI_MODE_2] = sh_sci_spi_txrx_mode2; | ||
144 | sp->bitbang.txrx_word[SPI_MODE_3] = sh_sci_spi_txrx_mode3; | ||
145 | |||
146 | r = platform_get_resource(dev, IORESOURCE_MEM, 0); | ||
147 | if (r == NULL) { | ||
148 | ret = -ENOENT; | ||
149 | goto err1; | ||
150 | } | ||
151 | sp->membase = ioremap(r->start, r->end - r->start + 1); | ||
152 | if (!sp->membase) { | ||
153 | ret = -ENXIO; | ||
154 | goto err1; | ||
155 | } | ||
156 | sp->val = ioread8(SCSPTR(sp)); | ||
157 | setbits(sp, PIN_INIT, 1); | ||
158 | |||
159 | ret = spi_bitbang_start(&sp->bitbang); | ||
160 | if (!ret) | ||
161 | return 0; | ||
162 | |||
163 | setbits(sp, PIN_INIT, 0); | ||
164 | iounmap(sp->membase); | ||
165 | err1: | ||
166 | spi_master_put(sp->bitbang.master); | ||
167 | err0: | ||
168 | return ret; | ||
169 | } | ||
170 | |||
171 | static int sh_sci_spi_remove(struct platform_device *dev) | ||
172 | { | ||
173 | struct sh_sci_spi *sp = platform_get_drvdata(dev); | ||
174 | |||
175 | iounmap(sp->membase); | ||
176 | setbits(sp, PIN_INIT, 0); | ||
177 | spi_bitbang_stop(&sp->bitbang); | ||
178 | spi_master_put(sp->bitbang.master); | ||
179 | return 0; | ||
180 | } | ||
181 | |||
182 | static struct platform_driver sh_sci_spi_drv = { | ||
183 | .probe = sh_sci_spi_probe, | ||
184 | .remove = sh_sci_spi_remove, | ||
185 | .driver = { | ||
186 | .name = "spi_sh_sci", | ||
187 | .owner = THIS_MODULE, | ||
188 | }, | ||
189 | }; | ||
190 | |||
191 | static int __init sh_sci_spi_init(void) | ||
192 | { | ||
193 | return platform_driver_register(&sh_sci_spi_drv); | ||
194 | } | ||
195 | module_init(sh_sci_spi_init); | ||
196 | |||
197 | static void __exit sh_sci_spi_exit(void) | ||
198 | { | ||
199 | platform_driver_unregister(&sh_sci_spi_drv); | ||
200 | } | ||
201 | module_exit(sh_sci_spi_exit); | ||
202 | |||
203 | MODULE_DESCRIPTION("SH SCI SPI Driver"); | ||
204 | MODULE_AUTHOR("Magnus Damm <damm@opensource.se>"); | ||
205 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c index cc246faa3590..2a77e9d42c68 100644 --- a/drivers/uio/uio.c +++ b/drivers/uio/uio.c | |||
@@ -417,30 +417,28 @@ static void uio_vma_close(struct vm_area_struct *vma) | |||
417 | idev->vma_count--; | 417 | idev->vma_count--; |
418 | } | 418 | } |
419 | 419 | ||
420 | static struct page *uio_vma_nopage(struct vm_area_struct *vma, | 420 | static int uio_vma_fault(struct vm_area_struct *vma, struct vm_fault *vmf) |
421 | unsigned long address, int *type) | ||
422 | { | 421 | { |
423 | struct uio_device *idev = vma->vm_private_data; | 422 | struct uio_device *idev = vma->vm_private_data; |
424 | struct page* page = NOPAGE_SIGBUS; | 423 | struct page *page; |
425 | 424 | ||
426 | int mi = uio_find_mem_index(vma); | 425 | int mi = uio_find_mem_index(vma); |
427 | if (mi < 0) | 426 | if (mi < 0) |
428 | return page; | 427 | return VM_FAULT_SIGBUS; |
429 | 428 | ||
430 | if (idev->info->mem[mi].memtype == UIO_MEM_LOGICAL) | 429 | if (idev->info->mem[mi].memtype == UIO_MEM_LOGICAL) |
431 | page = virt_to_page(idev->info->mem[mi].addr); | 430 | page = virt_to_page(idev->info->mem[mi].addr); |
432 | else | 431 | else |
433 | page = vmalloc_to_page((void*)idev->info->mem[mi].addr); | 432 | page = vmalloc_to_page((void*)idev->info->mem[mi].addr); |
434 | get_page(page); | 433 | get_page(page); |
435 | if (type) | 434 | vmf->page = page; |
436 | *type = VM_FAULT_MINOR; | 435 | return 0; |
437 | return page; | ||
438 | } | 436 | } |
439 | 437 | ||
440 | static struct vm_operations_struct uio_vm_ops = { | 438 | static struct vm_operations_struct uio_vm_ops = { |
441 | .open = uio_vma_open, | 439 | .open = uio_vma_open, |
442 | .close = uio_vma_close, | 440 | .close = uio_vma_close, |
443 | .nopage = uio_vma_nopage, | 441 | .fault = uio_vma_fault, |
444 | }; | 442 | }; |
445 | 443 | ||
446 | static int uio_mmap_physical(struct vm_area_struct *vma) | 444 | static int uio_mmap_physical(struct vm_area_struct *vma) |
diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c index f8e711147501..fc65c02306dd 100644 --- a/drivers/video/atmel_lcdfb.c +++ b/drivers/video/atmel_lcdfb.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/fb.h> | 16 | #include <linux/fb.h> |
17 | #include <linux/init.h> | 17 | #include <linux/init.h> |
18 | #include <linux/delay.h> | 18 | #include <linux/delay.h> |
19 | #include <linux/backlight.h> | ||
19 | 20 | ||
20 | #include <asm/arch/board.h> | 21 | #include <asm/arch/board.h> |
21 | #include <asm/arch/cpu.h> | 22 | #include <asm/arch/cpu.h> |
@@ -69,6 +70,107 @@ static void atmel_lcdfb_update_dma2d(struct atmel_lcdfb_info *sinfo, | |||
69 | } | 70 | } |
70 | #endif | 71 | #endif |
71 | 72 | ||
73 | static const u32 contrast_ctr = ATMEL_LCDC_PS_DIV8 | ||
74 | | ATMEL_LCDC_POL_POSITIVE | ||
75 | | ATMEL_LCDC_ENA_PWMENABLE; | ||
76 | |||
77 | #ifdef CONFIG_BACKLIGHT_ATMEL_LCDC | ||
78 | |||
79 | /* some bl->props field just changed */ | ||
80 | static int atmel_bl_update_status(struct backlight_device *bl) | ||
81 | { | ||
82 | struct atmel_lcdfb_info *sinfo = bl_get_data(bl); | ||
83 | int power = sinfo->bl_power; | ||
84 | int brightness = bl->props.brightness; | ||
85 | |||
86 | /* REVISIT there may be a meaningful difference between | ||
87 | * fb_blank and power ... there seem to be some cases | ||
88 | * this doesn't handle correctly. | ||
89 | */ | ||
90 | if (bl->props.fb_blank != sinfo->bl_power) | ||
91 | power = bl->props.fb_blank; | ||
92 | else if (bl->props.power != sinfo->bl_power) | ||
93 | power = bl->props.power; | ||
94 | |||
95 | if (brightness < 0 && power == FB_BLANK_UNBLANK) | ||
96 | brightness = lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_VAL); | ||
97 | else if (power != FB_BLANK_UNBLANK) | ||
98 | brightness = 0; | ||
99 | |||
100 | lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_VAL, brightness); | ||
101 | lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, | ||
102 | brightness ? contrast_ctr : 0); | ||
103 | |||
104 | bl->props.fb_blank = bl->props.power = sinfo->bl_power = power; | ||
105 | |||
106 | return 0; | ||
107 | } | ||
108 | |||
109 | static int atmel_bl_get_brightness(struct backlight_device *bl) | ||
110 | { | ||
111 | struct atmel_lcdfb_info *sinfo = bl_get_data(bl); | ||
112 | |||
113 | return lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_VAL); | ||
114 | } | ||
115 | |||
116 | static struct backlight_ops atmel_lcdc_bl_ops = { | ||
117 | .update_status = atmel_bl_update_status, | ||
118 | .get_brightness = atmel_bl_get_brightness, | ||
119 | }; | ||
120 | |||
121 | static void init_backlight(struct atmel_lcdfb_info *sinfo) | ||
122 | { | ||
123 | struct backlight_device *bl; | ||
124 | |||
125 | sinfo->bl_power = FB_BLANK_UNBLANK; | ||
126 | |||
127 | if (sinfo->backlight) | ||
128 | return; | ||
129 | |||
130 | bl = backlight_device_register("backlight", &sinfo->pdev->dev, | ||
131 | sinfo, &atmel_lcdc_bl_ops); | ||
132 | if (IS_ERR(sinfo->backlight)) { | ||
133 | dev_err(&sinfo->pdev->dev, "error %ld on backlight register\n", | ||
134 | PTR_ERR(bl)); | ||
135 | return; | ||
136 | } | ||
137 | sinfo->backlight = bl; | ||
138 | |||
139 | bl->props.power = FB_BLANK_UNBLANK; | ||
140 | bl->props.fb_blank = FB_BLANK_UNBLANK; | ||
141 | bl->props.max_brightness = 0xff; | ||
142 | bl->props.brightness = atmel_bl_get_brightness(bl); | ||
143 | } | ||
144 | |||
145 | static void exit_backlight(struct atmel_lcdfb_info *sinfo) | ||
146 | { | ||
147 | if (sinfo->backlight) | ||
148 | backlight_device_unregister(sinfo->backlight); | ||
149 | } | ||
150 | |||
151 | #else | ||
152 | |||
153 | static void init_backlight(struct atmel_lcdfb_info *sinfo) | ||
154 | { | ||
155 | dev_warn(&sinfo->pdev->dev, "backlight control is not available\n"); | ||
156 | } | ||
157 | |||
158 | static void exit_backlight(struct atmel_lcdfb_info *sinfo) | ||
159 | { | ||
160 | } | ||
161 | |||
162 | #endif | ||
163 | |||
164 | static void init_contrast(struct atmel_lcdfb_info *sinfo) | ||
165 | { | ||
166 | /* have some default contrast/backlight settings */ | ||
167 | lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, contrast_ctr); | ||
168 | lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_VAL, ATMEL_LCDC_CVAL_DEFAULT); | ||
169 | |||
170 | if (sinfo->lcdcon_is_backlight) | ||
171 | init_backlight(sinfo); | ||
172 | } | ||
173 | |||
72 | 174 | ||
73 | static struct fb_fix_screeninfo atmel_lcdfb_fix __initdata = { | 175 | static struct fb_fix_screeninfo atmel_lcdfb_fix __initdata = { |
74 | .type = FB_TYPE_PACKED_PIXELS, | 176 | .type = FB_TYPE_PACKED_PIXELS, |
@@ -203,6 +305,26 @@ static int atmel_lcdfb_check_var(struct fb_var_screeninfo *var, | |||
203 | var->transp.offset = var->transp.length = 0; | 305 | var->transp.offset = var->transp.length = 0; |
204 | var->xoffset = var->yoffset = 0; | 306 | var->xoffset = var->yoffset = 0; |
205 | 307 | ||
308 | /* Saturate vertical and horizontal timings at maximum values */ | ||
309 | var->vsync_len = min_t(u32, var->vsync_len, | ||
310 | (ATMEL_LCDC_VPW >> ATMEL_LCDC_VPW_OFFSET) + 1); | ||
311 | var->upper_margin = min_t(u32, var->upper_margin, | ||
312 | ATMEL_LCDC_VBP >> ATMEL_LCDC_VBP_OFFSET); | ||
313 | var->lower_margin = min_t(u32, var->lower_margin, | ||
314 | ATMEL_LCDC_VFP); | ||
315 | var->right_margin = min_t(u32, var->right_margin, | ||
316 | (ATMEL_LCDC_HFP >> ATMEL_LCDC_HFP_OFFSET) + 1); | ||
317 | var->hsync_len = min_t(u32, var->hsync_len, | ||
318 | (ATMEL_LCDC_HPW >> ATMEL_LCDC_HPW_OFFSET) + 1); | ||
319 | var->left_margin = min_t(u32, var->left_margin, | ||
320 | ATMEL_LCDC_HBP + 1); | ||
321 | |||
322 | /* Some parameters can't be zero */ | ||
323 | var->vsync_len = max_t(u32, var->vsync_len, 1); | ||
324 | var->right_margin = max_t(u32, var->right_margin, 1); | ||
325 | var->hsync_len = max_t(u32, var->hsync_len, 1); | ||
326 | var->left_margin = max_t(u32, var->left_margin, 1); | ||
327 | |||
206 | switch (var->bits_per_pixel) { | 328 | switch (var->bits_per_pixel) { |
207 | case 1: | 329 | case 1: |
208 | case 2: | 330 | case 2: |
@@ -370,10 +492,6 @@ static int atmel_lcdfb_set_par(struct fb_info *info) | |||
370 | /* Disable all interrupts */ | 492 | /* Disable all interrupts */ |
371 | lcdc_writel(sinfo, ATMEL_LCDC_IDR, ~0UL); | 493 | lcdc_writel(sinfo, ATMEL_LCDC_IDR, ~0UL); |
372 | 494 | ||
373 | /* Set contrast */ | ||
374 | value = ATMEL_LCDC_PS_DIV8 | ATMEL_LCDC_POL_POSITIVE | ATMEL_LCDC_ENA_PWMENABLE; | ||
375 | lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, value); | ||
376 | lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_VAL, ATMEL_LCDC_CVAL_DEFAULT); | ||
377 | /* ...wait for DMA engine to become idle... */ | 495 | /* ...wait for DMA engine to become idle... */ |
378 | while (lcdc_readl(sinfo, ATMEL_LCDC_DMACON) & ATMEL_LCDC_DMABUSY) | 496 | while (lcdc_readl(sinfo, ATMEL_LCDC_DMACON) & ATMEL_LCDC_DMABUSY) |
379 | msleep(10); | 497 | msleep(10); |
@@ -577,6 +695,7 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev) | |||
577 | sinfo->default_monspecs = pdata_sinfo->default_monspecs; | 695 | sinfo->default_monspecs = pdata_sinfo->default_monspecs; |
578 | sinfo->atmel_lcdfb_power_control = pdata_sinfo->atmel_lcdfb_power_control; | 696 | sinfo->atmel_lcdfb_power_control = pdata_sinfo->atmel_lcdfb_power_control; |
579 | sinfo->guard_time = pdata_sinfo->guard_time; | 697 | sinfo->guard_time = pdata_sinfo->guard_time; |
698 | sinfo->lcdcon_is_backlight = pdata_sinfo->lcdcon_is_backlight; | ||
580 | } else { | 699 | } else { |
581 | dev_err(dev, "cannot get default configuration\n"); | 700 | dev_err(dev, "cannot get default configuration\n"); |
582 | goto free_info; | 701 | goto free_info; |
@@ -670,6 +789,9 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev) | |||
670 | goto release_mem; | 789 | goto release_mem; |
671 | } | 790 | } |
672 | 791 | ||
792 | /* Initialize PWM for contrast or backlight ("off") */ | ||
793 | init_contrast(sinfo); | ||
794 | |||
673 | /* interrupt */ | 795 | /* interrupt */ |
674 | ret = request_irq(sinfo->irq_base, atmel_lcdfb_interrupt, 0, pdev->name, info); | 796 | ret = request_irq(sinfo->irq_base, atmel_lcdfb_interrupt, 0, pdev->name, info); |
675 | if (ret) { | 797 | if (ret) { |
@@ -721,6 +843,7 @@ free_cmap: | |||
721 | unregister_irqs: | 843 | unregister_irqs: |
722 | free_irq(sinfo->irq_base, info); | 844 | free_irq(sinfo->irq_base, info); |
723 | unmap_mmio: | 845 | unmap_mmio: |
846 | exit_backlight(sinfo); | ||
724 | iounmap(sinfo->mmio); | 847 | iounmap(sinfo->mmio); |
725 | release_mem: | 848 | release_mem: |
726 | release_mem_region(info->fix.mmio_start, info->fix.mmio_len); | 849 | release_mem_region(info->fix.mmio_start, info->fix.mmio_len); |
@@ -755,6 +878,7 @@ static int __exit atmel_lcdfb_remove(struct platform_device *pdev) | |||
755 | if (!sinfo) | 878 | if (!sinfo) |
756 | return 0; | 879 | return 0; |
757 | 880 | ||
881 | exit_backlight(sinfo); | ||
758 | if (sinfo->atmel_lcdfb_power_control) | 882 | if (sinfo->atmel_lcdfb_power_control) |
759 | sinfo->atmel_lcdfb_power_control(0); | 883 | sinfo->atmel_lcdfb_power_control(0); |
760 | unregister_framebuffer(info); | 884 | unregister_framebuffer(info); |
@@ -781,6 +905,9 @@ static int __exit atmel_lcdfb_remove(struct platform_device *pdev) | |||
781 | 905 | ||
782 | static struct platform_driver atmel_lcdfb_driver = { | 906 | static struct platform_driver atmel_lcdfb_driver = { |
783 | .remove = __exit_p(atmel_lcdfb_remove), | 907 | .remove = __exit_p(atmel_lcdfb_remove), |
908 | |||
909 | // FIXME need suspend, resume | ||
910 | |||
784 | .driver = { | 911 | .driver = { |
785 | .name = "atmel_lcdfb", | 912 | .name = "atmel_lcdfb", |
786 | .owner = THIS_MODULE, | 913 | .owner = THIS_MODULE, |
diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig index 9609a6c676be..924e2551044a 100644 --- a/drivers/video/backlight/Kconfig +++ b/drivers/video/backlight/Kconfig | |||
@@ -50,6 +50,19 @@ config BACKLIGHT_CLASS_DEVICE | |||
50 | To have support for your specific LCD panel you will have to | 50 | To have support for your specific LCD panel you will have to |
51 | select the proper drivers which depend on this option. | 51 | select the proper drivers which depend on this option. |
52 | 52 | ||
53 | config BACKLIGHT_ATMEL_LCDC | ||
54 | bool "Atmel LCDC Contrast-as-Backlight control" | ||
55 | depends on BACKLIGHT_CLASS_DEVICE && FB_ATMEL | ||
56 | default y if MACH_SAM9261EK || MACH_SAM9263EK | ||
57 | help | ||
58 | This provides a backlight control internal to the Atmel LCDC | ||
59 | driver. If the LCD "contrast control" on your board is wired | ||
60 | so it controls the backlight brightness, select this option to | ||
61 | export this as a PWM-based backlight control. | ||
62 | |||
63 | If in doubt, it's safe to enable this option; it doesn't kick | ||
64 | in unless the board's description says it's wired that way. | ||
65 | |||
53 | config BACKLIGHT_CORGI | 66 | config BACKLIGHT_CORGI |
54 | tristate "Generic (aka Sharp Corgi) Backlight Driver" | 67 | tristate "Generic (aka Sharp Corgi) Backlight Driver" |
55 | depends on BACKLIGHT_CLASS_DEVICE | 68 | depends on BACKLIGHT_CLASS_DEVICE |
diff --git a/drivers/video/bf54x-lq043fb.c b/drivers/video/bf54x-lq043fb.c index c8e7427a0bc8..0ce791e6f79c 100644 --- a/drivers/video/bf54x-lq043fb.c +++ b/drivers/video/bf54x-lq043fb.c | |||
@@ -498,8 +498,7 @@ static struct lcd_device *lcd_dev; | |||
498 | 498 | ||
499 | static irqreturn_t bfin_bf54x_irq_error(int irq, void *dev_id) | 499 | static irqreturn_t bfin_bf54x_irq_error(int irq, void *dev_id) |
500 | { | 500 | { |
501 | 501 | /*struct bfin_bf54xfb_info *info = dev_id;*/ | |
502 | /*struct bfin_bf54xfb_info *info = (struct bfin_bf54xfb_info *)dev_id;*/ | ||
503 | 502 | ||
504 | u16 status = bfin_read_EPPI0_STATUS(); | 503 | u16 status = bfin_read_EPPI0_STATUS(); |
505 | 504 | ||
diff --git a/drivers/video/console/bitblit.c b/drivers/video/console/bitblit.c index 308850df16fe..69864b1b3f9e 100644 --- a/drivers/video/console/bitblit.c +++ b/drivers/video/console/bitblit.c | |||
@@ -63,7 +63,7 @@ static void bit_clear(struct vc_data *vc, struct fb_info *info, int sy, | |||
63 | int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; | 63 | int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; |
64 | struct fb_fillrect region; | 64 | struct fb_fillrect region; |
65 | 65 | ||
66 | region.color = attr_bgcol_ec(bgshift, vc); | 66 | region.color = attr_bgcol_ec(bgshift, vc, info); |
67 | region.dx = sx * vc->vc_font.width; | 67 | region.dx = sx * vc->vc_font.width; |
68 | region.dy = sy * vc->vc_font.height; | 68 | region.dy = sy * vc->vc_font.height; |
69 | region.width = width * vc->vc_font.width; | 69 | region.width = width * vc->vc_font.width; |
@@ -213,7 +213,7 @@ static void bit_clear_margins(struct vc_data *vc, struct fb_info *info, | |||
213 | unsigned int bs = info->var.yres - bh; | 213 | unsigned int bs = info->var.yres - bh; |
214 | struct fb_fillrect region; | 214 | struct fb_fillrect region; |
215 | 215 | ||
216 | region.color = attr_bgcol_ec(bgshift, vc); | 216 | region.color = attr_bgcol_ec(bgshift, vc, info); |
217 | region.rop = ROP_COPY; | 217 | region.rop = ROP_COPY; |
218 | 218 | ||
219 | if (rw && !bottom_only) { | 219 | if (rw && !bottom_only) { |
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index 0f32f4a00b2d..022282494d3f 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c | |||
@@ -84,7 +84,7 @@ | |||
84 | #ifdef CONFIG_MAC | 84 | #ifdef CONFIG_MAC |
85 | #include <asm/macints.h> | 85 | #include <asm/macints.h> |
86 | #endif | 86 | #endif |
87 | #if defined(__mc68000__) || defined(CONFIG_APUS) | 87 | #if defined(__mc68000__) |
88 | #include <asm/machdep.h> | 88 | #include <asm/machdep.h> |
89 | #include <asm/setup.h> | 89 | #include <asm/setup.h> |
90 | #endif | 90 | #endif |
@@ -147,7 +147,7 @@ static char fontname[40]; | |||
147 | static int info_idx = -1; | 147 | static int info_idx = -1; |
148 | 148 | ||
149 | /* console rotation */ | 149 | /* console rotation */ |
150 | static int rotate; | 150 | static int initial_rotation; |
151 | static int fbcon_has_sysfs; | 151 | static int fbcon_has_sysfs; |
152 | 152 | ||
153 | static const struct consw fb_con; | 153 | static const struct consw fb_con; |
@@ -334,10 +334,7 @@ static inline int get_color(struct vc_data *vc, struct fb_info *info, | |||
334 | switch (depth) { | 334 | switch (depth) { |
335 | case 1: | 335 | case 1: |
336 | { | 336 | { |
337 | int col = ~(0xfff << (max(info->var.green.length, | 337 | int col = mono_col(info); |
338 | max(info->var.red.length, | ||
339 | info->var.blue.length)))) & 0xff; | ||
340 | |||
341 | /* 0 or 1 */ | 338 | /* 0 or 1 */ |
342 | int fg = (info->fix.visual != FB_VISUAL_MONO01) ? col : 0; | 339 | int fg = (info->fix.visual != FB_VISUAL_MONO01) ? col : 0; |
343 | int bg = (info->fix.visual != FB_VISUAL_MONO01) ? 0 : col; | 340 | int bg = (info->fix.visual != FB_VISUAL_MONO01) ? 0 : col; |
@@ -537,9 +534,9 @@ static int __init fb_console_setup(char *this_opt) | |||
537 | if (!strncmp(options, "rotate:", 7)) { | 534 | if (!strncmp(options, "rotate:", 7)) { |
538 | options += 7; | 535 | options += 7; |
539 | if (*options) | 536 | if (*options) |
540 | rotate = simple_strtoul(options, &options, 0); | 537 | initial_rotation = simple_strtoul(options, &options, 0); |
541 | if (rotate > 3) | 538 | if (initial_rotation > 3) |
542 | rotate = 0; | 539 | initial_rotation = 0; |
543 | } | 540 | } |
544 | } | 541 | } |
545 | return 1; | 542 | return 1; |
@@ -989,7 +986,7 @@ static const char *fbcon_startup(void) | |||
989 | ops->graphics = 1; | 986 | ops->graphics = 1; |
990 | ops->cur_rotate = -1; | 987 | ops->cur_rotate = -1; |
991 | info->fbcon_par = ops; | 988 | info->fbcon_par = ops; |
992 | p->con_rotate = rotate; | 989 | p->con_rotate = initial_rotation; |
993 | set_blitting_type(vc, info); | 990 | set_blitting_type(vc, info); |
994 | 991 | ||
995 | if (info->fix.type != FB_TYPE_TEXT) { | 992 | if (info->fix.type != FB_TYPE_TEXT) { |
@@ -1176,7 +1173,7 @@ static void fbcon_init(struct vc_data *vc, int init) | |||
1176 | con_copy_unimap(vc, svc); | 1173 | con_copy_unimap(vc, svc); |
1177 | 1174 | ||
1178 | ops = info->fbcon_par; | 1175 | ops = info->fbcon_par; |
1179 | p->con_rotate = rotate; | 1176 | p->con_rotate = initial_rotation; |
1180 | set_blitting_type(vc, info); | 1177 | set_blitting_type(vc, info); |
1181 | 1178 | ||
1182 | cols = vc->vc_cols; | 1179 | cols = vc->vc_cols; |
@@ -2795,7 +2792,7 @@ static int fbcon_scrolldelta(struct vc_data *vc, int lines) | |||
2795 | { | 2792 | { |
2796 | struct fb_info *info = registered_fb[con2fb_map[fg_console]]; | 2793 | struct fb_info *info = registered_fb[con2fb_map[fg_console]]; |
2797 | struct fbcon_ops *ops = info->fbcon_par; | 2794 | struct fbcon_ops *ops = info->fbcon_par; |
2798 | struct display *p = &fb_display[fg_console]; | 2795 | struct display *disp = &fb_display[fg_console]; |
2799 | int offset, limit, scrollback_old; | 2796 | int offset, limit, scrollback_old; |
2800 | 2797 | ||
2801 | if (softback_top) { | 2798 | if (softback_top) { |
@@ -2833,7 +2830,7 @@ static int fbcon_scrolldelta(struct vc_data *vc, int lines) | |||
2833 | logo_shown = FBCON_LOGO_CANSHOW; | 2830 | logo_shown = FBCON_LOGO_CANSHOW; |
2834 | } | 2831 | } |
2835 | fbcon_cursor(vc, CM_ERASE | CM_SOFTBACK); | 2832 | fbcon_cursor(vc, CM_ERASE | CM_SOFTBACK); |
2836 | fbcon_redraw_softback(vc, p, lines); | 2833 | fbcon_redraw_softback(vc, disp, lines); |
2837 | fbcon_cursor(vc, CM_DRAW | CM_SOFTBACK); | 2834 | fbcon_cursor(vc, CM_DRAW | CM_SOFTBACK); |
2838 | return 0; | 2835 | return 0; |
2839 | } | 2836 | } |
@@ -2855,9 +2852,9 @@ static int fbcon_scrolldelta(struct vc_data *vc, int lines) | |||
2855 | 2852 | ||
2856 | fbcon_cursor(vc, CM_ERASE); | 2853 | fbcon_cursor(vc, CM_ERASE); |
2857 | 2854 | ||
2858 | offset = p->yscroll - scrollback_current; | 2855 | offset = disp->yscroll - scrollback_current; |
2859 | limit = p->vrows; | 2856 | limit = disp->vrows; |
2860 | switch (p->scrollmode) { | 2857 | switch (disp->scrollmode) { |
2861 | case SCROLL_WRAP_MOVE: | 2858 | case SCROLL_WRAP_MOVE: |
2862 | info->var.vmode |= FB_VMODE_YWRAP; | 2859 | info->var.vmode |= FB_VMODE_YWRAP; |
2863 | break; | 2860 | break; |
diff --git a/drivers/video/console/fbcon.h b/drivers/video/console/fbcon.h index 8e6ef4bc7a5c..3706307e70ed 100644 --- a/drivers/video/console/fbcon.h +++ b/drivers/video/console/fbcon.h | |||
@@ -93,10 +93,6 @@ struct fbcon_ops { | |||
93 | (((s) >> (fgshift)) & 0x0f) | 93 | (((s) >> (fgshift)) & 0x0f) |
94 | #define attr_bgcol(bgshift,s) \ | 94 | #define attr_bgcol(bgshift,s) \ |
95 | (((s) >> (bgshift)) & 0x0f) | 95 | (((s) >> (bgshift)) & 0x0f) |
96 | #define attr_bgcol_ec(bgshift,vc) \ | ||
97 | ((vc) ? (((vc)->vc_video_erase_char >> (bgshift)) & 0x0f) : 0) | ||
98 | #define attr_fgcol_ec(fgshift,vc) \ | ||
99 | ((vc) ? (((vc)->vc_video_erase_char >> (fgshift)) & 0x0f) : 0) | ||
100 | 96 | ||
101 | /* Monochrome */ | 97 | /* Monochrome */ |
102 | #define attr_bold(s) \ | 98 | #define attr_bold(s) \ |
@@ -108,6 +104,49 @@ struct fbcon_ops { | |||
108 | #define attr_blink(s) \ | 104 | #define attr_blink(s) \ |
109 | ((s) & 0x8000) | 105 | ((s) & 0x8000) |
110 | 106 | ||
107 | #define mono_col(info) \ | ||
108 | (~(0xfff << (max((info)->var.green.length, \ | ||
109 | max((info)->var.red.length, \ | ||
110 | (info)->var.blue.length)))) & 0xff) | ||
111 | |||
112 | static inline int attr_col_ec(int shift, struct vc_data *vc, | ||
113 | struct fb_info *info, int is_fg) | ||
114 | { | ||
115 | int is_mono01; | ||
116 | int col; | ||
117 | int fg; | ||
118 | int bg; | ||
119 | |||
120 | if (!vc) | ||
121 | return 0; | ||
122 | |||
123 | if (vc->vc_can_do_color) | ||
124 | return is_fg ? attr_fgcol(shift,vc->vc_video_erase_char) | ||
125 | : attr_bgcol(shift,vc->vc_video_erase_char); | ||
126 | |||
127 | if (!info) | ||
128 | return 0; | ||
129 | |||
130 | col = mono_col(info); | ||
131 | is_mono01 = info->fix.visual == FB_VISUAL_MONO01; | ||
132 | |||
133 | if (attr_reverse(vc->vc_video_erase_char)) { | ||
134 | fg = is_mono01 ? col : 0; | ||
135 | bg = is_mono01 ? 0 : col; | ||
136 | } | ||
137 | else { | ||
138 | fg = is_mono01 ? 0 : col; | ||
139 | bg = is_mono01 ? col : 0; | ||
140 | } | ||
141 | |||
142 | return is_fg ? fg : bg; | ||
143 | } | ||
144 | |||
145 | #define attr_bgcol_ec(bgshift,vc,info) \ | ||
146 | attr_col_ec(bgshift,vc,info,0); | ||
147 | #define attr_fgcol_ec(fgshift,vc,info) \ | ||
148 | attr_col_ec(fgshift,vc,info,1); | ||
149 | |||
111 | /* Font */ | 150 | /* Font */ |
112 | #define REFCOUNT(fd) (((int *)(fd))[-1]) | 151 | #define REFCOUNT(fd) (((int *)(fd))[-1]) |
113 | #define FNTSIZE(fd) (((int *)(fd))[-2]) | 152 | #define FNTSIZE(fd) (((int *)(fd))[-2]) |
diff --git a/drivers/video/console/fbcon_ccw.c b/drivers/video/console/fbcon_ccw.c index 825e6d6972a7..bdf913ecf001 100644 --- a/drivers/video/console/fbcon_ccw.c +++ b/drivers/video/console/fbcon_ccw.c | |||
@@ -84,7 +84,7 @@ static void ccw_clear(struct vc_data *vc, struct fb_info *info, int sy, | |||
84 | int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; | 84 | int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; |
85 | u32 vyres = GETVYRES(ops->p->scrollmode, info); | 85 | u32 vyres = GETVYRES(ops->p->scrollmode, info); |
86 | 86 | ||
87 | region.color = attr_bgcol_ec(bgshift,vc); | 87 | region.color = attr_bgcol_ec(bgshift,vc,info); |
88 | region.dx = sy * vc->vc_font.height; | 88 | region.dx = sy * vc->vc_font.height; |
89 | region.dy = vyres - ((sx + width) * vc->vc_font.width); | 89 | region.dy = vyres - ((sx + width) * vc->vc_font.width); |
90 | region.height = width * vc->vc_font.width; | 90 | region.height = width * vc->vc_font.width; |
@@ -198,7 +198,7 @@ static void ccw_clear_margins(struct vc_data *vc, struct fb_info *info, | |||
198 | struct fb_fillrect region; | 198 | struct fb_fillrect region; |
199 | int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; | 199 | int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; |
200 | 200 | ||
201 | region.color = attr_bgcol_ec(bgshift,vc); | 201 | region.color = attr_bgcol_ec(bgshift,vc,info); |
202 | region.rop = ROP_COPY; | 202 | region.rop = ROP_COPY; |
203 | 203 | ||
204 | if (rw && !bottom_only) { | 204 | if (rw && !bottom_only) { |
diff --git a/drivers/video/console/fbcon_cw.c b/drivers/video/console/fbcon_cw.c index c637e6318803..a6819b9d1770 100644 --- a/drivers/video/console/fbcon_cw.c +++ b/drivers/video/console/fbcon_cw.c | |||
@@ -70,7 +70,7 @@ static void cw_clear(struct vc_data *vc, struct fb_info *info, int sy, | |||
70 | int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; | 70 | int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; |
71 | u32 vxres = GETVXRES(ops->p->scrollmode, info); | 71 | u32 vxres = GETVXRES(ops->p->scrollmode, info); |
72 | 72 | ||
73 | region.color = attr_bgcol_ec(bgshift,vc); | 73 | region.color = attr_bgcol_ec(bgshift,vc,info); |
74 | region.dx = vxres - ((sy + height) * vc->vc_font.height); | 74 | region.dx = vxres - ((sy + height) * vc->vc_font.height); |
75 | region.dy = sx * vc->vc_font.width; | 75 | region.dy = sx * vc->vc_font.width; |
76 | region.height = width * vc->vc_font.width; | 76 | region.height = width * vc->vc_font.width; |
@@ -182,7 +182,7 @@ static void cw_clear_margins(struct vc_data *vc, struct fb_info *info, | |||
182 | struct fb_fillrect region; | 182 | struct fb_fillrect region; |
183 | int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; | 183 | int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; |
184 | 184 | ||
185 | region.color = attr_bgcol_ec(bgshift,vc); | 185 | region.color = attr_bgcol_ec(bgshift,vc,info); |
186 | region.rop = ROP_COPY; | 186 | region.rop = ROP_COPY; |
187 | 187 | ||
188 | if (rw && !bottom_only) { | 188 | if (rw && !bottom_only) { |
diff --git a/drivers/video/console/fbcon_ud.c b/drivers/video/console/fbcon_ud.c index 1473506df5d0..d9b5d6eb68a7 100644 --- a/drivers/video/console/fbcon_ud.c +++ b/drivers/video/console/fbcon_ud.c | |||
@@ -71,7 +71,7 @@ static void ud_clear(struct vc_data *vc, struct fb_info *info, int sy, | |||
71 | u32 vyres = GETVYRES(ops->p->scrollmode, info); | 71 | u32 vyres = GETVYRES(ops->p->scrollmode, info); |
72 | u32 vxres = GETVXRES(ops->p->scrollmode, info); | 72 | u32 vxres = GETVXRES(ops->p->scrollmode, info); |
73 | 73 | ||
74 | region.color = attr_bgcol_ec(bgshift,vc); | 74 | region.color = attr_bgcol_ec(bgshift,vc,info); |
75 | region.dy = vyres - ((sy + height) * vc->vc_font.height); | 75 | region.dy = vyres - ((sy + height) * vc->vc_font.height); |
76 | region.dx = vxres - ((sx + width) * vc->vc_font.width); | 76 | region.dx = vxres - ((sx + width) * vc->vc_font.width); |
77 | region.width = width * vc->vc_font.width; | 77 | region.width = width * vc->vc_font.width; |
@@ -228,7 +228,7 @@ static void ud_clear_margins(struct vc_data *vc, struct fb_info *info, | |||
228 | struct fb_fillrect region; | 228 | struct fb_fillrect region; |
229 | int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; | 229 | int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; |
230 | 230 | ||
231 | region.color = attr_bgcol_ec(bgshift,vc); | 231 | region.color = attr_bgcol_ec(bgshift,vc,info); |
232 | region.rop = ROP_COPY; | 232 | region.rop = ROP_COPY; |
233 | 233 | ||
234 | if (rw && !bottom_only) { | 234 | if (rw && !bottom_only) { |
diff --git a/drivers/video/console/fonts.c b/drivers/video/console/fonts.c index 96979c377518..d0c03fd70871 100644 --- a/drivers/video/console/fonts.c +++ b/drivers/video/console/fonts.c | |||
@@ -15,7 +15,7 @@ | |||
15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
16 | #include <linux/types.h> | 16 | #include <linux/types.h> |
17 | #include <linux/string.h> | 17 | #include <linux/string.h> |
18 | #if defined(__mc68000__) || defined(CONFIG_APUS) | 18 | #if defined(__mc68000__) |
19 | #include <asm/setup.h> | 19 | #include <asm/setup.h> |
20 | #endif | 20 | #endif |
21 | #include <linux/font.h> | 21 | #include <linux/font.h> |
@@ -120,7 +120,7 @@ const struct font_desc *get_default_font(int xres, int yres, u32 font_w, | |||
120 | for(i=0; i<num_fonts; i++) { | 120 | for(i=0; i<num_fonts; i++) { |
121 | f = fonts[i]; | 121 | f = fonts[i]; |
122 | c = f->pref; | 122 | c = f->pref; |
123 | #if defined(__mc68000__) || defined(CONFIG_APUS) | 123 | #if defined(__mc68000__) |
124 | #ifdef CONFIG_FONT_PEARL_8x8 | 124 | #ifdef CONFIG_FONT_PEARL_8x8 |
125 | if (MACH_IS_AMIGA && f->idx == PEARL8x8_IDX) | 125 | if (MACH_IS_AMIGA && f->idx == PEARL8x8_IDX) |
126 | c = 100; | 126 | c = 100; |
diff --git a/drivers/video/console/tileblit.c b/drivers/video/console/tileblit.c index d981fe4d86c6..0056a41e5c35 100644 --- a/drivers/video/console/tileblit.c +++ b/drivers/video/console/tileblit.c | |||
@@ -40,8 +40,8 @@ static void tile_clear(struct vc_data *vc, struct fb_info *info, int sy, | |||
40 | 40 | ||
41 | rect.index = vc->vc_video_erase_char & | 41 | rect.index = vc->vc_video_erase_char & |
42 | ((vc->vc_hi_font_mask) ? 0x1ff : 0xff); | 42 | ((vc->vc_hi_font_mask) ? 0x1ff : 0xff); |
43 | rect.fg = attr_fgcol_ec(fgshift, vc); | 43 | rect.fg = attr_fgcol_ec(fgshift, vc, info); |
44 | rect.bg = attr_bgcol_ec(bgshift, vc); | 44 | rect.bg = attr_bgcol_ec(bgshift, vc, info); |
45 | rect.sx = sx; | 45 | rect.sx = sx; |
46 | rect.sy = sy; | 46 | rect.sy = sy; |
47 | rect.width = width; | 47 | rect.width = width; |
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c index f65bcd314d54..6df29a62d720 100644 --- a/drivers/video/console/vgacon.c +++ b/drivers/video/console/vgacon.c | |||
@@ -1153,8 +1153,6 @@ static int vgacon_do_font_op(struct vgastate *state,char *arg,int set,int ch512) | |||
1153 | 1153 | ||
1154 | /* if 512 char mode is already enabled don't re-enable it. */ | 1154 | /* if 512 char mode is already enabled don't re-enable it. */ |
1155 | if ((set) && (ch512 != vga_512_chars)) { | 1155 | if ((set) && (ch512 != vga_512_chars)) { |
1156 | int i; | ||
1157 | |||
1158 | /* attribute controller */ | 1156 | /* attribute controller */ |
1159 | for (i = 0; i < MAX_NR_CONSOLES; i++) { | 1157 | for (i = 0; i < MAX_NR_CONSOLES; i++) { |
1160 | struct vc_data *c = vc_cons[i].d; | 1158 | struct vc_data *c = vc_cons[i].d; |
diff --git a/drivers/video/fb_defio.c b/drivers/video/fb_defio.c index a0c5d9d90d74..0f8cfb988c90 100644 --- a/drivers/video/fb_defio.c +++ b/drivers/video/fb_defio.c | |||
@@ -25,8 +25,8 @@ | |||
25 | #include <linux/pagemap.h> | 25 | #include <linux/pagemap.h> |
26 | 26 | ||
27 | /* this is to find and return the vmalloc-ed fb pages */ | 27 | /* this is to find and return the vmalloc-ed fb pages */ |
28 | static struct page* fb_deferred_io_nopage(struct vm_area_struct *vma, | 28 | static int fb_deferred_io_fault(struct vm_area_struct *vma, |
29 | unsigned long vaddr, int *type) | 29 | struct vm_fault *vmf) |
30 | { | 30 | { |
31 | unsigned long offset; | 31 | unsigned long offset; |
32 | struct page *page; | 32 | struct page *page; |
@@ -34,18 +34,17 @@ static struct page* fb_deferred_io_nopage(struct vm_area_struct *vma, | |||
34 | /* info->screen_base is in System RAM */ | 34 | /* info->screen_base is in System RAM */ |
35 | void *screen_base = (void __force *) info->screen_base; | 35 | void *screen_base = (void __force *) info->screen_base; |
36 | 36 | ||
37 | offset = (vaddr - vma->vm_start) + (vma->vm_pgoff << PAGE_SHIFT); | 37 | offset = vmf->pgoff << PAGE_SHIFT; |
38 | if (offset >= info->fix.smem_len) | 38 | if (offset >= info->fix.smem_len) |
39 | return NOPAGE_SIGBUS; | 39 | return VM_FAULT_SIGBUS; |
40 | 40 | ||
41 | page = vmalloc_to_page(screen_base + offset); | 41 | page = vmalloc_to_page(screen_base + offset); |
42 | if (!page) | 42 | if (!page) |
43 | return NOPAGE_OOM; | 43 | return VM_FAULT_SIGBUS; |
44 | 44 | ||
45 | get_page(page); | 45 | get_page(page); |
46 | if (type) | 46 | vmf->page = page; |
47 | *type = VM_FAULT_MINOR; | 47 | return 0; |
48 | return page; | ||
49 | } | 48 | } |
50 | 49 | ||
51 | int fb_deferred_io_fsync(struct file *file, struct dentry *dentry, int datasync) | 50 | int fb_deferred_io_fsync(struct file *file, struct dentry *dentry, int datasync) |
@@ -84,7 +83,7 @@ static int fb_deferred_io_mkwrite(struct vm_area_struct *vma, | |||
84 | } | 83 | } |
85 | 84 | ||
86 | static struct vm_operations_struct fb_deferred_io_vm_ops = { | 85 | static struct vm_operations_struct fb_deferred_io_vm_ops = { |
87 | .nopage = fb_deferred_io_nopage, | 86 | .fault = fb_deferred_io_fault, |
88 | .page_mkwrite = fb_deferred_io_mkwrite, | 87 | .page_mkwrite = fb_deferred_io_mkwrite, |
89 | }; | 88 | }; |
90 | 89 | ||
diff --git a/drivers/video/fb_draw.h b/drivers/video/fb_draw.h index cdafbe14ef1f..a2a0618d86a5 100644 --- a/drivers/video/fb_draw.h +++ b/drivers/video/fb_draw.h | |||
@@ -91,6 +91,7 @@ static inline unsigned long fb_rev_pixels_in_long(unsigned long val, | |||
91 | val = comp(val >> 2, val << 2, REV_PIXELS_MASK2); | 91 | val = comp(val >> 2, val << 2, REV_PIXELS_MASK2); |
92 | if (bswapmask & 3) | 92 | if (bswapmask & 3) |
93 | val = comp(val >> 4, val << 4, REV_PIXELS_MASK4); | 93 | val = comp(val >> 4, val << 4, REV_PIXELS_MASK4); |
94 | return val; | ||
94 | } | 95 | } |
95 | 96 | ||
96 | static inline u32 fb_shifted_pixels_mask_u32(u32 index, u32 bswapmask) | 97 | static inline u32 fb_shifted_pixels_mask_u32(u32 index, u32 bswapmask) |
diff --git a/drivers/video/fbmon.c b/drivers/video/fbmon.c index 4ba9c0894416..052e18058498 100644 --- a/drivers/video/fbmon.c +++ b/drivers/video/fbmon.c | |||
@@ -4,7 +4,7 @@ | |||
4 | * Copyright (C) 2002 James Simmons <jsimmons@users.sf.net> | 4 | * Copyright (C) 2002 James Simmons <jsimmons@users.sf.net> |
5 | * | 5 | * |
6 | * Credits: | 6 | * Credits: |
7 | * | 7 | * |
8 | * The EDID Parser is a conglomeration from the following sources: | 8 | * The EDID Parser is a conglomeration from the following sources: |
9 | * | 9 | * |
10 | * 1. SciTech SNAP Graphics Architecture | 10 | * 1. SciTech SNAP Graphics Architecture |
@@ -12,13 +12,13 @@ | |||
12 | * | 12 | * |
13 | * 2. XFree86 4.3.0, interpret_edid.c | 13 | * 2. XFree86 4.3.0, interpret_edid.c |
14 | * Copyright 1998 by Egbert Eich <Egbert.Eich@Physik.TU-Darmstadt.DE> | 14 | * Copyright 1998 by Egbert Eich <Egbert.Eich@Physik.TU-Darmstadt.DE> |
15 | * | 15 | * |
16 | * 3. John Fremlin <vii@users.sourceforge.net> and | 16 | * 3. John Fremlin <vii@users.sourceforge.net> and |
17 | * Ani Joshi <ajoshi@unixbox.com> | 17 | * Ani Joshi <ajoshi@unixbox.com> |
18 | * | 18 | * |
19 | * Generalized Timing Formula is derived from: | 19 | * Generalized Timing Formula is derived from: |
20 | * | 20 | * |
21 | * GTF Spreadsheet by Andy Morrish (1/5/97) | 21 | * GTF Spreadsheet by Andy Morrish (1/5/97) |
22 | * available at http://www.vesa.org | 22 | * available at http://www.vesa.org |
23 | * | 23 | * |
24 | * This file is subject to the terms and conditions of the GNU General Public | 24 | * This file is subject to the terms and conditions of the GNU General Public |
@@ -36,7 +36,7 @@ | |||
36 | #endif | 36 | #endif |
37 | #include "edid.h" | 37 | #include "edid.h" |
38 | 38 | ||
39 | /* | 39 | /* |
40 | * EDID parser | 40 | * EDID parser |
41 | */ | 41 | */ |
42 | 42 | ||
@@ -160,8 +160,8 @@ static int check_edid(unsigned char *edid) | |||
160 | for (i = 0; i < ARRAY_SIZE(brokendb); i++) { | 160 | for (i = 0; i < ARRAY_SIZE(brokendb); i++) { |
161 | if (!strncmp(manufacturer, brokendb[i].manufacturer, 4) && | 161 | if (!strncmp(manufacturer, brokendb[i].manufacturer, 4) && |
162 | brokendb[i].model == model) { | 162 | brokendb[i].model == model) { |
163 | fix = brokendb[i].fix; | 163 | fix = brokendb[i].fix; |
164 | break; | 164 | break; |
165 | } | 165 | } |
166 | } | 166 | } |
167 | 167 | ||
@@ -323,7 +323,7 @@ static void get_dpms_capabilities(unsigned char flags, | |||
323 | (flags & DPMS_SUSPEND) ? "yes" : "no", | 323 | (flags & DPMS_SUSPEND) ? "yes" : "no", |
324 | (flags & DPMS_STANDBY) ? "yes" : "no"); | 324 | (flags & DPMS_STANDBY) ? "yes" : "no"); |
325 | } | 325 | } |
326 | 326 | ||
327 | static void get_chroma(unsigned char *block, struct fb_monspecs *specs) | 327 | static void get_chroma(unsigned char *block, struct fb_monspecs *specs) |
328 | { | 328 | { |
329 | int tmp; | 329 | int tmp; |
@@ -365,7 +365,7 @@ static void get_chroma(unsigned char *block, struct fb_monspecs *specs) | |||
365 | tmp += 512; | 365 | tmp += 512; |
366 | specs->chroma.bluey = tmp/1024; | 366 | specs->chroma.bluey = tmp/1024; |
367 | DPRINTK("BlueY: 0.%03d\n", specs->chroma.bluey); | 367 | DPRINTK("BlueY: 0.%03d\n", specs->chroma.bluey); |
368 | 368 | ||
369 | tmp = ((block[6] & (3 << 2)) >> 2) | (block[0xd] << 2); | 369 | tmp = ((block[6] & (3 << 2)) >> 2) | (block[0xd] << 2); |
370 | tmp *= 1000; | 370 | tmp *= 1000; |
371 | tmp += 512; | 371 | tmp += 512; |
@@ -383,7 +383,7 @@ static void calc_mode_timings(int xres, int yres, int refresh, | |||
383 | struct fb_videomode *mode) | 383 | struct fb_videomode *mode) |
384 | { | 384 | { |
385 | struct fb_var_screeninfo *var; | 385 | struct fb_var_screeninfo *var; |
386 | 386 | ||
387 | var = kzalloc(sizeof(struct fb_var_screeninfo), GFP_KERNEL); | 387 | var = kzalloc(sizeof(struct fb_var_screeninfo), GFP_KERNEL); |
388 | 388 | ||
389 | if (var) { | 389 | if (var) { |
@@ -451,11 +451,11 @@ static int get_est_timing(unsigned char *block, struct fb_videomode *mode) | |||
451 | 451 | ||
452 | c = block[1]; | 452 | c = block[1]; |
453 | if (c&0x80) { | 453 | if (c&0x80) { |
454 | mode[num++] = vesa_modes[9]; | 454 | mode[num++] = vesa_modes[9]; |
455 | DPRINTK(" 800x600@72Hz\n"); | 455 | DPRINTK(" 800x600@72Hz\n"); |
456 | } | 456 | } |
457 | if (c&0x40) { | 457 | if (c&0x40) { |
458 | mode[num++] = vesa_modes[10]; | 458 | mode[num++] = vesa_modes[10]; |
459 | DPRINTK(" 800x600@75Hz\n"); | 459 | DPRINTK(" 800x600@75Hz\n"); |
460 | } | 460 | } |
461 | if (c&0x20) { | 461 | if (c&0x20) { |
@@ -495,7 +495,7 @@ static int get_est_timing(unsigned char *block, struct fb_videomode *mode) | |||
495 | static int get_std_timing(unsigned char *block, struct fb_videomode *mode) | 495 | static int get_std_timing(unsigned char *block, struct fb_videomode *mode) |
496 | { | 496 | { |
497 | int xres, yres = 0, refresh, ratio, i; | 497 | int xres, yres = 0, refresh, ratio, i; |
498 | 498 | ||
499 | xres = (block[0] + 31) * 8; | 499 | xres = (block[0] + 31) * 8; |
500 | if (xres <= 256) | 500 | if (xres <= 256) |
501 | return 0; | 501 | return 0; |
@@ -519,7 +519,7 @@ static int get_std_timing(unsigned char *block, struct fb_videomode *mode) | |||
519 | 519 | ||
520 | DPRINTK(" %dx%d@%dHz\n", xres, yres, refresh); | 520 | DPRINTK(" %dx%d@%dHz\n", xres, yres, refresh); |
521 | for (i = 0; i < VESA_MODEDB_SIZE; i++) { | 521 | for (i = 0; i < VESA_MODEDB_SIZE; i++) { |
522 | if (vesa_modes[i].xres == xres && | 522 | if (vesa_modes[i].xres == xres && |
523 | vesa_modes[i].yres == yres && | 523 | vesa_modes[i].yres == yres && |
524 | vesa_modes[i].refresh == refresh) { | 524 | vesa_modes[i].refresh == refresh) { |
525 | *mode = vesa_modes[i]; | 525 | *mode = vesa_modes[i]; |
@@ -536,13 +536,13 @@ static int get_dst_timing(unsigned char *block, | |||
536 | { | 536 | { |
537 | int j, num = 0; | 537 | int j, num = 0; |
538 | 538 | ||
539 | for (j = 0; j < 6; j++, block+= STD_TIMING_DESCRIPTION_SIZE) | 539 | for (j = 0; j < 6; j++, block += STD_TIMING_DESCRIPTION_SIZE) |
540 | num += get_std_timing(block, &mode[num]); | 540 | num += get_std_timing(block, &mode[num]); |
541 | 541 | ||
542 | return num; | 542 | return num; |
543 | } | 543 | } |
544 | 544 | ||
545 | static void get_detailed_timing(unsigned char *block, | 545 | static void get_detailed_timing(unsigned char *block, |
546 | struct fb_videomode *mode) | 546 | struct fb_videomode *mode) |
547 | { | 547 | { |
548 | mode->xres = H_ACTIVE; | 548 | mode->xres = H_ACTIVE; |
@@ -553,7 +553,7 @@ static void get_detailed_timing(unsigned char *block, | |||
553 | mode->right_margin = H_SYNC_OFFSET; | 553 | mode->right_margin = H_SYNC_OFFSET; |
554 | mode->left_margin = (H_ACTIVE + H_BLANKING) - | 554 | mode->left_margin = (H_ACTIVE + H_BLANKING) - |
555 | (H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH); | 555 | (H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH); |
556 | mode->upper_margin = V_BLANKING - V_SYNC_OFFSET - | 556 | mode->upper_margin = V_BLANKING - V_SYNC_OFFSET - |
557 | V_SYNC_WIDTH; | 557 | V_SYNC_WIDTH; |
558 | mode->lower_margin = V_SYNC_OFFSET; | 558 | mode->lower_margin = V_SYNC_OFFSET; |
559 | mode->hsync_len = H_SYNC_WIDTH; | 559 | mode->hsync_len = H_SYNC_WIDTH; |
@@ -597,7 +597,7 @@ static struct fb_videomode *fb_create_modedb(unsigned char *edid, int *dbsize) | |||
597 | if (mode == NULL) | 597 | if (mode == NULL) |
598 | return NULL; | 598 | return NULL; |
599 | 599 | ||
600 | if (edid == NULL || !edid_checksum(edid) || | 600 | if (edid == NULL || !edid_checksum(edid) || |
601 | !edid_check_header(edid)) { | 601 | !edid_check_header(edid)) { |
602 | kfree(mode); | 602 | kfree(mode); |
603 | return NULL; | 603 | return NULL; |
@@ -632,7 +632,7 @@ static struct fb_videomode *fb_create_modedb(unsigned char *edid, int *dbsize) | |||
632 | if (block[0] == 0x00 && block[1] == 0x00 && block[3] == 0xfa) | 632 | if (block[0] == 0x00 && block[1] == 0x00 && block[3] == 0xfa) |
633 | num += get_dst_timing(block + 5, &mode[num]); | 633 | num += get_dst_timing(block + 5, &mode[num]); |
634 | } | 634 | } |
635 | 635 | ||
636 | /* Yikes, EDID data is totally useless */ | 636 | /* Yikes, EDID data is totally useless */ |
637 | if (!num) { | 637 | if (!num) { |
638 | kfree(mode); | 638 | kfree(mode); |
@@ -686,7 +686,7 @@ static int fb_get_monitor_limits(unsigned char *edid, struct fb_monspecs *specs) | |||
686 | /* estimate monitor limits based on modes supported */ | 686 | /* estimate monitor limits based on modes supported */ |
687 | if (retval) { | 687 | if (retval) { |
688 | struct fb_videomode *modes, *mode; | 688 | struct fb_videomode *modes, *mode; |
689 | int num_modes, i, hz, hscan, pixclock; | 689 | int num_modes, hz, hscan, pixclock; |
690 | int vtotal, htotal; | 690 | int vtotal, htotal; |
691 | 691 | ||
692 | modes = fb_create_modedb(edid, &num_modes); | 692 | modes = fb_create_modedb(edid, &num_modes); |
@@ -713,7 +713,7 @@ static int fb_get_monitor_limits(unsigned char *edid, struct fb_monspecs *specs) | |||
713 | hscan = (pixclock + htotal / 2) / htotal; | 713 | hscan = (pixclock + htotal / 2) / htotal; |
714 | hscan = (hscan + 500) / 1000 * 1000; | 714 | hscan = (hscan + 500) / 1000 * 1000; |
715 | hz = (hscan + vtotal / 2) / vtotal; | 715 | hz = (hscan + vtotal / 2) / vtotal; |
716 | 716 | ||
717 | if (specs->dclkmax == 0 || specs->dclkmax < pixclock) | 717 | if (specs->dclkmax == 0 || specs->dclkmax < pixclock) |
718 | specs->dclkmax = pixclock; | 718 | specs->dclkmax = pixclock; |
719 | 719 | ||
@@ -966,8 +966,8 @@ void fb_edid_to_monspecs(unsigned char *edid, struct fb_monspecs *specs) | |||
966 | DPRINTK("========================================\n"); | 966 | DPRINTK("========================================\n"); |
967 | } | 967 | } |
968 | 968 | ||
969 | /* | 969 | /* |
970 | * VESA Generalized Timing Formula (GTF) | 970 | * VESA Generalized Timing Formula (GTF) |
971 | */ | 971 | */ |
972 | 972 | ||
973 | #define FLYBACK 550 | 973 | #define FLYBACK 550 |
@@ -996,7 +996,7 @@ struct __fb_timings { | |||
996 | * @hfreq: horizontal freq | 996 | * @hfreq: horizontal freq |
997 | * | 997 | * |
998 | * DESCRIPTION: | 998 | * DESCRIPTION: |
999 | * vblank = right_margin + vsync_len + left_margin | 999 | * vblank = right_margin + vsync_len + left_margin |
1000 | * | 1000 | * |
1001 | * given: right_margin = 1 (V_FRONTPORCH) | 1001 | * given: right_margin = 1 (V_FRONTPORCH) |
1002 | * vsync_len = 3 | 1002 | * vsync_len = 3 |
@@ -1010,12 +1010,12 @@ static u32 fb_get_vblank(u32 hfreq) | |||
1010 | { | 1010 | { |
1011 | u32 vblank; | 1011 | u32 vblank; |
1012 | 1012 | ||
1013 | vblank = (hfreq * FLYBACK)/1000; | 1013 | vblank = (hfreq * FLYBACK)/1000; |
1014 | vblank = (vblank + 500)/1000; | 1014 | vblank = (vblank + 500)/1000; |
1015 | return (vblank + V_FRONTPORCH); | 1015 | return (vblank + V_FRONTPORCH); |
1016 | } | 1016 | } |
1017 | 1017 | ||
1018 | /** | 1018 | /** |
1019 | * fb_get_hblank_by_freq - get horizontal blank time given hfreq | 1019 | * fb_get_hblank_by_freq - get horizontal blank time given hfreq |
1020 | * @hfreq: horizontal freq | 1020 | * @hfreq: horizontal freq |
1021 | * @xres: horizontal resolution in pixels | 1021 | * @xres: horizontal resolution in pixels |
@@ -1031,7 +1031,7 @@ static u32 fb_get_vblank(u32 hfreq) | |||
1031 | * | 1031 | * |
1032 | * where: C = ((offset - scale factor) * blank_scale) | 1032 | * where: C = ((offset - scale factor) * blank_scale) |
1033 | * -------------------------------------- + scale factor | 1033 | * -------------------------------------- + scale factor |
1034 | * 256 | 1034 | * 256 |
1035 | * M = blank_scale * gradient | 1035 | * M = blank_scale * gradient |
1036 | * | 1036 | * |
1037 | */ | 1037 | */ |
@@ -1039,7 +1039,7 @@ static u32 fb_get_hblank_by_hfreq(u32 hfreq, u32 xres) | |||
1039 | { | 1039 | { |
1040 | u32 c_val, m_val, duty_cycle, hblank; | 1040 | u32 c_val, m_val, duty_cycle, hblank; |
1041 | 1041 | ||
1042 | c_val = (((H_OFFSET - H_SCALEFACTOR) * H_BLANKSCALE)/256 + | 1042 | c_val = (((H_OFFSET - H_SCALEFACTOR) * H_BLANKSCALE)/256 + |
1043 | H_SCALEFACTOR) * 1000; | 1043 | H_SCALEFACTOR) * 1000; |
1044 | m_val = (H_BLANKSCALE * H_GRADIENT)/256; | 1044 | m_val = (H_BLANKSCALE * H_GRADIENT)/256; |
1045 | m_val = (m_val * 1000000)/hfreq; | 1045 | m_val = (m_val * 1000000)/hfreq; |
@@ -1048,7 +1048,7 @@ static u32 fb_get_hblank_by_hfreq(u32 hfreq, u32 xres) | |||
1048 | return (hblank); | 1048 | return (hblank); |
1049 | } | 1049 | } |
1050 | 1050 | ||
1051 | /** | 1051 | /** |
1052 | * fb_get_hblank_by_dclk - get horizontal blank time given pixelclock | 1052 | * fb_get_hblank_by_dclk - get horizontal blank time given pixelclock |
1053 | * @dclk: pixelclock in Hz | 1053 | * @dclk: pixelclock in Hz |
1054 | * @xres: horizontal resolution in pixels | 1054 | * @xres: horizontal resolution in pixels |
@@ -1061,7 +1061,7 @@ static u32 fb_get_hblank_by_hfreq(u32 hfreq, u32 xres) | |||
1061 | * | 1061 | * |
1062 | * duty cycle = percent of htotal assigned to inactive display | 1062 | * duty cycle = percent of htotal assigned to inactive display |
1063 | * duty cycle = C - (M * h_period) | 1063 | * duty cycle = C - (M * h_period) |
1064 | * | 1064 | * |
1065 | * where: h_period = SQRT(100 - C + (0.4 * xres * M)/dclk) + C - 100 | 1065 | * where: h_period = SQRT(100 - C + (0.4 * xres * M)/dclk) + C - 100 |
1066 | * ----------------------------------------------- | 1066 | * ----------------------------------------------- |
1067 | * 2 * M | 1067 | * 2 * M |
@@ -1077,11 +1077,11 @@ static u32 fb_get_hblank_by_dclk(u32 dclk, u32 xres) | |||
1077 | h_period = 100 - C_VAL; | 1077 | h_period = 100 - C_VAL; |
1078 | h_period *= h_period; | 1078 | h_period *= h_period; |
1079 | h_period += (M_VAL * xres * 2 * 1000)/(5 * dclk); | 1079 | h_period += (M_VAL * xres * 2 * 1000)/(5 * dclk); |
1080 | h_period *=10000; | 1080 | h_period *= 10000; |
1081 | 1081 | ||
1082 | h_period = int_sqrt(h_period); | 1082 | h_period = int_sqrt(h_period); |
1083 | h_period -= (100 - C_VAL) * 100; | 1083 | h_period -= (100 - C_VAL) * 100; |
1084 | h_period *= 1000; | 1084 | h_period *= 1000; |
1085 | h_period /= 2 * M_VAL; | 1085 | h_period /= 2 * M_VAL; |
1086 | 1086 | ||
1087 | duty_cycle = C_VAL * 1000 - (M_VAL * h_period)/100; | 1087 | duty_cycle = C_VAL * 1000 - (M_VAL * h_period)/100; |
@@ -1089,7 +1089,7 @@ static u32 fb_get_hblank_by_dclk(u32 dclk, u32 xres) | |||
1089 | hblank &= ~15; | 1089 | hblank &= ~15; |
1090 | return (hblank); | 1090 | return (hblank); |
1091 | } | 1091 | } |
1092 | 1092 | ||
1093 | /** | 1093 | /** |
1094 | * fb_get_hfreq - estimate hsync | 1094 | * fb_get_hfreq - estimate hsync |
1095 | * @vfreq: vertical refresh rate | 1095 | * @vfreq: vertical refresh rate |
@@ -1100,13 +1100,13 @@ static u32 fb_get_hblank_by_dclk(u32 dclk, u32 xres) | |||
1100 | * (yres + front_port) * vfreq * 1000000 | 1100 | * (yres + front_port) * vfreq * 1000000 |
1101 | * hfreq = ------------------------------------- | 1101 | * hfreq = ------------------------------------- |
1102 | * (1000000 - (vfreq * FLYBACK) | 1102 | * (1000000 - (vfreq * FLYBACK) |
1103 | * | 1103 | * |
1104 | */ | 1104 | */ |
1105 | 1105 | ||
1106 | static u32 fb_get_hfreq(u32 vfreq, u32 yres) | 1106 | static u32 fb_get_hfreq(u32 vfreq, u32 yres) |
1107 | { | 1107 | { |
1108 | u32 divisor, hfreq; | 1108 | u32 divisor, hfreq; |
1109 | 1109 | ||
1110 | divisor = (1000000 - (vfreq * FLYBACK))/1000; | 1110 | divisor = (1000000 - (vfreq * FLYBACK))/1000; |
1111 | hfreq = (yres + V_FRONTPORCH) * vfreq * 1000; | 1111 | hfreq = (yres + V_FRONTPORCH) * vfreq * 1000; |
1112 | return (hfreq/divisor); | 1112 | return (hfreq/divisor); |
@@ -1117,7 +1117,7 @@ static void fb_timings_vfreq(struct __fb_timings *timings) | |||
1117 | timings->hfreq = fb_get_hfreq(timings->vfreq, timings->vactive); | 1117 | timings->hfreq = fb_get_hfreq(timings->vfreq, timings->vactive); |
1118 | timings->vblank = fb_get_vblank(timings->hfreq); | 1118 | timings->vblank = fb_get_vblank(timings->hfreq); |
1119 | timings->vtotal = timings->vactive + timings->vblank; | 1119 | timings->vtotal = timings->vactive + timings->vblank; |
1120 | timings->hblank = fb_get_hblank_by_hfreq(timings->hfreq, | 1120 | timings->hblank = fb_get_hblank_by_hfreq(timings->hfreq, |
1121 | timings->hactive); | 1121 | timings->hactive); |
1122 | timings->htotal = timings->hactive + timings->hblank; | 1122 | timings->htotal = timings->hactive + timings->hblank; |
1123 | timings->dclk = timings->htotal * timings->hfreq; | 1123 | timings->dclk = timings->htotal * timings->hfreq; |
@@ -1128,7 +1128,7 @@ static void fb_timings_hfreq(struct __fb_timings *timings) | |||
1128 | timings->vblank = fb_get_vblank(timings->hfreq); | 1128 | timings->vblank = fb_get_vblank(timings->hfreq); |
1129 | timings->vtotal = timings->vactive + timings->vblank; | 1129 | timings->vtotal = timings->vactive + timings->vblank; |
1130 | timings->vfreq = timings->hfreq/timings->vtotal; | 1130 | timings->vfreq = timings->hfreq/timings->vtotal; |
1131 | timings->hblank = fb_get_hblank_by_hfreq(timings->hfreq, | 1131 | timings->hblank = fb_get_hblank_by_hfreq(timings->hfreq, |
1132 | timings->hactive); | 1132 | timings->hactive); |
1133 | timings->htotal = timings->hactive + timings->hblank; | 1133 | timings->htotal = timings->hactive + timings->hblank; |
1134 | timings->dclk = timings->htotal * timings->hfreq; | 1134 | timings->dclk = timings->htotal * timings->hfreq; |
@@ -1136,7 +1136,7 @@ static void fb_timings_hfreq(struct __fb_timings *timings) | |||
1136 | 1136 | ||
1137 | static void fb_timings_dclk(struct __fb_timings *timings) | 1137 | static void fb_timings_dclk(struct __fb_timings *timings) |
1138 | { | 1138 | { |
1139 | timings->hblank = fb_get_hblank_by_dclk(timings->dclk, | 1139 | timings->hblank = fb_get_hblank_by_dclk(timings->dclk, |
1140 | timings->hactive); | 1140 | timings->hactive); |
1141 | timings->htotal = timings->hactive + timings->hblank; | 1141 | timings->htotal = timings->hactive + timings->hblank; |
1142 | timings->hfreq = timings->dclk/timings->htotal; | 1142 | timings->hfreq = timings->dclk/timings->htotal; |
@@ -1156,29 +1156,29 @@ static void fb_timings_dclk(struct __fb_timings *timings) | |||
1156 | * @info: pointer to fb_info | 1156 | * @info: pointer to fb_info |
1157 | * | 1157 | * |
1158 | * DESCRIPTION: | 1158 | * DESCRIPTION: |
1159 | * Calculates video mode based on monitor specs using VESA GTF. | 1159 | * Calculates video mode based on monitor specs using VESA GTF. |
1160 | * The GTF is best for VESA GTF compliant monitors but is | 1160 | * The GTF is best for VESA GTF compliant monitors but is |
1161 | * specifically formulated to work for older monitors as well. | 1161 | * specifically formulated to work for older monitors as well. |
1162 | * | 1162 | * |
1163 | * If @flag==0, the function will attempt to maximize the | 1163 | * If @flag==0, the function will attempt to maximize the |
1164 | * refresh rate. Otherwise, it will calculate timings based on | 1164 | * refresh rate. Otherwise, it will calculate timings based on |
1165 | * the flag and accompanying value. | 1165 | * the flag and accompanying value. |
1166 | * | 1166 | * |
1167 | * If FB_IGNOREMON bit is set in @flags, monitor specs will be | 1167 | * If FB_IGNOREMON bit is set in @flags, monitor specs will be |
1168 | * ignored and @var will be filled with the calculated timings. | 1168 | * ignored and @var will be filled with the calculated timings. |
1169 | * | 1169 | * |
1170 | * All calculations are based on the VESA GTF Spreadsheet | 1170 | * All calculations are based on the VESA GTF Spreadsheet |
1171 | * available at VESA's public ftp (http://www.vesa.org). | 1171 | * available at VESA's public ftp (http://www.vesa.org). |
1172 | * | 1172 | * |
1173 | * NOTES: | 1173 | * NOTES: |
1174 | * The timings generated by the GTF will be different from VESA | 1174 | * The timings generated by the GTF will be different from VESA |
1175 | * DMT. It might be a good idea to keep a table of standard | 1175 | * DMT. It might be a good idea to keep a table of standard |
1176 | * VESA modes as well. The GTF may also not work for some displays, | 1176 | * VESA modes as well. The GTF may also not work for some displays, |
1177 | * such as, and especially, analog TV. | 1177 | * such as, and especially, analog TV. |
1178 | * | 1178 | * |
1179 | * REQUIRES: | 1179 | * REQUIRES: |
1180 | * A valid info->monspecs, otherwise 'safe numbers' will be used. | 1180 | * A valid info->monspecs, otherwise 'safe numbers' will be used. |
1181 | */ | 1181 | */ |
1182 | int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var, struct fb_info *info) | 1182 | int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var, struct fb_info *info) |
1183 | { | 1183 | { |
1184 | struct __fb_timings *timings; | 1184 | struct __fb_timings *timings; |
@@ -1191,7 +1191,7 @@ int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var, struct fb_inf | |||
1191 | if (!timings) | 1191 | if (!timings) |
1192 | return -ENOMEM; | 1192 | return -ENOMEM; |
1193 | 1193 | ||
1194 | /* | 1194 | /* |
1195 | * If monspecs are invalid, use values that are enough | 1195 | * If monspecs are invalid, use values that are enough |
1196 | * for 640x480@60 | 1196 | * for 640x480@60 |
1197 | */ | 1197 | */ |
@@ -1214,7 +1214,7 @@ int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var, struct fb_inf | |||
1214 | 1214 | ||
1215 | timings->hactive = var->xres; | 1215 | timings->hactive = var->xres; |
1216 | timings->vactive = var->yres; | 1216 | timings->vactive = var->yres; |
1217 | if (var->vmode & FB_VMODE_INTERLACED) { | 1217 | if (var->vmode & FB_VMODE_INTERLACED) { |
1218 | timings->vactive /= 2; | 1218 | timings->vactive /= 2; |
1219 | interlace = 2; | 1219 | interlace = 2; |
1220 | } | 1220 | } |
@@ -1250,9 +1250,9 @@ int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var, struct fb_inf | |||
1250 | break; | 1250 | break; |
1251 | default: | 1251 | default: |
1252 | err = -EINVAL; | 1252 | err = -EINVAL; |
1253 | 1253 | ||
1254 | } | 1254 | } |
1255 | 1255 | ||
1256 | if (err || (!(flags & FB_IGNOREMON) && | 1256 | if (err || (!(flags & FB_IGNOREMON) && |
1257 | (timings->vfreq < vfmin || timings->vfreq > vfmax || | 1257 | (timings->vfreq < vfmin || timings->vfreq > vfmax || |
1258 | timings->hfreq < hfmin || timings->hfreq > hfmax || | 1258 | timings->hfreq < hfmin || timings->hfreq > hfmax || |
@@ -1269,7 +1269,7 @@ int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var, struct fb_inf | |||
1269 | var->upper_margin = (timings->vblank * interlace)/dscan - | 1269 | var->upper_margin = (timings->vblank * interlace)/dscan - |
1270 | (var->vsync_len + var->lower_margin); | 1270 | (var->vsync_len + var->lower_margin); |
1271 | } | 1271 | } |
1272 | 1272 | ||
1273 | kfree(timings); | 1273 | kfree(timings); |
1274 | return err; | 1274 | return err; |
1275 | } | 1275 | } |
@@ -1291,7 +1291,7 @@ int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var, | |||
1291 | return -EINVAL; | 1291 | return -EINVAL; |
1292 | } | 1292 | } |
1293 | #endif /* CONFIG_FB_MODE_HELPERS */ | 1293 | #endif /* CONFIG_FB_MODE_HELPERS */ |
1294 | 1294 | ||
1295 | /* | 1295 | /* |
1296 | * fb_validate_mode - validates var against monitor capabilities | 1296 | * fb_validate_mode - validates var against monitor capabilities |
1297 | * @var: pointer to fb_var_screeninfo | 1297 | * @var: pointer to fb_var_screeninfo |
@@ -1309,7 +1309,7 @@ int fb_validate_mode(const struct fb_var_screeninfo *var, struct fb_info *info) | |||
1309 | u32 hfreq, vfreq, htotal, vtotal, pixclock; | 1309 | u32 hfreq, vfreq, htotal, vtotal, pixclock; |
1310 | u32 hfmin, hfmax, vfmin, vfmax, dclkmin, dclkmax; | 1310 | u32 hfmin, hfmax, vfmin, vfmax, dclkmin, dclkmax; |
1311 | 1311 | ||
1312 | /* | 1312 | /* |
1313 | * If monspecs are invalid, use values that are enough | 1313 | * If monspecs are invalid, use values that are enough |
1314 | * for 640x480@60 | 1314 | * for 640x480@60 |
1315 | */ | 1315 | */ |
@@ -1333,10 +1333,10 @@ int fb_validate_mode(const struct fb_var_screeninfo *var, struct fb_info *info) | |||
1333 | if (!var->pixclock) | 1333 | if (!var->pixclock) |
1334 | return -EINVAL; | 1334 | return -EINVAL; |
1335 | pixclock = PICOS2KHZ(var->pixclock) * 1000; | 1335 | pixclock = PICOS2KHZ(var->pixclock) * 1000; |
1336 | 1336 | ||
1337 | htotal = var->xres + var->right_margin + var->hsync_len + | 1337 | htotal = var->xres + var->right_margin + var->hsync_len + |
1338 | var->left_margin; | 1338 | var->left_margin; |
1339 | vtotal = var->yres + var->lower_margin + var->vsync_len + | 1339 | vtotal = var->yres + var->lower_margin + var->vsync_len + |
1340 | var->upper_margin; | 1340 | var->upper_margin; |
1341 | 1341 | ||
1342 | if (var->vmode & FB_VMODE_INTERLACED) | 1342 | if (var->vmode & FB_VMODE_INTERLACED) |
@@ -1349,7 +1349,7 @@ int fb_validate_mode(const struct fb_var_screeninfo *var, struct fb_info *info) | |||
1349 | 1349 | ||
1350 | vfreq = hfreq/vtotal; | 1350 | vfreq = hfreq/vtotal; |
1351 | 1351 | ||
1352 | return (vfreq < vfmin || vfreq > vfmax || | 1352 | return (vfreq < vfmin || vfreq > vfmax || |
1353 | hfreq < hfmin || hfreq > hfmax || | 1353 | hfreq < hfmin || hfreq > hfmax || |
1354 | pixclock < dclkmin || pixclock > dclkmax) ? | 1354 | pixclock < dclkmin || pixclock > dclkmax) ? |
1355 | -EINVAL : 0; | 1355 | -EINVAL : 0; |
diff --git a/drivers/video/geode/lxfb_core.c b/drivers/video/geode/lxfb_core.c index 583185fd7c94..eb6b88171538 100644 --- a/drivers/video/geode/lxfb_core.c +++ b/drivers/video/geode/lxfb_core.c | |||
@@ -34,7 +34,7 @@ static int fbsize; | |||
34 | * we try to make it something sane - 640x480-60 is sane | 34 | * we try to make it something sane - 640x480-60 is sane |
35 | */ | 35 | */ |
36 | 36 | ||
37 | const struct fb_videomode geode_modedb[] __initdata = { | 37 | static const struct fb_videomode geode_modedb[] __initdata = { |
38 | /* 640x480-60 */ | 38 | /* 640x480-60 */ |
39 | { NULL, 60, 640, 480, 39682, 48, 8, 25, 2, 88, 2, | 39 | { NULL, 60, 640, 480, 39682, 48, 8, 25, 2, 88, 2, |
40 | FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, | 40 | FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, |
diff --git a/drivers/video/hpfb.c b/drivers/video/hpfb.c index b18486ad8e17..2eb4fb159084 100644 --- a/drivers/video/hpfb.c +++ b/drivers/video/hpfb.c | |||
@@ -207,7 +207,8 @@ static struct fb_ops hpfb_ops = { | |||
207 | #define HPFB_FBOMSB 0x5d /* Frame buffer offset */ | 207 | #define HPFB_FBOMSB 0x5d /* Frame buffer offset */ |
208 | #define HPFB_FBOLSB 0x5f | 208 | #define HPFB_FBOLSB 0x5f |
209 | 209 | ||
210 | static int __init hpfb_init_one(unsigned long phys_base, unsigned long virt_base) | 210 | static int __devinit hpfb_init_one(unsigned long phys_base, |
211 | unsigned long virt_base) | ||
211 | { | 212 | { |
212 | unsigned long fboff, fb_width, fb_height, fb_start; | 213 | unsigned long fboff, fb_width, fb_height, fb_start; |
213 | 214 | ||
diff --git a/drivers/video/i810/i810_main.c b/drivers/video/i810/i810_main.c index 1a7d7789d877..1d13dd099af8 100644 --- a/drivers/video/i810/i810_main.c +++ b/drivers/video/i810/i810_main.c | |||
@@ -1476,7 +1476,7 @@ static int i810fb_cursor(struct fb_info *info, struct fb_cursor *cursor) | |||
1476 | struct i810fb_par *par = info->par; | 1476 | struct i810fb_par *par = info->par; |
1477 | u8 __iomem *mmio = par->mmio_start_virtual; | 1477 | u8 __iomem *mmio = par->mmio_start_virtual; |
1478 | 1478 | ||
1479 | if (!par->dev_flags & LOCKUP) | 1479 | if (!(par->dev_flags & LOCKUP)) |
1480 | return -ENXIO; | 1480 | return -ENXIO; |
1481 | 1481 | ||
1482 | if (cursor->image.width > 64 || cursor->image.height > 64) | 1482 | if (cursor->image.width > 64 || cursor->image.height > 64) |
diff --git a/drivers/video/igafb.c b/drivers/video/igafb.c index b87ea21d3d78..3a81060137a2 100644 --- a/drivers/video/igafb.c +++ b/drivers/video/igafb.c | |||
@@ -400,6 +400,7 @@ int __init igafb_init(void) | |||
400 | info = kzalloc(size, GFP_ATOMIC); | 400 | info = kzalloc(size, GFP_ATOMIC); |
401 | if (!info) { | 401 | if (!info) { |
402 | printk("igafb_init: can't alloc fb_info\n"); | 402 | printk("igafb_init: can't alloc fb_info\n"); |
403 | pci_dev_put(pdev); | ||
403 | return -ENOMEM; | 404 | return -ENOMEM; |
404 | } | 405 | } |
405 | 406 | ||
@@ -409,12 +410,14 @@ int __init igafb_init(void) | |||
409 | if ((addr = pdev->resource[0].start) == 0) { | 410 | if ((addr = pdev->resource[0].start) == 0) { |
410 | printk("igafb_init: no memory start\n"); | 411 | printk("igafb_init: no memory start\n"); |
411 | kfree(info); | 412 | kfree(info); |
413 | pci_dev_put(pdev); | ||
412 | return -ENXIO; | 414 | return -ENXIO; |
413 | } | 415 | } |
414 | 416 | ||
415 | if ((info->screen_base = ioremap(addr, 1024*1024*2)) == 0) { | 417 | if ((info->screen_base = ioremap(addr, 1024*1024*2)) == 0) { |
416 | printk("igafb_init: can't remap %lx[2M]\n", addr); | 418 | printk("igafb_init: can't remap %lx[2M]\n", addr); |
417 | kfree(info); | 419 | kfree(info); |
420 | pci_dev_put(pdev); | ||
418 | return -ENXIO; | 421 | return -ENXIO; |
419 | } | 422 | } |
420 | 423 | ||
@@ -449,6 +452,7 @@ int __init igafb_init(void) | |||
449 | printk("igafb_init: can't remap %lx[4K]\n", igafb_fix.mmio_start); | 452 | printk("igafb_init: can't remap %lx[4K]\n", igafb_fix.mmio_start); |
450 | iounmap((void *)info->screen_base); | 453 | iounmap((void *)info->screen_base); |
451 | kfree(info); | 454 | kfree(info); |
455 | pci_dev_put(pdev); | ||
452 | return -ENXIO; | 456 | return -ENXIO; |
453 | } | 457 | } |
454 | 458 | ||
@@ -466,6 +470,7 @@ int __init igafb_init(void) | |||
466 | iounmap((void *)par->io_base); | 470 | iounmap((void *)par->io_base); |
467 | iounmap(info->screen_base); | 471 | iounmap(info->screen_base); |
468 | kfree(info); | 472 | kfree(info); |
473 | pci_dev_put(pdev); | ||
469 | return -ENOMEM; | 474 | return -ENOMEM; |
470 | } | 475 | } |
471 | 476 | ||
diff --git a/drivers/video/intelfb/intelfbhw.c b/drivers/video/intelfb/intelfbhw.c index 5f6fb7d2c408..fa1fff553565 100644 --- a/drivers/video/intelfb/intelfbhw.c +++ b/drivers/video/intelfb/intelfbhw.c | |||
@@ -1971,7 +1971,7 @@ void intelfbhw_cursor_reset(struct intelfb_info *dinfo) | |||
1971 | static irqreturn_t intelfbhw_irq(int irq, void *dev_id) | 1971 | static irqreturn_t intelfbhw_irq(int irq, void *dev_id) |
1972 | { | 1972 | { |
1973 | u16 tmp; | 1973 | u16 tmp; |
1974 | struct intelfb_info *dinfo = (struct intelfb_info *)dev_id; | 1974 | struct intelfb_info *dinfo = dev_id; |
1975 | 1975 | ||
1976 | spin_lock(&dinfo->int_lock); | 1976 | spin_lock(&dinfo->int_lock); |
1977 | 1977 | ||
diff --git a/drivers/video/neofb.c b/drivers/video/neofb.c index 4b6a99b5be0d..5246b0402d76 100644 --- a/drivers/video/neofb.c +++ b/drivers/video/neofb.c | |||
@@ -2066,40 +2066,49 @@ static struct fb_info *__devinit neo_alloc_fb_info(struct pci_dev *dev, const st | |||
2066 | 2066 | ||
2067 | switch (info->fix.accel) { | 2067 | switch (info->fix.accel) { |
2068 | case FB_ACCEL_NEOMAGIC_NM2070: | 2068 | case FB_ACCEL_NEOMAGIC_NM2070: |
2069 | sprintf(info->fix.id, "MagicGraph 128"); | 2069 | snprintf(info->fix.id, sizeof(info->fix.id), |
2070 | "MagicGraph 128"); | ||
2070 | break; | 2071 | break; |
2071 | case FB_ACCEL_NEOMAGIC_NM2090: | 2072 | case FB_ACCEL_NEOMAGIC_NM2090: |
2072 | sprintf(info->fix.id, "MagicGraph 128V"); | 2073 | snprintf(info->fix.id, sizeof(info->fix.id), |
2074 | "MagicGraph 128V"); | ||
2073 | break; | 2075 | break; |
2074 | case FB_ACCEL_NEOMAGIC_NM2093: | 2076 | case FB_ACCEL_NEOMAGIC_NM2093: |
2075 | sprintf(info->fix.id, "MagicGraph 128ZV"); | 2077 | snprintf(info->fix.id, sizeof(info->fix.id), |
2078 | "MagicGraph 128ZV"); | ||
2076 | break; | 2079 | break; |
2077 | case FB_ACCEL_NEOMAGIC_NM2097: | 2080 | case FB_ACCEL_NEOMAGIC_NM2097: |
2078 | sprintf(info->fix.id, "MagicGraph 128ZV+"); | 2081 | snprintf(info->fix.id, sizeof(info->fix.id), |
2082 | "MagicGraph 128ZV+"); | ||
2079 | break; | 2083 | break; |
2080 | case FB_ACCEL_NEOMAGIC_NM2160: | 2084 | case FB_ACCEL_NEOMAGIC_NM2160: |
2081 | sprintf(info->fix.id, "MagicGraph 128XD"); | 2085 | snprintf(info->fix.id, sizeof(info->fix.id), |
2086 | "MagicGraph 128XD"); | ||
2082 | break; | 2087 | break; |
2083 | case FB_ACCEL_NEOMAGIC_NM2200: | 2088 | case FB_ACCEL_NEOMAGIC_NM2200: |
2084 | sprintf(info->fix.id, "MagicGraph 256AV"); | 2089 | snprintf(info->fix.id, sizeof(info->fix.id), |
2090 | "MagicGraph 256AV"); | ||
2085 | info->flags |= FBINFO_HWACCEL_IMAGEBLIT | | 2091 | info->flags |= FBINFO_HWACCEL_IMAGEBLIT | |
2086 | FBINFO_HWACCEL_COPYAREA | | 2092 | FBINFO_HWACCEL_COPYAREA | |
2087 | FBINFO_HWACCEL_FILLRECT; | 2093 | FBINFO_HWACCEL_FILLRECT; |
2088 | break; | 2094 | break; |
2089 | case FB_ACCEL_NEOMAGIC_NM2230: | 2095 | case FB_ACCEL_NEOMAGIC_NM2230: |
2090 | sprintf(info->fix.id, "MagicGraph 256AV+"); | 2096 | snprintf(info->fix.id, sizeof(info->fix.id), |
2097 | "MagicGraph 256AV+"); | ||
2091 | info->flags |= FBINFO_HWACCEL_IMAGEBLIT | | 2098 | info->flags |= FBINFO_HWACCEL_IMAGEBLIT | |
2092 | FBINFO_HWACCEL_COPYAREA | | 2099 | FBINFO_HWACCEL_COPYAREA | |
2093 | FBINFO_HWACCEL_FILLRECT; | 2100 | FBINFO_HWACCEL_FILLRECT; |
2094 | break; | 2101 | break; |
2095 | case FB_ACCEL_NEOMAGIC_NM2360: | 2102 | case FB_ACCEL_NEOMAGIC_NM2360: |
2096 | sprintf(info->fix.id, "MagicGraph 256ZX"); | 2103 | snprintf(info->fix.id, sizeof(info->fix.id), |
2104 | "MagicGraph 256ZX"); | ||
2097 | info->flags |= FBINFO_HWACCEL_IMAGEBLIT | | 2105 | info->flags |= FBINFO_HWACCEL_IMAGEBLIT | |
2098 | FBINFO_HWACCEL_COPYAREA | | 2106 | FBINFO_HWACCEL_COPYAREA | |
2099 | FBINFO_HWACCEL_FILLRECT; | 2107 | FBINFO_HWACCEL_FILLRECT; |
2100 | break; | 2108 | break; |
2101 | case FB_ACCEL_NEOMAGIC_NM2380: | 2109 | case FB_ACCEL_NEOMAGIC_NM2380: |
2102 | sprintf(info->fix.id, "MagicGraph 256XL+"); | 2110 | snprintf(info->fix.id, sizeof(info->fix.id), |
2111 | "MagicGraph 256XL+"); | ||
2103 | info->flags |= FBINFO_HWACCEL_IMAGEBLIT | | 2112 | info->flags |= FBINFO_HWACCEL_IMAGEBLIT | |
2104 | FBINFO_HWACCEL_COPYAREA | | 2113 | FBINFO_HWACCEL_COPYAREA | |
2105 | FBINFO_HWACCEL_FILLRECT; | 2114 | FBINFO_HWACCEL_FILLRECT; |
diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c index 30e14eb1f51e..74517b1b26a6 100644 --- a/drivers/video/nvidia/nvidia.c +++ b/drivers/video/nvidia/nvidia.c | |||
@@ -849,9 +849,27 @@ static int nvidiafb_check_var(struct fb_var_screeninfo *var, | |||
849 | if (!mode_valid && info->monspecs.modedb_len) | 849 | if (!mode_valid && info->monspecs.modedb_len) |
850 | return -EINVAL; | 850 | return -EINVAL; |
851 | 851 | ||
852 | /* | ||
853 | * If we're on a flat panel, check if the mode is outside of the | ||
854 | * panel dimensions. If so, cap it and try for the next best mode | ||
855 | * before bailing out. | ||
856 | */ | ||
852 | if (par->fpWidth && par->fpHeight && (par->fpWidth < var->xres || | 857 | if (par->fpWidth && par->fpHeight && (par->fpWidth < var->xres || |
853 | par->fpHeight < var->yres)) | 858 | par->fpHeight < var->yres)) { |
854 | return -EINVAL; | 859 | const struct fb_videomode *mode; |
860 | |||
861 | var->xres = par->fpWidth; | ||
862 | var->yres = par->fpHeight; | ||
863 | |||
864 | mode = fb_find_best_mode(var, &info->modelist); | ||
865 | if (!mode) { | ||
866 | printk(KERN_ERR PFX "mode out of range of flat " | ||
867 | "panel dimensions\n"); | ||
868 | return -EINVAL; | ||
869 | } | ||
870 | |||
871 | fb_videomode_to_var(var, mode); | ||
872 | } | ||
855 | 873 | ||
856 | if (var->yres_virtual < var->yres) | 874 | if (var->yres_virtual < var->yres) |
857 | var->yres_virtual = var->yres; | 875 | var->yres_virtual = var->yres; |
diff --git a/drivers/video/pm2fb.c b/drivers/video/pm2fb.c index 5591dfb22b18..30181b593829 100644 --- a/drivers/video/pm2fb.c +++ b/drivers/video/pm2fb.c | |||
@@ -1159,6 +1159,11 @@ static void pm2fb_imageblit(struct fb_info *info, const struct fb_image *image) | |||
1159 | u32 fgx, bgx; | 1159 | u32 fgx, bgx; |
1160 | const u32 *src = (const u32 *)image->data; | 1160 | const u32 *src = (const u32 *)image->data; |
1161 | u32 xres = (info->var.xres + 31) & ~31; | 1161 | u32 xres = (info->var.xres + 31) & ~31; |
1162 | int raster_mode = 1; /* invert bits */ | ||
1163 | |||
1164 | #ifdef __LITTLE_ENDIAN | ||
1165 | raster_mode |= 3 << 7; /* reverse byte order */ | ||
1166 | #endif | ||
1162 | 1167 | ||
1163 | if (info->state != FBINFO_STATE_RUNNING) | 1168 | if (info->state != FBINFO_STATE_RUNNING) |
1164 | return; | 1169 | return; |
@@ -1208,9 +1213,8 @@ static void pm2fb_imageblit(struct fb_info *info, const struct fb_image *image) | |||
1208 | pm2_WR(par, PM2R_RENDER, | 1213 | pm2_WR(par, PM2R_RENDER, |
1209 | PM2F_RENDER_RECTANGLE | | 1214 | PM2F_RENDER_RECTANGLE | |
1210 | PM2F_INCREASE_X | PM2F_INCREASE_Y); | 1215 | PM2F_INCREASE_X | PM2F_INCREASE_Y); |
1211 | /* BitMapPackEachScanline & invert bits and byte order*/ | 1216 | /* BitMapPackEachScanline */ |
1212 | /* force background */ | 1217 | pm2_WR(par, PM2R_RASTERIZER_MODE, raster_mode | (1 << 9)); |
1213 | pm2_WR(par, PM2R_RASTERIZER_MODE, (1 << 9) | 1 | (3 << 7)); | ||
1214 | pm2_WR(par, PM2R_CONSTANT_COLOR, fgx); | 1218 | pm2_WR(par, PM2R_CONSTANT_COLOR, fgx); |
1215 | pm2_WR(par, PM2R_RENDER, | 1219 | pm2_WR(par, PM2R_RENDER, |
1216 | PM2F_RENDER_RECTANGLE | | 1220 | PM2F_RENDER_RECTANGLE | |
@@ -1224,8 +1228,7 @@ static void pm2fb_imageblit(struct fb_info *info, const struct fb_image *image) | |||
1224 | PM2F_RENDER_RECTANGLE | | 1228 | PM2F_RENDER_RECTANGLE | |
1225 | PM2F_RENDER_FASTFILL | | 1229 | PM2F_RENDER_FASTFILL | |
1226 | PM2F_INCREASE_X | PM2F_INCREASE_Y); | 1230 | PM2F_INCREASE_X | PM2F_INCREASE_Y); |
1227 | /* invert bits and byte order*/ | 1231 | pm2_WR(par, PM2R_RASTERIZER_MODE, raster_mode); |
1228 | pm2_WR(par, PM2R_RASTERIZER_MODE, 1 | (3 << 7)); | ||
1229 | pm2_WR(par, PM2R_FB_BLOCK_COLOR, fgx); | 1232 | pm2_WR(par, PM2R_FB_BLOCK_COLOR, fgx); |
1230 | pm2_WR(par, PM2R_RENDER, | 1233 | pm2_WR(par, PM2R_RENDER, |
1231 | PM2F_RENDER_RECTANGLE | | 1234 | PM2F_RENDER_RECTANGLE | |
diff --git a/drivers/video/pm3fb.c b/drivers/video/pm3fb.c index 070659992c18..5dba8cdd0517 100644 --- a/drivers/video/pm3fb.c +++ b/drivers/video/pm3fb.c | |||
@@ -1227,7 +1227,7 @@ static struct fb_ops pm3fb_ops = { | |||
1227 | 1227 | ||
1228 | /* mmio register are already mapped when this function is called */ | 1228 | /* mmio register are already mapped when this function is called */ |
1229 | /* the pm3fb_fix.smem_start is also set */ | 1229 | /* the pm3fb_fix.smem_start is also set */ |
1230 | static unsigned long pm3fb_size_memory(struct pm3_par *par) | 1230 | static unsigned long __devinit pm3fb_size_memory(struct pm3_par *par) |
1231 | { | 1231 | { |
1232 | unsigned long memsize = 0; | 1232 | unsigned long memsize = 0; |
1233 | unsigned long tempBypass, i, temp1, temp2; | 1233 | unsigned long tempBypass, i, temp1, temp2; |
diff --git a/drivers/video/pmag-aa-fb.c b/drivers/video/pmag-aa-fb.c index a864438b6008..6515ec11c16b 100644 --- a/drivers/video/pmag-aa-fb.c +++ b/drivers/video/pmag-aa-fb.c | |||
@@ -150,7 +150,7 @@ static int aafbcon_set_font(struct display *disp, int width, int height) | |||
150 | { | 150 | { |
151 | struct aafb_info *info = (struct aafb_info *)disp->fb_info; | 151 | struct aafb_info *info = (struct aafb_info *)disp->fb_info; |
152 | struct aafb_cursor *c = &info->cursor; | 152 | struct aafb_cursor *c = &info->cursor; |
153 | u8 fgc = ~attr_bgcol_ec(disp, disp->conp); | 153 | u8 fgc = ~attr_bgcol_ec(disp, disp->conp, &info->info); |
154 | 154 | ||
155 | if (width > 64 || height > 64 || width < 0 || height < 0) | 155 | if (width > 64 || height > 64 || width < 0 || height < 0) |
156 | return -EINVAL; | 156 | return -EINVAL; |
diff --git a/drivers/video/ps3fb.c b/drivers/video/ps3fb.c index 044a423a72cb..dc3af1c78c56 100644 --- a/drivers/video/ps3fb.c +++ b/drivers/video/ps3fb.c | |||
@@ -57,8 +57,6 @@ | |||
57 | #define GPU_ALIGN_UP(x) _ALIGN_UP((x), 64) | 57 | #define GPU_ALIGN_UP(x) _ALIGN_UP((x), 64) |
58 | #define GPU_MAX_LINE_LENGTH (65536 - 64) | 58 | #define GPU_MAX_LINE_LENGTH (65536 - 64) |
59 | 59 | ||
60 | #define PS3FB_FULL_MODE_BIT 0x80 | ||
61 | |||
62 | #define GPU_INTR_STATUS_VSYNC_0 0 /* vsync on head A */ | 60 | #define GPU_INTR_STATUS_VSYNC_0 0 /* vsync on head A */ |
63 | #define GPU_INTR_STATUS_VSYNC_1 1 /* vsync on head B */ | 61 | #define GPU_INTR_STATUS_VSYNC_1 1 /* vsync on head B */ |
64 | #define GPU_INTR_STATUS_FLIP_0 3 /* flip head A */ | 62 | #define GPU_INTR_STATUS_FLIP_0 3 /* flip head A */ |
@@ -118,8 +116,6 @@ struct ps3fb_priv { | |||
118 | unsigned int irq_no; | 116 | unsigned int irq_no; |
119 | 117 | ||
120 | u64 context_handle, memory_handle; | 118 | u64 context_handle, memory_handle; |
121 | void *xdr_ea; | ||
122 | size_t xdr_size; | ||
123 | struct gpu_driver_info *dinfo; | 119 | struct gpu_driver_info *dinfo; |
124 | 120 | ||
125 | u64 vblank_count; /* frame count */ | 121 | u64 vblank_count; /* frame count */ |
@@ -136,42 +132,19 @@ static struct ps3fb_priv ps3fb; | |||
136 | struct ps3fb_par { | 132 | struct ps3fb_par { |
137 | u32 pseudo_palette[16]; | 133 | u32 pseudo_palette[16]; |
138 | int mode_id, new_mode_id; | 134 | int mode_id, new_mode_id; |
139 | int res_index; | ||
140 | unsigned int num_frames; /* num of frame buffers */ | 135 | unsigned int num_frames; /* num of frame buffers */ |
141 | unsigned int width; | 136 | unsigned int width; |
142 | unsigned int height; | 137 | unsigned int height; |
143 | unsigned long full_offset; /* start of fullscreen DDR fb */ | 138 | unsigned int ddr_line_length; |
144 | unsigned long fb_offset; /* start of actual DDR fb */ | 139 | unsigned int ddr_frame_size; |
145 | unsigned long pan_offset; | 140 | unsigned int xdr_frame_size; |
141 | unsigned int full_offset; /* start of fullscreen DDR fb */ | ||
142 | unsigned int fb_offset; /* start of actual DDR fb */ | ||
143 | unsigned int pan_offset; | ||
146 | }; | 144 | }; |
147 | 145 | ||
148 | struct ps3fb_res_table { | 146 | |
149 | u32 xres; | 147 | #define FIRST_NATIVE_MODE_INDEX 10 |
150 | u32 yres; | ||
151 | u32 xoff; | ||
152 | u32 yoff; | ||
153 | u32 type; | ||
154 | }; | ||
155 | #define PS3FB_RES_FULL 1 | ||
156 | static const struct ps3fb_res_table ps3fb_res[] = { | ||
157 | /* res_x,y margin_x,y full */ | ||
158 | { 720, 480, 72, 48 , 0}, | ||
159 | { 720, 576, 72, 58 , 0}, | ||
160 | { 1280, 720, 78, 38 , 0}, | ||
161 | { 1920, 1080, 116, 58 , 0}, | ||
162 | /* full mode */ | ||
163 | { 720, 480, 0, 0 , PS3FB_RES_FULL}, | ||
164 | { 720, 576, 0, 0 , PS3FB_RES_FULL}, | ||
165 | { 1280, 720, 0, 0 , PS3FB_RES_FULL}, | ||
166 | { 1920, 1080, 0, 0 , PS3FB_RES_FULL}, | ||
167 | /* vesa: normally full mode */ | ||
168 | { 1280, 768, 0, 0 , 0}, | ||
169 | { 1280, 1024, 0, 0 , 0}, | ||
170 | { 1920, 1200, 0, 0 , 0}, | ||
171 | { 0, 0, 0, 0 , 0} }; | ||
172 | |||
173 | /* default resolution */ | ||
174 | #define GPU_RES_INDEX 0 /* 720 x 480 */ | ||
175 | 148 | ||
176 | static const struct fb_videomode ps3fb_modedb[] = { | 149 | static const struct fb_videomode ps3fb_modedb[] = { |
177 | /* 60 Hz broadcast modes (modes "1" to "5") */ | 150 | /* 60 Hz broadcast modes (modes "1" to "5") */ |
@@ -211,7 +184,7 @@ static const struct fb_videomode ps3fb_modedb[] = { | |||
211 | "720p", 50, 1124, 644, 13468, 298, 478, 57, 44, 80, 5, | 184 | "720p", 50, 1124, 644, 13468, 298, 478, 57, 44, 80, 5, |
212 | FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED | 185 | FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED |
213 | }, { | 186 | }, { |
214 | /* 1080 */ | 187 | /* 1080i */ |
215 | "1080i", 50, 1688, 964, 13468, 264, 600, 94, 62, 88, 5, | 188 | "1080i", 50, 1688, 964, 13468, 264, 600, 94, 62, 88, 5, |
216 | FB_SYNC_BROADCAST, FB_VMODE_INTERLACED | 189 | FB_SYNC_BROADCAST, FB_VMODE_INTERLACED |
217 | }, { | 190 | }, { |
@@ -220,24 +193,7 @@ static const struct fb_videomode ps3fb_modedb[] = { | |||
220 | FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED | 193 | FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED |
221 | }, | 194 | }, |
222 | 195 | ||
223 | /* VESA modes (modes "11" to "13") */ | 196 | [FIRST_NATIVE_MODE_INDEX] = |
224 | { | ||
225 | /* WXGA */ | ||
226 | "wxga", 60, 1280, 768, 12924, 160, 24, 29, 3, 136, 6, | ||
227 | 0, FB_VMODE_NONINTERLACED, | ||
228 | FB_MODE_IS_VESA | ||
229 | }, { | ||
230 | /* SXGA */ | ||
231 | "sxga", 60, 1280, 1024, 9259, 248, 48, 38, 1, 112, 3, | ||
232 | FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, | ||
233 | FB_MODE_IS_VESA | ||
234 | }, { | ||
235 | /* WUXGA */ | ||
236 | "wuxga", 60, 1920, 1200, 6494, 80, 48, 26, 3, 32, 6, | ||
237 | FB_SYNC_HOR_HIGH_ACT, FB_VMODE_NONINTERLACED, | ||
238 | FB_MODE_IS_VESA | ||
239 | }, | ||
240 | |||
241 | /* 60 Hz broadcast modes (full resolution versions of modes "1" to "5") */ | 197 | /* 60 Hz broadcast modes (full resolution versions of modes "1" to "5") */ |
242 | { | 198 | { |
243 | /* 480if */ | 199 | /* 480if */ |
@@ -276,12 +232,30 @@ static const struct fb_videomode ps3fb_modedb[] = { | |||
276 | FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED | 232 | FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED |
277 | }, { | 233 | }, { |
278 | /* 1080if */ | 234 | /* 1080if */ |
279 | "1080f", 50, 1920, 1080, 13468, 148, 484, 36, 4, 88, 5, | 235 | "1080if", 50, 1920, 1080, 13468, 148, 484, 36, 4, 88, 5, |
280 | FB_SYNC_BROADCAST, FB_VMODE_INTERLACED | 236 | FB_SYNC_BROADCAST, FB_VMODE_INTERLACED |
281 | }, { | 237 | }, { |
282 | /* 1080pf */ | 238 | /* 1080pf */ |
283 | "1080pf", 50, 1920, 1080, 6734, 148, 484, 36, 4, 88, 5, | 239 | "1080pf", 50, 1920, 1080, 6734, 148, 484, 36, 4, 88, 5, |
284 | FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED | 240 | FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED |
241 | }, | ||
242 | |||
243 | /* VESA modes (modes "11" to "13") */ | ||
244 | { | ||
245 | /* WXGA */ | ||
246 | "wxga", 60, 1280, 768, 12924, 160, 24, 29, 3, 136, 6, | ||
247 | 0, FB_VMODE_NONINTERLACED, | ||
248 | FB_MODE_IS_VESA | ||
249 | }, { | ||
250 | /* SXGA */ | ||
251 | "sxga", 60, 1280, 1024, 9259, 248, 48, 38, 1, 112, 3, | ||
252 | FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, | ||
253 | FB_MODE_IS_VESA | ||
254 | }, { | ||
255 | /* WUXGA */ | ||
256 | "wuxga", 60, 1920, 1200, 6494, 80, 48, 26, 3, 32, 6, | ||
257 | FB_SYNC_HOR_HIGH_ACT, FB_VMODE_NONINTERLACED, | ||
258 | FB_MODE_IS_VESA | ||
285 | } | 259 | } |
286 | }; | 260 | }; |
287 | 261 | ||
@@ -289,110 +263,188 @@ static const struct fb_videomode ps3fb_modedb[] = { | |||
289 | #define HEAD_A | 263 | #define HEAD_A |
290 | #define HEAD_B | 264 | #define HEAD_B |
291 | 265 | ||
292 | #define X_OFF(i) (ps3fb_res[i].xoff) /* left/right margin (pixel) */ | ||
293 | #define Y_OFF(i) (ps3fb_res[i].yoff) /* top/bottom margin (pixel) */ | ||
294 | #define WIDTH(i) (ps3fb_res[i].xres) /* width of FB */ | ||
295 | #define HEIGHT(i) (ps3fb_res[i].yres) /* height of FB */ | ||
296 | #define BPP 4 /* number of bytes per pixel */ | 266 | #define BPP 4 /* number of bytes per pixel */ |
297 | 267 | ||
298 | /* Start of the virtual frame buffer (relative to fullscreen ) */ | ||
299 | #define VP_OFF(i) ((WIDTH(i) * Y_OFF(i) + X_OFF(i)) * BPP) | ||
300 | |||
301 | 268 | ||
302 | static int ps3fb_mode; | 269 | static int ps3fb_mode; |
303 | module_param(ps3fb_mode, int, 0); | 270 | module_param(ps3fb_mode, int, 0); |
304 | 271 | ||
305 | static char *mode_option __devinitdata; | 272 | static char *mode_option __devinitdata; |
306 | 273 | ||
307 | static int ps3fb_get_res_table(u32 xres, u32 yres, int mode) | 274 | static int ps3fb_cmp_mode(const struct fb_videomode *vmode, |
275 | const struct fb_var_screeninfo *var) | ||
308 | { | 276 | { |
309 | int full_mode; | 277 | long xres, yres, left_margin, right_margin, upper_margin, lower_margin; |
310 | unsigned int i; | 278 | long dx, dy; |
311 | u32 x, y, f; | 279 | |
312 | 280 | /* maximum values */ | |
313 | full_mode = (mode & PS3FB_FULL_MODE_BIT) ? PS3FB_RES_FULL : 0; | 281 | if (var->xres > vmode->xres || var->yres > vmode->yres || |
314 | for (i = 0;; i++) { | 282 | var->pixclock > vmode->pixclock || |
315 | x = ps3fb_res[i].xres; | 283 | var->hsync_len > vmode->hsync_len || |
316 | y = ps3fb_res[i].yres; | 284 | var->vsync_len > vmode->vsync_len) |
317 | f = ps3fb_res[i].type; | 285 | return -1; |
318 | |||
319 | if (!x) { | ||
320 | pr_debug("ERROR: ps3fb_get_res_table()\n"); | ||
321 | return -1; | ||
322 | } | ||
323 | 286 | ||
324 | if (full_mode == PS3FB_RES_FULL && f != PS3FB_RES_FULL) | 287 | /* progressive/interlaced must match */ |
325 | continue; | 288 | if ((var->vmode & FB_VMODE_MASK) != vmode->vmode) |
289 | return -1; | ||
326 | 290 | ||
327 | if (x == xres && (yres == 0 || y == yres)) | 291 | /* minimum resolution */ |
328 | break; | 292 | xres = max(var->xres, 1U); |
293 | yres = max(var->yres, 1U); | ||
294 | |||
295 | /* minimum margins */ | ||
296 | left_margin = max(var->left_margin, vmode->left_margin); | ||
297 | right_margin = max(var->right_margin, vmode->right_margin); | ||
298 | upper_margin = max(var->upper_margin, vmode->upper_margin); | ||
299 | lower_margin = max(var->lower_margin, vmode->lower_margin); | ||
300 | |||
301 | /* resolution + margins may not exceed native parameters */ | ||
302 | dx = ((long)vmode->left_margin + (long)vmode->xres + | ||
303 | (long)vmode->right_margin) - | ||
304 | (left_margin + xres + right_margin); | ||
305 | if (dx < 0) | ||
306 | return -1; | ||
329 | 307 | ||
330 | x = x - 2 * ps3fb_res[i].xoff; | 308 | dy = ((long)vmode->upper_margin + (long)vmode->yres + |
331 | y = y - 2 * ps3fb_res[i].yoff; | 309 | (long)vmode->lower_margin) - |
332 | if (x == xres && (yres == 0 || y == yres)) | 310 | (upper_margin + yres + lower_margin); |
333 | break; | 311 | if (dy < 0) |
312 | return -1; | ||
313 | |||
314 | /* exact match */ | ||
315 | if (!dx && !dy) | ||
316 | return 0; | ||
317 | |||
318 | /* resolution difference */ | ||
319 | return (vmode->xres - xres) * (vmode->yres - yres); | ||
320 | } | ||
321 | |||
322 | static const struct fb_videomode *ps3fb_native_vmode(enum ps3av_mode_num id) | ||
323 | { | ||
324 | return &ps3fb_modedb[FIRST_NATIVE_MODE_INDEX + id - 1]; | ||
325 | } | ||
326 | |||
327 | static const struct fb_videomode *ps3fb_vmode(int id) | ||
328 | { | ||
329 | u32 mode = id & PS3AV_MODE_MASK; | ||
330 | |||
331 | if (mode < PS3AV_MODE_480I || mode > PS3AV_MODE_WUXGA) | ||
332 | return NULL; | ||
333 | |||
334 | if (mode <= PS3AV_MODE_1080P50 && !(id & PS3AV_MODE_FULL)) { | ||
335 | /* Non-fullscreen broadcast mode */ | ||
336 | return &ps3fb_modedb[mode - 1]; | ||
334 | } | 337 | } |
335 | return i; | 338 | |
339 | return ps3fb_native_vmode(mode); | ||
336 | } | 340 | } |
337 | 341 | ||
338 | static unsigned int ps3fb_find_mode(const struct fb_var_screeninfo *var, | 342 | static unsigned int ps3fb_find_mode(struct fb_var_screeninfo *var, |
339 | u32 *ddr_line_length, u32 *xdr_line_length) | 343 | u32 *ddr_line_length, u32 *xdr_line_length) |
340 | { | 344 | { |
341 | unsigned int i, mode; | 345 | unsigned int id, best_id; |
342 | 346 | int diff, best_diff; | |
343 | for (i = 0; i < ARRAY_SIZE(ps3fb_modedb); i++) | 347 | const struct fb_videomode *vmode; |
344 | if (var->xres == ps3fb_modedb[i].xres && | 348 | long gap; |
345 | var->yres == ps3fb_modedb[i].yres && | 349 | |
346 | var->pixclock == ps3fb_modedb[i].pixclock && | 350 | best_id = 0; |
347 | var->hsync_len == ps3fb_modedb[i].hsync_len && | 351 | best_diff = INT_MAX; |
348 | var->vsync_len == ps3fb_modedb[i].vsync_len && | 352 | pr_debug("%s: wanted %u [%u] %u x %u [%u] %u\n", __func__, |
349 | var->left_margin == ps3fb_modedb[i].left_margin && | 353 | var->left_margin, var->xres, var->right_margin, |
350 | var->right_margin == ps3fb_modedb[i].right_margin && | 354 | var->upper_margin, var->yres, var->lower_margin); |
351 | var->upper_margin == ps3fb_modedb[i].upper_margin && | 355 | for (id = PS3AV_MODE_480I; id <= PS3AV_MODE_WUXGA; id++) { |
352 | var->lower_margin == ps3fb_modedb[i].lower_margin && | 356 | vmode = ps3fb_native_vmode(id); |
353 | var->sync == ps3fb_modedb[i].sync && | 357 | diff = ps3fb_cmp_mode(vmode, var); |
354 | (var->vmode & FB_VMODE_MASK) == ps3fb_modedb[i].vmode) | 358 | pr_debug("%s: mode %u: %u [%u] %u x %u [%u] %u: diff = %d\n", |
355 | goto found; | 359 | __func__, id, vmode->left_margin, vmode->xres, |
356 | 360 | vmode->right_margin, vmode->upper_margin, | |
357 | pr_debug("ps3fb_find_mode: mode not found\n"); | 361 | vmode->yres, vmode->lower_margin, diff); |
358 | return 0; | 362 | if (diff < 0) |
363 | continue; | ||
364 | if (diff < best_diff) { | ||
365 | best_id = id; | ||
366 | if (!diff) | ||
367 | break; | ||
368 | best_diff = diff; | ||
369 | } | ||
370 | } | ||
359 | 371 | ||
360 | found: | 372 | if (!best_id) { |
361 | /* Cropped broadcast modes use the full line length */ | 373 | pr_debug("%s: no suitable mode found\n", __func__); |
362 | *ddr_line_length = ps3fb_modedb[i < 10 ? i + 13 : i].xres * BPP; | 374 | return 0; |
375 | } | ||
363 | 376 | ||
364 | if (ps3_compare_firmware_version(1, 9, 0) >= 0) { | 377 | id = best_id; |
365 | *xdr_line_length = GPU_ALIGN_UP(max(var->xres, | 378 | vmode = ps3fb_native_vmode(id); |
366 | var->xres_virtual) * BPP); | ||
367 | if (*xdr_line_length > GPU_MAX_LINE_LENGTH) | ||
368 | *xdr_line_length = GPU_MAX_LINE_LENGTH; | ||
369 | } else | ||
370 | *xdr_line_length = *ddr_line_length; | ||
371 | 379 | ||
372 | /* Full broadcast modes have the full mode bit set */ | 380 | *ddr_line_length = vmode->xres * BPP; |
373 | mode = i > 12 ? (i - 12) | PS3FB_FULL_MODE_BIT : i + 1; | ||
374 | 381 | ||
375 | pr_debug("ps3fb_find_mode: mode %u\n", mode); | 382 | /* minimum resolution */ |
383 | if (!var->xres) | ||
384 | var->xres = 1; | ||
385 | if (!var->yres) | ||
386 | var->yres = 1; | ||
376 | 387 | ||
377 | return mode; | 388 | /* minimum virtual resolution */ |
378 | } | 389 | if (var->xres_virtual < var->xres) |
390 | var->xres_virtual = var->xres; | ||
391 | if (var->yres_virtual < var->yres) | ||
392 | var->yres_virtual = var->yres; | ||
379 | 393 | ||
380 | static const struct fb_videomode *ps3fb_default_mode(int id) | 394 | /* minimum margins */ |
381 | { | 395 | if (var->left_margin < vmode->left_margin) |
382 | u32 mode = id & PS3AV_MODE_MASK; | 396 | var->left_margin = vmode->left_margin; |
383 | u32 flags; | 397 | if (var->right_margin < vmode->right_margin) |
398 | var->right_margin = vmode->right_margin; | ||
399 | if (var->upper_margin < vmode->upper_margin) | ||
400 | var->upper_margin = vmode->upper_margin; | ||
401 | if (var->lower_margin < vmode->lower_margin) | ||
402 | var->lower_margin = vmode->lower_margin; | ||
403 | |||
404 | /* extra margins */ | ||
405 | gap = ((long)vmode->left_margin + (long)vmode->xres + | ||
406 | (long)vmode->right_margin) - | ||
407 | ((long)var->left_margin + (long)var->xres + | ||
408 | (long)var->right_margin); | ||
409 | if (gap > 0) { | ||
410 | var->left_margin += gap/2; | ||
411 | var->right_margin += (gap+1)/2; | ||
412 | pr_debug("%s: rounded up H to %u [%u] %u\n", __func__, | ||
413 | var->left_margin, var->xres, var->right_margin); | ||
414 | } | ||
384 | 415 | ||
385 | if (mode < 1 || mode > 13) | 416 | gap = ((long)vmode->upper_margin + (long)vmode->yres + |
386 | return NULL; | 417 | (long)vmode->lower_margin) - |
418 | ((long)var->upper_margin + (long)var->yres + | ||
419 | (long)var->lower_margin); | ||
420 | if (gap > 0) { | ||
421 | var->upper_margin += gap/2; | ||
422 | var->lower_margin += (gap+1)/2; | ||
423 | pr_debug("%s: rounded up V to %u [%u] %u\n", __func__, | ||
424 | var->upper_margin, var->yres, var->lower_margin); | ||
425 | } | ||
426 | |||
427 | /* fixed fields */ | ||
428 | var->pixclock = vmode->pixclock; | ||
429 | var->hsync_len = vmode->hsync_len; | ||
430 | var->vsync_len = vmode->vsync_len; | ||
431 | var->sync = vmode->sync; | ||
387 | 432 | ||
388 | flags = id & ~PS3AV_MODE_MASK; | 433 | if (ps3_compare_firmware_version(1, 9, 0) >= 0) { |
434 | *xdr_line_length = GPU_ALIGN_UP(var->xres_virtual * BPP); | ||
435 | if (*xdr_line_length > GPU_MAX_LINE_LENGTH) | ||
436 | *xdr_line_length = GPU_MAX_LINE_LENGTH; | ||
437 | } else | ||
438 | *xdr_line_length = *ddr_line_length; | ||
389 | 439 | ||
390 | if (mode <= 10 && flags & PS3FB_FULL_MODE_BIT) { | 440 | if (vmode->sync & FB_SYNC_BROADCAST) { |
391 | /* Full broadcast mode */ | 441 | /* Full broadcast modes have the full mode bit set */ |
392 | return &ps3fb_modedb[mode + 12]; | 442 | if (vmode->xres == var->xres && vmode->yres == var->yres) |
443 | id |= PS3AV_MODE_FULL; | ||
393 | } | 444 | } |
394 | 445 | ||
395 | return &ps3fb_modedb[mode - 1]; | 446 | pr_debug("%s: mode %u\n", __func__, id); |
447 | return id; | ||
396 | } | 448 | } |
397 | 449 | ||
398 | static void ps3fb_sync_image(struct device *dev, u64 frame_offset, | 450 | static void ps3fb_sync_image(struct device *dev, u64 frame_offset, |
@@ -439,8 +491,7 @@ static void ps3fb_sync_image(struct device *dev, u64 frame_offset, | |||
439 | static int ps3fb_sync(struct fb_info *info, u32 frame) | 491 | static int ps3fb_sync(struct fb_info *info, u32 frame) |
440 | { | 492 | { |
441 | struct ps3fb_par *par = info->par; | 493 | struct ps3fb_par *par = info->par; |
442 | int i, error = 0; | 494 | int error = 0; |
443 | u32 ddr_line_length, xdr_line_length; | ||
444 | u64 ddr_base, xdr_base; | 495 | u64 ddr_base, xdr_base; |
445 | 496 | ||
446 | if (frame > par->num_frames - 1) { | 497 | if (frame > par->num_frames - 1) { |
@@ -450,16 +501,13 @@ static int ps3fb_sync(struct fb_info *info, u32 frame) | |||
450 | goto out; | 501 | goto out; |
451 | } | 502 | } |
452 | 503 | ||
453 | i = par->res_index; | 504 | xdr_base = frame * par->xdr_frame_size; |
454 | xdr_line_length = info->fix.line_length; | 505 | ddr_base = frame * par->ddr_frame_size; |
455 | ddr_line_length = ps3fb_res[i].xres * BPP; | ||
456 | xdr_base = frame * info->var.yres_virtual * xdr_line_length; | ||
457 | ddr_base = frame * ps3fb_res[i].yres * ddr_line_length; | ||
458 | 506 | ||
459 | ps3fb_sync_image(info->device, ddr_base + par->full_offset, | 507 | ps3fb_sync_image(info->device, ddr_base + par->full_offset, |
460 | ddr_base + par->fb_offset, xdr_base + par->pan_offset, | 508 | ddr_base + par->fb_offset, xdr_base + par->pan_offset, |
461 | par->width, par->height, ddr_line_length, | 509 | par->width, par->height, par->ddr_line_length, |
462 | xdr_line_length); | 510 | info->fix.line_length); |
463 | 511 | ||
464 | out: | 512 | out: |
465 | return error; | 513 | return error; |
@@ -498,22 +546,11 @@ static int ps3fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) | |||
498 | u32 xdr_line_length, ddr_line_length; | 546 | u32 xdr_line_length, ddr_line_length; |
499 | int mode; | 547 | int mode; |
500 | 548 | ||
501 | dev_dbg(info->device, "var->xres:%u info->var.xres:%u\n", var->xres, | ||
502 | info->var.xres); | ||
503 | dev_dbg(info->device, "var->yres:%u info->var.yres:%u\n", var->yres, | ||
504 | info->var.yres); | ||
505 | |||
506 | /* FIXME For now we do exact matches only */ | ||
507 | mode = ps3fb_find_mode(var, &ddr_line_length, &xdr_line_length); | 549 | mode = ps3fb_find_mode(var, &ddr_line_length, &xdr_line_length); |
508 | if (!mode) | 550 | if (!mode) |
509 | return -EINVAL; | 551 | return -EINVAL; |
510 | 552 | ||
511 | /* Virtual screen */ | 553 | /* Virtual screen */ |
512 | if (var->xres_virtual < var->xres) | ||
513 | var->xres_virtual = var->xres; | ||
514 | if (var->yres_virtual < var->yres) | ||
515 | var->yres_virtual = var->yres; | ||
516 | |||
517 | if (var->xres_virtual > xdr_line_length / BPP) { | 554 | if (var->xres_virtual > xdr_line_length / BPP) { |
518 | dev_dbg(info->device, | 555 | dev_dbg(info->device, |
519 | "Horizontal virtual screen size too large\n"); | 556 | "Horizontal virtual screen size too large\n"); |
@@ -559,7 +596,7 @@ static int ps3fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) | |||
559 | } | 596 | } |
560 | 597 | ||
561 | /* Memory limit */ | 598 | /* Memory limit */ |
562 | if (var->yres_virtual * xdr_line_length > ps3fb.xdr_size) { | 599 | if (var->yres_virtual * xdr_line_length > info->fix.smem_len) { |
563 | dev_dbg(info->device, "Not enough memory\n"); | 600 | dev_dbg(info->device, "Not enough memory\n"); |
564 | return -ENOMEM; | 601 | return -ENOMEM; |
565 | } | 602 | } |
@@ -578,39 +615,38 @@ static int ps3fb_set_par(struct fb_info *info) | |||
578 | { | 615 | { |
579 | struct ps3fb_par *par = info->par; | 616 | struct ps3fb_par *par = info->par; |
580 | unsigned int mode, ddr_line_length, xdr_line_length, lines, maxlines; | 617 | unsigned int mode, ddr_line_length, xdr_line_length, lines, maxlines; |
581 | int i; | 618 | unsigned int ddr_xoff, ddr_yoff, offset; |
582 | unsigned long offset; | 619 | const struct fb_videomode *vmode; |
583 | u64 dst; | 620 | u64 dst; |
584 | 621 | ||
585 | dev_dbg(info->device, "xres:%d xv:%d yres:%d yv:%d clock:%d\n", | ||
586 | info->var.xres, info->var.xres_virtual, | ||
587 | info->var.yres, info->var.yres_virtual, info->var.pixclock); | ||
588 | |||
589 | mode = ps3fb_find_mode(&info->var, &ddr_line_length, &xdr_line_length); | 622 | mode = ps3fb_find_mode(&info->var, &ddr_line_length, &xdr_line_length); |
590 | if (!mode) | 623 | if (!mode) |
591 | return -EINVAL; | 624 | return -EINVAL; |
592 | 625 | ||
593 | i = ps3fb_get_res_table(info->var.xres, info->var.yres, mode); | 626 | vmode = ps3fb_native_vmode(mode & PS3AV_MODE_MASK); |
594 | par->res_index = i; | ||
595 | 627 | ||
596 | info->fix.smem_start = virt_to_abs(ps3fb.xdr_ea); | ||
597 | info->fix.smem_len = ps3fb.xdr_size; | ||
598 | info->fix.xpanstep = info->var.xres_virtual > info->var.xres ? 1 : 0; | 628 | info->fix.xpanstep = info->var.xres_virtual > info->var.xres ? 1 : 0; |
599 | info->fix.ypanstep = info->var.yres_virtual > info->var.yres ? 1 : 0; | 629 | info->fix.ypanstep = info->var.yres_virtual > info->var.yres ? 1 : 0; |
600 | info->fix.line_length = xdr_line_length; | 630 | info->fix.line_length = xdr_line_length; |
601 | 631 | ||
602 | info->screen_base = (char __iomem *)ps3fb.xdr_ea; | 632 | par->ddr_line_length = ddr_line_length; |
633 | par->ddr_frame_size = vmode->yres * ddr_line_length; | ||
634 | par->xdr_frame_size = info->var.yres_virtual * xdr_line_length; | ||
603 | 635 | ||
604 | par->num_frames = ps3fb.xdr_size / | 636 | par->num_frames = info->fix.smem_len / |
605 | max(ps3fb_res[i].yres * ddr_line_length, | 637 | max(par->ddr_frame_size, par->xdr_frame_size); |
606 | info->var.yres_virtual * xdr_line_length); | ||
607 | 638 | ||
608 | /* Keep the special bits we cannot set using fb_var_screeninfo */ | 639 | /* Keep the special bits we cannot set using fb_var_screeninfo */ |
609 | par->new_mode_id = (par->new_mode_id & ~PS3AV_MODE_MASK) | mode; | 640 | par->new_mode_id = (par->new_mode_id & ~PS3AV_MODE_MASK) | mode; |
610 | 641 | ||
611 | par->width = info->var.xres; | 642 | par->width = info->var.xres; |
612 | par->height = info->var.yres; | 643 | par->height = info->var.yres; |
613 | offset = VP_OFF(i); | 644 | |
645 | /* Start of the virtual frame buffer (relative to fullscreen) */ | ||
646 | ddr_xoff = info->var.left_margin - vmode->left_margin; | ||
647 | ddr_yoff = info->var.upper_margin - vmode->upper_margin; | ||
648 | offset = ddr_yoff * ddr_line_length + ddr_xoff * BPP; | ||
649 | |||
614 | par->fb_offset = GPU_ALIGN_UP(offset); | 650 | par->fb_offset = GPU_ALIGN_UP(offset); |
615 | par->full_offset = par->fb_offset - offset; | 651 | par->full_offset = par->fb_offset - offset; |
616 | par->pan_offset = info->var.yoffset * xdr_line_length + | 652 | par->pan_offset = info->var.yoffset * xdr_line_length + |
@@ -625,16 +661,16 @@ static int ps3fb_set_par(struct fb_info *info) | |||
625 | } | 661 | } |
626 | 662 | ||
627 | /* Clear XDR frame buffer memory */ | 663 | /* Clear XDR frame buffer memory */ |
628 | memset(ps3fb.xdr_ea, 0, ps3fb.xdr_size); | 664 | memset((void __force *)info->screen_base, 0, info->fix.smem_len); |
629 | 665 | ||
630 | /* Clear DDR frame buffer memory */ | 666 | /* Clear DDR frame buffer memory */ |
631 | lines = ps3fb_res[i].yres * par->num_frames; | 667 | lines = vmode->yres * par->num_frames; |
632 | if (par->full_offset) | 668 | if (par->full_offset) |
633 | lines++; | 669 | lines++; |
634 | maxlines = ps3fb.xdr_size / ddr_line_length; | 670 | maxlines = info->fix.smem_len / ddr_line_length; |
635 | for (dst = 0; lines; dst += maxlines * ddr_line_length) { | 671 | for (dst = 0; lines; dst += maxlines * ddr_line_length) { |
636 | unsigned int l = min(lines, maxlines); | 672 | unsigned int l = min(lines, maxlines); |
637 | ps3fb_sync_image(info->device, 0, dst, 0, ps3fb_res[i].xres, l, | 673 | ps3fb_sync_image(info->device, 0, dst, 0, vmode->xres, l, |
638 | ddr_line_length, ddr_line_length); | 674 | ddr_line_length, ddr_line_length); |
639 | lines -= l; | 675 | lines -= l; |
640 | } | 676 | } |
@@ -797,7 +833,7 @@ static int ps3fb_ioctl(struct fb_info *info, unsigned int cmd, | |||
797 | case PS3FB_IOCTL_SETMODE: | 833 | case PS3FB_IOCTL_SETMODE: |
798 | { | 834 | { |
799 | struct ps3fb_par *par = info->par; | 835 | struct ps3fb_par *par = info->par; |
800 | const struct fb_videomode *mode; | 836 | const struct fb_videomode *vmode; |
801 | struct fb_var_screeninfo var; | 837 | struct fb_var_screeninfo var; |
802 | 838 | ||
803 | if (copy_from_user(&val, argp, sizeof(val))) | 839 | if (copy_from_user(&val, argp, sizeof(val))) |
@@ -810,10 +846,10 @@ static int ps3fb_ioctl(struct fb_info *info, unsigned int cmd, | |||
810 | } | 846 | } |
811 | dev_dbg(info->device, "PS3FB_IOCTL_SETMODE:%x\n", val); | 847 | dev_dbg(info->device, "PS3FB_IOCTL_SETMODE:%x\n", val); |
812 | retval = -EINVAL; | 848 | retval = -EINVAL; |
813 | mode = ps3fb_default_mode(val); | 849 | vmode = ps3fb_vmode(val); |
814 | if (mode) { | 850 | if (vmode) { |
815 | var = info->var; | 851 | var = info->var; |
816 | fb_videomode_to_var(&var, mode); | 852 | fb_videomode_to_var(&var, vmode); |
817 | acquire_console_sem(); | 853 | acquire_console_sem(); |
818 | info->flags |= FBINFO_MISC_USEREVENT; | 854 | info->flags |= FBINFO_MISC_USEREVENT; |
819 | /* Force, in case only special bits changed */ | 855 | /* Force, in case only special bits changed */ |
@@ -975,10 +1011,9 @@ static int ps3fb_xdr_settings(u64 xdr_lpar, struct device *dev) | |||
975 | __func__, status); | 1011 | __func__, status); |
976 | return -ENXIO; | 1012 | return -ENXIO; |
977 | } | 1013 | } |
978 | dev_dbg(dev, | 1014 | dev_dbg(dev, "video:%p ioif:%lx lpar:%lx size:%lx\n", |
979 | "video:%p xdr_ea:%p ioif:%lx lpar:%lx phys:%lx size:%lx\n", | 1015 | ps3fb_videomemory.address, GPU_IOIF, xdr_lpar, |
980 | ps3fb_videomemory.address, ps3fb.xdr_ea, GPU_IOIF, xdr_lpar, | 1016 | ps3fb_videomemory.size); |
981 | virt_to_abs(ps3fb.xdr_ea), ps3fb_videomemory.size); | ||
982 | 1017 | ||
983 | status = lv1_gpu_context_attribute(ps3fb.context_handle, | 1018 | status = lv1_gpu_context_attribute(ps3fb.context_handle, |
984 | L1GPU_CONTEXT_ATTRIBUTE_FB_SETUP, | 1019 | L1GPU_CONTEXT_ATTRIBUTE_FB_SETUP, |
@@ -1055,14 +1090,14 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev) | |||
1055 | struct fb_info *info; | 1090 | struct fb_info *info; |
1056 | struct ps3fb_par *par; | 1091 | struct ps3fb_par *par; |
1057 | int retval = -ENOMEM; | 1092 | int retval = -ENOMEM; |
1058 | u32 xres, yres; | ||
1059 | u64 ddr_lpar = 0; | 1093 | u64 ddr_lpar = 0; |
1060 | u64 lpar_dma_control = 0; | 1094 | u64 lpar_dma_control = 0; |
1061 | u64 lpar_driver_info = 0; | 1095 | u64 lpar_driver_info = 0; |
1062 | u64 lpar_reports = 0; | 1096 | u64 lpar_reports = 0; |
1063 | u64 lpar_reports_size = 0; | 1097 | u64 lpar_reports_size = 0; |
1064 | u64 xdr_lpar; | 1098 | u64 xdr_lpar; |
1065 | int status, res_index; | 1099 | void *fb_start; |
1100 | int status; | ||
1066 | struct task_struct *task; | 1101 | struct task_struct *task; |
1067 | unsigned long max_ps3fb_size; | 1102 | unsigned long max_ps3fb_size; |
1068 | 1103 | ||
@@ -1080,14 +1115,7 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev) | |||
1080 | 1115 | ||
1081 | if (!ps3fb_mode) | 1116 | if (!ps3fb_mode) |
1082 | ps3fb_mode = ps3av_get_mode(); | 1117 | ps3fb_mode = ps3av_get_mode(); |
1083 | dev_dbg(&dev->core, "ps3av_mode:%d\n", ps3fb_mode); | 1118 | dev_dbg(&dev->core, "ps3fb_mode: %d\n", ps3fb_mode); |
1084 | |||
1085 | if (ps3fb_mode > 0 && | ||
1086 | !ps3av_video_mode2res(ps3fb_mode, &xres, &yres)) { | ||
1087 | res_index = ps3fb_get_res_table(xres, yres, ps3fb_mode); | ||
1088 | dev_dbg(&dev->core, "res_index:%d\n", res_index); | ||
1089 | } else | ||
1090 | res_index = GPU_RES_INDEX; | ||
1091 | 1119 | ||
1092 | atomic_set(&ps3fb.f_count, -1); /* fbcon opens ps3fb */ | 1120 | atomic_set(&ps3fb.f_count, -1); /* fbcon opens ps3fb */ |
1093 | atomic_set(&ps3fb.ext_flip, 0); /* for flip with vsync */ | 1121 | atomic_set(&ps3fb.ext_flip, 0); /* for flip with vsync */ |
@@ -1124,7 +1152,7 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev) | |||
1124 | } | 1152 | } |
1125 | 1153 | ||
1126 | /* vsync interrupt */ | 1154 | /* vsync interrupt */ |
1127 | ps3fb.dinfo = ioremap(lpar_driver_info, 128 * 1024); | 1155 | ps3fb.dinfo = (void __force *)ioremap(lpar_driver_info, 128 * 1024); |
1128 | if (!ps3fb.dinfo) { | 1156 | if (!ps3fb.dinfo) { |
1129 | dev_err(&dev->core, "%s: ioremap failed\n", __func__); | 1157 | dev_err(&dev->core, "%s: ioremap failed\n", __func__); |
1130 | goto err_gpu_context_free; | 1158 | goto err_gpu_context_free; |
@@ -1134,22 +1162,10 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev) | |||
1134 | if (retval) | 1162 | if (retval) |
1135 | goto err_iounmap_dinfo; | 1163 | goto err_iounmap_dinfo; |
1136 | 1164 | ||
1137 | /* XDR frame buffer */ | ||
1138 | ps3fb.xdr_ea = ps3fb_videomemory.address; | ||
1139 | xdr_lpar = ps3_mm_phys_to_lpar(__pa(ps3fb.xdr_ea)); | ||
1140 | |||
1141 | /* Clear memory to prevent kernel info leakage into userspace */ | 1165 | /* Clear memory to prevent kernel info leakage into userspace */ |
1142 | memset(ps3fb.xdr_ea, 0, ps3fb_videomemory.size); | 1166 | memset(ps3fb_videomemory.address, 0, ps3fb_videomemory.size); |
1143 | |||
1144 | /* | ||
1145 | * The GPU command buffer is at the start of video memory | ||
1146 | * As we don't use the full command buffer, we can put the actual | ||
1147 | * frame buffer at offset GPU_FB_START and save some precious XDR | ||
1148 | * memory | ||
1149 | */ | ||
1150 | ps3fb.xdr_ea += GPU_FB_START; | ||
1151 | ps3fb.xdr_size = ps3fb_videomemory.size - GPU_FB_START; | ||
1152 | 1167 | ||
1168 | xdr_lpar = ps3_mm_phys_to_lpar(__pa(ps3fb_videomemory.address)); | ||
1153 | retval = ps3fb_xdr_settings(xdr_lpar, &dev->core); | 1169 | retval = ps3fb_xdr_settings(xdr_lpar, &dev->core); |
1154 | if (retval) | 1170 | if (retval) |
1155 | goto err_free_irq; | 1171 | goto err_free_irq; |
@@ -1161,15 +1177,22 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev) | |||
1161 | par = info->par; | 1177 | par = info->par; |
1162 | par->mode_id = ~ps3fb_mode; /* != ps3fb_mode, to trigger change */ | 1178 | par->mode_id = ~ps3fb_mode; /* != ps3fb_mode, to trigger change */ |
1163 | par->new_mode_id = ps3fb_mode; | 1179 | par->new_mode_id = ps3fb_mode; |
1164 | par->res_index = res_index; | ||
1165 | par->num_frames = 1; | 1180 | par->num_frames = 1; |
1166 | 1181 | ||
1167 | info->screen_base = (char __iomem *)ps3fb.xdr_ea; | ||
1168 | info->fbops = &ps3fb_ops; | 1182 | info->fbops = &ps3fb_ops; |
1169 | |||
1170 | info->fix = ps3fb_fix; | 1183 | info->fix = ps3fb_fix; |
1171 | info->fix.smem_start = virt_to_abs(ps3fb.xdr_ea); | 1184 | |
1172 | info->fix.smem_len = ps3fb.xdr_size; | 1185 | /* |
1186 | * The GPU command buffer is at the start of video memory | ||
1187 | * As we don't use the full command buffer, we can put the actual | ||
1188 | * frame buffer at offset GPU_FB_START and save some precious XDR | ||
1189 | * memory | ||
1190 | */ | ||
1191 | fb_start = ps3fb_videomemory.address + GPU_FB_START; | ||
1192 | info->screen_base = (char __force __iomem *)fb_start; | ||
1193 | info->fix.smem_start = virt_to_abs(fb_start); | ||
1194 | info->fix.smem_len = ps3fb_videomemory.size - GPU_FB_START; | ||
1195 | |||
1173 | info->pseudo_palette = par->pseudo_palette; | 1196 | info->pseudo_palette = par->pseudo_palette; |
1174 | info->flags = FBINFO_DEFAULT | FBINFO_READS_FAST | | 1197 | info->flags = FBINFO_DEFAULT | FBINFO_READS_FAST | |
1175 | FBINFO_HWACCEL_XPAN | FBINFO_HWACCEL_YPAN; | 1198 | FBINFO_HWACCEL_XPAN | FBINFO_HWACCEL_YPAN; |
@@ -1180,7 +1203,7 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev) | |||
1180 | 1203 | ||
1181 | if (!fb_find_mode(&info->var, info, mode_option, ps3fb_modedb, | 1204 | if (!fb_find_mode(&info->var, info, mode_option, ps3fb_modedb, |
1182 | ARRAY_SIZE(ps3fb_modedb), | 1205 | ARRAY_SIZE(ps3fb_modedb), |
1183 | ps3fb_default_mode(par->new_mode_id), 32)) { | 1206 | ps3fb_vmode(par->new_mode_id), 32)) { |
1184 | retval = -EINVAL; | 1207 | retval = -EINVAL; |
1185 | goto err_fb_dealloc; | 1208 | goto err_fb_dealloc; |
1186 | } | 1209 | } |
@@ -1194,9 +1217,9 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev) | |||
1194 | 1217 | ||
1195 | dev->core.driver_data = info; | 1218 | dev->core.driver_data = info; |
1196 | 1219 | ||
1197 | dev_info(info->device, "%s %s, using %lu KiB of video memory\n", | 1220 | dev_info(info->device, "%s %s, using %u KiB of video memory\n", |
1198 | dev_driver_string(info->dev), info->dev->bus_id, | 1221 | dev_driver_string(info->dev), info->dev->bus_id, |
1199 | ps3fb.xdr_size >> 10); | 1222 | info->fix.smem_len >> 10); |
1200 | 1223 | ||
1201 | task = kthread_run(ps3fbd, info, DEVICE_NAME); | 1224 | task = kthread_run(ps3fbd, info, DEVICE_NAME); |
1202 | if (IS_ERR(task)) { | 1225 | if (IS_ERR(task)) { |
@@ -1219,7 +1242,7 @@ err_free_irq: | |||
1219 | free_irq(ps3fb.irq_no, &dev->core); | 1242 | free_irq(ps3fb.irq_no, &dev->core); |
1220 | ps3_irq_plug_destroy(ps3fb.irq_no); | 1243 | ps3_irq_plug_destroy(ps3fb.irq_no); |
1221 | err_iounmap_dinfo: | 1244 | err_iounmap_dinfo: |
1222 | iounmap((u8 __iomem *)ps3fb.dinfo); | 1245 | iounmap((u8 __force __iomem *)ps3fb.dinfo); |
1223 | err_gpu_context_free: | 1246 | err_gpu_context_free: |
1224 | lv1_gpu_context_free(ps3fb.context_handle); | 1247 | lv1_gpu_context_free(ps3fb.context_handle); |
1225 | err_gpu_memory_free: | 1248 | err_gpu_memory_free: |
@@ -1254,7 +1277,7 @@ static int ps3fb_shutdown(struct ps3_system_bus_device *dev) | |||
1254 | framebuffer_release(info); | 1277 | framebuffer_release(info); |
1255 | info = dev->core.driver_data = NULL; | 1278 | info = dev->core.driver_data = NULL; |
1256 | } | 1279 | } |
1257 | iounmap((u8 __iomem *)ps3fb.dinfo); | 1280 | iounmap((u8 __force __iomem *)ps3fb.dinfo); |
1258 | 1281 | ||
1259 | status = lv1_gpu_context_free(ps3fb.context_handle); | 1282 | status = lv1_gpu_context_free(ps3fb.context_handle); |
1260 | if (status) | 1283 | if (status) |
diff --git a/drivers/video/s3c2410fb.c b/drivers/video/s3c2410fb.c index b3c31d9dc591..71fa6edb5c47 100644 --- a/drivers/video/s3c2410fb.c +++ b/drivers/video/s3c2410fb.c | |||
@@ -110,6 +110,11 @@ static int debug = 0; | |||
110 | 110 | ||
111 | /* useful functions */ | 111 | /* useful functions */ |
112 | 112 | ||
113 | static int is_s3c2412(struct s3c2410fb_info *fbi) | ||
114 | { | ||
115 | return (fbi->drv_type == DRV_S3C2412); | ||
116 | } | ||
117 | |||
113 | /* s3c2410fb_set_lcdaddr | 118 | /* s3c2410fb_set_lcdaddr |
114 | * | 119 | * |
115 | * initialise lcd controller address pointers | 120 | * initialise lcd controller address pointers |
@@ -501,7 +506,7 @@ static void schedule_palette_update(struct s3c2410fb_info *fbi, | |||
501 | { | 506 | { |
502 | unsigned long flags; | 507 | unsigned long flags; |
503 | unsigned long irqen; | 508 | unsigned long irqen; |
504 | void __iomem *regs = fbi->io; | 509 | void __iomem *irq_base = fbi->irq_base; |
505 | 510 | ||
506 | local_irq_save(flags); | 511 | local_irq_save(flags); |
507 | 512 | ||
@@ -511,9 +516,9 @@ static void schedule_palette_update(struct s3c2410fb_info *fbi, | |||
511 | fbi->palette_ready = 1; | 516 | fbi->palette_ready = 1; |
512 | 517 | ||
513 | /* enable IRQ */ | 518 | /* enable IRQ */ |
514 | irqen = readl(regs + S3C2410_LCDINTMSK); | 519 | irqen = readl(irq_base + S3C24XX_LCDINTMSK); |
515 | irqen &= ~S3C2410_LCDINT_FRSYNC; | 520 | irqen &= ~S3C2410_LCDINT_FRSYNC; |
516 | writel(irqen, regs + S3C2410_LCDINTMSK); | 521 | writel(irqen, irq_base + S3C24XX_LCDINTMSK); |
517 | } | 522 | } |
518 | 523 | ||
519 | local_irq_restore(flags); | 524 | local_irq_restore(flags); |
@@ -594,15 +599,17 @@ static int s3c2410fb_setcolreg(unsigned regno, | |||
594 | static int s3c2410fb_blank(int blank_mode, struct fb_info *info) | 599 | static int s3c2410fb_blank(int blank_mode, struct fb_info *info) |
595 | { | 600 | { |
596 | struct s3c2410fb_info *fbi = info->par; | 601 | struct s3c2410fb_info *fbi = info->par; |
597 | void __iomem *regs = fbi->io; | 602 | void __iomem *tpal_reg = fbi->io; |
598 | 603 | ||
599 | dprintk("blank(mode=%d, info=%p)\n", blank_mode, info); | 604 | dprintk("blank(mode=%d, info=%p)\n", blank_mode, info); |
600 | 605 | ||
606 | tpal_reg += is_s3c2412(fbi) ? S3C2412_TPAL : S3C2410_TPAL; | ||
607 | |||
601 | if (blank_mode == FB_BLANK_UNBLANK) | 608 | if (blank_mode == FB_BLANK_UNBLANK) |
602 | writel(0x0, regs + S3C2410_TPAL); | 609 | writel(0x0, tpal_reg); |
603 | else { | 610 | else { |
604 | dprintk("setting TPAL to output 0x000000\n"); | 611 | dprintk("setting TPAL to output 0x000000\n"); |
605 | writel(S3C2410_TPAL_EN, regs + S3C2410_TPAL); | 612 | writel(S3C2410_TPAL_EN, tpal_reg); |
606 | } | 613 | } |
607 | 614 | ||
608 | return 0; | 615 | return 0; |
@@ -663,7 +670,7 @@ static int __init s3c2410fb_map_video_memory(struct fb_info *info) | |||
663 | dma_addr_t map_dma; | 670 | dma_addr_t map_dma; |
664 | unsigned map_size = PAGE_ALIGN(info->fix.smem_len); | 671 | unsigned map_size = PAGE_ALIGN(info->fix.smem_len); |
665 | 672 | ||
666 | dprintk("map_video_memory(fbi=%p)\n", fbi); | 673 | dprintk("map_video_memory(fbi=%p) map_size %u\n", fbi, map_size); |
667 | 674 | ||
668 | info->screen_base = dma_alloc_writecombine(fbi->dev, map_size, | 675 | info->screen_base = dma_alloc_writecombine(fbi->dev, map_size, |
669 | &map_dma, GFP_KERNEL); | 676 | &map_dma, GFP_KERNEL); |
@@ -672,7 +679,7 @@ static int __init s3c2410fb_map_video_memory(struct fb_info *info) | |||
672 | /* prevent initial garbage on screen */ | 679 | /* prevent initial garbage on screen */ |
673 | dprintk("map_video_memory: clear %p:%08x\n", | 680 | dprintk("map_video_memory: clear %p:%08x\n", |
674 | info->screen_base, map_size); | 681 | info->screen_base, map_size); |
675 | memset(info->screen_base, 0xf0, map_size); | 682 | memset(info->screen_base, 0x00, map_size); |
676 | 683 | ||
677 | info->fix.smem_start = map_dma; | 684 | info->fix.smem_start = map_dma; |
678 | 685 | ||
@@ -709,6 +716,16 @@ static int s3c2410fb_init_registers(struct fb_info *info) | |||
709 | struct s3c2410fb_mach_info *mach_info = fbi->dev->platform_data; | 716 | struct s3c2410fb_mach_info *mach_info = fbi->dev->platform_data; |
710 | unsigned long flags; | 717 | unsigned long flags; |
711 | void __iomem *regs = fbi->io; | 718 | void __iomem *regs = fbi->io; |
719 | void __iomem *tpal; | ||
720 | void __iomem *lpcsel; | ||
721 | |||
722 | if (is_s3c2412(fbi)) { | ||
723 | tpal = regs + S3C2412_TPAL; | ||
724 | lpcsel = regs + S3C2412_TCONSEL; | ||
725 | } else { | ||
726 | tpal = regs + S3C2410_TPAL; | ||
727 | lpcsel = regs + S3C2410_LPCSEL; | ||
728 | } | ||
712 | 729 | ||
713 | /* Initialise LCD with values from haret */ | 730 | /* Initialise LCD with values from haret */ |
714 | 731 | ||
@@ -724,12 +741,12 @@ static int s3c2410fb_init_registers(struct fb_info *info) | |||
724 | local_irq_restore(flags); | 741 | local_irq_restore(flags); |
725 | 742 | ||
726 | dprintk("LPCSEL = 0x%08lx\n", mach_info->lpcsel); | 743 | dprintk("LPCSEL = 0x%08lx\n", mach_info->lpcsel); |
727 | writel(mach_info->lpcsel, regs + S3C2410_LPCSEL); | 744 | writel(mach_info->lpcsel, lpcsel); |
728 | 745 | ||
729 | dprintk("replacing TPAL %08x\n", readl(regs + S3C2410_TPAL)); | 746 | dprintk("replacing TPAL %08x\n", readl(tpal)); |
730 | 747 | ||
731 | /* ensure temporary palette disabled */ | 748 | /* ensure temporary palette disabled */ |
732 | writel(0x00, regs + S3C2410_TPAL); | 749 | writel(0x00, tpal); |
733 | 750 | ||
734 | return 0; | 751 | return 0; |
735 | } | 752 | } |
@@ -763,15 +780,15 @@ static void s3c2410fb_write_palette(struct s3c2410fb_info *fbi) | |||
763 | static irqreturn_t s3c2410fb_irq(int irq, void *dev_id) | 780 | static irqreturn_t s3c2410fb_irq(int irq, void *dev_id) |
764 | { | 781 | { |
765 | struct s3c2410fb_info *fbi = dev_id; | 782 | struct s3c2410fb_info *fbi = dev_id; |
766 | void __iomem *regs = fbi->io; | 783 | void __iomem *irq_base = fbi->irq_base; |
767 | unsigned long lcdirq = readl(regs + S3C2410_LCDINTPND); | 784 | unsigned long lcdirq = readl(irq_base + S3C24XX_LCDINTPND); |
768 | 785 | ||
769 | if (lcdirq & S3C2410_LCDINT_FRSYNC) { | 786 | if (lcdirq & S3C2410_LCDINT_FRSYNC) { |
770 | if (fbi->palette_ready) | 787 | if (fbi->palette_ready) |
771 | s3c2410fb_write_palette(fbi); | 788 | s3c2410fb_write_palette(fbi); |
772 | 789 | ||
773 | writel(S3C2410_LCDINT_FRSYNC, regs + S3C2410_LCDINTPND); | 790 | writel(S3C2410_LCDINT_FRSYNC, irq_base + S3C24XX_LCDINTPND); |
774 | writel(S3C2410_LCDINT_FRSYNC, regs + S3C2410_LCDSRCPND); | 791 | writel(S3C2410_LCDINT_FRSYNC, irq_base + S3C24XX_LCDSRCPND); |
775 | } | 792 | } |
776 | 793 | ||
777 | return IRQ_HANDLED; | 794 | return IRQ_HANDLED; |
@@ -779,7 +796,8 @@ static irqreturn_t s3c2410fb_irq(int irq, void *dev_id) | |||
779 | 796 | ||
780 | static char driver_name[] = "s3c2410fb"; | 797 | static char driver_name[] = "s3c2410fb"; |
781 | 798 | ||
782 | static int __init s3c2410fb_probe(struct platform_device *pdev) | 799 | static int __init s3c24xxfb_probe(struct platform_device *pdev, |
800 | enum s3c_drv_type drv_type) | ||
783 | { | 801 | { |
784 | struct s3c2410fb_info *info; | 802 | struct s3c2410fb_info *info; |
785 | struct s3c2410fb_display *display; | 803 | struct s3c2410fb_display *display; |
@@ -799,6 +817,12 @@ static int __init s3c2410fb_probe(struct platform_device *pdev) | |||
799 | return -EINVAL; | 817 | return -EINVAL; |
800 | } | 818 | } |
801 | 819 | ||
820 | if (mach_info->default_display >= mach_info->num_displays) { | ||
821 | dev_err(&pdev->dev, "default is %d but only %d displays\n", | ||
822 | mach_info->default_display, mach_info->num_displays); | ||
823 | return -EINVAL; | ||
824 | } | ||
825 | |||
802 | display = mach_info->displays + mach_info->default_display; | 826 | display = mach_info->displays + mach_info->default_display; |
803 | 827 | ||
804 | irq = platform_get_irq(pdev, 0); | 828 | irq = platform_get_irq(pdev, 0); |
@@ -815,6 +839,7 @@ static int __init s3c2410fb_probe(struct platform_device *pdev) | |||
815 | 839 | ||
816 | info = fbinfo->par; | 840 | info = fbinfo->par; |
817 | info->dev = &pdev->dev; | 841 | info->dev = &pdev->dev; |
842 | info->drv_type = drv_type; | ||
818 | 843 | ||
819 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 844 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
820 | if (res == NULL) { | 845 | if (res == NULL) { |
@@ -838,6 +863,8 @@ static int __init s3c2410fb_probe(struct platform_device *pdev) | |||
838 | goto release_mem; | 863 | goto release_mem; |
839 | } | 864 | } |
840 | 865 | ||
866 | info->irq_base = info->io + ((drv_type == DRV_S3C2412) ? S3C2412_LCDINTBASE : S3C2410_LCDINTBASE); | ||
867 | |||
841 | dprintk("devinit\n"); | 868 | dprintk("devinit\n"); |
842 | 869 | ||
843 | strcpy(fbinfo->fix.id, driver_name); | 870 | strcpy(fbinfo->fix.id, driver_name); |
@@ -946,6 +973,16 @@ dealloc_fb: | |||
946 | return ret; | 973 | return ret; |
947 | } | 974 | } |
948 | 975 | ||
976 | static int __init s3c2410fb_probe(struct platform_device *pdev) | ||
977 | { | ||
978 | return s3c24xxfb_probe(pdev, DRV_S3C2410); | ||
979 | } | ||
980 | |||
981 | static int __init s3c2412fb_probe(struct platform_device *pdev) | ||
982 | { | ||
983 | return s3c24xxfb_probe(pdev, DRV_S3C2412); | ||
984 | } | ||
985 | |||
949 | /* s3c2410fb_stop_lcd | 986 | /* s3c2410fb_stop_lcd |
950 | * | 987 | * |
951 | * shutdown the lcd controller | 988 | * shutdown the lcd controller |
@@ -1047,14 +1084,31 @@ static struct platform_driver s3c2410fb_driver = { | |||
1047 | }, | 1084 | }, |
1048 | }; | 1085 | }; |
1049 | 1086 | ||
1087 | static struct platform_driver s3c2412fb_driver = { | ||
1088 | .probe = s3c2412fb_probe, | ||
1089 | .remove = s3c2410fb_remove, | ||
1090 | .suspend = s3c2410fb_suspend, | ||
1091 | .resume = s3c2410fb_resume, | ||
1092 | .driver = { | ||
1093 | .name = "s3c2412-lcd", | ||
1094 | .owner = THIS_MODULE, | ||
1095 | }, | ||
1096 | }; | ||
1097 | |||
1050 | int __init s3c2410fb_init(void) | 1098 | int __init s3c2410fb_init(void) |
1051 | { | 1099 | { |
1052 | return platform_driver_register(&s3c2410fb_driver); | 1100 | int ret = platform_driver_register(&s3c2410fb_driver); |
1101 | |||
1102 | if (ret == 0) | ||
1103 | ret = platform_driver_register(&s3c2412fb_driver);; | ||
1104 | |||
1105 | return ret; | ||
1053 | } | 1106 | } |
1054 | 1107 | ||
1055 | static void __exit s3c2410fb_cleanup(void) | 1108 | static void __exit s3c2410fb_cleanup(void) |
1056 | { | 1109 | { |
1057 | platform_driver_unregister(&s3c2410fb_driver); | 1110 | platform_driver_unregister(&s3c2410fb_driver); |
1111 | platform_driver_unregister(&s3c2412fb_driver); | ||
1058 | } | 1112 | } |
1059 | 1113 | ||
1060 | module_init(s3c2410fb_init); | 1114 | module_init(s3c2410fb_init); |
diff --git a/drivers/video/s3c2410fb.h b/drivers/video/s3c2410fb.h index 6ce5dc26c5f7..dbb73b95e2ef 100644 --- a/drivers/video/s3c2410fb.h +++ b/drivers/video/s3c2410fb.h | |||
@@ -25,13 +25,20 @@ | |||
25 | #ifndef __S3C2410FB_H | 25 | #ifndef __S3C2410FB_H |
26 | #define __S3C2410FB_H | 26 | #define __S3C2410FB_H |
27 | 27 | ||
28 | enum s3c_drv_type { | ||
29 | DRV_S3C2410, | ||
30 | DRV_S3C2412, | ||
31 | }; | ||
32 | |||
28 | struct s3c2410fb_info { | 33 | struct s3c2410fb_info { |
29 | struct device *dev; | 34 | struct device *dev; |
30 | struct clk *clk; | 35 | struct clk *clk; |
31 | 36 | ||
32 | struct resource *mem; | 37 | struct resource *mem; |
33 | void __iomem *io; | 38 | void __iomem *io; |
39 | void __iomem *irq_base; | ||
34 | 40 | ||
41 | enum s3c_drv_type drv_type; | ||
35 | struct s3c2410fb_hw regs; | 42 | struct s3c2410fb_hw regs; |
36 | 43 | ||
37 | unsigned int palette_ready; | 44 | unsigned int palette_ready; |
diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c index 93ae747440cb..73803624c131 100644 --- a/drivers/video/sis/sis_main.c +++ b/drivers/video/sis/sis_main.c | |||
@@ -427,7 +427,7 @@ sisfb_interpret_edid(struct sisfb_monitor *monitor, u8 *buffer) | |||
427 | 427 | ||
428 | monitor->feature = buffer[0x18]; | 428 | monitor->feature = buffer[0x18]; |
429 | 429 | ||
430 | if(!buffer[0x14] & 0x80) { | 430 | if(!(buffer[0x14] & 0x80)) { |
431 | if(!(buffer[0x14] & 0x08)) { | 431 | if(!(buffer[0x14] & 0x08)) { |
432 | printk(KERN_INFO | 432 | printk(KERN_INFO |
433 | "sisfb: WARNING: Monitor does not support separate syncs\n"); | 433 | "sisfb: WARNING: Monitor does not support separate syncs\n"); |
@@ -4621,9 +4621,9 @@ sisfb_find_host_bridge(struct sis_video_info *ivideo, struct pci_dev *mypdev, | |||
4621 | 4621 | ||
4622 | while((pdev = pci_get_class(PCI_CLASS_BRIDGE_HOST, pdev))) { | 4622 | while((pdev = pci_get_class(PCI_CLASS_BRIDGE_HOST, pdev))) { |
4623 | temp = pdev->vendor; | 4623 | temp = pdev->vendor; |
4624 | pci_dev_put(pdev); | ||
4625 | if(temp == pcivendor) { | 4624 | if(temp == pcivendor) { |
4626 | ret = 1; | 4625 | ret = 1; |
4626 | pci_dev_put(pdev); | ||
4627 | break; | 4627 | break; |
4628 | } | 4628 | } |
4629 | } | 4629 | } |
diff --git a/drivers/video/sm501fb.c b/drivers/video/sm501fb.c index 58f200c69be3..e83dfba7e636 100644 --- a/drivers/video/sm501fb.c +++ b/drivers/video/sm501fb.c | |||
@@ -641,6 +641,7 @@ static void sm501fb_panel_power(struct sm501fb_info *fbi, int to) | |||
641 | { | 641 | { |
642 | unsigned long control; | 642 | unsigned long control; |
643 | void __iomem *ctrl_reg = fbi->regs + SM501_DC_PANEL_CONTROL; | 643 | void __iomem *ctrl_reg = fbi->regs + SM501_DC_PANEL_CONTROL; |
644 | struct sm501_platdata_fbsub *pd = fbi->pdata->fb_pnl; | ||
644 | 645 | ||
645 | control = readl(ctrl_reg); | 646 | control = readl(ctrl_reg); |
646 | 647 | ||
@@ -657,26 +658,34 @@ static void sm501fb_panel_power(struct sm501fb_info *fbi, int to) | |||
657 | sm501fb_sync_regs(fbi); | 658 | sm501fb_sync_regs(fbi); |
658 | mdelay(10); | 659 | mdelay(10); |
659 | 660 | ||
660 | control |= SM501_DC_PANEL_CONTROL_BIAS; /* VBIASEN */ | 661 | if (pd->flags & SM501FB_FLAG_PANEL_USE_VBIASEN) { |
661 | writel(control, ctrl_reg); | 662 | control |= SM501_DC_PANEL_CONTROL_BIAS; /* VBIASEN */ |
662 | sm501fb_sync_regs(fbi); | 663 | writel(control, ctrl_reg); |
663 | mdelay(10); | 664 | sm501fb_sync_regs(fbi); |
664 | 665 | mdelay(10); | |
665 | control |= SM501_DC_PANEL_CONTROL_FPEN; | 666 | } |
666 | writel(control, ctrl_reg); | ||
667 | 667 | ||
668 | if (pd->flags & SM501FB_FLAG_PANEL_USE_FPEN) { | ||
669 | control |= SM501_DC_PANEL_CONTROL_FPEN; | ||
670 | writel(control, ctrl_reg); | ||
671 | sm501fb_sync_regs(fbi); | ||
672 | mdelay(10); | ||
673 | } | ||
668 | } else if (!to && (control & SM501_DC_PANEL_CONTROL_VDD) != 0) { | 674 | } else if (!to && (control & SM501_DC_PANEL_CONTROL_VDD) != 0) { |
669 | /* disable panel power */ | 675 | /* disable panel power */ |
676 | if (pd->flags & SM501FB_FLAG_PANEL_USE_FPEN) { | ||
677 | control &= ~SM501_DC_PANEL_CONTROL_FPEN; | ||
678 | writel(control, ctrl_reg); | ||
679 | sm501fb_sync_regs(fbi); | ||
680 | mdelay(10); | ||
681 | } | ||
670 | 682 | ||
671 | control &= ~SM501_DC_PANEL_CONTROL_FPEN; | 683 | if (pd->flags & SM501FB_FLAG_PANEL_USE_VBIASEN) { |
672 | writel(control, ctrl_reg); | 684 | control &= ~SM501_DC_PANEL_CONTROL_BIAS; |
673 | sm501fb_sync_regs(fbi); | 685 | writel(control, ctrl_reg); |
674 | mdelay(10); | 686 | sm501fb_sync_regs(fbi); |
675 | 687 | mdelay(10); | |
676 | control &= ~SM501_DC_PANEL_CONTROL_BIAS; | 688 | } |
677 | writel(control, ctrl_reg); | ||
678 | sm501fb_sync_regs(fbi); | ||
679 | mdelay(10); | ||
680 | 689 | ||
681 | control &= ~SM501_DC_PANEL_CONTROL_DATA; | 690 | control &= ~SM501_DC_PANEL_CONTROL_DATA; |
682 | writel(control, ctrl_reg); | 691 | writel(control, ctrl_reg); |
@@ -1267,6 +1276,7 @@ static int sm501fb_start(struct sm501fb_info *info, | |||
1267 | { | 1276 | { |
1268 | struct resource *res; | 1277 | struct resource *res; |
1269 | struct device *dev; | 1278 | struct device *dev; |
1279 | int k; | ||
1270 | int ret; | 1280 | int ret; |
1271 | 1281 | ||
1272 | info->dev = dev = &pdev->dev; | 1282 | info->dev = dev = &pdev->dev; |
@@ -1328,6 +1338,13 @@ static int sm501fb_start(struct sm501fb_info *info, | |||
1328 | 1338 | ||
1329 | info->fbmem_len = (res->end - res->start)+1; | 1339 | info->fbmem_len = (res->end - res->start)+1; |
1330 | 1340 | ||
1341 | /* clear framebuffer memory - avoids garbage data on unused fb */ | ||
1342 | memset(info->fbmem, 0, info->fbmem_len); | ||
1343 | |||
1344 | /* clear palette ram - undefined at power on */ | ||
1345 | for (k = 0; k < (256 * 3); k++) | ||
1346 | writel(0, info->regs + SM501_DC_PANEL_PALETTE + (k * 4)); | ||
1347 | |||
1331 | /* enable display controller */ | 1348 | /* enable display controller */ |
1332 | sm501_unit_power(dev->parent, SM501_GATE_DISPLAY, 1); | 1349 | sm501_unit_power(dev->parent, SM501_GATE_DISPLAY, 1); |
1333 | 1350 | ||
@@ -1681,6 +1698,15 @@ static int sm501fb_suspend_fb(struct sm501fb_info *info, | |||
1681 | if (par->screen.size == 0) | 1698 | if (par->screen.size == 0) |
1682 | return 0; | 1699 | return 0; |
1683 | 1700 | ||
1701 | /* blank the relevant interface to ensure unit power minimised */ | ||
1702 | (par->ops.fb_blank)(FB_BLANK_POWERDOWN, fbi); | ||
1703 | |||
1704 | /* tell console/fb driver we are suspending */ | ||
1705 | |||
1706 | acquire_console_sem(); | ||
1707 | fb_set_suspend(fbi, 1); | ||
1708 | release_console_sem(); | ||
1709 | |||
1684 | /* backup copies in case chip is powered down over suspend */ | 1710 | /* backup copies in case chip is powered down over suspend */ |
1685 | 1711 | ||
1686 | par->store_fb = vmalloc(par->screen.size); | 1712 | par->store_fb = vmalloc(par->screen.size); |
@@ -1700,12 +1726,6 @@ static int sm501fb_suspend_fb(struct sm501fb_info *info, | |||
1700 | 1726 | ||
1701 | memcpy_fromio(par->store_fb, par->screen.k_addr, par->screen.size); | 1727 | memcpy_fromio(par->store_fb, par->screen.k_addr, par->screen.size); |
1702 | memcpy_fromio(par->store_cursor, par->cursor.k_addr, par->cursor.size); | 1728 | memcpy_fromio(par->store_cursor, par->cursor.k_addr, par->cursor.size); |
1703 | /* blank the relevant interface to ensure unit power minimised */ | ||
1704 | (par->ops.fb_blank)(FB_BLANK_POWERDOWN, fbi); | ||
1705 | |||
1706 | acquire_console_sem(); | ||
1707 | fb_set_suspend(fbi, 1); | ||
1708 | release_console_sem(); | ||
1709 | 1729 | ||
1710 | return 0; | 1730 | return 0; |
1711 | 1731 | ||
diff --git a/drivers/video/tdfxfb.c b/drivers/video/tdfxfb.c index 057bdd593800..71e179ea5f95 100644 --- a/drivers/video/tdfxfb.c +++ b/drivers/video/tdfxfb.c | |||
@@ -1342,7 +1342,7 @@ out_err: | |||
1342 | } | 1342 | } |
1343 | 1343 | ||
1344 | #ifndef MODULE | 1344 | #ifndef MODULE |
1345 | static void tdfxfb_setup(char *options) | 1345 | static void __init tdfxfb_setup(char *options) |
1346 | { | 1346 | { |
1347 | char *this_opt; | 1347 | char *this_opt; |
1348 | 1348 | ||
diff --git a/drivers/video/uvesafb.c b/drivers/video/uvesafb.c index a14ef894d571..be27b9c1ed72 100644 --- a/drivers/video/uvesafb.c +++ b/drivers/video/uvesafb.c | |||
@@ -2003,12 +2003,12 @@ static void __devexit uvesafb_exit(void) | |||
2003 | 2003 | ||
2004 | module_exit(uvesafb_exit); | 2004 | module_exit(uvesafb_exit); |
2005 | 2005 | ||
2006 | static inline int param_get_scroll(char *buffer, struct kernel_param *kp) | 2006 | static int param_get_scroll(char *buffer, struct kernel_param *kp) |
2007 | { | 2007 | { |
2008 | return 0; | 2008 | return 0; |
2009 | } | 2009 | } |
2010 | 2010 | ||
2011 | static inline int param_set_scroll(const char *val, struct kernel_param *kp) | 2011 | static int param_set_scroll(const char *val, struct kernel_param *kp) |
2012 | { | 2012 | { |
2013 | ypan = 0; | 2013 | ypan = 0; |
2014 | 2014 | ||
@@ -2022,11 +2022,11 @@ static inline int param_set_scroll(const char *val, struct kernel_param *kp) | |||
2022 | return 0; | 2022 | return 0; |
2023 | } | 2023 | } |
2024 | 2024 | ||
2025 | #define param_check_scroll(name, p) __param_check(name, p, void); | 2025 | #define param_check_scroll(name, p) __param_check(name, p, void) |
2026 | 2026 | ||
2027 | module_param_named(scroll, ypan, scroll, 0); | 2027 | module_param_named(scroll, ypan, scroll, 0); |
2028 | MODULE_PARM_DESC(scroll, | 2028 | MODULE_PARM_DESC(scroll, |
2029 | "Scrolling mode, set to 'redraw', ''ypan' or 'ywrap'"); | 2029 | "Scrolling mode, set to 'redraw', 'ypan', or 'ywrap'"); |
2030 | module_param_named(vgapal, pmi_setpal, invbool, 0); | 2030 | module_param_named(vgapal, pmi_setpal, invbool, 0); |
2031 | MODULE_PARM_DESC(vgapal, "Set palette using VGA registers"); | 2031 | MODULE_PARM_DESC(vgapal, "Set palette using VGA registers"); |
2032 | module_param_named(pmipal, pmi_setpal, bool, 0); | 2032 | module_param_named(pmipal, pmi_setpal, bool, 0); |
diff --git a/drivers/video/vermilion/vermilion.c b/drivers/video/vermilion/vermilion.c index 1c656667b937..2aa71eb67c2b 100644 --- a/drivers/video/vermilion/vermilion.c +++ b/drivers/video/vermilion/vermilion.c | |||
@@ -651,7 +651,7 @@ static int vmlfb_check_var_locked(struct fb_var_screeninfo *var, | |||
651 | return -EINVAL; | 651 | return -EINVAL; |
652 | } | 652 | } |
653 | 653 | ||
654 | pitch = __ALIGN_MASK((var->xres * var->bits_per_pixel) >> 3, 0x3F); | 654 | pitch = ALIGN((var->xres * var->bits_per_pixel) >> 3, 0x40); |
655 | mem = pitch * var->yres_virtual; | 655 | mem = pitch * var->yres_virtual; |
656 | if (mem > vinfo->vram_contig_size) { | 656 | if (mem > vinfo->vram_contig_size) { |
657 | return -ENOMEM; | 657 | return -ENOMEM; |
@@ -785,8 +785,7 @@ static int vmlfb_set_par_locked(struct vml_info *vinfo) | |||
785 | int clock; | 785 | int clock; |
786 | 786 | ||
787 | vinfo->bytes_per_pixel = var->bits_per_pixel >> 3; | 787 | vinfo->bytes_per_pixel = var->bits_per_pixel >> 3; |
788 | vinfo->stride = | 788 | vinfo->stride = ALIGN(var->xres_virtual * vinfo->bytes_per_pixel, 0x40); |
789 | __ALIGN_MASK(var->xres_virtual * vinfo->bytes_per_pixel, 0x3F); | ||
790 | info->fix.line_length = vinfo->stride; | 789 | info->fix.line_length = vinfo->stride; |
791 | 790 | ||
792 | if (!subsys) | 791 | if (!subsys) |
diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c index 622aece1acce..c8a4332d1132 100644 --- a/drivers/virtio/virtio_balloon.c +++ b/drivers/virtio/virtio_balloon.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/swap.h> | 23 | #include <linux/swap.h> |
24 | #include <linux/kthread.h> | 24 | #include <linux/kthread.h> |
25 | #include <linux/freezer.h> | 25 | #include <linux/freezer.h> |
26 | #include <linux/delay.h> | ||
26 | 27 | ||
27 | struct virtio_balloon | 28 | struct virtio_balloon |
28 | { | 29 | { |
diff --git a/drivers/w1/masters/Kconfig b/drivers/w1/masters/Kconfig index 8236d447adf5..c4493091c655 100644 --- a/drivers/w1/masters/Kconfig +++ b/drivers/w1/masters/Kconfig | |||
@@ -42,5 +42,15 @@ config W1_MASTER_DS1WM | |||
42 | in HP iPAQ devices like h5xxx, h2200, and ASIC3-based like | 42 | in HP iPAQ devices like h5xxx, h2200, and ASIC3-based like |
43 | hx4700. | 43 | hx4700. |
44 | 44 | ||
45 | config W1_MASTER_GPIO | ||
46 | tristate "GPIO 1-wire busmaster" | ||
47 | depends on GENERIC_GPIO | ||
48 | help | ||
49 | Say Y here if you want to communicate with your 1-wire devices using | ||
50 | GPIO pins. This driver uses the GPIO API to control the wire. | ||
51 | |||
52 | This support is also available as a module. If so, the module | ||
53 | will be called w1-gpio.ko. | ||
54 | |||
45 | endmenu | 55 | endmenu |
46 | 56 | ||
diff --git a/drivers/w1/masters/Makefile b/drivers/w1/masters/Makefile index 11551b328186..1420b5bbdda8 100644 --- a/drivers/w1/masters/Makefile +++ b/drivers/w1/masters/Makefile | |||
@@ -6,3 +6,4 @@ obj-$(CONFIG_W1_MASTER_MATROX) += matrox_w1.o | |||
6 | obj-$(CONFIG_W1_MASTER_DS2490) += ds2490.o | 6 | obj-$(CONFIG_W1_MASTER_DS2490) += ds2490.o |
7 | obj-$(CONFIG_W1_MASTER_DS2482) += ds2482.o | 7 | obj-$(CONFIG_W1_MASTER_DS2482) += ds2482.o |
8 | obj-$(CONFIG_W1_MASTER_DS1WM) += ds1wm.o | 8 | obj-$(CONFIG_W1_MASTER_DS1WM) += ds1wm.o |
9 | obj-$(CONFIG_W1_MASTER_GPIO) += w1-gpio.o | ||
diff --git a/drivers/w1/masters/ds1wm.c b/drivers/w1/masters/ds1wm.c index 5747997f8d7d..688e435b4d9a 100644 --- a/drivers/w1/masters/ds1wm.c +++ b/drivers/w1/masters/ds1wm.c | |||
@@ -361,11 +361,12 @@ static int ds1wm_probe(struct platform_device *pdev) | |||
361 | goto err1; | 361 | goto err1; |
362 | } | 362 | } |
363 | ds1wm_data->irq = res->start; | 363 | ds1wm_data->irq = res->start; |
364 | ds1wm_data->active_high = (res->flags & IORESOURCE_IRQ_HIGHEDGE) ? | 364 | ds1wm_data->active_high = plat->active_high; |
365 | 1 : 0; | ||
366 | 365 | ||
367 | set_irq_type(ds1wm_data->irq, ds1wm_data->active_high ? | 366 | if (res->flags & IORESOURCE_IRQ_HIGHEDGE) |
368 | IRQ_TYPE_EDGE_RISING : IRQ_TYPE_EDGE_FALLING); | 367 | set_irq_type(ds1wm_data->irq, IRQ_TYPE_EDGE_RISING); |
368 | if (res->flags & IORESOURCE_IRQ_LOWEDGE) | ||
369 | set_irq_type(ds1wm_data->irq, IRQ_TYPE_EDGE_FALLING); | ||
369 | 370 | ||
370 | ret = request_irq(ds1wm_data->irq, ds1wm_isr, IRQF_DISABLED, | 371 | ret = request_irq(ds1wm_data->irq, ds1wm_isr, IRQF_DISABLED, |
371 | "ds1wm", ds1wm_data); | 372 | "ds1wm", ds1wm_data); |
diff --git a/drivers/w1/masters/w1-gpio.c b/drivers/w1/masters/w1-gpio.c new file mode 100644 index 000000000000..9e1138a75e8b --- /dev/null +++ b/drivers/w1/masters/w1-gpio.c | |||
@@ -0,0 +1,124 @@ | |||
1 | /* | ||
2 | * w1-gpio - GPIO w1 bus master driver | ||
3 | * | ||
4 | * Copyright (C) 2007 Ville Syrjala <syrjala@sci.fi> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 | ||
8 | * as published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #include <linux/init.h> | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/platform_device.h> | ||
14 | #include <linux/w1-gpio.h> | ||
15 | |||
16 | #include "../w1.h" | ||
17 | #include "../w1_int.h" | ||
18 | |||
19 | #include <asm/gpio.h> | ||
20 | |||
21 | static void w1_gpio_write_bit_dir(void *data, u8 bit) | ||
22 | { | ||
23 | struct w1_gpio_platform_data *pdata = data; | ||
24 | |||
25 | if (bit) | ||
26 | gpio_direction_input(pdata->pin); | ||
27 | else | ||
28 | gpio_direction_output(pdata->pin, 0); | ||
29 | } | ||
30 | |||
31 | static void w1_gpio_write_bit_val(void *data, u8 bit) | ||
32 | { | ||
33 | struct w1_gpio_platform_data *pdata = data; | ||
34 | |||
35 | gpio_set_value(pdata->pin, bit); | ||
36 | } | ||
37 | |||
38 | static u8 w1_gpio_read_bit(void *data) | ||
39 | { | ||
40 | struct w1_gpio_platform_data *pdata = data; | ||
41 | |||
42 | return gpio_get_value(pdata->pin); | ||
43 | } | ||
44 | |||
45 | static int __init w1_gpio_probe(struct platform_device *pdev) | ||
46 | { | ||
47 | struct w1_bus_master *master; | ||
48 | struct w1_gpio_platform_data *pdata = pdev->dev.platform_data; | ||
49 | int err; | ||
50 | |||
51 | if (!pdata) | ||
52 | return -ENXIO; | ||
53 | |||
54 | master = kzalloc(sizeof(struct w1_bus_master), GFP_KERNEL); | ||
55 | if (!master) | ||
56 | return -ENOMEM; | ||
57 | |||
58 | err = gpio_request(pdata->pin, "w1"); | ||
59 | if (err) | ||
60 | goto free_master; | ||
61 | |||
62 | master->data = pdata; | ||
63 | master->read_bit = w1_gpio_read_bit; | ||
64 | |||
65 | if (pdata->is_open_drain) { | ||
66 | gpio_direction_output(pdata->pin, 1); | ||
67 | master->write_bit = w1_gpio_write_bit_val; | ||
68 | } else { | ||
69 | gpio_direction_input(pdata->pin); | ||
70 | master->write_bit = w1_gpio_write_bit_dir; | ||
71 | } | ||
72 | |||
73 | err = w1_add_master_device(master); | ||
74 | if (err) | ||
75 | goto free_gpio; | ||
76 | |||
77 | platform_set_drvdata(pdev, master); | ||
78 | |||
79 | return 0; | ||
80 | |||
81 | free_gpio: | ||
82 | gpio_free(pdata->pin); | ||
83 | free_master: | ||
84 | kfree(master); | ||
85 | |||
86 | return err; | ||
87 | } | ||
88 | |||
89 | static int __exit w1_gpio_remove(struct platform_device *pdev) | ||
90 | { | ||
91 | struct w1_bus_master *master = platform_get_drvdata(pdev); | ||
92 | struct w1_gpio_platform_data *pdata = pdev->dev.platform_data; | ||
93 | |||
94 | w1_remove_master_device(master); | ||
95 | gpio_free(pdata->pin); | ||
96 | kfree(master); | ||
97 | |||
98 | return 0; | ||
99 | } | ||
100 | |||
101 | static struct platform_driver w1_gpio_driver = { | ||
102 | .driver = { | ||
103 | .name = "w1-gpio", | ||
104 | .owner = THIS_MODULE, | ||
105 | }, | ||
106 | .remove = __exit_p(w1_gpio_remove), | ||
107 | }; | ||
108 | |||
109 | static int __init w1_gpio_init(void) | ||
110 | { | ||
111 | return platform_driver_probe(&w1_gpio_driver, w1_gpio_probe); | ||
112 | } | ||
113 | |||
114 | static void __exit w1_gpio_exit(void) | ||
115 | { | ||
116 | platform_driver_unregister(&w1_gpio_driver); | ||
117 | } | ||
118 | |||
119 | module_init(w1_gpio_init); | ||
120 | module_exit(w1_gpio_exit); | ||
121 | |||
122 | MODULE_DESCRIPTION("GPIO w1 bus master driver"); | ||
123 | MODULE_AUTHOR("Ville Syrjala <syrjala@sci.fi>"); | ||
124 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/w1/slaves/w1_therm.c b/drivers/w1/slaves/w1_therm.c index 112f4ec59035..fb28acaeed6c 100644 --- a/drivers/w1/slaves/w1_therm.c +++ b/drivers/w1/slaves/w1_therm.c | |||
@@ -92,6 +92,7 @@ struct w1_therm_family_converter | |||
92 | int (*convert)(u8 rom[9]); | 92 | int (*convert)(u8 rom[9]); |
93 | }; | 93 | }; |
94 | 94 | ||
95 | /* The return value is millidegrees Centigrade. */ | ||
95 | static inline int w1_DS18B20_convert_temp(u8 rom[9]); | 96 | static inline int w1_DS18B20_convert_temp(u8 rom[9]); |
96 | static inline int w1_DS18S20_convert_temp(u8 rom[9]); | 97 | static inline int w1_DS18S20_convert_temp(u8 rom[9]); |
97 | 98 | ||
@@ -113,7 +114,7 @@ static struct w1_therm_family_converter w1_therm_families[] = { | |||
113 | static inline int w1_DS18B20_convert_temp(u8 rom[9]) | 114 | static inline int w1_DS18B20_convert_temp(u8 rom[9]) |
114 | { | 115 | { |
115 | s16 t = (rom[1] << 8) | rom[0]; | 116 | s16 t = (rom[1] << 8) | rom[0]; |
116 | t /= 16; | 117 | t = t*1000/16; |
117 | return t; | 118 | return t; |
118 | } | 119 | } |
119 | 120 | ||
diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c index 33e50310e9e0..7293c9b11f91 100644 --- a/drivers/w1/w1.c +++ b/drivers/w1/w1.c | |||
@@ -675,7 +675,6 @@ static void w1_slave_found(void *data, u64 rn) | |||
675 | struct w1_slave *sl; | 675 | struct w1_slave *sl; |
676 | struct list_head *ent; | 676 | struct list_head *ent; |
677 | struct w1_reg_num *tmp; | 677 | struct w1_reg_num *tmp; |
678 | int family_found = 0; | ||
679 | struct w1_master *dev; | 678 | struct w1_master *dev; |
680 | u64 rn_le = cpu_to_le64(rn); | 679 | u64 rn_le = cpu_to_le64(rn); |
681 | 680 | ||
@@ -698,9 +697,6 @@ static void w1_slave_found(void *data, u64 rn) | |||
698 | sl->reg_num.crc == tmp->crc) { | 697 | sl->reg_num.crc == tmp->crc) { |
699 | set_bit(W1_SLAVE_ACTIVE, (long *)&sl->flags); | 698 | set_bit(W1_SLAVE_ACTIVE, (long *)&sl->flags); |
700 | break; | 699 | break; |
701 | } else if (sl->reg_num.family == tmp->family) { | ||
702 | family_found = 1; | ||
703 | break; | ||
704 | } | 700 | } |
705 | 701 | ||
706 | slave_count++; | 702 | slave_count++; |