summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorTony Lindgren <tony@atomide.com>2012-11-09 23:54:17 +0100
committerTony Lindgren <tony@atomide.com>2012-11-09 23:54:17 +0100
commitf56f52e02a9c3da4bc2cc6eb9ddcf5602ea44b37 (patch)
treea9ce4f46ea3b2e516698b2c3817e40414a8bbf51 /drivers
parentMerge branch 'for_3.8/dts_part2' of git://git.kernel.org/pub/scm/linux/kernel... (diff)
parentARM: OMAP: Remove omap_init_consistent_dma_size() (diff)
downloadlinux-f56f52e02a9c3da4bc2cc6eb9ddcf5602ea44b37.tar.xz
linux-f56f52e02a9c3da4bc2cc6eb9ddcf5602ea44b37.zip
Merge branch 'omap-for-v3.8/cleanup-headers-prepare-multiplatform-v3' into omap-for-v3.8/dt
Conflicts: arch/arm/plat-omap/dmtimer.c Resolved as suggested by Jon Hunter.
Diffstat (limited to 'drivers')
-rw-r--r--drivers/bluetooth/hci_ldisc.c7
-rw-r--r--drivers/char/hw_random/omap-rng.c2
-rw-r--r--drivers/crypto/omap-aes.c8
-rw-r--r--drivers/crypto/omap-sham.c10
-rw-r--r--drivers/dma/omap-dma.c5
-rw-r--r--drivers/media/platform/omap/omap_vout.c4
-rw-r--r--drivers/media/platform/omap/omap_vout_vrfb.c6
-rw-r--r--drivers/media/platform/omap/omap_voutdef.h2
-rw-r--r--drivers/media/platform/omap3isp/isphist.c2
-rw-r--r--drivers/media/platform/omap3isp/ispstat.h2
-rw-r--r--drivers/media/platform/omap3isp/ispvideo.c1
-rw-r--r--drivers/media/platform/soc_camera/omap1_camera.c3
-rw-r--r--drivers/media/rc/ir-rx51.c1
-rw-r--r--drivers/mfd/menelaus.c2
-rw-r--r--drivers/mfd/omap-usb-host.c5
-rw-r--r--drivers/mfd/omap-usb-tll.c2
-rw-r--r--drivers/mfd/omap-usb.h2
-rw-r--r--drivers/mmc/host/omap.c35
-rw-r--r--drivers/mmc/host/omap_hsmmc.c4
-rw-r--r--drivers/mtd/nand/omap2.c129
-rw-r--r--drivers/mtd/onenand/omap2.c47
-rw-r--r--drivers/pcmcia/omap_cf.c2
-rw-r--r--drivers/staging/tidspbridge/include/dspbridge/host_os.h1
-rw-r--r--drivers/tty/n_tty.c752
-rw-r--r--drivers/tty/pty.c30
-rw-r--r--drivers/tty/serial/8250/8250.c9
-rw-r--r--drivers/tty/serial/8250/8250.h36
-rw-r--r--drivers/tty/serial/8250/8250_early.c2
-rw-r--r--drivers/tty/serial/samsung.c16
-rw-r--r--drivers/tty/tty_audit.c15
-rw-r--r--drivers/tty/tty_buffer.c228
-rw-r--r--drivers/tty/tty_io.c15
-rw-r--r--drivers/tty/tty_ldisc.c15
-rw-r--r--drivers/tty/tty_port.c2
-rw-r--r--drivers/tty/vt/selection.c9
-rw-r--r--drivers/usb/gadget/omap_udc.c4
-rw-r--r--drivers/usb/host/ehci-omap.c3
-rw-r--r--drivers/usb/host/ohci-omap.c5
-rw-r--r--drivers/usb/host/ohci-omap3.c1
-rw-r--r--drivers/usb/musb/am35x.c3
-rw-r--r--drivers/usb/musb/musb_dsps.c3
-rw-r--r--drivers/usb/musb/omap2430.h2
-rw-r--r--drivers/usb/musb/tusb6010_omap.c9
-rw-r--r--drivers/video/omap/lcd_inn1510.c7
-rw-r--r--drivers/video/omap/lcdc.c2
-rw-r--r--drivers/video/omap/omapfb_main.c2
-rw-r--r--drivers/video/omap/sossi.c2
-rw-r--r--drivers/video/omap2/dss/core.c2
-rw-r--r--drivers/video/omap2/dss/dispc.c43
-rw-r--r--drivers/video/omap2/dss/dss.c39
-rw-r--r--drivers/video/omap2/dss/dss_features.c64
-rw-r--r--drivers/video/omap2/dss/dss_features.h5
-rw-r--r--drivers/video/omap2/dss/hdmi.c3
-rw-r--r--drivers/video/omap2/omapfb/omapfb-ioctl.c2
-rw-r--r--drivers/video/omap2/omapfb/omapfb-main.c8
-rw-r--r--drivers/video/omap2/omapfb/omapfb-sysfs.c2
-rw-r--r--drivers/video/omap2/vrfb.c142
57 files changed, 1071 insertions, 693 deletions
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index c8abce3d2d9c..ed0fade46aed 100644
--- a/drivers/bluetooth/hci_ldisc.c
+++ b/drivers/bluetooth/hci_ldisc.c
@@ -270,15 +270,10 @@ static int hci_uart_send_frame(struct sk_buff *skb)
*/
static int hci_uart_tty_open(struct tty_struct *tty)
{
- struct hci_uart *hu = (void *) tty->disc_data;
+ struct hci_uart *hu;
BT_DBG("tty %p", tty);
- /* FIXME: This btw is bogus, nothing requires the old ldisc to clear
- the pointer */
- if (hu)
- return -EEXIST;
-
/* Error if the tty has no write op instead of leaving an exploitable
hole */
if (tty->ops->write == NULL)
diff --git a/drivers/char/hw_random/omap-rng.c b/drivers/char/hw_random/omap-rng.c
index a5effd813abd..45e467dcc8c8 100644
--- a/drivers/char/hw_random/omap-rng.c
+++ b/drivers/char/hw_random/omap-rng.c
@@ -27,8 +27,6 @@
#include <asm/io.h>
-#include <plat/cpu.h>
-
#define RNG_OUT_REG 0x00 /* Output register */
#define RNG_STAT_REG 0x04 /* Status register
[0] = STAT_BUSY */
diff --git a/drivers/crypto/omap-aes.c b/drivers/crypto/omap-aes.c
index 093a8af59cbe..649a146e1382 100644
--- a/drivers/crypto/omap-aes.c
+++ b/drivers/crypto/omap-aes.c
@@ -29,8 +29,7 @@
#include <crypto/scatterwalk.h>
#include <crypto/aes.h>
-#include <plat/cpu.h>
-#include <plat/dma.h>
+#include <plat-omap/dma-omap.h>
/* OMAP TRM gives bitfields as start:end, where start is the higher bit
number. For example 7:0 */
@@ -941,11 +940,6 @@ static int __init omap_aes_mod_init(void)
{
pr_info("loading %s driver\n", "omap-aes");
- if (!cpu_class_is_omap2() || omap_type() != OMAP2_DEVICE_TYPE_SEC) {
- pr_err("Unsupported cpu\n");
- return -ENODEV;
- }
-
return platform_driver_register(&omap_aes_driver);
}
diff --git a/drivers/crypto/omap-sham.c b/drivers/crypto/omap-sham.c
index a3fd6fc504b1..d76fe06b9417 100644
--- a/drivers/crypto/omap-sham.c
+++ b/drivers/crypto/omap-sham.c
@@ -37,8 +37,7 @@
#include <crypto/hash.h>
#include <crypto/internal/hash.h>
-#include <plat/cpu.h>
-#include <plat/dma.h>
+#include <plat-omap/dma-omap.h>
#include <mach/irqs.h>
#define SHA_REG_DIGEST(x) (0x00 + ((x) * 0x04))
@@ -1289,13 +1288,6 @@ static int __init omap_sham_mod_init(void)
{
pr_info("loading %s driver\n", "omap-sham");
- if (!cpu_class_is_omap2() ||
- (omap_type() != OMAP2_DEVICE_TYPE_SEC &&
- omap_type() != OMAP2_DEVICE_TYPE_EMU)) {
- pr_err("Unsupported cpu\n");
- return -ENODEV;
- }
-
return platform_driver_register(&omap_sham_driver);
}
diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c
index bb2d8e7029eb..7d35c237fbf1 100644
--- a/drivers/dma/omap-dma.c
+++ b/drivers/dma/omap-dma.c
@@ -19,8 +19,7 @@
#include "virt-dma.h"
-#include <plat/cpu.h>
-#include <plat/dma.h>
+#include <plat-omap/dma-omap.h>
struct omap_dmadev {
struct dma_device ddev;
@@ -438,7 +437,7 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic(
omap_disable_dma_irq(c->dma_ch, OMAP_DMA_BLOCK_IRQ);
}
- if (!cpu_class_is_omap1()) {
+ if (dma_omap2plus()) {
omap_set_dma_src_burst_mode(c->dma_ch, OMAP_DMA_DATA_BURST_16);
omap_set_dma_dest_burst_mode(c->dma_ch, OMAP_DMA_DATA_BURST_16);
}
diff --git a/drivers/media/platform/omap/omap_vout.c b/drivers/media/platform/omap/omap_vout.c
index a3b1a34c896d..4b1becc86e54 100644
--- a/drivers/media/platform/omap/omap_vout.c
+++ b/drivers/media/platform/omap/omap_vout.c
@@ -45,8 +45,8 @@
#include <media/v4l2-ioctl.h>
#include <plat/cpu.h>
-#include <plat/dma.h>
-#include <plat/vrfb.h>
+#include <plat-omap/dma-omap.h>
+#include <video/omapvrfb.h>
#include <video/omapdss.h>
#include "omap_voutlib.h"
diff --git a/drivers/media/platform/omap/omap_vout_vrfb.c b/drivers/media/platform/omap/omap_vout_vrfb.c
index 4be26abf6cea..8340445a0ee5 100644
--- a/drivers/media/platform/omap/omap_vout_vrfb.c
+++ b/drivers/media/platform/omap/omap_vout_vrfb.c
@@ -16,12 +16,14 @@
#include <media/videobuf-dma-contig.h>
#include <media/v4l2-device.h>
-#include <plat/dma.h>
-#include <plat/vrfb.h>
+#include <plat-omap/dma-omap.h>
+#include <video/omapvrfb.h>
#include "omap_voutdef.h"
#include "omap_voutlib.h"
+#define OMAP_DMA_NO_DEVICE 0
+
/*
* Function for allocating video buffers
*/
diff --git a/drivers/media/platform/omap/omap_voutdef.h b/drivers/media/platform/omap/omap_voutdef.h
index 27a95d23b913..9ccfe1f475a4 100644
--- a/drivers/media/platform/omap/omap_voutdef.h
+++ b/drivers/media/platform/omap/omap_voutdef.h
@@ -12,7 +12,7 @@
#define OMAP_VOUTDEF_H
#include <video/omapdss.h>
-#include <plat/vrfb.h>
+#include <video/omapvrfb.h>
#define YUYV_BPP 2
#define RGB565_BPP 2
diff --git a/drivers/media/platform/omap3isp/isphist.c b/drivers/media/platform/omap3isp/isphist.c
index d1a8dee5e1ca..e7f9c4292cc6 100644
--- a/drivers/media/platform/omap3isp/isphist.c
+++ b/drivers/media/platform/omap3isp/isphist.c
@@ -34,6 +34,8 @@
#include "ispreg.h"
#include "isphist.h"
+#define OMAP24XX_DMA_NO_DEVICE 0
+
#define HIST_CONFIG_DMA 1
#define HIST_USING_DMA(hist) ((hist)->dma_ch >= 0)
diff --git a/drivers/media/platform/omap3isp/ispstat.h b/drivers/media/platform/omap3isp/ispstat.h
index a6fe653eb237..40f87cdd7994 100644
--- a/drivers/media/platform/omap3isp/ispstat.h
+++ b/drivers/media/platform/omap3isp/ispstat.h
@@ -30,7 +30,7 @@
#include <linux/types.h>
#include <linux/omap3isp.h>
-#include <plat/dma.h>
+#include <plat-omap/dma-omap.h>
#include <media/v4l2-event.h>
#include "isp.h"
diff --git a/drivers/media/platform/omap3isp/ispvideo.c b/drivers/media/platform/omap3isp/ispvideo.c
index a0b737fecf13..5bd40e6870cc 100644
--- a/drivers/media/platform/omap3isp/ispvideo.c
+++ b/drivers/media/platform/omap3isp/ispvideo.c
@@ -36,7 +36,6 @@
#include <media/v4l2-ioctl.h>
#include <plat/iommu.h>
#include <plat/iovmm.h>
-#include <plat/omap-pm.h>
#include "ispvideo.h"
#include "isp.h"
diff --git a/drivers/media/platform/soc_camera/omap1_camera.c b/drivers/media/platform/soc_camera/omap1_camera.c
index fa08c7695ccb..cae9ce6275e9 100644
--- a/drivers/media/platform/soc_camera/omap1_camera.c
+++ b/drivers/media/platform/soc_camera/omap1_camera.c
@@ -34,12 +34,13 @@
#include <media/videobuf-dma-contig.h>
#include <media/videobuf-dma-sg.h>
-#include <plat/dma.h>
+#include <plat-omap/dma-omap.h>
#define DRIVER_NAME "omap1-camera"
#define DRIVER_VERSION "0.0.2"
+#define OMAP_DMA_CAMERA_IF_RX 20
/*
* ---------------------------------------------------------------------------
diff --git a/drivers/media/rc/ir-rx51.c b/drivers/media/rc/ir-rx51.c
index 546199e9ccc7..82e6c1e282d5 100644
--- a/drivers/media/rc/ir-rx51.c
+++ b/drivers/media/rc/ir-rx51.c
@@ -28,7 +28,6 @@
#include <plat/dmtimer.h>
#include <plat/clock.h>
-#include <plat/omap-pm.h>
#include <media/lirc.h>
#include <media/lirc_dev.h>
diff --git a/drivers/mfd/menelaus.c b/drivers/mfd/menelaus.c
index 55d589981412..998ce8cb3065 100644
--- a/drivers/mfd/menelaus.c
+++ b/drivers/mfd/menelaus.c
@@ -41,11 +41,11 @@
#include <linux/rtc.h>
#include <linux/bcd.h>
#include <linux/slab.h>
+#include <linux/mfd/menelaus.h>
#include <asm/mach/irq.h>
#include <asm/gpio.h>
-#include <plat/menelaus.h>
#define DRIVER_NAME "menelaus"
diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c
index 23cec57c02ba..cebfe0a68aa7 100644
--- a/drivers/mfd/omap-usb-host.c
+++ b/drivers/mfd/omap-usb-host.c
@@ -26,9 +26,12 @@
#include <linux/spinlock.h>
#include <linux/gpio.h>
#include <plat/cpu.h>
-#include <plat/usb.h>
+#include <linux/platform_device.h>
+#include <linux/platform_data/usb-omap.h>
#include <linux/pm_runtime.h>
+#include "omap-usb.h"
+
#define USBHS_DRIVER_NAME "usbhs_omap"
#define OMAP_EHCI_DEVICE "ehci-omap"
#define OMAP_OHCI_DEVICE "ohci-omap3"
diff --git a/drivers/mfd/omap-usb-tll.c b/drivers/mfd/omap-usb-tll.c
index 4b7757b84301..0db0dfa3d08c 100644
--- a/drivers/mfd/omap-usb-tll.c
+++ b/drivers/mfd/omap-usb-tll.c
@@ -25,8 +25,8 @@
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/err.h>
-#include <plat/usb.h>
#include <linux/pm_runtime.h>
+#include <linux/platform_data/usb-omap.h>
#define USBTLL_DRIVER_NAME "usbhs_tll"
diff --git a/drivers/mfd/omap-usb.h b/drivers/mfd/omap-usb.h
new file mode 100644
index 000000000000..972aa961b064
--- /dev/null
+++ b/drivers/mfd/omap-usb.h
@@ -0,0 +1,2 @@
+extern int omap_tll_enable(void);
+extern int omap_tll_disable(void);
diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c
index 48ad361613ef..ae115c01283b 100644
--- a/drivers/mmc/host/omap.c
+++ b/drivers/mmc/host/omap.c
@@ -28,9 +28,8 @@
#include <linux/clk.h>
#include <linux/scatterlist.h>
#include <linux/slab.h>
+#include <linux/platform_data/mmc-omap.h>
-#include <plat/mmc.h>
-#include <plat/dma.h>
#define OMAP_MMC_REG_CMD 0x00
#define OMAP_MMC_REG_ARGL 0x01
@@ -72,6 +71,13 @@
#define OMAP_MMC_STAT_CARD_BUSY (1 << 2)
#define OMAP_MMC_STAT_END_OF_CMD (1 << 0)
+#define mmc_omap7xx() (host->features & MMC_OMAP7XX)
+#define mmc_omap15xx() (host->features & MMC_OMAP15XX)
+#define mmc_omap16xx() (host->features & MMC_OMAP16XX)
+#define MMC_OMAP1_MASK (MMC_OMAP7XX | MMC_OMAP15XX | MMC_OMAP16XX)
+#define mmc_omap1() (host->features & MMC_OMAP1_MASK)
+#define mmc_omap2() (!mmc_omap1())
+
#define OMAP_MMC_REG(host, reg) (OMAP_MMC_REG_##reg << (host)->reg_shift)
#define OMAP_MMC_READ(host, reg) __raw_readw((host)->virt_base + OMAP_MMC_REG(host, reg))
#define OMAP_MMC_WRITE(host, reg, val) __raw_writew((val), (host)->virt_base + OMAP_MMC_REG(host, reg))
@@ -84,6 +90,16 @@
#define OMAP_MMC_CMDTYPE_AC 2
#define OMAP_MMC_CMDTYPE_ADTC 3
+#define OMAP_DMA_MMC_TX 21
+#define OMAP_DMA_MMC_RX 22
+#define OMAP_DMA_MMC2_TX 54
+#define OMAP_DMA_MMC2_RX 55
+
+#define OMAP24XX_DMA_MMC2_TX 47
+#define OMAP24XX_DMA_MMC2_RX 48
+#define OMAP24XX_DMA_MMC1_TX 61
+#define OMAP24XX_DMA_MMC1_RX 62
+
#define DRIVER_NAME "mmci-omap"
@@ -147,6 +163,7 @@ struct mmc_omap_host {
u32 buffer_bytes_left;
u32 total_bytes_left;
+ unsigned features;
unsigned use_dma:1;
unsigned brs_received:1, dma_done:1;
unsigned dma_in_use:1;
@@ -988,7 +1005,7 @@ mmc_omap_prepare_data(struct mmc_omap_host *host, struct mmc_request *req)
* blocksize is at least that large. Blocksize is
* usually 512 bytes; but not for some SD reads.
*/
- burst = cpu_is_omap15xx() ? 32 : 64;
+ burst = mmc_omap15xx() ? 32 : 64;
if (burst > data->blksz)
burst = data->blksz;
@@ -1104,8 +1121,7 @@ static void mmc_omap_set_power(struct mmc_omap_slot *slot, int power_on,
if (slot->pdata->set_power != NULL)
slot->pdata->set_power(mmc_dev(slot->mmc), slot->id, power_on,
vdd);
-
- if (cpu_is_omap24xx()) {
+ if (mmc_omap2()) {
u16 w;
if (power_on) {
@@ -1239,7 +1255,7 @@ static int __devinit mmc_omap_new_slot(struct mmc_omap_host *host, int id)
mmc->ops = &mmc_omap_ops;
mmc->f_min = 400000;
- if (cpu_class_is_omap2())
+ if (mmc_omap2())
mmc->f_max = 48000000;
else
mmc->f_max = 24000000;
@@ -1359,6 +1375,7 @@ static int __devinit mmc_omap_probe(struct platform_device *pdev)
init_waitqueue_head(&host->slot_wq);
host->pdata = pdata;
+ host->features = host->pdata->slots[0].features;
host->dev = &pdev->dev;
platform_set_drvdata(pdev, host);
@@ -1391,7 +1408,7 @@ static int __devinit mmc_omap_probe(struct platform_device *pdev)
host->dma_tx_burst = -1;
host->dma_rx_burst = -1;
- if (cpu_is_omap24xx())
+ if (mmc_omap2())
sig = host->id == 0 ? OMAP24XX_DMA_MMC1_TX : OMAP24XX_DMA_MMC2_TX;
else
sig = host->id == 0 ? OMAP_DMA_MMC_TX : OMAP_DMA_MMC2_TX;
@@ -1407,7 +1424,7 @@ static int __devinit mmc_omap_probe(struct platform_device *pdev)
dev_warn(host->dev, "unable to obtain TX DMA engine channel %u\n",
sig);
#endif
- if (cpu_is_omap24xx())
+ if (mmc_omap2())
sig = host->id == 0 ? OMAP24XX_DMA_MMC1_RX : OMAP24XX_DMA_MMC2_RX;
else
sig = host->id == 0 ? OMAP_DMA_MMC_RX : OMAP_DMA_MMC2_RX;
@@ -1435,7 +1452,7 @@ static int __devinit mmc_omap_probe(struct platform_device *pdev)
}
host->nr_slots = pdata->nr_slots;
- host->reg_shift = (cpu_is_omap7xx() ? 1 : 2);
+ host->reg_shift = (mmc_omap7xx() ? 1 : 2);
host->mmc_omap_wq = alloc_workqueue("mmc_omap", 0, 0);
if (!host->mmc_omap_wq)
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index 54bfd0cc106b..9b24bd46aad3 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -38,9 +38,7 @@
#include <linux/gpio.h>
#include <linux/regulator/consumer.h>
#include <linux/pm_runtime.h>
-#include <mach/hardware.h>
-#include <plat/mmc.h>
-#include <plat/cpu.h>
+#include <linux/platform_data/mmc-omap.h>
/* OMAP HSMMC Host Controller Registers */
#define OMAP_HSMMC_SYSSTATUS 0x0014
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index 5b3138620646..5c8978e90240 100644
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -27,8 +27,7 @@
#include <linux/bch.h>
#endif
-#include <plat/dma.h>
-#include <plat/gpmc.h>
+#include <plat-omap/dma-omap.h>
#include <linux/platform_data/mtd-nand-omap2.h>
#define DRIVER_NAME "omap2-nand"
@@ -106,10 +105,18 @@
#define CS_MASK 0x7
#define ENABLE_PREFETCH (0x1 << 7)
#define DMA_MPU_MODE_SHIFT 2
+#define ECCSIZE0_SHIFT 12
#define ECCSIZE1_SHIFT 22
#define ECC1RESULTSIZE 0x1
#define ECCCLEAR 0x100
#define ECC1 0x1
+#define PREFETCH_FIFOTHRESHOLD_MAX 0x40
+#define PREFETCH_FIFOTHRESHOLD(val) ((val) << 8)
+#define PREFETCH_STATUS_COUNT(val) (val & 0x00003fff)
+#define PREFETCH_STATUS_FIFO_CNT(val) ((val >> 24) & 0x7F)
+#define STATUS_BUFF_EMPTY 0x00000001
+
+#define OMAP24XX_DMA_GPMC 4
/* oob info generated runtime depending on ecc algorithm and layout selected */
static struct nand_ecclayout omap_oobinfo;
@@ -269,7 +276,7 @@ static void omap_write_buf8(struct mtd_info *mtd, const u_char *buf, int len)
/* wait until buffer is available for write */
do {
status = readl(info->reg.gpmc_status) &
- GPMC_STATUS_BUFF_EMPTY;
+ STATUS_BUFF_EMPTY;
} while (!status);
}
}
@@ -307,7 +314,7 @@ static void omap_write_buf16(struct mtd_info *mtd, const u_char * buf, int len)
/* wait until buffer is available for write */
do {
status = readl(info->reg.gpmc_status) &
- GPMC_STATUS_BUFF_EMPTY;
+ STATUS_BUFF_EMPTY;
} while (!status);
}
}
@@ -348,7 +355,7 @@ static void omap_read_buf_pref(struct mtd_info *mtd, u_char *buf, int len)
} else {
do {
r_count = readl(info->reg.gpmc_prefetch_status);
- r_count = GPMC_PREFETCH_STATUS_FIFO_CNT(r_count);
+ r_count = PREFETCH_STATUS_FIFO_CNT(r_count);
r_count = r_count >> 2;
ioread32_rep(info->nand.IO_ADDR_R, p, r_count);
p += r_count;
@@ -395,7 +402,7 @@ static void omap_write_buf_pref(struct mtd_info *mtd,
} else {
while (len) {
w_count = readl(info->reg.gpmc_prefetch_status);
- w_count = GPMC_PREFETCH_STATUS_FIFO_CNT(w_count);
+ w_count = PREFETCH_STATUS_FIFO_CNT(w_count);
w_count = w_count >> 1;
for (i = 0; (i < w_count) && len; i++, len -= 2)
iowrite16(*p++, info->nand.IO_ADDR_W);
@@ -407,7 +414,7 @@ static void omap_write_buf_pref(struct mtd_info *mtd,
do {
cpu_relax();
val = readl(info->reg.gpmc_prefetch_status);
- val = GPMC_PREFETCH_STATUS_COUNT(val);
+ val = PREFETCH_STATUS_COUNT(val);
} while (val && (tim++ < limit));
/* disable and stop the PFPW engine */
@@ -493,7 +500,7 @@ static inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr,
do {
cpu_relax();
val = readl(info->reg.gpmc_prefetch_status);
- val = GPMC_PREFETCH_STATUS_COUNT(val);
+ val = PREFETCH_STATUS_COUNT(val);
} while (val && (tim++ < limit));
/* disable and stop the PFPW engine */
@@ -556,7 +563,7 @@ static irqreturn_t omap_nand_irq(int this_irq, void *dev)
u32 bytes;
bytes = readl(info->reg.gpmc_prefetch_status);
- bytes = GPMC_PREFETCH_STATUS_FIFO_CNT(bytes);
+ bytes = PREFETCH_STATUS_FIFO_CNT(bytes);
bytes = bytes & 0xFFFC; /* io in multiple of 4 bytes */
if (info->iomode == OMAP_NAND_IO_WRITE) { /* checks for write io */
if (this_irq == info->gpmc_irq_count)
@@ -682,7 +689,7 @@ static void omap_write_buf_irq_pref(struct mtd_info *mtd,
limit = (loops_per_jiffy * msecs_to_jiffies(OMAP_NAND_TIMEOUT_MS));
do {
val = readl(info->reg.gpmc_prefetch_status);
- val = GPMC_PREFETCH_STATUS_COUNT(val);
+ val = PREFETCH_STATUS_COUNT(val);
cpu_relax();
} while (val && (tim++ < limit));
@@ -996,7 +1003,7 @@ static int omap_wait(struct mtd_info *mtd, struct nand_chip *chip)
cond_resched();
}
- status = gpmc_nand_read(info->gpmc_cs, GPMC_NAND_DATA);
+ status = readb(info->reg.gpmc_nand_data);
return status;
}
@@ -1029,19 +1036,45 @@ static int omap_dev_ready(struct mtd_info *mtd)
static void omap3_enable_hwecc_bch(struct mtd_info *mtd, int mode)
{
int nerrors;
- unsigned int dev_width;
+ unsigned int dev_width, nsectors;
struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
mtd);
struct nand_chip *chip = mtd->priv;
+ u32 val;
nerrors = (info->nand.ecc.bytes == 13) ? 8 : 4;
dev_width = (chip->options & NAND_BUSWIDTH_16) ? 1 : 0;
+ nsectors = 1;
/*
* Program GPMC to perform correction on one 512-byte sector at a time.
* Using 4 sectors at a time (i.e. ecc.size = 2048) is also possible and
* gives a slight (5%) performance gain (but requires additional code).
*/
- (void)gpmc_enable_hwecc_bch(info->gpmc_cs, mode, dev_width, 1, nerrors);
+
+ writel(ECC1, info->reg.gpmc_ecc_control);
+
+ /*
+ * When using BCH, sector size is hardcoded to 512 bytes.
+ * Here we are using wrapping mode 6 both for reading and writing, with:
+ * size0 = 0 (no additional protected byte in spare area)
+ * size1 = 32 (skip 32 nibbles = 16 bytes per sector in spare area)
+ */
+ val = (32 << ECCSIZE1_SHIFT) | (0 << ECCSIZE0_SHIFT);
+ writel(val, info->reg.gpmc_ecc_size_config);
+
+ /* BCH configuration */
+ val = ((1 << 16) | /* enable BCH */
+ (((nerrors == 8) ? 1 : 0) << 12) | /* 8 or 4 bits */
+ (0x06 << 8) | /* wrap mode = 6 */
+ (dev_width << 7) | /* bus width */
+ (((nsectors-1) & 0x7) << 4) | /* number of sectors */
+ (info->gpmc_cs << 1) | /* ECC CS */
+ (0x1)); /* enable ECC */
+
+ writel(val, info->reg.gpmc_ecc_config);
+
+ /* clear ecc and enable bits */
+ writel(ECCCLEAR | ECC1, info->reg.gpmc_ecc_control);
}
/**
@@ -1055,7 +1088,32 @@ static int omap3_calculate_ecc_bch4(struct mtd_info *mtd, const u_char *dat,
{
struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
mtd);
- return gpmc_calculate_ecc_bch4(info->gpmc_cs, dat, ecc_code);
+ unsigned long nsectors, val1, val2;
+ int i;
+
+ nsectors = ((readl(info->reg.gpmc_ecc_config) >> 4) & 0x7) + 1;
+
+ for (i = 0; i < nsectors; i++) {
+
+ /* Read hw-computed remainder */
+ val1 = readl(info->reg.gpmc_bch_result0[i]);
+ val2 = readl(info->reg.gpmc_bch_result1[i]);
+
+ /*
+ * Add constant polynomial to remainder, in order to get an ecc
+ * sequence of 0xFFs for a buffer filled with 0xFFs; and
+ * left-justify the resulting polynomial.
+ */
+ *ecc_code++ = 0x28 ^ ((val2 >> 12) & 0xFF);
+ *ecc_code++ = 0x13 ^ ((val2 >> 4) & 0xFF);
+ *ecc_code++ = 0xcc ^ (((val2 & 0xF) << 4)|((val1 >> 28) & 0xF));
+ *ecc_code++ = 0x39 ^ ((val1 >> 20) & 0xFF);
+ *ecc_code++ = 0x96 ^ ((val1 >> 12) & 0xFF);
+ *ecc_code++ = 0xac ^ ((val1 >> 4) & 0xFF);
+ *ecc_code++ = 0x7f ^ ((val1 & 0xF) << 4);
+ }
+
+ return 0;
}
/**
@@ -1069,7 +1127,39 @@ static int omap3_calculate_ecc_bch8(struct mtd_info *mtd, const u_char *dat,
{
struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
mtd);
- return gpmc_calculate_ecc_bch8(info->gpmc_cs, dat, ecc_code);
+ unsigned long nsectors, val1, val2, val3, val4;
+ int i;
+
+ nsectors = ((readl(info->reg.gpmc_ecc_config) >> 4) & 0x7) + 1;
+
+ for (i = 0; i < nsectors; i++) {
+
+ /* Read hw-computed remainder */
+ val1 = readl(info->reg.gpmc_bch_result0[i]);
+ val2 = readl(info->reg.gpmc_bch_result1[i]);
+ val3 = readl(info->reg.gpmc_bch_result2[i]);
+ val4 = readl(info->reg.gpmc_bch_result3[i]);
+
+ /*
+ * Add constant polynomial to remainder, in order to get an ecc
+ * sequence of 0xFFs for a buffer filled with 0xFFs.
+ */
+ *ecc_code++ = 0xef ^ (val4 & 0xFF);
+ *ecc_code++ = 0x51 ^ ((val3 >> 24) & 0xFF);
+ *ecc_code++ = 0x2e ^ ((val3 >> 16) & 0xFF);
+ *ecc_code++ = 0x09 ^ ((val3 >> 8) & 0xFF);
+ *ecc_code++ = 0xed ^ (val3 & 0xFF);
+ *ecc_code++ = 0x93 ^ ((val2 >> 24) & 0xFF);
+ *ecc_code++ = 0x9a ^ ((val2 >> 16) & 0xFF);
+ *ecc_code++ = 0xc2 ^ ((val2 >> 8) & 0xFF);
+ *ecc_code++ = 0x97 ^ (val2 & 0xFF);
+ *ecc_code++ = 0x79 ^ ((val1 >> 24) & 0xFF);
+ *ecc_code++ = 0xe5 ^ ((val1 >> 16) & 0xFF);
+ *ecc_code++ = 0x24 ^ ((val1 >> 8) & 0xFF);
+ *ecc_code++ = 0xb5 ^ (val1 & 0xFF);
+ }
+
+ return 0;
}
/**
@@ -1125,7 +1215,7 @@ static void omap3_free_bch(struct mtd_info *mtd)
*/
static int omap3_init_bch(struct mtd_info *mtd, int ecc_opt)
{
- int ret, max_errors;
+ int max_errors;
struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
mtd);
#ifdef CONFIG_MTD_NAND_OMAP_BCH8
@@ -1142,11 +1232,6 @@ static int omap3_init_bch(struct mtd_info *mtd, int ecc_opt)
goto fail;
}
- /* initialize GPMC BCH engine */
- ret = gpmc_init_hwecc_bch(info->gpmc_cs, 1, max_errors);
- if (ret)
- goto fail;
-
/* software bch library is only used to detect and locate errors */
info->bch = init_bch(13, max_errors, 0x201b /* hw polynomial */);
if (!info->bch)
@@ -1513,7 +1598,7 @@ static int omap_nand_remove(struct platform_device *pdev)
/* Release NAND device, its internal structures and partitions */
nand_release(&info->mtd);
iounmap(info->nand.IO_ADDR_R);
- release_mem_region(info->phys_base, NAND_IO_SIZE);
+ release_mem_region(info->phys_base, info->mem_size);
kfree(info);
return 0;
}
diff --git a/drivers/mtd/onenand/omap2.c b/drivers/mtd/onenand/omap2.c
index 1961be985171..99f96e19ebea 100644
--- a/drivers/mtd/onenand/omap2.c
+++ b/drivers/mtd/onenand/omap2.c
@@ -38,12 +38,10 @@
#include <linux/regulator/consumer.h>
#include <asm/mach/flash.h>
-#include <plat/gpmc.h>
#include <linux/platform_data/mtd-onenand-omap2.h>
#include <asm/gpio.h>
-#include <plat/dma.h>
-#include <plat/cpu.h>
+#include <plat-omap/dma-omap.h>
#define DRIVER_NAME "omap2-onenand"
@@ -63,6 +61,7 @@ struct omap2_onenand {
int freq;
int (*setup)(void __iomem *base, int *freq_ptr);
struct regulator *regulator;
+ u8 flags;
};
static void omap2_onenand_dma_cb(int lch, u16 ch_status, void *data)
@@ -155,7 +154,7 @@ static int omap2_onenand_wait(struct mtd_info *mtd, int state)
if (!(syscfg & ONENAND_SYS_CFG1_IOBE)) {
syscfg |= ONENAND_SYS_CFG1_IOBE;
write_reg(c, syscfg, ONENAND_REG_SYS_CFG1);
- if (cpu_is_omap34xx())
+ if (c->flags & ONENAND_IN_OMAP34XX)
/* Add a delay to let GPIO settle */
syscfg = read_reg(c, ONENAND_REG_SYS_CFG1);
}
@@ -446,13 +445,19 @@ out_copy:
#else
-int omap3_onenand_read_bufferram(struct mtd_info *mtd, int area,
- unsigned char *buffer, int offset,
- size_t count);
+static int omap3_onenand_read_bufferram(struct mtd_info *mtd, int area,
+ unsigned char *buffer, int offset,
+ size_t count)
+{
+ return -ENOSYS;
+}
-int omap3_onenand_write_bufferram(struct mtd_info *mtd, int area,
- const unsigned char *buffer,
- int offset, size_t count);
+static int omap3_onenand_write_bufferram(struct mtd_info *mtd, int area,
+ const unsigned char *buffer,
+ int offset, size_t count)
+{
+ return -ENOSYS;
+}
#endif
@@ -550,13 +555,19 @@ static int omap2_onenand_write_bufferram(struct mtd_info *mtd, int area,
#else
-int omap2_onenand_read_bufferram(struct mtd_info *mtd, int area,
- unsigned char *buffer, int offset,
- size_t count);
+static int omap2_onenand_read_bufferram(struct mtd_info *mtd, int area,
+ unsigned char *buffer, int offset,
+ size_t count)
+{
+ return -ENOSYS;
+}
-int omap2_onenand_write_bufferram(struct mtd_info *mtd, int area,
- const unsigned char *buffer,
- int offset, size_t count);
+static int omap2_onenand_write_bufferram(struct mtd_info *mtd, int area,
+ const unsigned char *buffer,
+ int offset, size_t count)
+{
+ return -ENOSYS;
+}
#endif
@@ -639,6 +650,7 @@ static int __devinit omap2_onenand_probe(struct platform_device *pdev)
init_completion(&c->irq_done);
init_completion(&c->dma_done);
+ c->flags = pdata->flags;
c->gpmc_cs = pdata->cs;
c->gpio_irq = pdata->gpio_irq;
c->dma_channel = pdata->dma_channel;
@@ -729,7 +741,7 @@ static int __devinit omap2_onenand_probe(struct platform_device *pdev)
this = &c->onenand;
if (c->dma_channel >= 0) {
this->wait = omap2_onenand_wait;
- if (cpu_is_omap34xx()) {
+ if (c->flags & ONENAND_IN_OMAP34XX) {
this->read_bufferram = omap3_onenand_read_bufferram;
this->write_bufferram = omap3_onenand_write_bufferram;
} else {
@@ -803,7 +815,6 @@ static int __devexit omap2_onenand_remove(struct platform_device *pdev)
}
iounmap(c->onenand.base);
release_mem_region(c->phys_base, c->mem_size);
- gpmc_cs_free(c->gpmc_cs);
kfree(c);
return 0;
diff --git a/drivers/pcmcia/omap_cf.c b/drivers/pcmcia/omap_cf.c
index fa74efe82206..25c4b1993b3d 100644
--- a/drivers/pcmcia/omap_cf.c
+++ b/drivers/pcmcia/omap_cf.c
@@ -25,7 +25,7 @@
#include <asm/sizes.h>
#include <mach/mux.h>
-#include <plat/tc.h>
+#include <mach/tc.h>
/* NOTE: don't expect this to support many I/O cards. The 16xx chips have
diff --git a/drivers/staging/tidspbridge/include/dspbridge/host_os.h b/drivers/staging/tidspbridge/include/dspbridge/host_os.h
index 5e2f4d82d925..7f3a1db31619 100644
--- a/drivers/staging/tidspbridge/include/dspbridge/host_os.h
+++ b/drivers/staging/tidspbridge/include/dspbridge/host_os.h
@@ -40,7 +40,6 @@
#include <linux/vmalloc.h>
#include <linux/ioport.h>
#include <linux/platform_device.h>
-#include <plat/clock.h>
#include <linux/clk.h>
#include <plat/mailbox.h>
#include <linux/pagemap.h>
diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c
index 8c0b7b42319c..60b076cc4e20 100644
--- a/drivers/tty/n_tty.c
+++ b/drivers/tty/n_tty.c
@@ -73,10 +73,42 @@
#define ECHO_OP_SET_CANON_COL 0x81
#define ECHO_OP_ERASE_TAB 0x82
+struct n_tty_data {
+ unsigned int column;
+ unsigned long overrun_time;
+ int num_overrun;
+
+ unsigned char lnext:1, erasing:1, raw:1, real_raw:1, icanon:1;
+ unsigned char echo_overrun:1;
+
+ DECLARE_BITMAP(process_char_map, 256);
+ DECLARE_BITMAP(read_flags, N_TTY_BUF_SIZE);
+
+ char *read_buf;
+ int read_head;
+ int read_tail;
+ int read_cnt;
+
+ unsigned char *echo_buf;
+ unsigned int echo_pos;
+ unsigned int echo_cnt;
+
+ int canon_data;
+ unsigned long canon_head;
+ unsigned int canon_column;
+
+ struct mutex atomic_read_lock;
+ struct mutex output_lock;
+ struct mutex echo_lock;
+ spinlock_t read_lock;
+};
+
static inline int tty_put_user(struct tty_struct *tty, unsigned char x,
unsigned char __user *ptr)
{
- tty_audit_add_data(tty, &x, 1);
+ struct n_tty_data *ldata = tty->disc_data;
+
+ tty_audit_add_data(tty, &x, 1, ldata->icanon);
return put_user(x, ptr);
}
@@ -92,17 +124,18 @@ static inline int tty_put_user(struct tty_struct *tty, unsigned char x,
static void n_tty_set_room(struct tty_struct *tty)
{
+ struct n_tty_data *ldata = tty->disc_data;
int left;
int old_left;
- /* tty->read_cnt is not read locked ? */
+ /* ldata->read_cnt is not read locked ? */
if (I_PARMRK(tty)) {
/* Multiply read_cnt by 3, since each byte might take up to
* three times as many spaces when PARMRK is set (depending on
* its flags, e.g. parity error). */
- left = N_TTY_BUF_SIZE - tty->read_cnt * 3 - 1;
+ left = N_TTY_BUF_SIZE - ldata->read_cnt * 3 - 1;
} else
- left = N_TTY_BUF_SIZE - tty->read_cnt - 1;
+ left = N_TTY_BUF_SIZE - ldata->read_cnt - 1;
/*
* If we are doing input canonicalization, and there are no
@@ -111,44 +144,47 @@ static void n_tty_set_room(struct tty_struct *tty)
* characters will be beeped.
*/
if (left <= 0)
- left = tty->icanon && !tty->canon_data;
+ left = ldata->icanon && !ldata->canon_data;
old_left = tty->receive_room;
tty->receive_room = left;
/* Did this open up the receive buffer? We may need to flip */
- if (left && !old_left)
- schedule_work(&tty->buf.work);
+ if (left && !old_left) {
+ WARN_RATELIMIT(tty->port->itty == NULL,
+ "scheduling with invalid itty");
+ schedule_work(&tty->port->buf.work);
+ }
}
-static void put_tty_queue_nolock(unsigned char c, struct tty_struct *tty)
+static void put_tty_queue_nolock(unsigned char c, struct n_tty_data *ldata)
{
- if (tty->read_cnt < N_TTY_BUF_SIZE) {
- tty->read_buf[tty->read_head] = c;
- tty->read_head = (tty->read_head + 1) & (N_TTY_BUF_SIZE-1);
- tty->read_cnt++;
+ if (ldata->read_cnt < N_TTY_BUF_SIZE) {
+ ldata->read_buf[ldata->read_head] = c;
+ ldata->read_head = (ldata->read_head + 1) & (N_TTY_BUF_SIZE-1);
+ ldata->read_cnt++;
}
}
/**
* put_tty_queue - add character to tty
* @c: character
- * @tty: tty device
+ * @ldata: n_tty data
*
* Add a character to the tty read_buf queue. This is done under the
* read_lock to serialize character addition and also to protect us
* against parallel reads or flushes
*/
-static void put_tty_queue(unsigned char c, struct tty_struct *tty)
+static void put_tty_queue(unsigned char c, struct n_tty_data *ldata)
{
unsigned long flags;
/*
* The problem of stomping on the buffers ends here.
* Why didn't anyone see this one coming? --AJK
*/
- spin_lock_irqsave(&tty->read_lock, flags);
- put_tty_queue_nolock(c, tty);
- spin_unlock_irqrestore(&tty->read_lock, flags);
+ spin_lock_irqsave(&ldata->read_lock, flags);
+ put_tty_queue_nolock(c, ldata);
+ spin_unlock_irqrestore(&ldata->read_lock, flags);
}
/**
@@ -179,18 +215,19 @@ static void check_unthrottle(struct tty_struct *tty)
static void reset_buffer_flags(struct tty_struct *tty)
{
+ struct n_tty_data *ldata = tty->disc_data;
unsigned long flags;
- spin_lock_irqsave(&tty->read_lock, flags);
- tty->read_head = tty->read_tail = tty->read_cnt = 0;
- spin_unlock_irqrestore(&tty->read_lock, flags);
+ spin_lock_irqsave(&ldata->read_lock, flags);
+ ldata->read_head = ldata->read_tail = ldata->read_cnt = 0;
+ spin_unlock_irqrestore(&ldata->read_lock, flags);
- mutex_lock(&tty->echo_lock);
- tty->echo_pos = tty->echo_cnt = tty->echo_overrun = 0;
- mutex_unlock(&tty->echo_lock);
+ mutex_lock(&ldata->echo_lock);
+ ldata->echo_pos = ldata->echo_cnt = ldata->echo_overrun = 0;
+ mutex_unlock(&ldata->echo_lock);
- tty->canon_head = tty->canon_data = tty->erasing = 0;
- memset(&tty->read_flags, 0, sizeof tty->read_flags);
+ ldata->canon_head = ldata->canon_data = ldata->erasing = 0;
+ bitmap_zero(ldata->read_flags, N_TTY_BUF_SIZE);
n_tty_set_room(tty);
}
@@ -235,18 +272,19 @@ static void n_tty_flush_buffer(struct tty_struct *tty)
static ssize_t n_tty_chars_in_buffer(struct tty_struct *tty)
{
+ struct n_tty_data *ldata = tty->disc_data;
unsigned long flags;
ssize_t n = 0;
- spin_lock_irqsave(&tty->read_lock, flags);
- if (!tty->icanon) {
- n = tty->read_cnt;
- } else if (tty->canon_data) {
- n = (tty->canon_head > tty->read_tail) ?
- tty->canon_head - tty->read_tail :
- tty->canon_head + (N_TTY_BUF_SIZE - tty->read_tail);
+ spin_lock_irqsave(&ldata->read_lock, flags);
+ if (!ldata->icanon) {
+ n = ldata->read_cnt;
+ } else if (ldata->canon_data) {
+ n = (ldata->canon_head > ldata->read_tail) ?
+ ldata->canon_head - ldata->read_tail :
+ ldata->canon_head + (N_TTY_BUF_SIZE - ldata->read_tail);
}
- spin_unlock_irqrestore(&tty->read_lock, flags);
+ spin_unlock_irqrestore(&ldata->read_lock, flags);
return n;
}
@@ -301,6 +339,7 @@ static inline int is_continuation(unsigned char c, struct tty_struct *tty)
static int do_output_char(unsigned char c, struct tty_struct *tty, int space)
{
+ struct n_tty_data *ldata = tty->disc_data;
int spaces;
if (!space)
@@ -309,48 +348,48 @@ static int do_output_char(unsigned char c, struct tty_struct *tty, int space)
switch (c) {
case '\n':
if (O_ONLRET(tty))
- tty->column = 0;
+ ldata->column = 0;
if (O_ONLCR(tty)) {
if (space < 2)
return -1;
- tty->canon_column = tty->column = 0;
+ ldata->canon_column = ldata->column = 0;
tty->ops->write(tty, "\r\n", 2);
return 2;
}
- tty->canon_column = tty->column;
+ ldata->canon_column = ldata->column;
break;
case '\r':
- if (O_ONOCR(tty) && tty->column == 0)
+ if (O_ONOCR(tty) && ldata->column == 0)
return 0;
if (O_OCRNL(tty)) {
c = '\n';
if (O_ONLRET(tty))
- tty->canon_column = tty->column = 0;
+ ldata->canon_column = ldata->column = 0;
break;
}
- tty->canon_column = tty->column = 0;
+ ldata->canon_column = ldata->column = 0;
break;
case '\t':
- spaces = 8 - (tty->column & 7);
+ spaces = 8 - (ldata->column & 7);
if (O_TABDLY(tty) == XTABS) {
if (space < spaces)
return -1;
- tty->column += spaces;
+ ldata->column += spaces;
tty->ops->write(tty, " ", spaces);
return spaces;
}
- tty->column += spaces;
+ ldata->column += spaces;
break;
case '\b':
- if (tty->column > 0)
- tty->column--;
+ if (ldata->column > 0)
+ ldata->column--;
break;
default:
if (!iscntrl(c)) {
if (O_OLCUC(tty))
c = toupper(c);
if (!is_continuation(c, tty))
- tty->column++;
+ ldata->column++;
}
break;
}
@@ -375,14 +414,15 @@ static int do_output_char(unsigned char c, struct tty_struct *tty, int space)
static int process_output(unsigned char c, struct tty_struct *tty)
{
+ struct n_tty_data *ldata = tty->disc_data;
int space, retval;
- mutex_lock(&tty->output_lock);
+ mutex_lock(&ldata->output_lock);
space = tty_write_room(tty);
retval = do_output_char(c, tty, space);
- mutex_unlock(&tty->output_lock);
+ mutex_unlock(&ldata->output_lock);
if (retval < 0)
return -1;
else
@@ -411,15 +451,16 @@ static int process_output(unsigned char c, struct tty_struct *tty)
static ssize_t process_output_block(struct tty_struct *tty,
const unsigned char *buf, unsigned int nr)
{
+ struct n_tty_data *ldata = tty->disc_data;
int space;
int i;
const unsigned char *cp;
- mutex_lock(&tty->output_lock);
+ mutex_lock(&ldata->output_lock);
space = tty_write_room(tty);
if (!space) {
- mutex_unlock(&tty->output_lock);
+ mutex_unlock(&ldata->output_lock);
return 0;
}
if (nr > space)
@@ -431,30 +472,30 @@ static ssize_t process_output_block(struct tty_struct *tty,
switch (c) {
case '\n':
if (O_ONLRET(tty))
- tty->column = 0;
+ ldata->column = 0;
if (O_ONLCR(tty))
goto break_out;
- tty->canon_column = tty->column;
+ ldata->canon_column = ldata->column;
break;
case '\r':
- if (O_ONOCR(tty) && tty->column == 0)
+ if (O_ONOCR(tty) && ldata->column == 0)
goto break_out;
if (O_OCRNL(tty))
goto break_out;
- tty->canon_column = tty->column = 0;
+ ldata->canon_column = ldata->column = 0;
break;
case '\t':
goto break_out;
case '\b':
- if (tty->column > 0)
- tty->column--;
+ if (ldata->column > 0)
+ ldata->column--;
break;
default:
if (!iscntrl(c)) {
if (O_OLCUC(tty))
goto break_out;
if (!is_continuation(c, tty))
- tty->column++;
+ ldata->column++;
}
break;
}
@@ -462,7 +503,7 @@ static ssize_t process_output_block(struct tty_struct *tty,
break_out:
i = tty->ops->write(tty, buf, i);
- mutex_unlock(&tty->output_lock);
+ mutex_unlock(&ldata->output_lock);
return i;
}
@@ -494,21 +535,22 @@ break_out:
static void process_echoes(struct tty_struct *tty)
{
+ struct n_tty_data *ldata = tty->disc_data;
int space, nr;
unsigned char c;
unsigned char *cp, *buf_end;
- if (!tty->echo_cnt)
+ if (!ldata->echo_cnt)
return;
- mutex_lock(&tty->output_lock);
- mutex_lock(&tty->echo_lock);
+ mutex_lock(&ldata->output_lock);
+ mutex_lock(&ldata->echo_lock);
space = tty_write_room(tty);
- buf_end = tty->echo_buf + N_TTY_BUF_SIZE;
- cp = tty->echo_buf + tty->echo_pos;
- nr = tty->echo_cnt;
+ buf_end = ldata->echo_buf + N_TTY_BUF_SIZE;
+ cp = ldata->echo_buf + ldata->echo_pos;
+ nr = ldata->echo_cnt;
while (nr > 0) {
c = *cp;
if (c == ECHO_OP_START) {
@@ -545,7 +587,7 @@ static void process_echoes(struct tty_struct *tty)
* Otherwise, tab spacing is normal.
*/
if (!(num_chars & 0x80))
- num_chars += tty->canon_column;
+ num_chars += ldata->canon_column;
num_bs = 8 - (num_chars & 7);
if (num_bs > space) {
@@ -555,22 +597,22 @@ static void process_echoes(struct tty_struct *tty)
space -= num_bs;
while (num_bs--) {
tty_put_char(tty, '\b');
- if (tty->column > 0)
- tty->column--;
+ if (ldata->column > 0)
+ ldata->column--;
}
cp += 3;
nr -= 3;
break;
case ECHO_OP_SET_CANON_COL:
- tty->canon_column = tty->column;
+ ldata->canon_column = ldata->column;
cp += 2;
nr -= 2;
break;
case ECHO_OP_MOVE_BACK_COL:
- if (tty->column > 0)
- tty->column--;
+ if (ldata->column > 0)
+ ldata->column--;
cp += 2;
nr -= 2;
break;
@@ -582,7 +624,7 @@ static void process_echoes(struct tty_struct *tty)
break;
}
tty_put_char(tty, ECHO_OP_START);
- tty->column++;
+ ldata->column++;
space--;
cp += 2;
nr -= 2;
@@ -604,7 +646,7 @@ static void process_echoes(struct tty_struct *tty)
}
tty_put_char(tty, '^');
tty_put_char(tty, op ^ 0100);
- tty->column += 2;
+ ldata->column += 2;
space -= 2;
cp += 2;
nr -= 2;
@@ -635,20 +677,20 @@ static void process_echoes(struct tty_struct *tty)
}
if (nr == 0) {
- tty->echo_pos = 0;
- tty->echo_cnt = 0;
- tty->echo_overrun = 0;
+ ldata->echo_pos = 0;
+ ldata->echo_cnt = 0;
+ ldata->echo_overrun = 0;
} else {
- int num_processed = tty->echo_cnt - nr;
- tty->echo_pos += num_processed;
- tty->echo_pos &= N_TTY_BUF_SIZE - 1;
- tty->echo_cnt = nr;
+ int num_processed = ldata->echo_cnt - nr;
+ ldata->echo_pos += num_processed;
+ ldata->echo_pos &= N_TTY_BUF_SIZE - 1;
+ ldata->echo_cnt = nr;
if (num_processed > 0)
- tty->echo_overrun = 0;
+ ldata->echo_overrun = 0;
}
- mutex_unlock(&tty->echo_lock);
- mutex_unlock(&tty->output_lock);
+ mutex_unlock(&ldata->echo_lock);
+ mutex_unlock(&ldata->output_lock);
if (tty->ops->flush_chars)
tty->ops->flush_chars(tty);
@@ -657,72 +699,70 @@ static void process_echoes(struct tty_struct *tty)
/**
* add_echo_byte - add a byte to the echo buffer
* @c: unicode byte to echo
- * @tty: terminal device
+ * @ldata: n_tty data
*
* Add a character or operation byte to the echo buffer.
*
* Should be called under the echo lock to protect the echo buffer.
*/
-static void add_echo_byte(unsigned char c, struct tty_struct *tty)
+static void add_echo_byte(unsigned char c, struct n_tty_data *ldata)
{
int new_byte_pos;
- if (tty->echo_cnt == N_TTY_BUF_SIZE) {
+ if (ldata->echo_cnt == N_TTY_BUF_SIZE) {
/* Circular buffer is already at capacity */
- new_byte_pos = tty->echo_pos;
+ new_byte_pos = ldata->echo_pos;
/*
* Since the buffer start position needs to be advanced,
* be sure to step by a whole operation byte group.
*/
- if (tty->echo_buf[tty->echo_pos] == ECHO_OP_START) {
- if (tty->echo_buf[(tty->echo_pos + 1) &
+ if (ldata->echo_buf[ldata->echo_pos] == ECHO_OP_START) {
+ if (ldata->echo_buf[(ldata->echo_pos + 1) &
(N_TTY_BUF_SIZE - 1)] ==
ECHO_OP_ERASE_TAB) {
- tty->echo_pos += 3;
- tty->echo_cnt -= 2;
+ ldata->echo_pos += 3;
+ ldata->echo_cnt -= 2;
} else {
- tty->echo_pos += 2;
- tty->echo_cnt -= 1;
+ ldata->echo_pos += 2;
+ ldata->echo_cnt -= 1;
}
} else {
- tty->echo_pos++;
+ ldata->echo_pos++;
}
- tty->echo_pos &= N_TTY_BUF_SIZE - 1;
+ ldata->echo_pos &= N_TTY_BUF_SIZE - 1;
- tty->echo_overrun = 1;
+ ldata->echo_overrun = 1;
} else {
- new_byte_pos = tty->echo_pos + tty->echo_cnt;
+ new_byte_pos = ldata->echo_pos + ldata->echo_cnt;
new_byte_pos &= N_TTY_BUF_SIZE - 1;
- tty->echo_cnt++;
+ ldata->echo_cnt++;
}
- tty->echo_buf[new_byte_pos] = c;
+ ldata->echo_buf[new_byte_pos] = c;
}
/**
* echo_move_back_col - add operation to move back a column
- * @tty: terminal device
+ * @ldata: n_tty data
*
* Add an operation to the echo buffer to move back one column.
*
* Locking: echo_lock to protect the echo buffer
*/
-static void echo_move_back_col(struct tty_struct *tty)
+static void echo_move_back_col(struct n_tty_data *ldata)
{
- mutex_lock(&tty->echo_lock);
-
- add_echo_byte(ECHO_OP_START, tty);
- add_echo_byte(ECHO_OP_MOVE_BACK_COL, tty);
-
- mutex_unlock(&tty->echo_lock);
+ mutex_lock(&ldata->echo_lock);
+ add_echo_byte(ECHO_OP_START, ldata);
+ add_echo_byte(ECHO_OP_MOVE_BACK_COL, ldata);
+ mutex_unlock(&ldata->echo_lock);
}
/**
* echo_set_canon_col - add operation to set the canon column
- * @tty: terminal device
+ * @ldata: n_tty data
*
* Add an operation to the echo buffer to set the canon column
* to the current column.
@@ -730,21 +770,19 @@ static void echo_move_back_col(struct tty_struct *tty)
* Locking: echo_lock to protect the echo buffer
*/
-static void echo_set_canon_col(struct tty_struct *tty)
+static void echo_set_canon_col(struct n_tty_data *ldata)
{
- mutex_lock(&tty->echo_lock);
-
- add_echo_byte(ECHO_OP_START, tty);
- add_echo_byte(ECHO_OP_SET_CANON_COL, tty);
-
- mutex_unlock(&tty->echo_lock);
+ mutex_lock(&ldata->echo_lock);
+ add_echo_byte(ECHO_OP_START, ldata);
+ add_echo_byte(ECHO_OP_SET_CANON_COL, ldata);
+ mutex_unlock(&ldata->echo_lock);
}
/**
* echo_erase_tab - add operation to erase a tab
* @num_chars: number of character columns already used
* @after_tab: true if num_chars starts after a previous tab
- * @tty: terminal device
+ * @ldata: n_tty data
*
* Add an operation to the echo buffer to erase a tab.
*
@@ -758,12 +796,12 @@ static void echo_set_canon_col(struct tty_struct *tty)
*/
static void echo_erase_tab(unsigned int num_chars, int after_tab,
- struct tty_struct *tty)
+ struct n_tty_data *ldata)
{
- mutex_lock(&tty->echo_lock);
+ mutex_lock(&ldata->echo_lock);
- add_echo_byte(ECHO_OP_START, tty);
- add_echo_byte(ECHO_OP_ERASE_TAB, tty);
+ add_echo_byte(ECHO_OP_START, ldata);
+ add_echo_byte(ECHO_OP_ERASE_TAB, ldata);
/* We only need to know this modulo 8 (tab spacing) */
num_chars &= 7;
@@ -772,9 +810,9 @@ static void echo_erase_tab(unsigned int num_chars, int after_tab,
if (after_tab)
num_chars |= 0x80;
- add_echo_byte(num_chars, tty);
+ add_echo_byte(num_chars, ldata);
- mutex_unlock(&tty->echo_lock);
+ mutex_unlock(&ldata->echo_lock);
}
/**
@@ -790,18 +828,16 @@ static void echo_erase_tab(unsigned int num_chars, int after_tab,
* Locking: echo_lock to protect the echo buffer
*/
-static void echo_char_raw(unsigned char c, struct tty_struct *tty)
+static void echo_char_raw(unsigned char c, struct n_tty_data *ldata)
{
- mutex_lock(&tty->echo_lock);
-
+ mutex_lock(&ldata->echo_lock);
if (c == ECHO_OP_START) {
- add_echo_byte(ECHO_OP_START, tty);
- add_echo_byte(ECHO_OP_START, tty);
+ add_echo_byte(ECHO_OP_START, ldata);
+ add_echo_byte(ECHO_OP_START, ldata);
} else {
- add_echo_byte(c, tty);
+ add_echo_byte(c, ldata);
}
-
- mutex_unlock(&tty->echo_lock);
+ mutex_unlock(&ldata->echo_lock);
}
/**
@@ -820,30 +856,32 @@ static void echo_char_raw(unsigned char c, struct tty_struct *tty)
static void echo_char(unsigned char c, struct tty_struct *tty)
{
- mutex_lock(&tty->echo_lock);
+ struct n_tty_data *ldata = tty->disc_data;
+
+ mutex_lock(&ldata->echo_lock);
if (c == ECHO_OP_START) {
- add_echo_byte(ECHO_OP_START, tty);
- add_echo_byte(ECHO_OP_START, tty);
+ add_echo_byte(ECHO_OP_START, ldata);
+ add_echo_byte(ECHO_OP_START, ldata);
} else {
if (L_ECHOCTL(tty) && iscntrl(c) && c != '\t')
- add_echo_byte(ECHO_OP_START, tty);
- add_echo_byte(c, tty);
+ add_echo_byte(ECHO_OP_START, ldata);
+ add_echo_byte(c, ldata);
}
- mutex_unlock(&tty->echo_lock);
+ mutex_unlock(&ldata->echo_lock);
}
/**
* finish_erasing - complete erase
- * @tty: tty doing the erase
+ * @ldata: n_tty data
*/
-static inline void finish_erasing(struct tty_struct *tty)
+static inline void finish_erasing(struct n_tty_data *ldata)
{
- if (tty->erasing) {
- echo_char_raw('/', tty);
- tty->erasing = 0;
+ if (ldata->erasing) {
+ echo_char_raw('/', ldata);
+ ldata->erasing = 0;
}
}
@@ -861,12 +899,13 @@ static inline void finish_erasing(struct tty_struct *tty)
static void eraser(unsigned char c, struct tty_struct *tty)
{
+ struct n_tty_data *ldata = tty->disc_data;
enum { ERASE, WERASE, KILL } kill_type;
int head, seen_alnums, cnt;
unsigned long flags;
/* FIXME: locking needed ? */
- if (tty->read_head == tty->canon_head) {
+ if (ldata->read_head == ldata->canon_head) {
/* process_output('\a', tty); */ /* what do you think? */
return;
}
@@ -876,24 +915,24 @@ static void eraser(unsigned char c, struct tty_struct *tty)
kill_type = WERASE;
else {
if (!L_ECHO(tty)) {
- spin_lock_irqsave(&tty->read_lock, flags);
- tty->read_cnt -= ((tty->read_head - tty->canon_head) &
+ spin_lock_irqsave(&ldata->read_lock, flags);
+ ldata->read_cnt -= ((ldata->read_head - ldata->canon_head) &
(N_TTY_BUF_SIZE - 1));
- tty->read_head = tty->canon_head;
- spin_unlock_irqrestore(&tty->read_lock, flags);
+ ldata->read_head = ldata->canon_head;
+ spin_unlock_irqrestore(&ldata->read_lock, flags);
return;
}
if (!L_ECHOK(tty) || !L_ECHOKE(tty) || !L_ECHOE(tty)) {
- spin_lock_irqsave(&tty->read_lock, flags);
- tty->read_cnt -= ((tty->read_head - tty->canon_head) &
+ spin_lock_irqsave(&ldata->read_lock, flags);
+ ldata->read_cnt -= ((ldata->read_head - ldata->canon_head) &
(N_TTY_BUF_SIZE - 1));
- tty->read_head = tty->canon_head;
- spin_unlock_irqrestore(&tty->read_lock, flags);
- finish_erasing(tty);
+ ldata->read_head = ldata->canon_head;
+ spin_unlock_irqrestore(&ldata->read_lock, flags);
+ finish_erasing(ldata);
echo_char(KILL_CHAR(tty), tty);
/* Add a newline if ECHOK is on and ECHOKE is off. */
if (L_ECHOK(tty))
- echo_char_raw('\n', tty);
+ echo_char_raw('\n', ldata);
return;
}
kill_type = KILL;
@@ -901,14 +940,14 @@ static void eraser(unsigned char c, struct tty_struct *tty)
seen_alnums = 0;
/* FIXME: Locking ?? */
- while (tty->read_head != tty->canon_head) {
- head = tty->read_head;
+ while (ldata->read_head != ldata->canon_head) {
+ head = ldata->read_head;
/* erase a single possibly multibyte character */
do {
head = (head - 1) & (N_TTY_BUF_SIZE-1);
- c = tty->read_buf[head];
- } while (is_continuation(c, tty) && head != tty->canon_head);
+ c = ldata->read_buf[head];
+ } while (is_continuation(c, tty) && head != ldata->canon_head);
/* do not partially erase */
if (is_continuation(c, tty))
@@ -921,30 +960,31 @@ static void eraser(unsigned char c, struct tty_struct *tty)
else if (seen_alnums)
break;
}
- cnt = (tty->read_head - head) & (N_TTY_BUF_SIZE-1);
- spin_lock_irqsave(&tty->read_lock, flags);
- tty->read_head = head;
- tty->read_cnt -= cnt;
- spin_unlock_irqrestore(&tty->read_lock, flags);
+ cnt = (ldata->read_head - head) & (N_TTY_BUF_SIZE-1);
+ spin_lock_irqsave(&ldata->read_lock, flags);
+ ldata->read_head = head;
+ ldata->read_cnt -= cnt;
+ spin_unlock_irqrestore(&ldata->read_lock, flags);
if (L_ECHO(tty)) {
if (L_ECHOPRT(tty)) {
- if (!tty->erasing) {
- echo_char_raw('\\', tty);
- tty->erasing = 1;
+ if (!ldata->erasing) {
+ echo_char_raw('\\', ldata);
+ ldata->erasing = 1;
}
/* if cnt > 1, output a multi-byte character */
echo_char(c, tty);
while (--cnt > 0) {
head = (head+1) & (N_TTY_BUF_SIZE-1);
- echo_char_raw(tty->read_buf[head], tty);
- echo_move_back_col(tty);
+ echo_char_raw(ldata->read_buf[head],
+ ldata);
+ echo_move_back_col(ldata);
}
} else if (kill_type == ERASE && !L_ECHOE(tty)) {
echo_char(ERASE_CHAR(tty), tty);
} else if (c == '\t') {
unsigned int num_chars = 0;
int after_tab = 0;
- unsigned long tail = tty->read_head;
+ unsigned long tail = ldata->read_head;
/*
* Count the columns used for characters
@@ -953,9 +993,9 @@ static void eraser(unsigned char c, struct tty_struct *tty)
* This info is used to go back the correct
* number of columns.
*/
- while (tail != tty->canon_head) {
+ while (tail != ldata->canon_head) {
tail = (tail-1) & (N_TTY_BUF_SIZE-1);
- c = tty->read_buf[tail];
+ c = ldata->read_buf[tail];
if (c == '\t') {
after_tab = 1;
break;
@@ -966,25 +1006,25 @@ static void eraser(unsigned char c, struct tty_struct *tty)
num_chars++;
}
}
- echo_erase_tab(num_chars, after_tab, tty);
+ echo_erase_tab(num_chars, after_tab, ldata);
} else {
if (iscntrl(c) && L_ECHOCTL(tty)) {
- echo_char_raw('\b', tty);
- echo_char_raw(' ', tty);
- echo_char_raw('\b', tty);
+ echo_char_raw('\b', ldata);
+ echo_char_raw(' ', ldata);
+ echo_char_raw('\b', ldata);
}
if (!iscntrl(c) || L_ECHOCTL(tty)) {
- echo_char_raw('\b', tty);
- echo_char_raw(' ', tty);
- echo_char_raw('\b', tty);
+ echo_char_raw('\b', ldata);
+ echo_char_raw(' ', ldata);
+ echo_char_raw('\b', ldata);
}
}
}
if (kill_type == ERASE)
break;
}
- if (tty->read_head == tty->canon_head && L_ECHO(tty))
- finish_erasing(tty);
+ if (ldata->read_head == ldata->canon_head && L_ECHO(tty))
+ finish_erasing(ldata);
}
/**
@@ -1023,6 +1063,8 @@ static inline void isig(int sig, struct tty_struct *tty, int flush)
static inline void n_tty_receive_break(struct tty_struct *tty)
{
+ struct n_tty_data *ldata = tty->disc_data;
+
if (I_IGNBRK(tty))
return;
if (I_BRKINT(tty)) {
@@ -1030,10 +1072,10 @@ static inline void n_tty_receive_break(struct tty_struct *tty)
return;
}
if (I_PARMRK(tty)) {
- put_tty_queue('\377', tty);
- put_tty_queue('\0', tty);
+ put_tty_queue('\377', ldata);
+ put_tty_queue('\0', ldata);
}
- put_tty_queue('\0', tty);
+ put_tty_queue('\0', ldata);
wake_up_interruptible(&tty->read_wait);
}
@@ -1052,16 +1094,17 @@ static inline void n_tty_receive_break(struct tty_struct *tty)
static inline void n_tty_receive_overrun(struct tty_struct *tty)
{
+ struct n_tty_data *ldata = tty->disc_data;
char buf[64];
- tty->num_overrun++;
- if (time_before(tty->overrun_time, jiffies - HZ) ||
- time_after(tty->overrun_time, jiffies)) {
+ ldata->num_overrun++;
+ if (time_after(jiffies, ldata->overrun_time + HZ) ||
+ time_after(ldata->overrun_time, jiffies)) {
printk(KERN_WARNING "%s: %d input overrun(s)\n",
tty_name(tty, buf),
- tty->num_overrun);
- tty->overrun_time = jiffies;
- tty->num_overrun = 0;
+ ldata->num_overrun);
+ ldata->overrun_time = jiffies;
+ ldata->num_overrun = 0;
}
}
@@ -1076,16 +1119,18 @@ static inline void n_tty_receive_overrun(struct tty_struct *tty)
static inline void n_tty_receive_parity_error(struct tty_struct *tty,
unsigned char c)
{
+ struct n_tty_data *ldata = tty->disc_data;
+
if (I_IGNPAR(tty))
return;
if (I_PARMRK(tty)) {
- put_tty_queue('\377', tty);
- put_tty_queue('\0', tty);
- put_tty_queue(c, tty);
+ put_tty_queue('\377', ldata);
+ put_tty_queue('\0', ldata);
+ put_tty_queue(c, ldata);
} else if (I_INPCK(tty))
- put_tty_queue('\0', tty);
+ put_tty_queue('\0', ldata);
else
- put_tty_queue(c, tty);
+ put_tty_queue(c, ldata);
wake_up_interruptible(&tty->read_wait);
}
@@ -1101,11 +1146,12 @@ static inline void n_tty_receive_parity_error(struct tty_struct *tty,
static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
{
+ struct n_tty_data *ldata = tty->disc_data;
unsigned long flags;
int parmrk;
- if (tty->raw) {
- put_tty_queue(c, tty);
+ if (ldata->raw) {
+ put_tty_queue(c, ldata);
return;
}
@@ -1115,7 +1161,7 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
c = tolower(c);
if (L_EXTPROC(tty)) {
- put_tty_queue(c, tty);
+ put_tty_queue(c, ldata);
return;
}
@@ -1143,26 +1189,26 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
* handle specially, do shortcut processing to speed things
* up.
*/
- if (!test_bit(c, tty->process_char_map) || tty->lnext) {
- tty->lnext = 0;
+ if (!test_bit(c, ldata->process_char_map) || ldata->lnext) {
+ ldata->lnext = 0;
parmrk = (c == (unsigned char) '\377' && I_PARMRK(tty)) ? 1 : 0;
- if (tty->read_cnt >= (N_TTY_BUF_SIZE - parmrk - 1)) {
+ if (ldata->read_cnt >= (N_TTY_BUF_SIZE - parmrk - 1)) {
/* beep if no space */
if (L_ECHO(tty))
process_output('\a', tty);
return;
}
if (L_ECHO(tty)) {
- finish_erasing(tty);
+ finish_erasing(ldata);
/* Record the column of first canon char. */
- if (tty->canon_head == tty->read_head)
- echo_set_canon_col(tty);
+ if (ldata->canon_head == ldata->read_head)
+ echo_set_canon_col(ldata);
echo_char(c, tty);
process_echoes(tty);
}
if (parmrk)
- put_tty_queue(c, tty);
- put_tty_queue(c, tty);
+ put_tty_queue(c, ldata);
+ put_tty_queue(c, ldata);
return;
}
@@ -1218,7 +1264,7 @@ send_signal:
} else if (c == '\n' && I_INLCR(tty))
c = '\r';
- if (tty->icanon) {
+ if (ldata->icanon) {
if (c == ERASE_CHAR(tty) || c == KILL_CHAR(tty) ||
(c == WERASE_CHAR(tty) && L_IEXTEN(tty))) {
eraser(c, tty);
@@ -1226,12 +1272,12 @@ send_signal:
return;
}
if (c == LNEXT_CHAR(tty) && L_IEXTEN(tty)) {
- tty->lnext = 1;
+ ldata->lnext = 1;
if (L_ECHO(tty)) {
- finish_erasing(tty);
+ finish_erasing(ldata);
if (L_ECHOCTL(tty)) {
- echo_char_raw('^', tty);
- echo_char_raw('\b', tty);
+ echo_char_raw('^', ldata);
+ echo_char_raw('\b', ldata);
process_echoes(tty);
}
}
@@ -1239,34 +1285,34 @@ send_signal:
}
if (c == REPRINT_CHAR(tty) && L_ECHO(tty) &&
L_IEXTEN(tty)) {
- unsigned long tail = tty->canon_head;
+ unsigned long tail = ldata->canon_head;
- finish_erasing(tty);
+ finish_erasing(ldata);
echo_char(c, tty);
- echo_char_raw('\n', tty);
- while (tail != tty->read_head) {
- echo_char(tty->read_buf[tail], tty);
+ echo_char_raw('\n', ldata);
+ while (tail != ldata->read_head) {
+ echo_char(ldata->read_buf[tail], tty);
tail = (tail+1) & (N_TTY_BUF_SIZE-1);
}
process_echoes(tty);
return;
}
if (c == '\n') {
- if (tty->read_cnt >= N_TTY_BUF_SIZE) {
+ if (ldata->read_cnt >= N_TTY_BUF_SIZE) {
if (L_ECHO(tty))
process_output('\a', tty);
return;
}
if (L_ECHO(tty) || L_ECHONL(tty)) {
- echo_char_raw('\n', tty);
+ echo_char_raw('\n', ldata);
process_echoes(tty);
}
goto handle_newline;
}
if (c == EOF_CHAR(tty)) {
- if (tty->read_cnt >= N_TTY_BUF_SIZE)
+ if (ldata->read_cnt >= N_TTY_BUF_SIZE)
return;
- if (tty->canon_head != tty->read_head)
+ if (ldata->canon_head != ldata->read_head)
set_bit(TTY_PUSH, &tty->flags);
c = __DISABLED_CHAR;
goto handle_newline;
@@ -1275,7 +1321,7 @@ send_signal:
(c == EOL2_CHAR(tty) && L_IEXTEN(tty))) {
parmrk = (c == (unsigned char) '\377' && I_PARMRK(tty))
? 1 : 0;
- if (tty->read_cnt >= (N_TTY_BUF_SIZE - parmrk)) {
+ if (ldata->read_cnt >= (N_TTY_BUF_SIZE - parmrk)) {
if (L_ECHO(tty))
process_output('\a', tty);
return;
@@ -1285,8 +1331,8 @@ send_signal:
*/
if (L_ECHO(tty)) {
/* Record the column of first canon char. */
- if (tty->canon_head == tty->read_head)
- echo_set_canon_col(tty);
+ if (ldata->canon_head == ldata->read_head)
+ echo_set_canon_col(ldata);
echo_char(c, tty);
process_echoes(tty);
}
@@ -1295,15 +1341,15 @@ send_signal:
* EOL_CHAR and EOL2_CHAR?
*/
if (parmrk)
- put_tty_queue(c, tty);
+ put_tty_queue(c, ldata);
handle_newline:
- spin_lock_irqsave(&tty->read_lock, flags);
- set_bit(tty->read_head, tty->read_flags);
- put_tty_queue_nolock(c, tty);
- tty->canon_head = tty->read_head;
- tty->canon_data++;
- spin_unlock_irqrestore(&tty->read_lock, flags);
+ spin_lock_irqsave(&ldata->read_lock, flags);
+ set_bit(ldata->read_head, ldata->read_flags);
+ put_tty_queue_nolock(c, ldata);
+ ldata->canon_head = ldata->read_head;
+ ldata->canon_data++;
+ spin_unlock_irqrestore(&ldata->read_lock, flags);
kill_fasync(&tty->fasync, SIGIO, POLL_IN);
if (waitqueue_active(&tty->read_wait))
wake_up_interruptible(&tty->read_wait);
@@ -1312,29 +1358,29 @@ handle_newline:
}
parmrk = (c == (unsigned char) '\377' && I_PARMRK(tty)) ? 1 : 0;
- if (tty->read_cnt >= (N_TTY_BUF_SIZE - parmrk - 1)) {
+ if (ldata->read_cnt >= (N_TTY_BUF_SIZE - parmrk - 1)) {
/* beep if no space */
if (L_ECHO(tty))
process_output('\a', tty);
return;
}
if (L_ECHO(tty)) {
- finish_erasing(tty);
+ finish_erasing(ldata);
if (c == '\n')
- echo_char_raw('\n', tty);
+ echo_char_raw('\n', ldata);
else {
/* Record the column of first canon char. */
- if (tty->canon_head == tty->read_head)
- echo_set_canon_col(tty);
+ if (ldata->canon_head == ldata->read_head)
+ echo_set_canon_col(ldata);
echo_char(c, tty);
}
process_echoes(tty);
}
if (parmrk)
- put_tty_queue(c, tty);
+ put_tty_queue(c, ldata);
- put_tty_queue(c, tty);
+ put_tty_queue(c, ldata);
}
@@ -1369,33 +1415,31 @@ static void n_tty_write_wakeup(struct tty_struct *tty)
static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
char *fp, int count)
{
+ struct n_tty_data *ldata = tty->disc_data;
const unsigned char *p;
char *f, flags = TTY_NORMAL;
int i;
char buf[64];
unsigned long cpuflags;
- if (!tty->read_buf)
- return;
-
- if (tty->real_raw) {
- spin_lock_irqsave(&tty->read_lock, cpuflags);
- i = min(N_TTY_BUF_SIZE - tty->read_cnt,
- N_TTY_BUF_SIZE - tty->read_head);
+ if (ldata->real_raw) {
+ spin_lock_irqsave(&ldata->read_lock, cpuflags);
+ i = min(N_TTY_BUF_SIZE - ldata->read_cnt,
+ N_TTY_BUF_SIZE - ldata->read_head);
i = min(count, i);
- memcpy(tty->read_buf + tty->read_head, cp, i);
- tty->read_head = (tty->read_head + i) & (N_TTY_BUF_SIZE-1);
- tty->read_cnt += i;
+ memcpy(ldata->read_buf + ldata->read_head, cp, i);
+ ldata->read_head = (ldata->read_head + i) & (N_TTY_BUF_SIZE-1);
+ ldata->read_cnt += i;
cp += i;
count -= i;
- i = min(N_TTY_BUF_SIZE - tty->read_cnt,
- N_TTY_BUF_SIZE - tty->read_head);
+ i = min(N_TTY_BUF_SIZE - ldata->read_cnt,
+ N_TTY_BUF_SIZE - ldata->read_head);
i = min(count, i);
- memcpy(tty->read_buf + tty->read_head, cp, i);
- tty->read_head = (tty->read_head + i) & (N_TTY_BUF_SIZE-1);
- tty->read_cnt += i;
- spin_unlock_irqrestore(&tty->read_lock, cpuflags);
+ memcpy(ldata->read_buf + ldata->read_head, cp, i);
+ ldata->read_head = (ldata->read_head + i) & (N_TTY_BUF_SIZE-1);
+ ldata->read_cnt += i;
+ spin_unlock_irqrestore(&ldata->read_lock, cpuflags);
} else {
for (i = count, p = cp, f = fp; i; i--, p++) {
if (f)
@@ -1426,7 +1470,7 @@ static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
n_tty_set_room(tty);
- if ((!tty->icanon && (tty->read_cnt >= tty->minimum_to_wake)) ||
+ if ((!ldata->icanon && (ldata->read_cnt >= tty->minimum_to_wake)) ||
L_EXTPROC(tty)) {
kill_fasync(&tty->fasync, SIGIO, POLL_IN);
if (waitqueue_active(&tty->read_wait))
@@ -1470,25 +1514,25 @@ int is_ignored(int sig)
static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old)
{
+ struct n_tty_data *ldata = tty->disc_data;
int canon_change = 1;
- BUG_ON(!tty);
if (old)
canon_change = (old->c_lflag ^ tty->termios.c_lflag) & ICANON;
if (canon_change) {
- memset(&tty->read_flags, 0, sizeof tty->read_flags);
- tty->canon_head = tty->read_tail;
- tty->canon_data = 0;
- tty->erasing = 0;
+ bitmap_zero(ldata->read_flags, N_TTY_BUF_SIZE);
+ ldata->canon_head = ldata->read_tail;
+ ldata->canon_data = 0;
+ ldata->erasing = 0;
}
- if (canon_change && !L_ICANON(tty) && tty->read_cnt)
+ if (canon_change && !L_ICANON(tty) && ldata->read_cnt)
wake_up_interruptible(&tty->read_wait);
- tty->icanon = (L_ICANON(tty) != 0);
+ ldata->icanon = (L_ICANON(tty) != 0);
if (test_bit(TTY_HW_COOK_IN, &tty->flags)) {
- tty->raw = 1;
- tty->real_raw = 1;
+ ldata->raw = 1;
+ ldata->real_raw = 1;
n_tty_set_room(tty);
return;
}
@@ -1496,51 +1540,51 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old)
I_ICRNL(tty) || I_INLCR(tty) || L_ICANON(tty) ||
I_IXON(tty) || L_ISIG(tty) || L_ECHO(tty) ||
I_PARMRK(tty)) {
- memset(tty->process_char_map, 0, 256/8);
+ bitmap_zero(ldata->process_char_map, 256);
if (I_IGNCR(tty) || I_ICRNL(tty))
- set_bit('\r', tty->process_char_map);
+ set_bit('\r', ldata->process_char_map);
if (I_INLCR(tty))
- set_bit('\n', tty->process_char_map);
+ set_bit('\n', ldata->process_char_map);
if (L_ICANON(tty)) {
- set_bit(ERASE_CHAR(tty), tty->process_char_map);
- set_bit(KILL_CHAR(tty), tty->process_char_map);
- set_bit(EOF_CHAR(tty), tty->process_char_map);
- set_bit('\n', tty->process_char_map);
- set_bit(EOL_CHAR(tty), tty->process_char_map);
+ set_bit(ERASE_CHAR(tty), ldata->process_char_map);
+ set_bit(KILL_CHAR(tty), ldata->process_char_map);
+ set_bit(EOF_CHAR(tty), ldata->process_char_map);
+ set_bit('\n', ldata->process_char_map);
+ set_bit(EOL_CHAR(tty), ldata->process_char_map);
if (L_IEXTEN(tty)) {
set_bit(WERASE_CHAR(tty),
- tty->process_char_map);
+ ldata->process_char_map);
set_bit(LNEXT_CHAR(tty),
- tty->process_char_map);
+ ldata->process_char_map);
set_bit(EOL2_CHAR(tty),
- tty->process_char_map);
+ ldata->process_char_map);
if (L_ECHO(tty))
set_bit(REPRINT_CHAR(tty),
- tty->process_char_map);
+ ldata->process_char_map);
}
}
if (I_IXON(tty)) {
- set_bit(START_CHAR(tty), tty->process_char_map);
- set_bit(STOP_CHAR(tty), tty->process_char_map);
+ set_bit(START_CHAR(tty), ldata->process_char_map);
+ set_bit(STOP_CHAR(tty), ldata->process_char_map);
}
if (L_ISIG(tty)) {
- set_bit(INTR_CHAR(tty), tty->process_char_map);
- set_bit(QUIT_CHAR(tty), tty->process_char_map);
- set_bit(SUSP_CHAR(tty), tty->process_char_map);
+ set_bit(INTR_CHAR(tty), ldata->process_char_map);
+ set_bit(QUIT_CHAR(tty), ldata->process_char_map);
+ set_bit(SUSP_CHAR(tty), ldata->process_char_map);
}
- clear_bit(__DISABLED_CHAR, tty->process_char_map);
- tty->raw = 0;
- tty->real_raw = 0;
+ clear_bit(__DISABLED_CHAR, ldata->process_char_map);
+ ldata->raw = 0;
+ ldata->real_raw = 0;
} else {
- tty->raw = 1;
+ ldata->raw = 1;
if ((I_IGNBRK(tty) || (!I_BRKINT(tty) && !I_PARMRK(tty))) &&
(I_IGNPAR(tty) || !I_INPCK(tty)) &&
(tty->driver->flags & TTY_DRIVER_REAL_RAW))
- tty->real_raw = 1;
+ ldata->real_raw = 1;
else
- tty->real_raw = 0;
+ ldata->real_raw = 0;
}
n_tty_set_room(tty);
/* The termios change make the tty ready for I/O */
@@ -1560,15 +1604,13 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old)
static void n_tty_close(struct tty_struct *tty)
{
+ struct n_tty_data *ldata = tty->disc_data;
+
n_tty_flush_buffer(tty);
- if (tty->read_buf) {
- kfree(tty->read_buf);
- tty->read_buf = NULL;
- }
- if (tty->echo_buf) {
- kfree(tty->echo_buf);
- tty->echo_buf = NULL;
- }
+ kfree(ldata->read_buf);
+ kfree(ldata->echo_buf);
+ kfree(ldata);
+ tty->disc_data = NULL;
}
/**
@@ -1583,37 +1625,50 @@ static void n_tty_close(struct tty_struct *tty)
static int n_tty_open(struct tty_struct *tty)
{
- if (!tty)
- return -EINVAL;
+ struct n_tty_data *ldata;
+
+ ldata = kzalloc(sizeof(*ldata), GFP_KERNEL);
+ if (!ldata)
+ goto err;
+
+ ldata->overrun_time = jiffies;
+ mutex_init(&ldata->atomic_read_lock);
+ mutex_init(&ldata->output_lock);
+ mutex_init(&ldata->echo_lock);
+ spin_lock_init(&ldata->read_lock);
/* These are ugly. Currently a malloc failure here can panic */
- if (!tty->read_buf) {
- tty->read_buf = kzalloc(N_TTY_BUF_SIZE, GFP_KERNEL);
- if (!tty->read_buf)
- return -ENOMEM;
- }
- if (!tty->echo_buf) {
- tty->echo_buf = kzalloc(N_TTY_BUF_SIZE, GFP_KERNEL);
+ ldata->read_buf = kzalloc(N_TTY_BUF_SIZE, GFP_KERNEL);
+ ldata->echo_buf = kzalloc(N_TTY_BUF_SIZE, GFP_KERNEL);
+ if (!ldata->read_buf || !ldata->echo_buf)
+ goto err_free_bufs;
- if (!tty->echo_buf)
- return -ENOMEM;
- }
+ tty->disc_data = ldata;
reset_buffer_flags(tty);
tty_unthrottle(tty);
- tty->column = 0;
+ ldata->column = 0;
n_tty_set_termios(tty, NULL);
tty->minimum_to_wake = 1;
tty->closing = 0;
+
return 0;
+err_free_bufs:
+ kfree(ldata->read_buf);
+ kfree(ldata->echo_buf);
+ kfree(ldata);
+err:
+ return -ENOMEM;
}
static inline int input_available_p(struct tty_struct *tty, int amt)
{
+ struct n_tty_data *ldata = tty->disc_data;
+
tty_flush_to_ldisc(tty);
- if (tty->icanon && !L_EXTPROC(tty)) {
- if (tty->canon_data)
+ if (ldata->icanon && !L_EXTPROC(tty)) {
+ if (ldata->canon_data)
return 1;
- } else if (tty->read_cnt >= (amt ? amt : 1))
+ } else if (ldata->read_cnt >= (amt ? amt : 1))
return 1;
return 0;
@@ -1632,7 +1687,7 @@ static inline int input_available_p(struct tty_struct *tty, int amt)
* buffer, and once to drain the space from the (physical) beginning of
* the buffer to head pointer.
*
- * Called under the tty->atomic_read_lock sem
+ * Called under the ldata->atomic_read_lock sem
*
*/
@@ -1641,29 +1696,31 @@ static int copy_from_read_buf(struct tty_struct *tty,
size_t *nr)
{
+ struct n_tty_data *ldata = tty->disc_data;
int retval;
size_t n;
unsigned long flags;
bool is_eof;
retval = 0;
- spin_lock_irqsave(&tty->read_lock, flags);
- n = min(tty->read_cnt, N_TTY_BUF_SIZE - tty->read_tail);
+ spin_lock_irqsave(&ldata->read_lock, flags);
+ n = min(ldata->read_cnt, N_TTY_BUF_SIZE - ldata->read_tail);
n = min(*nr, n);
- spin_unlock_irqrestore(&tty->read_lock, flags);
+ spin_unlock_irqrestore(&ldata->read_lock, flags);
if (n) {
- retval = copy_to_user(*b, &tty->read_buf[tty->read_tail], n);
+ retval = copy_to_user(*b, &ldata->read_buf[ldata->read_tail], n);
n -= retval;
is_eof = n == 1 &&
- tty->read_buf[tty->read_tail] == EOF_CHAR(tty);
- tty_audit_add_data(tty, &tty->read_buf[tty->read_tail], n);
- spin_lock_irqsave(&tty->read_lock, flags);
- tty->read_tail = (tty->read_tail + n) & (N_TTY_BUF_SIZE-1);
- tty->read_cnt -= n;
+ ldata->read_buf[ldata->read_tail] == EOF_CHAR(tty);
+ tty_audit_add_data(tty, &ldata->read_buf[ldata->read_tail], n,
+ ldata->icanon);
+ spin_lock_irqsave(&ldata->read_lock, flags);
+ ldata->read_tail = (ldata->read_tail + n) & (N_TTY_BUF_SIZE-1);
+ ldata->read_cnt -= n;
/* Turn single EOF into zero-length read */
- if (L_EXTPROC(tty) && tty->icanon && is_eof && !tty->read_cnt)
+ if (L_EXTPROC(tty) && ldata->icanon && is_eof && !ldata->read_cnt)
n = 0;
- spin_unlock_irqrestore(&tty->read_lock, flags);
+ spin_unlock_irqrestore(&ldata->read_lock, flags);
*b += n;
*nr -= n;
}
@@ -1730,6 +1787,7 @@ static int job_control(struct tty_struct *tty, struct file *file)
static ssize_t n_tty_read(struct tty_struct *tty, struct file *file,
unsigned char __user *buf, size_t nr)
{
+ struct n_tty_data *ldata = tty->disc_data;
unsigned char __user *b = buf;
DECLARE_WAITQUEUE(wait, current);
int c;
@@ -1741,17 +1799,13 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file,
int packet;
do_it_again:
-
- if (WARN_ON(!tty->read_buf))
- return -EAGAIN;
-
c = job_control(tty, file);
if (c < 0)
return c;
minimum = time = 0;
timeout = MAX_SCHEDULE_TIMEOUT;
- if (!tty->icanon) {
+ if (!ldata->icanon) {
time = (HZ / 10) * TIME_CHAR(tty);
minimum = MIN_CHAR(tty);
if (minimum) {
@@ -1774,10 +1828,10 @@ do_it_again:
* Internal serialization of reads.
*/
if (file->f_flags & O_NONBLOCK) {
- if (!mutex_trylock(&tty->atomic_read_lock))
+ if (!mutex_trylock(&ldata->atomic_read_lock))
return -EAGAIN;
} else {
- if (mutex_lock_interruptible(&tty->atomic_read_lock))
+ if (mutex_lock_interruptible(&ldata->atomic_read_lock))
return -ERESTARTSYS;
}
packet = tty->packet;
@@ -1830,7 +1884,6 @@ do_it_again:
/* FIXME: does n_tty_set_room need locking ? */
n_tty_set_room(tty);
timeout = schedule_timeout(timeout);
- BUG_ON(!tty->read_buf);
continue;
}
__set_current_state(TASK_RUNNING);
@@ -1845,45 +1898,45 @@ do_it_again:
nr--;
}
- if (tty->icanon && !L_EXTPROC(tty)) {
+ if (ldata->icanon && !L_EXTPROC(tty)) {
/* N.B. avoid overrun if nr == 0 */
- spin_lock_irqsave(&tty->read_lock, flags);
- while (nr && tty->read_cnt) {
+ spin_lock_irqsave(&ldata->read_lock, flags);
+ while (nr && ldata->read_cnt) {
int eol;
- eol = test_and_clear_bit(tty->read_tail,
- tty->read_flags);
- c = tty->read_buf[tty->read_tail];
- tty->read_tail = ((tty->read_tail+1) &
+ eol = test_and_clear_bit(ldata->read_tail,
+ ldata->read_flags);
+ c = ldata->read_buf[ldata->read_tail];
+ ldata->read_tail = ((ldata->read_tail+1) &
(N_TTY_BUF_SIZE-1));
- tty->read_cnt--;
+ ldata->read_cnt--;
if (eol) {
/* this test should be redundant:
* we shouldn't be reading data if
* canon_data is 0
*/
- if (--tty->canon_data < 0)
- tty->canon_data = 0;
+ if (--ldata->canon_data < 0)
+ ldata->canon_data = 0;
}
- spin_unlock_irqrestore(&tty->read_lock, flags);
+ spin_unlock_irqrestore(&ldata->read_lock, flags);
if (!eol || (c != __DISABLED_CHAR)) {
if (tty_put_user(tty, c, b++)) {
retval = -EFAULT;
b--;
- spin_lock_irqsave(&tty->read_lock, flags);
+ spin_lock_irqsave(&ldata->read_lock, flags);
break;
}
nr--;
}
if (eol) {
tty_audit_push(tty);
- spin_lock_irqsave(&tty->read_lock, flags);
+ spin_lock_irqsave(&ldata->read_lock, flags);
break;
}
- spin_lock_irqsave(&tty->read_lock, flags);
+ spin_lock_irqsave(&ldata->read_lock, flags);
}
- spin_unlock_irqrestore(&tty->read_lock, flags);
+ spin_unlock_irqrestore(&ldata->read_lock, flags);
if (retval)
break;
} else {
@@ -1915,7 +1968,7 @@ do_it_again:
if (time)
timeout = time;
}
- mutex_unlock(&tty->atomic_read_lock);
+ mutex_unlock(&ldata->atomic_read_lock);
remove_wait_queue(&tty->read_wait, &wait);
if (!waitqueue_active(&tty->read_wait))
@@ -2076,19 +2129,19 @@ static unsigned int n_tty_poll(struct tty_struct *tty, struct file *file,
return mask;
}
-static unsigned long inq_canon(struct tty_struct *tty)
+static unsigned long inq_canon(struct n_tty_data *ldata)
{
int nr, head, tail;
- if (!tty->canon_data)
+ if (!ldata->canon_data)
return 0;
- head = tty->canon_head;
- tail = tty->read_tail;
+ head = ldata->canon_head;
+ tail = ldata->read_tail;
nr = (head - tail) & (N_TTY_BUF_SIZE-1);
/* Skip EOF-chars.. */
while (head != tail) {
- if (test_bit(tail, tty->read_flags) &&
- tty->read_buf[tail] == __DISABLED_CHAR)
+ if (test_bit(tail, ldata->read_flags) &&
+ ldata->read_buf[tail] == __DISABLED_CHAR)
nr--;
tail = (tail+1) & (N_TTY_BUF_SIZE-1);
}
@@ -2098,6 +2151,7 @@ static unsigned long inq_canon(struct tty_struct *tty)
static int n_tty_ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg)
{
+ struct n_tty_data *ldata = tty->disc_data;
int retval;
switch (cmd) {
@@ -2105,9 +2159,9 @@ static int n_tty_ioctl(struct tty_struct *tty, struct file *file,
return put_user(tty_chars_in_buffer(tty), (int __user *) arg);
case TIOCINQ:
/* FIXME: Locking */
- retval = tty->read_cnt;
+ retval = ldata->read_cnt;
if (L_ICANON(tty))
- retval = inq_canon(tty);
+ retval = inq_canon(ldata);
return put_user(retval, (unsigned int __user *) arg);
default:
return n_tty_ioctl_helper(tty, file, cmd, arg);
diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c
index a82b39939a9c..4219f040adb8 100644
--- a/drivers/tty/pty.c
+++ b/drivers/tty/pty.c
@@ -4,9 +4,6 @@
* Added support for a Unix98-style ptmx device.
* -- C. Scott Ananian <cananian@alumni.princeton.edu>, 14-Jan-1998
*
- * When reading this code see also fs/devpts. In particular note that the
- * driver_data field is used by the devpts side as a binding to the devpts
- * inode.
*/
#include <linux/module.h>
@@ -59,7 +56,7 @@ static void pty_close(struct tty_struct *tty, struct file *filp)
#ifdef CONFIG_UNIX98_PTYS
if (tty->driver == ptm_driver) {
mutex_lock(&devpts_mutex);
- devpts_pty_kill(tty->link);
+ devpts_pty_kill(tty->link->driver_data);
mutex_unlock(&devpts_mutex);
}
#endif
@@ -96,7 +93,7 @@ static void pty_unthrottle(struct tty_struct *tty)
static int pty_space(struct tty_struct *to)
{
- int n = 8192 - to->buf.memory_used;
+ int n = 8192 - to->port->buf.memory_used;
if (n < 0)
return 0;
return n;
@@ -348,6 +345,7 @@ static int pty_common_install(struct tty_driver *driver, struct tty_struct *tty,
tty_port_init(ports[1]);
o_tty->port = ports[0];
tty->port = ports[1];
+ o_tty->port->itty = o_tty;
tty_driver_kref_get(driver);
tty->count++;
@@ -366,8 +364,15 @@ err:
return retval;
}
+/* this is called once with whichever end is closed last */
+static void pty_unix98_shutdown(struct tty_struct *tty)
+{
+ devpts_kill_index(tty->driver_data, tty->index);
+}
+
static void pty_cleanup(struct tty_struct *tty)
{
+ tty->port->itty = NULL;
kfree(tty->port);
}
@@ -547,7 +552,7 @@ static struct tty_struct *pts_unix98_lookup(struct tty_driver *driver,
struct tty_struct *tty;
mutex_lock(&devpts_mutex);
- tty = devpts_get_tty(pts_inode, idx);
+ tty = devpts_get_priv(pts_inode);
mutex_unlock(&devpts_mutex);
/* Master must be open before slave */
if (!tty)
@@ -581,6 +586,7 @@ static const struct tty_operations ptm_unix98_ops = {
.set_termios = pty_set_termios,
.ioctl = pty_unix98_ioctl,
.resize = pty_resize,
+ .shutdown = pty_unix98_shutdown,
.cleanup = pty_cleanup
};
@@ -596,6 +602,7 @@ static const struct tty_operations pty_unix98_ops = {
.chars_in_buffer = pty_chars_in_buffer,
.unthrottle = pty_unthrottle,
.set_termios = pty_set_termios,
+ .shutdown = pty_unix98_shutdown,
.cleanup = pty_cleanup,
};
@@ -614,6 +621,7 @@ static const struct tty_operations pty_unix98_ops = {
static int ptmx_open(struct inode *inode, struct file *filp)
{
struct tty_struct *tty;
+ struct inode *slave_inode;
int retval;
int index;
@@ -650,15 +658,21 @@ static int ptmx_open(struct inode *inode, struct file *filp)
tty_add_file(tty, filp);
- retval = devpts_pty_new(inode, tty->link);
- if (retval)
+ slave_inode = devpts_pty_new(inode,
+ MKDEV(UNIX98_PTY_SLAVE_MAJOR, index), index,
+ tty->link);
+ if (IS_ERR(slave_inode)) {
+ retval = PTR_ERR(slave_inode);
goto err_release;
+ }
retval = ptm_driver->ops->open(tty, filp);
if (retval)
goto err_release;
tty_unlock(tty);
+ tty->driver_data = inode;
+ tty->link->driver_data = slave_inode;
return 0;
err_release:
tty_unlock(tty);
diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c
index 3ba4234592bc..5ccbd90540cf 100644
--- a/drivers/tty/serial/8250/8250.c
+++ b/drivers/tty/serial/8250/8250.c
@@ -2349,16 +2349,14 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
serial_port_out(port, UART_EFR, efr);
}
-#ifdef CONFIG_ARCH_OMAP1
/* Workaround to enable 115200 baud on OMAP1510 internal ports */
- if (cpu_is_omap1510() && is_omap_port(up)) {
+ if (is_omap1510_8250(up)) {
if (baud == 115200) {
quot = 1;
serial_port_out(port, UART_OMAP_OSC_12M_SEL, 1);
} else
serial_port_out(port, UART_OMAP_OSC_12M_SEL, 0);
}
-#endif
/*
* For NatSemi, switch to bank 2 not bank 1, to avoid resetting EXCR2,
@@ -2439,10 +2437,9 @@ static unsigned int serial8250_port_size(struct uart_8250_port *pt)
{
if (pt->port.iotype == UPIO_AU)
return 0x1000;
-#ifdef CONFIG_ARCH_OMAP1
- if (is_omap_port(pt))
+ if (is_omap1_8250(pt))
return 0x16 << pt->port.regshift;
-#endif
+
return 8 << pt->port.regshift;
}
diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h
index 5a76f9c8d36b..3b4ea84898c2 100644
--- a/drivers/tty/serial/8250/8250.h
+++ b/drivers/tty/serial/8250/8250.h
@@ -106,3 +106,39 @@ static inline int serial8250_pnp_init(void) { return 0; }
static inline void serial8250_pnp_exit(void) { }
#endif
+#ifdef CONFIG_ARCH_OMAP1
+static inline int is_omap1_8250(struct uart_8250_port *pt)
+{
+ int res;
+
+ switch (pt->port.mapbase) {
+ case OMAP1_UART1_BASE:
+ case OMAP1_UART2_BASE:
+ case OMAP1_UART3_BASE:
+ res = 1;
+ break;
+ default:
+ res = 0;
+ break;
+ }
+
+ return res;
+}
+
+static inline int is_omap1510_8250(struct uart_8250_port *pt)
+{
+ if (!cpu_is_omap1510())
+ return 0;
+
+ return is_omap1_8250(pt);
+}
+#else
+static inline int is_omap1_8250(struct uart_8250_port *pt)
+{
+ return 0;
+}
+static inline int is_omap1510_8250(struct uart_8250_port *pt)
+{
+ return 0;
+}
+#endif
diff --git a/drivers/tty/serial/8250/8250_early.c b/drivers/tty/serial/8250/8250_early.c
index eaafb98debed..843a150ba105 100644
--- a/drivers/tty/serial/8250/8250_early.c
+++ b/drivers/tty/serial/8250/8250_early.c
@@ -140,7 +140,7 @@ static void __init init_port(struct early_serial8250_device *device)
serial_out(port, UART_FCR, 0); /* no fifo */
serial_out(port, UART_MCR, 0x3); /* DTR + RTS */
- divisor = port->uartclk / (16 * device->baud);
+ divisor = DIV_ROUND_CLOSEST(port->uartclk, 16 * device->baud);
c = serial_in(port, UART_LCR);
serial_out(port, UART_LCR, c | UART_LCR_DLAB);
serial_out(port, UART_DLL, divisor & 0xff);
diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c
index 7f04717176aa..740458ca62cc 100644
--- a/drivers/tty/serial/samsung.c
+++ b/drivers/tty/serial/samsung.c
@@ -530,16 +530,16 @@ static void s3c24xx_serial_pm(struct uart_port *port, unsigned int level,
switch (level) {
case 3:
if (!IS_ERR(ourport->baudclk))
- clk_disable(ourport->baudclk);
+ clk_disable_unprepare(ourport->baudclk);
- clk_disable(ourport->clk);
+ clk_disable_unprepare(ourport->clk);
break;
case 0:
- clk_enable(ourport->clk);
+ clk_prepare_enable(ourport->clk);
if (!IS_ERR(ourport->baudclk))
- clk_enable(ourport->baudclk);
+ clk_prepare_enable(ourport->baudclk);
break;
default:
@@ -713,11 +713,11 @@ static void s3c24xx_serial_set_termios(struct uart_port *port,
s3c24xx_serial_setsource(port, clk_sel);
if (!IS_ERR(ourport->baudclk)) {
- clk_disable(ourport->baudclk);
+ clk_disable_unprepare(ourport->baudclk);
ourport->baudclk = ERR_PTR(-EINVAL);
}
- clk_enable(clk);
+ clk_prepare_enable(clk);
ourport->baudclk = clk;
ourport->baudclk_rate = clk ? clk_get_rate(clk) : 0;
@@ -1287,9 +1287,9 @@ static int s3c24xx_serial_resume(struct device *dev)
struct s3c24xx_uart_port *ourport = to_ourport(port);
if (port) {
- clk_enable(ourport->clk);
+ clk_prepare_enable(ourport->clk);
s3c24xx_serial_resetport(port, s3c24xx_port_to_cfg(port));
- clk_disable(ourport->clk);
+ clk_disable_unprepare(ourport->clk);
uart_resume_port(&s3c24xx_uart_drv, port);
}
diff --git a/drivers/tty/tty_audit.c b/drivers/tty/tty_audit.c
index b0b39b823ccf..6953dc82850c 100644
--- a/drivers/tty/tty_audit.c
+++ b/drivers/tty/tty_audit.c
@@ -23,7 +23,7 @@ struct tty_audit_buf {
};
static struct tty_audit_buf *tty_audit_buf_alloc(int major, int minor,
- int icanon)
+ unsigned icanon)
{
struct tty_audit_buf *buf;
@@ -239,7 +239,8 @@ int tty_audit_push_task(struct task_struct *tsk, kuid_t loginuid, u32 sessionid)
* if TTY auditing is disabled or out of memory. Otherwise, return a new
* reference to the buffer.
*/
-static struct tty_audit_buf *tty_audit_buf_get(struct tty_struct *tty)
+static struct tty_audit_buf *tty_audit_buf_get(struct tty_struct *tty,
+ unsigned icanon)
{
struct tty_audit_buf *buf, *buf2;
@@ -257,7 +258,7 @@ static struct tty_audit_buf *tty_audit_buf_get(struct tty_struct *tty)
buf2 = tty_audit_buf_alloc(tty->driver->major,
tty->driver->minor_start + tty->index,
- tty->icanon);
+ icanon);
if (buf2 == NULL) {
audit_log_lost("out of memory in TTY auditing");
return NULL;
@@ -287,7 +288,7 @@ static struct tty_audit_buf *tty_audit_buf_get(struct tty_struct *tty)
* Audit @data of @size from @tty, if necessary.
*/
void tty_audit_add_data(struct tty_struct *tty, unsigned char *data,
- size_t size)
+ size_t size, unsigned icanon)
{
struct tty_audit_buf *buf;
int major, minor;
@@ -299,7 +300,7 @@ void tty_audit_add_data(struct tty_struct *tty, unsigned char *data,
&& tty->driver->subtype == PTY_TYPE_MASTER)
return;
- buf = tty_audit_buf_get(tty);
+ buf = tty_audit_buf_get(tty, icanon);
if (!buf)
return;
@@ -307,11 +308,11 @@ void tty_audit_add_data(struct tty_struct *tty, unsigned char *data,
major = tty->driver->major;
minor = tty->driver->minor_start + tty->index;
if (buf->major != major || buf->minor != minor
- || buf->icanon != tty->icanon) {
+ || buf->icanon != icanon) {
tty_audit_buf_push_current(buf);
buf->major = major;
buf->minor = minor;
- buf->icanon = tty->icanon;
+ buf->icanon = icanon;
}
do {
size_t run;
diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c
index 91e326ffe7db..6cf87d7afb7e 100644
--- a/drivers/tty/tty_buffer.c
+++ b/drivers/tty/tty_buffer.c
@@ -27,19 +27,21 @@
* Locking: none
*/
-void tty_buffer_free_all(struct tty_struct *tty)
+void tty_buffer_free_all(struct tty_port *port)
{
+ struct tty_bufhead *buf = &port->buf;
struct tty_buffer *thead;
- while ((thead = tty->buf.head) != NULL) {
- tty->buf.head = thead->next;
+
+ while ((thead = buf->head) != NULL) {
+ buf->head = thead->next;
kfree(thead);
}
- while ((thead = tty->buf.free) != NULL) {
- tty->buf.free = thead->next;
+ while ((thead = buf->free) != NULL) {
+ buf->free = thead->next;
kfree(thead);
}
- tty->buf.tail = NULL;
- tty->buf.memory_used = 0;
+ buf->tail = NULL;
+ buf->memory_used = 0;
}
/**
@@ -54,11 +56,11 @@ void tty_buffer_free_all(struct tty_struct *tty)
* Locking: Caller must hold tty->buf.lock
*/
-static struct tty_buffer *tty_buffer_alloc(struct tty_struct *tty, size_t size)
+static struct tty_buffer *tty_buffer_alloc(struct tty_port *port, size_t size)
{
struct tty_buffer *p;
- if (tty->buf.memory_used + size > 65536)
+ if (port->buf.memory_used + size > 65536)
return NULL;
p = kmalloc(sizeof(struct tty_buffer) + 2 * size, GFP_ATOMIC);
if (p == NULL)
@@ -70,7 +72,7 @@ static struct tty_buffer *tty_buffer_alloc(struct tty_struct *tty, size_t size)
p->read = 0;
p->char_buf_ptr = (char *)(p->data);
p->flag_buf_ptr = (unsigned char *)p->char_buf_ptr + size;
- tty->buf.memory_used += size;
+ port->buf.memory_used += size;
return p;
}
@@ -85,17 +87,19 @@ static struct tty_buffer *tty_buffer_alloc(struct tty_struct *tty, size_t size)
* Locking: Caller must hold tty->buf.lock
*/
-static void tty_buffer_free(struct tty_struct *tty, struct tty_buffer *b)
+static void tty_buffer_free(struct tty_port *port, struct tty_buffer *b)
{
+ struct tty_bufhead *buf = &port->buf;
+
/* Dumb strategy for now - should keep some stats */
- tty->buf.memory_used -= b->size;
- WARN_ON(tty->buf.memory_used < 0);
+ buf->memory_used -= b->size;
+ WARN_ON(buf->memory_used < 0);
if (b->size >= 512)
kfree(b);
else {
- b->next = tty->buf.free;
- tty->buf.free = b;
+ b->next = buf->free;
+ buf->free = b;
}
}
@@ -110,15 +114,16 @@ static void tty_buffer_free(struct tty_struct *tty, struct tty_buffer *b)
* Locking: Caller must hold tty->buf.lock
*/
-static void __tty_buffer_flush(struct tty_struct *tty)
+static void __tty_buffer_flush(struct tty_port *port)
{
+ struct tty_bufhead *buf = &port->buf;
struct tty_buffer *thead;
- while ((thead = tty->buf.head) != NULL) {
- tty->buf.head = thead->next;
- tty_buffer_free(tty, thead);
+ while ((thead = buf->head) != NULL) {
+ buf->head = thead->next;
+ tty_buffer_free(port, thead);
}
- tty->buf.tail = NULL;
+ buf->tail = NULL;
}
/**
@@ -134,21 +139,24 @@ static void __tty_buffer_flush(struct tty_struct *tty)
void tty_buffer_flush(struct tty_struct *tty)
{
+ struct tty_port *port = tty->port;
+ struct tty_bufhead *buf = &port->buf;
unsigned long flags;
- spin_lock_irqsave(&tty->buf.lock, flags);
+
+ spin_lock_irqsave(&buf->lock, flags);
/* If the data is being pushed to the tty layer then we can't
process it here. Instead set a flag and the flush_to_ldisc
path will process the flush request before it exits */
- if (test_bit(TTY_FLUSHING, &tty->flags)) {
- set_bit(TTY_FLUSHPENDING, &tty->flags);
- spin_unlock_irqrestore(&tty->buf.lock, flags);
+ if (test_bit(TTYP_FLUSHING, &port->iflags)) {
+ set_bit(TTYP_FLUSHPENDING, &port->iflags);
+ spin_unlock_irqrestore(&buf->lock, flags);
wait_event(tty->read_wait,
- test_bit(TTY_FLUSHPENDING, &tty->flags) == 0);
+ test_bit(TTYP_FLUSHPENDING, &port->iflags) == 0);
return;
} else
- __tty_buffer_flush(tty);
- spin_unlock_irqrestore(&tty->buf.lock, flags);
+ __tty_buffer_flush(port);
+ spin_unlock_irqrestore(&buf->lock, flags);
}
/**
@@ -163,9 +171,9 @@ void tty_buffer_flush(struct tty_struct *tty)
* Locking: Caller must hold tty->buf.lock
*/
-static struct tty_buffer *tty_buffer_find(struct tty_struct *tty, size_t size)
+static struct tty_buffer *tty_buffer_find(struct tty_port *port, size_t size)
{
- struct tty_buffer **tbh = &tty->buf.free;
+ struct tty_buffer **tbh = &port->buf.free;
while ((*tbh) != NULL) {
struct tty_buffer *t = *tbh;
if (t->size >= size) {
@@ -174,14 +182,14 @@ static struct tty_buffer *tty_buffer_find(struct tty_struct *tty, size_t size)
t->used = 0;
t->commit = 0;
t->read = 0;
- tty->buf.memory_used += t->size;
+ port->buf.memory_used += t->size;
return t;
}
tbh = &((*tbh)->next);
}
/* Round the buffer size out */
size = (size + 0xFF) & ~0xFF;
- return tty_buffer_alloc(tty, size);
+ return tty_buffer_alloc(port, size);
/* Should possibly check if this fails for the largest buffer we
have queued and recycle that ? */
}
@@ -192,29 +200,31 @@ static struct tty_buffer *tty_buffer_find(struct tty_struct *tty, size_t size)
*
* Make at least size bytes of linear space available for the tty
* buffer. If we fail return the size we managed to find.
- * Locking: Caller must hold tty->buf.lock
+ * Locking: Caller must hold port->buf.lock
*/
-static int __tty_buffer_request_room(struct tty_struct *tty, size_t size)
+static int __tty_buffer_request_room(struct tty_port *port, size_t size)
{
+ struct tty_bufhead *buf = &port->buf;
struct tty_buffer *b, *n;
int left;
/* OPTIMISATION: We could keep a per tty "zero" sized buffer to
remove this conditional if its worth it. This would be invisible
to the callers */
- if ((b = tty->buf.tail) != NULL)
+ b = buf->tail;
+ if (b != NULL)
left = b->size - b->used;
else
left = 0;
if (left < size) {
/* This is the slow path - looking for new buffers to use */
- if ((n = tty_buffer_find(tty, size)) != NULL) {
+ if ((n = tty_buffer_find(port, size)) != NULL) {
if (b != NULL) {
b->next = n;
b->commit = b->used;
} else
- tty->buf.head = n;
- tty->buf.tail = n;
+ buf->head = n;
+ buf->tail = n;
} else
size = left;
}
@@ -231,16 +241,17 @@ static int __tty_buffer_request_room(struct tty_struct *tty, size_t size)
* Make at least size bytes of linear space available for the tty
* buffer. If we fail return the size we managed to find.
*
- * Locking: Takes tty->buf.lock
+ * Locking: Takes port->buf.lock
*/
int tty_buffer_request_room(struct tty_struct *tty, size_t size)
{
+ struct tty_port *port = tty->port;
unsigned long flags;
int length;
- spin_lock_irqsave(&tty->buf.lock, flags);
- length = __tty_buffer_request_room(tty, size);
- spin_unlock_irqrestore(&tty->buf.lock, flags);
+ spin_lock_irqsave(&port->buf.lock, flags);
+ length = __tty_buffer_request_room(port, size);
+ spin_unlock_irqrestore(&port->buf.lock, flags);
return length;
}
EXPORT_SYMBOL_GPL(tty_buffer_request_room);
@@ -255,12 +266,13 @@ EXPORT_SYMBOL_GPL(tty_buffer_request_room);
* Queue a series of bytes to the tty buffering. All the characters
* passed are marked with the supplied flag. Returns the number added.
*
- * Locking: Called functions may take tty->buf.lock
+ * Locking: Called functions may take port->buf.lock
*/
int tty_insert_flip_string_fixed_flag(struct tty_struct *tty,
const unsigned char *chars, char flag, size_t size)
{
+ struct tty_bufhead *buf = &tty->port->buf;
int copied = 0;
do {
int goal = min_t(size_t, size - copied, TTY_BUFFER_PAGE);
@@ -268,18 +280,18 @@ int tty_insert_flip_string_fixed_flag(struct tty_struct *tty,
unsigned long flags;
struct tty_buffer *tb;
- spin_lock_irqsave(&tty->buf.lock, flags);
- space = __tty_buffer_request_room(tty, goal);
- tb = tty->buf.tail;
+ spin_lock_irqsave(&buf->lock, flags);
+ space = __tty_buffer_request_room(tty->port, goal);
+ tb = buf->tail;
/* If there is no space then tb may be NULL */
if (unlikely(space == 0)) {
- spin_unlock_irqrestore(&tty->buf.lock, flags);
+ spin_unlock_irqrestore(&buf->lock, flags);
break;
}
memcpy(tb->char_buf_ptr + tb->used, chars, space);
memset(tb->flag_buf_ptr + tb->used, flag, space);
tb->used += space;
- spin_unlock_irqrestore(&tty->buf.lock, flags);
+ spin_unlock_irqrestore(&buf->lock, flags);
copied += space;
chars += space;
/* There is a small chance that we need to split the data over
@@ -300,12 +312,13 @@ EXPORT_SYMBOL(tty_insert_flip_string_fixed_flag);
* the flags array indicates the status of the character. Returns the
* number added.
*
- * Locking: Called functions may take tty->buf.lock
+ * Locking: Called functions may take port->buf.lock
*/
int tty_insert_flip_string_flags(struct tty_struct *tty,
const unsigned char *chars, const char *flags, size_t size)
{
+ struct tty_bufhead *buf = &tty->port->buf;
int copied = 0;
do {
int goal = min_t(size_t, size - copied, TTY_BUFFER_PAGE);
@@ -313,18 +326,18 @@ int tty_insert_flip_string_flags(struct tty_struct *tty,
unsigned long __flags;
struct tty_buffer *tb;
- spin_lock_irqsave(&tty->buf.lock, __flags);
- space = __tty_buffer_request_room(tty, goal);
- tb = tty->buf.tail;
+ spin_lock_irqsave(&buf->lock, __flags);
+ space = __tty_buffer_request_room(tty->port, goal);
+ tb = buf->tail;
/* If there is no space then tb may be NULL */
if (unlikely(space == 0)) {
- spin_unlock_irqrestore(&tty->buf.lock, __flags);
+ spin_unlock_irqrestore(&buf->lock, __flags);
break;
}
memcpy(tb->char_buf_ptr + tb->used, chars, space);
memcpy(tb->flag_buf_ptr + tb->used, flags, space);
tb->used += space;
- spin_unlock_irqrestore(&tty->buf.lock, __flags);
+ spin_unlock_irqrestore(&buf->lock, __flags);
copied += space;
chars += space;
flags += space;
@@ -342,18 +355,23 @@ EXPORT_SYMBOL(tty_insert_flip_string_flags);
* Takes any pending buffers and transfers their ownership to the
* ldisc side of the queue. It then schedules those characters for
* processing by the line discipline.
+ * Note that this function can only be used when the low_latency flag
+ * is unset. Otherwise the workqueue won't be flushed.
*
- * Locking: Takes tty->buf.lock
+ * Locking: Takes port->buf.lock
*/
void tty_schedule_flip(struct tty_struct *tty)
{
+ struct tty_bufhead *buf = &tty->port->buf;
unsigned long flags;
- spin_lock_irqsave(&tty->buf.lock, flags);
- if (tty->buf.tail != NULL)
- tty->buf.tail->commit = tty->buf.tail->used;
- spin_unlock_irqrestore(&tty->buf.lock, flags);
- schedule_work(&tty->buf.work);
+ WARN_ON(tty->low_latency);
+
+ spin_lock_irqsave(&buf->lock, flags);
+ if (buf->tail != NULL)
+ buf->tail->commit = buf->tail->used;
+ spin_unlock_irqrestore(&buf->lock, flags);
+ schedule_work(&buf->work);
}
EXPORT_SYMBOL(tty_schedule_flip);
@@ -369,26 +387,27 @@ EXPORT_SYMBOL(tty_schedule_flip);
* that need their own block copy routines into the buffer. There is no
* guarantee the buffer is a DMA target!
*
- * Locking: May call functions taking tty->buf.lock
+ * Locking: May call functions taking port->buf.lock
*/
int tty_prepare_flip_string(struct tty_struct *tty, unsigned char **chars,
- size_t size)
+ size_t size)
{
+ struct tty_bufhead *buf = &tty->port->buf;
int space;
unsigned long flags;
struct tty_buffer *tb;
- spin_lock_irqsave(&tty->buf.lock, flags);
- space = __tty_buffer_request_room(tty, size);
+ spin_lock_irqsave(&buf->lock, flags);
+ space = __tty_buffer_request_room(tty->port, size);
- tb = tty->buf.tail;
+ tb = buf->tail;
if (likely(space)) {
*chars = tb->char_buf_ptr + tb->used;
memset(tb->flag_buf_ptr + tb->used, TTY_NORMAL, space);
tb->used += space;
}
- spin_unlock_irqrestore(&tty->buf.lock, flags);
+ spin_unlock_irqrestore(&buf->lock, flags);
return space;
}
EXPORT_SYMBOL_GPL(tty_prepare_flip_string);
@@ -406,26 +425,27 @@ EXPORT_SYMBOL_GPL(tty_prepare_flip_string);
* that need their own block copy routines into the buffer. There is no
* guarantee the buffer is a DMA target!
*
- * Locking: May call functions taking tty->buf.lock
+ * Locking: May call functions taking port->buf.lock
*/
int tty_prepare_flip_string_flags(struct tty_struct *tty,
unsigned char **chars, char **flags, size_t size)
{
+ struct tty_bufhead *buf = &tty->port->buf;
int space;
unsigned long __flags;
struct tty_buffer *tb;
- spin_lock_irqsave(&tty->buf.lock, __flags);
- space = __tty_buffer_request_room(tty, size);
+ spin_lock_irqsave(&buf->lock, __flags);
+ space = __tty_buffer_request_room(tty->port, size);
- tb = tty->buf.tail;
+ tb = buf->tail;
if (likely(space)) {
*chars = tb->char_buf_ptr + tb->used;
*flags = tb->flag_buf_ptr + tb->used;
tb->used += space;
}
- spin_unlock_irqrestore(&tty->buf.lock, __flags);
+ spin_unlock_irqrestore(&buf->lock, __flags);
return space;
}
EXPORT_SYMBOL_GPL(tty_prepare_flip_string_flags);
@@ -446,20 +466,25 @@ EXPORT_SYMBOL_GPL(tty_prepare_flip_string_flags);
static void flush_to_ldisc(struct work_struct *work)
{
- struct tty_struct *tty =
- container_of(work, struct tty_struct, buf.work);
+ struct tty_port *port = container_of(work, struct tty_port, buf.work);
+ struct tty_bufhead *buf = &port->buf;
+ struct tty_struct *tty;
unsigned long flags;
struct tty_ldisc *disc;
+ tty = port->itty;
+ if (WARN_RATELIMIT(tty == NULL, "tty is NULL"))
+ return;
+
disc = tty_ldisc_ref(tty);
if (disc == NULL) /* !TTY_LDISC */
return;
- spin_lock_irqsave(&tty->buf.lock, flags);
+ spin_lock_irqsave(&buf->lock, flags);
- if (!test_and_set_bit(TTY_FLUSHING, &tty->flags)) {
+ if (!test_and_set_bit(TTYP_FLUSHING, &port->iflags)) {
struct tty_buffer *head;
- while ((head = tty->buf.head) != NULL) {
+ while ((head = buf->head) != NULL) {
int count;
char *char_buf;
unsigned char *flag_buf;
@@ -468,14 +493,14 @@ static void flush_to_ldisc(struct work_struct *work)
if (!count) {
if (head->next == NULL)
break;
- tty->buf.head = head->next;
- tty_buffer_free(tty, head);
+ buf->head = head->next;
+ tty_buffer_free(port, head);
continue;
}
/* Ldisc or user is trying to flush the buffers
we are feeding to the ldisc, stop feeding the
line discipline as we want to empty the queue */
- if (test_bit(TTY_FLUSHPENDING, &tty->flags))
+ if (test_bit(TTYP_FLUSHPENDING, &port->iflags))
break;
if (!tty->receive_room)
break;
@@ -484,22 +509,22 @@ static void flush_to_ldisc(struct work_struct *work)
char_buf = head->char_buf_ptr + head->read;
flag_buf = head->flag_buf_ptr + head->read;
head->read += count;
- spin_unlock_irqrestore(&tty->buf.lock, flags);
+ spin_unlock_irqrestore(&buf->lock, flags);
disc->ops->receive_buf(tty, char_buf,
flag_buf, count);
- spin_lock_irqsave(&tty->buf.lock, flags);
+ spin_lock_irqsave(&buf->lock, flags);
}
- clear_bit(TTY_FLUSHING, &tty->flags);
+ clear_bit(TTYP_FLUSHING, &port->iflags);
}
/* We may have a deferred request to flush the input buffer,
if so pull the chain under the lock and empty the queue */
- if (test_bit(TTY_FLUSHPENDING, &tty->flags)) {
- __tty_buffer_flush(tty);
- clear_bit(TTY_FLUSHPENDING, &tty->flags);
+ if (test_bit(TTYP_FLUSHPENDING, &port->iflags)) {
+ __tty_buffer_flush(port);
+ clear_bit(TTYP_FLUSHPENDING, &port->iflags);
wake_up(&tty->read_wait);
}
- spin_unlock_irqrestore(&tty->buf.lock, flags);
+ spin_unlock_irqrestore(&buf->lock, flags);
tty_ldisc_deref(disc);
}
@@ -514,7 +539,8 @@ static void flush_to_ldisc(struct work_struct *work)
*/
void tty_flush_to_ldisc(struct tty_struct *tty)
{
- flush_work(&tty->buf.work);
+ if (!tty->low_latency)
+ flush_work(&tty->port->buf.work);
}
/**
@@ -532,16 +558,18 @@ void tty_flush_to_ldisc(struct tty_struct *tty)
void tty_flip_buffer_push(struct tty_struct *tty)
{
+ struct tty_bufhead *buf = &tty->port->buf;
unsigned long flags;
- spin_lock_irqsave(&tty->buf.lock, flags);
- if (tty->buf.tail != NULL)
- tty->buf.tail->commit = tty->buf.tail->used;
- spin_unlock_irqrestore(&tty->buf.lock, flags);
+
+ spin_lock_irqsave(&buf->lock, flags);
+ if (buf->tail != NULL)
+ buf->tail->commit = buf->tail->used;
+ spin_unlock_irqrestore(&buf->lock, flags);
if (tty->low_latency)
- flush_to_ldisc(&tty->buf.work);
+ flush_to_ldisc(&buf->work);
else
- schedule_work(&tty->buf.work);
+ schedule_work(&buf->work);
}
EXPORT_SYMBOL(tty_flip_buffer_push);
@@ -555,13 +583,15 @@ EXPORT_SYMBOL(tty_flip_buffer_push);
* Locking: none
*/
-void tty_buffer_init(struct tty_struct *tty)
+void tty_buffer_init(struct tty_port *port)
{
- spin_lock_init(&tty->buf.lock);
- tty->buf.head = NULL;
- tty->buf.tail = NULL;
- tty->buf.free = NULL;
- tty->buf.memory_used = 0;
- INIT_WORK(&tty->buf.work, flush_to_ldisc);
+ struct tty_bufhead *buf = &port->buf;
+
+ spin_lock_init(&buf->lock);
+ buf->head = NULL;
+ buf->tail = NULL;
+ buf->free = NULL;
+ buf->memory_used = 0;
+ INIT_WORK(&buf->work, flush_to_ldisc);
}
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index 2ea176b2280e..a3eba7f359ed 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -186,7 +186,6 @@ void free_tty_struct(struct tty_struct *tty)
if (tty->dev)
put_device(tty->dev);
kfree(tty->write_buf);
- tty_buffer_free_all(tty);
tty->magic = 0xDEADDEAD;
kfree(tty);
}
@@ -1417,6 +1416,8 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx)
"%s: %s driver does not set tty->port. This will crash the kernel later. Fix the driver!\n",
__func__, tty->driver->name);
+ tty->port->itty = tty;
+
/*
* Structures all installed ... call the ldisc open routines.
* If we fail here just call release_tty to clean up. No need
@@ -1552,6 +1553,7 @@ static void release_tty(struct tty_struct *tty, int idx)
tty->ops->shutdown(tty);
tty_free_termios(tty);
tty_driver_remove_tty(tty->driver, tty);
+ tty->port->itty = NULL;
if (tty->link)
tty_kref_put(tty->link);
@@ -1625,7 +1627,6 @@ int tty_release(struct inode *inode, struct file *filp)
struct tty_struct *tty = file_tty(filp);
struct tty_struct *o_tty;
int pty_master, tty_closing, o_tty_closing, do_sleep;
- int devpts;
int idx;
char buf[64];
@@ -1640,7 +1641,6 @@ int tty_release(struct inode *inode, struct file *filp)
idx = tty->index;
pty_master = (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
tty->driver->subtype == PTY_TYPE_MASTER);
- devpts = (tty->driver->flags & TTY_DRIVER_DEVPTS_MEM) != 0;
/* Review: parallel close */
o_tty = tty->link;
@@ -1799,9 +1799,6 @@ int tty_release(struct inode *inode, struct file *filp)
release_tty(tty, idx);
mutex_unlock(&tty_mutex);
- /* Make this pty number available for reallocation */
- if (devpts)
- devpts_kill_index(inode, idx);
return 0;
}
@@ -2937,19 +2934,13 @@ void initialize_tty_struct(struct tty_struct *tty,
tty_ldisc_init(tty);
tty->session = NULL;
tty->pgrp = NULL;
- tty->overrun_time = jiffies;
- tty_buffer_init(tty);
mutex_init(&tty->legacy_mutex);
mutex_init(&tty->termios_mutex);
mutex_init(&tty->ldisc_mutex);
init_waitqueue_head(&tty->write_wait);
init_waitqueue_head(&tty->read_wait);
INIT_WORK(&tty->hangup_work, do_tty_hangup);
- mutex_init(&tty->atomic_read_lock);
mutex_init(&tty->atomic_write_lock);
- mutex_init(&tty->output_lock);
- mutex_init(&tty->echo_lock);
- spin_lock_init(&tty->read_lock);
spin_lock_init(&tty->ctrl_lock);
INIT_LIST_HEAD(&tty->tty_files);
INIT_WORK(&tty->SAK_work, do_SAK_work);
diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c
index 0f2a2c5e704c..f4e6754525dc 100644
--- a/drivers/tty/tty_ldisc.c
+++ b/drivers/tty/tty_ldisc.c
@@ -512,7 +512,7 @@ static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old)
static int tty_ldisc_halt(struct tty_struct *tty)
{
clear_bit(TTY_LDISC, &tty->flags);
- return cancel_work_sync(&tty->buf.work);
+ return cancel_work_sync(&tty->port->buf.work);
}
/**
@@ -525,7 +525,7 @@ static void tty_ldisc_flush_works(struct tty_struct *tty)
{
flush_work(&tty->hangup_work);
flush_work(&tty->SAK_work);
- flush_work(&tty->buf.work);
+ flush_work(&tty->port->buf.work);
}
/**
@@ -704,9 +704,9 @@ enable:
/* Restart the work queue in case no characters kick it off. Safe if
already running */
if (work)
- schedule_work(&tty->buf.work);
+ schedule_work(&tty->port->buf.work);
if (o_work)
- schedule_work(&o_tty->buf.work);
+ schedule_work(&o_tty->port->buf.work);
mutex_unlock(&tty->ldisc_mutex);
tty_unlock(tty);
return retval;
@@ -817,7 +817,7 @@ void tty_ldisc_hangup(struct tty_struct *tty)
*/
clear_bit(TTY_LDISC, &tty->flags);
tty_unlock(tty);
- cancel_work_sync(&tty->buf.work);
+ cancel_work_sync(&tty->port->buf.work);
mutex_unlock(&tty->ldisc_mutex);
retry:
tty_lock(tty);
@@ -897,6 +897,11 @@ int tty_ldisc_setup(struct tty_struct *tty, struct tty_struct *o_tty)
static void tty_ldisc_kill(struct tty_struct *tty)
{
+ /* There cannot be users from userspace now. But there still might be
+ * drivers holding a reference via tty_ldisc_ref. Do not steal them the
+ * ldisc until they are done. */
+ tty_ldisc_wait_idle(tty, MAX_SCHEDULE_TIMEOUT);
+
mutex_lock(&tty->ldisc_mutex);
/*
* Now kill off the ldisc
diff --git a/drivers/tty/tty_port.c b/drivers/tty/tty_port.c
index d7bdd8d0c23f..416b42f7c346 100644
--- a/drivers/tty/tty_port.c
+++ b/drivers/tty/tty_port.c
@@ -21,6 +21,7 @@
void tty_port_init(struct tty_port *port)
{
memset(port, 0, sizeof(*port));
+ tty_buffer_init(port);
init_waitqueue_head(&port->open_wait);
init_waitqueue_head(&port->close_wait);
init_waitqueue_head(&port->delta_msr_wait);
@@ -126,6 +127,7 @@ static void tty_port_destructor(struct kref *kref)
struct tty_port *port = container_of(kref, struct tty_port, kref);
if (port->xmit_buf)
free_page((unsigned long)port->xmit_buf);
+ tty_buffer_free_all(port);
if (port->ops->destruct)
port->ops->destruct(port);
else
diff --git a/drivers/tty/vt/selection.c b/drivers/tty/vt/selection.c
index 8e9b4be97a2d..60b7b6926059 100644
--- a/drivers/tty/vt/selection.c
+++ b/drivers/tty/vt/selection.c
@@ -341,15 +341,11 @@ int paste_selection(struct tty_struct *tty)
struct tty_ldisc *ld;
DECLARE_WAITQUEUE(wait, current);
-
console_lock();
poke_blanked_console();
console_unlock();
- /* FIXME: wtf is this supposed to achieve ? */
- ld = tty_ldisc_ref(tty);
- if (!ld)
- ld = tty_ldisc_ref_wait(tty);
+ ld = tty_ldisc_ref_wait(tty);
/* FIXME: this is completely unsafe */
add_wait_queue(&vc->paste_wait, &wait);
@@ -361,8 +357,7 @@ int paste_selection(struct tty_struct *tty)
}
count = sel_buffer_lth - pasted;
count = min(count, tty->receive_room);
- tty->ldisc->ops->receive_buf(tty, sel_buffer + pasted,
- NULL, count);
+ ld->ops->receive_buf(tty, sel_buffer + pasted, NULL, count);
pasted += count;
}
remove_wait_queue(&vc->paste_wait, &wait);
diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c
index 2a4749c3eb3f..23afa06b65a4 100644
--- a/drivers/usb/gadget/omap_udc.c
+++ b/drivers/usb/gadget/omap_udc.c
@@ -44,7 +44,7 @@
#include <asm/unaligned.h>
#include <asm/mach-types.h>
-#include <plat/dma.h>
+#include <plat-omap/dma-omap.h>
#include <mach/usb.h>
@@ -61,6 +61,8 @@
#define DRIVER_DESC "OMAP UDC driver"
#define DRIVER_VERSION "4 October 2004"
+#define OMAP_DMA_USB_W2FC_TX0 29
+
/*
* The OMAP UDC needs _very_ early endpoint setup: before enabling the
* D+ pullup to allow enumeration. That's too early for the gadget
diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c
index d7fe287d0678..0d5ac36fdf47 100644
--- a/drivers/usb/host/ehci-omap.c
+++ b/drivers/usb/host/ehci-omap.c
@@ -39,12 +39,13 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/usb/ulpi.h>
-#include <plat/usb.h>
#include <linux/regulator/consumer.h>
#include <linux/pm_runtime.h>
#include <linux/gpio.h>
#include <linux/clk.h>
+#include <linux/platform_data/usb-omap.h>
+
/* EHCI Register Set */
#define EHCI_INSNREG04 (0xA0)
#define EHCI_INSNREG04_DISABLE_UNSUSPEND (1 << 5)
diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c
index 4531d03503c3..439e6e4f2d6b 100644
--- a/drivers/usb/host/ohci-omap.c
+++ b/drivers/usb/host/ohci-omap.c
@@ -25,7 +25,6 @@
#include <asm/mach-types.h>
#include <mach/mux.h>
-#include <plat/fpga.h>
#include <mach/hardware.h>
#include <mach/irqs.h>
@@ -93,14 +92,14 @@ static int omap_ohci_transceiver_power(int on)
{
if (on) {
if (machine_is_omap_innovator() && cpu_is_omap1510())
- fpga_write(fpga_read(INNOVATOR_FPGA_CAM_USB_CONTROL)
+ __raw_writeb(__raw_readb(INNOVATOR_FPGA_CAM_USB_CONTROL)
| ((1 << 5/*usb1*/) | (1 << 3/*usb2*/)),
INNOVATOR_FPGA_CAM_USB_CONTROL);
else if (machine_is_omap_osk())
tps65010_set_gpio_out_value(GPIO1, LOW);
} else {
if (machine_is_omap_innovator() && cpu_is_omap1510())
- fpga_write(fpga_read(INNOVATOR_FPGA_CAM_USB_CONTROL)
+ __raw_writeb(__raw_readb(INNOVATOR_FPGA_CAM_USB_CONTROL)
& ~((1 << 5/*usb1*/) | (1 << 3/*usb2*/)),
INNOVATOR_FPGA_CAM_USB_CONTROL);
else if (machine_is_omap_osk())
diff --git a/drivers/usb/host/ohci-omap3.c b/drivers/usb/host/ohci-omap3.c
index 1b8133b6e451..bd7803dce9be 100644
--- a/drivers/usb/host/ohci-omap3.c
+++ b/drivers/usb/host/ohci-omap3.c
@@ -30,7 +30,6 @@
*/
#include <linux/platform_device.h>
-#include <plat/usb.h>
#include <linux/pm_runtime.h>
/*-------------------------------------------------------------------------*/
diff --git a/drivers/usb/musb/am35x.c b/drivers/usb/musb/am35x.c
index c964d6af178b..a87cdd2387cf 100644
--- a/drivers/usb/musb/am35x.c
+++ b/drivers/usb/musb/am35x.c
@@ -34,8 +34,7 @@
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/usb/nop-usb-xceiv.h>
-
-#include <plat/usb.h>
+#include <linux/platform_data/usb-omap.h>
#include "musb_core.h"
diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c
index ff5f112053d2..aa34f22181c1 100644
--- a/drivers/usb/musb/musb_dsps.c
+++ b/drivers/usb/musb/musb_dsps.c
@@ -38,13 +38,12 @@
#include <linux/pm_runtime.h>
#include <linux/module.h>
#include <linux/usb/nop-usb-xceiv.h>
+#include <linux/platform_data/usb-omap.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_address.h>
-#include <plat/usb.h>
-
#include "musb_core.h"
#ifdef CONFIG_OF
diff --git a/drivers/usb/musb/omap2430.h b/drivers/usb/musb/omap2430.h
index b85f3973e78c..8ef656659fcb 100644
--- a/drivers/usb/musb/omap2430.h
+++ b/drivers/usb/musb/omap2430.h
@@ -10,7 +10,7 @@
#ifndef __MUSB_OMAP243X_H__
#define __MUSB_OMAP243X_H__
-#include <plat/usb.h>
+#include <linux/platform_data/usb-omap.h>
/*
* OMAP2430-specific definitions
diff --git a/drivers/usb/musb/tusb6010_omap.c b/drivers/usb/musb/tusb6010_omap.c
index 7a62b95dac24..bfca114f7c56 100644
--- a/drivers/usb/musb/tusb6010_omap.c
+++ b/drivers/usb/musb/tusb6010_omap.c
@@ -16,7 +16,7 @@
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/slab.h>
-#include <plat/dma.h>
+#include <plat-omap/dma-omap.h>
#include "musb_core.h"
#include "tusb6010.h"
@@ -25,6 +25,13 @@
#define MAX_DMAREQ 5 /* REVISIT: Really 6, but req5 not OK */
+#define OMAP24XX_DMA_EXT_DMAREQ0 2
+#define OMAP24XX_DMA_EXT_DMAREQ1 3
+#define OMAP242X_DMA_EXT_DMAREQ2 14
+#define OMAP242X_DMA_EXT_DMAREQ3 15
+#define OMAP242X_DMA_EXT_DMAREQ4 16
+#define OMAP242X_DMA_EXT_DMAREQ5 64
+
struct tusb_omap_dma_ch {
struct musb *musb;
void __iomem *tbase;
diff --git a/drivers/video/omap/lcd_inn1510.c b/drivers/video/omap/lcd_inn1510.c
index b38b1dd15ce3..2ee423279e35 100644
--- a/drivers/video/omap/lcd_inn1510.c
+++ b/drivers/video/omap/lcd_inn1510.c
@@ -23,7 +23,8 @@
#include <linux/platform_device.h>
#include <linux/io.h>
-#include <plat/fpga.h>
+#include <mach/hardware.h>
+
#include "omapfb.h"
static int innovator1510_panel_init(struct lcd_panel *panel,
@@ -38,13 +39,13 @@ static void innovator1510_panel_cleanup(struct lcd_panel *panel)
static int innovator1510_panel_enable(struct lcd_panel *panel)
{
- fpga_write(0x7, OMAP1510_FPGA_LCD_PANEL_CONTROL);
+ __raw_writeb(0x7, OMAP1510_FPGA_LCD_PANEL_CONTROL);
return 0;
}
static void innovator1510_panel_disable(struct lcd_panel *panel)
{
- fpga_write(0x0, OMAP1510_FPGA_LCD_PANEL_CONTROL);
+ __raw_writeb(0x0, OMAP1510_FPGA_LCD_PANEL_CONTROL);
}
static unsigned long innovator1510_panel_get_caps(struct lcd_panel *panel)
diff --git a/drivers/video/omap/lcdc.c b/drivers/video/omap/lcdc.c
index 7767338f8b14..c39d6e46f8c5 100644
--- a/drivers/video/omap/lcdc.c
+++ b/drivers/video/omap/lcdc.c
@@ -31,7 +31,7 @@
#include <linux/gfp.h>
#include <mach/lcdc.h>
-#include <plat/dma.h>
+#include <plat-omap/dma-omap.h>
#include <asm/mach-types.h>
diff --git a/drivers/video/omap/omapfb_main.c b/drivers/video/omap/omapfb_main.c
index 4351c438b76f..1b5ee8ec192a 100644
--- a/drivers/video/omap/omapfb_main.c
+++ b/drivers/video/omap/omapfb_main.c
@@ -30,7 +30,7 @@
#include <linux/uaccess.h>
#include <linux/module.h>
-#include <plat/dma.h>
+#include <plat-omap/dma-omap.h>
#include "omapfb.h"
#include "lcdc.h"
diff --git a/drivers/video/omap/sossi.c b/drivers/video/omap/sossi.c
index f79c137753d7..c510a4457398 100644
--- a/drivers/video/omap/sossi.c
+++ b/drivers/video/omap/sossi.c
@@ -25,7 +25,7 @@
#include <linux/io.h>
#include <linux/interrupt.h>
-#include <plat/dma.h>
+#include <plat-omap/dma-omap.h>
#include "omapfb.h"
#include "lcdc.h"
diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c
index b2af72dc20bd..d94ef9e31a35 100644
--- a/drivers/video/omap2/dss/core.c
+++ b/drivers/video/omap2/dss/core.c
@@ -237,7 +237,7 @@ static int __init omap_dss_probe(struct platform_device *pdev)
core.pdev = pdev;
- dss_features_init();
+ dss_features_init(pdata->version);
dss_apply_init();
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index b43477a5fae8..a5ab354f267a 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -37,8 +37,6 @@
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
-#include <plat/cpu.h>
-
#include <video/omapdss.h>
#include "dss.h"
@@ -4042,29 +4040,44 @@ static const struct dispc_features omap44xx_dispc_feats __initconst = {
.gfx_fifo_workaround = true,
};
-static int __init dispc_init_features(struct device *dev)
+static int __init dispc_init_features(struct platform_device *pdev)
{
+ struct omap_dss_board_info *pdata = pdev->dev.platform_data;
const struct dispc_features *src;
struct dispc_features *dst;
- dst = devm_kzalloc(dev, sizeof(*dst), GFP_KERNEL);
+ dst = devm_kzalloc(&pdev->dev, sizeof(*dst), GFP_KERNEL);
if (!dst) {
- dev_err(dev, "Failed to allocate DISPC Features\n");
+ dev_err(&pdev->dev, "Failed to allocate DISPC Features\n");
return -ENOMEM;
}
- if (cpu_is_omap24xx()) {
+ switch (pdata->version) {
+ case OMAPDSS_VER_OMAP24xx:
src = &omap24xx_dispc_feats;
- } else if (cpu_is_omap34xx()) {
- if (omap_rev() < OMAP3430_REV_ES3_0)
- src = &omap34xx_rev1_0_dispc_feats;
- else
- src = &omap34xx_rev3_0_dispc_feats;
- } else if (cpu_is_omap44xx()) {
+ break;
+
+ case OMAPDSS_VER_OMAP34xx_ES1:
+ src = &omap34xx_rev1_0_dispc_feats;
+ break;
+
+ case OMAPDSS_VER_OMAP34xx_ES3:
+ case OMAPDSS_VER_OMAP3630:
+ case OMAPDSS_VER_AM35xx:
+ src = &omap34xx_rev3_0_dispc_feats;
+ break;
+
+ case OMAPDSS_VER_OMAP4430_ES1:
+ case OMAPDSS_VER_OMAP4430_ES2:
+ case OMAPDSS_VER_OMAP4:
src = &omap44xx_dispc_feats;
- } else if (soc_is_omap54xx()) {
+ break;
+
+ case OMAPDSS_VER_OMAP5:
src = &omap44xx_dispc_feats;
- } else {
+ break;
+
+ default:
return -ENODEV;
}
@@ -4084,7 +4097,7 @@ static int __init omap_dispchw_probe(struct platform_device *pdev)
dispc.pdev = pdev;
- r = dispc_init_features(&dispc.pdev->dev);
+ r = dispc_init_features(dispc.pdev);
if (r)
return r;
diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
index 2ab1c3e96553..363852a0f764 100644
--- a/drivers/video/omap2/dss/dss.c
+++ b/drivers/video/omap2/dss/dss.c
@@ -35,8 +35,6 @@
#include <video/omapdss.h>
-#include <plat/cpu.h>
-
#include "dss.h"
#include "dss_features.h"
@@ -792,29 +790,46 @@ static const struct dss_features omap54xx_dss_feats __initconst = {
.dpi_select_source = &dss_dpi_select_source_omap5,
};
-static int __init dss_init_features(struct device *dev)
+static int __init dss_init_features(struct platform_device *pdev)
{
+ struct omap_dss_board_info *pdata = pdev->dev.platform_data;
const struct dss_features *src;
struct dss_features *dst;
- dst = devm_kzalloc(dev, sizeof(*dst), GFP_KERNEL);
+ dst = devm_kzalloc(&pdev->dev, sizeof(*dst), GFP_KERNEL);
if (!dst) {
- dev_err(dev, "Failed to allocate local DSS Features\n");
+ dev_err(&pdev->dev, "Failed to allocate local DSS Features\n");
return -ENOMEM;
}
- if (cpu_is_omap24xx())
+ switch (pdata->version) {
+ case OMAPDSS_VER_OMAP24xx:
src = &omap24xx_dss_feats;
- else if (cpu_is_omap34xx())
+ break;
+
+ case OMAPDSS_VER_OMAP34xx_ES1:
+ case OMAPDSS_VER_OMAP34xx_ES3:
+ case OMAPDSS_VER_AM35xx:
src = &omap34xx_dss_feats;
- else if (cpu_is_omap3630())
+ break;
+
+ case OMAPDSS_VER_OMAP3630:
src = &omap3630_dss_feats;
- else if (cpu_is_omap44xx())
+ break;
+
+ case OMAPDSS_VER_OMAP4430_ES1:
+ case OMAPDSS_VER_OMAP4430_ES2:
+ case OMAPDSS_VER_OMAP4:
src = &omap44xx_dss_feats;
- else if (soc_is_omap54xx())
+ break;
+
+ case OMAPDSS_VER_OMAP5:
src = &omap54xx_dss_feats;
- else
+ break;
+
+ default:
return -ENODEV;
+ }
memcpy(dst, src, sizeof(*dst));
dss.feat = dst;
@@ -831,7 +846,7 @@ static int __init omap_dsshw_probe(struct platform_device *pdev)
dss.pdev = pdev;
- r = dss_init_features(&dss.pdev->dev);
+ r = dss_init_features(dss.pdev);
if (r)
return r;
diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c
index acbc1e1efba3..3e8287c8709d 100644
--- a/drivers/video/omap2/dss/dss_features.c
+++ b/drivers/video/omap2/dss/dss_features.c
@@ -23,7 +23,6 @@
#include <linux/slab.h>
#include <video/omapdss.h>
-#include <plat/cpu.h>
#include "dss.h"
#include "dss_features.h"
@@ -825,10 +824,20 @@ static const struct ti_hdmi_ip_ops omap4_hdmi_functions = {
};
-void dss_init_hdmi_ip_ops(struct hdmi_ip_data *ip_data)
+void dss_init_hdmi_ip_ops(struct hdmi_ip_data *ip_data,
+ enum omapdss_version version)
{
- if (cpu_is_omap44xx())
+ switch (version) {
+ case OMAPDSS_VER_OMAP4430_ES1:
+ case OMAPDSS_VER_OMAP4430_ES2:
+ case OMAPDSS_VER_OMAP4:
ip_data->ops = &omap4_hdmi_functions;
+ break;
+ default:
+ ip_data->ops = NULL;
+ }
+
+ WARN_ON(ip_data->ops == NULL);
}
#endif
@@ -929,29 +938,44 @@ bool dss_feat_rotation_type_supported(enum omap_dss_rotation_type rot_type)
return omap_current_dss_features->supported_rotation_types & rot_type;
}
-void dss_features_init(void)
+void dss_features_init(enum omapdss_version version)
{
- if (cpu_is_omap24xx())
+ switch (version) {
+ case OMAPDSS_VER_OMAP24xx:
omap_current_dss_features = &omap2_dss_features;
- else if (cpu_is_omap3630())
+ break;
+
+ case OMAPDSS_VER_OMAP34xx_ES1:
+ case OMAPDSS_VER_OMAP34xx_ES3:
+ omap_current_dss_features = &omap3430_dss_features;
+ break;
+
+ case OMAPDSS_VER_OMAP3630:
omap_current_dss_features = &omap3630_dss_features;
- else if (cpu_is_omap34xx()) {
- if (soc_is_am35xx()) {
- omap_current_dss_features = &am35xx_dss_features;
- } else {
- omap_current_dss_features = &omap3430_dss_features;
- }
- }
- else if (omap_rev() == OMAP4430_REV_ES1_0)
+ break;
+
+ case OMAPDSS_VER_OMAP4430_ES1:
omap_current_dss_features = &omap4430_es1_0_dss_features;
- else if (omap_rev() == OMAP4430_REV_ES2_0 ||
- omap_rev() == OMAP4430_REV_ES2_1 ||
- omap_rev() == OMAP4430_REV_ES2_2)
+ break;
+
+ case OMAPDSS_VER_OMAP4430_ES2:
omap_current_dss_features = &omap4430_es2_0_1_2_dss_features;
- else if (cpu_is_omap44xx())
+ break;
+
+ case OMAPDSS_VER_OMAP4:
omap_current_dss_features = &omap4_dss_features;
- else if (soc_is_omap54xx())
+ break;
+
+ case OMAPDSS_VER_OMAP5:
omap_current_dss_features = &omap5_dss_features;
- else
+ break;
+
+ case OMAPDSS_VER_AM35xx:
+ omap_current_dss_features = &am35xx_dss_features;
+ break;
+
+ default:
DSSWARN("Unsupported OMAP version");
+ break;
+ }
}
diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h
index 9218113b5e88..fc492ef72a51 100644
--- a/drivers/video/omap2/dss/dss_features.h
+++ b/drivers/video/omap2/dss/dss_features.h
@@ -123,8 +123,9 @@ bool dss_feat_rotation_type_supported(enum omap_dss_rotation_type rot_type);
bool dss_has_feature(enum dss_feat_id id);
void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end);
-void dss_features_init(void);
+void dss_features_init(enum omapdss_version version);
#if defined(CONFIG_OMAP4_DSS_HDMI)
-void dss_init_hdmi_ip_ops(struct hdmi_ip_data *ip_data);
+void dss_init_hdmi_ip_ops(struct hdmi_ip_data *ip_data,
+ enum omapdss_version version);
#endif
#endif
diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index a48a7dd75b33..adcc906d12f8 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -323,6 +323,7 @@ static void hdmi_runtime_put(void)
static int __init hdmi_init_display(struct omap_dss_device *dssdev)
{
+ struct omap_dss_board_info *pdata = hdmi.pdev->dev.platform_data;
int r;
struct gpio gpios[] = {
@@ -333,7 +334,7 @@ static int __init hdmi_init_display(struct omap_dss_device *dssdev)
DSSDBG("init_display\n");
- dss_init_hdmi_ip_ops(&hdmi.ip_data);
+ dss_init_hdmi_ip_ops(&hdmi.ip_data, pdata->version);
if (hdmi.vdda_hdmi_dac_reg == NULL) {
struct regulator *reg;
diff --git a/drivers/video/omap2/omapfb/omapfb-ioctl.c b/drivers/video/omap2/omapfb/omapfb-ioctl.c
index 606b89f12351..55a39be694a5 100644
--- a/drivers/video/omap2/omapfb/omapfb-ioctl.c
+++ b/drivers/video/omap2/omapfb/omapfb-ioctl.c
@@ -30,7 +30,7 @@
#include <linux/export.h>
#include <video/omapdss.h>
-#include <plat/vrfb.h>
+#include <video/omapvrfb.h>
#include <plat/vram.h>
#include "omapfb.h"
diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
index 16db1589bd91..bc225e46fdd2 100644
--- a/drivers/video/omap2/omapfb/omapfb-main.c
+++ b/drivers/video/omap2/omapfb/omapfb-main.c
@@ -31,9 +31,8 @@
#include <linux/omapfb.h>
#include <video/omapdss.h>
-#include <plat/cpu.h>
#include <plat/vram.h>
-#include <plat/vrfb.h>
+#include <video/omapvrfb.h>
#include "omapfb.h"
@@ -2396,10 +2395,7 @@ static int __init omapfb_probe(struct platform_device *pdev)
goto err0;
}
- /* TODO : Replace cpu check with omap_has_vrfb once HAS_FEATURE
- * available for OMAP2 and OMAP3
- */
- if (def_vrfb && !cpu_is_omap24xx() && !cpu_is_omap34xx()) {
+ if (def_vrfb && !omap_vrfb_supported()) {
def_vrfb = 0;
dev_warn(&pdev->dev, "VRFB is not supported on this hardware, "
"ignoring the module parameter vrfb=y\n");
diff --git a/drivers/video/omap2/omapfb/omapfb-sysfs.c b/drivers/video/omap2/omapfb/omapfb-sysfs.c
index e8d8cc76a435..17aa174e187c 100644
--- a/drivers/video/omap2/omapfb/omapfb-sysfs.c
+++ b/drivers/video/omap2/omapfb/omapfb-sysfs.c
@@ -30,7 +30,7 @@
#include <linux/omapfb.h>
#include <video/omapdss.h>
-#include <plat/vrfb.h>
+#include <video/omapvrfb.h>
#include "omapfb.h"
diff --git a/drivers/video/omap2/vrfb.c b/drivers/video/omap2/vrfb.c
index 7e990220ad2a..5d8fdac3b800 100644
--- a/drivers/video/omap2/vrfb.c
+++ b/drivers/video/omap2/vrfb.c
@@ -26,9 +26,9 @@
#include <linux/io.h>
#include <linux/bitops.h>
#include <linux/mutex.h>
+#include <linux/platform_device.h>
-#include <plat/vrfb.h>
-#include <plat/sdrc.h>
+#include <video/omapvrfb.h>
#ifdef DEBUG
#define DBG(format, ...) pr_debug("VRFB: " format, ## __VA_ARGS__)
@@ -36,10 +36,10 @@
#define DBG(format, ...)
#endif
-#define SMS_ROT_VIRT_BASE(context, rot) \
- (((context >= 4) ? 0xD0000000 : 0x70000000) \
- + (0x4000000 * (context)) \
- + (0x1000000 * (rot)))
+#define SMS_ROT_CONTROL(context) (0x0 + 0x10 * context)
+#define SMS_ROT_SIZE(context) (0x4 + 0x10 * context)
+#define SMS_ROT_PHYSICAL_BA(context) (0x8 + 0x10 * context)
+#define SMS_ROT_VIRT_BASE(rot) (0x1000000 * (rot))
#define OMAP_VRFB_SIZE (2048 * 2048 * 4)
@@ -53,10 +53,16 @@
#define SMS_PW_OFFSET 4
#define SMS_PS_OFFSET 0
-#define VRFB_NUM_CTXS 12
/* bitmap of reserved contexts */
static unsigned long ctx_map;
+struct vrfb_ctx {
+ u32 base;
+ u32 physical_ba;
+ u32 control;
+ u32 size;
+};
+
static DEFINE_MUTEX(ctx_lock);
/*
@@ -65,17 +71,34 @@ static DEFINE_MUTEX(ctx_lock);
* we don't need locking, since no drivers will run until after the wake-up
* has finished.
*/
-static struct {
- u32 physical_ba;
- u32 control;
- u32 size;
-} vrfb_hw_context[VRFB_NUM_CTXS];
+
+static void __iomem *vrfb_base;
+
+static int num_ctxs;
+static struct vrfb_ctx *ctxs;
+
+static bool vrfb_loaded;
+
+static void omap2_sms_write_rot_control(u32 val, unsigned ctx)
+{
+ __raw_writel(val, vrfb_base + SMS_ROT_CONTROL(ctx));
+}
+
+static void omap2_sms_write_rot_size(u32 val, unsigned ctx)
+{
+ __raw_writel(val, vrfb_base + SMS_ROT_SIZE(ctx));
+}
+
+static void omap2_sms_write_rot_physical_ba(u32 val, unsigned ctx)
+{
+ __raw_writel(val, vrfb_base + SMS_ROT_PHYSICAL_BA(ctx));
+}
static inline void restore_hw_context(int ctx)
{
- omap2_sms_write_rot_control(vrfb_hw_context[ctx].control, ctx);
- omap2_sms_write_rot_size(vrfb_hw_context[ctx].size, ctx);
- omap2_sms_write_rot_physical_ba(vrfb_hw_context[ctx].physical_ba, ctx);
+ omap2_sms_write_rot_control(ctxs[ctx].control, ctx);
+ omap2_sms_write_rot_size(ctxs[ctx].size, ctx);
+ omap2_sms_write_rot_physical_ba(ctxs[ctx].physical_ba, ctx);
}
static u32 get_image_width_roundup(u16 width, u8 bytespp)
@@ -196,9 +219,9 @@ void omap_vrfb_setup(struct vrfb *vrfb, unsigned long paddr,
control |= VRFB_PAGE_WIDTH_EXP << SMS_PW_OFFSET;
control |= VRFB_PAGE_HEIGHT_EXP << SMS_PH_OFFSET;
- vrfb_hw_context[ctx].physical_ba = paddr;
- vrfb_hw_context[ctx].size = size;
- vrfb_hw_context[ctx].control = control;
+ ctxs[ctx].physical_ba = paddr;
+ ctxs[ctx].size = size;
+ ctxs[ctx].control = control;
omap2_sms_write_rot_physical_ba(paddr, ctx);
omap2_sms_write_rot_size(size, ctx);
@@ -274,11 +297,11 @@ int omap_vrfb_request_ctx(struct vrfb *vrfb)
mutex_lock(&ctx_lock);
- for (ctx = 0; ctx < VRFB_NUM_CTXS; ++ctx)
+ for (ctx = 0; ctx < num_ctxs; ++ctx)
if ((ctx_map & (1 << ctx)) == 0)
break;
- if (ctx == VRFB_NUM_CTXS) {
+ if (ctx == num_ctxs) {
pr_err("vrfb: no free contexts\n");
r = -EBUSY;
goto out;
@@ -293,7 +316,7 @@ int omap_vrfb_request_ctx(struct vrfb *vrfb)
vrfb->context = ctx;
for (rot = 0; rot < 4; ++rot) {
- paddr = SMS_ROT_VIRT_BASE(ctx, rot);
+ paddr = ctxs[ctx].base + SMS_ROT_VIRT_BASE(rot);
if (!request_mem_region(paddr, OMAP_VRFB_SIZE, "vrfb")) {
pr_err("vrfb: failed to reserve VRFB "
"area for ctx %d, rotation %d\n",
@@ -314,3 +337,80 @@ out:
return r;
}
EXPORT_SYMBOL(omap_vrfb_request_ctx);
+
+bool omap_vrfb_supported(void)
+{
+ return vrfb_loaded;
+}
+EXPORT_SYMBOL(omap_vrfb_supported);
+
+static int __init vrfb_probe(struct platform_device *pdev)
+{
+ struct resource *mem;
+ int i;
+
+ /* first resource is the register res, the rest are vrfb contexts */
+
+ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!mem) {
+ dev_err(&pdev->dev, "can't get vrfb base address\n");
+ return -EINVAL;
+ }
+
+ vrfb_base = devm_request_and_ioremap(&pdev->dev, mem);
+ if (!vrfb_base) {
+ dev_err(&pdev->dev, "can't ioremap vrfb memory\n");
+ return -ENOMEM;
+ }
+
+ num_ctxs = pdev->num_resources - 1;
+
+ ctxs = devm_kzalloc(&pdev->dev,
+ sizeof(struct vrfb_ctx) * num_ctxs,
+ GFP_KERNEL);
+
+ if (!ctxs)
+ return -ENOMEM;
+
+ for (i = 0; i < num_ctxs; ++i) {
+ mem = platform_get_resource(pdev, IORESOURCE_MEM, 1 + i);
+ if (!mem) {
+ dev_err(&pdev->dev, "can't get vrfb ctx %d address\n",
+ i);
+ return -EINVAL;
+ }
+
+ ctxs[i].base = mem->start;
+ }
+
+ vrfb_loaded = true;
+
+ return 0;
+}
+
+static void __exit vrfb_remove(struct platform_device *pdev)
+{
+ vrfb_loaded = false;
+}
+
+static struct platform_driver vrfb_driver = {
+ .driver.name = "omapvrfb",
+ .remove = __exit_p(vrfb_remove),
+};
+
+static int __init vrfb_init(void)
+{
+ return platform_driver_probe(&vrfb_driver, &vrfb_probe);
+}
+
+static void __exit vrfb_exit(void)
+{
+ platform_driver_unregister(&vrfb_driver);
+}
+
+module_init(vrfb_init);
+module_exit(vrfb_exit);
+
+MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
+MODULE_DESCRIPTION("OMAP VRFB");
+MODULE_LICENSE("GPL v2");