From b2e1b30290539b344cbaff0d9da38012e03aa347 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Tue, 9 Sep 2008 23:19:48 -0700 Subject: cfg80211: Add new wireless regulatory infrastructure This adds the new wireless regulatory infrastructure. The main motiviation behind this was to centralize regulatory code as each driver was implementing their own regulatory solution, and to replace the initial centralized code we have where: * only 3 regulatory domains are supported: US, JP and EU * regulatory domains can only be changed through module parameter * all rules were built statically in the kernel We now have support for regulatory domains for many countries and regulatory domains are now queried through a userspace agent through udev allowing distributions to update regulatory rules without updating the kernel. Each driver can regulatory_hint() a regulatory domain based on either their EEPROM mapped regulatory domain value to a respective ISO/IEC 3166-1 country code or pass an internally built regulatory domain. We also add support to let the user set the regulatory domain through userspace in case of faulty EEPROMs to further help compliance. Support for world roaming will be added soon for cards capable of this. For more information see: http://wireless.kernel.org/en/developers/Regulatory/CRDA For now we leave an option to enable the old module parameter, ieee80211_regdom, and to build the 3 old regdomains statically (US, JP and EU). This option is CONFIG_WIRELESS_OLD_REGULATORY. These old static definitions and the module parameter is being scheduled for removal for 2.6.29. Note that if you use this you won't make use of a world regulatory domain as its pointless. If you leave this option enabled and if CRDA is present and you use US or JP we will try to ask CRDA to update us a regulatory domain for us. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- Documentation/feature-removal-schedule.txt | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'Documentation/feature-removal-schedule.txt') diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index eb1a47b97427..c93fcdec246d 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -6,6 +6,24 @@ be removed from this file. --------------------------- +What: old static regulatory information and ieee80211_regdom module parameter +When: 2.6.29 +Why: The old regulatory infrastructure has been replaced with a new one + which does not require statically defined regulatory domains. We do + not want to keep static regulatory domains in the kernel due to the + the dynamic nature of regulatory law and localization. We kept around + the old static definitions for the regulatory domains of: + * US + * JP + * EU + and used by default the US when CONFIG_WIRELESS_OLD_REGULATORY was + set. We also kept around the ieee80211_regdom module parameter in case + some applications were relying on it. Changing regulatory domains + can now be done instead by using nl80211, as is done with iw. +Who: Luis R. Rodriguez + +--------------------------- + What: dev->power.power_state When: July 2007 Why: Broken design for runtime control over driver power states, confusing -- cgit v1.2.3 From 079aa88fe7172b7650c7cf2c0bc01662bafea236 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Wed, 8 Oct 2008 11:35:00 +0200 Subject: netfilter: xt_recent: IPv6 support This updates xt_recent to support the IPv6 address family. The new /proc/net/xt_recent directory must be used for this. The old proc interface can also be configured out. Signed-off-by: Jan Engelhardt Signed-off-by: Patrick McHardy --- Documentation/feature-removal-schedule.txt | 3 + net/netfilter/Kconfig | 7 + net/netfilter/xt_recent.c | 300 +++++++++++++++++++++++------ 3 files changed, 256 insertions(+), 54 deletions(-) (limited to 'Documentation/feature-removal-schedule.txt') diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index d0f22fac55da..3d2d0c29f027 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -250,6 +250,9 @@ What (Why): - xt_mark match revision 0 (superseded by xt_mark match revision 1) + - xt_recent: the old ipt_recent proc dir + (superseded by /proc/net/xt_recent) + When: January 2009 or Linux 2.7.0, whichever comes first Why: Superseded by newer revisions or modules Who: Jan Engelhardt diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index ccc78b07a1a4..4a464857f216 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig @@ -743,6 +743,13 @@ config NETFILTER_XT_MATCH_RECENT Short options are available by using 'iptables -m recent -h' Official Website: +config NETFILTER_XT_MATCH_RECENT_PROC_COMPAT + bool 'Enable obsolete /proc/net/ipt_recent' + depends on NETFILTER_XT_MATCH_RECENT && PROC_FS + ---help--- + This option enables the old /proc/net/ipt_recent interface, + which has been obsoleted by /proc/net/xt_recent. + config NETFILTER_XT_MATCH_SCTP tristate '"sctp" protocol match support (EXPERIMENTAL)' depends on NETFILTER_XTABLES && EXPERIMENTAL diff --git a/net/netfilter/xt_recent.c b/net/netfilter/xt_recent.c index 422c0e4d66b7..adc2e2f1b09c 100644 --- a/net/netfilter/xt_recent.c +++ b/net/netfilter/xt_recent.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2006 Patrick McHardy + * Copyright © CC Computer Consultants GmbH, 2007 - 2008 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -13,6 +14,8 @@ */ #include #include +#include +#include #include #include #include @@ -30,9 +33,11 @@ #include MODULE_AUTHOR("Patrick McHardy "); +MODULE_AUTHOR("Jan Engelhardt "); MODULE_DESCRIPTION("Xtables: \"recently-seen\" host matching for IPv4"); MODULE_LICENSE("GPL"); MODULE_ALIAS("ipt_recent"); +MODULE_ALIAS("ip6t_recent"); static unsigned int ip_list_tot = 100; static unsigned int ip_pkt_list_tot = 20; @@ -49,14 +54,15 @@ module_param(ip_list_gid, uint, 0400); MODULE_PARM_DESC(ip_list_tot, "number of IPs to remember per list"); MODULE_PARM_DESC(ip_pkt_list_tot, "number of packets per IP to remember (max. 255)"); MODULE_PARM_DESC(ip_list_hash_size, "size of hash table used to look up IPs"); -MODULE_PARM_DESC(ip_list_perms, "permissions on /proc/net/ipt_recent/* files"); -MODULE_PARM_DESC(ip_list_uid,"owner of /proc/net/ipt_recent/* files"); -MODULE_PARM_DESC(ip_list_gid,"owning group of /proc/net/ipt_recent/* files"); +MODULE_PARM_DESC(ip_list_perms, "permissions on /proc/net/xt_recent/* files"); +MODULE_PARM_DESC(ip_list_uid,"owner of /proc/net/xt_recent/* files"); +MODULE_PARM_DESC(ip_list_gid,"owning group of /proc/net/xt_recent/* files"); struct recent_entry { struct list_head list; struct list_head lru_list; - __be32 addr; + union nf_inet_addr addr; + u_int16_t family; u_int8_t ttl; u_int8_t index; u_int16_t nstamps; @@ -67,7 +73,7 @@ struct recent_table { struct list_head list; char name[XT_RECENT_NAME_LEN]; #ifdef CONFIG_PROC_FS - struct proc_dir_entry *proc; + struct proc_dir_entry *proc_old, *proc; #endif unsigned int refcnt; unsigned int entries; @@ -80,31 +86,53 @@ static DEFINE_SPINLOCK(recent_lock); static DEFINE_MUTEX(recent_mutex); #ifdef CONFIG_PROC_FS -static struct proc_dir_entry *proc_dir; -static const struct file_operations recent_fops; +#ifdef CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT +static struct proc_dir_entry *proc_old_dir; +#endif +static struct proc_dir_entry *recent_proc_dir; +static const struct file_operations recent_old_fops, recent_mt_fops; #endif static u_int32_t hash_rnd; -static int hash_rnd_initted; +static bool hash_rnd_initted; + +static unsigned int recent_entry_hash4(const union nf_inet_addr *addr) +{ + if (!hash_rnd_initted) { + get_random_bytes(&hash_rnd, sizeof(hash_rnd)); + hash_rnd_initted = true; + } + return jhash_1word((__force u32)addr->ip, hash_rnd) & + (ip_list_hash_size - 1); +} -static unsigned int recent_entry_hash(__be32 addr) +static unsigned int recent_entry_hash6(const union nf_inet_addr *addr) { if (!hash_rnd_initted) { - get_random_bytes(&hash_rnd, 4); - hash_rnd_initted = 1; + get_random_bytes(&hash_rnd, sizeof(hash_rnd)); + hash_rnd_initted = true; } - return jhash_1word((__force u32)addr, hash_rnd) & (ip_list_hash_size - 1); + return jhash2((u32 *)addr->ip6, ARRAY_SIZE(addr->ip6), hash_rnd) & + (ip_list_hash_size - 1); } static struct recent_entry * -recent_entry_lookup(const struct recent_table *table, __be32 addr, u_int8_t ttl) +recent_entry_lookup(const struct recent_table *table, + const union nf_inet_addr *addrp, u_int16_t family, + u_int8_t ttl) { struct recent_entry *e; unsigned int h; - h = recent_entry_hash(addr); + if (family == AF_INET) + h = recent_entry_hash4(addrp); + else + h = recent_entry_hash6(addrp); + list_for_each_entry(e, &table->iphash[h], list) - if (e->addr == addr && (ttl == e->ttl || !ttl || !e->ttl)) + if (e->family == family && + memcmp(&e->addr, addrp, sizeof(e->addr)) == 0 && + (ttl == e->ttl || ttl == 0 || e->ttl == 0)) return e; return NULL; } @@ -118,7 +146,8 @@ static void recent_entry_remove(struct recent_table *t, struct recent_entry *e) } static struct recent_entry * -recent_entry_init(struct recent_table *t, __be32 addr, u_int8_t ttl) +recent_entry_init(struct recent_table *t, const union nf_inet_addr *addr, + u_int16_t family, u_int8_t ttl) { struct recent_entry *e; @@ -130,12 +159,16 @@ recent_entry_init(struct recent_table *t, __be32 addr, u_int8_t ttl) GFP_ATOMIC); if (e == NULL) return NULL; - e->addr = addr; + memcpy(&e->addr, addr, sizeof(e->addr)); e->ttl = ttl; e->stamps[0] = jiffies; e->nstamps = 1; e->index = 1; - list_add_tail(&e->list, &t->iphash[recent_entry_hash(addr)]); + e->family = family; + if (family == AF_INET) + list_add_tail(&e->list, &t->iphash[recent_entry_hash4(addr)]); + else + list_add_tail(&e->list, &t->iphash[recent_entry_hash6(addr)]); list_add_tail(&e->lru_list, &t->lru_list); t->entries++; return e; @@ -179,28 +212,42 @@ recent_mt(const struct sk_buff *skb, const struct net_device *in, const struct xt_recent_mtinfo *info = matchinfo; struct recent_table *t; struct recent_entry *e; - __be32 addr; + union nf_inet_addr addr = {}; u_int8_t ttl; bool ret = info->invert; - if (info->side == XT_RECENT_DEST) - addr = ip_hdr(skb)->daddr; - else - addr = ip_hdr(skb)->saddr; + if (match->family == AF_INET) { + const struct iphdr *iph = ip_hdr(skb); + + if (info->side == XT_RECENT_DEST) + addr.ip = iph->daddr; + else + addr.ip = iph->saddr; + + ttl = iph->ttl; + } else { + const struct ipv6hdr *iph = ipv6_hdr(skb); + + if (info->side == XT_RECENT_DEST) + memcpy(&addr.in6, &iph->daddr, sizeof(addr.in6)); + else + memcpy(&addr.in6, &iph->saddr, sizeof(addr.in6)); + + ttl = iph->hop_limit; + } - ttl = ip_hdr(skb)->ttl; /* use TTL as seen before forwarding */ if (out && !skb->sk) ttl++; spin_lock_bh(&recent_lock); t = recent_table_lookup(info->name); - e = recent_entry_lookup(t, addr, - info->check_set & XT_RECENT_TTL ? ttl : 0); + e = recent_entry_lookup(t, &addr, match->family, + (info->check_set & XT_RECENT_TTL) ? ttl : 0); if (e == NULL) { if (!(info->check_set & XT_RECENT_SET)) goto out; - e = recent_entry_init(t, addr, ttl); + e = recent_entry_init(t, &addr, match->family, ttl); if (e == NULL) *hotdrop = true; ret = !ret; @@ -277,11 +324,24 @@ recent_mt_check(const char *tablename, const void *ip, for (i = 0; i < ip_list_hash_size; i++) INIT_LIST_HEAD(&t->iphash[i]); #ifdef CONFIG_PROC_FS - t->proc = proc_create(t->name, ip_list_perms, proc_dir, &recent_fops); + t->proc = proc_create(t->name, ip_list_perms, recent_proc_dir, + &recent_mt_fops); if (t->proc == NULL) { kfree(t); goto out; } +#ifdef CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT + t->proc_old = proc_create(t->name, ip_list_perms, proc_old_dir, + &recent_old_fops); + if (t->proc_old == NULL) { + remove_proc_entry(t->name, proc_old_dir); + kfree(t); + goto out; + } + t->proc_old->uid = ip_list_uid; + t->proc_old->gid = ip_list_gid; + t->proc_old->data = t; +#endif t->proc->uid = ip_list_uid; t->proc->gid = ip_list_gid; t->proc->data = t; @@ -307,7 +367,10 @@ static void recent_mt_destroy(const struct xt_match *match, void *matchinfo) list_del(&t->list); spin_unlock_bh(&recent_lock); #ifdef CONFIG_PROC_FS - remove_proc_entry(t->name, proc_dir); +#ifdef CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT + remove_proc_entry(t->name, proc_old_dir); +#endif + remove_proc_entry(t->name, recent_proc_dir); #endif recent_table_flush(t); kfree(t); @@ -317,7 +380,7 @@ static void recent_mt_destroy(const struct xt_match *match, void *matchinfo) #ifdef CONFIG_PROC_FS struct recent_iter_state { - struct recent_table *table; + const struct recent_table *table; unsigned int bucket; }; @@ -342,8 +405,8 @@ static void *recent_seq_next(struct seq_file *seq, void *v, loff_t *pos) { struct recent_iter_state *st = seq->private; const struct recent_table *t = st->table; - struct recent_entry *e = v; - struct list_head *head = e->list.next; + const struct recent_entry *e = v; + const struct list_head *head = e->list.next; while (head == &t->iphash[st->bucket]) { if (++st->bucket >= ip_list_hash_size) @@ -366,8 +429,14 @@ static int recent_seq_show(struct seq_file *seq, void *v) unsigned int i; i = (e->index - 1) % ip_pkt_list_tot; - seq_printf(seq, "src=%u.%u.%u.%u ttl: %u last_seen: %lu oldest_pkt: %u", - NIPQUAD(e->addr), e->ttl, e->stamps[i], e->index); + if (e->family == AF_INET) + seq_printf(seq, "src=" NIPQUAD_FMT " ttl: %u last_seen: %lu " + "oldest_pkt: %u", NIPQUAD(e->addr.ip), e->ttl, + e->stamps[i], e->index); + else + seq_printf(seq, "src=" NIP6_FMT " ttl: %u last_seen: %lu " + "oldest_pkt: %u", NIP6(e->addr.in6), e->ttl, + e->stamps[i], e->index); for (i = 0; i < e->nstamps; i++) seq_printf(seq, "%s %lu", i ? "," : "", e->stamps[i]); seq_printf(seq, "\n"); @@ -394,8 +463,22 @@ static int recent_seq_open(struct inode *inode, struct file *file) return 0; } -static ssize_t recent_proc_write(struct file *file, const char __user *input, - size_t size, loff_t *loff) +#ifdef CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT +static int recent_old_seq_open(struct inode *inode, struct file *filp) +{ + static bool warned_of_old; + + if (unlikely(!warned_of_old)) { + printk(KERN_INFO KBUILD_MODNAME ": Use of /proc/net/ipt_recent" + " is deprecated; use /proc/net/xt_recent.\n"); + warned_of_old = true; + } + return recent_seq_open(inode, filp); +} + +static ssize_t recent_old_proc_write(struct file *file, + const char __user *input, + size_t size, loff_t *loff) { const struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode); struct recent_table *t = pde->data; @@ -408,6 +491,7 @@ static ssize_t recent_proc_write(struct file *file, const char __user *input, size = sizeof(buf); if (copy_from_user(buf, input, size)) return -EFAULT; + while (isspace(*c)) c++; @@ -435,10 +519,10 @@ static ssize_t recent_proc_write(struct file *file, const char __user *input, addr = in_aton(c); spin_lock_bh(&recent_lock); - e = recent_entry_lookup(t, addr, 0); + e = recent_entry_lookup(t, (const void *)&addr, PF_INET, 0); if (e == NULL) { if (add) - recent_entry_init(t, addr, 0); + recent_entry_init(t, (const void *)&addr, PF_INET, 0); } else { if (add) recent_entry_update(t, e); @@ -449,23 +533,118 @@ static ssize_t recent_proc_write(struct file *file, const char __user *input, return size; } -static const struct file_operations recent_fops = { - .open = recent_seq_open, +static const struct file_operations recent_old_fops = { + .open = recent_old_seq_open, .read = seq_read, - .write = recent_proc_write, + .write = recent_old_proc_write, .release = seq_release_private, .owner = THIS_MODULE, }; +#endif + +static ssize_t +recent_mt_proc_write(struct file *file, const char __user *input, + size_t size, loff_t *loff) +{ + const struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode); + struct recent_table *t = pde->data; + struct recent_entry *e; + char buf[sizeof("+b335:1d35:1e55:dead:c0de:1715:5afe:c0de")]; + const char *c = buf; + union nf_inet_addr addr; + u_int16_t family; + bool add, succ; + + if (size == 0) + return 0; + if (size > sizeof(buf)) + size = sizeof(buf); + if (copy_from_user(buf, input, size) != 0) + return -EFAULT; + + /* Strict protocol! */ + if (*loff != 0) + return -ESPIPE; + switch (*c) { + case '/': /* flush table */ + spin_lock_bh(&recent_lock); + recent_table_flush(t); + spin_unlock_bh(&recent_lock); + return size; + case '-': /* remove address */ + add = false; + break; + case '+': /* add address */ + add = true; + break; + default: + printk(KERN_INFO KBUILD_MODNAME ": Need +ip, -ip or /\n"); + return -EINVAL; + } + + ++c; + --size; + if (strnchr(c, size, ':') != NULL) { + family = AF_INET6; + succ = in6_pton(c, size, (void *)&addr, '\n', NULL); + } else { + family = AF_INET; + succ = in4_pton(c, size, (void *)&addr, '\n', NULL); + } + + if (!succ) { + printk(KERN_INFO KBUILD_MODNAME ": illegal address written " + "to procfs\n"); + return -EINVAL; + } + + spin_lock_bh(&recent_lock); + e = recent_entry_lookup(t, &addr, family, 0); + if (e == NULL) { + if (add) + recent_entry_init(t, &addr, family, 0); + } else { + if (add) + recent_entry_update(t, e); + else + recent_entry_remove(t, e); + } + spin_unlock_bh(&recent_lock); + /* Note we removed one above */ + *loff += size + 1; + return size + 1; +} + +static const struct file_operations recent_mt_fops = { + .open = recent_seq_open, + .read = seq_read, + .write = recent_mt_proc_write, + .release = seq_release_private, + .owner = THIS_MODULE, +}; #endif /* CONFIG_PROC_FS */ -static struct xt_match recent_mt_reg __read_mostly = { - .name = "recent", - .family = AF_INET, - .match = recent_mt, - .matchsize = sizeof(struct xt_recent_mtinfo), - .checkentry = recent_mt_check, - .destroy = recent_mt_destroy, - .me = THIS_MODULE, +static struct xt_match recent_mt_reg[] __read_mostly = { + { + .name = "recent", + .revision = 0, + .family = AF_INET, + .match = recent_mt, + .matchsize = sizeof(struct xt_recent_mtinfo), + .checkentry = recent_mt_check, + .destroy = recent_mt_destroy, + .me = THIS_MODULE, + }, + { + .name = "recent", + .revision = 0, + .family = AF_INET6, + .match = recent_mt, + .matchsize = sizeof(struct xt_recent_mtinfo), + .checkentry = recent_mt_check, + .destroy = recent_mt_destroy, + .me = THIS_MODULE, + }, }; static int __init recent_mt_init(void) @@ -476,15 +655,25 @@ static int __init recent_mt_init(void) return -EINVAL; ip_list_hash_size = 1 << fls(ip_list_tot); - err = xt_register_match(&recent_mt_reg); + err = xt_register_matches(recent_mt_reg, ARRAY_SIZE(recent_mt_reg)); #ifdef CONFIG_PROC_FS if (err) return err; - proc_dir = proc_mkdir("ipt_recent", init_net.proc_net); - if (proc_dir == NULL) { - xt_unregister_match(&recent_mt_reg); + recent_proc_dir = proc_mkdir("xt_recent", init_net.proc_net); + if (recent_proc_dir == NULL) { + xt_unregister_matches(recent_mt_reg, ARRAY_SIZE(recent_mt_reg)); + err = -ENOMEM; + } +#ifdef CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT + if (err < 0) + return err; + proc_old_dir = proc_mkdir("ipt_recent", init_net.proc_net); + if (proc_old_dir == NULL) { + remove_proc_entry("xt_recent", init_net.proc_net); + xt_unregister_matches(recent_mt_reg, ARRAY_SIZE(recent_mt_reg)); err = -ENOMEM; } +#endif #endif return err; } @@ -492,9 +681,12 @@ static int __init recent_mt_init(void) static void __exit recent_mt_exit(void) { BUG_ON(!list_empty(&tables)); - xt_unregister_match(&recent_mt_reg); + xt_unregister_matches(recent_mt_reg, ARRAY_SIZE(recent_mt_reg)); #ifdef CONFIG_PROC_FS +#ifdef CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT remove_proc_entry("ipt_recent", init_net.proc_net); +#endif + remove_proc_entry("xt_recent", init_net.proc_net); #endif } -- cgit v1.2.3 From 02f11f392434656f00fdcc8c51348d52bd39afe8 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 13 Oct 2008 10:31:59 +0100 Subject: coldfire: scheduled SERIAL_COLDFIRE removal This patch contains the scheduled removal of the obsolete SERIAL_COLDFIRE driver. Signed-off-by: Adrian Bunk Signed-off-by: Alan Cox Signed-off-by: Linus Torvalds --- Documentation/feature-removal-schedule.txt | 8 - drivers/serial/Kconfig | 16 +- drivers/serial/Makefile | 1 - drivers/serial/mcfserial.c | 1965 ---------------------------- drivers/serial/mcfserial.h | 74 -- 5 files changed, 2 insertions(+), 2062 deletions(-) delete mode 100644 drivers/serial/mcfserial.c delete mode 100644 drivers/serial/mcfserial.h (limited to 'Documentation/feature-removal-schedule.txt') diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index 3d2d0c29f027..cc8093c15cf5 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -287,14 +287,6 @@ Who: Glauber Costa --------------------------- -What: old style serial driver for ColdFire (CONFIG_SERIAL_COLDFIRE) -When: 2.6.28 -Why: This driver still uses the old interface and has been replaced - by CONFIG_SERIAL_MCF. -Who: Sebastian Siewior - ---------------------------- - What: /sys/o2cb symlink When: January 2010 Why: /sys/fs/o2cb is the proper location for this information - /sys/o2cb diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 77cb34270fc1..0db20452c79a 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -994,24 +994,12 @@ config SERIAL_68328_RTS_CTS bool "Support RTS/CTS on 68328 serial port" depends on SERIAL_68328 -config SERIAL_COLDFIRE - bool "ColdFire serial support (DEPRECATED)" - depends on COLDFIRE - help - This driver supports the built-in serial ports of the Motorola ColdFire - family of CPUs. - This driver is deprecated because it supports only the old interface - for serial drivers and features like magic keys are not working. - Please switch to the new style driver because this driver will be - removed soon. - config SERIAL_MCF - bool "Coldfire serial support (new style driver)" + bool "Coldfire serial support" depends on COLDFIRE select SERIAL_CORE help - This new serial driver supports the Freescale Coldfire serial ports - using the new serial driver subsystem. + This serial driver supports the Freescale Coldfire serial ports. config SERIAL_MCF_BAUDRATE int "Default baudrate for Coldfire serial ports" diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index 7e7383e890d8..1462eb3f7bd2 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -40,7 +40,6 @@ obj-$(CONFIG_SERIAL_SUNSAB) += sunsab.o obj-$(CONFIG_SERIAL_MUX) += mux.o obj-$(CONFIG_SERIAL_68328) += 68328serial.o obj-$(CONFIG_SERIAL_68360) += 68360serial.o -obj-$(CONFIG_SERIAL_COLDFIRE) += mcfserial.o obj-$(CONFIG_SERIAL_MCF) += mcf.o obj-$(CONFIG_SERIAL_PMACZILOG) += pmac_zilog.o obj-$(CONFIG_SERIAL_LH7A40X) += serial_lh7a40x.o diff --git a/drivers/serial/mcfserial.c b/drivers/serial/mcfserial.c deleted file mode 100644 index fbe3835f6b77..000000000000 --- a/drivers/serial/mcfserial.c +++ /dev/null @@ -1,1965 +0,0 @@ -#warning This driver is deprecated. Check Kconfig for details. -/* - * mcfserial.c -- serial driver for ColdFire internal UARTS. - * - * Copyright (C) 1999-2003 Greg Ungerer - * Copyright (c) 2000-2001 Lineo, Inc. - * Copyright (C) 2001-2002 SnapGear Inc. - * - * Based on code from 68332serial.c which was: - * - * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) - * Copyright (C) 1998 TSHG - * Copyright (c) 1999 Rt-Control Inc. - * - * Changes: - * 08/07/2003 Daniele Bellucci - * some cleanups in mcfrs_write. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "mcfserial.h" - -struct timer_list mcfrs_timer_struct; - -/* - * Default console baud rate, we use this as the default - * for all ports so init can just open /dev/console and - * keep going. Perhaps one day the cflag settings for the - * console can be used instead. - */ -#if defined(CONFIG_HW_FEITH) -#define CONSOLE_BAUD_RATE 38400 -#define DEFAULT_CBAUD B38400 -#elif defined(CONFIG_MOD5272) || defined(CONFIG_M5208EVB) || \ - defined(CONFIG_M5329EVB) || defined(CONFIG_GILBARCO) -#define CONSOLE_BAUD_RATE 115200 -#define DEFAULT_CBAUD B115200 -#elif defined(CONFIG_ARNEWSH) || defined(CONFIG_FREESCALE) || \ - defined(CONFIG_senTec) || defined(CONFIG_SNEHA) || defined(CONFIG_AVNET) -#define CONSOLE_BAUD_RATE 19200 -#define DEFAULT_CBAUD B19200 -#endif - -#ifndef CONSOLE_BAUD_RATE -#define CONSOLE_BAUD_RATE 9600 -#define DEFAULT_CBAUD B9600 -#endif - -int mcfrs_console_inited = 0; -int mcfrs_console_port = -1; -int mcfrs_console_baud = CONSOLE_BAUD_RATE; -int mcfrs_console_cbaud = DEFAULT_CBAUD; - -/* - * Driver data structures. - */ -static struct tty_driver *mcfrs_serial_driver; - -/* number of characters left in xmit buffer before we ask for more */ -#define WAKEUP_CHARS 256 - -/* Debugging... - */ -#undef SERIAL_DEBUG_OPEN -#undef SERIAL_DEBUG_FLOW - -#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \ - defined(CONFIG_M520x) || defined(CONFIG_M532x) -#define IRQBASE (MCFINT_VECBASE+MCFINT_UART0) -#else -#define IRQBASE 73 -#endif - -/* - * Configuration table, UARTs to look for at startup. - */ -static struct mcf_serial mcfrs_table[] = { - { /* ttyS0 */ - .magic = 0, - .addr = (volatile unsigned char *) (MCF_MBAR+MCFUART_BASE1), - .irq = IRQBASE, - .flags = ASYNC_BOOT_AUTOCONF, - }, -#ifdef MCFUART_BASE2 - { /* ttyS1 */ - .magic = 0, - .addr = (volatile unsigned char *) (MCF_MBAR+MCFUART_BASE2), - .irq = IRQBASE+1, - .flags = ASYNC_BOOT_AUTOCONF, - }, -#endif -#ifdef MCFUART_BASE3 - { /* ttyS2 */ - .magic = 0, - .addr = (volatile unsigned char *) (MCF_MBAR+MCFUART_BASE3), - .irq = IRQBASE+2, - .flags = ASYNC_BOOT_AUTOCONF, - }, -#endif -#ifdef MCFUART_BASE4 - { /* ttyS3 */ - .magic = 0, - .addr = (volatile unsigned char *) (MCF_MBAR+MCFUART_BASE4), - .irq = IRQBASE+3, - .flags = ASYNC_BOOT_AUTOCONF, - }, -#endif -}; - - -#define NR_PORTS (sizeof(mcfrs_table) / sizeof(struct mcf_serial)) - -/* - * This is used to figure out the divisor speeds and the timeouts. - */ -static int mcfrs_baud_table[] = { - 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, - 9600, 19200, 38400, 57600, 115200, 230400, 460800, 0 -}; -#define MCFRS_BAUD_TABLE_SIZE \ - (sizeof(mcfrs_baud_table)/sizeof(mcfrs_baud_table[0])) - - -#ifdef CONFIG_MAGIC_SYSRQ -/* - * Magic system request keys. Used for debugging... - */ -extern int magic_sysrq_key(int ch); -#endif - - -/* - * Forware declarations... - */ -static void mcfrs_change_speed(struct mcf_serial *info); -static void mcfrs_wait_until_sent(struct tty_struct *tty, int timeout); - - -static inline int serial_paranoia_check(struct mcf_serial *info, - char *name, const char *routine) -{ -#ifdef SERIAL_PARANOIA_CHECK - static const char badmagic[] = - "MCFRS(warning): bad magic number for serial struct %s in %s\n"; - static const char badinfo[] = - "MCFRS(warning): null mcf_serial for %s in %s\n"; - - if (!info) { - printk(badinfo, name, routine); - return 1; - } - if (info->magic != SERIAL_MAGIC) { - printk(badmagic, name, routine); - return 1; - } -#endif - return 0; -} - -/* - * Sets or clears DTR and RTS on the requested line. - */ -static void mcfrs_setsignals(struct mcf_serial *info, int dtr, int rts) -{ - volatile unsigned char *uartp; - unsigned long flags; - -#if 0 - printk("%s(%d): mcfrs_setsignals(info=%x,dtr=%d,rts=%d)\n", - __FILE__, __LINE__, info, dtr, rts); -#endif - - local_irq_save(flags); - if (dtr >= 0) { -#ifdef MCFPP_DTR0 - if (info->line) - mcf_setppdata(MCFPP_DTR1, (dtr ? 0 : MCFPP_DTR1)); - else - mcf_setppdata(MCFPP_DTR0, (dtr ? 0 : MCFPP_DTR0)); -#endif - } - if (rts >= 0) { - uartp = info->addr; - if (rts) { - info->sigs |= TIOCM_RTS; - uartp[MCFUART_UOP1] = MCFUART_UOP_RTS; - } else { - info->sigs &= ~TIOCM_RTS; - uartp[MCFUART_UOP0] = MCFUART_UOP_RTS; - } - } - local_irq_restore(flags); - return; -} - -/* - * Gets values of serial signals. - */ -static int mcfrs_getsignals(struct mcf_serial *info) -{ - volatile unsigned char *uartp; - unsigned long flags; - int sigs; -#if defined(CONFIG_NETtel) && defined(CONFIG_M5307) - unsigned short ppdata; -#endif - -#if 0 - printk("%s(%d): mcfrs_getsignals(info=%x)\n", __FILE__, __LINE__); -#endif - - local_irq_save(flags); - uartp = info->addr; - sigs = (uartp[MCFUART_UIPR] & MCFUART_UIPR_CTS) ? 0 : TIOCM_CTS; - sigs |= (info->sigs & TIOCM_RTS); - -#ifdef MCFPP_DCD0 -{ - unsigned int ppdata; - ppdata = mcf_getppdata(); - if (info->line == 0) { - sigs |= (ppdata & MCFPP_DCD0) ? 0 : TIOCM_CD; - sigs |= (ppdata & MCFPP_DTR0) ? 0 : TIOCM_DTR; - } else if (info->line == 1) { - sigs |= (ppdata & MCFPP_DCD1) ? 0 : TIOCM_CD; - sigs |= (ppdata & MCFPP_DTR1) ? 0 : TIOCM_DTR; - } -} -#endif - - local_irq_restore(flags); - return(sigs); -} - -/* - * ------------------------------------------------------------ - * mcfrs_stop() and mcfrs_start() - * - * This routines are called before setting or resetting tty->stopped. - * They enable or disable transmitter interrupts, as necessary. - * ------------------------------------------------------------ - */ -static void mcfrs_stop(struct tty_struct *tty) -{ - volatile unsigned char *uartp; - struct mcf_serial *info = (struct mcf_serial *)tty->driver_data; - unsigned long flags; - - if (serial_paranoia_check(info, tty->name, "mcfrs_stop")) - return; - - local_irq_save(flags); - uartp = info->addr; - info->imr &= ~MCFUART_UIR_TXREADY; - uartp[MCFUART_UIMR] = info->imr; - local_irq_restore(flags); -} - -static void mcfrs_start(struct tty_struct *tty) -{ - volatile unsigned char *uartp; - struct mcf_serial *info = (struct mcf_serial *)tty->driver_data; - unsigned long flags; - - if (serial_paranoia_check(info, tty->name, "mcfrs_start")) - return; - - local_irq_save(flags); - if (info->xmit_cnt && info->xmit_buf) { - uartp = info->addr; - info->imr |= MCFUART_UIR_TXREADY; - uartp[MCFUART_UIMR] = info->imr; - } - local_irq_restore(flags); -} - -/* - * ---------------------------------------------------------------------- - * - * Here starts the interrupt handling routines. All of the following - * subroutines are declared as inline and are folded into - * mcfrs_interrupt(). They were separated out for readability's sake. - * - * Note: mcfrs_interrupt() is a "fast" interrupt, which means that it - * runs with interrupts turned off. People who may want to modify - * mcfrs_interrupt() should try to keep the interrupt handler as fast as - * possible. After you are done making modifications, it is not a bad - * idea to do: - * - * gcc -S -DKERNEL -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer serial.c - * - * and look at the resulting assemble code in serial.s. - * - * - Ted Ts'o (tytso@mit.edu), 7-Mar-93 - * ----------------------------------------------------------------------- - */ - -static inline void receive_chars(struct mcf_serial *info) -{ - volatile unsigned char *uartp; - struct tty_struct *tty = info->port.tty; - unsigned char status, ch, flag; - - if (!tty) - return; - - uartp = info->addr; - - while ((status = uartp[MCFUART_USR]) & MCFUART_USR_RXREADY) { - ch = uartp[MCFUART_URB]; - info->stats.rx++; - -#ifdef CONFIG_MAGIC_SYSRQ - if (mcfrs_console_inited && (info->line == mcfrs_console_port)) { - if (magic_sysrq_key(ch)) - continue; - } -#endif - - flag = TTY_NORMAL; - if (status & MCFUART_USR_RXERR) { - uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETERR; - if (status & MCFUART_USR_RXBREAK) { - info->stats.rxbreak++; - flag = TTY_BREAK; - } else if (status & MCFUART_USR_RXPARITY) { - info->stats.rxparity++; - flag = TTY_PARITY; - } else if (status & MCFUART_USR_RXOVERRUN) { - info->stats.rxoverrun++; - flag = TTY_OVERRUN; - } else if (status & MCFUART_USR_RXFRAMING) { - info->stats.rxframing++; - flag = TTY_FRAME; - } - } - tty_insert_flip_char(tty, ch, flag); - } - tty_schedule_flip(tty); - return; -} - -static inline void transmit_chars(struct mcf_serial *info) -{ - volatile unsigned char *uartp; - - uartp = info->addr; - - if (info->x_char) { - /* Send special char - probably flow control */ - uartp[MCFUART_UTB] = info->x_char; - info->x_char = 0; - info->stats.tx++; - } - - if ((info->xmit_cnt <= 0) || info->port.tty->stopped) { - info->imr &= ~MCFUART_UIR_TXREADY; - uartp[MCFUART_UIMR] = info->imr; - return; - } - - while (uartp[MCFUART_USR] & MCFUART_USR_TXREADY) { - uartp[MCFUART_UTB] = info->xmit_buf[info->xmit_tail++]; - info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1); - info->stats.tx++; - if (--info->xmit_cnt <= 0) - break; - } - - if (info->xmit_cnt < WAKEUP_CHARS) - schedule_work(&info->tqueue); - return; -} - -/* - * This is the serial driver's generic interrupt routine - */ -irqreturn_t mcfrs_interrupt(int irq, void *dev_id) -{ - struct mcf_serial *info; - unsigned char isr; - - info = &mcfrs_table[(irq - IRQBASE)]; - isr = info->addr[MCFUART_UISR] & info->imr; - - if (isr & MCFUART_UIR_RXREADY) - receive_chars(info); - if (isr & MCFUART_UIR_TXREADY) - transmit_chars(info); - return IRQ_HANDLED; -} - -/* - * ------------------------------------------------------------------- - * Here ends the serial interrupt routines. - * ------------------------------------------------------------------- - */ - -static void mcfrs_offintr(struct work_struct *work) -{ - struct mcf_serial *info = container_of(work, struct mcf_serial, tqueue); - struct tty_struct *tty = info->port.tty; - - if (tty) - tty_wakeup(tty); -} - - -/* - * Change of state on a DCD line. - */ -void mcfrs_modem_change(struct mcf_serial *info, int dcd) -{ - if (info->count == 0) - return; - - if (info->flags & ASYNC_CHECK_CD) { - if (dcd) - wake_up_interruptible(&info->open_wait); - else - schedule_work(&info->tqueue_hangup); - } -} - - -#ifdef MCFPP_DCD0 - -unsigned short mcfrs_ppstatus; - -/* - * This subroutine is called when the RS_TIMER goes off. It is used - * to monitor the state of the DCD lines - since they have no edge - * sensors and interrupt generators. - */ -static void mcfrs_timer(void) -{ - unsigned int ppstatus, dcdval, i; - - ppstatus = mcf_getppdata() & (MCFPP_DCD0 | MCFPP_DCD1); - - if (ppstatus != mcfrs_ppstatus) { - for (i = 0; (i < 2); i++) { - dcdval = (i ? MCFPP_DCD1 : MCFPP_DCD0); - if ((ppstatus & dcdval) != (mcfrs_ppstatus & dcdval)) { - mcfrs_modem_change(&mcfrs_table[i], - ((ppstatus & dcdval) ? 0 : 1)); - } - } - } - mcfrs_ppstatus = ppstatus; - - /* Re-arm timer */ - mcfrs_timer_struct.expires = jiffies + HZ/25; - add_timer(&mcfrs_timer_struct); -} - -#endif /* MCFPP_DCD0 */ - - -/* - * This routine is called from the scheduler tqueue when the interrupt - * routine has signalled that a hangup has occurred. The path of - * hangup processing is: - * - * serial interrupt routine -> (scheduler tqueue) -> - * do_serial_hangup() -> tty->hangup() -> mcfrs_hangup() - * - */ -static void do_serial_hangup(struct work_struct *work) -{ - struct mcf_serial *info = container_of(work, struct mcf_serial, tqueue_hangup); - struct tty_struct *tty = info->port.tty; - - if (tty) - tty_hangup(tty); -} - -static int startup(struct mcf_serial * info) -{ - volatile unsigned char *uartp; - unsigned long flags; - - if (info->flags & ASYNC_INITIALIZED) - return 0; - - if (!info->xmit_buf) { - info->xmit_buf = (unsigned char *) __get_free_page(GFP_KERNEL); - if (!info->xmit_buf) - return -ENOMEM; - } - - local_irq_save(flags); - -#ifdef SERIAL_DEBUG_OPEN - printk("starting up ttyS%d (irq %d)...\n", info->line, info->irq); -#endif - - /* - * Reset UART, get it into known state... - */ - uartp = info->addr; - uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETRX; /* reset RX */ - uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETTX; /* reset TX */ - mcfrs_setsignals(info, 1, 1); - - if (info->port.tty) - clear_bit(TTY_IO_ERROR, &info->port.tty->flags); - info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; - - /* - * and set the speed of the serial port - */ - mcfrs_change_speed(info); - - /* - * Lastly enable the UART transmitter and receiver, and - * interrupt enables. - */ - info->imr = MCFUART_UIR_RXREADY; - uartp[MCFUART_UCR] = MCFUART_UCR_RXENABLE | MCFUART_UCR_TXENABLE; - uartp[MCFUART_UIMR] = info->imr; - - info->flags |= ASYNC_INITIALIZED; - local_irq_restore(flags); - return 0; -} - -/* - * This routine will shutdown a serial port; interrupts are disabled, and - * DTR is dropped if the hangup on close termio flag is on. - */ -static void shutdown(struct mcf_serial * info) -{ - volatile unsigned char *uartp; - unsigned long flags; - - if (!(info->flags & ASYNC_INITIALIZED)) - return; - -#ifdef SERIAL_DEBUG_OPEN - printk("Shutting down serial port %d (irq %d)....\n", info->line, - info->irq); -#endif - - local_irq_save(flags); - - uartp = info->addr; - uartp[MCFUART_UIMR] = 0; /* mask all interrupts */ - uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETRX; /* reset RX */ - uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETTX; /* reset TX */ - - if (!info->port.tty || (info->port.tty->termios->c_cflag & HUPCL)) - mcfrs_setsignals(info, 0, 0); - - if (info->xmit_buf) { - free_page((unsigned long) info->xmit_buf); - info->xmit_buf = 0; - } - - if (info->port.tty) - set_bit(TTY_IO_ERROR, &info->port.tty->flags); - - info->flags &= ~ASYNC_INITIALIZED; - local_irq_restore(flags); -} - - -/* - * This routine is called to set the UART divisor registers to match - * the specified baud rate for a serial port. - */ -static void mcfrs_change_speed(struct mcf_serial *info) -{ - volatile unsigned char *uartp; - unsigned int baudclk, cflag; - unsigned long flags; - unsigned char mr1, mr2; - int i; -#ifdef CONFIG_M5272 - unsigned int fraction; -#endif - - if (!info->port.tty || !info->port.tty->termios) - return; - cflag = info->port.tty->termios->c_cflag; - if (info->addr == 0) - return; - -#if 0 - printk("%s(%d): mcfrs_change_speed()\n", __FILE__, __LINE__); -#endif - - i = cflag & CBAUD; - if (i & CBAUDEX) { - i &= ~CBAUDEX; - if (i < 1 || i > 4) - info->port.tty->termios->c_cflag &= ~CBAUDEX; - else - i += 15; - } - if (i == 0) { - mcfrs_setsignals(info, 0, -1); - return; - } - - /* compute the baudrate clock */ -#ifdef CONFIG_M5272 - /* - * For the MCF5272, also compute the baudrate fraction. - */ - baudclk = (MCF_BUSCLK / mcfrs_baud_table[i]) / 32; - fraction = MCF_BUSCLK - (baudclk * 32 * mcfrs_baud_table[i]); - fraction *= 16; - fraction /= (32 * mcfrs_baud_table[i]); -#else - baudclk = ((MCF_BUSCLK / mcfrs_baud_table[i]) + 16) / 32; -#endif - - info->baud = mcfrs_baud_table[i]; - - mr1 = MCFUART_MR1_RXIRQRDY | MCFUART_MR1_RXERRCHAR; - mr2 = 0; - - switch (cflag & CSIZE) { - case CS5: mr1 |= MCFUART_MR1_CS5; break; - case CS6: mr1 |= MCFUART_MR1_CS6; break; - case CS7: mr1 |= MCFUART_MR1_CS7; break; - case CS8: - default: mr1 |= MCFUART_MR1_CS8; break; - } - - if (cflag & PARENB) { - if (cflag & CMSPAR) { - if (cflag & PARODD) - mr1 |= MCFUART_MR1_PARITYMARK; - else - mr1 |= MCFUART_MR1_PARITYSPACE; - } else { - if (cflag & PARODD) - mr1 |= MCFUART_MR1_PARITYODD; - else - mr1 |= MCFUART_MR1_PARITYEVEN; - } - } else { - mr1 |= MCFUART_MR1_PARITYNONE; - } - - if (cflag & CSTOPB) - mr2 |= MCFUART_MR2_STOP2; - else - mr2 |= MCFUART_MR2_STOP1; - - if (cflag & CRTSCTS) { - mr1 |= MCFUART_MR1_RXRTS; - mr2 |= MCFUART_MR2_TXCTS; - } - - if (cflag & CLOCAL) - info->flags &= ~ASYNC_CHECK_CD; - else - info->flags |= ASYNC_CHECK_CD; - - uartp = info->addr; - - local_irq_save(flags); -#if 0 - printk("%s(%d): mr1=%x mr2=%x baudclk=%x\n", __FILE__, __LINE__, - mr1, mr2, baudclk); -#endif - /* - Note: pg 12-16 of MCF5206e User's Manual states that a - software reset should be performed prior to changing - UMR1,2, UCSR, UACR, bit 7 - */ - uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETRX; /* reset RX */ - uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETTX; /* reset TX */ - uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETMRPTR; /* reset MR pointer */ - uartp[MCFUART_UMR] = mr1; - uartp[MCFUART_UMR] = mr2; - uartp[MCFUART_UBG1] = (baudclk & 0xff00) >> 8; /* set msb byte */ - uartp[MCFUART_UBG2] = (baudclk & 0xff); /* set lsb byte */ -#ifdef CONFIG_M5272 - uartp[MCFUART_UFPD] = (fraction & 0xf); /* set fraction */ -#endif - uartp[MCFUART_UCSR] = MCFUART_UCSR_RXCLKTIMER | MCFUART_UCSR_TXCLKTIMER; - uartp[MCFUART_UCR] = MCFUART_UCR_RXENABLE | MCFUART_UCR_TXENABLE; - mcfrs_setsignals(info, 1, -1); - local_irq_restore(flags); - return; -} - -static void mcfrs_flush_chars(struct tty_struct *tty) -{ - volatile unsigned char *uartp; - struct mcf_serial *info = (struct mcf_serial *)tty->driver_data; - unsigned long flags; - - if (serial_paranoia_check(info, tty->name, "mcfrs_flush_chars")) - return; - - uartp = (volatile unsigned char *) info->addr; - - /* - * re-enable receiver interrupt - */ - local_irq_save(flags); - if ((!(info->imr & MCFUART_UIR_RXREADY)) && - (info->flags & ASYNC_INITIALIZED) ) { - info->imr |= MCFUART_UIR_RXREADY; - uartp[MCFUART_UIMR] = info->imr; - } - local_irq_restore(flags); - - if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped || - !info->xmit_buf) - return; - - /* Enable transmitter */ - local_irq_save(flags); - info->imr |= MCFUART_UIR_TXREADY; - uartp[MCFUART_UIMR] = info->imr; - local_irq_restore(flags); -} - -static int mcfrs_write(struct tty_struct * tty, - const unsigned char *buf, int count) -{ - volatile unsigned char *uartp; - struct mcf_serial *info = (struct mcf_serial *)tty->driver_data; - unsigned long flags; - int c, total = 0; - -#if 0 - printk("%s(%d): mcfrs_write(tty=%x,buf=%x,count=%d)\n", - __FILE__, __LINE__, (int)tty, (int)buf, count); -#endif - - if (serial_paranoia_check(info, tty->name, "mcfrs_write")) - return 0; - - if (!tty || !info->xmit_buf) - return 0; - - local_save_flags(flags); - while (1) { - local_irq_disable(); - c = min(count, (int) min(((int)SERIAL_XMIT_SIZE) - info->xmit_cnt - 1, - ((int)SERIAL_XMIT_SIZE) - info->xmit_head)); - local_irq_restore(flags); - - if (c <= 0) - break; - - memcpy(info->xmit_buf + info->xmit_head, buf, c); - - local_irq_disable(); - info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1); - info->xmit_cnt += c; - local_irq_restore(flags); - - buf += c; - count -= c; - total += c; - } - - local_irq_disable(); - uartp = info->addr; - info->imr |= MCFUART_UIR_TXREADY; - uartp[MCFUART_UIMR] = info->imr; - local_irq_restore(flags); - - return total; -} - -static int mcfrs_write_room(struct tty_struct *tty) -{ - struct mcf_serial *info = (struct mcf_serial *)tty->driver_data; - int ret; - - if (serial_paranoia_check(info, tty->name, "mcfrs_write_room")) - return 0; - ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1; - if (ret < 0) - ret = 0; - return ret; -} - -static int mcfrs_chars_in_buffer(struct tty_struct *tty) -{ - struct mcf_serial *info = (struct mcf_serial *)tty->driver_data; - - if (serial_paranoia_check(info, tty->name, "mcfrs_chars_in_buffer")) - return 0; - return info->xmit_cnt; -} - -static void mcfrs_flush_buffer(struct tty_struct *tty) -{ - struct mcf_serial *info = (struct mcf_serial *)tty->driver_data; - unsigned long flags; - - if (serial_paranoia_check(info, tty->name, "mcfrs_flush_buffer")) - return; - - local_irq_save(flags); - info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; - local_irq_restore(flags); - - tty_wakeup(tty); -} - -/* - * ------------------------------------------------------------ - * mcfrs_throttle() - * - * This routine is called by the upper-layer tty layer to signal that - * incoming characters should be throttled. - * ------------------------------------------------------------ - */ -static void mcfrs_throttle(struct tty_struct * tty) -{ - struct mcf_serial *info = (struct mcf_serial *)tty->driver_data; -#ifdef SERIAL_DEBUG_THROTTLE - char buf[64]; - - printk("throttle %s: %d....\n", tty_name(tty, buf), - tty->ldisc.chars_in_buffer(tty)); -#endif - - if (serial_paranoia_check(info, tty->name, "mcfrs_throttle")) - return; - - if (I_IXOFF(tty)) - info->x_char = STOP_CHAR(tty); - - /* Turn off RTS line (do this atomic) */ -} - -static void mcfrs_unthrottle(struct tty_struct * tty) -{ - struct mcf_serial *info = (struct mcf_serial *)tty->driver_data; -#ifdef SERIAL_DEBUG_THROTTLE - char buf[64]; - - printk("unthrottle %s: %d....\n", tty_name(tty, buf), - tty->ldisc.chars_in_buffer(tty)); -#endif - - if (serial_paranoia_check(info, tty->name, "mcfrs_unthrottle")) - return; - - if (I_IXOFF(tty)) { - if (info->x_char) - info->x_char = 0; - else - info->x_char = START_CHAR(tty); - } - - /* Assert RTS line (do this atomic) */ -} - -/* - * ------------------------------------------------------------ - * mcfrs_ioctl() and friends - * ------------------------------------------------------------ - */ - -static int get_serial_info(struct mcf_serial * info, - struct serial_struct * retinfo) -{ - struct serial_struct tmp; - - if (!retinfo) - return -EFAULT; - memset(&tmp, 0, sizeof(tmp)); - tmp.type = info->type; - tmp.line = info->line; - tmp.port = (unsigned int) info->addr; - tmp.irq = info->irq; - tmp.flags = info->flags; - tmp.baud_base = info->baud_base; - tmp.close_delay = info->close_delay; - tmp.closing_wait = info->closing_wait; - tmp.custom_divisor = info->custom_divisor; - return copy_to_user(retinfo,&tmp,sizeof(*retinfo)) ? -EFAULT : 0; -} - -static int set_serial_info(struct mcf_serial * info, - struct serial_struct * new_info) -{ - struct serial_struct new_serial; - struct mcf_serial old_info; - int retval = 0; - - if (!new_info) - return -EFAULT; - if (copy_from_user(&new_serial,new_info,sizeof(new_serial))) - return -EFAULT; - old_info = *info; - - if (!capable(CAP_SYS_ADMIN)) { - if ((new_serial.baud_base != info->baud_base) || - (new_serial.type != info->type) || - (new_serial.close_delay != info->close_delay) || - ((new_serial.flags & ~ASYNC_USR_MASK) != - (info->flags & ~ASYNC_USR_MASK))) - return -EPERM; - info->flags = ((info->flags & ~ASYNC_USR_MASK) | - (new_serial.flags & ASYNC_USR_MASK)); - info->custom_divisor = new_serial.custom_divisor; - goto check_and_exit; - } - - if (info->count > 1) - return -EBUSY; - - /* - * OK, past this point, all the error checking has been done. - * At this point, we start making changes..... - */ - - info->baud_base = new_serial.baud_base; - info->flags = ((info->flags & ~ASYNC_FLAGS) | - (new_serial.flags & ASYNC_FLAGS)); - info->type = new_serial.type; - info->close_delay = new_serial.close_delay; - info->closing_wait = new_serial.closing_wait; - -check_and_exit: - retval = startup(info); - return retval; -} - -/* - * get_lsr_info - get line status register info - * - * Purpose: Let user call ioctl() to get info when the UART physically - * is emptied. On bus types like RS485, the transmitter must - * release the bus after transmitting. This must be done when - * the transmit shift register is empty, not be done when the - * transmit holding register is empty. This functionality - * allows an RS485 driver to be written in user space. - */ -static int get_lsr_info(struct mcf_serial * info, unsigned int *value) -{ - volatile unsigned char *uartp; - unsigned long flags; - unsigned char status; - - local_irq_save(flags); - uartp = info->addr; - status = (uartp[MCFUART_USR] & MCFUART_USR_TXEMPTY) ? TIOCSER_TEMT : 0; - local_irq_restore(flags); - - return put_user(status,value); -} - -/* - * This routine sends a break character out the serial port. - */ -static void send_break( struct mcf_serial * info, int duration) -{ - volatile unsigned char *uartp; - unsigned long flags; - - if (!info->addr) - return; - set_current_state(TASK_INTERRUPTIBLE); - uartp = info->addr; - - local_irq_save(flags); - uartp[MCFUART_UCR] = MCFUART_UCR_CMDBREAKSTART; - schedule_timeout(duration); - uartp[MCFUART_UCR] = MCFUART_UCR_CMDBREAKSTOP; - local_irq_restore(flags); -} - -static int mcfrs_tiocmget(struct tty_struct *tty, struct file *file) -{ - struct mcf_serial * info = (struct mcf_serial *)tty->driver_data; - - if (serial_paranoia_check(info, tty->name, "mcfrs_ioctl")) - return -ENODEV; - if (tty->flags & (1 << TTY_IO_ERROR)) - return -EIO; - - return mcfrs_getsignals(info); -} - -static int mcfrs_tiocmset(struct tty_struct *tty, struct file *file, - unsigned int set, unsigned int clear) -{ - struct mcf_serial * info = (struct mcf_serial *)tty->driver_data; - int rts = -1, dtr = -1; - - if (serial_paranoia_check(info, tty->name, "mcfrs_ioctl")) - return -ENODEV; - if (tty->flags & (1 << TTY_IO_ERROR)) - return -EIO; - - if (set & TIOCM_RTS) - rts = 1; - if (set & TIOCM_DTR) - dtr = 1; - if (clear & TIOCM_RTS) - rts = 0; - if (clear & TIOCM_DTR) - dtr = 0; - - mcfrs_setsignals(info, dtr, rts); - - return 0; -} - -static int mcfrs_ioctl(struct tty_struct *tty, struct file * file, - unsigned int cmd, unsigned long arg) -{ - struct mcf_serial * info = (struct mcf_serial *)tty->driver_data; - int retval, error; - - if (serial_paranoia_check(info, tty->name, "mcfrs_ioctl")) - return -ENODEV; - - if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && - (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGWILD) && - (cmd != TIOCSERSWILD) && (cmd != TIOCSERGSTRUCT)) { - if (tty->flags & (1 << TTY_IO_ERROR)) - return -EIO; - } - - switch (cmd) { - case TCSBRK: /* SVID version: non-zero arg --> no break */ - retval = tty_check_change(tty); - if (retval) - return retval; - tty_wait_until_sent(tty, 0); - if (!arg) - send_break(info, HZ/4); /* 1/4 second */ - return 0; - case TCSBRKP: /* support for POSIX tcsendbreak() */ - retval = tty_check_change(tty); - if (retval) - return retval; - tty_wait_until_sent(tty, 0); - send_break(info, arg ? arg*(HZ/10) : HZ/4); - return 0; - case TIOCGSERIAL: - if (access_ok(VERIFY_WRITE, (void *) arg, - sizeof(struct serial_struct))) - return get_serial_info(info, - (struct serial_struct *) arg); - return -EFAULT; - case TIOCSSERIAL: - return set_serial_info(info, - (struct serial_struct *) arg); - case TIOCSERGETLSR: /* Get line status register */ - if (access_ok(VERIFY_WRITE, (void *) arg, - sizeof(unsigned int))) - return get_lsr_info(info, (unsigned int *) arg); - return -EFAULT; - case TIOCSERGSTRUCT: - error = copy_to_user((struct mcf_serial *) arg, - info, sizeof(struct mcf_serial)); - if (error) - return -EFAULT; - return 0; - -#ifdef TIOCSET422 - case TIOCSET422: { - unsigned int val; - get_user(val, (unsigned int *) arg); - mcf_setpa(MCFPP_PA11, (val ? 0 : MCFPP_PA11)); - break; - } - case TIOCGET422: { - unsigned int val; - val = (mcf_getpa() & MCFPP_PA11) ? 0 : 1; - put_user(val, (unsigned int *) arg); - break; - } -#endif - - default: - return -ENOIOCTLCMD; - } - return 0; -} - -static void mcfrs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) -{ - struct mcf_serial *info = (struct mcf_serial *)tty->driver_data; - - if (tty->termios->c_cflag == old_termios->c_cflag) - return; - - mcfrs_change_speed(info); - - if ((old_termios->c_cflag & CRTSCTS) && - !(tty->termios->c_cflag & CRTSCTS)) { - tty->hw_stopped = 0; - mcfrs_setsignals(info, -1, 1); -#if 0 - mcfrs_start(tty); -#endif - } -} - -/* - * ------------------------------------------------------------ - * mcfrs_close() - * - * This routine is called when the serial port gets closed. First, we - * wait for the last remaining data to be sent. Then, we unlink its - * S structure from the interrupt chain if necessary, and we free - * that IRQ if nothing is left in the chain. - * ------------------------------------------------------------ - */ -static void mcfrs_close(struct tty_struct *tty, struct file * filp) -{ - volatile unsigned char *uartp; - struct mcf_serial *info = (struct mcf_serial *)tty->driver_data; - unsigned long flags; - - if (!info || serial_paranoia_check(info, tty->name, "mcfrs_close")) - return; - - local_irq_save(flags); - - if (tty_hung_up_p(filp)) { - local_irq_restore(flags); - return; - } - -#ifdef SERIAL_DEBUG_OPEN - printk("mcfrs_close ttyS%d, count = %d\n", info->line, info->count); -#endif - if ((tty->count == 1) && (info->count != 1)) { - /* - * Uh, oh. tty->count is 1, which means that the tty - * structure will be freed. Info->count should always - * be one in these conditions. If it's greater than - * one, we've got real problems, since it means the - * serial port won't be shutdown. - */ - printk("MCFRS: bad serial port count; tty->count is 1, " - "info->count is %d\n", info->count); - info->count = 1; - } - if (--info->count < 0) { - printk("MCFRS: bad serial port count for ttyS%d: %d\n", - info->line, info->count); - info->count = 0; - } - if (info->count) { - local_irq_restore(flags); - return; - } - info->flags |= ASYNC_CLOSING; - - /* - * Now we wait for the transmit buffer to clear; and we notify - * the line discipline to only process XON/XOFF characters. - */ - tty->closing = 1; - if (info->closing_wait != ASYNC_CLOSING_WAIT_NONE) - tty_wait_until_sent(tty, info->closing_wait); - - /* - * At this point we stop accepting input. To do this, we - * disable the receive line status interrupts, and tell the - * interrupt driver to stop checking the data ready bit in the - * line status register. - */ - info->imr &= ~MCFUART_UIR_RXREADY; - uartp = info->addr; - uartp[MCFUART_UIMR] = info->imr; - -#if 0 - /* FIXME: do we need to keep this enabled for console?? */ - if (mcfrs_console_inited && (mcfrs_console_port == info->line)) { - /* Do not disable the UART */ ; - } else -#endif - shutdown(info); - mcfrs_flush_buffer(tty); - tty_ldisc_flush(tty); - - tty->closing = 0; - info->event = 0; - info->port.tty = NULL; -#if 0 - if (tty->ldisc.num != ldiscs[N_TTY].num) { - if (tty->ldisc.close) - (tty->ldisc.close)(tty); - tty->ldisc = ldiscs[N_TTY]; - tty->termios->c_line = N_TTY; - if (tty->ldisc.open) - (tty->ldisc.open)(tty); - } -#endif - if (info->blocked_open) { - if (info->close_delay) { - msleep_interruptible(jiffies_to_msecs(info->close_delay)); - } - wake_up_interruptible(&info->open_wait); - } - info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); - wake_up_interruptible(&info->close_wait); - local_irq_restore(flags); -} - -/* - * mcfrs_wait_until_sent() --- wait until the transmitter is empty - */ -static void -mcfrs_wait_until_sent(struct tty_struct *tty, int timeout) -{ -#ifdef CONFIG_M5272 -#define MCF5272_FIFO_SIZE 25 /* fifo size + shift reg */ - - struct mcf_serial * info = (struct mcf_serial *)tty->driver_data; - volatile unsigned char *uartp; - unsigned long orig_jiffies, fifo_time, char_time, fifo_cnt; - - if (serial_paranoia_check(info, tty->name, "mcfrs_wait_until_sent")) - return; - - orig_jiffies = jiffies; - - /* - * Set the check interval to be 1/5 of the approximate time - * to send the entire fifo, and make it at least 1. The check - * interval should also be less than the timeout. - * - * Note: we have to use pretty tight timings here to satisfy - * the NIST-PCTS. - */ - lock_kernel(); - - fifo_time = (MCF5272_FIFO_SIZE * HZ * 10) / info->baud; - char_time = fifo_time / 5; - if (char_time == 0) - char_time = 1; - if (timeout && timeout < char_time) - char_time = timeout; - - /* - * Clamp the timeout period at 2 * the time to empty the - * fifo. Just to be safe, set the minimum at .5 seconds. - */ - fifo_time *= 2; - if (fifo_time < (HZ/2)) - fifo_time = HZ/2; - if (!timeout || timeout > fifo_time) - timeout = fifo_time; - - /* - * Account for the number of bytes in the UART - * transmitter FIFO plus any byte being shifted out. - */ - uartp = (volatile unsigned char *) info->addr; - for (;;) { - fifo_cnt = (uartp[MCFUART_UTF] & MCFUART_UTF_TXB); - if ((uartp[MCFUART_USR] & (MCFUART_USR_TXREADY| - MCFUART_USR_TXEMPTY)) == - MCFUART_USR_TXREADY) - fifo_cnt++; - if (fifo_cnt == 0) - break; - msleep_interruptible(jiffies_to_msecs(char_time)); - if (signal_pending(current)) - break; - if (timeout && time_after(jiffies, orig_jiffies + timeout)) - break; - } - unlock_kernel(); -#else - /* - * For the other coldfire models, assume all data has been sent - */ -#endif -} - -/* - * mcfrs_hangup() --- called by tty_hangup() when a hangup is signaled. - */ -void mcfrs_hangup(struct tty_struct *tty) -{ - struct mcf_serial * info = (struct mcf_serial *)tty->driver_data; - - if (serial_paranoia_check(info, tty->name, "mcfrs_hangup")) - return; - - mcfrs_flush_buffer(tty); - shutdown(info); - info->event = 0; - info->count = 0; - info->flags &= ~ASYNC_NORMAL_ACTIVE; - info->port.tty = NULL; - wake_up_interruptible(&info->open_wait); -} - -/* - * ------------------------------------------------------------ - * mcfrs_open() and friends - * ------------------------------------------------------------ - */ -static int block_til_ready(struct tty_struct *tty, struct file * filp, - struct mcf_serial *info) -{ - DECLARE_WAITQUEUE(wait, current); - int retval; - int do_clocal = 0; - - /* - * If the device is in the middle of being closed, then block - * until it's done, and then try again. - */ - if (info->flags & ASYNC_CLOSING) { - interruptible_sleep_on(&info->close_wait); -#ifdef SERIAL_DO_RESTART - if (info->flags & ASYNC_HUP_NOTIFY) - return -EAGAIN; - else - return -ERESTARTSYS; -#else - return -EAGAIN; -#endif - } - - /* - * If non-blocking mode is set, or the port is not enabled, - * then make the check up front and then exit. - */ - if ((filp->f_flags & O_NONBLOCK) || - (tty->flags & (1 << TTY_IO_ERROR))) { - info->flags |= ASYNC_NORMAL_ACTIVE; - return 0; - } - - if (tty->termios->c_cflag & CLOCAL) - do_clocal = 1; - - /* - * Block waiting for the carrier detect and the line to become - * free (i.e., not in use by the callout). While we are in - * this loop, info->count is dropped by one, so that - * mcfrs_close() knows when to free things. We restore it upon - * exit, either normal or abnormal. - */ - retval = 0; - add_wait_queue(&info->open_wait, &wait); -#ifdef SERIAL_DEBUG_OPEN - printk("block_til_ready before block: ttyS%d, count = %d\n", - info->line, info->count); -#endif - info->count--; - info->blocked_open++; - while (1) { - local_irq_disable(); - mcfrs_setsignals(info, 1, 1); - local_irq_enable(); - current->state = TASK_INTERRUPTIBLE; - if (tty_hung_up_p(filp) || - !(info->flags & ASYNC_INITIALIZED)) { -#ifdef SERIAL_DO_RESTART - if (info->flags & ASYNC_HUP_NOTIFY) - retval = -EAGAIN; - else - retval = -ERESTARTSYS; -#else - retval = -EAGAIN; -#endif - break; - } - if (!(info->flags & ASYNC_CLOSING) && - (do_clocal || (mcfrs_getsignals(info) & TIOCM_CD))) - break; - if (signal_pending(current)) { - retval = -ERESTARTSYS; - break; - } -#ifdef SERIAL_DEBUG_OPEN - printk("block_til_ready blocking: ttyS%d, count = %d\n", - info->line, info->count); -#endif - schedule(); - } - current->state = TASK_RUNNING; - remove_wait_queue(&info->open_wait, &wait); - if (!tty_hung_up_p(filp)) - info->count++; - info->blocked_open--; -#ifdef SERIAL_DEBUG_OPEN - printk("block_til_ready after blocking: ttyS%d, count = %d\n", - info->line, info->count); -#endif - if (retval) - return retval; - info->flags |= ASYNC_NORMAL_ACTIVE; - return 0; -} - -/* - * This routine is called whenever a serial port is opened. It - * enables interrupts for a serial port, linking in its structure into - * the IRQ chain. It also performs the serial-specific - * initialization for the tty structure. - */ -int mcfrs_open(struct tty_struct *tty, struct file * filp) -{ - struct mcf_serial *info; - int retval, line; - - line = tty->index; - if ((line < 0) || (line >= NR_PORTS)) - return -ENODEV; - info = mcfrs_table + line; - if (serial_paranoia_check(info, tty->name, "mcfrs_open")) - return -ENODEV; -#ifdef SERIAL_DEBUG_OPEN - printk("mcfrs_open %s, count = %d\n", tty->name, info->count); -#endif - info->count++; - tty->driver_data = info; - info->port.tty = tty; - - /* - * Start up serial port - */ - retval = startup(info); - if (retval) - return retval; - - retval = block_til_ready(tty, filp, info); - if (retval) { -#ifdef SERIAL_DEBUG_OPEN - printk("mcfrs_open returning after block_til_ready with %d\n", - retval); -#endif - return retval; - } - -#ifdef SERIAL_DEBUG_OPEN - printk("mcfrs_open %s successful...\n", tty->name); -#endif - return 0; -} - -/* - * Based on the line number set up the internal interrupt stuff. - */ -static void mcfrs_irqinit(struct mcf_serial *info) -{ -#if defined(CONFIG_M5272) - volatile unsigned long *icrp; - volatile unsigned long *portp; - volatile unsigned char *uartp; - - uartp = info->addr; - icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR2); - - switch (info->line) { - case 0: - *icrp = 0xe0000000; - break; - case 1: - *icrp = 0x0e000000; - break; - default: - printk("MCFRS: don't know how to handle UART %d interrupt?\n", - info->line); - return; - } - - /* Enable the output lines for the serial ports */ - portp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_PBCNT); - *portp = (*portp & ~0x000000ff) | 0x00000055; - portp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_PDCNT); - *portp = (*portp & ~0x000003fc) | 0x000002a8; -#elif defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) - volatile unsigned char *icrp, *uartp; - volatile unsigned long *imrp; - - uartp = info->addr; - - icrp = (volatile unsigned char *) (MCF_MBAR + MCFICM_INTC0 + - MCFINTC_ICR0 + MCFINT_UART0 + info->line); - *icrp = 0x30 + info->line; /* level 6, line based priority */ - - imrp = (volatile unsigned long *) (MCF_MBAR + MCFICM_INTC0 + - MCFINTC_IMRL); - *imrp &= ~((1 << (info->irq - MCFINT_VECBASE)) | 1); -#if defined(CONFIG_M527x) - { - /* - * External Pin Mask Setting & Enable External Pin for Interface - * mrcbis@aliceposta.it - */ - u16 *serpin_enable_mask; - serpin_enable_mask = (u16 *) (MCF_IPSBAR + MCF_GPIO_PAR_UART); - if (info->line == 0) - *serpin_enable_mask |= UART0_ENABLE_MASK; - else if (info->line == 1) - *serpin_enable_mask |= UART1_ENABLE_MASK; - else if (info->line == 2) - *serpin_enable_mask |= UART2_ENABLE_MASK; - } -#endif -#if defined(CONFIG_M528x) - /* make sure PUAPAR is set for UART0 and UART1 */ - if (info->line < 2) { - volatile unsigned char *portp = (volatile unsigned char *) (MCF_MBAR + MCF5282_GPIO_PUAPAR); - *portp |= (0x03 << (info->line * 2)); - } -#endif -#elif defined(CONFIG_M520x) - volatile unsigned char *icrp, *uartp; - volatile unsigned long *imrp; - - uartp = info->addr; - - icrp = (volatile unsigned char *) (MCF_MBAR + MCFICM_INTC0 + - MCFINTC_ICR0 + MCFINT_UART0 + info->line); - *icrp = 0x03; - - imrp = (volatile unsigned long *) (MCF_MBAR + MCFICM_INTC0 + - MCFINTC_IMRL); - *imrp &= ~((1 << (info->irq - MCFINT_VECBASE)) | 1); - if (info->line < 2) { - unsigned short *uart_par; - uart_par = (unsigned short *)(MCF_IPSBAR + MCF_GPIO_PAR_UART); - if (info->line == 0) - *uart_par |= MCF_GPIO_PAR_UART_PAR_UTXD0 - | MCF_GPIO_PAR_UART_PAR_URXD0; - else if (info->line == 1) - *uart_par |= MCF_GPIO_PAR_UART_PAR_UTXD1 - | MCF_GPIO_PAR_UART_PAR_URXD1; - } else if (info->line == 2) { - unsigned char *feci2c_par; - feci2c_par = (unsigned char *)(MCF_IPSBAR + MCF_GPIO_PAR_FECI2C); - *feci2c_par &= ~0x0F; - *feci2c_par |= MCF_GPIO_PAR_FECI2C_PAR_SCL_UTXD2 - | MCF_GPIO_PAR_FECI2C_PAR_SDA_URXD2; - } -#elif defined(CONFIG_M532x) - volatile unsigned char *uartp; - uartp = info->addr; - switch (info->line) { - case 0: - MCF_INTC0_ICR26 = 0x3; - MCF_INTC0_CIMR = 26; - /* GPIO initialization */ - MCF_GPIO_PAR_UART |= 0x000F; - break; - case 1: - MCF_INTC0_ICR27 = 0x3; - MCF_INTC0_CIMR = 27; - /* GPIO initialization */ - MCF_GPIO_PAR_UART |= 0x0FF0; - break; - case 2: - MCF_INTC0_ICR28 = 0x3; - MCF_INTC0_CIMR = 28; - /* GPIOs also must be initalized, depends on board */ - break; - } -#else - volatile unsigned char *icrp, *uartp; - - switch (info->line) { - case 0: - icrp = (volatile unsigned char *) (MCF_MBAR + MCFSIM_UART1ICR); - *icrp = /*MCFSIM_ICR_AUTOVEC |*/ MCFSIM_ICR_LEVEL6 | - MCFSIM_ICR_PRI1; - mcf_setimr(mcf_getimr() & ~MCFSIM_IMR_UART1); - break; - case 1: - icrp = (volatile unsigned char *) (MCF_MBAR + MCFSIM_UART2ICR); - *icrp = /*MCFSIM_ICR_AUTOVEC |*/ MCFSIM_ICR_LEVEL6 | - MCFSIM_ICR_PRI2; - mcf_setimr(mcf_getimr() & ~MCFSIM_IMR_UART2); - break; - default: - printk("MCFRS: don't know how to handle UART %d interrupt?\n", - info->line); - return; - } - - uartp = info->addr; - uartp[MCFUART_UIVR] = info->irq; -#endif - - /* Clear mask, so no surprise interrupts. */ - uartp[MCFUART_UIMR] = 0; - - if (request_irq(info->irq, mcfrs_interrupt, IRQF_DISABLED, - "ColdFire UART", NULL)) { - printk("MCFRS: Unable to attach ColdFire UART %d interrupt " - "vector=%d\n", info->line, info->irq); - } - - return; -} - - -char *mcfrs_drivername = "ColdFire internal UART serial driver version 1.00\n"; - - -/* - * Serial stats reporting... - */ -int mcfrs_readproc(char *page, char **start, off_t off, int count, - int *eof, void *data) -{ - struct mcf_serial *info; - char str[20]; - int len, sigs, i; - - len = sprintf(page, mcfrs_drivername); - for (i = 0; (i < NR_PORTS); i++) { - info = &mcfrs_table[i]; - len += sprintf((page + len), "%d: port:%x irq=%d baud:%d ", - i, (unsigned int) info->addr, info->irq, info->baud); - if (info->stats.rx || info->stats.tx) - len += sprintf((page + len), "tx:%d rx:%d ", - info->stats.tx, info->stats.rx); - if (info->stats.rxframing) - len += sprintf((page + len), "fe:%d ", - info->stats.rxframing); - if (info->stats.rxparity) - len += sprintf((page + len), "pe:%d ", - info->stats.rxparity); - if (info->stats.rxbreak) - len += sprintf((page + len), "brk:%d ", - info->stats.rxbreak); - if (info->stats.rxoverrun) - len += sprintf((page + len), "oe:%d ", - info->stats.rxoverrun); - - str[0] = str[1] = 0; - if ((sigs = mcfrs_getsignals(info))) { - if (sigs & TIOCM_RTS) - strcat(str, "|RTS"); - if (sigs & TIOCM_CTS) - strcat(str, "|CTS"); - if (sigs & TIOCM_DTR) - strcat(str, "|DTR"); - if (sigs & TIOCM_CD) - strcat(str, "|CD"); - } - - len += sprintf((page + len), "%s\n", &str[1]); - } - - return(len); -} - - -/* Finally, routines used to initialize the serial driver. */ - -static void show_serial_version(void) -{ - printk(mcfrs_drivername); -} - -static const struct tty_operations mcfrs_ops = { - .open = mcfrs_open, - .close = mcfrs_close, - .write = mcfrs_write, - .flush_chars = mcfrs_flush_chars, - .write_room = mcfrs_write_room, - .chars_in_buffer = mcfrs_chars_in_buffer, - .flush_buffer = mcfrs_flush_buffer, - .ioctl = mcfrs_ioctl, - .throttle = mcfrs_throttle, - .unthrottle = mcfrs_unthrottle, - .set_termios = mcfrs_set_termios, - .stop = mcfrs_stop, - .start = mcfrs_start, - .hangup = mcfrs_hangup, - .read_proc = mcfrs_readproc, - .wait_until_sent = mcfrs_wait_until_sent, - .tiocmget = mcfrs_tiocmget, - .tiocmset = mcfrs_tiocmset, -}; - -/* mcfrs_init inits the driver */ -static int __init -mcfrs_init(void) -{ - struct mcf_serial *info; - unsigned long flags; - int i; - - /* Setup base handler, and timer table. */ -#ifdef MCFPP_DCD0 - init_timer(&mcfrs_timer_struct); - mcfrs_timer_struct.function = mcfrs_timer; - mcfrs_timer_struct.data = 0; - mcfrs_timer_struct.expires = jiffies + HZ/25; - add_timer(&mcfrs_timer_struct); - mcfrs_ppstatus = mcf_getppdata() & (MCFPP_DCD0 | MCFPP_DCD1); -#endif - mcfrs_serial_driver = alloc_tty_driver(NR_PORTS); - if (!mcfrs_serial_driver) - return -ENOMEM; - - show_serial_version(); - - /* Initialize the tty_driver structure */ - mcfrs_serial_driver->owner = THIS_MODULE; - mcfrs_serial_driver->name = "ttyS"; - mcfrs_serial_driver->driver_name = "mcfserial"; - mcfrs_serial_driver->major = TTY_MAJOR; - mcfrs_serial_driver->minor_start = 64; - mcfrs_serial_driver->type = TTY_DRIVER_TYPE_SERIAL; - mcfrs_serial_driver->subtype = SERIAL_TYPE_NORMAL; - mcfrs_serial_driver->init_termios = tty_std_termios; - - mcfrs_serial_driver->init_termios.c_cflag = - mcfrs_console_cbaud | CS8 | CREAD | HUPCL | CLOCAL; - mcfrs_serial_driver->flags = TTY_DRIVER_REAL_RAW; - - tty_set_operations(mcfrs_serial_driver, &mcfrs_ops); - - if (tty_register_driver(mcfrs_serial_driver)) { - printk("MCFRS: Couldn't register serial driver\n"); - put_tty_driver(mcfrs_serial_driver); - return(-EBUSY); - } - - local_irq_save(flags); - - /* - * Configure all the attached serial ports. - */ - for (i = 0, info = mcfrs_table; (i < NR_PORTS); i++, info++) { - info->magic = SERIAL_MAGIC; - info->line = i; - info->port.tty = NULL; - info->custom_divisor = 16; - info->close_delay = 50; - info->closing_wait = 3000; - info->x_char = 0; - info->event = 0; - info->count = 0; - info->blocked_open = 0; - INIT_WORK(&info->tqueue, mcfrs_offintr); - INIT_WORK(&info->tqueue_hangup, do_serial_hangup); - init_waitqueue_head(&info->open_wait); - init_waitqueue_head(&info->close_wait); - - info->imr = 0; - mcfrs_setsignals(info, 0, 0); - mcfrs_irqinit(info); - - printk("ttyS%d at 0x%04x (irq = %d)", info->line, - (unsigned int) info->addr, info->irq); - printk(" is a builtin ColdFire UART\n"); - } - - local_irq_restore(flags); - return 0; -} - -module_init(mcfrs_init); - -/****************************************************************************/ -/* Serial Console */ -/****************************************************************************/ - -/* - * Quick and dirty UART initialization, for console output. - */ - -void mcfrs_init_console(void) -{ - volatile unsigned char *uartp; - unsigned int clk; - - /* - * Reset UART, get it into known state... - */ - uartp = (volatile unsigned char *) (MCF_MBAR + - (mcfrs_console_port ? MCFUART_BASE2 : MCFUART_BASE1)); - - uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETRX; /* reset RX */ - uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETTX; /* reset TX */ - uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETMRPTR; /* reset MR pointer */ - - /* - * Set port for defined baud , 8 data bits, 1 stop bit, no parity. - */ - uartp[MCFUART_UMR] = MCFUART_MR1_PARITYNONE | MCFUART_MR1_CS8; - uartp[MCFUART_UMR] = MCFUART_MR2_STOP1; - -#ifdef CONFIG_M5272 -{ - /* - * For the MCF5272, also compute the baudrate fraction. - */ - int fraction = MCF_BUSCLK - (clk * 32 * mcfrs_console_baud); - fraction *= 16; - fraction /= (32 * mcfrs_console_baud); - uartp[MCFUART_UFPD] = (fraction & 0xf); /* set fraction */ - clk = (MCF_BUSCLK / mcfrs_console_baud) / 32; -} -#else - clk = ((MCF_BUSCLK / mcfrs_console_baud) + 16) / 32; /* set baud */ -#endif - - uartp[MCFUART_UBG1] = (clk & 0xff00) >> 8; /* set msb baud */ - uartp[MCFUART_UBG2] = (clk & 0xff); /* set lsb baud */ - uartp[MCFUART_UCSR] = MCFUART_UCSR_RXCLKTIMER | MCFUART_UCSR_TXCLKTIMER; - uartp[MCFUART_UCR] = MCFUART_UCR_RXENABLE | MCFUART_UCR_TXENABLE; - - mcfrs_console_inited++; - return; -} - - -/* - * Setup for console. Argument comes from the boot command line. - */ - -int mcfrs_console_setup(struct console *cp, char *arg) -{ - int i, n = CONSOLE_BAUD_RATE; - - if (!cp) - return(-1); - - if (!strncmp(cp->name, "ttyS", 4)) - mcfrs_console_port = cp->index; - else if (!strncmp(cp->name, "cua", 3)) - mcfrs_console_port = cp->index; - else - return(-1); - - if (arg) - n = simple_strtoul(arg,NULL,0); - for (i = 0; i < MCFRS_BAUD_TABLE_SIZE; i++) - if (mcfrs_baud_table[i] == n) - break; - if (i < MCFRS_BAUD_TABLE_SIZE) { - mcfrs_console_baud = n; - mcfrs_console_cbaud = 0; - if (i > 15) { - mcfrs_console_cbaud |= CBAUDEX; - i -= 15; - } - mcfrs_console_cbaud |= i; - } - mcfrs_init_console(); /* make sure baud rate changes */ - return(0); -} - - -static struct tty_driver *mcfrs_console_device(struct console *c, int *index) -{ - *index = c->index; - return mcfrs_serial_driver; -} - - -/* - * Output a single character, using UART polled mode. - * This is used for console output. - */ - -int mcfrs_put_char(char ch) -{ - volatile unsigned char *uartp; - unsigned long flags; - int i; - - uartp = (volatile unsigned char *) (MCF_MBAR + - (mcfrs_console_port ? MCFUART_BASE2 : MCFUART_BASE1)); - - local_irq_save(flags); - for (i = 0; (i < 0x10000); i++) { - if (uartp[MCFUART_USR] & MCFUART_USR_TXREADY) - break; - } - if (i < 0x10000) { - uartp[MCFUART_UTB] = ch; - for (i = 0; (i < 0x10000); i++) - if (uartp[MCFUART_USR] & MCFUART_USR_TXEMPTY) - break; - } - if (i >= 0x10000) - mcfrs_init_console(); /* try and get it back */ - local_irq_restore(flags); - - return 1; -} - - -/* - * rs_console_write is registered for printk output. - */ - -void mcfrs_console_write(struct console *cp, const char *p, unsigned len) -{ - if (!mcfrs_console_inited) - mcfrs_init_console(); - while (len-- > 0) { - if (*p == '\n') - mcfrs_put_char('\r'); - mcfrs_put_char(*p++); - } -} - -/* - * declare our consoles - */ - -struct console mcfrs_console = { - .name = "ttyS", - .write = mcfrs_console_write, - .device = mcfrs_console_device, - .setup = mcfrs_console_setup, - .flags = CON_PRINTBUFFER, - .index = -1, -}; - -static int __init mcfrs_console_init(void) -{ - register_console(&mcfrs_console); - return 0; -} - -console_initcall(mcfrs_console_init); - -/****************************************************************************/ diff --git a/drivers/serial/mcfserial.h b/drivers/serial/mcfserial.h deleted file mode 100644 index 56420e2cb110..000000000000 --- a/drivers/serial/mcfserial.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * mcfserial.c -- serial driver for ColdFire internal UARTS. - * - * Copyright (c) 1999 Greg Ungerer - * Copyright (c) 2000-2001 Lineo, Inc. - * Copyright (c) 2002 SnapGear Inc., - * - * Based on code from 68332serial.c which was: - * - * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) - * Copyright (C) 1998 TSHG - * Copyright (c) 1999 Rt-Control Inc. - */ -#ifndef _MCF_SERIAL_H -#define _MCF_SERIAL_H - -#include - -#ifdef __KERNEL__ - -/* - * Define a local serial stats structure. - */ - -struct mcf_stats { - unsigned int rx; - unsigned int tx; - unsigned int rxbreak; - unsigned int rxframing; - unsigned int rxparity; - unsigned int rxoverrun; -}; - - -/* - * This is our internal structure for each serial port's state. - * Each serial port has one of these structures associated with it. - */ - -struct mcf_serial { - int magic; - volatile unsigned char *addr; /* UART memory address */ - int irq; - int flags; /* defined in tty.h */ - int type; /* UART type */ - struct tty_struct *tty; - unsigned char imr; /* Software imr register */ - unsigned int baud; - int sigs; - int custom_divisor; - int x_char; /* xon/xoff character */ - int baud_base; - int close_delay; - unsigned short closing_wait; - unsigned short closing_wait2; - unsigned long event; - int line; - int count; /* # of fd on device */ - int blocked_open; /* # of blocked opens */ - unsigned char *xmit_buf; - int xmit_head; - int xmit_tail; - int xmit_cnt; - struct mcf_stats stats; - struct work_struct tqueue; - struct work_struct tqueue_hangup; - wait_queue_head_t open_wait; - wait_queue_head_t close_wait; - -}; - -#endif /* __KERNEL__ */ - -#endif /* _MCF_SERIAL_H */ -- cgit v1.2.3 From 02ae9a1a8bc1d08a8fd5f6a0b8bde400b0f891b9 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Fri, 16 May 2008 11:49:22 +0200 Subject: HID: add compat support Add compat option to hid code to allow loading of all modules on systems which don't allow autoloading because of old userspace. Signed-off-by: Jiri Slaby Signed-off-by: Jiri Kosina --- Documentation/feature-removal-schedule.txt | 7 +++++++ drivers/hid/Kconfig | 12 ++++++++++++ drivers/hid/Makefile | 4 ++++ drivers/hid/hid-apple.c | 2 ++ drivers/hid/hid-core.c | 12 ++++++++++++ drivers/hid/hid-dummy.c | 18 ++++++++++++++++++ drivers/hid/hid-logitech.c | 2 ++ include/linux/hid.h | 17 +++++++++++++++-- 8 files changed, 72 insertions(+), 2 deletions(-) create mode 100644 drivers/hid/hid-dummy.c (limited to 'Documentation/feature-removal-schedule.txt') diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index cc8093c15cf5..4d2566a7d168 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -287,6 +287,13 @@ Who: Glauber Costa --------------------------- +What: remove HID compat support +When: 2.6.29 +Why: needed only as a temporary solution until distros fix themselves up +Who: Jiri Slaby + +--------------------------- + What: /sys/o2cb symlink When: January 2010 Why: /sys/fs/o2cb is the proper location for this information - /sys/o2cb diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 41283fff5145..d9d1a5671d95 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -70,6 +70,18 @@ source "drivers/hid/usbhid/Kconfig" menu "Special HID drivers" depends on HID +config HID_COMPAT + bool "Load all HID drivers on hid core load" + default y + ---help--- + Compatible option for older userspace. If you have system without udev + support of module loading through aliases and also old + module-init-tools which can't handle hid bus, choose Y here. Otherwise + say N. If you say N and your userspace is old enough, the only + functionality you loose is modules autoloading. + + If unsure, say Y. + config HID_APPLE tristate "Apple" default m diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile index 4a14821ceefa..8e053eca4742 100644 --- a/drivers/hid/Makefile +++ b/drivers/hid/Makefile @@ -8,6 +8,10 @@ obj-$(CONFIG_HID) += hid.o hid-$(CONFIG_HID_DEBUG) += hid-debug.o hid-$(CONFIG_HIDRAW) += hidraw.o +ifdef CONFIG_HID_COMPAT +obj-m += hid-dummy.o +endif + obj-$(CONFIG_HID_APPLE) += hid-apple.o obj-$(CONFIG_HID_LOGITECH) += hid-logitech.o diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c index 5642e2c685fc..2a68661fcea8 100644 --- a/drivers/hid/hid-apple.c +++ b/drivers/hid/hid-apple.c @@ -477,3 +477,5 @@ static void apple_exit(void) module_init(apple_init); module_exit(apple_exit); MODULE_LICENSE("GPL"); + +HID_COMPAT_LOAD_DRIVER(apple); diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 8e3c264c9b2b..397e1b2ffe5a 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1532,6 +1532,14 @@ void hid_unregister_driver(struct hid_driver *hdrv) } EXPORT_SYMBOL_GPL(hid_unregister_driver); +#ifdef CONFIG_HID_COMPAT +static void hid_compat_load(struct work_struct *ws) +{ + request_module("hid-dummy"); +} +static DECLARE_WORK(hid_compat_work, hid_compat_load); +#endif + static int __init hid_init(void) { int ret; @@ -1546,6 +1554,10 @@ static int __init hid_init(void) if (ret) goto err_bus; +#ifdef CONFIG_HID_COMPAT + schedule_work(&hid_compat_work); +#endif + return 0; err_bus: bus_unregister(&hid_bus_type); diff --git a/drivers/hid/hid-dummy.c b/drivers/hid/hid-dummy.c new file mode 100644 index 000000000000..b76c44efe1b8 --- /dev/null +++ b/drivers/hid/hid-dummy.c @@ -0,0 +1,18 @@ +#include +#include +#include + +static int __init hid_dummy_init(void) +{ +#ifdef CONFIG_HID_APPLE_MODULE + HID_COMPAT_CALL_DRIVER(apple); +#endif +#ifdef CONFIG_HID_LOGITECH_MODULE + HID_COMPAT_CALL_DRIVER(logitech); +#endif + + return -EIO; +} +module_init(hid_dummy_init); + +MODULE_LICENSE("GPL"); diff --git a/drivers/hid/hid-logitech.c b/drivers/hid/hid-logitech.c index 395e42ffb4d5..b2aaebe1ac05 100644 --- a/drivers/hid/hid-logitech.c +++ b/drivers/hid/hid-logitech.c @@ -310,3 +310,5 @@ static void lg_exit(void) module_init(lg_init); module_exit(lg_exit); MODULE_LICENSE("GPL"); + +HID_COMPAT_LOAD_DRIVER(logitech); diff --git a/include/linux/hid.h b/include/linux/hid.h index 75cc1531dd84..60e44e6b86e6 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -790,10 +790,23 @@ dbg_hid(const char *fmt, ...) return 0; } #define dbg_hid_line dbg_hid -#endif +#endif /* HID_DEBUG */ #define err_hid(format, arg...) printk(KERN_ERR "%s: " format "\n" , \ __FILE__ , ## arg) -#endif +#endif /* HID_FF */ + +#ifdef CONFIG_HID_COMPAT +#define HID_COMPAT_LOAD_DRIVER(name) \ +void hid_compat_##name(void) { } \ +EXPORT_SYMBOL(hid_compat_##name) +#else +#define HID_COMPAT_LOAD_DRIVER(name) +#endif /* HID_COMPAT */ +#define HID_COMPAT_CALL_DRIVER(name) do { \ + extern void hid_compat_##name(void); \ + hid_compat_##name(); \ +} while (0) + #endif -- cgit v1.2.3 From c80cfb0406c01bb5da91bfe30f5cb1fd96831138 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Wed, 15 Oct 2008 22:01:35 -0700 Subject: vsprintf: use new vsprintf symbolic function pointer format Use the '%pF' format to get rid of an "#ifdef DEBUG" and make some printks atomic. This removes the last in-tree uses of print_fn_descriptor_symbol(). I marked print_fn_descriptor_symbol() deprecated and scheduled it for removal next year to give time for out-of-tree modules to be updated. parisc's print_fn_descriptor_symbol() is currently broken there (it needs to dereference the function pointer similar to ia64 and power). This patch shouldn't make anything worse, but it means we need to fix dereference_function_descriptor() instead of print_fn_descriptor_symbol() to get meaningful initcall_debug output. Signed-off-by: Bjorn Helgaas Cc: Jesse Barnes Cc: Kyle McMartin Cc: "Rafael J. Wysocki" Cc: Kay Sievers Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/feature-removal-schedule.txt | 9 +++++++++ drivers/base/power/main.c | 7 ++----- include/linux/kallsyms.h | 8 +++----- 3 files changed, 14 insertions(+), 10 deletions(-) (limited to 'Documentation/feature-removal-schedule.txt') diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index 4d2566a7d168..f5f812daf9f4 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -294,6 +294,15 @@ Who: Jiri Slaby --------------------------- +What: print_fn_descriptor_symbol() +When: October 2009 +Why: The %pF vsprintf format provides the same functionality in a + simpler way. print_fn_descriptor_symbol() is deprecated but + still present to give out-of-tree modules time to change. +Who: Bjorn Helgaas + +--------------------------- + What: /sys/o2cb symlink When: January 2010 Why: /sys/fs/o2cb is the proper location for this information - /sys/o2cb diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 273a944d4040..03bde7524bc3 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -778,10 +778,7 @@ EXPORT_SYMBOL_GPL(device_suspend); void __suspend_report_result(const char *function, void *fn, int ret) { - if (ret) { - printk(KERN_ERR "%s(): ", function); - print_fn_descriptor_symbol("%s returns ", fn); - printk("%d\n", ret); - } + if (ret) + printk(KERN_ERR "%s(): %pF returns %d\n", function, fn, ret); } EXPORT_SYMBOL_GPL(__suspend_report_result); diff --git a/include/linux/kallsyms.h b/include/linux/kallsyms.h index b96144887444..f3fe34391d8e 100644 --- a/include/linux/kallsyms.h +++ b/include/linux/kallsyms.h @@ -93,12 +93,10 @@ static inline void print_symbol(const char *fmt, unsigned long addr) } /* - * Pretty-print a function pointer. - * - * ia64 and ppc64 function pointers are really function descriptors, - * which contain a pointer the real address. + * Pretty-print a function pointer. This function is deprecated. + * Please use the "%pF" vsprintf format instead. */ -static inline void print_fn_descriptor_symbol(const char *fmt, void *addr) +static inline void __deprecated print_fn_descriptor_symbol(const char *fmt, void *addr) { #if defined(CONFIG_IA64) || defined(CONFIG_PPC64) addr = *(void **)addr; -- cgit v1.2.3