aboutsummaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/atm/Kconfig8
-rw-r--r--drivers/auxdisplay/Kconfig8
-rw-r--r--drivers/base/dmapool.c2
-rw-r--r--drivers/block/Kconfig9
-rw-r--r--drivers/block/Makefile1
-rw-r--r--drivers/block/nbd.c22
-rw-r--r--drivers/block/pktcdvd.c3
-rw-r--r--drivers/block/sunvdc.c972
-rw-r--r--drivers/block/z2ram.c3
-rw-r--r--drivers/char/Kconfig9
-rw-r--r--drivers/char/Makefile1
-rw-r--r--drivers/char/amiserial.c7
-rw-r--r--drivers/char/consolemap.c78
-rw-r--r--drivers/char/cyclades.c4
-rw-r--r--drivers/char/esp.c7
-rw-r--r--drivers/char/generic_serial.c120
-rw-r--r--drivers/char/genrtc.c22
-rw-r--r--drivers/char/hw_random/intel-rng.c10
-rw-r--r--drivers/char/ip2/i2ellis.c44
-rw-r--r--drivers/char/ipmi/Kconfig15
-rw-r--r--drivers/char/ipmi/ipmi_poweroff.c2
-rw-r--r--drivers/char/ipmi/ipmi_si_intf.c2
-rw-r--r--drivers/char/istallion.c3
-rw-r--r--drivers/char/keyboard.c26
-rw-r--r--drivers/char/misc.c18
-rw-r--r--drivers/char/mspec.c2
-rw-r--r--drivers/char/mxser.c16
-rw-r--r--drivers/char/mxser_new.c22
-rw-r--r--drivers/char/n_hdlc.c16
-rw-r--r--drivers/char/n_r3964.c14
-rw-r--r--drivers/char/n_tty.c23
-rw-r--r--drivers/char/nvram.c192
-rw-r--r--drivers/char/rocket.c3
-rw-r--r--drivers/char/rtc.c3
-rw-r--r--drivers/char/selection.c48
-rw-r--r--drivers/char/sonypi.c47
-rw-r--r--drivers/char/synclink.c8
-rw-r--r--drivers/char/synclink_gt.c8
-rw-r--r--drivers/char/synclinkmp.c8
-rw-r--r--drivers/char/tpm/Kconfig18
-rw-r--r--drivers/char/tty_audit.c345
-rw-r--r--drivers/char/tty_io.c65
-rw-r--r--drivers/char/tty_ioctl.c32
-rw-r--r--drivers/connector/Kconfig7
-rw-r--r--drivers/crypto/Kconfig9
-rw-r--r--drivers/dma/Kconfig2
-rw-r--r--drivers/edac/Kconfig14
-rw-r--r--drivers/firmware/edd.c7
-rw-r--r--drivers/firmware/pcdp.c6
-rw-r--r--drivers/macintosh/adb.c10
-rw-r--r--drivers/message/i2o/Kconfig22
-rw-r--r--drivers/message/i2o/device.c16
-rw-r--r--drivers/message/i2o/exec-osm.c4
-rw-r--r--drivers/message/i2o/iop.c2
-rw-r--r--drivers/misc/Kconfig8
-rw-r--r--drivers/misc/sony-laptop.c3
-rw-r--r--drivers/net/Kconfig6
-rw-r--r--drivers/net/Makefile1
-rw-r--r--drivers/net/sunvnet.c1164
-rw-r--r--drivers/net/sunvnet.h70
-rw-r--r--drivers/net/wan/Kconfig2
-rw-r--r--drivers/parport/Kconfig26
-rw-r--r--drivers/parport/parport_pc.c5
-rw-r--r--drivers/pci/pci-sysfs.c2
-rw-r--r--drivers/pci/probe.c12
-rw-r--r--drivers/pci/proc.c2
-rw-r--r--drivers/pci/search.c4
-rw-r--r--drivers/pnp/Kconfig13
-rw-r--r--drivers/pnp/isapnp/Kconfig2
-rw-r--r--drivers/pnp/isapnp/core.c2
-rw-r--r--drivers/pnp/pnpbios/Kconfig2
-rw-r--r--drivers/sbus/char/cpwatchdog.c1
-rw-r--r--drivers/scsi/Kconfig2
-rw-r--r--drivers/serial/68360serial.c7
-rw-r--r--drivers/serial/8250.c28
-rw-r--r--drivers/serial/8250_early.c117
-rw-r--r--drivers/serial/Kconfig14
-rw-r--r--drivers/serial/atmel_serial.c32
-rw-r--r--drivers/serial/ip22zilog.c3
-rw-r--r--drivers/serial/serial_core.c6
-rw-r--r--drivers/serial/sh-sci.c4
-rw-r--r--drivers/serial/sh-sci.h50
-rw-r--r--drivers/serial/sn_console.c4
-rw-r--r--drivers/serial/sunhv.c30
-rw-r--r--drivers/serial/sunsab.c19
-rw-r--r--drivers/serial/sunsu.c14
-rw-r--r--drivers/serial/sunzilog.c17
-rw-r--r--drivers/telephony/Kconfig12
-rw-r--r--drivers/video/pvr2fb.c101
-rw-r--r--drivers/w1/Kconfig12
-rw-r--r--drivers/w1/masters/Kconfig7
-rw-r--r--drivers/w1/slaves/Kconfig4
92 files changed, 3242 insertions, 931 deletions
diff --git a/drivers/atm/Kconfig b/drivers/atm/Kconfig
index 5b4fab24155..bb4ae628149 100644
--- a/drivers/atm/Kconfig
+++ b/drivers/atm/Kconfig
@@ -142,7 +142,7 @@ config ATM_ENI_BURST_RX_2W
config ATM_FIRESTREAM
tristate "Fujitsu FireStream (FS50/FS155) "
- depends on PCI
+ depends on PCI && VIRT_TO_BUS
help
Driver for the Fujitsu FireStream 155 (MB86697) and
FireStream 50 (MB86695) ATM PCI chips.
@@ -152,7 +152,7 @@ config ATM_FIRESTREAM
config ATM_ZATM
tristate "ZeitNet ZN1221/ZN1225"
- depends on PCI
+ depends on PCI && VIRT_TO_BUS
help
Driver for the ZeitNet ZN1221 (MMF) and ZN1225 (UTP-5) 155 Mbps ATM
adapters.
@@ -240,7 +240,7 @@ config ATM_IDT77252_USE_SUNI
config ATM_AMBASSADOR
tristate "Madge Ambassador (Collage PCI 155 Server)"
- depends on PCI
+ depends on PCI && VIRT_TO_BUS
select BITREVERSE
help
This is a driver for ATMizer based ATM card produced by Madge
@@ -265,7 +265,7 @@ config ATM_AMBASSADOR_DEBUG
config ATM_HORIZON
tristate "Madge Horizon [Ultra] (Collage PCI 25 and Collage PCI 155 Client)"
- depends on PCI
+ depends on PCI && VIRT_TO_BUS
help
This is a driver for the Horizon chipset ATM adapter cards once
produced by Madge Networks Ltd. Say Y (or M to compile as a module
diff --git a/drivers/auxdisplay/Kconfig b/drivers/auxdisplay/Kconfig
index ea4fe3e48f3..de2fcce10ba 100644
--- a/drivers/auxdisplay/Kconfig
+++ b/drivers/auxdisplay/Kconfig
@@ -5,8 +5,11 @@
# Auxiliary display drivers configuration.
#
-menu "Auxiliary Display support"
+menuconfig AUXDISPLAY
depends on PARPORT
+ bool "Auxiliary Display support"
+
+if AUXDISPLAY && PARPORT
config KS0108
tristate "KS0108 LCD Controller"
@@ -111,4 +114,5 @@ config CFAG12864B_RATE
If you compile this as a module, you can still override this
value using the module parameters.
-endmenu
+
+endif # AUXDISPLAY
diff --git a/drivers/base/dmapool.c b/drivers/base/dmapool.c
index 91970e9bb05..7647abfe189 100644
--- a/drivers/base/dmapool.c
+++ b/drivers/base/dmapool.c
@@ -127,7 +127,7 @@ dma_pool_create (const char *name, struct device *dev,
} else if (allocation < size)
return NULL;
- if (!(retval = kmalloc (sizeof *retval, GFP_KERNEL)))
+ if (!(retval = kmalloc_node (sizeof *retval, GFP_KERNEL, dev_to_node(dev))))
return retval;
strlcpy (retval->name, name, sizeof retval->name);
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
index 95d6838c4ff..c5a61571a07 100644
--- a/drivers/block/Kconfig
+++ b/drivers/block/Kconfig
@@ -102,7 +102,7 @@ source "drivers/block/paride/Kconfig"
config BLK_CPQ_DA
tristate "Compaq SMART2 support"
- depends on PCI
+ depends on PCI && VIRT_TO_BUS
help
This is the driver for Compaq Smart Array controllers. Everyone
using these boards should say Y here. See the file
@@ -412,6 +412,13 @@ config ATA_OVER_ETH
This driver provides Support for ATA over Ethernet block
devices like the Coraid EtherDrive (R) Storage Blade.
+config SUNVDC
+ tristate "Sun Virtual Disk Client support"
+ depends on SUN_LDOMS
+ help
+ Support for virtual disk devices as a client under Sun
+ Logical Domains.
+
source "drivers/s390/block/Kconfig"
endif # BLK_DEV
diff --git a/drivers/block/Makefile b/drivers/block/Makefile
index bba3119b28c..7926be8c9fb 100644
--- a/drivers/block/Makefile
+++ b/drivers/block/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_BLK_CPQ_DA) += cpqarray.o
obj-$(CONFIG_BLK_CPQ_CISS_DA) += cciss.o
obj-$(CONFIG_BLK_DEV_DAC960) += DAC960.o
obj-$(CONFIG_CDROM_PKTCDVD) += pktcdvd.o
+obj-$(CONFIG_SUNVDC) += sunvdc.o
obj-$(CONFIG_BLK_DEV_UMEM) += umem.o
obj-$(CONFIG_BLK_DEV_NBD) += nbd.o
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index c575fb1d585..c1295102409 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -122,17 +122,12 @@ static int sock_xmit(struct socket *sock, int send, void *buf, int size,
int result;
struct msghdr msg;
struct kvec iov;
- unsigned long flags;
- sigset_t oldset;
+ sigset_t blocked, oldset;
/* Allow interception of SIGKILL only
* Don't allow other signals to interrupt the transmission */
- spin_lock_irqsave(&current->sighand->siglock, flags);
- oldset = current->blocked;
- sigfillset(&current->blocked);
- sigdelsetmask(&current->blocked, sigmask(SIGKILL));
- recalc_sigpending();
- spin_unlock_irqrestore(&current->sighand->siglock, flags);
+ siginitsetinv(&blocked, sigmask(SIGKILL));
+ sigprocmask(SIG_SETMASK, &blocked, &oldset);
do {
sock->sk->sk_allocation = GFP_NOIO;
@@ -151,11 +146,9 @@ static int sock_xmit(struct socket *sock, int send, void *buf, int size,
if (signal_pending(current)) {
siginfo_t info;
- spin_lock_irqsave(&current->sighand->siglock, flags);
printk(KERN_WARNING "nbd (pid %d: %s) got signal %d\n",
- current->pid, current->comm,
- dequeue_signal(current, &current->blocked, &info));
- spin_unlock_irqrestore(&current->sighand->siglock, flags);
+ current->pid, current->comm,
+ dequeue_signal_lock(current, &current->blocked, &info));
result = -EINTR;
break;
}
@@ -169,10 +162,7 @@ static int sock_xmit(struct socket *sock, int send, void *buf, int size,
buf += result;
} while (size > 0);
- spin_lock_irqsave(&current->sighand->siglock, flags);
- current->blocked = oldset;
- recalc_sigpending();
- spin_unlock_irqrestore(&current->sighand->siglock, flags);
+ sigprocmask(SIG_SETMASK, &oldset, NULL);
return result;
}
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index ce64e86d6ff..7c294a40002 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -1652,9 +1652,6 @@ static int kcdrwd(void *foobar)
}
}
- if (signal_pending(current)) {
- flush_signals(current);
- }
if (kthread_should_stop())
break;
}
diff --git a/drivers/block/sunvdc.c b/drivers/block/sunvdc.c
new file mode 100644
index 00000000000..0f5e3caf85d
--- /dev/null
+++ b/drivers/block/sunvdc.c
@@ -0,0 +1,972 @@
+/* sunvdc.c: Sun LDOM Virtual Disk Client.
+ *
+ * Copyright (C) 2007 David S. Miller <davem@davemloft.net>
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/blkdev.h>
+#include <linux/hdreg.h>
+#include <linux/genhd.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/list.h>
+
+#include <asm/vio.h>
+#include <asm/ldc.h>
+
+#define DRV_MODULE_NAME "sunvdc"
+#define PFX DRV_MODULE_NAME ": "
+#define DRV_MODULE_VERSION "1.0"
+#define DRV_MODULE_RELDATE "June 25, 2007"
+
+static char version[] __devinitdata =
+ DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
+MODULE_AUTHOR("David S. Miller (davem@davemloft.net)");
+MODULE_DESCRIPTION("Sun LDOM virtual disk client driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_MODULE_VERSION);
+
+#define VDC_TX_RING_SIZE 256
+
+#define WAITING_FOR_LINK_UP 0x01
+#define WAITING_FOR_TX_SPACE 0x02
+#define WAITING_FOR_GEN_CMD 0x04
+#define WAITING_FOR_ANY -1
+
+struct vdc_req_entry {
+ struct request *req;
+};
+
+struct vdc_port {
+ struct vio_driver_state vio;
+
+ struct vdc *vp;
+
+ struct gendisk *disk;
+
+ struct vdc_completion *cmp;
+
+ u64 req_id;
+ u64 seq;
+ struct vdc_req_entry rq_arr[VDC_TX_RING_SIZE];
+
+ unsigned long ring_cookies;
+
+ u64 max_xfer_size;
+ u32 vdisk_block_size;
+
+ /* The server fills these in for us in the disk attribute
+ * ACK packet.
+ */
+ u64 operations;
+ u32 vdisk_size;
+ u8 vdisk_type;
+ u8 dev_no;
+
+ char disk_name[32];
+
+ struct vio_disk_geom geom;
+ struct vio_disk_vtoc label;
+
+ struct list_head list;
+};
+
+static inline struct vdc_port *to_vdc_port(struct vio_driver_state *vio)
+{
+ return container_of(vio, struct vdc_port, vio);
+}
+
+struct vdc {
+ /* Protects prot_list. */
+ spinlock_t lock;
+
+ struct vio_dev *dev;
+
+ struct list_head port_list;
+};
+
+/* Ordered from largest major to lowest */
+static struct vio_version vdc_versions[] = {
+ { .major = 1, .minor = 0 },
+};
+
+#define VDCBLK_NAME "vdisk"
+static int vdc_major;
+#define PARTITION_SHIFT 3
+
+static inline u32 vdc_tx_dring_avail(struct vio_dring_state *dr)
+{
+ return vio_dring_avail(dr, VDC_TX_RING_SIZE);
+}
+
+static int vdc_getgeo(struct block_device *bdev, struct hd_geometry *geo)
+{
+ struct gendisk *disk = bdev->bd_disk;
+ struct vdc_port *port = disk->private_data;
+
+ geo->heads = (u8) port->geom.num_hd;
+ geo->sectors = (u8) port->geom.num_sec;
+ geo->cylinders = port->geom.num_cyl;
+
+ return 0;
+}
+
+static struct block_device_operations vdc_fops = {
+ .owner = THIS_MODULE,
+ .getgeo = vdc_getgeo,
+};
+
+static void vdc_finish(struct vio_driver_state *vio, int err, int waiting_for)
+{
+ if (vio->cmp &&
+ (waiting_for == -1 ||
+ vio->cmp->waiting_for == waiting_for)) {
+ vio->cmp->err = err;
+ complete(&vio->cmp->com);
+ vio->cmp = NULL;
+ }
+}
+
+static void vdc_handshake_complete(struct vio_driver_state *vio)
+{
+ vdc_finish(vio, 0, WAITING_FOR_LINK_UP);
+}
+
+static int vdc_handle_unknown(struct vdc_port *port, void *arg)
+{
+ struct vio_msg_tag *pkt = arg;
+
+ printk(KERN_ERR PFX "Received unknown msg [%02x:%02x:%04x:%08x]\n",
+ pkt->type, pkt->stype, pkt->stype_env, pkt->sid);
+ printk(KERN_ERR PFX "Resetting connection.\n");
+
+ ldc_disconnect(port->vio.lp);
+
+ return -ECONNRESET;
+}
+
+static int vdc_send_attr(struct vio_driver_state *vio)
+{
+ struct vdc_port *port = to_vdc_port(vio);
+ struct vio_disk_attr_info pkt;
+
+ memset(&pkt, 0, sizeof(pkt));
+
+ pkt.tag.type = VIO_TYPE_CTRL;
+ pkt.tag.stype = VIO_SUBTYPE_INFO;
+ pkt.tag.stype_env = VIO_ATTR_INFO;
+ pkt.tag.sid = vio_send_sid(vio);
+
+ pkt.xfer_mode = VIO_DRING_MODE;
+ pkt.vdisk_block_size = port->vdisk_block_size;
+ pkt.max_xfer_size = port->max_xfer_size;
+
+ viodbg(HS, "SEND ATTR xfer_mode[0x%x] blksz[%u] max_xfer[%lu]\n",
+ pkt.xfer_mode, pkt.vdisk_block_size, pkt.max_xfer_size);
+
+ return vio_ldc_send(&port->vio, &pkt, sizeof(pkt));
+}
+
+static int vdc_handle_attr(struct vio_driver_state *vio, void *arg)
+{
+ struct vdc_port *port = to_vdc_port(vio);
+ struct vio_disk_attr_info *pkt = arg;
+
+ viodbg(HS, "GOT ATTR stype[0x%x] ops[%lx] disk_size[%lu] disk_type[%x] "
+ "xfer_mode[0x%x] blksz[%u] max_xfer[%lu]\n",
+ pkt->tag.stype, pkt->operations,
+ pkt->vdisk_size, pkt->vdisk_type,
+ pkt->xfer_mode, pkt->vdisk_block_size,
+ pkt->max_xfer_size);
+
+ if (pkt->tag.stype == VIO_SUBTYPE_ACK) {
+ switch (pkt->vdisk_type) {
+ case VD_DISK_TYPE_DISK:
+ case VD_DISK_TYPE_SLICE:
+ break;
+
+ default:
+ printk(KERN_ERR PFX "%s: Bogus vdisk_type 0x%x\n",
+ vio->name, pkt->vdisk_type);
+ return -ECONNRESET;
+ }
+
+ if (pkt->vdisk_block_size > port->vdisk_block_size) {
+ printk(KERN_ERR PFX "%s: BLOCK size increased "
+ "%u --> %u\n",
+ vio->name,
+ port->vdisk_block_size, pkt->vdisk_block_size);
+ return -ECONNRESET;
+ }
+
+ port->operations = pkt->operations;
+ port->vdisk_size = pkt->vdisk_size;
+ port->vdisk_type = pkt->vdisk_type;
+ if (pkt->max_xfer_size < port->max_xfer_size)
+ port->max_xfer_size = pkt->max_xfer_size;
+ port->vdisk_block_size = pkt->vdisk_block_size;
+ return 0;
+ } else {
+ printk(KERN_ERR PFX "%s: Attribute NACK\n", vio->name);
+
+ return -ECONNRESET;
+ }
+}
+
+static void vdc_end_special(struct vdc_port *port, struct vio_disk_desc *desc)
+{
+ int err = desc->status;
+
+ vdc_finish(&port->vio, -err, WAITING_FOR_GEN_CMD);
+}
+
+static void vdc_end_request(struct request *req, int uptodate, int num_sectors)
+{
+ if (end_that_request_first(req, uptodate, num_sectors))
+ return;
+ add_disk_randomness(req->rq_disk);
+ end_that_request_last(req, uptodate);
+}
+
+static void vdc_end_one(struct vdc_port *port, struct vio_dring_state *dr,
+ unsigned int index)
+{
+ struct vio_disk_desc *desc = vio_dring_entry(dr, index);
+ struct vdc_req_entry *rqe = &port->rq_arr[index];
+ struct request *req;
+
+ if (unlikely(desc->hdr.state != VIO_DESC_DONE))
+ return;
+
+ ldc_unmap(port->vio.lp, desc->cookies, desc->ncookies);
+ desc->hdr.state = VIO_DESC_FREE;
+ dr->cons = (index + 1) & (VDC_TX_RING_SIZE - 1);
+
+ req = rqe->req;
+ if (req == NULL) {
+ vdc_end_special(port, desc);
+ return;
+ }
+
+ rqe->req = NULL;
+
+ vdc_end_request(req, !desc->status, desc->size >> 9);
+
+ if (blk_queue_stopped(port->disk->queue))
+ blk_start_queue(port->disk->queue);
+}
+
+static int vdc_ack(struct vdc_port *port, void *msgbuf)
+{
+ struct vio_dring_state *dr = &port->vio.drings[VIO_DRIVER_TX_RING];
+ struct vio_dring_data *pkt = msgbuf;
+
+ if (unlikely(pkt->dring_ident != dr->ident ||
+ pkt->start_idx != pkt->end_idx ||
+ pkt->start_idx >= VDC_TX_RING_SIZE))
+ return 0;
+
+ vdc_end_one(port, dr, pkt->start_idx);
+
+ return 0;
+}
+
+static int vdc_nack(struct vdc_port *port, void *msgbuf)
+{
+ /* XXX Implement me XXX */
+ return 0;
+}
+
+static void vdc_event(void *arg, int event)
+{
+ struct vdc_port *port = arg;
+ struct vio_driver_state *vio = &port->vio;
+ unsigned long flags;
+ int err;
+
+ spin_lock_irqsave(&vio->lock, flags);
+
+ if (unlikely(event == LDC_EVENT_RESET ||
+ event == LDC_EVENT_UP)) {
+ vio_link_state_change(vio, event);
+ spin_unlock_irqrestore(&vio->lock, flags);
+ return;
+ }
+
+ if (unlikely(event != LDC_EVENT_DATA_READY)) {
+ printk(KERN_WARNING PFX "Unexpected LDC event %d\n", event);
+ spin_unlock_irqrestore(&vio->lock, flags);
+ return;
+ }
+
+ err = 0;
+ while (1) {
+ union {
+ struct vio_msg_tag tag;
+ u64 raw[8];
+ } msgbuf;
+
+ err = ldc_read(vio->lp, &msgbuf, sizeof(msgbuf));
+ if (unlikely(err < 0)) {
+ if (err == -ECONNRESET)
+ vio_conn_reset(vio);
+ break;
+ }
+ if (err == 0)
+ break;
+ viodbg(DATA, "TAG [%02x:%02x:%04x:%08x]\n",
+ msgbuf.tag.type,
+ msgbuf.tag.stype,
+ msgbuf.tag.stype_env,
+ msgbuf.tag.sid);
+ err = vio_validate_sid(vio, &msgbuf.tag);
+ if (err < 0)
+ break;
+
+ if (likely(msgbuf.tag.type == VIO_TYPE_DATA)) {
+ if (msgbuf.tag.stype == VIO_SUBTYPE_ACK)
+ err = vdc_ack(port, &msgbuf);
+ else if (msgbuf.tag.stype == VIO_SUBTYPE_NACK)
+ err = vdc_nack(port, &msgbuf);
+ else
+ err = vdc_handle_unknown(port, &msgbuf);
+ } else if (msgbuf.tag.type == VIO_TYPE_CTRL) {
+ err = vio_control_pkt_engine(vio, &msgbuf);
+ } else {
+ err = vdc_handle_unknown(port, &msgbuf);
+ }
+ if (err < 0)
+ break;
+ }
+ if (err < 0)
+ vdc_finish(&port->vio, err, WAITING_FOR_ANY);
+ spin_unlock_irqrestore(&vio->lock, flags);
+}
+
+static int __vdc_tx_trigger(struct vdc_port *port)
+{
+ struct vio_dring_state *dr = &port->vio.drings[VIO_DRIVER_TX_RING];
+ struct vio_dring_data hdr = {
+ .tag = {
+ .type = VIO_TYPE_DATA,
+ .stype = VIO_SUBTYPE_INFO,
+ .stype_env = VIO_DRING_DATA,
+ .sid = vio_send_sid(&port->vio),
+ },
+ .dring_ident = dr->ident,
+ .start_idx = dr->prod,
+ .end_idx = dr->prod,
+ };
+ int err, delay;
+
+ hdr.seq = dr->snd_nxt;
+ delay = 1;
+ do {
+ err = vio_ldc_send(&port->vio, &hdr, sizeof(hdr));
+ if (err > 0) {
+ dr->snd_nxt++;
+ break;
+ }
+ udelay(delay);
+ if ((delay <<= 1) > 128)
+ delay = 128;
+ } while (err == -EAGAIN);
+
+ return err;
+}
+
+static int __send_request(struct request *req)
+{
+ struct vdc_port *port = req->rq_disk->private_data;
+ struct vio_dring_state *dr = &port->vio.drings[VIO_DRIVER_TX_RING];
+ struct scatterlist sg[port->ring_cookies];
+ struct vdc_req_entry *rqe;
+ struct vio_disk_desc *desc;
+ unsigned int map_perm;
+ int nsg, err, i;
+ u64 len;
+ u8 op;
+
+ map_perm = LDC_MAP_SHADOW | LDC_MAP_DIRECT | LDC_MAP_IO;
+
+ if (rq_data_dir(req) == READ) {
+ map_perm |= LDC_MAP_W;
+ op = VD_OP_BREAD;
+ } else {
+ map_perm |= LDC_MAP_R;
+ op = VD_OP_BWRITE;
+ }
+
+ nsg = blk_rq_map_sg(req->q, req, sg);
+
+ len = 0;
+ for (i = 0; i < nsg; i++)
+ len += sg[i].length;
+
+ if (unlikely(vdc_tx_dring_avail(dr) < 1)) {
+ blk_stop_queue(port->disk->queue);
+ err = -ENOMEM;
+ goto out;
+ }
+
+ desc = vio_dring_cur(dr);
+
+ err = ldc_map_sg(port->vio.lp, sg, nsg,
+ desc->cookies, port->ring_cookies,
+ map_perm);
+ if (err < 0) {
+ printk(KERN_ERR PFX "ldc_map_sg() failure, err=%d.\n", err);
+ return err;
+ }
+
+ rqe = &port->rq_arr[dr->prod];
+ rqe->req = req;
+
+ desc->hdr.ack = VIO_ACK_ENABLE;
+ desc->req_id = port->req_id;
+ desc->operation = op;
+ if (port->vdisk_type == VD_DISK_TYPE_DISK) {
+ desc->slice = 2;
+ } else {
+ desc->slice = 0;
+ }
+ desc->status = ~0;
+ desc->offset = (req->sector << 9) / port->vdisk_block_size;
+ desc->size = len;
+ desc->ncookies = err;
+
+ /* This has to be a non-SMP write barrier because we are writing
+ * to memory which is shared with the peer LDOM.
+ */
+ wmb();
+ desc->hdr.state = VIO_DESC_READY;
+
+ err = __vdc_tx_trigger(port);
+ if (err < 0) {
+ printk(KERN_ERR PFX "vdc_tx_trigger() failure, err=%d\n", err);
+ } else {
+ port->req_id++;
+ dr->prod = (dr->prod + 1) & (VDC_TX_RING_SIZE - 1);
+ }
+out:
+
+ return err;
+}
+
+static void do_vdc_request(request_queue_t *q)
+{
+ while (1) {
+ struct request *req = elv_next_request(q);
+
+ if (!req)
+ break;
+
+ blkdev_dequeue_request(req);
+ if (__send_request(req) < 0)
+ vdc_end_request(req, 0, req->hard_nr_sectors);
+ }
+}
+
+static int generic_request(struct vdc_port *port, u8 op, void *buf, int len)
+{
+ struct vio_dring_state *dr;
+ struct vio_completion comp;
+ struct vio_disk_desc *desc;
+ unsigned int map_perm;
+ unsigned long flags;
+ int op_len, err;
+ void *req_buf;
+
+ if (!(((u64)1 << ((u64)op - 1)) & port->operations))
+ return -EOPNOTSUPP;
+
+ switch (op) {
+ case VD_OP_BREAD:
+ case VD_OP_BWRITE:
+ default:
+ return -EINVAL;
+
+ case VD_OP_FLUSH:
+ op_len = 0;
+ map_perm = 0;
+ break;
+
+ case VD_OP_GET_WCE:
+ op_len = sizeof(u32);
+ map_perm = LDC_MAP_W;
+ break;
+
+ case VD_OP_SET_WCE:
+ op_len = sizeof(u32);
+ map_perm = LDC_MAP_R;
+ break;
+
+ case VD_OP_GET_VTOC:
+ op_len = sizeof(struct vio_disk_vtoc);
+ map_perm = LDC_MAP_W;
+ break;
+
+ case VD_OP_SET_VTOC:
+ op_len = sizeof(struct vio_disk_vtoc);
+ map_perm = LDC_MAP_R;
+ break;
+
+ case VD_OP_GET_DISKGEOM:
+ op_len = sizeof(struct vio_disk_geom);
+ map_perm = LDC_MAP_W;
+ break;
+
+ case VD_OP_SET_DISKGEOM:
+ op_len = sizeof(struct vio_disk_geom);
+ map_perm = LDC_MAP_R;
+ break;
+
+ case VD_OP_SCSICMD:
+ op_len = 16;
+ map_perm = LDC_MAP_RW;
+ break;
+
+ case VD_OP_GET_DEVID:
+ op_len = sizeof(struct vio_disk_devid);
+ map_perm = LDC_MAP_W;
+ break;
+
+ case VD_OP_GET_EFI:
+ case VD_OP_SET_EFI:
+ return -EOPNOTSUPP;
+ break;
+ };
+
+ map_perm |= LDC_MAP_SHADOW | LDC_MAP_DIRECT | LDC_MAP_IO;
+
+ op_len = (op_len + 7) & ~7;
+ req_buf = kzalloc(op_len, GFP_KERNEL);
+ if (!req_buf)
+ return -ENOMEM;
+
+ if (len > op_len)
+ len = op_len;
+
+ if (map_perm & LDC_MAP_R)
+ memcpy(req_buf, buf, len);
+
+ spin_lock_irqsave(&port->vio.lock, flags);
+
+ dr = &port->vio.drings[VIO_DRIVER_TX_RING];
+
+ /* XXX If we want to use this code generically we have to
+ * XXX handle TX ring exhaustion etc.
+ */
+ desc = vio_dring_cur(dr);
+
+ err = ldc_map_single(port->vio.lp, req_buf, op_len,
+ desc->cookies, port->ring_cookies,
+ map_perm);
+ if (err < 0) {
+ spin_unlock_irqrestore(&port->vio.lock, flags);
+ kfree(req_buf);
+ return err;
+ }
+
+ init_completion(&comp.com);
+ comp.waiting_for = WAITING_FOR_GEN_CMD;
+ port->vio.cmp = &comp;
+
+ desc->hdr.ack = VIO_ACK_ENABLE;
+ desc->req_id = port->req_id;
+ desc->operation = op;
+ desc->slice = 0;
+ desc->status = ~0;
+ desc->offset = 0;
+ desc->size = op_len;
+ desc->ncookies = err;
+
+ /* This has to be a non-SMP write barrier because we are writing
+ * to memory which is shared with the peer LDOM.
+ */
+ wmb();
+ desc->hdr.state = VIO_DESC_READY;
+
+ err = __vdc_tx_trigger(port);
+ if (err >= 0) {
+ port->req_id++;
+ dr->prod = (dr->prod + 1) & (VDC_TX_RING_SIZE - 1);
+ spin_unlock_irqrestore(&port->vio.lock, flags);
+
+ wait_for_completion(&comp.com);
+ err = comp.err;
+ } else {
+ port->vio.cmp = NULL;
+ spin_unlock_irqrestore(&port->vio.lock, flags);
+ }
+
+ if (map_perm & LDC_MAP_W)
+ memcpy(buf, req_buf, len);
+
+ kfree(req_buf);
+
+ return err;
+}
+
+static int __devinit vdc_alloc_tx_ring(struct vdc_port *port)
+{
+ struct vio_dring_state *dr = &port->vio.drings[VIO_DRIVER_TX_RING];
+ unsigned long len, entry_size;
+ int ncookies;
+ void *dring;
+
+ entry_size = sizeof(struct vio_disk_desc) +
+ (sizeof(struct ldc_trans_cookie) * port->ring_cookies);
+ len = (VDC_TX_RING_SIZE * entry_size);
+
+ ncookies = VIO_MAX_RING_COOKIES;
+ dring = ldc_alloc_exp_dring(port->vio.lp, len,
+ dr->cookies, &ncookies,
+ (LDC_MAP_SHADOW |
+ LDC_MAP_DIRECT |
+ LDC_MAP_RW));
+ if (IS_ERR(dring))
+ return PTR_ERR(dring);
+
+ dr->base = dring;
+ dr->entry_size = entry_size;
+ dr->num_entries = VDC_TX_RING_SIZE;
+ dr->prod = dr->cons = 0;
+ dr->pending = VDC_TX_RING_SIZE;
+ dr->ncookies = ncookies;
+
+ return 0;
+}
+
+static void vdc_free_tx_ring(struct vdc_port *port)
+{
+ struct vio_dring_state *dr = &port->vio.drings[VIO_DRIVER_TX_RING];
+
+ if (dr->base) {
+ ldc_free_exp_dring(port->vio.lp, dr->base,
+ (dr->entry_size * dr->num_entries),
+ dr->cookies, dr->ncookies);
+ dr->base = NULL;
+ dr->entry_size = 0;
+ dr->num_entries = 0;
+ dr->pending = 0;
+ dr->ncookies = 0;
+ }
+}
+
+static int probe_disk(struct vdc_port *port)
+{
+ struct vio_completion comp;
+ struct request_queue *q;
+ struct gendisk *g;
+ int err;
+
+ init_completion(&comp.com);
+ comp.err = 0;
+ comp.waiting_for = WAITING_FOR_LINK_UP;
+ port->vio.cmp = &comp;
+
+ vio_port_up(&port->vio);
+
+ wait_for_completion(&comp.com);
+ if (comp.err)
+ return comp.err;
+
+ err = generic_request(port, VD_OP_GET_VTOC,
+ &port->label, sizeof(port->label));
+ if (err < 0) {
+ printk(KERN_ERR PFX "VD_OP_GET_VTOC returns error %d\n", err);
+ return err;
+ }
+
+ err = generic_request(port, VD_OP_GET_DISKGEOM,
+ &port->geom, sizeof(port->geom));
+ if (err < 0) {
+ printk(KERN_ERR PFX "VD_OP_GET_DISKGEOM returns "
+ "error %d\n", err);
+ return err;
+ }
+
+ port->vdisk_size = ((u64)port->geom.num_cyl *
+ (u64)port->geom.num_hd *
+ (u64)port->geom.num_sec);
+
+ q = blk_init_queue(do_vdc_request, &port->vio.lock);
+ if (!q) {
+ printk(KERN_ERR PFX "%s: Could not allocate queue.\n",
+ port->vio.name);
+ return -ENOMEM;
+ }
+ g = alloc_disk(1 << PARTITION_SHIFT);
+ if (!g) {
+ printk(KERN_ERR PFX "%s: Could not allocate gendisk.\n",
+ port->vio.name);
+ blk_cleanup_queue(q);
+ return -ENOMEM;
+ }
+
+ port->disk = g;
+
+ blk_queue_max_hw_segments(q, port->ring_cookies);
+ blk_queue_max_phys_segments(q, port->ring_cookies);
+ blk_queue_max_sectors(q, port->max_xfer_size);
+ g->major = vdc_major;
+ g->first_minor = port->dev_no << PARTITION_SHIFT;
+ strcpy(g->disk_name, port->disk_name);
+
+ g->fops = &vdc_fops;
+ g->queue = q;
+ g->private_data = port;
+ g->driverfs_dev = &port->vio.vdev->dev;
+
+ set_capacity(g, port->vdisk_size);
+
+ printk(KERN_INFO PFX "%s: %u sectors (%u MB)\n",
+ g->disk_name,
+ port->vdisk_size, (port->vdisk_size >> (20 - 9)));
+
+ add_disk(g);
+
+ return 0;
+}
+
+static struct ldc_channel_config vdc_ldc_cfg = {
+ .event = vdc_event,
+ .mtu = 64,
+ .mode = LDC_MODE_UNRELIABLE,
+};
+
+static struct vio_driver_ops vdc_vio_ops = {
+ .send_attr = vdc_send_attr,
+ .handle_attr = vdc_handle_attr,
+ .handshake_complete = vdc_handshake_complete,
+};
+
+static int __devinit vdc_port_probe(struct vio_dev *vdev,
+ const struct vio_device_id *id)
+{
+ struct mdesc_handle *hp;
+ struct vdc_port *port;
+ unsigned long flags;
+ struct vdc *vp;
+ const u64 *port_id;
+ int err;
+
+ vp = dev_get_drvdata(vdev->dev.parent);
+ if (!vp) {
+ printk(KERN_ERR PFX "Cannot find port parent vdc.\n");
+ return -ENODEV;
+ }
+
+ hp = mdesc_grab();
+
+ port_id = mdesc_get_property(hp, vdev->mp, "id", NULL);
+ err = -ENODEV;
+ if (!port_id) {
+ printk(KERN_ERR PFX "Port lacks id property.\n");
+ goto err_out_release_mdesc;
+ }
+ if ((*port_id << PARTITION_SHIFT) & ~(u64)MINORMASK) {
+ printk(KERN_ERR PFX "Port id [%lu] too large.\n", *port_id);
+ goto err_out_release_mdesc;
+ }
+
+ port = kzalloc(sizeof(*port), GFP_KERNEL);
+ err = -ENOMEM;
+ if (!port) {
+ printk(KERN_ERR PFX "Cannot allocate vdc_port.\n");
+ goto err_out_release_mdesc;
+ }
+
+ port->vp = vp;
+ port->dev_no = *port_id;
+
+ if (port->dev_no >= 26)
+ snprintf(port->disk_name, sizeof(port->disk_name),
+ VDCBLK_NAME "%c%c",
+ 'a' + (port->dev_no / 26) - 1,
+ 'a' + (port->dev_no % 26));
+ else
+ snprintf(port->disk_name, sizeof(port->disk_name),
+ VDCBLK_NAME "%c", 'a' + (port->dev_no % 26));
+
+ err = vio_driver_init(&port->vio, vdev, VDEV_DISK,
+ vdc_versions, ARRAY_SIZE(vdc_versions),
+ &vdc_vio_ops, port->disk_name);
+ if (err)
+ goto err_out_free_port;
+
+ port->vdisk_block_size = 512;
+ port->max_xfer_size = ((128 * 1024) / port->vdisk_block_size);
+ port->ring_cookies = ((port->max_xfer_size *
+ port->vdisk_block_size) / PAGE_SIZE) + 2;
+
+ err = vio_ldc_alloc(&port->vio, &vdc_ldc_cfg, port);
+ if (err)
+ goto err_out_free_port;
+
+ err = vdc_alloc_tx_ring(port);
+ if (err)
+ goto err_out_free_ldc;
+
+ err = probe_disk(port);
+ if (err)
+ goto err_out_free_tx_ring;
+
+ INIT_LIST_HEAD(&port->list);
+
+ spin_lock_irqsave(&vp->lock, flags);
+ list_add(&port->list, &vp->port_list);
+ spin_unlock_irqrestore(&vp->lock, flags);
+
+ dev_set_drvdata(&vdev->dev, port);
+
+ mdesc_release(hp);
+
+ return 0;
+
+err_out_free_tx_ring:
+ vdc_free_tx_ring(port);
+
+err_out_free_ldc:
+ vio_ldc_free(&port->vio);
+
+err_out_free_port:
+ kfree(port);
+
+err_out_release_mdesc:
+ mdesc_release(hp);
+ return err;
+}
+
+static int vdc_port_remove(struct vio_dev *vdev)
+{
+ struct vdc_port *port = dev_get_drvdata(&vdev->dev);
+
+ if (port) {
+ del_timer_sync(&port->vio.timer);
+
+ vdc_free_tx_ring(port);
+ vio_ldc_free(&port->vio);
+
+ dev_set_drvdata(&vdev->dev, NULL);
+
+ kfree(port);
+ }
+ return 0;
+}
+
+static struct vio_device_id vdc_port_match[] = {
+ {
+ .type = "vdc-port",
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(vio, vdc_match);
+
+static struct vio_driver vdc_port_driver = {
+ .id_table = vdc_port_match,
+ .probe = vdc_port_probe,
+ .remove = vdc_port_remove,
+ .driver = {
+ .name = "vdc_port",
+ .owner = THIS_MODULE,
+ }
+};
+
+static int __devinit vdc_probe(struct vio_dev *vdev,
+ const struct vio_device_id *id)
+{
+ static int vdc_version_printed;
+ struct vdc *vp;
+
+ if (vdc_version_printed++ == 0)
+ printk(KERN_INFO "%s", version);
+
+ vp = kzalloc(sizeof(struct vdc), GFP_KERNEL);
+ if (!vp)
+ return -ENOMEM;
+
+ spin_lock_init(&vp->lock);
+ vp->dev = vdev;
+ INIT_LIST_HEAD(&vp->port_list);
+
+ dev_set_drvdata(&vdev->dev, vp);
+
+ return 0;
+}
+
+static int vdc_remove(struct vio_dev *vdev)
+{
+
+ struct vdc *vp = dev_get_drvdata(&vdev->dev);
+
+ if (vp) {
+ kfree(vp);
+ dev_set_drvdata(&vdev->dev, NULL);
+ }
+ return 0;
+}
+
+static struct vio_device_id vdc_match[] = {
+ {
+ .type = "block",
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(vio, vdc_match);
+
+static struct vio_driver vdc_driver = {
+ .id_table = vdc_match,
+ .probe = vdc_probe,
+ .remove = vdc_remove,
+ .driver = {
+ .name = "vdc",
+ .owner = THIS_MODULE,
+ }
+};
+
+static int __init vdc_init(void)
+{
+ int err;
+
+ err = register_blkdev(0, VDCBLK_NAME);
+ if (err < 0)
+ goto out_err;
+
+ vdc_major = err;
+ err = vio_register_driver(&vdc_driver);
+ if (err)
+ goto out_unregister_blkdev;
+
+ err = vio_register_driver(&vdc_port_driver);
+ if (err)
+ goto out_unregister_vdc;
+
+ return 0;
+
+out_unregister_vdc:
+ vio_unregister_driver(&vdc_driver);
+
+out_unregister_blkdev:
+ unregister_blkdev(vdc_major, VDCBLK_NAME);
+ vdc_major = 0;
+
+out_err:
+ return err;
+}
+
+static void __exit vdc_exit(void)
+{
+ vio_unregister_driver(&vdc_port_driver);
+ vio_unregister_driver(&vdc_driver);
+ unregister_blkdev(vdc_major, VDCBLK_NAME);
+}
+
+module_init(vdc_init);
+module_exit(vdc_exit);
diff --git a/drivers/block/z2ram.c b/drivers/block/z2ram.c
index 7cc2685ca84..2abf94cc313 100644
--- a/drivers/block/z2ram.c
+++ b/drivers/block/z2ram.c
@@ -44,9 +44,6 @@
extern int m68k_realnum_memory;
extern struct mem_info m68k_memory[NUM_MEMINFO];
-#define TRUE (1)
-#define FALSE (0)
-
#define Z2MINOR_COMBINED (0)
#define Z2MINOR_Z2ONLY (1)
#define Z2MINOR_CHIPONLY (2)
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index f6648682b43..ec9dc3d53f1 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -979,15 +979,14 @@ config GPIO_VR41XX
depends on CPU_VR41XX
config RAW_DRIVER
- tristate "RAW driver (/dev/raw/rawN) (OBSOLETE)"
+ tristate "RAW driver (/dev/raw/rawN)"
depends on BLOCK
help
- The raw driver permits block devices to be bound to /dev/raw/rawN.
- Once bound, I/O against /dev/raw/rawN uses efficient zero-copy I/O.
+ The raw driver permits block devices to be bound to /dev/raw/rawN.
+ Once bound, I/O against /dev/raw/rawN uses efficient zero-copy I/O.
See the raw(8) manpage for more details.
- The raw driver is deprecated and will be removed soon.
- Applications should simply open the device (eg /dev/hda1)
+ Applications should preferably open the device (eg /dev/hda1)
with the O_DIRECT flag.
config MAX_RAW_DEVS
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index 2f56ecc035a..f2996a95eb0 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -15,6 +15,7 @@ obj-y += misc.o
obj-$(CONFIG_VT) += vt_ioctl.o vc_screen.o consolemap.o \
consolemap_deftbl.o selection.o keyboard.o
obj-$(CONFIG_HW_CONSOLE) += vt.o defkeymap.o
+obj-$(CONFIG_AUDIT) += tty_audit.o
obj-$(CONFIG_MAGIC_SYSRQ) += sysrq.o
obj-$(CONFIG_ESPSERIAL) += esp.o
obj-$(CONFIG_MVME147_SCC) += generic_serial.o vme_scc.o
diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c
index 4eaceabd8ce..7b02bf1289a 100644
--- a/drivers/char/amiserial.c
+++ b/drivers/char/amiserial.c
@@ -738,6 +738,7 @@ static void change_speed(struct async_struct *info,
}
/* If the quotient is zero refuse the change */
if (!quot && old_termios) {
+ /* FIXME: Will need updating for new tty in the end */
info->tty->termios->c_cflag &= ~CBAUD;
info->tty->termios->c_cflag |= (old_termios->c_cflag & CBAUD);
baud = tty_get_baud_rate(info->tty);
@@ -783,7 +784,6 @@ static void change_speed(struct async_struct *info,
/*
* Set up parity check flag
*/
-#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
info->read_status_mask = UART_LSR_OE | UART_LSR_DR;
if (I_INPCK(info->tty))
@@ -1367,11 +1367,6 @@ static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
unsigned long flags;
unsigned int cflag = tty->termios->c_cflag;
- if ( (cflag == old_termios->c_cflag)
- && ( RELEVANT_IFLAG(tty->termios->c_iflag)
- == RELEVANT_IFLAG(old_termios->c_iflag)))
- return;
-
change_speed(info, old_termios);
/* Handle transition to B0 status */
diff --git a/drivers/char/consolemap.c b/drivers/char/consolemap.c
index fd40b959afd..4b3916f5490 100644
--- a/drivers/char/consolemap.c
+++ b/drivers/char/consolemap.c
@@ -177,6 +177,7 @@ struct uni_pagedir {
unsigned long refcount;
unsigned long sum;
unsigned char *inverse_translations[4];
+ u16 *inverse_trans_unicode;
int readonly;
};
@@ -207,6 +208,41 @@ static void set_inverse_transl(struct vc_data *conp, struct uni_pagedir *p, int
}
}
+static void set_inverse_trans_unicode(struct vc_data *conp,
+ struct uni_pagedir *p)
+{
+ int i, j, k, glyph;
+ u16 **p1, *p2;
+ u16 *q;
+
+ if (!p) return;
+ q = p->inverse_trans_unicode;
+ if (!q) {
+ q = p->inverse_trans_unicode =
+ kmalloc(MAX_GLYPH * sizeof(u16), GFP_KERNEL);
+ if (!q)
+ return;
+ }
+ memset(q, 0, MAX_GLYPH * sizeof(u16));
+
+ for (i = 0; i < 32; i++) {
+ p1 = p->uni_pgdir[i];
+ if (!p1)
+ continue;
+ for (j = 0; j < 32; j++) {
+ p2 = p1[j];
+ if (!p2)
+ continue;
+ for (k = 0; k < 64; k++) {
+ glyph = p2[k];
+ if (glyph >= 0 && glyph < MAX_GLYPH
+ && q[glyph] < 32)
+ q[glyph] = (i << 11) + (j << 6) + k;
+ }
+ }
+ }
+}
+
unsigned short *set_translate(int m, struct vc_data *vc)
{
inv_translate[vc->vc_num] = m;
@@ -217,19 +253,29 @@ unsigned short *set_translate(int m, struct vc_data *vc)
* Inverse translation is impossible for several reasons:
* 1. The font<->character maps are not 1-1.
* 2. The text may have been written while a different translation map
- * was active, or using Unicode.
+ * was active.
* Still, it is now possible to a certain extent to cut and paste non-ASCII.
*/
-unsigned char inverse_translate(struct vc_data *conp, int glyph)
+u16 inverse_translate(struct vc_data *conp, int glyph, int use_unicode)
{
struct uni_pagedir *p;
+ int m;
if (glyph < 0 || glyph >= MAX_GLYPH)
return 0;
- else if (!(p = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc) ||
- !p->inverse_translations[inv_translate[conp->vc_num]])
+ else if (!(p = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc))
return glyph;
- else
- return p->inverse_translations[inv_translate[conp->vc_num]][glyph];
+ else if (use_unicode) {
+ if (!p->inverse_trans_unicode)
+ return glyph;
+ else
+ return p->inverse_trans_unicode[glyph];
+ } else {
+ m = inv_translate[conp->vc_num];
+ if (!p->inverse_translations[m])
+ return glyph;
+ else
+ return p->inverse_translations[m][glyph];
+ }
}
static void update_user_maps(void)
@@ -243,6 +289,7 @@ static void update_user_maps(void)
p = (struct uni_pagedir *)*vc_cons[i].d->vc_uni_pagedir_loc;
if (p && p != q) {
set_inverse_transl(vc_cons[i].d, p, USER_MAP);
+ set_inverse_trans_unicode(vc_cons[i].d, p);
q = p;
}
}
@@ -353,6 +400,10 @@ static void con_release_unimap(struct uni_pagedir *p)
kfree(p->inverse_translations[i]);
p->inverse_translations[i] = NULL;
}
+ if (p->inverse_trans_unicode) {
+ kfree(p->inverse_trans_unicode);
+ p->inverse_trans_unicode = NULL;
+ }
}
void con_free_unimap(struct vc_data *vc)
@@ -511,6 +562,7 @@ int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list)
for (i = 0; i <= 3; i++)
set_inverse_transl(vc, p, i); /* Update all inverse translations */
+ set_inverse_trans_unicode(vc, p);
return err;
}
@@ -561,6 +613,7 @@ int con_set_default_unimap(struct vc_data *vc)
for (i = 0; i <= 3; i++)
set_inverse_transl(vc, p, i); /* Update all inverse translations */
+ set_inverse_trans_unicode(vc, p);
dflt = p;
return err;
}
@@ -617,6 +670,19 @@ void con_protect_unimap(struct vc_data *vc, int rdonly)
p->readonly = rdonly;
}
+/* may be called during an interrupt */
+u32 conv_8bit_to_uni(unsigned char c)
+{
+ /*
+ * Always use USER_MAP. This function is used by the keyboard,
+ * which shouldn't be affected by G0/G1 switching, etc.
+ * If the user map still contains default values, i.e. the
+ * direct-to-font mapping, then assume user is using Latin1.
+ */
+ unsigned short uni = translations[USER_MAP][c];
+ return uni == (0xf000 | c) ? c : uni;
+}
+
int
conv_uni_to_pc(struct vc_data *conp, long ucs)
{
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c
index ca376b92162..e04005b5f8a 100644
--- a/drivers/char/cyclades.c
+++ b/drivers/char/cyclades.c
@@ -4127,10 +4127,6 @@ static void cy_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
printk(KERN_DEBUG "cyc:cy_set_termios ttyC%d\n", info->line);
#endif
- if (tty->termios->c_cflag == old_termios->c_cflag &&
- (tty->termios->c_iflag & (IXON | IXANY)) ==
- (old_termios->c_iflag & (IXON | IXANY)))
- return;
set_line_char(info);
if ((old_termios->c_cflag & CRTSCTS) &&
diff --git a/drivers/char/esp.c b/drivers/char/esp.c
index d1bfbaa2aa0..74cd5118af5 100644
--- a/drivers/char/esp.c
+++ b/drivers/char/esp.c
@@ -1121,8 +1121,6 @@ static void change_speed(struct esp_struct *info)
/*
* Set up parity check flag
*/
-#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
-
info->read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
if (I_INPCK(info->tty))
info->read_status_mask |= UART_LSR_FE | UART_LSR_PE;
@@ -1920,11 +1918,6 @@ static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
struct esp_struct *info = (struct esp_struct *)tty->driver_data;
unsigned long flags;
- if ( (tty->termios->c_cflag == old_termios->c_cflag)
- && ( RELEVANT_IFLAG(tty->termios->c_iflag)
- == RELEVANT_IFLAG(old_termios->c_iflag)))
- return;
-
change_speed(info);
spin_lock_irqsave(&info->lock, flags);
diff --git a/drivers/char/generic_serial.c b/drivers/char/generic_serial.c
index 8ea02755b1c..8facf3e25c4 100644
--- a/drivers/char/generic_serial.c
+++ b/drivers/char/generic_serial.c
@@ -43,16 +43,6 @@ static int gs_debug;
#define func_enter() gs_dprintk (GS_DEBUG_FLOW, "gs: enter %s\n", __FUNCTION__)
#define func_exit() gs_dprintk (GS_DEBUG_FLOW, "gs: exit %s\n", __FUNCTION__)
-#define NEW_WRITE_LOCKING 1
-#if NEW_WRITE_LOCKING
-#define DECL /* Nothing */
-#define LOCKIT mutex_lock(& port->port_write_mutex);
-#define RELEASEIT mutex_unlock(&port->port_write_mutex);
-#else
-#define DECL unsigned long flags;
-#define LOCKIT save_flags (flags);cli ()
-#define RELEASEIT restore_flags (flags)
-#endif
#define RS_EVENT_WRITE_WAKEUP 1
@@ -62,7 +52,6 @@ module_param(gs_debug, int, 0644);
void gs_put_char(struct tty_struct * tty, unsigned char ch)
{
struct gs_port *port;
- DECL
func_enter ();
@@ -75,11 +64,11 @@ void gs_put_char(struct tty_struct * tty, unsigned char ch)
if (! (port->flags & ASYNC_INITIALIZED)) return;
/* Take a lock on the serial tranmit buffer! */
- LOCKIT;
+ mutex_lock(& port->port_write_mutex);
if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1) {
/* Sorry, buffer is full, drop character. Update statistics???? -- REW */
- RELEASEIT;
+ mutex_unlock(&port->port_write_mutex);
return;
}
@@ -87,13 +76,11 @@ void gs_put_char(struct tty_struct * tty, unsigned char ch)
port->xmit_head &= SERIAL_XMIT_SIZE - 1;
port->xmit_cnt++; /* Characters in buffer */
- RELEASEIT;
+ mutex_unlock(&port->port_write_mutex);
func_exit ();
}
-#ifdef NEW_WRITE_LOCKING
-
/*
> Problems to take into account are:
> -1- Interrupts that empty part of the buffer.
@@ -166,90 +153,6 @@ int gs_write(struct tty_struct * tty,
func_exit ();
return total;
}
-#else
-/*
-> Problems to take into account are:
-> -1- Interrupts that empty part of the buffer.
-> -2- page faults on the access to userspace.
-> -3- Other processes that are also trying to do a "write".
-*/
-
-int gs_write(struct tty_struct * tty,
- const unsigned char *buf, int count)
-{
- struct gs_port *port;
- int c, total = 0;
- int t;
- unsigned long flags;
-
- func_enter ();
-
- /* The standard serial driver returns 0 in this case.
- That sounds to me as "No error, I just didn't get to writing any
- bytes. Feel free to try again."
- The "official" way to write n bytes from buf is:
-
- for (nwritten = 0;nwritten < n;nwritten += rv) {
- rv = write (fd, buf+nwritten, n-nwritten);
- if (rv < 0) break; // Error: bail out. //
- }
-
- which will loop endlessly in this case. The manual page for write
- agrees with me. In practise almost everybody writes
- "write (fd, buf,n);" but some people might have had to deal with
- incomplete writes in the past and correctly implemented it by now...
- */
-
- if (!tty) return -EIO;
-
- port = tty->driver_data;
- if (!port || !port->xmit_buf)
- return -EIO;
-
- local_save_flags(flags);
- while (1) {
- cli();
- c = count;
-
- /* This is safe because we "OWN" the "head". Noone else can
- change the "head": we own the port_write_mutex. */
- /* Don't overrun the end of the buffer */
- t = SERIAL_XMIT_SIZE - port->xmit_head;
- if (t < c) c = t;
-
- /* This is safe because the xmit_cnt can only decrease. This
- would increase "t", so we might copy too little chars. */
- /* Don't copy past the "head" of the buffer */
- t = SERIAL_XMIT_SIZE - 1 - port->xmit_cnt;
- if (t < c) c = t;
-
- /* Can't copy more? break out! */
- if (c <= 0) {
- local_restore_flags(flags);
- break;
- }
- memcpy(port->xmit_buf + port->xmit_head, buf, c);
- port->xmit_head = ((port->xmit_head + c) &
- (SERIAL_XMIT_SIZE-1));
- port->xmit_cnt += c;
- local_restore_flags(flags);
- buf += c;
- count -= c;
- total += c;
- }
-
- if (port->xmit_cnt &&
- !tty->stopped &&
- !tty->hw_stopped &&
- !(port->flags & GS_TX_INTEN)) {
- port->flags |= GS_TX_INTEN;
- port->rd->enable_tx_interrupts (port);
- }
- func_exit ();
- return total;
-}
-
-#endif
@@ -737,23 +640,6 @@ void gs_set_termios (struct tty_struct * tty,
gs_dprintk (GS_DEBUG_TERMIOS, "termios structure (%p):\n", tiosp);
}
- /* This is an optimization that is only allowed for dumb cards */
- /* Smart cards require knowledge of iflags and oflags too: that
- might change hardware cooking mode.... */
- if (old_termios) {
- if( (tiosp->c_iflag == old_termios->c_iflag)
- && (tiosp->c_oflag == old_termios->c_oflag)
- && (tiosp->c_cflag == old_termios->c_cflag)
- && (tiosp->c_lflag == old_termios->c_lflag)
- && (tiosp->c_line == old_termios->c_line)
- && (memcmp(tiosp->c_cc, old_termios->c_cc, NCC) == 0)) {
- gs_dprintk(GS_DEBUG_TERMIOS, "gs_set_termios: optimized away\n");
- return /* 0 */;
- }
- } else
- gs_dprintk(GS_DEBUG_TERMIOS, "gs_set_termios: no old_termios: "
- "no optimization\n");
-
if(old_termios && (gs_debug & GS_DEBUG_TERMIOS)) {
if(tiosp->c_iflag != old_termios->c_iflag) printk("c_iflag changed\n");
if(tiosp->c_oflag != old_termios->c_oflag) printk("c_oflag changed\n");
diff --git a/drivers/char/genrtc.c b/drivers/char/genrtc.c
index 9e1fc02967f..69f0a2993af 100644
--- a/drivers/char/genrtc.c
+++ b/drivers/char/genrtc.c
@@ -173,7 +173,6 @@ static void gen_rtc_interrupt(unsigned long arg)
static ssize_t gen_rtc_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
{
- DECLARE_WAITQUEUE(wait, current);
unsigned long data;
ssize_t retval;
@@ -183,18 +182,10 @@ static ssize_t gen_rtc_read(struct file *file, char __user *buf,
if (file->f_flags & O_NONBLOCK && !gen_rtc_irq_data)
return -EAGAIN;
- add_wait_queue(&gen_rtc_wait, &wait);
- retval = -ERESTARTSYS;
-
- while (1) {
- set_current_state(TASK_INTERRUPTIBLE);
- data = xchg(&gen_rtc_irq_data, 0);
- if (data)
- break;
- if (signal_pending(current))
- goto out;
- schedule();
- }
+ retval = wait_event_interruptible(gen_rtc_wait,
+ (data = xchg(&gen_rtc_irq_data, 0)));
+ if (retval)
+ goto out;
/* first test allows optimizer to nuke this case for 32-bit machines */
if (sizeof (int) != sizeof (long) && count == sizeof (unsigned int)) {
@@ -206,10 +197,7 @@ static ssize_t gen_rtc_read(struct file *file, char __user *buf,
retval = put_user(data, (unsigned long __user *)buf) ?:
sizeof(unsigned long);
}
- out:
- __set_current_state(TASK_RUNNING);
- remove_wait_queue(&gen_rtc_wait, &wait);
-
+out:
return retval;
}
diff --git a/drivers/char/hw_random/intel-rng.c b/drivers/char/hw_random/intel-rng.c
index 4ae9811d1a6..753f46052b8 100644
--- a/drivers/char/hw_random/intel-rng.c
+++ b/drivers/char/hw_random/intel-rng.c
@@ -296,12 +296,10 @@ static int __init intel_init_hw_struct(struct intel_rng_hw *intel_rng_hw,
(BIOS_CNTL_LOCK_ENABLE_MASK|BIOS_CNTL_WRITE_ENABLE_MASK))
== BIOS_CNTL_LOCK_ENABLE_MASK) {
static __initdata /*const*/ char warning[] =
- KERN_WARNING PFX "Firmware space is locked read-only. "
- KERN_WARNING PFX "If you can't or\n don't want to "
- KERN_WARNING PFX "disable this in firmware setup, and "
- KERN_WARNING PFX "if\n you are certain that your "
- KERN_WARNING PFX "system has a functional\n RNG, try"
- KERN_WARNING PFX "using the 'no_fwh_detect' option.\n";
+ KERN_WARNING PFX "Firmware space is locked read-only. If you can't or\n"
+ KERN_WARNING PFX "don't want to disable this in firmware setup, and if\n"
+ KERN_WARNING PFX "you are certain that your system has a functional\n"
+ KERN_WARNING PFX "RNG, try using the 'no_fwh_detect' option.\n";
if (no_fwh_detect)
return -ENODEV;
diff --git a/drivers/char/ip2/i2ellis.c b/drivers/char/ip2/i2ellis.c
index dd761a1e4f0..61ef013b844 100644
--- a/drivers/char/ip2/i2ellis.c
+++ b/drivers/char/ip2/i2ellis.c
@@ -43,8 +43,6 @@ static void iiEnableMailIrqIIEX(i2eBordStrPtr);
static void iiWriteMaskII(i2eBordStrPtr, unsigned char);
static void iiWriteMaskIIEX(i2eBordStrPtr, unsigned char);
-static void ii2DelayTimer(unsigned int);
-static void ii2DelayWakeup(unsigned long id);
static void ii2Nop(void);
//***************
@@ -55,8 +53,6 @@ static int ii2Safe; // Safe I/O address for delay routine
static int iiDelayed; // Set when the iiResetDelay function is
// called. Cleared when ANY board is reset.
-static struct timer_list * pDelayTimer; // Used by iiDelayTimer
-static wait_queue_head_t pDelayWait; // Used by iiDelayTimer
static rwlock_t Dl_spinlock;
//********
@@ -86,9 +82,6 @@ static rwlock_t Dl_spinlock;
static void
iiEllisInit(void)
{
- pDelayTimer = kmalloc ( sizeof (struct timer_list), GFP_KERNEL );
- init_timer(pDelayTimer);
- init_waitqueue_head(&pDelayWait);
LOCK_INIT(&Dl_spinlock);
}
@@ -106,7 +99,6 @@ iiEllisInit(void)
static void
iiEllisCleanup(void)
{
- kfree(pDelayTimer);
}
//******************************************************************************
@@ -560,19 +552,6 @@ iiInitialize(i2eBordStrPtr pB)
COMPLETE(pB, I2EE_GOOD);
}
-//=======================================================
-// Delay Routines
-//
-// iiDelayIO
-// iiNop
-//=======================================================
-
-static void
-ii2DelayWakeup(unsigned long id)
-{
- wake_up_interruptible ( &pDelayWait );
-}
-
//******************************************************************************
// Function: ii2DelayTimer(mseconds)
// Parameters: mseconds - number of milliseconds to delay
@@ -594,28 +573,7 @@ ii2DelayWakeup(unsigned long id)
static void
ii2DelayTimer(unsigned int mseconds)
{
- wait_queue_t wait;
-
- init_waitqueue_entry(&wait, current);
-
- init_timer ( pDelayTimer );
-
- add_wait_queue(&pDelayWait, &wait);
-
- set_current_state( TASK_INTERRUPTIBLE );
-
- pDelayTimer->expires = jiffies + ( mseconds + 9 ) / 10;
- pDelayTimer->function = ii2DelayWakeup;
- pDelayTimer->data = 0;
-
- add_timer ( pDelayTimer );
-
- schedule();
-
- set_current_state( TASK_RUNNING );
- remove_wait_queue(&pDelayWait, &wait);
-
- del_timer ( pDelayTimer );
+ msleep_interruptible(mseconds);
}
#if 0
diff --git a/drivers/char/ipmi/Kconfig b/drivers/char/ipmi/Kconfig
index b894f67fdf1..0baa8fab4ea 100644
--- a/drivers/char/ipmi/Kconfig
+++ b/drivers/char/ipmi/Kconfig
@@ -2,11 +2,9 @@
# IPMI device configuration
#
-menu "IPMI"
- depends on HAS_IOMEM
-
-config IPMI_HANDLER
+menuconfig IPMI_HANDLER
tristate 'IPMI top-level message handler'
+ depends on HAS_IOMEM
help
This enables the central IPMI message handler, required for IPMI
to work.
@@ -18,9 +16,10 @@ config IPMI_HANDLER
If unsure, say N.
+if IPMI_HANDLER
+
config IPMI_PANIC_EVENT
bool 'Generate a panic event to all BMCs on a panic'
- depends on IPMI_HANDLER
help
When a panic occurs, this will cause the IPMI message handler to
generate an IPMI event describing the panic to each interface
@@ -40,14 +39,12 @@ config IPMI_PANIC_STRING
config IPMI_DEVICE_INTERFACE
tristate 'Device interface for IPMI'
- depends on IPMI_HANDLER
help
This provides an IOCTL interface to the IPMI message handler so
userland processes may use IPMI. It supports poll() and select().
config IPMI_SI
tristate 'IPMI System Interface handler'
- depends on IPMI_HANDLER
help
Provides a driver for System Interfaces (KCS, SMIC, BT).
Currently, only KCS and SMIC are supported. If
@@ -55,15 +52,13 @@ config IPMI_SI
config IPMI_WATCHDOG
tristate 'IPMI Watchdog Timer'
- depends on IPMI_HANDLER
help
This enables the IPMI watchdog timer.
config IPMI_POWEROFF
tristate 'IPMI Poweroff'
- depends on IPMI_HANDLER
help
This enables a function to power off the system with IPMI if
the IPMI management controller is capable of this.
-endmenu
+endif # IPMI_HANDLER
diff --git a/drivers/char/ipmi/ipmi_poweroff.c b/drivers/char/ipmi/ipmi_poweroff.c
index e02893b7b30..b86186de7f0 100644
--- a/drivers/char/ipmi/ipmi_poweroff.c
+++ b/drivers/char/ipmi/ipmi_poweroff.c
@@ -679,7 +679,7 @@ static int ipmi_poweroff_init (void)
{
int rv;
- printk ("Copyright (C) 2004 MontaVista Software -"
+ printk (KERN_INFO "Copyright (C) 2004 MontaVista Software -"
" IPMI Powerdown via sys_reboot.\n");
if (poweroff_powercycle)
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index 78e1b962fe3..4edfdda0cf9 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -2857,7 +2857,7 @@ static int try_smi_init(struct smi_info *new_smi)
mutex_unlock(&smi_infos_lock);
- printk(" IPMI %s interface initialized\n",si_to_str[new_smi->si_type]);
+ printk(KERN_INFO "IPMI %s interface initialized\n",si_to_str[new_smi->si_type]);
return 0;
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c
index 7b279d1de4a..80940992299 100644
--- a/drivers/char/istallion.c
+++ b/drivers/char/istallion.c
@@ -1753,9 +1753,6 @@ static void stli_settermios(struct tty_struct *tty, struct ktermios *old)
return;
tiosp = tty->termios;
- if ((tiosp->c_cflag == old->c_cflag) &&
- (tiosp->c_iflag == old->c_iflag))
- return;
stli_mkasyport(portp, &aport, tiosp);
stli_cmdwait(brdp, portp, A_SETPORT, &aport, sizeof(asyport_t), 0);
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c
index 90965b4def5..2ce0af1bd58 100644
--- a/drivers/char/keyboard.c
+++ b/drivers/char/keyboard.c
@@ -24,6 +24,7 @@
* 21-08-02: Converted to input API, major cleanup. (Vojtech Pavlik)
*/
+#include <linux/consolemap.h>
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/tty.h>
@@ -308,10 +309,9 @@ static void applkey(struct vc_data *vc, int key, char mode)
* Many other routines do put_queue, but I think either
* they produce ASCII, or they produce some user-assigned
* string, and in both cases we might assume that it is
- * in utf-8 already. UTF-8 is defined for words of up to 31 bits,
- * but we need only 16 bits here
+ * in utf-8 already.
*/
-static void to_utf8(struct vc_data *vc, ushort c)
+static void to_utf8(struct vc_data *vc, uint c)
{
if (c < 0x80)
/* 0******* */
@@ -320,11 +320,21 @@ static void to_utf8(struct vc_data *vc, ushort c)
/* 110***** 10****** */
put_queue(vc, 0xc0 | (c >> 6));
put_queue(vc, 0x80 | (c & 0x3f));
- } else {
+ } else if (c < 0x10000) {
+ if (c >= 0xD800 && c < 0xE000)
+ return;
+ if (c == 0xFFFF)
+ return;
/* 1110**** 10****** 10****** */
put_queue(vc, 0xe0 | (c >> 12));
put_queue(vc, 0x80 | ((c >> 6) & 0x3f));
put_queue(vc, 0x80 | (c & 0x3f));
+ } else if (c < 0x110000) {
+ /* 11110*** 10****** 10****** 10****** */
+ put_queue(vc, 0xf0 | (c >> 18));
+ put_queue(vc, 0x80 | ((c >> 12) & 0x3f));
+ put_queue(vc, 0x80 | ((c >> 6) & 0x3f));
+ put_queue(vc, 0x80 | (c & 0x3f));
}
}
@@ -393,7 +403,7 @@ static unsigned int handle_diacr(struct vc_data *vc, unsigned int ch)
return d;
if (kbd->kbdmode == VC_UNICODE)
- to_utf8(vc, d);
+ to_utf8(vc, conv_8bit_to_uni(d));
else if (d < 0x100)
put_queue(vc, d);
@@ -407,7 +417,7 @@ static void fn_enter(struct vc_data *vc)
{
if (diacr) {
if (kbd->kbdmode == VC_UNICODE)
- to_utf8(vc, diacr);
+ to_utf8(vc, conv_8bit_to_uni(diacr));
else if (diacr < 0x100)
put_queue(vc, diacr);
diacr = 0;
@@ -617,7 +627,7 @@ static void k_unicode(struct vc_data *vc, unsigned int value, char up_flag)
return;
}
if (kbd->kbdmode == VC_UNICODE)
- to_utf8(vc, value);
+ to_utf8(vc, conv_8bit_to_uni(value));
else if (value < 0x100)
put_queue(vc, value);
}
@@ -775,7 +785,7 @@ static void k_shift(struct vc_data *vc, unsigned char value, char up_flag)
/* kludge */
if (up_flag && shift_state != old_state && npadch != -1) {
if (kbd->kbdmode == VC_UNICODE)
- to_utf8(vc, npadch & 0xffff);
+ to_utf8(vc, npadch);
else
put_queue(vc, npadch & 0xff);
npadch = -1;
diff --git a/drivers/char/misc.c b/drivers/char/misc.c
index 4e6fb9651a1..71c8cd7fa15 100644
--- a/drivers/char/misc.c
+++ b/drivers/char/misc.c
@@ -67,25 +67,13 @@ extern int pmu_device_init(void);
#ifdef CONFIG_PROC_FS
static void *misc_seq_start(struct seq_file *seq, loff_t *pos)
{
- struct miscdevice *p;
- loff_t off = 0;
-
mutex_lock(&misc_mtx);
- list_for_each_entry(p, &misc_list, list) {
- if (*pos == off++)
- return p;
- }
- return NULL;
+ return seq_list_start(&misc_list, *pos);
}
static void *misc_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{
- struct list_head *n = ((struct miscdevice *)v)->list.next;
-
- ++*pos;
-
- return (n != &misc_list) ? list_entry(n, struct miscdevice, list)
- : NULL;
+ return seq_list_next(v, &misc_list, pos);
}
static void misc_seq_stop(struct seq_file *seq, void *v)
@@ -95,7 +83,7 @@ static void misc_seq_stop(struct seq_file *seq, void *v)
static int misc_seq_show(struct seq_file *seq, void *v)
{
- const struct miscdevice *p = v;
+ const struct miscdevice *p = list_entry(v, struct miscdevice, list);
seq_printf(seq, "%3i %s\n", p->minor, p->name ? p->name : "");
return 0;
diff --git a/drivers/char/mspec.c b/drivers/char/mspec.c
index 7ac30612068..c716ef0dd37 100644
--- a/drivers/char/mspec.c
+++ b/drivers/char/mspec.c
@@ -265,7 +265,7 @@ mspec_mmap(struct file *file, struct vm_area_struct *vma, int type)
vdata->refcnt = ATOMIC_INIT(1);
vma->vm_private_data = vdata;
- vma->vm_flags |= (VM_IO | VM_LOCKED | VM_RESERVED | VM_PFNMAP);
+ vma->vm_flags |= (VM_IO | VM_RESERVED | VM_PFNMAP);
if (vdata->type == MSPEC_FETCHOP || vdata->type == MSPEC_UNCACHED)
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
vma->vm_ops = &mspec_vm_ops;
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c
index 5953a45d7e9..2aee3fef041 100644
--- a/drivers/char/mxser.c
+++ b/drivers/char/mxser.c
@@ -90,8 +90,6 @@
#define UART_MCR_AFE 0x20
#define UART_LSR_SPECIAL 0x1E
-#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK|\
- IXON|IXOFF))
#define IRQ_T(info) ((info->flags & ASYNC_SHARE_IRQ) ? IRQF_SHARED : IRQF_DISABLED)
@@ -1729,16 +1727,12 @@ static void mxser_set_termios(struct tty_struct *tty, struct ktermios *old_termi
struct mxser_struct *info = tty->driver_data;
unsigned long flags;
- if ((tty->termios->c_cflag != old_termios->c_cflag) ||
- (RELEVANT_IFLAG(tty->termios->c_iflag) != RELEVANT_IFLAG(old_termios->c_iflag))) {
+ mxser_change_speed(info, old_termios);
- mxser_change_speed(info, old_termios);
-
- if ((old_termios->c_cflag & CRTSCTS) &&
- !(tty->termios->c_cflag & CRTSCTS)) {
- tty->hw_stopped = 0;
- mxser_start(tty);
- }
+ if ((old_termios->c_cflag & CRTSCTS) &&
+ !(tty->termios->c_cflag & CRTSCTS)) {
+ tty->hw_stopped = 0;
+ mxser_start(tty);
}
/* Handle sw stopped */
diff --git a/drivers/char/mxser_new.c b/drivers/char/mxser_new.c
index 6cde448cd5b..6a563932ba1 100644
--- a/drivers/char/mxser_new.c
+++ b/drivers/char/mxser_new.c
@@ -72,8 +72,6 @@
#define UART_MCR_AFE 0x20
#define UART_LSR_SPECIAL 0x1E
-#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK|\
- IXON|IXOFF))
#define C168_ASIC_ID 1
#define C104_ASIC_ID 2
@@ -1560,7 +1558,7 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp)
return -EFAULT;
return 0;
case MOXA_ASPP_MON_EXT: {
- int status, p, shiftbit;
+ int p, shiftbit;
unsigned long opmode;
unsigned cflag, iflag;
@@ -1990,18 +1988,14 @@ static void mxser_set_termios(struct tty_struct *tty, struct ktermios *old_termi
struct mxser_port *info = tty->driver_data;
unsigned long flags;
- if ((tty->termios->c_cflag != old_termios->c_cflag) ||
- (RELEVANT_IFLAG(tty->termios->c_iflag) != RELEVANT_IFLAG(old_termios->c_iflag))) {
-
- spin_lock_irqsave(&info->slock, flags);
- mxser_change_speed(info, old_termios);
- spin_unlock_irqrestore(&info->slock, flags);
+ spin_lock_irqsave(&info->slock, flags);
+ mxser_change_speed(info, old_termios);
+ spin_unlock_irqrestore(&info->slock, flags);
- if ((old_termios->c_cflag & CRTSCTS) &&
- !(tty->termios->c_cflag & CRTSCTS)) {
- tty->hw_stopped = 0;
- mxser_start(tty);
- }
+ if ((old_termios->c_cflag & CRTSCTS) &&
+ !(tty->termios->c_cflag & CRTSCTS)) {
+ tty->hw_stopped = 0;
+ mxser_start(tty);
}
/* Handle sw stopped */
diff --git a/drivers/char/n_hdlc.c b/drivers/char/n_hdlc.c
index 337a87f86a3..e8332f305d7 100644
--- a/drivers/char/n_hdlc.c
+++ b/drivers/char/n_hdlc.c
@@ -400,7 +400,12 @@ static void n_hdlc_send_frames(struct n_hdlc *n_hdlc, struct tty_struct *tty)
/* Send the next block of data to device */
tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);
actual = tty->driver->write(tty, tbuf->buf, tbuf->count);
-
+
+ /* rollback was possible and has been done */
+ if (actual == -ERESTARTSYS) {
+ n_hdlc->tbuf = tbuf;
+ break;
+ }
/* if transmit error, throw frame away by */
/* pretending it was accepted by driver */
if (actual < 0)
@@ -780,13 +785,14 @@ static unsigned int n_hdlc_tty_poll(struct tty_struct *tty, struct file *filp,
poll_wait(filp, &tty->write_wait, wait);
/* set bits for operations that won't block */
- if(n_hdlc->rx_buf_list.head)
+ if (n_hdlc->rx_buf_list.head)
mask |= POLLIN | POLLRDNORM; /* readable */
if (test_bit(TTY_OTHER_CLOSED, &tty->flags))
mask |= POLLHUP;
- if(tty_hung_up_p(filp))
+ if (tty_hung_up_p(filp))
mask |= POLLHUP;
- if(n_hdlc->tx_free_buf_list.head)
+ if (!tty_is_writelocked(tty) &&
+ n_hdlc->tx_free_buf_list.head)
mask |= POLLOUT | POLLWRNORM; /* writable */
}
return mask;
@@ -861,7 +867,7 @@ static void n_hdlc_buf_put(struct n_hdlc_buf_list *list,
spin_lock_irqsave(&list->spinlock,flags);
buf->link=NULL;
- if(list->tail)
+ if (list->tail)
list->tail->link = buf;
else
list->head = buf;
diff --git a/drivers/char/n_r3964.c b/drivers/char/n_r3964.c
index 14557a4822c..6b918b80f73 100644
--- a/drivers/char/n_r3964.c
+++ b/drivers/char/n_r3964.c
@@ -1071,8 +1071,6 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file,
struct r3964_client_info *pClient;
struct r3964_message *pMsg;
struct r3964_client_message theMsg;
- DECLARE_WAITQUEUE(wait, current);
-
int count;
TRACE_L("read()");
@@ -1086,16 +1084,8 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file,
return -EAGAIN;
}
/* block until there is a message: */
- add_wait_queue(&pInfo->read_wait, &wait);
-repeat:
- __set_current_state(TASK_INTERRUPTIBLE);
- pMsg = remove_msg(pInfo, pClient);
- if (!pMsg && !signal_pending(current)) {
- schedule();
- goto repeat;
- }
- __set_current_state(TASK_RUNNING);
- remove_wait_queue(&pInfo->read_wait, &wait);
+ wait_event_interruptible(pInfo->read_wait,
+ (pMsg = remove_msg(pInfo, pClient)));
}
/* If we still haven't got a message, we must have been signalled */
diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c
index 154f42203b0..03805691193 100644
--- a/drivers/char/n_tty.c
+++ b/drivers/char/n_tty.c
@@ -45,6 +45,8 @@
#include <linux/slab.h>
#include <linux/poll.h>
#include <linux/bitops.h>
+#include <linux/audit.h>
+#include <linux/file.h>
#include <asm/uaccess.h>
#include <asm/system.h>
@@ -78,6 +80,13 @@ static inline void free_buf(unsigned char *buf)
free_page((unsigned long) buf);
}
+static inline int tty_put_user(struct tty_struct *tty, unsigned char x,
+ unsigned char __user *ptr)
+{
+ tty_audit_add_data(tty, &x, 1);
+ return put_user(x, ptr);
+}
+
/**
* n_tty_set__room - receive space
* @tty: terminal
@@ -1153,6 +1162,7 @@ static int copy_from_read_buf(struct tty_struct *tty,
if (n) {
retval = copy_to_user(*b, &tty->read_buf[tty->read_tail], n);
n -= retval;
+ 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;
@@ -1279,7 +1289,7 @@ do_it_again:
break;
cs = tty->link->ctrl_status;
tty->link->ctrl_status = 0;
- if (put_user(cs, b++)) {
+ if (tty_put_user(tty, cs, b++)) {
retval = -EFAULT;
b--;
break;
@@ -1321,7 +1331,7 @@ do_it_again:
/* Deal with packet mode. */
if (tty->packet && b == buf) {
- if (put_user(TIOCPKT_DATA, b++)) {
+ if (tty_put_user(tty, TIOCPKT_DATA, b++)) {
retval = -EFAULT;
b--;
break;
@@ -1352,15 +1362,17 @@ do_it_again:
spin_unlock_irqrestore(&tty->read_lock, flags);
if (!eol || (c != __DISABLED_CHAR)) {
- if (put_user(c, b++)) {
+ if (tty_put_user(tty, c, b++)) {
retval = -EFAULT;
b--;
break;
}
nr--;
}
- if (eol)
+ if (eol) {
+ tty_audit_push(tty);
break;
+ }
}
if (retval)
break;
@@ -1538,7 +1550,8 @@ static unsigned int normal_poll(struct tty_struct * tty, struct file * file, pol
else
tty->minimum_to_wake = 1;
}
- if (tty->driver->chars_in_buffer(tty) < WAKEUP_CHARS &&
+ if (!tty_is_writelocked(tty) &&
+ tty->driver->chars_in_buffer(tty) < WAKEUP_CHARS &&
tty->driver->write_room(tty) > 0)
mask |= POLLOUT | POLLWRNORM;
return mask;
diff --git a/drivers/char/nvram.c b/drivers/char/nvram.c
index 204deaa0de8..98dec380af4 100644
--- a/drivers/char/nvram.c
+++ b/drivers/char/nvram.c
@@ -42,19 +42,12 @@
#define PC 1
#define ATARI 2
-#define COBALT 3
/* select machine configuration */
#if defined(CONFIG_ATARI)
# define MACH ATARI
#elif defined(__i386__) || defined(__x86_64__) || defined(__arm__) /* and others?? */
-#define MACH PC
-# if defined(CONFIG_COBALT)
-# include <linux/cobalt-nvram.h>
-# define MACH COBALT
-# else
-# define MACH PC
-# endif
+# define MACH PC
#else
# error Cannot build nvram driver for this machine configuration.
#endif
@@ -76,18 +69,6 @@
#endif
-#if MACH == COBALT
-
-#define CHECK_DRIVER_INIT() 1
-
-#define NVRAM_BYTES (128-NVRAM_FIRST_BYTE)
-
-#define mach_check_checksum cobalt_check_checksum
-#define mach_set_checksum cobalt_set_checksum
-#define mach_proc_infos cobalt_proc_infos
-
-#endif
-
#if MACH == ATARI
/* Special parameters for RTC in Atari machines */
@@ -604,177 +585,6 @@ pc_proc_infos(unsigned char *nvram, char *buffer, int *len,
#endif /* MACH == PC */
-#if MACH == COBALT
-
-/* the cobalt CMOS has a wider range of its checksum */
-static int cobalt_check_checksum(void)
-{
- int i;
- unsigned short sum = 0;
- unsigned short expect;
-
- for (i = COBT_CMOS_CKS_START; i <= COBT_CMOS_CKS_END; ++i) {
- if ((i == COBT_CMOS_CHECKSUM) || (i == (COBT_CMOS_CHECKSUM+1)))
- continue;
-
- sum += __nvram_read_byte(i);
- }
- expect = __nvram_read_byte(COBT_CMOS_CHECKSUM) << 8 |
- __nvram_read_byte(COBT_CMOS_CHECKSUM+1);
- return ((sum & 0xffff) == expect);
-}
-
-static void cobalt_set_checksum(void)
-{
- int i;
- unsigned short sum = 0;
-
- for (i = COBT_CMOS_CKS_START; i <= COBT_CMOS_CKS_END; ++i) {
- if ((i == COBT_CMOS_CHECKSUM) || (i == (COBT_CMOS_CHECKSUM+1)))
- continue;
-
- sum += __nvram_read_byte(i);
- }
-
- __nvram_write_byte(sum >> 8, COBT_CMOS_CHECKSUM);
- __nvram_write_byte(sum & 0xff, COBT_CMOS_CHECKSUM+1);
-}
-
-#ifdef CONFIG_PROC_FS
-
-static int cobalt_proc_infos(unsigned char *nvram, char *buffer, int *len,
- off_t *begin, off_t offset, int size)
-{
- int i;
- unsigned int checksum;
- unsigned int flags;
- char sernum[14];
- char *key = "cNoEbTaWlOtR!";
- unsigned char bto_csum;
-
- spin_lock_irq(&rtc_lock);
- checksum = __nvram_check_checksum();
- spin_unlock_irq(&rtc_lock);
-
- PRINT_PROC("Checksum status: %svalid\n", checksum ? "" : "not ");
-
- flags = nvram[COBT_CMOS_FLAG_BYTE_0] << 8
- | nvram[COBT_CMOS_FLAG_BYTE_1];
-
- PRINT_PROC("Console: %s\n",
- flags & COBT_CMOS_CONSOLE_FLAG ? "on": "off");
-
- PRINT_PROC("Firmware Debug Messages: %s\n",
- flags & COBT_CMOS_DEBUG_FLAG ? "on": "off");
-
- PRINT_PROC("Auto Prompt: %s\n",
- flags & COBT_CMOS_AUTO_PROMPT_FLAG ? "on": "off");
-
- PRINT_PROC("Shutdown Status: %s\n",
- flags & COBT_CMOS_CLEAN_BOOT_FLAG ? "clean": "dirty");
-
- PRINT_PROC("Hardware Probe: %s\n",
- flags & COBT_CMOS_HW_NOPROBE_FLAG ? "partial": "full");
-
- PRINT_PROC("System Fault: %sdetected\n",
- flags & COBT_CMOS_SYSFAULT_FLAG ? "": "not ");
-
- PRINT_PROC("Panic on OOPS: %s\n",
- flags & COBT_CMOS_OOPSPANIC_FLAG ? "yes": "no");
-
- PRINT_PROC("Delayed Cache Initialization: %s\n",
- flags & COBT_CMOS_DELAY_CACHE_FLAG ? "yes": "no");
-
- PRINT_PROC("Show Logo at Boot: %s\n",
- flags & COBT_CMOS_NOLOGO_FLAG ? "no": "yes");
-
- PRINT_PROC("Boot Method: ");
- switch (nvram[COBT_CMOS_BOOT_METHOD]) {
- case COBT_CMOS_BOOT_METHOD_DISK:
- PRINT_PROC("disk\n");
- break;
-
- case COBT_CMOS_BOOT_METHOD_ROM:
- PRINT_PROC("rom\n");
- break;
-
- case COBT_CMOS_BOOT_METHOD_NET:
- PRINT_PROC("net\n");
- break;
-
- default:
- PRINT_PROC("unknown\n");
- break;
- }
-
- PRINT_PROC("Primary Boot Device: %d:%d\n",
- nvram[COBT_CMOS_BOOT_DEV0_MAJ],
- nvram[COBT_CMOS_BOOT_DEV0_MIN] );
- PRINT_PROC("Secondary Boot Device: %d:%d\n",
- nvram[COBT_CMOS_BOOT_DEV1_MAJ],
- nvram[COBT_CMOS_BOOT_DEV1_MIN] );
- PRINT_PROC("Tertiary Boot Device: %d:%d\n",
- nvram[COBT_CMOS_BOOT_DEV2_MAJ],
- nvram[COBT_CMOS_BOOT_DEV2_MIN] );
-
- PRINT_PROC("Uptime: %d\n",
- nvram[COBT_CMOS_UPTIME_0] << 24 |
- nvram[COBT_CMOS_UPTIME_1] << 16 |
- nvram[COBT_CMOS_UPTIME_2] << 8 |
- nvram[COBT_CMOS_UPTIME_3]);
-
- PRINT_PROC("Boot Count: %d\n",
- nvram[COBT_CMOS_BOOTCOUNT_0] << 24 |
- nvram[COBT_CMOS_BOOTCOUNT_1] << 16 |
- nvram[COBT_CMOS_BOOTCOUNT_2] << 8 |
- nvram[COBT_CMOS_BOOTCOUNT_3]);
-
- /* 13 bytes of serial num */
- for (i=0 ; i<13 ; i++) {
- sernum[i] = nvram[COBT_CMOS_SYS_SERNUM_0 + i];
- }
- sernum[13] = '\0';
-
- checksum = 0;
- for (i=0 ; i<13 ; i++) {
- checksum += sernum[i] ^ key[i];
- }
- checksum = ((checksum & 0x7f) ^ (0xd6)) & 0xff;
-
- PRINT_PROC("Serial Number: %s", sernum);
- if (checksum != nvram[COBT_CMOS_SYS_SERNUM_CSUM]) {
- PRINT_PROC(" (invalid checksum)");
- }
- PRINT_PROC("\n");
-
- PRINT_PROC("Rom Revison: %d.%d.%d\n", nvram[COBT_CMOS_ROM_REV_MAJ],
- nvram[COBT_CMOS_ROM_REV_MIN], nvram[COBT_CMOS_ROM_REV_REV]);
-
- PRINT_PROC("BTO Server: %d.%d.%d.%d", nvram[COBT_CMOS_BTO_IP_0],
- nvram[COBT_CMOS_BTO_IP_1], nvram[COBT_CMOS_BTO_IP_2],
- nvram[COBT_CMOS_BTO_IP_3]);
- bto_csum = nvram[COBT_CMOS_BTO_IP_0] + nvram[COBT_CMOS_BTO_IP_1]
- + nvram[COBT_CMOS_BTO_IP_2] + nvram[COBT_CMOS_BTO_IP_3];
- if (bto_csum != nvram[COBT_CMOS_BTO_IP_CSUM]) {
- PRINT_PROC(" (invalid checksum)");
- }
- PRINT_PROC("\n");
-
- if (flags & COBT_CMOS_VERSION_FLAG
- && nvram[COBT_CMOS_VERSION] >= COBT_CMOS_VER_BTOCODE) {
- PRINT_PROC("BTO Code: 0x%x\n",
- nvram[COBT_CMOS_BTO_CODE_0] << 24 |
- nvram[COBT_CMOS_BTO_CODE_1] << 16 |
- nvram[COBT_CMOS_BTO_CODE_2] << 8 |
- nvram[COBT_CMOS_BTO_CODE_3]);
- }
-
- return 1;
-}
-#endif /* CONFIG_PROC_FS */
-
-#endif /* MACH == COBALT */
-
#if MACH == ATARI
static int
diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c
index a3fd7e7ba5a..0270080ff0c 100644
--- a/drivers/char/rocket.c
+++ b/drivers/char/rocket.c
@@ -1702,7 +1702,8 @@ static int rp_write(struct tty_struct *tty,
if (count <= 0 || rocket_paranoia_check(info, "rp_write"))
return 0;
- mutex_lock_interruptible(&info->write_mtx);
+ if (mutex_lock_interruptible(&info->write_mtx))
+ return -ERESTARTSYS;
#ifdef ROCKET_DEBUG_WRITE
printk(KERN_INFO "rp_write %d chars...", count);
diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c
index 20380a2c4de..22cf7aa56cc 100644
--- a/drivers/char/rtc.c
+++ b/drivers/char/rtc.c
@@ -1159,7 +1159,8 @@ static void rtc_dropped_irq(unsigned long data)
spin_unlock_irq(&rtc_lock);
- printk(KERN_WARNING "rtc: lost some interrupts at %ldHz.\n", freq);
+ if (printk_ratelimit())
+ printk(KERN_WARNING "rtc: lost some interrupts at %ldHz.\n", freq);
/* Now we have new data */
wake_up_interruptible(&rtc_wait);
diff --git a/drivers/char/selection.c b/drivers/char/selection.c
index a69f094d1ed..d63f5ccc29e 100644
--- a/drivers/char/selection.c
+++ b/drivers/char/selection.c
@@ -20,6 +20,7 @@
#include <asm/uaccess.h>
+#include <linux/kbd_kern.h>
#include <linux/vt_kern.h>
#include <linux/consolemap.h>
#include <linux/selection.h>
@@ -34,6 +35,7 @@ extern void poke_blanked_console(void);
/* Variables for selection control. */
/* Use a dynamic buffer, instead of static (Dec 1994) */
struct vc_data *sel_cons; /* must not be deallocated */
+static int use_unicode;
static volatile int sel_start = -1; /* cleared by clear_selection */
static int sel_end;
static int sel_buffer_lth;
@@ -54,10 +56,11 @@ static inline void highlight_pointer(const int where)
complement_pos(sel_cons, where);
}
-static unsigned char
+static u16
sel_pos(int n)
{
- return inverse_translate(sel_cons, screen_glyph(sel_cons, n));
+ return inverse_translate(sel_cons, screen_glyph(sel_cons, n),
+ use_unicode);
}
/* remove the current selection highlight, if any,
@@ -86,8 +89,8 @@ static u32 inwordLut[8]={
0xFF7FFFFF /* latin-1 accented letters, not division sign */
};
-static inline int inword(const unsigned char c) {
- return ( inwordLut[c>>5] >> (c & 0x1F) ) & 1;
+static inline int inword(const u16 c) {
+ return c > 0xff || (( inwordLut[c>>5] >> (c & 0x1F) ) & 1);
}
/* set inwordLut contents. Invoked by ioctl(). */
@@ -108,13 +111,36 @@ static inline unsigned short limit(const unsigned short v, const unsigned short
return (v > u) ? u : v;
}
+/* stores the char in UTF8 and returns the number of bytes used (1-3) */
+static int store_utf8(u16 c, char *p)
+{
+ if (c < 0x80) {
+ /* 0******* */
+ p[0] = c;
+ return 1;
+ } else if (c < 0x800) {
+ /* 110***** 10****** */
+ p[0] = 0xc0 | (c >> 6);
+ p[1] = 0x80 | (c & 0x3f);
+ return 2;
+ } else {
+ /* 1110**** 10****** 10****** */
+ p[0] = 0xe0 | (c >> 12);
+ p[1] = 0x80 | ((c >> 6) & 0x3f);
+ p[2] = 0x80 | (c & 0x3f);
+ return 3;
+ }
+}
+
/* set the current selection. Invoked by ioctl() or by kernel code. */
int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *tty)
{
struct vc_data *vc = vc_cons[fg_console].d;
int sel_mode, new_sel_start, new_sel_end, spc;
char *bp, *obp;
- int i, ps, pe;
+ int i, ps, pe, multiplier;
+ u16 c;
+ struct kbd_struct *kbd = kbd_table + fg_console;
poke_blanked_console();
@@ -158,6 +184,7 @@ int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *t
clear_selection();
sel_cons = vc_cons[fg_console].d;
}
+ use_unicode = kbd && kbd->kbdmode == VC_UNICODE;
switch (sel_mode)
{
@@ -240,7 +267,8 @@ int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *t
sel_end = new_sel_end;
/* Allocate a new buffer before freeing the old one ... */
- bp = kmalloc((sel_end-sel_start)/2+1, GFP_KERNEL);
+ multiplier = use_unicode ? 3 : 1; /* chars can take up to 3 bytes */
+ bp = kmalloc((sel_end-sel_start)/2*multiplier+1, GFP_KERNEL);
if (!bp) {
printk(KERN_WARNING "selection: kmalloc() failed\n");
clear_selection();
@@ -251,8 +279,12 @@ int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *t
obp = bp;
for (i = sel_start; i <= sel_end; i += 2) {
- *bp = sel_pos(i);
- if (!isspace(*bp++))
+ c = sel_pos(i);
+ if (use_unicode)
+ bp += store_utf8(c, bp);
+ else
+ *bp++ = c;
+ if (!isspace(c))
obp = bp;
if (! ((i + 2) % vc->vc_size_row)) {
/* strip trailing blanks from line and add newline,
diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c
index 3ef593a9015..73037a4d3c5 100644
--- a/drivers/char/sonypi.c
+++ b/drivers/char/sonypi.c
@@ -885,53 +885,6 @@ found:
return IRQ_HANDLED;
}
-/* External camera command (exported to the motion eye v4l driver) */
-int sonypi_camera_command(int command, u8 value)
-{
- if (!camera)
- return -EIO;
-
- mutex_lock(&sonypi_device.lock);
-
- switch (command) {
- case SONYPI_COMMAND_SETCAMERA:
- if (value)
- sonypi_camera_on();
- else
- sonypi_camera_off();
- break;
- case SONYPI_COMMAND_SETCAMERABRIGHTNESS:
- sonypi_set(SONYPI_CAMERA_BRIGHTNESS, value);
- break;
- case SONYPI_COMMAND_SETCAMERACONTRAST:
- sonypi_set(SONYPI_CAMERA_CONTRAST, value);
- break;
- case SONYPI_COMMAND_SETCAMERAHUE:
- sonypi_set(SONYPI_CAMERA_HUE, value);
- break;
- case SONYPI_COMMAND_SETCAMERACOLOR:
- sonypi_set(SONYPI_CAMERA_COLOR, value);
- break;
- case SONYPI_COMMAND_SETCAMERASHARPNESS:
- sonypi_set(SONYPI_CAMERA_SHARPNESS, value);
- break;
- case SONYPI_COMMAND_SETCAMERAPICTURE:
- sonypi_set(SONYPI_CAMERA_PICTURE, value);
- break;
- case SONYPI_COMMAND_SETCAMERAAGC:
- sonypi_set(SONYPI_CAMERA_AGC, value);
- break;
- default:
- printk(KERN_ERR "sonypi: sonypi_camera_command invalid: %d\n",
- command);
- break;
- }
- mutex_unlock(&sonypi_device.lock);
- return 0;
-}
-
-EXPORT_SYMBOL(sonypi_camera_command);
-
static int sonypi_misc_fasync(int fd, struct file *filp, int on)
{
int retval;
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c
index f02a0795983..f53e51ddb9d 100644
--- a/drivers/char/synclink.c
+++ b/drivers/char/synclink.c
@@ -160,8 +160,6 @@ typedef struct _DMABUFFERENTRY
#define IO_PIN_SHUTDOWN_LIMIT 100
-#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
-
struct _input_signal_events {
int ri_up;
int ri_down;
@@ -3064,12 +3062,6 @@ static void mgsl_set_termios(struct tty_struct *tty, struct ktermios *old_termio
printk("%s(%d):mgsl_set_termios %s\n", __FILE__,__LINE__,
tty->driver->name );
- /* just return if nothing has changed */
- if ((tty->termios->c_cflag == old_termios->c_cflag)
- && (RELEVANT_IFLAG(tty->termios->c_iflag)
- == RELEVANT_IFLAG(old_termios->c_iflag)))
- return;
-
mgsl_change_params(info);
/* Handle transition to B0 status */
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c
index 02b49bc0002..428b514201f 100644
--- a/drivers/char/synclink_gt.c
+++ b/drivers/char/synclink_gt.c
@@ -144,8 +144,6 @@ MODULE_PARM_DESC(dosyncppp, "Enable synchronous net device, 0=disable 1=enable")
/*
* tty support and callbacks
*/
-#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
-
static struct tty_driver *serial_driver;
static int open(struct tty_struct *tty, struct file * filp);
@@ -823,12 +821,6 @@ static void set_termios(struct tty_struct *tty, struct ktermios *old_termios)
DBGINFO(("%s set_termios\n", tty->driver->name));
- /* just return if nothing has changed */
- if ((tty->termios->c_cflag == old_termios->c_cflag)
- && (RELEVANT_IFLAG(tty->termios->c_iflag)
- == RELEVANT_IFLAG(old_termios->c_iflag)))
- return;
-
change_params(info);
/* Handle transition to B0 status */
diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c
index ef93d055bdd..a65407b3207 100644
--- a/drivers/char/synclinkmp.c
+++ b/drivers/char/synclinkmp.c
@@ -135,8 +135,6 @@ typedef struct _SCADESC_EX
#define IO_PIN_SHUTDOWN_LIMIT 100
-#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
-
struct _input_signal_events {
int ri_up;
int ri_down;
@@ -927,12 +925,6 @@ static void set_termios(struct tty_struct *tty, struct ktermios *old_termios)
printk("%s(%d):%s set_termios()\n", __FILE__,__LINE__,
tty->driver->name );
- /* just return if nothing has changed */
- if ((tty->termios->c_cflag == old_termios->c_cflag)
- && (RELEVANT_IFLAG(tty->termios->c_iflag)
- == RELEVANT_IFLAG(old_termios->c_iflag)))
- return;
-
change_params(info);
/* Handle transition to B0 status */
diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig
index dc4e1ff7f56..8f3f7620f95 100644
--- a/drivers/char/tpm/Kconfig
+++ b/drivers/char/tpm/Kconfig
@@ -2,11 +2,9 @@
# TPM device configuration
#
-menu "TPM devices"
- depends on HAS_IOMEM
-
-config TCG_TPM
+menuconfig TCG_TPM
tristate "TPM Hardware Support"
+ depends on HAS_IOMEM
depends on EXPERIMENTAL
---help---
If you have a TPM security chip in your system, which
@@ -21,9 +19,11 @@ config TCG_TPM
Note: For more TPM drivers enable CONFIG_PNP, CONFIG_ACPI
and CONFIG_PNPACPI.
+if TCG_TPM
+
config TCG_TIS
tristate "TPM Interface Specification 1.2 Interface"
- depends on TCG_TPM && PNPACPI
+ depends on PNPACPI
---help---
If you have a TPM security chip that is compliant with the
TCG TIS 1.2 TPM specification say Yes and it will be accessible
@@ -32,7 +32,7 @@ config TCG_TIS
config TCG_NSC
tristate "National Semiconductor TPM Interface"
- depends on TCG_TPM && PNPACPI
+ depends on PNPACPI
---help---
If you have a TPM security chip from National Semiconductor
say Yes and it will be accessible from within Linux. To
@@ -41,7 +41,6 @@ config TCG_NSC
config TCG_ATMEL
tristate "Atmel TPM Interface"
- depends on TCG_TPM
---help---
If you have a TPM security chip from Atmel say Yes and it
will be accessible from within Linux. To compile this driver
@@ -49,7 +48,7 @@ config TCG_ATMEL
config TCG_INFINEON
tristate "Infineon Technologies TPM Interface"
- depends on TCG_TPM && PNPACPI
+ depends on PNPACPI
---help---
If you have a TPM security chip from Infineon Technologies
(either SLD 9630 TT 1.1 or SLB 9635 TT 1.2) say Yes and it
@@ -59,5 +58,4 @@ config TCG_INFINEON
Further information on this driver and the supported hardware
can be found at http://www.prosec.rub.de/tpm
-endmenu
-
+endif # TCG_TPM
diff --git a/drivers/char/tty_audit.c b/drivers/char/tty_audit.c
new file mode 100644
index 00000000000..d222012c1b0
--- /dev/null
+++ b/drivers/char/tty_audit.c
@@ -0,0 +1,345 @@
+/*
+ * Creating audit events from TTY input.
+ *
+ * Copyright (C) 2007 Red Hat, Inc. All rights reserved. This copyrighted
+ * material is made available to anyone wishing to use, modify, copy, or
+ * redistribute it subject to the terms and conditions of the GNU General
+ * Public License v.2.
+ *
+ * Authors: Miloslav Trmac <mitr@redhat.com>
+ */
+
+#include <linux/audit.h>
+#include <linux/file.h>
+#include <linux/tty.h>
+
+struct tty_audit_buf {
+ atomic_t count;
+ struct mutex mutex; /* Protects all data below */
+ int major, minor; /* The TTY which the data is from */
+ unsigned icanon:1;
+ size_t valid;
+ unsigned char *data; /* Allocated size N_TTY_BUF_SIZE */
+};
+
+static struct tty_audit_buf *tty_audit_buf_alloc(int major, int minor,
+ int icanon)
+{
+ struct tty_audit_buf *buf;
+
+ buf = kmalloc(sizeof (*buf), GFP_KERNEL);
+ if (!buf)
+ goto err;
+ if (PAGE_SIZE != N_TTY_BUF_SIZE)
+ buf->data = kmalloc(N_TTY_BUF_SIZE, GFP_KERNEL);
+ else
+ buf->data = (unsigned char *)__get_free_page(GFP_KERNEL);
+ if (!buf->data)
+ goto err_buf;
+ atomic_set(&buf->count, 1);
+ mutex_init(&buf->mutex);
+ buf->major = major;
+ buf->minor = minor;
+ buf->icanon = icanon;
+ buf->valid = 0;
+ return buf;
+
+err_buf:
+ kfree(buf);
+err:
+ return NULL;
+}
+
+static void tty_audit_buf_free(struct tty_audit_buf *buf)
+{
+ WARN_ON(buf->valid != 0);
+ if (PAGE_SIZE != N_TTY_BUF_SIZE)
+ kfree(buf->data);
+ else
+ free_page((unsigned long)buf->data);
+ kfree(buf);
+}
+
+static void tty_audit_buf_put(struct tty_audit_buf *buf)
+{
+ if (atomic_dec_and_test(&buf->count))
+ tty_audit_buf_free(buf);
+}
+
+/**
+ * tty_audit_buf_push - Push buffered data out
+ *
+ * Generate an audit message from the contents of @buf, which is owned by
+ * @tsk with @loginuid. @buf->mutex must be locked.
+ */
+static void tty_audit_buf_push(struct task_struct *tsk, uid_t loginuid,
+ struct tty_audit_buf *buf)
+{
+ struct audit_buffer *ab;
+
+ if (buf->valid == 0)
+ return;
+ if (audit_enabled == 0)
+ return;
+ ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_TTY);
+ if (ab) {
+ char name[sizeof(tsk->comm)];
+
+ audit_log_format(ab, "tty pid=%u uid=%u auid=%u major=%d "
+ "minor=%d comm=", tsk->pid, tsk->uid,
+ loginuid, buf->major, buf->minor);
+ get_task_comm(name, tsk);
+ audit_log_untrustedstring(ab, name);
+ audit_log_format(ab, " data=");
+ audit_log_n_untrustedstring(ab, buf->valid, buf->data);
+ audit_log_end(ab);
+ }
+ buf->valid = 0;
+}
+
+/**
+ * tty_audit_buf_push_current - Push buffered data out
+ *
+ * Generate an audit message from the contents of @buf, which is owned by
+ * the current task. @buf->mutex must be locked.
+ */
+static void tty_audit_buf_push_current(struct tty_audit_buf *buf)
+{
+ tty_audit_buf_push(current, audit_get_loginuid(current->audit_context),
+ buf);
+}
+
+/**
+ * tty_audit_exit - Handle a task exit
+ *
+ * Make sure all buffered data is written out and deallocate the buffer.
+ * Only needs to be called if current->signal->tty_audit_buf != %NULL.
+ */
+void tty_audit_exit(void)
+{
+ struct tty_audit_buf *buf;
+
+ spin_lock_irq(&current->sighand->siglock);
+ buf = current->signal->tty_audit_buf;
+ current->signal->tty_audit_buf = NULL;
+ spin_unlock_irq(&current->sighand->siglock);
+ if (!buf)
+ return;
+
+ mutex_lock(&buf->mutex);
+ tty_audit_buf_push_current(buf);
+ mutex_unlock(&buf->mutex);
+
+ tty_audit_buf_put(buf);
+}
+
+/**
+ * tty_audit_fork - Copy TTY audit state for a new task
+ *
+ * Set up TTY audit state in @sig from current. @sig needs no locking.
+ */
+void tty_audit_fork(struct signal_struct *sig)
+{
+ spin_lock_irq(&current->sighand->siglock);
+ sig->audit_tty = current->signal->audit_tty;
+ spin_unlock_irq(&current->sighand->siglock);
+ sig->tty_audit_buf = NULL;
+}
+
+/**
+ * tty_audit_push_task - Flush task's pending audit data
+ */
+void tty_audit_push_task(struct task_struct *tsk, uid_t loginuid)
+{
+ struct tty_audit_buf *buf;
+
+ spin_lock_irq(&tsk->sighand->siglock);
+ buf = tsk->signal->tty_audit_buf;
+ if (buf)
+ atomic_inc(&buf->count);
+ spin_unlock_irq(&tsk->sighand->siglock);
+ if (!buf)
+ return;
+
+ mutex_lock(&buf->mutex);
+ tty_audit_buf_push(tsk, loginuid, buf);
+ mutex_unlock(&buf->mutex);
+
+ tty_audit_buf_put(buf);
+}
+
+/**
+ * tty_audit_buf_get - Get an audit buffer.
+ *
+ * Get an audit buffer for @tty, allocate it if necessary. Return %NULL
+ * 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)
+{
+ struct tty_audit_buf *buf, *buf2;
+
+ buf = NULL;
+ buf2 = NULL;
+ spin_lock_irq(&current->sighand->siglock);
+ if (likely(!current->signal->audit_tty))
+ goto out;
+ buf = current->signal->tty_audit_buf;
+ if (buf) {
+ atomic_inc(&buf->count);
+ goto out;
+ }
+ spin_unlock_irq(&current->sighand->siglock);
+
+ buf2 = tty_audit_buf_alloc(tty->driver->major,
+ tty->driver->minor_start + tty->index,
+ tty->icanon);
+ if (buf2 == NULL) {
+ audit_log_lost("out of memory in TTY auditing");
+ return NULL;
+ }
+
+ spin_lock_irq(&current->sighand->siglock);
+ if (!current->signal->audit_tty)
+ goto out;
+ buf = current->signal->tty_audit_buf;
+ if (!buf) {
+ current->signal->tty_audit_buf = buf2;
+ buf = buf2;
+ buf2 = NULL;
+ }
+ atomic_inc(&buf->count);
+ /* Fall through */
+ out:
+ spin_unlock_irq(&current->sighand->siglock);
+ if (buf2)
+ tty_audit_buf_free(buf2);
+ return buf;
+}
+
+/**
+ * tty_audit_add_data - Add data for TTY auditing.
+ *
+ * Audit @data of @size from @tty, if necessary.
+ */
+void tty_audit_add_data(struct tty_struct *tty, unsigned char *data,
+ size_t size)
+{
+ struct tty_audit_buf *buf;
+ int major, minor;
+
+ if (unlikely(size == 0))
+ return;
+
+ buf = tty_audit_buf_get(tty);
+ if (!buf)
+ return;
+
+ mutex_lock(&buf->mutex);
+ major = tty->driver->major;
+ minor = tty->driver->minor_start + tty->index;
+ if (buf->major != major || buf->minor != minor
+ || buf->icanon != tty->icanon) {
+ tty_audit_buf_push_current(buf);
+ buf->major = major;
+ buf->minor = minor;
+ buf->icanon = tty->icanon;
+ }
+ do {
+ size_t run;
+
+ run = N_TTY_BUF_SIZE - buf->valid;
+ if (run > size)
+ run = size;
+ memcpy(buf->data + buf->valid, data, run);
+ buf->valid += run;
+ data += run;
+ size -= run;
+ if (buf->valid == N_TTY_BUF_SIZE)
+ tty_audit_buf_push_current(buf);
+ } while (size != 0);
+ mutex_unlock(&buf->mutex);
+ tty_audit_buf_put(buf);
+}
+
+/**
+ * tty_audit_push - Push buffered data out
+ *
+ * Make sure no audit data is pending for @tty on the current process.
+ */
+void tty_audit_push(struct tty_struct *tty)
+{
+ struct tty_audit_buf *buf;
+
+ spin_lock_irq(&current->sighand->siglock);
+ if (likely(!current->signal->audit_tty)) {
+ spin_unlock_irq(&current->sighand->siglock);
+ return;
+ }
+ buf = current->signal->tty_audit_buf;
+ if (buf)
+ atomic_inc(&buf->count);
+ spin_unlock_irq(&current->sighand->siglock);
+
+ if (buf) {
+ int major, minor;
+
+ major = tty->driver->major;
+ minor = tty->driver->minor_start + tty->index;
+ mutex_lock(&buf->mutex);
+ if (buf->major == major && buf->minor == minor)
+ tty_audit_buf_push_current(buf);
+ mutex_unlock(&buf->mutex);
+ tty_audit_buf_put(buf);
+ }
+}
+
+/**
+ * tty_audit_opening - A TTY is being opened.
+ *
+ * As a special hack, tasks that close all their TTYs and open new ones
+ * are assumed to be system daemons (e.g. getty) and auditing is
+ * automatically disabled for them.
+ */
+void tty_audit_opening(void)
+{
+ int disable;
+
+ disable = 1;
+ spin_lock_irq(&current->sighand->siglock);
+ if (current->signal->audit_tty == 0)
+ disable = 0;
+ spin_unlock_irq(&current->sighand->siglock);
+ if (!disable)
+ return;
+
+ task_lock(current);
+ if (current->files) {
+ struct fdtable *fdt;
+ unsigned i;
+
+ /*
+ * We don't take a ref to the file, so we must hold ->file_lock
+ * instead.
+ */
+ spin_lock(&current->files->file_lock);
+ fdt = files_fdtable(current->files);
+ for (i = 0; i < fdt->max_fds; i++) {
+ struct file *filp;
+
+ filp = fcheck_files(current->files, i);
+ if (filp && is_tty(filp)) {
+ disable = 0;
+ break;
+ }
+ }
+ spin_unlock(&current->files->file_lock);
+ }
+ task_unlock(current);
+ if (!disable)
+ return;
+
+ spin_lock_irq(&current->sighand->siglock);
+ current->signal->audit_tty = 0;
+ spin_unlock_irq(&current->sighand->siglock);
+}
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index a96f26a63fa..de37ebc3a4c 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -1503,6 +1503,15 @@ int tty_hung_up_p(struct file * filp)
EXPORT_SYMBOL(tty_hung_up_p);
+/**
+ * is_tty - checker whether file is a TTY
+ */
+int is_tty(struct file *filp)
+{
+ return filp->f_op->read == tty_read
+ || filp->f_op->read == hung_up_tty_read;
+}
+
static void session_clear_tty(struct pid *session)
{
struct task_struct *p;
@@ -1726,6 +1735,23 @@ static ssize_t tty_read(struct file * file, char __user * buf, size_t count,
return i;
}
+void tty_write_unlock(struct tty_struct *tty)
+{
+ mutex_unlock(&tty->atomic_write_lock);
+ wake_up_interruptible(&tty->write_wait);
+}
+
+int tty_write_lock(struct tty_struct *tty, int ndelay)
+{
+ if (!mutex_trylock(&tty->atomic_write_lock)) {
+ if (ndelay)
+ return -EAGAIN;
+ if (mutex_lock_interruptible(&tty->atomic_write_lock))
+ return -ERESTARTSYS;
+ }
+ return 0;
+}
+
/*
* Split writes up in sane blocksizes to avoid
* denial-of-service type attacks
@@ -1737,13 +1763,12 @@ static inline ssize_t do_tty_write(
const char __user *buf,
size_t count)
{
- ssize_t ret = 0, written = 0;
+ ssize_t ret, written = 0;
unsigned int chunk;
- /* FIXME: O_NDELAY ... */
- if (mutex_lock_interruptible(&tty->atomic_write_lock)) {
- return -ERESTARTSYS;
- }
+ ret = tty_write_lock(tty, file->f_flags & O_NDELAY);
+ if (ret < 0)
+ return ret;
/*
* We chunk up writes into a temporary buffer. This
@@ -1776,8 +1801,8 @@ static inline ssize_t do_tty_write(
buf = kmalloc(chunk, GFP_KERNEL);
if (!buf) {
- mutex_unlock(&tty->atomic_write_lock);
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto out;
}
kfree(tty->write_buf);
tty->write_cnt = chunk;
@@ -1812,7 +1837,8 @@ static inline ssize_t do_tty_write(
inode->i_mtime = current_fs_time(inode->i_sb);
ret = written;
}
- mutex_unlock(&tty->atomic_write_lock);
+out:
+ tty_write_unlock(tty);
return ret;
}
@@ -2016,11 +2042,9 @@ static int init_dev(struct tty_driver *driver, int idx,
}
if (!*ltp_loc) {
- ltp = (struct ktermios *) kmalloc(sizeof(struct ktermios),
- GFP_KERNEL);
+ ltp = kzalloc(sizeof(struct ktermios), GFP_KERNEL);
if (!ltp)
goto free_mem_out;
- memset(ltp, 0, sizeof(struct ktermios));
}
if (driver->type == TTY_DRIVER_TYPE_PTY) {
@@ -2049,11 +2073,9 @@ static int init_dev(struct tty_driver *driver, int idx,
}
if (!*o_ltp_loc) {
- o_ltp = (struct ktermios *)
- kmalloc(sizeof(struct ktermios), GFP_KERNEL);
+ o_ltp = kzalloc(sizeof(struct ktermios), GFP_KERNEL);
if (!o_ltp)
goto free_mem_out;
- memset(o_ltp, 0, sizeof(struct ktermios));
}
/*
@@ -2660,6 +2682,7 @@ got_driver:
__proc_set_tty(current, tty);
spin_unlock_irq(&current->sighand->siglock);
mutex_unlock(&tty_mutex);
+ tty_audit_opening();
return 0;
}
@@ -2722,8 +2745,10 @@ static int ptmx_open(struct inode * inode, struct file * filp)
check_tty_count(tty, "tty_open");
retval = ptm_driver->open(tty, filp);
- if (!retval)
+ if (!retval) {
+ tty_audit_opening();
return 0;
+ }
out1:
release_dev(filp);
return retval;
@@ -3163,14 +3188,13 @@ static int tiocsetd(struct tty_struct *tty, int __user *p)
static int send_break(struct tty_struct *tty, unsigned int duration)
{
- if (mutex_lock_interruptible(&tty->atomic_write_lock))
+ if (tty_write_lock(tty, 0) < 0)
return -EINTR;
tty->driver->break_ctl(tty, -1);
- if (!signal_pending(current)) {
+ if (!signal_pending(current))
msleep_interruptible(duration);
- }
tty->driver->break_ctl(tty, 0);
- mutex_unlock(&tty->atomic_write_lock);
+ tty_write_unlock(tty);
if (signal_pending(current))
return -EINTR;
return 0;
@@ -3739,9 +3763,8 @@ struct tty_driver *alloc_tty_driver(int lines)
{
struct tty_driver *driver;
- driver = kmalloc(sizeof(struct tty_driver), GFP_KERNEL);
+ driver = kzalloc(sizeof(struct tty_driver), GFP_KERNEL);
if (driver) {
- memset(driver, 0, sizeof(struct tty_driver));
driver->magic = TTY_DRIVER_MAGIC;
driver->num = lines;
/* later we'll move allocation of tables here */
diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c
index fd471cb3338..3423e9ee648 100644
--- a/drivers/char/tty_ioctl.c
+++ b/drivers/char/tty_ioctl.c
@@ -52,8 +52,6 @@
void tty_wait_until_sent(struct tty_struct * tty, long timeout)
{
- DECLARE_WAITQUEUE(wait, current);
-
#ifdef TTY_DEBUG_WAIT_UNTIL_SENT
char buf[64];
@@ -61,26 +59,13 @@ void tty_wait_until_sent(struct tty_struct * tty, long timeout)
#endif
if (!tty->driver->chars_in_buffer)
return;
- add_wait_queue(&tty->write_wait, &wait);
if (!timeout)
timeout = MAX_SCHEDULE_TIMEOUT;
- do {
-#ifdef TTY_DEBUG_WAIT_UNTIL_SENT
- printk(KERN_DEBUG "waiting %s...(%d)\n", tty_name(tty, buf),
- tty->driver->chars_in_buffer(tty));
-#endif
- set_current_state(TASK_INTERRUPTIBLE);
- if (signal_pending(current))
- goto stop_waiting;
- if (!tty->driver->chars_in_buffer(tty))
- break;
- timeout = schedule_timeout(timeout);
- } while (timeout);
+ if (wait_event_interruptible_timeout(tty->write_wait,
+ !tty->driver->chars_in_buffer(tty), timeout))
+ return;
if (tty->driver->wait_until_sent)
tty->driver->wait_until_sent(tty, timeout);
-stop_waiting:
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&tty->write_wait, &wait);
}
EXPORT_SYMBOL(tty_wait_until_sent);
@@ -276,13 +261,12 @@ void tty_termios_encode_baud_rate(struct ktermios *termios, speed_t ibaud, speed
termios->c_cflag |= (baud_bits[i] << IBSHIFT);
ifound = i;
}
- }
- while(++i < n_baud_table);
+ } while (++i < n_baud_table);
if (ofound == -1)
termios->c_cflag |= BOTHER;
/* Set exact input bits only if the input and output differ or the
user already did */
- if (ifound == -1 && (ibaud != obaud || ibinput))
+ if (ifound == -1 && (ibaud != obaud || ibinput))
termios->c_cflag |= (BOTHER << IBSHIFT);
}
@@ -575,7 +559,7 @@ static int set_sgttyb(struct tty_struct * tty, struct sgttyb __user * sgttyb)
return -EFAULT;
mutex_lock(&tty->termios_mutex);
- termios = *tty->termios;
+ termios = *tty->termios;
termios.c_cc[VERASE] = tmp.sg_erase;
termios.c_cc[VKILL] = tmp.sg_kill;
set_sgflags(&termios, tmp.sg_flags);
@@ -667,7 +651,7 @@ static int send_prio_char(struct tty_struct *tty, char ch)
return 0;
}
- if (mutex_lock_interruptible(&tty->atomic_write_lock))
+ if (tty_write_lock(tty, 0) < 0)
return -ERESTARTSYS;
if (was_stopped)
@@ -675,7 +659,7 @@ static int send_prio_char(struct tty_struct *tty, char ch)
tty->driver->write(tty, &ch, 1);
if (was_stopped)
stop_tty(tty);
- mutex_unlock(&tty->atomic_write_lock);
+ tty_write_unlock(tty);
return 0;
}
diff --git a/drivers/connector/Kconfig b/drivers/connector/Kconfig
index e0bdc0db964..100bfd42206 100644
--- a/drivers/connector/Kconfig
+++ b/drivers/connector/Kconfig
@@ -1,6 +1,5 @@
-menu "Connector - unified userspace <-> kernelspace linker"
-config CONNECTOR
+menuconfig CONNECTOR
tristate "Connector - unified userspace <-> kernelspace linker"
depends on NET
---help---
@@ -10,6 +9,8 @@ config CONNECTOR
Connector support can also be built as a module. If so, the module
will be called cn.ko.
+if CONNECTOR
+
config PROC_EVENTS
boolean "Report process events to userspace"
depends on CONNECTOR=y
@@ -18,4 +19,4 @@ config PROC_EVENTS
Provide a connector that reports process events to userspace. Send
events such as fork, exec, id change (uid, gid, suid, etc), and exit.
-endmenu
+endif # CONNECTOR
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index bb90cbd7ca5..84ebfcc1ffb 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -1,4 +1,9 @@
-menu "Hardware crypto devices"
+
+menuconfig CRYPTO_HW
+ bool "Hardware crypto devices"
+ default y
+
+if CRYPTO_HW
config CRYPTO_DEV_PADLOCK
tristate "Support for VIA PadLock ACE"
@@ -78,4 +83,4 @@ config ZCRYPT_MONOLITHIC
that contains all parts of the crypto device driver (ap bus,
request router and all the card drivers).
-endmenu
+endif # CRYPTO_HW
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index b31756d5997..8f670dae53b 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -3,7 +3,7 @@
#
menu "DMA Engine support"
- depends on !S390
+ depends on HAS_DMA
config DMA_ENGINE
bool "Support for DMA engines"
diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig
index 807c402df04..debf1d8e8b4 100644
--- a/drivers/edac/Kconfig
+++ b/drivers/edac/Kconfig
@@ -6,11 +6,9 @@
# $Id: Kconfig,v 1.4.2.7 2005/07/08 22:05:38 dsp_llnl Exp $
#
-menu 'EDAC - error detection and reporting (RAS) (EXPERIMENTAL)'
+menuconfig EDAC
+ tristate "EDAC - error detection and reporting (EXPERIMENTAL)"
depends on HAS_IOMEM
-
-config EDAC
- tristate "EDAC core system error reporting (EXPERIMENTAL)"
depends on X86 && EXPERIMENTAL
help
EDAC is designed to report errors in the core system.
@@ -30,13 +28,12 @@ config EDAC
There is also a mailing list for the EDAC project, which can
be found via the sourceforge page.
+if EDAC
comment "Reporting subsystems"
- depends on EDAC
config EDAC_DEBUG
bool "Debugging"
- depends on EDAC
help
This turns on debugging information for the entire EDAC
sub-system. You can insert module with "debug_level=x", current
@@ -45,7 +42,6 @@ config EDAC_DEBUG
config EDAC_MM_EDAC
tristate "Main Memory EDAC (Error Detection And Correction) reporting"
- depends on EDAC
default y
help
Some systems are able to detect and correct errors in main
@@ -100,15 +96,13 @@ config EDAC_R82600
choice
prompt "Error detecting method"
- depends on EDAC
default EDAC_POLL
config EDAC_POLL
bool "Poll for errors"
- depends on EDAC
help
Poll the chipset periodically to detect errors.
endchoice
-endmenu
+endif # EDAC
diff --git a/drivers/firmware/edd.c b/drivers/firmware/edd.c
index 15232271d84..0fb730ee1da 100644
--- a/drivers/firmware/edd.c
+++ b/drivers/firmware/edd.c
@@ -669,7 +669,7 @@ edd_get_pci_dev(struct edd_device *edev)
struct edd_info *info = edd_dev_get_info(edev);
if (edd_dev_is_type(edev, "PCI")) {
- return pci_find_slot(info->params.interface_path.pci.bus,
+ return pci_get_bus_and_slot(info->params.interface_path.pci.bus,
PCI_DEVFN(info->params.interface_path.pci.slot,
info->params.interface_path.pci.
function));
@@ -682,9 +682,12 @@ edd_create_symlink_to_pcidev(struct edd_device *edev)
{
struct pci_dev *pci_dev = edd_get_pci_dev(edev);
+ int ret;
if (!pci_dev)
return 1;
- return sysfs_create_link(&edev->kobj,&pci_dev->dev.kobj,"pci_dev");
+ ret = sysfs_create_link(&edev->kobj,&pci_dev->dev.kobj,"pci_dev");
+ pci_dev_put(pci_dev);
+ return ret;
}
static inline void
diff --git a/drivers/firmware/pcdp.c b/drivers/firmware/pcdp.c
index 2b4b76e8bd7..58e9f8e457f 100644
--- a/drivers/firmware/pcdp.c
+++ b/drivers/firmware/pcdp.c
@@ -15,6 +15,7 @@
#include <linux/console.h>
#include <linux/efi.h>
#include <linux/serial.h>
+#include <linux/serial_8250.h>
#include <asm/vga.h>
#include "pcdp.h"
@@ -27,7 +28,7 @@ setup_serial_console(struct pcdp_uart *uart)
char parity;
mmio = (uart->addr.space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY);
- p += sprintf(p, "console=uart,%s,0x%lx",
+ p += sprintf(p, "uart8250,%s,0x%lx",
mmio ? "mmio" : "io", uart->addr.address);
if (uart->baud) {
p += sprintf(p, ",%lu", uart->baud);
@@ -41,7 +42,8 @@ setup_serial_console(struct pcdp_uart *uart)
}
}
- return early_serial_console_init(options);
+ add_preferred_console("uart", 8250, &options[9]);
+ return setup_early_serial8250_console(options);
#else
return -ENODEV;
#endif
diff --git a/drivers/macintosh/adb.c b/drivers/macintosh/adb.c
index adfea3c7c62..bc77c5e2ca9 100644
--- a/drivers/macintosh/adb.c
+++ b/drivers/macintosh/adb.c
@@ -248,21 +248,15 @@ static int adb_scan_bus(void)
static int
adb_probe_task(void *x)
{
- sigset_t blocked;
-
strcpy(current->comm, "kadbprobe");
- sigfillset(&blocked);
- sigprocmask(SIG_BLOCK, &blocked, NULL);
- flush_signals(current);
-
printk(KERN_INFO "adb: starting probe task...\n");
do_adb_reset_bus();
printk(KERN_INFO "adb: finished probe task...\n");
-
+
adb_probe_task_pid = 0;
up(&adb_probe_mutex);
-
+
return 0;
}
diff --git a/drivers/message/i2o/Kconfig b/drivers/message/i2o/Kconfig
index f4ac21e5771..5afa0e393ec 100644
--- a/drivers/message/i2o/Kconfig
+++ b/drivers/message/i2o/Kconfig
@@ -1,9 +1,6 @@
-menu "I2O device support"
- depends on PCI
-
-config I2O
- tristate "I2O support"
+menuconfig I2O
+ tristate "I2O device support"
depends on PCI
---help---
The Intelligent Input/Output (I2O) architecture allows hardware
@@ -25,9 +22,10 @@ config I2O
If unsure, say N.
+if I2O
+
config I2O_LCT_NOTIFY_ON_CHANGES
bool "Enable LCT notification"
- depends on I2O
default y
---help---
Only say N here if you have a I2O controller from SUN. The SUN
@@ -39,7 +37,6 @@ config I2O_LCT_NOTIFY_ON_CHANGES
config I2O_EXT_ADAPTEC
bool "Enable Adaptec extensions"
- depends on I2O
default y
---help---
Say Y for support of raidutils for Adaptec I2O controllers. You also
@@ -57,7 +54,7 @@ config I2O_EXT_ADAPTEC_DMA64
config I2O_CONFIG
tristate "I2O Configuration support"
- depends on I2O
+ depends on VIRT_TO_BUS
---help---
Say Y for support of the configuration interface for the I2O adapters.
If you have a RAID controller from Adaptec and you want to use the
@@ -78,7 +75,6 @@ config I2O_CONFIG_OLD_IOCTL
config I2O_BUS
tristate "I2O Bus Adapter OSM"
- depends on I2O
---help---
Include support for the I2O Bus Adapter OSM. The Bus Adapter OSM
provides access to the busses on the I2O controller. The main purpose
@@ -89,7 +85,7 @@ config I2O_BUS
config I2O_BLOCK
tristate "I2O Block OSM"
- depends on I2O && BLOCK
+ depends on BLOCK
---help---
Include support for the I2O Block OSM. The Block OSM presents disk
and other structured block devices to the operating system. If you
@@ -102,7 +98,7 @@ config I2O_BLOCK
config I2O_SCSI
tristate "I2O SCSI OSM"
- depends on I2O && SCSI
+ depends on SCSI
---help---
Allows direct SCSI access to SCSI devices on a SCSI or FibreChannel
I2O controller. You can use both the SCSI and Block OSM together if
@@ -114,7 +110,6 @@ config I2O_SCSI
config I2O_PROC
tristate "I2O /proc support"
- depends on I2O
---help---
If you say Y here and to "/proc file system support", you will be
able to read I2O related information from the virtual directory
@@ -123,5 +118,4 @@ config I2O_PROC
To compile this support as a module, choose M here: the
module will be called i2o_proc.
-endmenu
-
+endif # I2O
diff --git a/drivers/message/i2o/device.c b/drivers/message/i2o/device.c
index 611adc3c0f7..489d7c5c496 100644
--- a/drivers/message/i2o/device.c
+++ b/drivers/message/i2o/device.c
@@ -62,7 +62,7 @@ int i2o_device_claim(struct i2o_device *dev)
{
int rc = 0;
- down(&dev->lock);
+ mutex_lock(&dev->lock);
rc = i2o_device_issue_claim(dev, I2O_CMD_UTIL_CLAIM, I2O_CLAIM_PRIMARY);
if (!rc)
@@ -72,7 +72,7 @@ int i2o_device_claim(struct i2o_device *dev)
pr_debug("i2o: claim of device %d failed %d\n",
dev->lct_data.tid, rc);
- up(&dev->lock);
+ mutex_unlock(&dev->lock);
return rc;
}
@@ -96,7 +96,7 @@ int i2o_device_claim_release(struct i2o_device *dev)
int tries;
int rc = 0;
- down(&dev->lock);
+ mutex_lock(&dev->lock);
/*
* If the controller takes a nonblocking approach to
@@ -118,7 +118,7 @@ int i2o_device_claim_release(struct i2o_device *dev)
pr_debug("i2o: claim release of device %d failed %d\n",
dev->lct_data.tid, rc);
- up(&dev->lock);
+ mutex_unlock(&dev->lock);
return rc;
}
@@ -198,7 +198,7 @@ static struct i2o_device *i2o_device_alloc(void)
return ERR_PTR(-ENOMEM);
INIT_LIST_HEAD(&dev->list);
- init_MUTEX(&dev->lock);
+ mutex_init(&dev->lock);
dev->device.bus = &i2o_bus_type;
dev->device.release = &i2o_device_release;
@@ -326,7 +326,7 @@ int i2o_device_parse_lct(struct i2o_controller *c)
u16 table_size;
u32 buf;
- down(&c->lct_lock);
+ mutex_lock(&c->lct_lock);
kfree(c->lct);
@@ -335,7 +335,7 @@ int i2o_device_parse_lct(struct i2o_controller *c)
lct = c->lct = kmalloc(table_size * 4, GFP_KERNEL);
if (!lct) {
- up(&c->lct_lock);
+ mutex_unlock(&c->lct_lock);
return -ENOMEM;
}
@@ -408,7 +408,7 @@ int i2o_device_parse_lct(struct i2o_controller *c)
i2o_device_remove(dev);
}
- up(&c->lct_lock);
+ mutex_unlock(&c->lct_lock);
return 0;
}
diff --git a/drivers/message/i2o/exec-osm.c b/drivers/message/i2o/exec-osm.c
index 5278aad92bc..c13b9321e7a 100644
--- a/drivers/message/i2o/exec-osm.c
+++ b/drivers/message/i2o/exec-osm.c
@@ -537,7 +537,7 @@ static int i2o_exec_lct_notify(struct i2o_controller *c, u32 change_ind)
struct device *dev;
struct i2o_message *msg;
- down(&c->lct_lock);
+ mutex_lock(&c->lct_lock);
dev = &c->pdev->dev;
@@ -561,7 +561,7 @@ static int i2o_exec_lct_notify(struct i2o_controller *c, u32 change_ind)
i2o_msg_post(c, msg);
- up(&c->lct_lock);
+ mutex_unlock(&c->lct_lock);
return 0;
};
diff --git a/drivers/message/i2o/iop.c b/drivers/message/i2o/iop.c
index 3305c12372a..a1ec16a075c 100644
--- a/drivers/message/i2o/iop.c
+++ b/drivers/message/i2o/iop.c
@@ -1067,7 +1067,7 @@ struct i2o_controller *i2o_iop_alloc(void)
INIT_LIST_HEAD(&c->devices);
spin_lock_init(&c->lock);
- init_MUTEX(&c->lct_lock);
+ mutex_init(&c->lct_lock);
device_initialize(&c->device);
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index bd601efa7bd..a92b8728b90 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -2,7 +2,11 @@
# Misc strange devices
#
-menu "Misc devices"
+menuconfig MISC_DEVICES
+ bool "Misc devices"
+ default y
+
+if MISC_DEVICES
config IBM_ASM
tristate "Device driver for IBM RSA service processor"
@@ -192,4 +196,4 @@ config THINKPAD_ACPI_BAY
If you are not sure, say Y here.
-endmenu
+endif # MISC_DEVICES
diff --git a/drivers/misc/sony-laptop.c b/drivers/misc/sony-laptop.c
index 8ee0321ef1c..9623eaf4f89 100644
--- a/drivers/misc/sony-laptop.c
+++ b/drivers/misc/sony-laptop.c
@@ -1917,7 +1917,8 @@ end:
*/
static int sony_pic_disable(struct acpi_device *device)
{
- if (ACPI_FAILURE(acpi_evaluate_object(device->handle, "_DIS", 0, NULL)))
+ if (ACPI_FAILURE(acpi_evaluate_object(device->handle,
+ "_DIS", NULL, NULL)))
return -ENXIO;
dprintk("Device disabled\n");
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 71e7ef2cc99..713ab05a87c 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -588,6 +588,12 @@ config CASSINI
Support for the Sun Cassini chip, aka Sun GigaSwift Ethernet. See also
<http://www.sun.com/products-n-solutions/hardware/docs/pdf/817-4341-10.pdf>
+config SUNVNET
+ tristate "Sun Virtual Network support"
+ depends on SUN_LDOMS
+ help
+ Support for virtual network devices under Sun Logical Domains.
+
config NET_VENDOR_3COM
bool "3COM cards"
depends on ISA || EISA || MCA || PCI
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index a21b98ea16a..eb4167622a6 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -34,6 +34,7 @@ obj-$(CONFIG_SUNBMAC) += sunbmac.o
obj-$(CONFIG_MYRI_SBUS) += myri_sbus.o
obj-$(CONFIG_SUNGEM) += sungem.o sungem_phy.o
obj-$(CONFIG_CASSINI) += cassini.o
+obj-$(CONFIG_SUNVNET) += sunvnet.o
obj-$(CONFIG_MACE) += mace.o
obj-$(CONFIG_BMAC) += bmac.o
diff --git a/drivers/net/sunvnet.c b/drivers/net/sunvnet.c
new file mode 100644
index 00000000000..8a667c13fae
--- /dev/null
+++ b/drivers/net/sunvnet.c
@@ -0,0 +1,1164 @@
+/* sunvnet.c: Sun LDOM Virtual Network Driver.
+ *
+ * Copyright (C) 2007 David S. Miller <davem@davemloft.net>
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/ethtool.h>
+#include <linux/etherdevice.h>
+
+#include <asm/vio.h>
+#include <asm/ldc.h>
+
+#include "sunvnet.h"
+
+#define DRV_MODULE_NAME "sunvnet"
+#define PFX DRV_MODULE_NAME ": "
+#define DRV_MODULE_VERSION "1.0"
+#define DRV_MODULE_RELDATE "June 25, 2007"
+
+static char version[] __devinitdata =
+ DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
+MODULE_AUTHOR("David S. Miller (davem@davemloft.net)");
+MODULE_DESCRIPTION("Sun LDOM virtual network driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_MODULE_VERSION);
+
+/* Ordered from largest major to lowest */
+static struct vio_version vnet_versions[] = {
+ { .major = 1, .minor = 0 },
+};
+
+static inline u32 vnet_tx_dring_avail(struct vio_dring_state *dr)
+{
+ return vio_dring_avail(dr, VNET_TX_RING_SIZE);
+}
+
+static int vnet_handle_unknown(struct vnet_port *port, void *arg)
+{
+ struct vio_msg_tag *pkt = arg;
+
+ printk(KERN_ERR PFX "Received unknown msg [%02x:%02x:%04x:%08x]\n",
+ pkt->type, pkt->stype, pkt->stype_env, pkt->sid);
+ printk(KERN_ERR PFX "Resetting connection.\n");
+
+ ldc_disconnect(port->vio.lp);
+
+ return -ECONNRESET;
+}
+
+static int vnet_send_attr(struct vio_driver_state *vio)
+{
+ struct vnet_port *port = to_vnet_port(vio);
+ struct net_device *dev = port->vp->dev;
+ struct vio_net_attr_info pkt;
+ int i;
+
+ memset(&pkt, 0, sizeof(pkt));
+ pkt.tag.type = VIO_TYPE_CTRL;
+ pkt.tag.stype = VIO_SUBTYPE_INFO;
+ pkt.tag.stype_env = VIO_ATTR_INFO;
+ pkt.tag.sid = vio_send_sid(vio);
+ pkt.xfer_mode = VIO_DRING_MODE;
+ pkt.addr_type = VNET_ADDR_ETHERMAC;
+ pkt.ack_freq = 0;
+ for (i = 0; i < 6; i++)
+ pkt.addr |= (u64)dev->dev_addr[i] << ((5 - i) * 8);
+ pkt.mtu = ETH_FRAME_LEN;
+
+ viodbg(HS, "SEND NET ATTR xmode[0x%x] atype[0x%x] addr[%llx] "
+ "ackfreq[%u] mtu[%llu]\n",
+ pkt.xfer_mode, pkt.addr_type,
+ (unsigned long long) pkt.addr,
+ pkt.ack_freq,
+ (unsigned long long) pkt.mtu);
+
+ return vio_ldc_send(vio, &pkt, sizeof(pkt));
+}
+
+static int handle_attr_info(struct vio_driver_state *vio,
+ struct vio_net_attr_info *pkt)
+{
+ viodbg(HS, "GOT NET ATTR INFO xmode[0x%x] atype[0x%x] addr[%llx] "
+ "ackfreq[%u] mtu[%llu]\n",
+ pkt->xfer_mode, pkt->addr_type,
+ (unsigned long long) pkt->addr,
+ pkt->ack_freq,
+ (unsigned long long) pkt->mtu);
+
+ pkt->tag.sid = vio_send_sid(vio);
+
+ if (pkt->xfer_mode != VIO_DRING_MODE ||
+ pkt->addr_type != VNET_ADDR_ETHERMAC ||
+ pkt->mtu != ETH_FRAME_LEN) {
+ viodbg(HS, "SEND NET ATTR NACK\n");
+
+ pkt->tag.stype = VIO_SUBTYPE_NACK;
+
+ (void) vio_ldc_send(vio, pkt, sizeof(*pkt));
+
+ return -ECONNRESET;
+ } else {
+ viodbg(HS, "SEND NET ATTR ACK\n");
+
+ pkt->tag.stype = VIO_SUBTYPE_ACK;
+
+ return vio_ldc_send(vio, pkt, sizeof(*pkt));
+ }
+
+}
+
+static int handle_attr_ack(struct vio_driver_state *vio,
+ struct vio_net_attr_info *pkt)
+{
+ viodbg(HS, "GOT NET ATTR ACK\n");
+
+ return 0;
+}
+
+static int handle_attr_nack(struct vio_driver_state *vio,
+ struct vio_net_attr_info *pkt)
+{
+ viodbg(HS, "GOT NET ATTR NACK\n");
+
+ return -ECONNRESET;
+}
+
+static int vnet_handle_attr(struct vio_driver_state *vio, void *arg)
+{
+ struct vio_net_attr_info *pkt = arg;
+
+ switch (pkt->tag.stype) {
+ case VIO_SUBTYPE_INFO:
+ return handle_attr_info(vio, pkt);
+
+ case VIO_SUBTYPE_ACK:
+ return handle_attr_ack(vio, pkt);
+
+ case VIO_SUBTYPE_NACK:
+ return handle_attr_nack(vio, pkt);
+
+ default:
+ return -ECONNRESET;
+ }
+}
+
+static void vnet_handshake_complete(struct vio_driver_state *vio)
+{
+ struct vio_dring_state *dr;
+
+ dr = &vio->drings[VIO_DRIVER_RX_RING];
+ dr->snd_nxt = dr->rcv_nxt = 1;
+
+ dr = &vio->drings[VIO_DRIVER_TX_RING];
+ dr->snd_nxt = dr->rcv_nxt = 1;
+}
+
+/* The hypervisor interface that implements copying to/from imported
+ * memory from another domain requires that copies are done to 8-byte
+ * aligned buffers, and that the lengths of such copies are also 8-byte
+ * multiples.
+ *
+ * So we align skb->data to an 8-byte multiple and pad-out the data
+ * area so we can round the copy length up to the next multiple of
+ * 8 for the copy.
+ *
+ * The transmitter puts the actual start of the packet 6 bytes into
+ * the buffer it sends over, so that the IP headers after the ethernet
+ * header are aligned properly. These 6 bytes are not in the descriptor
+ * length, they are simply implied. This offset is represented using
+ * the VNET_PACKET_SKIP macro.
+ */
+static struct sk_buff *alloc_and_align_skb(struct net_device *dev,
+ unsigned int len)
+{
+ struct sk_buff *skb = netdev_alloc_skb(dev, len+VNET_PACKET_SKIP+8+8);
+ unsigned long addr, off;
+
+ if (unlikely(!skb))
+ return NULL;
+
+ addr = (unsigned long) skb->data;
+ off = ((addr + 7UL) & ~7UL) - addr;
+ if (off)
+ skb_reserve(skb, off);
+
+ return skb;
+}
+
+static int vnet_rx_one(struct vnet_port *port, unsigned int len,
+ struct ldc_trans_cookie *cookies, int ncookies)
+{
+ struct net_device *dev = port->vp->dev;
+ unsigned int copy_len;
+ struct sk_buff *skb;
+ int err;
+
+ err = -EMSGSIZE;
+ if (unlikely(len < ETH_ZLEN || len > ETH_FRAME_LEN)) {
+ dev->stats.rx_length_errors++;
+ goto out_dropped;
+ }
+
+ skb = alloc_and_align_skb(dev, len);
+ err = -ENOMEM;
+ if (unlikely(!skb)) {
+ dev->stats.rx_missed_errors++;
+ goto out_dropped;
+ }
+
+ copy_len = (len + VNET_PACKET_SKIP + 7U) & ~7U;
+ skb_put(skb, copy_len);
+ err = ldc_copy(port->vio.lp, LDC_COPY_IN,
+ skb->data, copy_len, 0,
+ cookies, ncookies);
+ if (unlikely(err < 0)) {
+ dev->stats.rx_frame_errors++;
+ goto out_free_skb;
+ }
+
+ skb_pull(skb, VNET_PACKET_SKIP);
+ skb_trim(skb, len);
+ skb->protocol = eth_type_trans(skb, dev);
+
+ dev->stats.rx_packets++;
+ dev->stats.rx_bytes += len;
+
+ netif_rx(skb);
+
+ return 0;
+
+out_free_skb:
+ kfree_skb(skb);
+
+out_dropped:
+ dev->stats.rx_dropped++;
+ return err;
+}
+
+static int vnet_send_ack(struct vnet_port *port, struct vio_dring_state *dr,
+ u32 start, u32 end, u8 vio_dring_state)
+{
+ struct vio_dring_data hdr = {
+ .tag = {
+ .type = VIO_TYPE_DATA,
+ .stype = VIO_SUBTYPE_ACK,
+ .stype_env = VIO_DRING_DATA,
+ .sid = vio_send_sid(&port->vio),
+ },
+ .dring_ident = dr->ident,
+ .start_idx = start,
+ .end_idx = end,
+ .state = vio_dring_state,
+ };
+ int err, delay;
+
+ hdr.seq = dr->snd_nxt;
+ delay = 1;
+ do {
+ err = vio_ldc_send(&port->vio, &hdr, sizeof(hdr));
+ if (err > 0) {
+ dr->snd_nxt++;
+ break;
+ }
+ udelay(delay);
+ if ((delay <<= 1) > 128)
+ delay = 128;
+ } while (err == -EAGAIN);
+
+ return err;
+}
+
+static u32 next_idx(u32 idx, struct vio_dring_state *dr)
+{
+ if (++idx == dr->num_entries)
+ idx = 0;
+ return idx;
+}
+
+static u32 prev_idx(u32 idx, struct vio_dring_state *dr)
+{
+ if (idx == 0)
+ idx = dr->num_entries - 1;
+ else
+ idx--;
+
+ return idx;
+}
+
+static struct vio_net_desc *get_rx_desc(struct vnet_port *port,
+ struct vio_dring_state *dr,
+ u32 index)
+{
+ struct vio_net_desc *desc = port->vio.desc_buf;
+ int err;
+
+ err = ldc_get_dring_entry(port->vio.lp, desc, dr->entry_size,
+ (index * dr->entry_size),
+ dr->cookies, dr->ncookies);
+ if (err < 0)
+ return ERR_PTR(err);
+
+ return desc;
+}
+
+static int put_rx_desc(struct vnet_port *port,
+ struct vio_dring_state *dr,
+ struct vio_net_desc *desc,
+ u32 index)
+{
+ int err;
+
+ err = ldc_put_dring_entry(port->vio.lp, desc, dr->entry_size,
+ (index * dr->entry_size),
+ dr->cookies, dr->ncookies);
+ if (err < 0)
+ return err;
+
+ return 0;
+}
+
+static int vnet_walk_rx_one(struct vnet_port *port,
+ struct vio_dring_state *dr,
+ u32 index, int *needs_ack)
+{
+ struct vio_net_desc *desc = get_rx_desc(port, dr, index);
+ struct vio_driver_state *vio = &port->vio;
+ int err;
+
+ if (IS_ERR(desc))
+ return PTR_ERR(desc);
+
+ viodbg(DATA, "vio_walk_rx_one desc[%02x:%02x:%08x:%08x:%lx:%lx]\n",
+ desc->hdr.state, desc->hdr.ack,
+ desc->size, desc->ncookies,
+ desc->cookies[0].cookie_addr,
+ desc->cookies[0].cookie_size);
+
+ if (desc->hdr.state != VIO_DESC_READY)
+ return 1;
+ err = vnet_rx_one(port, desc->size, desc->cookies, desc->ncookies);
+ if (err == -ECONNRESET)
+ return err;
+ desc->hdr.state = VIO_DESC_DONE;
+ err = put_rx_desc(port, dr, desc, index);
+ if (err < 0)
+ return err;
+ *needs_ack = desc->hdr.ack;
+ return 0;
+}
+
+static int vnet_walk_rx(struct vnet_port *port, struct vio_dring_state *dr,
+ u32 start, u32 end)
+{
+ struct vio_driver_state *vio = &port->vio;
+ int ack_start = -1, ack_end = -1;
+
+ end = (end == (u32) -1) ? prev_idx(start, dr) : next_idx(end, dr);
+
+ viodbg(DATA, "vnet_walk_rx start[%08x] end[%08x]\n", start, end);
+
+ while (start != end) {
+ int ack = 0, err = vnet_walk_rx_one(port, dr, start, &ack);
+ if (err == -ECONNRESET)
+ return err;
+ if (err != 0)
+ break;
+ if (ack_start == -1)
+ ack_start = start;
+ ack_end = start;
+ start = next_idx(start, dr);
+ if (ack && start != end) {
+ err = vnet_send_ack(port, dr, ack_start, ack_end,
+ VIO_DRING_ACTIVE);
+ if (err == -ECONNRESET)
+ return err;
+ ack_start = -1;
+ }
+ }
+ if (unlikely(ack_start == -1))
+ ack_start = ack_end = prev_idx(start, dr);
+ return vnet_send_ack(port, dr, ack_start, ack_end, VIO_DRING_STOPPED);
+}
+
+static int vnet_rx(struct vnet_port *port, void *msgbuf)
+{
+ struct vio_dring_data *pkt = msgbuf;
+ struct vio_dring_state *dr = &port->vio.drings[VIO_DRIVER_RX_RING];
+ struct vio_driver_state *vio = &port->vio;
+
+ viodbg(DATA, "vnet_rx stype_env[%04x] seq[%016lx] rcv_nxt[%016lx]\n",
+ pkt->tag.stype_env, pkt->seq, dr->rcv_nxt);
+
+ if (unlikely(pkt->tag.stype_env != VIO_DRING_DATA))
+ return 0;
+ if (unlikely(pkt->seq != dr->rcv_nxt)) {
+ printk(KERN_ERR PFX "RX out of sequence seq[0x%lx] "
+ "rcv_nxt[0x%lx]\n", pkt->seq, dr->rcv_nxt);
+ return 0;
+ }
+
+ dr->rcv_nxt++;
+
+ /* XXX Validate pkt->start_idx and pkt->end_idx XXX */
+
+ return vnet_walk_rx(port, dr, pkt->start_idx, pkt->end_idx);
+}
+
+static int idx_is_pending(struct vio_dring_state *dr, u32 end)
+{
+ u32 idx = dr->cons;
+ int found = 0;
+
+ while (idx != dr->prod) {
+ if (idx == end) {
+ found = 1;
+ break;
+ }
+ idx = next_idx(idx, dr);
+ }
+ return found;
+}
+
+static int vnet_ack(struct vnet_port *port, void *msgbuf)
+{
+ struct vio_dring_state *dr = &port->vio.drings[VIO_DRIVER_TX_RING];
+ struct vio_dring_data *pkt = msgbuf;
+ struct net_device *dev;
+ struct vnet *vp;
+ u32 end;
+
+ if (unlikely(pkt->tag.stype_env != VIO_DRING_DATA))
+ return 0;
+
+ end = pkt->end_idx;
+ if (unlikely(!idx_is_pending(dr, end)))
+ return 0;
+
+ dr->cons = next_idx(end, dr);
+
+ vp = port->vp;
+ dev = vp->dev;
+ if (unlikely(netif_queue_stopped(dev) &&
+ vnet_tx_dring_avail(dr) >= VNET_TX_WAKEUP_THRESH(dr)))
+ return 1;
+
+ return 0;
+}
+
+static int vnet_nack(struct vnet_port *port, void *msgbuf)
+{
+ /* XXX just reset or similar XXX */
+ return 0;
+}
+
+static void maybe_tx_wakeup(struct vnet *vp)
+{
+ struct net_device *dev = vp->dev;
+
+ netif_tx_lock(dev);
+ if (likely(netif_queue_stopped(dev))) {
+ struct vnet_port *port;
+ int wake = 1;
+
+ list_for_each_entry(port, &vp->port_list, list) {
+ struct vio_dring_state *dr;
+
+ dr = &port->vio.drings[VIO_DRIVER_TX_RING];
+ if (vnet_tx_dring_avail(dr) <
+ VNET_TX_WAKEUP_THRESH(dr)) {
+ wake = 0;
+ break;
+ }
+ }
+ if (wake)
+ netif_wake_queue(dev);
+ }
+ netif_tx_unlock(dev);
+}
+
+static void vnet_event(void *arg, int event)
+{
+ struct vnet_port *port = arg;
+ struct vio_driver_state *vio = &port->vio;
+ unsigned long flags;
+ int tx_wakeup, err;
+
+ spin_lock_irqsave(&vio->lock, flags);
+
+ if (unlikely(event == LDC_EVENT_RESET ||
+ event == LDC_EVENT_UP)) {
+ vio_link_state_change(vio, event);
+ spin_unlock_irqrestore(&vio->lock, flags);
+
+ return;
+ }
+
+ if (unlikely(event != LDC_EVENT_DATA_READY)) {
+ printk(KERN_WARNING PFX "Unexpected LDC event %d\n", event);
+ spin_unlock_irqrestore(&vio->lock, flags);
+ return;
+ }
+
+ tx_wakeup = err = 0;
+ while (1) {
+ union {
+ struct vio_msg_tag tag;
+ u64 raw[8];
+ } msgbuf;
+
+ err = ldc_read(vio->lp, &msgbuf, sizeof(msgbuf));
+ if (unlikely(err < 0)) {
+ if (err == -ECONNRESET)
+ vio_conn_reset(vio);
+ break;
+ }
+ if (err == 0)
+ break;
+ viodbg(DATA, "TAG [%02x:%02x:%04x:%08x]\n",
+ msgbuf.tag.type,
+ msgbuf.tag.stype,
+ msgbuf.tag.stype_env,
+ msgbuf.tag.sid);
+ err = vio_validate_sid(vio, &msgbuf.tag);
+ if (err < 0)
+ break;
+
+ if (likely(msgbuf.tag.type == VIO_TYPE_DATA)) {
+ if (msgbuf.tag.stype == VIO_SUBTYPE_INFO) {
+ err = vnet_rx(port, &msgbuf);
+ } else if (msgbuf.tag.stype == VIO_SUBTYPE_ACK) {
+ err = vnet_ack(port, &msgbuf);
+ if (err > 0)
+ tx_wakeup |= err;
+ } else if (msgbuf.tag.stype == VIO_SUBTYPE_NACK) {
+ err = vnet_nack(port, &msgbuf);
+ }
+ } else if (msgbuf.tag.type == VIO_TYPE_CTRL) {
+ err = vio_control_pkt_engine(vio, &msgbuf);
+ if (err)
+ break;
+ } else {
+ err = vnet_handle_unknown(port, &msgbuf);
+ }
+ if (err == -ECONNRESET)
+ break;
+ }
+ spin_unlock(&vio->lock);
+ if (unlikely(tx_wakeup && err != -ECONNRESET))
+ maybe_tx_wakeup(port->vp);
+ local_irq_restore(flags);
+}
+
+static int __vnet_tx_trigger(struct vnet_port *port)
+{
+ struct vio_dring_state *dr = &port->vio.drings[VIO_DRIVER_TX_RING];
+ struct vio_dring_data hdr = {
+ .tag = {
+ .type = VIO_TYPE_DATA,
+ .stype = VIO_SUBTYPE_INFO,
+ .stype_env = VIO_DRING_DATA,
+ .sid = vio_send_sid(&port->vio),
+ },
+ .dring_ident = dr->ident,
+ .start_idx = dr->prod,
+ .end_idx = (u32) -1,
+ };
+ int err, delay;
+
+ hdr.seq = dr->snd_nxt;
+ delay = 1;
+ do {
+ err = vio_ldc_send(&port->vio, &hdr, sizeof(hdr));
+ if (err > 0) {
+ dr->snd_nxt++;
+ break;
+ }
+ udelay(delay);
+ if ((delay <<= 1) > 128)
+ delay = 128;
+ } while (err == -EAGAIN);
+
+ return err;
+}
+
+struct vnet_port *__tx_port_find(struct vnet *vp, struct sk_buff *skb)
+{
+ unsigned int hash = vnet_hashfn(skb->data);
+ struct hlist_head *hp = &vp->port_hash[hash];
+ struct hlist_node *n;
+ struct vnet_port *port;
+
+ hlist_for_each_entry(port, n, hp, hash) {
+ if (!compare_ether_addr(port->raddr, skb->data))
+ return port;
+ }
+ port = NULL;
+ if (!list_empty(&vp->port_list))
+ port = list_entry(vp->port_list.next, struct vnet_port, list);
+
+ return port;
+}
+
+struct vnet_port *tx_port_find(struct vnet *vp, struct sk_buff *skb)
+{
+ struct vnet_port *ret;
+ unsigned long flags;
+
+ spin_lock_irqsave(&vp->lock, flags);
+ ret = __tx_port_find(vp, skb);
+ spin_unlock_irqrestore(&vp->lock, flags);
+
+ return ret;
+}
+
+static int vnet_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct vnet *vp = netdev_priv(dev);
+ struct vnet_port *port = tx_port_find(vp, skb);
+ struct vio_dring_state *dr;
+ struct vio_net_desc *d;
+ unsigned long flags;
+ unsigned int len;
+ void *tx_buf;
+ int i, err;
+
+ if (unlikely(!port))
+ goto out_dropped;
+
+ spin_lock_irqsave(&port->vio.lock, flags);
+
+ dr = &port->vio.drings[VIO_DRIVER_TX_RING];
+ if (unlikely(vnet_tx_dring_avail(dr) < 2)) {
+ if (!netif_queue_stopped(dev)) {
+ netif_stop_queue(dev);
+
+ /* This is a hard error, log it. */
+ printk(KERN_ERR PFX "%s: BUG! Tx Ring full when "
+ "queue awake!\n", dev->name);
+ dev->stats.tx_errors++;
+ }
+ spin_unlock_irqrestore(&port->vio.lock, flags);
+ return NETDEV_TX_BUSY;
+ }
+
+ d = vio_dring_cur(dr);
+
+ tx_buf = port->tx_bufs[dr->prod].buf;
+ skb_copy_from_linear_data(skb, tx_buf + VNET_PACKET_SKIP, skb->len);
+
+ len = skb->len;
+ if (len < ETH_ZLEN) {
+ len = ETH_ZLEN;
+ memset(tx_buf+VNET_PACKET_SKIP+skb->len, 0, len - skb->len);
+ }
+
+ d->hdr.ack = VIO_ACK_ENABLE;
+ d->size = len;
+ d->ncookies = port->tx_bufs[dr->prod].ncookies;
+ for (i = 0; i < d->ncookies; i++)
+ d->cookies[i] = port->tx_bufs[dr->prod].cookies[i];
+
+ /* This has to be a non-SMP write barrier because we are writing
+ * to memory which is shared with the peer LDOM.
+ */
+ wmb();
+
+ d->hdr.state = VIO_DESC_READY;
+
+ err = __vnet_tx_trigger(port);
+ if (unlikely(err < 0)) {
+ printk(KERN_INFO PFX "%s: TX trigger error %d\n",
+ dev->name, err);
+ d->hdr.state = VIO_DESC_FREE;
+ dev->stats.tx_carrier_errors++;
+ goto out_dropped_unlock;
+ }
+
+ dev->stats.tx_packets++;
+ dev->stats.tx_bytes += skb->len;
+
+ dr->prod = (dr->prod + 1) & (VNET_TX_RING_SIZE - 1);
+ if (unlikely(vnet_tx_dring_avail(dr) < 2)) {
+ netif_stop_queue(dev);
+ if (vnet_tx_dring_avail(dr) > VNET_TX_WAKEUP_THRESH(dr))
+ netif_wake_queue(dev);
+ }
+
+ spin_unlock_irqrestore(&port->vio.lock, flags);
+
+ dev_kfree_skb(skb);
+
+ dev->trans_start = jiffies;
+ return NETDEV_TX_OK;
+
+out_dropped_unlock:
+ spin_unlock_irqrestore(&port->vio.lock, flags);
+
+out_dropped:
+ dev_kfree_skb(skb);
+ dev->stats.tx_dropped++;
+ return NETDEV_TX_OK;
+}
+
+static void vnet_tx_timeout(struct net_device *dev)
+{
+ /* XXX Implement me XXX */
+}
+
+static int vnet_open(struct net_device *dev)
+{
+ netif_carrier_on(dev);
+ netif_start_queue(dev);
+
+ return 0;
+}
+
+static int vnet_close(struct net_device *dev)
+{
+ netif_stop_queue(dev);
+ netif_carrier_off(dev);
+
+ return 0;
+}
+
+static void vnet_set_rx_mode(struct net_device *dev)
+{
+ /* XXX Implement multicast support XXX */
+}
+
+static int vnet_change_mtu(struct net_device *dev, int new_mtu)
+{
+ if (new_mtu != ETH_DATA_LEN)
+ return -EINVAL;
+
+ dev->mtu = new_mtu;
+ return 0;
+}
+
+static int vnet_set_mac_addr(struct net_device *dev, void *p)
+{
+ return -EINVAL;
+}
+
+static void vnet_get_drvinfo(struct net_device *dev,
+ struct ethtool_drvinfo *info)
+{
+ strcpy(info->driver, DRV_MODULE_NAME);
+ strcpy(info->version, DRV_MODULE_VERSION);
+}
+
+static u32 vnet_get_msglevel(struct net_device *dev)
+{
+ struct vnet *vp = netdev_priv(dev);
+ return vp->msg_enable;
+}
+
+static void vnet_set_msglevel(struct net_device *dev, u32 value)
+{
+ struct vnet *vp = netdev_priv(dev);
+ vp->msg_enable = value;
+}
+
+static const struct ethtool_ops vnet_ethtool_ops = {
+ .get_drvinfo = vnet_get_drvinfo,
+ .get_msglevel = vnet_get_msglevel,
+ .set_msglevel = vnet_set_msglevel,
+ .get_link = ethtool_op_get_link,
+ .get_perm_addr = ethtool_op_get_perm_addr,
+};
+
+static void vnet_port_free_tx_bufs(struct vnet_port *port)
+{
+ struct vio_dring_state *dr;
+ int i;
+
+ dr = &port->vio.drings[VIO_DRIVER_TX_RING];
+ if (dr->base) {
+ ldc_free_exp_dring(port->vio.lp, dr->base,
+ (dr->entry_size * dr->num_entries),
+ dr->cookies, dr->ncookies);
+ dr->base = NULL;
+ dr->entry_size = 0;
+ dr->num_entries = 0;
+ dr->pending = 0;
+ dr->ncookies = 0;
+ }
+
+ for (i = 0; i < VNET_TX_RING_SIZE; i++) {
+ void *buf = port->tx_bufs[i].buf;
+
+ if (!buf)
+ continue;
+
+ ldc_unmap(port->vio.lp,
+ port->tx_bufs[i].cookies,
+ port->tx_bufs[i].ncookies);
+
+ kfree(buf);
+ port->tx_bufs[i].buf = NULL;
+ }
+}
+
+static int __devinit vnet_port_alloc_tx_bufs(struct vnet_port *port)
+{
+ struct vio_dring_state *dr;
+ unsigned long len;
+ int i, err, ncookies;
+ void *dring;
+
+ for (i = 0; i < VNET_TX_RING_SIZE; i++) {
+ void *buf = kzalloc(ETH_FRAME_LEN + 8, GFP_KERNEL);
+ int map_len = (ETH_FRAME_LEN + 7) & ~7;
+
+ err = -ENOMEM;
+ if (!buf) {
+ printk(KERN_ERR "TX buffer allocation failure\n");
+ goto err_out;
+ }
+ err = -EFAULT;
+ if ((unsigned long)buf & (8UL - 1)) {
+ printk(KERN_ERR "TX buffer misaligned\n");
+ kfree(buf);
+ goto err_out;
+ }
+
+ err = ldc_map_single(port->vio.lp, buf, map_len,
+ port->tx_bufs[i].cookies, 2,
+ (LDC_MAP_SHADOW |
+ LDC_MAP_DIRECT |
+ LDC_MAP_RW));
+ if (err < 0) {
+ kfree(buf);
+ goto err_out;
+ }
+ port->tx_bufs[i].buf = buf;
+ port->tx_bufs[i].ncookies = err;
+ }
+
+ dr = &port->vio.drings[VIO_DRIVER_TX_RING];
+
+ len = (VNET_TX_RING_SIZE *
+ (sizeof(struct vio_net_desc) +
+ (sizeof(struct ldc_trans_cookie) * 2)));
+
+ ncookies = VIO_MAX_RING_COOKIES;
+ dring = ldc_alloc_exp_dring(port->vio.lp, len,
+ dr->cookies, &ncookies,
+ (LDC_MAP_SHADOW |
+ LDC_MAP_DIRECT |
+ LDC_MAP_RW));
+ if (IS_ERR(dring)) {
+ err = PTR_ERR(dring);
+ goto err_out;
+ }
+
+ dr->base = dring;
+ dr->entry_size = (sizeof(struct vio_net_desc) +
+ (sizeof(struct ldc_trans_cookie) * 2));
+ dr->num_entries = VNET_TX_RING_SIZE;
+ dr->prod = dr->cons = 0;
+ dr->pending = VNET_TX_RING_SIZE;
+ dr->ncookies = ncookies;
+
+ return 0;
+
+err_out:
+ vnet_port_free_tx_bufs(port);
+
+ return err;
+}
+
+static struct ldc_channel_config vnet_ldc_cfg = {
+ .event = vnet_event,
+ .mtu = 64,
+ .mode = LDC_MODE_UNRELIABLE,
+};
+
+static struct vio_driver_ops vnet_vio_ops = {
+ .send_attr = vnet_send_attr,
+ .handle_attr = vnet_handle_attr,
+ .handshake_complete = vnet_handshake_complete,
+};
+
+const char *remote_macaddr_prop = "remote-mac-address";
+
+static int __devinit vnet_port_probe(struct vio_dev *vdev,
+ const struct vio_device_id *id)
+{
+ struct mdesc_handle *hp;
+ struct vnet_port *port;
+ unsigned long flags;
+ struct vnet *vp;
+ const u64 *rmac;
+ int len, i, err, switch_port;
+
+ vp = dev_get_drvdata(vdev->dev.parent);
+ if (!vp) {
+ printk(KERN_ERR PFX "Cannot find port parent vnet.\n");
+ return -ENODEV;
+ }
+
+ hp = mdesc_grab();
+
+ rmac = mdesc_get_property(hp, vdev->mp, remote_macaddr_prop, &len);
+ err = -ENODEV;
+ if (!rmac) {
+ printk(KERN_ERR PFX "Port lacks %s property.\n",
+ remote_macaddr_prop);
+ goto err_out_put_mdesc;
+ }
+
+ port = kzalloc(sizeof(*port), GFP_KERNEL);
+ err = -ENOMEM;
+ if (!port) {
+ printk(KERN_ERR PFX "Cannot allocate vnet_port.\n");
+ goto err_out_put_mdesc;
+ }
+
+ for (i = 0; i < ETH_ALEN; i++)
+ port->raddr[i] = (*rmac >> (5 - i) * 8) & 0xff;
+
+ port->vp = vp;
+
+ err = vio_driver_init(&port->vio, vdev, VDEV_NETWORK,
+ vnet_versions, ARRAY_SIZE(vnet_versions),
+ &vnet_vio_ops, vp->dev->name);
+ if (err)
+ goto err_out_free_port;
+
+ err = vio_ldc_alloc(&port->vio, &vnet_ldc_cfg, port);
+ if (err)
+ goto err_out_free_port;
+
+ err = vnet_port_alloc_tx_bufs(port);
+ if (err)
+ goto err_out_free_ldc;
+
+ INIT_HLIST_NODE(&port->hash);
+ INIT_LIST_HEAD(&port->list);
+
+ switch_port = 0;
+ if (mdesc_get_property(hp, vdev->mp, "switch-port", NULL) != NULL)
+ switch_port = 1;
+
+ spin_lock_irqsave(&vp->lock, flags);
+ if (switch_port)
+ list_add(&port->list, &vp->port_list);
+ else
+ list_add_tail(&port->list, &vp->port_list);
+ hlist_add_head(&port->hash, &vp->port_hash[vnet_hashfn(port->raddr)]);
+ spin_unlock_irqrestore(&vp->lock, flags);
+
+ dev_set_drvdata(&vdev->dev, port);
+
+ printk(KERN_INFO "%s: PORT ( remote-mac ", vp->dev->name);
+ for (i = 0; i < 6; i++)
+ printk("%2.2x%c", port->raddr[i], i == 5 ? ' ' : ':');
+ if (switch_port)
+ printk("switch-port ");
+ printk(")\n");
+
+ vio_port_up(&port->vio);
+
+ mdesc_release(hp);
+
+ return 0;
+
+err_out_free_ldc:
+ vio_ldc_free(&port->vio);
+
+err_out_free_port:
+ kfree(port);
+
+err_out_put_mdesc:
+ mdesc_release(hp);
+ return err;
+}
+
+static int vnet_port_remove(struct vio_dev *vdev)
+{
+ struct vnet_port *port = dev_get_drvdata(&vdev->dev);
+
+ if (port) {
+ struct vnet *vp = port->vp;
+ unsigned long flags;
+
+ del_timer_sync(&port->vio.timer);
+
+ spin_lock_irqsave(&vp->lock, flags);
+ list_del(&port->list);
+ hlist_del(&port->hash);
+ spin_unlock_irqrestore(&vp->lock, flags);
+
+ vnet_port_free_tx_bufs(port);
+ vio_ldc_free(&port->vio);
+
+ dev_set_drvdata(&vdev->dev, NULL);
+
+ kfree(port);
+ }
+ return 0;
+}
+
+static struct vio_device_id vnet_port_match[] = {
+ {
+ .type = "vnet-port",
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(vio, vnet_match);
+
+static struct vio_driver vnet_port_driver = {
+ .id_table = vnet_port_match,
+ .probe = vnet_port_probe,
+ .remove = vnet_port_remove,
+ .driver = {
+ .name = "vnet_port",
+ .owner = THIS_MODULE,
+ }
+};
+
+const char *local_mac_prop = "local-mac-address";
+
+static int __devinit vnet_probe(struct vio_dev *vdev,
+ const struct vio_device_id *id)
+{
+ static int vnet_version_printed;
+ struct mdesc_handle *hp;
+ struct net_device *dev;
+ struct vnet *vp;
+ const u64 *mac;
+ int err, i, len;
+
+ if (vnet_version_printed++ == 0)
+ printk(KERN_INFO "%s", version);
+
+ hp = mdesc_grab();
+
+ mac = mdesc_get_property(hp, vdev->mp, local_mac_prop, &len);
+ if (!mac) {
+ printk(KERN_ERR PFX "vnet lacks %s property.\n",
+ local_mac_prop);
+ err = -ENODEV;
+ goto err_out;
+ }
+
+ dev = alloc_etherdev(sizeof(*vp));
+ if (!dev) {
+ printk(KERN_ERR PFX "Etherdev alloc failed, aborting.\n");
+ err = -ENOMEM;
+ goto err_out;
+ }
+
+ for (i = 0; i < ETH_ALEN; i++)
+ dev->dev_addr[i] = (*mac >> (5 - i) * 8) & 0xff;
+
+ memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
+
+ SET_NETDEV_DEV(dev, &vdev->dev);
+
+ vp = netdev_priv(dev);
+
+ spin_lock_init(&vp->lock);
+ vp->dev = dev;
+ vp->vdev = vdev;
+
+ INIT_LIST_HEAD(&vp->port_list);
+ for (i = 0; i < VNET_PORT_HASH_SIZE; i++)
+ INIT_HLIST_HEAD(&vp->port_hash[i]);
+
+ dev->open = vnet_open;
+ dev->stop = vnet_close;
+ dev->set_multicast_list = vnet_set_rx_mode;
+ dev->set_mac_address = vnet_set_mac_addr;
+ dev->tx_timeout = vnet_tx_timeout;
+ dev->ethtool_ops = &vnet_ethtool_ops;
+ dev->watchdog_timeo = VNET_TX_TIMEOUT;
+ dev->change_mtu = vnet_change_mtu;
+ dev->hard_start_xmit = vnet_start_xmit;
+
+ err = register_netdev(dev);
+ if (err) {
+ printk(KERN_ERR PFX "Cannot register net device, "
+ "aborting.\n");
+ goto err_out_free_dev;
+ }
+
+ printk(KERN_INFO "%s: Sun LDOM vnet ", dev->name);
+
+ for (i = 0; i < 6; i++)
+ printk("%2.2x%c", dev->dev_addr[i], i == 5 ? '\n' : ':');
+
+ dev_set_drvdata(&vdev->dev, vp);
+
+ mdesc_release(hp);
+
+ return 0;
+
+err_out_free_dev:
+ free_netdev(dev);
+
+err_out:
+ mdesc_release(hp);
+ return err;
+}
+
+static int vnet_remove(struct vio_dev *vdev)
+{
+
+ struct vnet *vp = dev_get_drvdata(&vdev->dev);
+
+ if (vp) {
+ /* XXX unregister port, or at least check XXX */
+ unregister_netdevice(vp->dev);
+ dev_set_drvdata(&vdev->dev, NULL);
+ }
+ return 0;
+}
+
+static struct vio_device_id vnet_match[] = {
+ {
+ .type = "network",
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(vio, vnet_match);
+
+static struct vio_driver vnet_driver = {
+ .id_table = vnet_match,
+ .probe = vnet_probe,
+ .remove = vnet_remove,
+ .driver = {
+ .name = "vnet",
+ .owner = THIS_MODULE,
+ }
+};
+
+static int __init vnet_init(void)
+{
+ int err = vio_register_driver(&vnet_driver);
+
+ if (!err) {
+ err = vio_register_driver(&vnet_port_driver);
+ if (err)
+ vio_unregister_driver(&vnet_driver);
+ }
+
+ return err;
+}
+
+static void __exit vnet_exit(void)
+{
+ vio_unregister_driver(&vnet_port_driver);
+ vio_unregister_driver(&vnet_driver);
+}
+
+module_init(vnet_init);
+module_exit(vnet_exit);
diff --git a/drivers/net/sunvnet.h b/drivers/net/sunvnet.h
new file mode 100644
index 00000000000..1c887302d46
--- /dev/null
+++ b/drivers/net/sunvnet.h
@@ -0,0 +1,70 @@
+#ifndef _SUNVNET_H
+#define _SUNVNET_H
+
+#define DESC_NCOOKIES(entry_size) \
+ ((entry_size) - sizeof(struct vio_net_desc))
+
+/* length of time before we decide the hardware is borked,
+ * and dev->tx_timeout() should be called to fix the problem
+ */
+#define VNET_TX_TIMEOUT (5 * HZ)
+
+#define VNET_TX_RING_SIZE 512
+#define VNET_TX_WAKEUP_THRESH(dr) ((dr)->pending / 4)
+
+/* VNET packets are sent in buffers with the first 6 bytes skipped
+ * so that after the ethernet header the IPv4/IPv6 headers are aligned
+ * properly.
+ */
+#define VNET_PACKET_SKIP 6
+
+struct vnet_tx_entry {
+ void *buf;
+ unsigned int ncookies;
+ struct ldc_trans_cookie cookies[2];
+};
+
+struct vnet;
+struct vnet_port {
+ struct vio_driver_state vio;
+
+ struct hlist_node hash;
+ u8 raddr[ETH_ALEN];
+
+ struct vnet *vp;
+
+ struct vnet_tx_entry tx_bufs[VNET_TX_RING_SIZE];
+
+ struct list_head list;
+};
+
+static inline struct vnet_port *to_vnet_port(struct vio_driver_state *vio)
+{
+ return container_of(vio, struct vnet_port, vio);
+}
+
+#define VNET_PORT_HASH_SIZE 16
+#define VNET_PORT_HASH_MASK (VNET_PORT_HASH_SIZE - 1)
+
+static inline unsigned int vnet_hashfn(u8 *mac)
+{
+ unsigned int val = mac[4] ^ mac[5];
+
+ return val & (VNET_PORT_HASH_MASK);
+}
+
+struct vnet {
+ /* Protects port_list and port_hash. */
+ spinlock_t lock;
+
+ struct net_device *dev;
+
+ u32 msg_enable;
+ struct vio_dev *vdev;
+
+ struct list_head port_list;
+
+ struct hlist_head port_hash[VNET_PORT_HASH_SIZE];
+};
+
+#endif /* _SUNVNET_H */
diff --git a/drivers/net/wan/Kconfig b/drivers/net/wan/Kconfig
index 4fc8681bc11..a3df09ee729 100644
--- a/drivers/net/wan/Kconfig
+++ b/drivers/net/wan/Kconfig
@@ -61,7 +61,7 @@ config COSA
#
config LANMEDIA
tristate "LanMedia Corp. SSI/V.35, T1/E1, HSSI, T3 boards"
- depends on PCI
+ depends on PCI && VIRT_TO_BUS
---help---
Driver for the following Lan Media family of serial boards:
diff --git a/drivers/parport/Kconfig b/drivers/parport/Kconfig
index f46c69e4ed8..09c93ff932b 100644
--- a/drivers/parport/Kconfig
+++ b/drivers/parport/Kconfig
@@ -5,11 +5,9 @@
# Parport configuration.
#
-menu "Parallel port support"
- depends on HAS_IOMEM
-
-config PARPORT
+menuconfig PARPORT
tristate "Parallel port support"
+ depends on HAS_IOMEM
---help---
If you want to use devices connected to your machine's parallel port
(the connector at the computer with 25 holes), e.g. printer, ZIP
@@ -33,9 +31,11 @@ config PARPORT
If unsure, say Y.
+if PARPORT
+
config PARPORT_PC
tristate "PC-style hardware"
- depends on PARPORT && (!SPARC64 || PCI) && !SPARC32 && !M32R && !FRV
+ depends on (!SPARC64 || PCI) && !SPARC32 && !M32R && !FRV
---help---
You should say Y here if you have a PC-style parallel port. All
IBM PC compatible computers and some Alphas have PC-style
@@ -85,7 +85,7 @@ config PARPORT_PC_PCMCIA
config PARPORT_IP32
tristate "SGI IP32 builtin port (EXPERIMENTAL)"
- depends on SGI_IP32 && PARPORT && EXPERIMENTAL
+ depends on SGI_IP32 && EXPERIMENTAL
select PARPORT_NOT_PC
help
Say Y here if you need support for the parallel port on
@@ -94,7 +94,7 @@ config PARPORT_IP32
config PARPORT_AMIGA
tristate "Amiga builtin port"
- depends on AMIGA && PARPORT
+ depends on AMIGA
select PARPORT_NOT_PC
help
Say Y here if you need support for the parallel port hardware on
@@ -103,7 +103,7 @@ config PARPORT_AMIGA
config PARPORT_MFC3
tristate "Multiface III parallel port"
- depends on ZORRO && PARPORT
+ depends on ZORRO
select PARPORT_NOT_PC
help
Say Y here if you need parallel port support for the MFC3 card.
@@ -112,7 +112,7 @@ config PARPORT_MFC3
config PARPORT_ATARI
tristate "Atari hardware"
- depends on ATARI && PARPORT
+ depends on ATARI
select PARPORT_NOT_PC
help
Say Y here if you need support for the parallel port hardware on
@@ -122,12 +122,11 @@ config PARPORT_ATARI
config PARPORT_GSC
tristate
default GSC
- depends on PARPORT
select PARPORT_NOT_PC
config PARPORT_SUNBPP
tristate "Sparc hardware (EXPERIMENTAL)"
- depends on SBUS && PARPORT && EXPERIMENTAL
+ depends on SBUS && EXPERIMENTAL
select PARPORT_NOT_PC
help
This driver provides support for the bidirectional parallel port
@@ -136,7 +135,6 @@ config PARPORT_SUNBPP
config PARPORT_AX88796
tristate "AX88796 Parallel Port"
- depends on PARPORT
select PARPORT_NOT_PC
help
Say Y here if you need support for the parallel port hardware on
@@ -148,7 +146,6 @@ config PARPORT_AX88796
config PARPORT_1284
bool "IEEE 1284 transfer modes"
- depends on PARPORT
help
If you have a printer that supports status readback or device ID, or
want to use a device that uses enhanced parallel port transfer modes
@@ -159,5 +156,4 @@ config PARPORT_1284
config PARPORT_NOT_PC
bool
-endmenu
-
+endif # PARPORT
diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c
index 7bfbad57879..5d58ad55d85 100644
--- a/drivers/parport/parport_pc.c
+++ b/drivers/parport/parport_pc.c
@@ -2424,7 +2424,6 @@ static int __devinit sio_ite_8872_probe (struct pci_dev *pdev, int autoirq,
u32 ite8872set;
u32 ite8872_lpt, ite8872_lpthi;
u8 ite8872_irq, type;
- char *fake_name = "parport probe";
int irq;
int i;
@@ -2432,11 +2431,11 @@ static int __devinit sio_ite_8872_probe (struct pci_dev *pdev, int autoirq,
// make sure which one chip
for(i = 0; i < 5; i++) {
- base_res = request_region(inta_addr[i], 0x8, fake_name);
+ base_res = request_region(inta_addr[i], 32, "it887x");
if (base_res) {
int test;
pci_write_config_dword (pdev, 0x60,
- 0xe7000000 | inta_addr[i]);
+ 0xe5000000 | inta_addr[i]);
pci_write_config_dword (pdev, 0x78,
0x00000000 | inta_addr[i]);
test = inb (inta_addr[i]);
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 10dbdec8041..1b7b2812bf2 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -20,7 +20,7 @@
#include <linux/stat.h>
#include <linux/topology.h>
#include <linux/mm.h>
-
+#include <linux/capability.h>
#include "pci.h"
static int sysfs_initialized; /* = 0 */
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index a7bce75c673..34b8dae0d90 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -22,6 +22,18 @@ EXPORT_SYMBOL(pci_root_buses);
LIST_HEAD(pci_devices);
+/*
+ * Some device drivers need know if pci is initiated.
+ * Basically, we think pci is not initiated when there
+ * is no device in list of pci_devices.
+ */
+int no_pci_devices(void)
+{
+ return list_empty(&pci_devices);
+}
+
+EXPORT_SYMBOL(no_pci_devices);
+
#ifdef HAVE_PCI_LEGACY
/**
* pci_create_legacy_files - create legacy I/O port and memory files
diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c
index cfa0dfe61b1..90adc62d07f 100644
--- a/drivers/pci/proc.c
+++ b/drivers/pci/proc.c
@@ -11,7 +11,7 @@
#include <linux/module.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
-
+#include <linux/capability.h>
#include <asm/uaccess.h>
#include <asm/byteorder.h>
#include "pci.h"
diff --git a/drivers/pci/search.c b/drivers/pci/search.c
index 9f7090fa877..c6e79d01ce3 100644
--- a/drivers/pci/search.c
+++ b/drivers/pci/search.c
@@ -202,7 +202,7 @@ static struct pci_dev * pci_find_subsys(unsigned int vendor,
* can cause some machines to crash. So here we detect and flag that
* situation and bail out early.
*/
- if (unlikely(list_empty(&pci_devices)))
+ if (unlikely(no_pci_devices()))
return NULL;
down_read(&pci_bus_sem);
n = from ? from->global_list.next : pci_devices.next;
@@ -277,7 +277,7 @@ pci_get_subsys(unsigned int vendor, unsigned int device,
* can cause some machines to crash. So here we detect and flag that
* situation and bail out early.
*/
- if (unlikely(list_empty(&pci_devices)))
+ if (unlikely(no_pci_devices()))
return NULL;
down_read(&pci_bus_sem);
n = from ? from->global_list.next : pci_devices.next;
diff --git a/drivers/pnp/Kconfig b/drivers/pnp/Kconfig
index 1959cef8e9d..821933f9aa5 100644
--- a/drivers/pnp/Kconfig
+++ b/drivers/pnp/Kconfig
@@ -2,11 +2,9 @@
# Plug and Play configuration
#
-menu "Plug and Play support"
- depends on HAS_IOMEM
-
-config PNP
+menuconfig PNP
bool "Plug and Play support"
+ depends on HAS_IOMEM
depends on ISA || ACPI
---help---
Plug and Play (PnP) is a standard for peripherals which allows those
@@ -22,15 +20,15 @@ config PNP
If unsure, say Y.
+if PNP
+
config PNP_DEBUG
bool "PnP Debug Messages"
- depends on PNP
help
Say Y if you want the Plug and Play Layer to print debug messages.
This is useful if you are developing a PnP driver or troubleshooting.
comment "Protocols"
- depends on PNP
source "drivers/pnp/isapnp/Kconfig"
@@ -38,5 +36,4 @@ source "drivers/pnp/pnpbios/Kconfig"
source "drivers/pnp/pnpacpi/Kconfig"
-endmenu
-
+endif # PNP
diff --git a/drivers/pnp/isapnp/Kconfig b/drivers/pnp/isapnp/Kconfig
index 578651eeb4b..f1ef36673ad 100644
--- a/drivers/pnp/isapnp/Kconfig
+++ b/drivers/pnp/isapnp/Kconfig
@@ -3,7 +3,7 @@
#
config ISAPNP
bool "ISA Plug and Play support"
- depends on PNP && ISA
+ depends on ISA
help
Say Y here if you would like support for ISA Plug and Play devices.
Some information is in <file:Documentation/isapnp.txt>.
diff --git a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c
index a0b158704ca..914d00c423a 100644
--- a/drivers/pnp/isapnp/core.c
+++ b/drivers/pnp/isapnp/core.c
@@ -370,8 +370,6 @@ static int __init isapnp_read_tag(unsigned char *type, unsigned short *size)
#if 0
printk(KERN_DEBUG "tag = 0x%x, type = 0x%x, size = %i\n", tag, *type, *size);
#endif
- if (type == 0) /* wrong type */
- return -1;
if (*type == 0xff && *size == 0xffff) /* probably invalid data */
return -1;
return 0;
diff --git a/drivers/pnp/pnpbios/Kconfig b/drivers/pnp/pnpbios/Kconfig
index fab848cae89..b986d9fa3b9 100644
--- a/drivers/pnp/pnpbios/Kconfig
+++ b/drivers/pnp/pnpbios/Kconfig
@@ -3,7 +3,7 @@
#
config PNPBIOS
bool "Plug and Play BIOS support (EXPERIMENTAL)"
- depends on PNP && ISA && X86 && EXPERIMENTAL
+ depends on ISA && X86 && EXPERIMENTAL
default n
---help---
Linux uses the PNPBIOS as defined in "Plug and Play BIOS
diff --git a/drivers/sbus/char/cpwatchdog.c b/drivers/sbus/char/cpwatchdog.c
index 022e869c44d..7b5773d8821 100644
--- a/drivers/sbus/char/cpwatchdog.c
+++ b/drivers/sbus/char/cpwatchdog.c
@@ -24,6 +24,7 @@
#include <linux/ioport.h>
#include <linux/timer.h>
#include <linux/smp_lock.h>
+#include <linux/io.h>
#include <asm/irq.h>
#include <asm/ebus.h>
#include <asm/oplib.h>
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 9d2119b53ac..372723161c9 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -545,7 +545,7 @@ config SCSI_HPTIOP
config SCSI_BUSLOGIC
tristate "BusLogic SCSI support"
- depends on (PCI || ISA || MCA) && SCSI && ISA_DMA_API
+ depends on (PCI || ISA || MCA) && SCSI && ISA_DMA_API && VIRT_TO_BUS
---help---
This is support for BusLogic MultiMaster and FlashPoint SCSI Host
Adapters. Consult the SCSI-HOWTO, available from
diff --git a/drivers/serial/68360serial.c b/drivers/serial/68360serial.c
index 68817a7d8c0..2aa6bfe8fdb 100644
--- a/drivers/serial/68360serial.c
+++ b/drivers/serial/68360serial.c
@@ -934,8 +934,6 @@ static void change_speed(ser_info_t *info)
/*
* Set up parity check flag
*/
-#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
-
info->read_status_mask = (BD_SC_EMPTY | BD_SC_OV);
if (I_INPCK(info->tty))
info->read_status_mask |= BD_SC_FR | BD_SC_PR;
@@ -1527,11 +1525,6 @@ static void rs_360_set_termios(struct tty_struct *tty, struct ktermios *old_term
{
ser_info_t *info = (ser_info_t *)tty->driver_data;
- if ( (tty->termios->c_cflag == old_termios->c_cflag)
- && ( RELEVANT_IFLAG(tty->termios->c_iflag)
- == RELEVANT_IFLAG(old_termios->c_iflag)))
- return;
-
change_speed(info);
#ifdef modem_control
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index c84dab083a8..0b3ec38ae61 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -2514,12 +2514,18 @@ static int __init serial8250_console_setup(struct console *co, char *options)
return uart_set_options(port, co, baud, parity, bits, flow);
}
+static int __init serial8250_console_early_setup(void)
+{
+ return serial8250_find_port_for_earlycon();
+}
+
static struct uart_driver serial8250_reg;
static struct console serial8250_console = {
.name = "ttyS",
.write = serial8250_console_write,
.device = uart_console_device,
.setup = serial8250_console_setup,
+ .early_setup = serial8250_console_early_setup,
.flags = CON_PRINTBUFFER,
.index = -1,
.data = &serial8250_reg,
@@ -2533,7 +2539,7 @@ static int __init serial8250_console_init(void)
}
console_initcall(serial8250_console_init);
-static int __init find_port(struct uart_port *p)
+int serial8250_find_port(struct uart_port *p)
{
int line;
struct uart_port *port;
@@ -2546,26 +2552,6 @@ static int __init find_port(struct uart_port *p)
return -ENODEV;
}
-int __init serial8250_start_console(struct uart_port *port, char *options)
-{
- int line;
-
- line = find_port(port);
- if (line < 0)
- return -ENODEV;
-
- add_preferred_console("ttyS", line, options);
- printk("Adding console on ttyS%d at %s 0x%lx (options '%s')\n",
- line, port->iotype == UPIO_MEM ? "MMIO" : "I/O port",
- port->iotype == UPIO_MEM ? (unsigned long) port->mapbase :
- (unsigned long) port->iobase, options);
- if (!(serial8250_console.flags & CON_ENABLED)) {
- serial8250_console.flags &= ~CON_PRINTBUFFER;
- register_console(&serial8250_console);
- }
- return line;
-}
-
#define SERIAL8250_CONSOLE &serial8250_console
#else
#define SERIAL8250_CONSOLE NULL
diff --git a/drivers/serial/8250_early.c b/drivers/serial/8250_early.c
index 7e511199b4c..947c20507e1 100644
--- a/drivers/serial/8250_early.c
+++ b/drivers/serial/8250_early.c
@@ -17,13 +17,11 @@
* we locate the device directly by its MMIO or I/O port address.
*
* The user can specify the device directly, e.g.,
- * console=uart,io,0x3f8,9600n8
- * console=uart,mmio,0xff5e0000,115200n8
- * or platform code can call early_uart_console_init() to set
- * the early UART device.
- *
- * After the normal serial driver starts, we try to locate the
- * matching ttyS device and start a console there.
+ * earlycon=uart8250,io,0x3f8,9600n8
+ * earlycon=uart8250,mmio,0xff5e0000,115200n8
+ * or
+ * console=uart8250,io,0x3f8,9600n8
+ * console=uart8250,mmio,0xff5e0000,115200n8
*/
#include <linux/tty.h>
@@ -32,17 +30,21 @@
#include <linux/serial_core.h>
#include <linux/serial_reg.h>
#include <linux/serial.h>
+#include <linux/serial_8250.h>
#include <asm/io.h>
#include <asm/serial.h>
+#ifdef CONFIG_FIX_EARLYCON_MEM
+#include <asm/pgtable.h>
+#include <asm/fixmap.h>
+#endif
-struct early_uart_device {
+struct early_serial8250_device {
struct uart_port port;
char options[16]; /* e.g., 115200n8 */
unsigned int baud;
};
-static struct early_uart_device early_device __initdata;
-static int early_uart_registered __initdata;
+static struct early_serial8250_device early_device;
static unsigned int __init serial_in(struct uart_port *port, int offset)
{
@@ -80,7 +82,7 @@ static void __init putc(struct uart_port *port, int c)
serial_out(port, UART_TX, c);
}
-static void __init early_uart_write(struct console *console, const char *s, unsigned int count)
+static void __init early_serial8250_write(struct console *console, const char *s, unsigned int count)
{
struct uart_port *port = &early_device.port;
unsigned int ier;
@@ -111,7 +113,7 @@ static unsigned int __init probe_baud(struct uart_port *port)
return (port->uartclk / 16) / quot;
}
-static void __init init_port(struct early_uart_device *device)
+static void __init init_port(struct early_serial8250_device *device)
{
struct uart_port *port = &device->port;
unsigned int divisor;
@@ -130,10 +132,9 @@ static void __init init_port(struct early_uart_device *device)
serial_out(port, UART_LCR, c & ~UART_LCR_DLAB);
}
-static int __init parse_options(struct early_uart_device *device, char *options)
+static int __init parse_options(struct early_serial8250_device *device, char *options)
{
struct uart_port *port = &device->port;
- int mapsize = 64;
int mmio, length;
if (!options)
@@ -143,12 +144,18 @@ static int __init parse_options(struct early_uart_device *device, char *options)
if (!strncmp(options, "mmio,", 5)) {
port->iotype = UPIO_MEM;
port->mapbase = simple_strtoul(options + 5, &options, 0);
- port->membase = ioremap(port->mapbase, mapsize);
+#ifdef CONFIG_FIX_EARLYCON_MEM
+ set_fixmap_nocache(FIX_EARLYCON_MEM_BASE, port->mapbase & PAGE_MASK);
+ port->membase = (void __iomem *)__fix_to_virt(FIX_EARLYCON_MEM_BASE);
+ port->membase += port->mapbase & ~PAGE_MASK;
+#else
+ port->membase = ioremap(port->mapbase, 64);
if (!port->membase) {
printk(KERN_ERR "%s: Couldn't ioremap 0x%lx\n",
__FUNCTION__, port->mapbase);
return -ENOMEM;
}
+#endif
mmio = 1;
} else if (!strncmp(options, "io,", 3)) {
port->iotype = UPIO_PORT;
@@ -175,9 +182,16 @@ static int __init parse_options(struct early_uart_device *device, char *options)
return 0;
}
-static int __init early_uart_setup(struct console *console, char *options)
+static struct console early_serial8250_console __initdata = {
+ .name = "uart",
+ .write = early_serial8250_write,
+ .flags = CON_PRINTBUFFER | CON_BOOT,
+ .index = -1,
+};
+
+static int __init early_serial8250_setup(char *options)
{
- struct early_uart_device *device = &early_device;
+ struct early_serial8250_device *device = &early_device;
int err;
if (device->port.membase || device->port.iobase)
@@ -190,61 +204,48 @@ static int __init early_uart_setup(struct console *console, char *options)
return 0;
}
-static struct console early_uart_console __initdata = {
- .name = "uart",
- .write = early_uart_write,
- .setup = early_uart_setup,
- .flags = CON_PRINTBUFFER,
- .index = -1,
-};
-
-static int __init early_uart_console_init(void)
-{
- if (!early_uart_registered) {
- register_console(&early_uart_console);
- early_uart_registered = 1;
- }
- return 0;
-}
-console_initcall(early_uart_console_init);
-
-int __init early_serial_console_init(char *cmdline)
+int __init setup_early_serial8250_console(char *cmdline)
{
char *options;
int err;
- options = strstr(cmdline, "console=uart,");
- if (!options)
- return -ENODEV;
+ options = strstr(cmdline, "uart8250,");
+ if (!options) {
+ options = strstr(cmdline, "uart,");
+ if (!options)
+ return 0;
+ }
options = strchr(cmdline, ',') + 1;
- if ((err = early_uart_setup(NULL, options)) < 0)
+ if ((err = early_serial8250_setup(options)) < 0)
return err;
- return early_uart_console_init();
+
+ register_console(&early_serial8250_console);
+
+ return 0;
}
-static int __init early_uart_console_switch(void)
+int __init serial8250_find_port_for_earlycon(void)
{
- struct early_uart_device *device = &early_device;
+ struct early_serial8250_device *device = &early_device;
struct uart_port *port = &device->port;
- int mmio, line;
+ int line;
+ int ret;
- if (!(early_uart_console.flags & CON_ENABLED))
- return 0;
+ if (!device->port.membase && !device->port.iobase)
+ return -ENODEV;
- /* Try to start the normal driver on a matching line. */
- mmio = (port->iotype == UPIO_MEM);
- line = serial8250_start_console(port, device->options);
+ line = serial8250_find_port(port);
if (line < 0)
- printk("No ttyS device at %s 0x%lx for console\n",
- mmio ? "MMIO" : "I/O port",
- mmio ? port->mapbase :
- (unsigned long) port->iobase);
+ return -ENODEV;
- unregister_console(&early_uart_console);
- if (mmio)
- iounmap(port->membase);
+ ret = update_console_cmdline("uart", 8250,
+ "ttyS", line, device->options);
+ if (ret < 0)
+ ret = update_console_cmdline("uart", 0,
+ "ttyS", line, device->options);
- return 0;
+ return ret;
}
-late_initcall(early_uart_console_switch);
+
+early_param("earlycon", setup_early_serial8250_console);
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 2adbed4e10f..cab42cbd920 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -62,8 +62,22 @@ config SERIAL_8250_CONSOLE
kernel will automatically use the first serial line, /dev/ttyS0, as
system console.
+ you can set that using a kernel command line option such as
+ "console=uart8250,io,0x3f8,9600n8"
+ "console=uart8250,mmio,0xff5e0000,115200n8".
+ and it will switch to normal serial console when correponding port is
+ ready.
+ "earlycon=uart8250,io,0x3f8,9600n8"
+ "earlycon=uart8250,mmio,0xff5e0000,115200n8".
+ it will not only setup early console.
+
If unsure, say N.
+config FIX_EARLYCON_MEM
+ bool
+ depends on X86
+ default y
+
config SERIAL_8250_GSC
tristate
depends on SERIAL_8250 && GSC
diff --git a/drivers/serial/atmel_serial.c b/drivers/serial/atmel_serial.c
index 3320bcd92c0..4d6b3c56d20 100644
--- a/drivers/serial/atmel_serial.c
+++ b/drivers/serial/atmel_serial.c
@@ -114,6 +114,7 @@ struct atmel_uart_port {
struct uart_port uart; /* uart */
struct clk *clk; /* uart clock */
unsigned short suspended; /* is port suspended? */
+ int break_active; /* break being received */
};
static struct atmel_uart_port atmel_ports[ATMEL_MAX_UART];
@@ -252,6 +253,7 @@ static void atmel_break_ctl(struct uart_port *port, int break_state)
*/
static void atmel_rx_chars(struct uart_port *port)
{
+ struct atmel_uart_port *atmel_port = (struct atmel_uart_port *) port;
struct tty_struct *tty = port->info->tty;
unsigned int status, ch, flg;
@@ -267,13 +269,29 @@ static void atmel_rx_chars(struct uart_port *port)
* note that the error handling code is
* out of the main execution path
*/
- if (unlikely(status & (ATMEL_US_PARE | ATMEL_US_FRAME | ATMEL_US_OVRE | ATMEL_US_RXBRK))) {
+ if (unlikely(status & (ATMEL_US_PARE | ATMEL_US_FRAME
+ | ATMEL_US_OVRE | ATMEL_US_RXBRK)
+ || atmel_port->break_active)) {
UART_PUT_CR(port, ATMEL_US_RSTSTA); /* clear error */
- if (status & ATMEL_US_RXBRK) {
+ if (status & ATMEL_US_RXBRK
+ && !atmel_port->break_active) {
status &= ~(ATMEL_US_PARE | ATMEL_US_FRAME); /* ignore side-effect */
port->icount.brk++;
+ atmel_port->break_active = 1;
+ UART_PUT_IER(port, ATMEL_US_RXBRK);
if (uart_handle_break(port))
goto ignore_char;
+ } else {
+ /*
+ * This is either the end-of-break
+ * condition or we've received at
+ * least one character without RXBRK
+ * being set. In both cases, the next
+ * RXBRK will indicate start-of-break.
+ */
+ UART_PUT_IDR(port, ATMEL_US_RXBRK);
+ status &= ~ATMEL_US_RXBRK;
+ atmel_port->break_active = 0;
}
if (status & ATMEL_US_PARE)
port->icount.parity++;
@@ -352,6 +370,16 @@ static irqreturn_t atmel_interrupt(int irq, void *dev_id)
/* Interrupt receive */
if (pending & ATMEL_US_RXRDY)
atmel_rx_chars(port);
+ else if (pending & ATMEL_US_RXBRK) {
+ /*
+ * End of break detected. If it came along
+ * with a character, atmel_rx_chars will
+ * handle it.
+ */
+ UART_PUT_CR(port, ATMEL_US_RSTSTA);
+ UART_PUT_IDR(port, ATMEL_US_RXBRK);
+ atmel_port->break_active = 0;
+ }
// TODO: All reads to CSR will clear these interrupts!
if (pending & ATMEL_US_RIIC) port->icount.rng++;
diff --git a/drivers/serial/ip22zilog.c b/drivers/serial/ip22zilog.c
index c3abfb39f31..f3257f708ef 100644
--- a/drivers/serial/ip22zilog.c
+++ b/drivers/serial/ip22zilog.c
@@ -862,6 +862,7 @@ ip22zilog_set_termios(struct uart_port *port, struct ktermios *termios,
up->cflag = termios->c_cflag;
ip22zilog_maybe_update_regs(up, ZILOG_CHANNEL_FROM_PORT(port));
+ uart_update_timeout(port, termios->c_cflag, baud);
spin_unlock_irqrestore(&up->port.lock, flags);
}
@@ -1017,6 +1018,8 @@ ip22serial_console_termios(struct console *con, char *options)
}
con->cflag = cflag | CS8; /* 8N1 */
+
+ uart_update_timeout(&ip22zilog_port_table[con->index].port, cflag, baud);
}
static int __init ip22zilog_console_setup(struct console *con, char *options)
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c
index 326020f86f7..9c57486c2e7 100644
--- a/drivers/serial/serial_core.c
+++ b/drivers/serial/serial_core.c
@@ -1910,6 +1910,12 @@ uart_set_options(struct uart_port *port, struct console *co,
if (flow == 'r')
termios.c_cflag |= CRTSCTS;
+ /*
+ * some uarts on other side don't support no flow control.
+ * So we set * DTR in host uart to make them happy
+ */
+ port->mctrl |= TIOCM_DTR;
+
port->ops->set_termios(port, &termios, NULL);
co->cflag = termios.c_cflag;
diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c
index 1f89496d530..672cd104253 100644
--- a/drivers/serial/sh-sci.c
+++ b/drivers/serial/sh-sci.c
@@ -367,7 +367,9 @@ static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag)
} else {
#ifdef CONFIG_CPU_SUBTYPE_SH7343
/* Nothing */
-#elif defined(CONFIG_CPU_SUBTYPE_SH7780) || defined(CONFIG_CPU_SUBTYPE_SH7785)
+#elif defined(CONFIG_CPU_SUBTYPE_SH7780) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7785) || \
+ defined(CONFIG_CPU_SUBTYPE_SHX3)
ctrl_outw(0x0080, SCSPTR0); /* Set RTS = 1 */
#else
ctrl_outw(0x0080, SCSPTR2); /* Set RTS = 1 */
diff --git a/drivers/serial/sh-sci.h b/drivers/serial/sh-sci.h
index fb04fb5f984..247fb66bf0f 100644
--- a/drivers/serial/sh-sci.h
+++ b/drivers/serial/sh-sci.h
@@ -53,7 +53,12 @@
# define SCIF_ORER 0x0001 /* overrun error bit */
# define SCSCR_INIT(port) 0x3a /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
# define SCIF_ONLY
-#elif defined(CONFIG_CPU_SUBTYPE_SH7750) || defined(CONFIG_CPU_SUBTYPE_SH7751)
+#elif defined(CONFIG_CPU_SUBTYPE_SH7750) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7750R) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7750S) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7091) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7751) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7751R)
# define SCSPTR1 0xffe0001c /* 8 bit SCI */
# define SCSPTR2 0xFFE80020 /* 16 bit SCIF */
# define SCIF_ORER 0x0001 /* overrun error bit */
@@ -73,7 +78,7 @@
# define SCPDR 0xA4050136 /* 16 bit SCIF */
# define SCSCR_INIT(port) 0x0030 /* TIE=0,RIE=0,TE=1,RE=1 */
# define SCIF_ONLY
-#elif defined(CONFIG_CPU_SUBTYPE_SH7710) || defined(CONFIG_CPU_SUBTYPE_SH7712)
+#elif defined(CONFIG_CPU_SUBTYPE_SH7710) || defined(CONFIG_CPU_SUBTYPE_SH7712)
# define SCSPTR0 0xA4400000 /* 16 bit SCIF */
# define SCI_NPORTS 2
# define SCIF_ORER 0x0001 /* overrun error bit */
@@ -168,6 +173,14 @@
# define SCIF_ORER 0x0001 /* overrun error bit */
# define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
# define SCIF_ONLY
+#elif defined(CONFIG_CPU_SUBTYPE_SHX3)
+# define SCSPTR0 0xffc30020 /* 16 bit SCIF */
+# define SCSPTR1 0xffc40020 /* 16 bit SCIF */
+# define SCSPTR2 0xffc50020 /* 16 bit SCIF */
+# define SCSPTR3 0xffc60020 /* 16 bit SCIF */
+# define SCIF_ORER 0x0001 /* Overrun error bit */
+# define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
+# define SCIF_ONLY
#else
# error CPU subtype not defined
#endif
@@ -177,10 +190,15 @@
#define SCI_CTRL_FLAGS_RIE 0x40 /* all */
#define SCI_CTRL_FLAGS_TE 0x20 /* all */
#define SCI_CTRL_FLAGS_RE 0x10 /* all */
-#if defined(CONFIG_CPU_SUBTYPE_SH7750) || \
- defined(CONFIG_CPU_SUBTYPE_SH7751) || \
- defined(CONFIG_CPU_SUBTYPE_SH7780) || \
- defined(CONFIG_CPU_SUBTYPE_SH7785)
+#if defined(CONFIG_CPU_SUBTYPE_SH7750) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7091) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7750R) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7750S) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7751) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7751R) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7780) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7785) || \
+ defined(CONFIG_CPU_SUBTYPE_SHX3)
#define SCI_CTRL_FLAGS_REIE 0x08 /* 7750 SCIF */
#else
#define SCI_CTRL_FLAGS_REIE 0
@@ -514,8 +532,12 @@ static inline void set_sh771x_scif_pfc(struct uart_port *port)
}
}
-#elif defined(CONFIG_CPU_SUBTYPE_SH7750) || \
- defined(CONFIG_CPU_SUBTYPE_SH7751) || \
+#elif defined(CONFIG_CPU_SUBTYPE_SH7750) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7751) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7751R) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7750R) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7750S) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7091) || \
defined(CONFIG_CPU_SUBTYPE_SH4_202)
static inline int sci_rxd_in(struct uart_port *port)
{
@@ -653,6 +675,18 @@ static inline int sci_rxd_in(struct uart_port *port)
return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */
return 1;
}
+#elif defined(CONFIG_CPU_SUBTYPE_SHX3)
+static inline int sci_rxd_in(struct uart_port *port)
+{
+ if (port->mapbase == 0xffc30000)
+ return ctrl_inw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */
+ if (port->mapbase == 0xffc40000)
+ return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */
+ if (port->mapbase == 0xffc50000)
+ return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */
+ if (port->mapbase == 0xffc60000)
+ return ctrl_inw(SCSPTR3) & 0x0001 ? 1 : 0; /* SCIF */
+}
#endif
/*
diff --git a/drivers/serial/sn_console.c b/drivers/serial/sn_console.c
index a27e9e92cb5..41fc6126444 100644
--- a/drivers/serial/sn_console.c
+++ b/drivers/serial/sn_console.c
@@ -759,7 +759,7 @@ static void __init sn_sal_switch_to_interrupts(struct sn_cons_port *port)
*/
static void sn_sal_console_write(struct console *, const char *, unsigned);
-static int __init sn_sal_console_setup(struct console *, char *);
+static int sn_sal_console_setup(struct console *, char *);
static struct uart_driver sal_console_uart;
extern struct tty_driver *uart_console_device(struct console *, int *);
@@ -1006,7 +1006,7 @@ sn_sal_console_write(struct console *co, const char *s, unsigned count)
* here so providing it is easier.
*
*/
-static int __init sn_sal_console_setup(struct console *co, char *options)
+static int sn_sal_console_setup(struct console *co, char *options)
{
return 0;
}
diff --git a/drivers/serial/sunhv.c b/drivers/serial/sunhv.c
index 96557e6dba6..17bcca53d6a 100644
--- a/drivers/serial/sunhv.c
+++ b/drivers/serial/sunhv.c
@@ -440,8 +440,16 @@ static void sunhv_console_write_paged(struct console *con, const char *s, unsign
{
struct uart_port *port = sunhv_port;
unsigned long flags;
+ int locked = 1;
+
+ local_irq_save(flags);
+ if (port->sysrq) {
+ locked = 0;
+ } else if (oops_in_progress) {
+ locked = spin_trylock(&port->lock);
+ } else
+ spin_lock(&port->lock);
- spin_lock_irqsave(&port->lock, flags);
while (n > 0) {
unsigned long ra = __pa(con_write_page);
unsigned long page_bytes;
@@ -469,7 +477,10 @@ static void sunhv_console_write_paged(struct console *con, const char *s, unsign
ra += written;
}
}
- spin_unlock_irqrestore(&port->lock, flags);
+
+ if (locked)
+ spin_unlock(&port->lock);
+ local_irq_restore(flags);
}
static inline void sunhv_console_putchar(struct uart_port *port, char c)
@@ -488,7 +499,15 @@ static void sunhv_console_write_bychar(struct console *con, const char *s, unsig
{
struct uart_port *port = sunhv_port;
unsigned long flags;
- int i;
+ int i, locked = 1;
+
+ local_irq_save(flags);
+ if (port->sysrq) {
+ locked = 0;
+ } else if (oops_in_progress) {
+ locked = spin_trylock(&port->lock);
+ } else
+ spin_lock(&port->lock);
spin_lock_irqsave(&port->lock, flags);
for (i = 0; i < n; i++) {
@@ -496,7 +515,10 @@ static void sunhv_console_write_bychar(struct console *con, const char *s, unsig
sunhv_console_putchar(port, '\r');
sunhv_console_putchar(port, *s++);
}
- spin_unlock_irqrestore(&port->lock, flags);
+
+ if (locked)
+ spin_unlock(&port->lock);
+ local_irq_restore(flags);
}
static struct console sunhv_console = {
diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c
index deb9ab4b5a0..8a0f9e4408d 100644
--- a/drivers/serial/sunsab.c
+++ b/drivers/serial/sunsab.c
@@ -860,22 +860,31 @@ static int num_channels;
static void sunsab_console_putchar(struct uart_port *port, int c)
{
struct uart_sunsab_port *up = (struct uart_sunsab_port *)port;
- unsigned long flags;
-
- spin_lock_irqsave(&up->port.lock, flags);
sunsab_tec_wait(up);
writeb(c, &up->regs->w.tic);
-
- spin_unlock_irqrestore(&up->port.lock, flags);
}
static void sunsab_console_write(struct console *con, const char *s, unsigned n)
{
struct uart_sunsab_port *up = &sunsab_ports[con->index];
+ unsigned long flags;
+ int locked = 1;
+
+ local_irq_save(flags);
+ if (up->port.sysrq) {
+ locked = 0;
+ } else if (oops_in_progress) {
+ locked = spin_trylock(&up->port.lock);
+ } else
+ spin_lock(&up->port.lock);
uart_console_write(&up->port, s, n, sunsab_console_putchar);
sunsab_tec_wait(up);
+
+ if (locked)
+ spin_unlock(&up->port.lock);
+ local_irq_restore(flags);
}
static int sunsab_console_setup(struct console *con, char *options)
diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c
index 2a63cdba320..26d720baf88 100644
--- a/drivers/serial/sunsu.c
+++ b/drivers/serial/sunsu.c
@@ -1288,7 +1288,17 @@ static void sunsu_console_write(struct console *co, const char *s,
unsigned int count)
{
struct uart_sunsu_port *up = &sunsu_ports[co->index];
+ unsigned long flags;
unsigned int ier;
+ int locked = 1;
+
+ local_irq_save(flags);
+ if (up->port.sysrq) {
+ locked = 0;
+ } else if (oops_in_progress) {
+ locked = spin_trylock(&up->port.lock);
+ } else
+ spin_lock(&up->port.lock);
/*
* First save the UER then disable the interrupts
@@ -1304,6 +1314,10 @@ static void sunsu_console_write(struct console *co, const char *s,
*/
wait_for_xmitr(up);
serial_out(up, UART_IER, ier);
+
+ if (locked)
+ spin_unlock(&up->port.lock);
+ local_irq_restore(flags);
}
/*
diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c
index 15b6e1cb040..0a3e10a4a35 100644
--- a/drivers/serial/sunzilog.c
+++ b/drivers/serial/sunzilog.c
@@ -9,7 +9,7 @@
* C. Dost, Pete Zaitcev, Ted Ts'o and Alex Buell for their
* work there.
*
- * Copyright (C) 2002, 2006 David S. Miller (davem@davemloft.net)
+ * Copyright (C) 2002, 2006, 2007 David S. Miller (davem@davemloft.net)
*/
#include <linux/module.h>
@@ -1151,11 +1151,22 @@ sunzilog_console_write(struct console *con, const char *s, unsigned int count)
{
struct uart_sunzilog_port *up = &sunzilog_port_table[con->index];
unsigned long flags;
+ int locked = 1;
+
+ local_irq_save(flags);
+ if (up->port.sysrq) {
+ locked = 0;
+ } else if (oops_in_progress) {
+ locked = spin_trylock(&up->port.lock);
+ } else
+ spin_lock(&up->port.lock);
- spin_lock_irqsave(&up->port.lock, flags);
uart_console_write(&up->port, s, count, sunzilog_putchar);
udelay(2);
- spin_unlock_irqrestore(&up->port.lock, flags);
+
+ if (locked)
+ spin_unlock(&up->port.lock);
+ local_irq_restore(flags);
}
static int __init sunzilog_console_setup(struct console *con, char *options)
diff --git a/drivers/telephony/Kconfig b/drivers/telephony/Kconfig
index dd1d6a53f3c..8f530e68263 100644
--- a/drivers/telephony/Kconfig
+++ b/drivers/telephony/Kconfig
@@ -2,11 +2,9 @@
# Telephony device configuration
#
-menu "Telephony Support"
+menuconfig PHONE
+ tristate "Telephony support"
depends on HAS_IOMEM
-
-config PHONE
- tristate "Linux telephony support"
---help---
Say Y here if you have a telephony card, which for example allows
you to use a regular phone for voice-over-IP applications.
@@ -17,9 +15,10 @@ config PHONE
To compile this driver as a module, choose M here: the
module will be called phonedev.
+if PHONE
+
config PHONE_IXJ
tristate "QuickNet Internet LineJack/PhoneJack support"
- depends on PHONE
---help---
Say M if you have a telephony card manufactured by Quicknet
Technologies, Inc. These include the Internet PhoneJACK and
@@ -44,5 +43,4 @@ config PHONE_IXJ_PCMCIA
cards manufactured by Quicknet Technologies, Inc. This changes the
card initialization code to work with the card manager daemon.
-endmenu
-
+endif # PHONE
diff --git a/drivers/video/pvr2fb.c b/drivers/video/pvr2fb.c
index df2909ae704..2ba959a83eb 100644
--- a/drivers/video/pvr2fb.c
+++ b/drivers/video/pvr2fb.c
@@ -115,11 +115,11 @@ enum { VO_PAL, VO_NTSC, VO_VGA };
enum { PAL_ARGB1555, PAL_RGB565, PAL_ARGB4444, PAL_ARGB8888 };
struct pvr2_params { unsigned int val; char *name; };
-static struct pvr2_params cables[] __initdata = {
+static struct pvr2_params cables[] __devinitdata = {
{ CT_VGA, "VGA" }, { CT_RGB, "RGB" }, { CT_COMPOSITE, "COMPOSITE" },
};
-static struct pvr2_params outputs[] __initdata = {
+static struct pvr2_params outputs[] __devinitdata = {
{ VO_PAL, "PAL" }, { VO_NTSC, "NTSC" }, { VO_VGA, "VGA" },
};
@@ -147,16 +147,16 @@ static struct pvr2fb_par {
static struct fb_info *fb_info;
-static struct fb_fix_screeninfo pvr2_fix __initdata = {
+static struct fb_fix_screeninfo pvr2_fix __devinitdata = {
.id = "NEC PowerVR2",
- .type = FB_TYPE_PACKED_PIXELS,
- .visual = FB_VISUAL_TRUECOLOR,
+ .type = FB_TYPE_PACKED_PIXELS,
+ .visual = FB_VISUAL_TRUECOLOR,
.ypanstep = 1,
.ywrapstep = 1,
- .accel = FB_ACCEL_NONE,
+ .accel = FB_ACCEL_NONE,
};
-static struct fb_var_screeninfo pvr2_var __initdata = {
+static struct fb_var_screeninfo pvr2_var __devinitdata = {
.xres = 640,
.yres = 480,
.xres_virtual = 640,
@@ -195,10 +195,6 @@ static unsigned int shdma = PVR2_CASCADE_CHAN;
static unsigned int pvr2dma = ONCHIP_NR_DMA_CHANNELS;
#endif
-/* Interface used by the world */
-
-int pvr2fb_setup(char*);
-
static int pvr2fb_setcolreg(unsigned int regno, unsigned int red, unsigned int green, unsigned int blue,
unsigned int transp, struct fb_info *info);
static int pvr2fb_blank(int blank, struct fb_info *info);
@@ -227,12 +223,12 @@ static struct fb_ops pvr2fb_ops = {
#ifdef CONFIG_SH_DMA
.fb_write = pvr2fb_write,
#endif
- .fb_fillrect = cfb_fillrect,
+ .fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
};
-static struct fb_videomode pvr2_modedb[] __initdata = {
+static struct fb_videomode pvr2_modedb[] __devinitdata = {
/*
* Broadcast video modes (PAL and NTSC). I'm unfamiliar with
* PAL-M and PAL-N, but from what I've read both modes parallel PAL and
@@ -252,7 +248,7 @@ static struct fb_videomode pvr2_modedb[] __initdata = {
/* 640x480 @ 60hz (VGA) */
"vga_640x480", 60, 640, 480, VGA_CLK, 38, 33, 0, 18, 146, 26,
0, FB_VMODE_YWRAP
- },
+ },
};
#define NUM_TOTAL_MODES ARRAY_SIZE(pvr2_modedb)
@@ -262,7 +258,7 @@ static struct fb_videomode pvr2_modedb[] __initdata = {
#define DEFMODE_VGA 2
static int defmode = DEFMODE_NTSC;
-static char *mode_option __initdata = NULL;
+static char *mode_option __devinitdata = NULL;
static inline void pvr2fb_set_pal_type(unsigned int type)
{
@@ -293,7 +289,7 @@ static void set_color_bitfields(struct fb_var_screeninfo *var)
{
switch (var->bits_per_pixel) {
case 16: /* RGB 565 */
- pvr2fb_set_pal_type(PAL_RGB565);
+ pvr2fb_set_pal_type(PAL_RGB565);
var->red.offset = 11; var->red.length = 5;
var->green.offset = 5; var->green.length = 6;
var->blue.offset = 0; var->blue.length = 5;
@@ -306,7 +302,7 @@ static void set_color_bitfields(struct fb_var_screeninfo *var)
var->transp.offset = 0; var->transp.length = 0;
break;
case 32: /* ARGB 8888 */
- pvr2fb_set_pal_type(PAL_ARGB8888);
+ pvr2fb_set_pal_type(PAL_ARGB8888);
var->red.offset = 16; var->red.length = 8;
var->green.offset = 8; var->green.length = 8;
var->blue.offset = 0; var->blue.length = 8;
@@ -379,13 +375,13 @@ static int pvr2fb_set_par(struct fb_info *info)
var->vmode &= FB_VMODE_MASK;
if (var->vmode & FB_VMODE_INTERLACED && video_output != VO_VGA)
par->is_interlaced = 1;
- /*
+ /*
* XXX: Need to be more creative with this (i.e. allow doublecan for
* PAL/NTSC output).
*/
if (var->vmode & FB_VMODE_DOUBLE && video_output == VO_VGA)
par->is_doublescan = 1;
-
+
par->hsync_total = var->left_margin + var->xres + var->right_margin +
var->hsync_len;
par->vsync_total = var->upper_margin + var->yres + var->lower_margin +
@@ -408,7 +404,7 @@ static int pvr2fb_set_par(struct fb_info *info)
} else {
/* VGA mode */
/* XXX: What else needs to be checked? */
- /*
+ /*
* XXX: We have a little freedom in VGA modes, what ranges
* should be here (i.e. hsync/vsync totals, etc.)?
*/
@@ -419,8 +415,8 @@ static int pvr2fb_set_par(struct fb_info *info)
/* Calculate the remainding offsets */
par->diwstart_h = par->borderstart_h + var->left_margin;
par->diwstart_v = par->borderstart_v + var->upper_margin;
- par->borderstop_h = par->diwstart_h + var->xres +
- var->right_margin;
+ par->borderstop_h = par->diwstart_h + var->xres +
+ var->right_margin;
par->borderstop_v = par->diwstart_v + var->yres +
var->lower_margin;
@@ -465,12 +461,12 @@ static int pvr2fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
set_color_bitfields(var);
if (var->vmode & FB_VMODE_YWRAP) {
- if (var->xoffset || var->yoffset < 0 ||
+ if (var->xoffset || var->yoffset < 0 ||
var->yoffset >= var->yres_virtual) {
var->xoffset = var->yoffset = 0;
} else {
if (var->xoffset > var->xres_virtual - var->xres ||
- var->yoffset > var->yres_virtual - var->yres ||
+ var->yoffset > var->yres_virtual - var->yres ||
var->xoffset < 0 || var->yoffset < 0)
var->xoffset = var->yoffset = 0;
}
@@ -478,7 +474,7 @@ static int pvr2fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
var->xoffset = var->yoffset = 0;
}
- /*
+ /*
* XXX: Need to be more creative with this (i.e. allow doublecan for
* PAL/NTSC output).
*/
@@ -507,7 +503,7 @@ static int pvr2fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
var->vsync_len = par->borderstop_v +
(par->vsync_total - par->borderstop_v);
}
-
+
hsync_total = var->left_margin + var->xres + var->right_margin +
var->hsync_len;
vtotal = var->upper_margin + var->yres + var->lower_margin +
@@ -531,7 +527,7 @@ static int pvr2fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
}
}
}
-
+
/* Check memory sizes */
line_length = get_line_length(var->xres_virtual, var->bits_per_pixel);
if (line_length * var->yres_virtual > info->fix.smem_len)
@@ -552,7 +548,7 @@ static void pvr2_update_display(struct fb_info *info)
DISP_DIWADDRS);
}
-/*
+/*
* Initialize the video mode. Currently, the 16bpp and 24bpp modes aren't
* very stable. It's probably due to the fact that a lot of the 2D video
* registers are still undocumented.
@@ -592,18 +588,18 @@ static void pvr2_init_display(struct fb_info *info)
/* display window start position */
fb_writel(par->diwstart_h, DISP_DIWHSTRT);
fb_writel((par->diwstart_v << 16) | par->diwstart_v, DISP_DIWVSTRT);
-
+
/* misc. settings */
fb_writel((0x16 << 16) | par->is_lowres, DISP_DIWCONF);
/* clock doubler (for VGA), scan doubler, display enable */
- fb_writel(((video_output == VO_VGA) << 23) |
+ fb_writel(((video_output == VO_VGA) << 23) |
(par->is_doublescan << 1) | 1, DISP_DIWMODE);
/* bits per pixel */
fb_writel(fb_readl(DISP_DIWMODE) | (--bytesperpixel << 2), DISP_DIWMODE);
- /* video enable, color sync, interlace,
+ /* video enable, color sync, interlace,
* hsync and vsync polarity (currently unused) */
fb_writel(0x100 | ((par->is_interlaced /*|4*/) << 4), DISP_SYNCCONF);
}
@@ -657,7 +653,7 @@ static irqreturn_t pvr2fb_interrupt(int irq, void *dev_id)
static int pvr2_init_cable(void)
{
if (cable_type < 0) {
- fb_writel((fb_readl(PCTRA) & 0xfff0ffff) | 0x000a0000,
+ fb_writel((fb_readl(PCTRA) & 0xfff0ffff) | 0x000a0000,
PCTRA);
cable_type = (fb_readw(PDTRA) >> 8) & 3;
}
@@ -687,7 +683,7 @@ static ssize_t pvr2fb_write(struct fb_info *info, const char *buf,
pages = kmalloc(nr_pages * sizeof(struct page *), GFP_KERNEL);
if (!pages)
return -ENOMEM;
-
+
down_read(&current->mm->mmap_sem);
ret = get_user_pages(current, current->mm, (unsigned long)buf,
nr_pages, WRITE, 0, pages, NULL);
@@ -700,7 +696,7 @@ static ssize_t pvr2fb_write(struct fb_info *info, const char *buf,
}
dma_configure_channel(shdma, 0x12c1);
-
+
dst = (unsigned long)fb_info->screen_base + *ppos;
start = (unsigned long)page_address(pages[0]);
end = (unsigned long)page_address(pages[nr_pages]);
@@ -744,7 +740,7 @@ out_unmap:
kfree(pages);
return ret;
-}
+}
#endif /* CONFIG_SH_DMA */
/**
@@ -765,21 +761,21 @@ out_unmap:
* in for flexibility anyways. Who knows, maybe someone has tv-out on a
* PCI-based version of these things ;-)
*/
-static int __init pvr2fb_common_init(void)
+static int __devinit pvr2fb_common_init(void)
{
struct pvr2fb_par *par = currentpar;
unsigned long modememused, rev;
fb_info->screen_base = ioremap_nocache(pvr2_fix.smem_start,
pvr2_fix.smem_len);
-
+
if (!fb_info->screen_base) {
printk(KERN_ERR "pvr2fb: Failed to remap smem space\n");
goto out_err;
}
par->mmio_base = (unsigned long)ioremap_nocache(pvr2_fix.mmio_start,
- pvr2_fix.mmio_len);
+ pvr2_fix.mmio_len);
if (!par->mmio_base) {
printk(KERN_ERR "pvr2fb: Failed to remap mmio space\n");
goto out_err;
@@ -820,7 +816,7 @@ static int __init pvr2fb_common_init(void)
printk("fb%d: %s (rev %ld.%ld) frame buffer device, using %ldk/%ldk of video memory\n",
fb_info->node, fb_info->fix.id, (rev >> 4) & 0x0f, rev & 0x0f,
modememused >> 10, (unsigned long)(fb_info->fix.smem_len >> 10));
- printk("fb%d: Mode %dx%d-%d pitch = %ld cable: %s video output: %s\n",
+ printk("fb%d: Mode %dx%d-%d pitch = %ld cable: %s video output: %s\n",
fb_info->node, fb_info->var.xres, fb_info->var.yres,
fb_info->var.bits_per_pixel,
get_line_length(fb_info->var.xres, fb_info->var.bits_per_pixel),
@@ -878,8 +874,8 @@ static int __init pvr2fb_dc_init(void)
video_output = VO_NTSC;
}
}
-
- /*
+
+ /*
* Nothing exciting about the DC PVR2 .. only a measly 8MiB.
*/
pvr2_fix.smem_start = 0xa5000000; /* RAM starts here */
@@ -903,7 +899,7 @@ static int __init pvr2fb_dc_init(void)
return pvr2fb_common_init();
}
-static void pvr2fb_dc_exit(void)
+static void __exit pvr2fb_dc_exit(void)
{
if (fb_info->screen_base) {
iounmap(fb_info->screen_base);
@@ -987,13 +983,13 @@ static int __init pvr2fb_pci_init(void)
return pci_register_driver(&pvr2fb_pci_driver);
}
-static void pvr2fb_pci_exit(void)
+static void __exit pvr2fb_pci_exit(void)
{
pci_unregister_driver(&pvr2fb_pci_driver);
}
#endif /* CONFIG_PCI */
-static int __init pvr2_get_param(const struct pvr2_params *p, const char *s,
+static int __devinit pvr2_get_param(const struct pvr2_params *p, const char *s,
int val, int size)
{
int i;
@@ -1021,7 +1017,7 @@ static int __init pvr2_get_param(const struct pvr2_params *p, const char *s,
*/
#ifndef MODULE
-int __init pvr2fb_setup(char *options)
+static int __init pvr2fb_setup(char *options)
{
char *this_opt;
char cable_arg[80];
@@ -1061,7 +1057,7 @@ static struct pvr2_board {
int (*init)(void);
void (*exit)(void);
char name[16];
-} board_list[] = {
+} board_driver[] = {
#ifdef CONFIG_SH_DREAMCAST
{ pvr2fb_dc_init, pvr2fb_dc_exit, "Sega DC PVR2" },
#endif
@@ -1071,7 +1067,7 @@ static struct pvr2_board {
{ 0, },
};
-int __init pvr2fb_init(void)
+static int __init pvr2fb_init(void)
{
int i, ret = -ENODEV;
int size;
@@ -1095,8 +1091,8 @@ int __init pvr2fb_init(void)
currentpar = (struct pvr2fb_par *)(fb_info + 1);
- for (i = 0; i < ARRAY_SIZE(board_list); i++) {
- struct pvr2_board *pvr_board = board_list + i;
+ for (i = 0; i < ARRAY_SIZE(board_driver); i++) {
+ struct pvr2_board *pvr_board = board_driver + i;
if (!pvr_board->init)
continue;
@@ -1118,13 +1114,13 @@ static void __exit pvr2fb_exit(void)
{
int i;
- for (i = 0; i < ARRAY_SIZE(board_list); i++) {
- struct pvr2_board *pvr_board = board_list + i;
+ for (i = 0; i < ARRAY_SIZE(board_driver); i++) {
+ struct pvr2_board *pvr_board = board_driver + i;
if (pvr_board->exit)
pvr_board->exit();
}
-
+
#ifdef CONFIG_SH_STORE_QUEUES
sq_unmap(pvr2fb_map);
#endif
@@ -1139,4 +1135,3 @@ module_exit(pvr2fb_exit);
MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>, M. R. Brown <mrbrown@0xd6.org>");
MODULE_DESCRIPTION("Framebuffer driver for NEC PowerVR 2 based graphics boards");
MODULE_LICENSE("GPL");
-
diff --git a/drivers/w1/Kconfig b/drivers/w1/Kconfig
index ca75b3ad3a2..6854fd6b971 100644
--- a/drivers/w1/Kconfig
+++ b/drivers/w1/Kconfig
@@ -1,8 +1,6 @@
-menu "Dallas's 1-wire bus"
- depends on HAS_IOMEM
-
-config W1
+menuconfig W1
tristate "Dallas's 1-wire support"
+ depends on HAS_IOMEM
---help---
Dallas' 1-wire bus is useful to connect slow 1-pin devices
such as iButtons and thermal sensors.
@@ -12,8 +10,10 @@ config W1
This W1 support can also be built as a module. If so, the module
will be called wire.ko.
+if W1
+
config W1_CON
- depends on CONNECTOR && W1
+ depends on CONNECTOR
bool "Userspace communication over connector"
default y
--- help ---
@@ -27,4 +27,4 @@ config W1_CON
source drivers/w1/masters/Kconfig
source drivers/w1/slaves/Kconfig
-endmenu
+endif # W1
diff --git a/drivers/w1/masters/Kconfig b/drivers/w1/masters/Kconfig
index 8f779338f74..8236d447adf 100644
--- a/drivers/w1/masters/Kconfig
+++ b/drivers/w1/masters/Kconfig
@@ -3,11 +3,10 @@
#
menu "1-wire Bus Masters"
- depends on W1
config W1_MASTER_MATROX
tristate "Matrox G400 transport layer for 1-wire"
- depends on W1 && PCI
+ depends on PCI
help
Say Y here if you want to communicate with your 1-wire devices
using Matrox's G400 GPIO pins.
@@ -17,7 +16,7 @@ config W1_MASTER_MATROX
config W1_MASTER_DS2490
tristate "DS2490 USB <-> W1 transport layer for 1-wire"
- depends on W1 && USB
+ depends on USB
help
Say Y here if you want to have a driver for DS2490 based USB <-> W1 bridges,
for example DS9490*.
@@ -27,7 +26,7 @@ config W1_MASTER_DS2490
config W1_MASTER_DS2482
tristate "Maxim DS2482 I2C to 1-Wire bridge"
- depends on I2C && W1 && EXPERIMENTAL
+ depends on I2C && EXPERIMENTAL
help
If you say yes here you get support for the Maxim DS2482
I2C to 1-Wire bridge.
diff --git a/drivers/w1/slaves/Kconfig b/drivers/w1/slaves/Kconfig
index df95d6c2cef..3df29a122f8 100644
--- a/drivers/w1/slaves/Kconfig
+++ b/drivers/w1/slaves/Kconfig
@@ -3,25 +3,21 @@
#
menu "1-wire Slaves"
- depends on W1
config W1_SLAVE_THERM
tristate "Thermal family implementation"
- depends on W1
help
Say Y here if you want to connect 1-wire thermal sensors to your
wire.
config W1_SLAVE_SMEM
tristate "Simple 64bit memory family implementation"
- depends on W1
help
Say Y here if you want to connect 1-wire
simple 64bit memory rom(ds2401/ds2411/ds1990*) to your wire.
config W1_SLAVE_DS2433
tristate "4kb EEPROM family support (DS2433)"
- depends on W1
help
Say Y here if you want to use a 1-wire
4kb EEPROM family device (DS2433).