diff options
author | Jeff Garzik <jeff@garzik.org> | 2006-04-12 20:54:43 (GMT) |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2006-04-12 20:54:43 (GMT) |
commit | a890b15c0990cc8d686edcc85f5fccde71ad5ce9 (patch) | |
tree | 73162355b58283a2531f13fbbf663809f95c1483 /drivers | |
parent | 79fa1b677be3a985cc66b9218a4dd09818f1051b (diff) | |
parent | 26ec634c31a11a003040e10b4d650495158632fd (diff) | |
download | linux-a890b15c0990cc8d686edcc85f5fccde71ad5ce9.tar.xz |
Merge branch 'upstream'
Diffstat (limited to 'drivers')
94 files changed, 3457 insertions, 3622 deletions
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 5cb9630..c24652d 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -329,7 +329,7 @@ config ACPI_CONTAINER config ACPI_HOTPLUG_MEMORY tristate "Memory Hotplug" depends on ACPI - depends on MEMORY_HOTPLUG + depends on MEMORY_HOTPLUG || X86_64 default n help This driver adds supports for ACPI Memory Hotplug. This driver diff --git a/drivers/base/node.c b/drivers/base/node.c index 16c513a..c80c3ae 100644 --- a/drivers/base/node.c +++ b/drivers/base/node.c @@ -106,7 +106,7 @@ static ssize_t node_read_numastat(struct sys_device * dev, char * buf) other_node = 0; for (i = 0; i < MAX_NR_ZONES; i++) { struct zone *z = &pg->node_zones[i]; - for (cpu = 0; cpu < NR_CPUS; cpu++) { + for_each_online_cpu(cpu) { struct per_cpu_pageset *ps = zone_pcp(z,cpu); numa_hit += ps->numa_hit; numa_miss += ps->numa_miss; diff --git a/drivers/cdrom/aztcd.c b/drivers/cdrom/aztcd.c index ce4a1ce..ec00489 100644 --- a/drivers/cdrom/aztcd.c +++ b/drivers/cdrom/aztcd.c @@ -1763,7 +1763,7 @@ static int __init aztcd_init(void) release_region(azt_port, 4); } } - if ((azt_port_auto[i] == 0) || (i == 16)) { + if ((i == 16) || (azt_port_auto[i] == 0)) { printk(KERN_INFO "aztcd: no AZTECH CD-ROM drive found\n"); return -EIO; } diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 889cad0..4022966 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -805,10 +805,6 @@ config S3C2410_RTC Samsung S3C2410. This can provide periodic interrupt rates from 1Hz to 64Hz for user programs, and wakeup from Alarm. -config RTC_VR41XX - tristate "NEC VR4100 series Real Time Clock Support" - depends on CPU_VR41XX - config COBALT_LCD bool "Support for Cobalt LCD" depends on MIPS_COBALT diff --git a/drivers/char/Makefile b/drivers/char/Makefile index a73cb49..f5b01c6 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -67,7 +67,6 @@ obj-$(CONFIG_SGI_DS1286) += ds1286.o obj-$(CONFIG_SGI_IP27_RTC) += ip27-rtc.o obj-$(CONFIG_DS1302) += ds1302.o obj-$(CONFIG_S3C2410_RTC) += s3c2410-rtc.o -obj-$(CONFIG_RTC_VR41XX) += vr41xx_rtc.o ifeq ($(CONFIG_GENERIC_NVRAM),y) obj-$(CONFIG_NVRAM) += generic_nvram.o else diff --git a/drivers/char/applicom.c b/drivers/char/applicom.c index 927a5bb..a370e7a 100644 --- a/drivers/char/applicom.c +++ b/drivers/char/applicom.c @@ -142,7 +142,7 @@ static int ac_register_board(unsigned long physloc, void __iomem *loc, if (!boardno) boardno = readb(loc + NUMCARD_OWNER_TO_PC); - if (!boardno && boardno > MAX_BOARD) { + if (!boardno || boardno > MAX_BOARD) { printk(KERN_WARNING "Board #%d (at 0x%lx) is out of range (1 <= x <= %d).\n", boardno, physloc, MAX_BOARD); return 0; diff --git a/drivers/char/dtlk.c b/drivers/char/dtlk.c index a229915..87dcaa2 100644 --- a/drivers/char/dtlk.c +++ b/drivers/char/dtlk.c @@ -490,7 +490,7 @@ for (i = 0; i < 10; i++) \ release_region(dtlk_portlist[i], DTLK_IO_EXTENT); } - printk(KERN_INFO "\nDoubleTalk PC - not found\n"); + printk(KERN_INFO "DoubleTalk PC - not found\n"); return -ENODEV; } diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index 0ded046..9f2f8fd 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c @@ -941,6 +941,7 @@ int ipmi_set_gets_events(ipmi_user_t user, int val) list_del(&msg->link); list_add_tail(&msg->link, &msgs); } + intf->waiting_events_count = 0; } /* Hold the events lock while doing this to preserve order. */ @@ -2916,6 +2917,7 @@ static int handle_read_event_rsp(ipmi_smi_t intf, copy_event_into_recv_msg(recv_msg, msg); list_add_tail(&(recv_msg->link), &(intf->waiting_events)); + intf->waiting_events_count++; } else { /* There's too many things in the queue, discard this message. */ diff --git a/drivers/char/random.c b/drivers/char/random.c index 86be04b..58f3512 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -1584,7 +1584,6 @@ u32 secure_ipv6_port_ephemeral(const __u32 *saddr, const __u32 *daddr, __u16 dpo return twothirdsMD4Transform(daddr, hash); } -EXPORT_SYMBOL(secure_ipv6_port_ephemeral); #endif #if defined(CONFIG_IP_DCCP) || defined(CONFIG_IP_DCCP_MODULE) diff --git a/drivers/char/tlclk.c b/drivers/char/tlclk.c index 2546637..f58ad7f 100644 --- a/drivers/char/tlclk.c +++ b/drivers/char/tlclk.c @@ -327,7 +327,7 @@ static ssize_t store_received_ref_clk3a(struct device *d, return strnlen(buf, count); } -static DEVICE_ATTR(received_ref_clk3a, S_IWUGO, NULL, +static DEVICE_ATTR(received_ref_clk3a, (S_IWUSR|S_IWGRP), NULL, store_received_ref_clk3a); @@ -349,7 +349,7 @@ static ssize_t store_received_ref_clk3b(struct device *d, return strnlen(buf, count); } -static DEVICE_ATTR(received_ref_clk3b, S_IWUGO, NULL, +static DEVICE_ATTR(received_ref_clk3b, (S_IWUSR|S_IWGRP), NULL, store_received_ref_clk3b); @@ -371,7 +371,7 @@ static ssize_t store_enable_clk3b_output(struct device *d, return strnlen(buf, count); } -static DEVICE_ATTR(enable_clk3b_output, S_IWUGO, NULL, +static DEVICE_ATTR(enable_clk3b_output, (S_IWUSR|S_IWGRP), NULL, store_enable_clk3b_output); static ssize_t store_enable_clk3a_output(struct device *d, @@ -392,7 +392,7 @@ static ssize_t store_enable_clk3a_output(struct device *d, return strnlen(buf, count); } -static DEVICE_ATTR(enable_clk3a_output, S_IWUGO, NULL, +static DEVICE_ATTR(enable_clk3a_output, (S_IWUSR|S_IWGRP), NULL, store_enable_clk3a_output); static ssize_t store_enable_clkb1_output(struct device *d, @@ -413,7 +413,7 @@ static ssize_t store_enable_clkb1_output(struct device *d, return strnlen(buf, count); } -static DEVICE_ATTR(enable_clkb1_output, S_IWUGO, NULL, +static DEVICE_ATTR(enable_clkb1_output, (S_IWUSR|S_IWGRP), NULL, store_enable_clkb1_output); @@ -435,7 +435,7 @@ static ssize_t store_enable_clka1_output(struct device *d, return strnlen(buf, count); } -static DEVICE_ATTR(enable_clka1_output, S_IWUGO, NULL, +static DEVICE_ATTR(enable_clka1_output, (S_IWUSR|S_IWGRP), NULL, store_enable_clka1_output); static ssize_t store_enable_clkb0_output(struct device *d, @@ -456,7 +456,7 @@ static ssize_t store_enable_clkb0_output(struct device *d, return strnlen(buf, count); } -static DEVICE_ATTR(enable_clkb0_output, S_IWUGO, NULL, +static DEVICE_ATTR(enable_clkb0_output, (S_IWUSR|S_IWGRP), NULL, store_enable_clkb0_output); static ssize_t store_enable_clka0_output(struct device *d, @@ -477,7 +477,7 @@ static ssize_t store_enable_clka0_output(struct device *d, return strnlen(buf, count); } -static DEVICE_ATTR(enable_clka0_output, S_IWUGO, NULL, +static DEVICE_ATTR(enable_clka0_output, (S_IWUSR|S_IWGRP), NULL, store_enable_clka0_output); static ssize_t store_select_amcb2_transmit_clock(struct device *d, @@ -519,7 +519,7 @@ static ssize_t store_select_amcb2_transmit_clock(struct device *d, return strnlen(buf, count); } -static DEVICE_ATTR(select_amcb2_transmit_clock, S_IWUGO, NULL, +static DEVICE_ATTR(select_amcb2_transmit_clock, (S_IWUSR|S_IWGRP), NULL, store_select_amcb2_transmit_clock); static ssize_t store_select_amcb1_transmit_clock(struct device *d, @@ -560,7 +560,7 @@ static ssize_t store_select_amcb1_transmit_clock(struct device *d, return strnlen(buf, count); } -static DEVICE_ATTR(select_amcb1_transmit_clock, S_IWUGO, NULL, +static DEVICE_ATTR(select_amcb1_transmit_clock, (S_IWUSR|S_IWGRP), NULL, store_select_amcb1_transmit_clock); static ssize_t store_select_redundant_clock(struct device *d, @@ -581,7 +581,7 @@ static ssize_t store_select_redundant_clock(struct device *d, return strnlen(buf, count); } -static DEVICE_ATTR(select_redundant_clock, S_IWUGO, NULL, +static DEVICE_ATTR(select_redundant_clock, (S_IWUSR|S_IWGRP), NULL, store_select_redundant_clock); static ssize_t store_select_ref_frequency(struct device *d, @@ -602,7 +602,7 @@ static ssize_t store_select_ref_frequency(struct device *d, return strnlen(buf, count); } -static DEVICE_ATTR(select_ref_frequency, S_IWUGO, NULL, +static DEVICE_ATTR(select_ref_frequency, (S_IWUSR|S_IWGRP), NULL, store_select_ref_frequency); static ssize_t store_filter_select(struct device *d, @@ -623,7 +623,7 @@ static ssize_t store_filter_select(struct device *d, return strnlen(buf, count); } -static DEVICE_ATTR(filter_select, S_IWUGO, NULL, store_filter_select); +static DEVICE_ATTR(filter_select, (S_IWUSR|S_IWGRP), NULL, store_filter_select); static ssize_t store_hardware_switching_mode(struct device *d, struct device_attribute *attr, const char *buf, size_t count) @@ -643,7 +643,7 @@ static ssize_t store_hardware_switching_mode(struct device *d, return strnlen(buf, count); } -static DEVICE_ATTR(hardware_switching_mode, S_IWUGO, NULL, +static DEVICE_ATTR(hardware_switching_mode, (S_IWUSR|S_IWGRP), NULL, store_hardware_switching_mode); static ssize_t store_hardware_switching(struct device *d, @@ -664,7 +664,7 @@ static ssize_t store_hardware_switching(struct device *d, return strnlen(buf, count); } -static DEVICE_ATTR(hardware_switching, S_IWUGO, NULL, +static DEVICE_ATTR(hardware_switching, (S_IWUSR|S_IWGRP), NULL, store_hardware_switching); static ssize_t store_refalign (struct device *d, @@ -684,7 +684,7 @@ static ssize_t store_refalign (struct device *d, return strnlen(buf, count); } -static DEVICE_ATTR(refalign, S_IWUGO, NULL, store_refalign); +static DEVICE_ATTR(refalign, (S_IWUSR|S_IWGRP), NULL, store_refalign); static ssize_t store_mode_select (struct device *d, struct device_attribute *attr, const char *buf, size_t count) @@ -704,7 +704,7 @@ static ssize_t store_mode_select (struct device *d, return strnlen(buf, count); } -static DEVICE_ATTR(mode_select, S_IWUGO, NULL, store_mode_select); +static DEVICE_ATTR(mode_select, (S_IWUSR|S_IWGRP), NULL, store_mode_select); static ssize_t store_reset (struct device *d, struct device_attribute *attr, const char *buf, size_t count) @@ -724,7 +724,7 @@ static ssize_t store_reset (struct device *d, return strnlen(buf, count); } -static DEVICE_ATTR(reset, S_IWUGO, NULL, store_reset); +static DEVICE_ATTR(reset, (S_IWUSR|S_IWGRP), NULL, store_reset); static struct attribute *tlclk_sysfs_entries[] = { &dev_attr_current_ref.attr, diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 98b126c..f70a47e 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -351,10 +351,10 @@ int tty_buffer_request_room(struct tty_struct *tty, size_t size) spin_unlock_irqrestore(&tty->buf.lock, flags); return size; } - EXPORT_SYMBOL_GPL(tty_buffer_request_room); -int tty_insert_flip_string(struct tty_struct *tty, const unsigned char *chars, size_t size) +int tty_insert_flip_string(struct tty_struct *tty, const unsigned char *chars, + size_t size) { int copied = 0; do { @@ -368,17 +368,16 @@ int tty_insert_flip_string(struct tty_struct *tty, const unsigned char *chars, s tb->used += space; copied += space; chars += space; -/* printk("Flip insert %d.\n", space); */ } /* There is a small chance that we need to split the data over several buffers. If this is the case we must loop */ while (unlikely(size > copied)); return copied; } - EXPORT_SYMBOL(tty_insert_flip_string); -int tty_insert_flip_string_flags(struct tty_struct *tty, const unsigned char *chars, const char *flags, size_t size) +int tty_insert_flip_string_flags(struct tty_struct *tty, + const unsigned char *chars, const char *flags, size_t size) { int copied = 0; do { @@ -399,9 +398,20 @@ int tty_insert_flip_string_flags(struct tty_struct *tty, const unsigned char *ch while (unlikely(size > copied)); return copied; } - EXPORT_SYMBOL_GPL(tty_insert_flip_string_flags); +void tty_schedule_flip(struct tty_struct *tty) +{ + unsigned long flags; + spin_lock_irqsave(&tty->buf.lock, flags); + if (tty->buf.tail != NULL) { + tty->buf.tail->active = 0; + tty->buf.tail->commit = tty->buf.tail->used; + } + spin_unlock_irqrestore(&tty->buf.lock, flags); + schedule_delayed_work(&tty->buf.work, 1); +} +EXPORT_SYMBOL(tty_schedule_flip); /* * Prepare a block of space in the buffer for data. Returns the length @@ -1730,7 +1740,7 @@ static void release_dev(struct file * filp) { struct tty_struct *tty, *o_tty; int pty_master, tty_closing, o_tty_closing, do_sleep; - int devpts_master, devpts; + int devpts; int idx; char buf[64]; unsigned long flags; @@ -1747,7 +1757,6 @@ static void release_dev(struct file * filp) pty_master = (tty->driver->type == TTY_DRIVER_TYPE_PTY && tty->driver->subtype == PTY_TYPE_MASTER); devpts = (tty->driver->flags & TTY_DRIVER_DEVPTS_MEM) != 0; - devpts_master = pty_master && devpts; o_tty = tty->link; #ifdef TTY_PARANOIA_CHECK @@ -2185,6 +2194,7 @@ static int ptmx_open(struct inode * inode, struct file * filp) return 0; out1: release_dev(filp); + return retval; out: down(&allocated_ptys_lock); idr_remove(&allocated_ptys, index); diff --git a/drivers/hwmon/hdaps.c b/drivers/hwmon/hdaps.c index 23a9e1e..1659f6c 100644 --- a/drivers/hwmon/hdaps.c +++ b/drivers/hwmon/hdaps.c @@ -509,12 +509,22 @@ static int hdaps_dmi_match_invert(struct dmi_system_id *id) } \ } +#define HDAPS_DMI_MATCH_LENOVO(model) { \ + .ident = "Lenovo " model, \ + .callback = hdaps_dmi_match_invert, \ + .matches = { \ + DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"), \ + DMI_MATCH(DMI_PRODUCT_VERSION, model) \ + } \ +} + static int __init hdaps_init(void) { int ret; /* Note that DMI_MATCH(...,"ThinkPad T42") will match "ThinkPad T42p" */ struct dmi_system_id hdaps_whitelist[] = { + HDAPS_DMI_MATCH_NORMAL("ThinkPad H"), HDAPS_DMI_MATCH_INVERT("ThinkPad R50p"), HDAPS_DMI_MATCH_NORMAL("ThinkPad R50"), HDAPS_DMI_MATCH_NORMAL("ThinkPad R51"), @@ -524,15 +534,17 @@ static int __init hdaps_init(void) HDAPS_DMI_MATCH_INVERT("ThinkPad T42p"), HDAPS_DMI_MATCH_NORMAL("ThinkPad T42"), HDAPS_DMI_MATCH_NORMAL("ThinkPad T43"), + HDAPS_DMI_MATCH_LENOVO("ThinkPad T60p"), HDAPS_DMI_MATCH_NORMAL("ThinkPad X40"), HDAPS_DMI_MATCH_NORMAL("ThinkPad X41 Tablet"), HDAPS_DMI_MATCH_NORMAL("ThinkPad X41"), + HDAPS_DMI_MATCH_LENOVO("ThinkPad X60"), { .ident = NULL } }; if (!dmi_check_system(hdaps_whitelist)) { printk(KERN_WARNING "hdaps: supported laptop not found!\n"); - ret = -ENXIO; + ret = -ENODEV; goto out; } diff --git a/drivers/isdn/gigaset/Kconfig b/drivers/isdn/gigaset/Kconfig index 53c4fb6..5b203fe 100644 --- a/drivers/isdn/gigaset/Kconfig +++ b/drivers/isdn/gigaset/Kconfig @@ -3,8 +3,8 @@ menu "Siemens Gigaset" config ISDN_DRV_GIGASET tristate "Siemens Gigaset support (isdn)" - depends on ISDN_I4L && m -# depends on ISDN_I4L && MODULES + depends on ISDN_I4L + select CRC_CCITT help Say m here if you have a Gigaset or Sinus isdn device. diff --git a/drivers/isdn/gigaset/asyncdata.c b/drivers/isdn/gigaset/asyncdata.c index 171f8b7..ce3cd77 100644 --- a/drivers/isdn/gigaset/asyncdata.c +++ b/drivers/isdn/gigaset/asyncdata.c @@ -3,7 +3,7 @@ * * Copyright (c) 2005 by Tilman Schmidt <tilman@imap.cc>, * Hansjoerg Lipp <hjlipp@web.de>, - * Stefan Eilers <Eilers.Stefan@epost.de>. + * Stefan Eilers. * * ===================================================================== * This program is free software; you can redistribute it and/or @@ -11,10 +11,6 @@ * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * ===================================================================== - * ToDo: ... - * ===================================================================== - * Version: $Id: asyncdata.c,v 1.2.2.7 2005/11/13 23:05:18 hjlipp Exp $ - * ===================================================================== */ #include "gigaset.h" @@ -45,7 +41,7 @@ static inline int muststuff(unsigned char c) * number of processed bytes */ static inline int cmd_loop(unsigned char c, unsigned char *src, int numbytes, - struct inbuf_t *inbuf) + struct inbuf_t *inbuf) { struct cardstate *cs = inbuf->cs; unsigned cbytes = cs->cbytes; @@ -55,10 +51,11 @@ static inline int cmd_loop(unsigned char c, unsigned char *src, int numbytes, for (;;) { cs->respdata[cbytes] = c; if (c == 10 || c == 13) { - dbg(DEBUG_TRANSCMD, "%s: End of Command (%d Bytes)", - __func__, cbytes); + gig_dbg(DEBUG_TRANSCMD, "%s: End of Command (%d Bytes)", + __func__, cbytes); cs->cbytes = cbytes; - gigaset_handle_modem_response(cs); /* can change cs->dle */ + gigaset_handle_modem_response(cs); /* can change + cs->dle */ cbytes = 0; if (cs->dle && @@ -71,7 +68,7 @@ static inline int cmd_loop(unsigned char c, unsigned char *src, int numbytes, if (cbytes < MAX_RESP_SIZE - 1) cbytes++; else - warn("response too large"); + dev_warn(cs->dev, "response too large\n"); } if (!numbytes) @@ -96,11 +93,12 @@ static inline int cmd_loop(unsigned char c, unsigned char *src, int numbytes, * number of processed bytes */ static inline int lock_loop(unsigned char *src, int numbytes, - struct inbuf_t *inbuf) + struct inbuf_t *inbuf) { struct cardstate *cs = inbuf->cs; - gigaset_dbg_buffer(DEBUG_LOCKCMD, "received response", numbytes, src, 0); + gigaset_dbg_buffer(DEBUG_LOCKCMD, "received response", + numbytes, src); gigaset_if_receive(cs, src, numbytes); return numbytes; @@ -115,24 +113,18 @@ static inline int lock_loop(unsigned char *src, int numbytes, * numbytes (all bytes processed) on error --FIXME */ static inline int hdlc_loop(unsigned char c, unsigned char *src, int numbytes, - struct inbuf_t *inbuf) + struct inbuf_t *inbuf) { struct cardstate *cs = inbuf->cs; struct bc_state *bcs = inbuf->bcs; - int inputstate; - __u16 fcs; - struct sk_buff *skb; + int inputstate = bcs->inputstate; + __u16 fcs = bcs->fcs; + struct sk_buff *skb = bcs->skb; unsigned char error; struct sk_buff *compskb; int startbytes = numbytes; int l; - IFNULLRETVAL(bcs, numbytes); - inputstate = bcs->inputstate; - fcs = bcs->fcs; - skb = bcs->skb; - IFNULLRETVAL(skb, numbytes); - if (unlikely(inputstate & INS_byte_stuff)) { inputstate &= ~INS_byte_stuff; goto byte_stuff; @@ -156,39 +148,37 @@ byte_stuff: c ^= PPP_TRANS; #ifdef CONFIG_GIGASET_DEBUG if (unlikely(!muststuff(c))) - dbg(DEBUG_HDLC, - "byte stuffed: 0x%02x", c); + gig_dbg(DEBUG_HDLC, "byte stuffed: 0x%02x", c); #endif } else if (unlikely(c == PPP_FLAG)) { if (unlikely(inputstate & INS_skip_frame)) { if (!(inputstate & INS_have_data)) { /* 7E 7E */ - //dbg(DEBUG_HDLC, "(7e)7e------------------------"); #ifdef CONFIG_GIGASET_DEBUG ++bcs->emptycount; #endif } else - dbg(DEBUG_HDLC, + gig_dbg(DEBUG_HDLC, "7e----------------------------"); /* end of frame */ error = 1; gigaset_rcv_error(NULL, cs, bcs); } else if (!(inputstate & INS_have_data)) { /* 7E 7E */ - //dbg(DEBUG_HDLC, "(7e)7e------------------------"); #ifdef CONFIG_GIGASET_DEBUG ++bcs->emptycount; #endif break; } else { - dbg(DEBUG_HDLC, - "7e----------------------------"); + gig_dbg(DEBUG_HDLC, + "7e----------------------------"); /* end of frame */ error = 0; if (unlikely(fcs != PPP_GOODFCS)) { - err("Packet checksum at %lu failed, " - "packet is corrupted (%u bytes)!", + dev_err(cs->dev, + "Packet checksum at %lu failed, " + "packet is corrupted (%u bytes)!\n", bcs->rcvbytes, skb->len); compskb = NULL; gigaset_rcv_error(compskb, cs, bcs); @@ -202,9 +192,11 @@ byte_stuff: skb = NULL; inputstate |= INS_skip_frame; if (l == 1) { - err("invalid packet size (1)!"); + dev_err(cs->dev, + "invalid packet size (1)!\n"); error = 1; - gigaset_rcv_error(NULL, cs, bcs); + gigaset_rcv_error(NULL, + cs, bcs); } } if (likely(!(error || @@ -227,7 +219,8 @@ byte_stuff: } else if (likely((skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL)) { skb_reserve(skb, HW_HDR_LEN); } else { - warn("could not allocate new skb"); + dev_warn(cs->dev, + "could not allocate new skb\n"); inputstate |= INS_skip_frame; } @@ -235,7 +228,7 @@ byte_stuff: #ifdef CONFIG_GIGASET_DEBUG } else if (unlikely(muststuff(c))) { /* Should not happen. Possible after ZDLE=1<CR><LF>. */ - dbg(DEBUG_HDLC, "not byte stuffed: 0x%02x", c); + gig_dbg(DEBUG_HDLC, "not byte stuffed: 0x%02x", c); #endif } @@ -243,8 +236,8 @@ byte_stuff: #ifdef CONFIG_GIGASET_DEBUG if (unlikely(!(inputstate & INS_have_data))) { - dbg(DEBUG_HDLC, - "7e (%d x) ================", bcs->emptycount); + gig_dbg(DEBUG_HDLC, "7e (%d x) ================", + bcs->emptycount); bcs->emptycount = 0; } #endif @@ -253,14 +246,13 @@ byte_stuff: if (likely(!(inputstate & INS_skip_frame))) { if (unlikely(skb->len == SBUFSIZE)) { - warn("received packet too long"); + dev_warn(cs->dev, "received packet too long\n"); dev_kfree_skb_any(skb); skb = NULL; inputstate |= INS_skip_frame; break; } - *gigaset_skb_put_quick(skb, 1) = c; - /* *__skb_put (skb, 1) = c; */ + *__skb_put(skb, 1) = c; fcs = crc_ccitt_byte(fcs, c); } @@ -289,19 +281,14 @@ byte_stuff: * numbytes (all bytes processed) on error --FIXME */ static inline int iraw_loop(unsigned char c, unsigned char *src, int numbytes, - struct inbuf_t *inbuf) + struct inbuf_t *inbuf) { struct cardstate *cs = inbuf->cs; struct bc_state *bcs = inbuf->bcs; - int inputstate; - struct sk_buff *skb; + int inputstate = bcs->inputstate; + struct sk_buff *skb = bcs->skb; int startbytes = numbytes; - IFNULLRETVAL(bcs, numbytes); - inputstate = bcs->inputstate; - skb = bcs->skb; - IFNULLRETVAL(skb, numbytes); - for (;;) { /* add character */ inputstate |= INS_have_data; @@ -309,13 +296,13 @@ static inline int iraw_loop(unsigned char c, unsigned char *src, int numbytes, if (likely(!(inputstate & INS_skip_frame))) { if (unlikely(skb->len == SBUFSIZE)) { //FIXME just pass skb up and allocate a new one - warn("received packet too long"); + dev_warn(cs->dev, "received packet too long\n"); dev_kfree_skb_any(skb); skb = NULL; inputstate |= INS_skip_frame; break; } - *gigaset_skb_put_quick(skb, 1) = gigaset_invtab[c]; + *__skb_put(skb, 1) = gigaset_invtab[c]; } if (unlikely(!numbytes)) @@ -343,7 +330,7 @@ static inline int iraw_loop(unsigned char c, unsigned char *src, int numbytes, != NULL)) { skb_reserve(skb, HW_HDR_LEN); } else { - warn("could not allocate new skb"); + dev_warn(cs->dev, "could not allocate new skb\n"); inputstate |= INS_skip_frame; } } @@ -364,13 +351,13 @@ void gigaset_m10x_input(struct inbuf_t *inbuf) head = atomic_read(&inbuf->head); tail = atomic_read(&inbuf->tail); - dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail); + gig_dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail); if (head != tail) { cs = inbuf->cs; src = inbuf->data + head; numbytes = (head > tail ? RBUFSIZE : tail) - head; - dbg(DEBUG_INTR, "processing %u bytes", numbytes); + gig_dbg(DEBUG_INTR, "processing %u bytes", numbytes); while (numbytes) { if (atomic_read(&cs->mstate) == MS_LOCKED) { @@ -392,8 +379,7 @@ void gigaset_m10x_input(struct inbuf_t *inbuf) if (!(inbuf->inputstate & INS_DLE_char)) { - /* FIXME Einfach je nach Modus Funktionszeiger in cs setzen [hier+hdlc_loop]? */ - /* FIXME Spart folgendes "if" und ermoeglicht andere Protokolle */ + /* FIXME use function pointers? */ if (inbuf->inputstate & INS_command) procbytes = cmd_loop(c, src, numbytes, inbuf); else if (inbuf->bcs->proto2 == ISDN_PROTO_L2_HDLC) @@ -403,13 +389,14 @@ void gigaset_m10x_input(struct inbuf_t *inbuf) src += procbytes; numbytes -= procbytes; - } else { /* DLE-char */ + } else { /* DLE char */ inbuf->inputstate &= ~INS_DLE_char; switch (c) { case 'X': /*begin of command*/ #ifdef CONFIG_GIGASET_DEBUG if (inbuf->inputstate & INS_command) - err("received <DLE> 'X' in command mode"); + dev_err(cs->dev, + "received <DLE> 'X' in command mode\n"); #endif inbuf->inputstate |= INS_command | INS_DLE_command; @@ -417,7 +404,8 @@ void gigaset_m10x_input(struct inbuf_t *inbuf) case '.': /*end of command*/ #ifdef CONFIG_GIGASET_DEBUG if (!(inbuf->inputstate & INS_command)) - err("received <DLE> '.' in hdlc mode"); + dev_err(cs->dev, + "received <DLE> '.' in hdlc mode\n"); #endif inbuf->inputstate &= cs->dle ? ~(INS_DLE_command|INS_command) @@ -425,7 +413,9 @@ void gigaset_m10x_input(struct inbuf_t *inbuf) break; //case DLE_FLAG: /*DLE_FLAG in data stream*/ /* schon oben behandelt! */ default: - err("received 0x10 0x%02x!", (int) c); + dev_err(cs->dev, + "received 0x10 0x%02x!\n", + (int) c); /* FIXME: reset driver?? */ } } @@ -444,7 +434,7 @@ nextbyte: } } - dbg(DEBUG_INTR, "setting head to %u", head); + gig_dbg(DEBUG_INTR, "setting head to %u", head); atomic_set(&inbuf->head, head); } } @@ -479,14 +469,13 @@ static struct sk_buff *HDLC_Encode(struct sk_buff *skb, int head, int tail) stuf_cnt++; fcs = crc_ccitt_byte(fcs, *cp++); } - fcs ^= 0xffff; /* complement */ + fcs ^= 0xffff; /* complement */ /* size of new buffer: original size + number of stuffing bytes * + 2 bytes FCS + 2 stuffing bytes for FCS (if needed) + 2 flag bytes */ hdlc_skb = dev_alloc_skb(skb->len + stuf_cnt + 6 + tail + head); if (!hdlc_skb) { - err("unable to allocate memory for HDLC encoding!"); dev_kfree_skb(skb); return NULL; } @@ -508,7 +497,7 @@ static struct sk_buff *HDLC_Encode(struct sk_buff *skb, int head, int tail) } /* Finally add FCS (byte stuffed) and flag sequence */ - c = (fcs & 0x00ff); /* least significant byte first */ + c = (fcs & 0x00ff); /* least significant byte first */ if (muststuff(c)) { *(skb_put(hdlc_skb, 1)) = PPP_ESCAPE; c ^= PPP_TRANS; @@ -546,7 +535,6 @@ static struct sk_buff *iraw_encode(struct sk_buff *skb, int head, int tail) /* worst case: every byte must be stuffed */ iraw_skb = dev_alloc_skb(2*skb->len + tail + head); if (!iraw_skb) { - err("unable to allocate memory for HDLC encoding!"); dev_kfree_skb(skb); return NULL; } @@ -577,21 +565,23 @@ static struct sk_buff *iraw_encode(struct sk_buff *skb, int head, int tail) */ int gigaset_m10x_send_skb(struct bc_state *bcs, struct sk_buff *skb) { - unsigned len; - - IFNULLRETVAL(bcs, -EFAULT); - IFNULLRETVAL(skb, -EFAULT); - len = skb->len; + unsigned len = skb->len; + unsigned long flags; if (bcs->proto2 == ISDN_PROTO_L2_HDLC) skb = HDLC_Encode(skb, HW_HDR_LEN, 0); else skb = iraw_encode(skb, HW_HDR_LEN, 0); - if (!skb) + if (!skb) { + err("unable to allocate memory for encoding!\n"); return -ENOMEM; + } skb_queue_tail(&bcs->squeue, skb); - tasklet_schedule(&bcs->cs->write_tasklet); + spin_lock_irqsave(&bcs->cs->lock, flags); + if (bcs->cs->connected) + tasklet_schedule(&bcs->cs->write_tasklet); + spin_unlock_irqrestore(&bcs->cs->lock, flags); return len; /* ok so far */ } diff --git a/drivers/isdn/gigaset/bas-gigaset.c b/drivers/isdn/gigaset/bas-gigaset.c index 31f0f07..f86ed6a 100644 --- a/drivers/isdn/gigaset/bas-gigaset.c +++ b/drivers/isdn/gigaset/bas-gigaset.c @@ -3,7 +3,7 @@ * * Copyright (c) 2001 by Hansjoerg Lipp <hjlipp@web.de>, * Tilman Schmidt <tilman@imap.cc>, - * Stefan Eilers <Eilers.Stefan@epost.de>. + * Stefan Eilers. * * Based on usb-gigaset.c. * @@ -13,10 +13,6 @@ * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * ===================================================================== - * ToDo: ... - * ===================================================================== - * Version: $Id: bas-gigaset.c,v 1.52.4.19 2006/02/04 18:28:16 hjlipp Exp $ - * ===================================================================== */ #include "gigaset.h" @@ -30,7 +26,7 @@ #include <linux/moduleparam.h> /* Version Information */ -#define DRIVER_AUTHOR "Tilman Schmidt <tilman@imap.cc>, Hansjoerg Lipp <hjlipp@web.de>, Stefan Eilers <Eilers.Stefan@epost.de>" +#define DRIVER_AUTHOR "Tilman Schmidt <tilman@imap.cc>, Hansjoerg Lipp <hjlipp@web.de>, Stefan Eilers" #define DRIVER_DESC "USB Driver for Gigaset 307x" @@ -70,9 +66,6 @@ static struct usb_device_id gigaset_table [] = { MODULE_DEVICE_TABLE(usb, gigaset_table); -/* Get a minor range for your devices from the usb maintainer */ -#define USB_SKEL_MINOR_BASE 200 - /*======================= local function prototypes =============================*/ /* This function is called if a new device is connected to the USB port. It @@ -88,25 +81,25 @@ static void gigaset_disconnect(struct usb_interface *interface); /*==============================================================================*/ struct bas_cardstate { - struct usb_device *udev; /* USB device pointer */ - struct usb_interface *interface; /* interface for this device */ + struct usb_device *udev; /* USB device pointer */ + struct usb_interface *interface; /* interface for this device */ unsigned char minor; /* starting minor number */ - struct urb *urb_ctrl; /* control pipe default URB */ + struct urb *urb_ctrl; /* control pipe default URB */ struct usb_ctrlrequest dr_ctrl; struct timer_list timer_ctrl; /* control request timeout */ struct timer_list timer_atrdy; /* AT command ready timeout */ - struct urb *urb_cmd_out; /* for sending AT commands */ + struct urb *urb_cmd_out; /* for sending AT commands */ struct usb_ctrlrequest dr_cmd_out; int retry_cmd_out; - struct urb *urb_cmd_in; /* for receiving AT replies */ + struct urb *urb_cmd_in; /* for receiving AT replies */ struct usb_ctrlrequest dr_cmd_in; struct timer_list timer_cmd_in; /* receive request timeout */ - unsigned char *rcvbuf; /* AT reply receive buffer */ + unsigned char *rcvbuf; /* AT reply receive buffer */ - struct urb *urb_int_in; /* URB for interrupt pipe */ + struct urb *urb_int_in; /* URB for interrupt pipe */ unsigned char int_in_buf[3]; spinlock_t lock; /* locks all following */ @@ -208,53 +201,54 @@ static inline char *usb_pipetype_str(int pipe) * write content of URB to syslog for debugging */ static inline void dump_urb(enum debuglevel level, const char *tag, - struct urb *urb) + struct urb *urb) { #ifdef CONFIG_GIGASET_DEBUG int i; - IFNULLRET(tag); - dbg(level, "%s urb(0x%08lx)->{", tag, (unsigned long) urb); + gig_dbg(level, "%s urb(0x%08lx)->{", tag, (unsigned long) urb); if (urb) { - dbg(level, - " dev=0x%08lx, pipe=%s:EP%d/DV%d:%s, " - "status=%d, hcpriv=0x%08lx, transfer_flags=0x%x,", - (unsigned long) urb->dev, - usb_pipetype_str(urb->pipe), - usb_pipeendpoint(urb->pipe), usb_pipedevice(urb->pipe), - usb_pipein(urb->pipe) ? "in" : "out", - urb->status, (unsigned long) urb->hcpriv, - urb->transfer_flags); - dbg(level, - " transfer_buffer=0x%08lx[%d], actual_length=%d, " - "bandwidth=%d, setup_packet=0x%08lx,", - (unsigned long) urb->transfer_buffer, - urb->transfer_buffer_length, urb->actual_length, - urb->bandwidth, (unsigned long) urb->setup_packet); - dbg(level, - " start_frame=%d, number_of_packets=%d, interval=%d, " - "error_count=%d,", - urb->start_frame, urb->number_of_packets, urb->interval, - urb->error_count); - dbg(level, - " context=0x%08lx, complete=0x%08lx, iso_frame_desc[]={", - (unsigned long) urb->context, - (unsigned long) urb->complete); + gig_dbg(level, + " dev=0x%08lx, pipe=%s:EP%d/DV%d:%s, " + "status=%d, hcpriv=0x%08lx, transfer_flags=0x%x,", + (unsigned long) urb->dev, + usb_pipetype_str(urb->pipe), + usb_pipeendpoint(urb->pipe), usb_pipedevice(urb->pipe), + usb_pipein(urb->pipe) ? "in" : "out", + urb->status, (unsigned long) urb->hcpriv, + urb->transfer_flags); + gig_dbg(level, + " transfer_buffer=0x%08lx[%d], actual_length=%d, " + "bandwidth=%d, setup_packet=0x%08lx,", + (unsigned long) urb->transfer_buffer, + urb->transfer_buffer_length, urb->actual_length, + urb->bandwidth, (unsigned long) urb->setup_packet); + gig_dbg(level, + " start_frame=%d, number_of_packets=%d, interval=%d, " + "error_count=%d,", + urb->start_frame, urb->number_of_packets, urb->interval, + urb->error_count); + gig_dbg(level, + " context=0x%08lx, complete=0x%08lx, " + "iso_frame_desc[]={", + (unsigned long) urb->context, + (unsigned long) urb->complete); for (i = 0; i < urb->number_of_packets; i++) { - struct usb_iso_packet_descriptor *pifd = &urb->iso_frame_desc[i]; - dbg(level, - " {offset=%u, length=%u, actual_length=%u, " - "status=%u}", - pifd->offset, pifd->length, pifd->actual_length, - pifd->status); + struct usb_iso_packet_descriptor *pifd + = &urb->iso_frame_desc[i]; + gig_dbg(level, + " {offset=%u, length=%u, actual_length=%u, " + "status=%u}", + pifd->offset, pifd->length, pifd->actual_length, + pifd->status); } } - dbg(level, "}}"); + gig_dbg(level, "}}"); #endif } /* read/set modem control bits etc. (m10x only) */ static int gigaset_set_modem_ctrl(struct cardstate *cs, unsigned old_state, - unsigned new_state) + unsigned new_state) { return -EINVAL; } @@ -280,8 +274,8 @@ static inline void error_hangup(struct bc_state *bcs) { struct cardstate *cs = bcs->cs; - dbg(DEBUG_ANY, - "%s: scheduling HUP for channel %d", __func__, bcs->channel); + gig_dbg(DEBUG_ANY, "%s: scheduling HUP for channel %d", + __func__, bcs->channel); if (!gigaset_add_event(cs, &bcs->at_state, EV_HUP, NULL, 0, NULL)) { //FIXME what should we do? @@ -301,22 +295,19 @@ static inline void error_hangup(struct bc_state *bcs) static inline void error_reset(struct cardstate *cs) { //FIXME try to recover without bothering the user - err("unrecoverable error - please disconnect the Gigaset base to reset"); + dev_err(cs->dev, + "unrecoverable error - please disconnect Gigaset base to reset\n"); } /* check_pending * check for completion of pending control request * parameter: - * urb USB request block of completed request - * urb->context = hardware specific controller state structure + * ucs hardware specific controller state structure */ static void check_pending(struct bas_cardstate *ucs) { unsigned long flags; - IFNULLRET(ucs); - IFNULLRET(cardstate); - spin_lock_irqsave(&ucs->lock, flags); switch (ucs->pending) { case 0: @@ -336,8 +327,6 @@ static void check_pending(struct bas_cardstate *ucs) case HD_CLOSE_ATCHANNEL: if (!(atomic_read(&ucs->basstate) & BS_ATOPEN)) ucs->pending = 0; - //wake_up_interruptible(cs->initwait); - //FIXME need own wait queue? break; case HD_CLOSE_B1CHANNEL: if (!(atomic_read(&ucs->basstate) & BS_B1OPEN)) @@ -354,7 +343,9 @@ static void check_pending(struct bas_cardstate *ucs) * are handled separately and should never end up here */ default: - warn("unknown pending request 0x%02x cleared", ucs->pending); + dev_warn(&ucs->interface->dev, + "unknown pending request 0x%02x cleared\n", + ucs->pending); ucs->pending = 0; } @@ -372,27 +363,23 @@ static void check_pending(struct bas_cardstate *ucs) static void cmd_in_timeout(unsigned long data) { struct cardstate *cs = (struct cardstate *) data; - struct bas_cardstate *ucs; + struct bas_cardstate *ucs = cs->hw.bas; unsigned long flags; - IFNULLRET(cs); - ucs = cs->hw.bas; - IFNULLRET(ucs); - spin_lock_irqsave(&cs->lock, flags); - if (!atomic_read(&cs->connected)) { - dbg(DEBUG_USBREQ, "%s: disconnected", __func__); + if (unlikely(!cs->connected)) { + gig_dbg(DEBUG_USBREQ, "%s: disconnected", __func__); spin_unlock_irqrestore(&cs->lock, flags); return; } if (!ucs->rcvbuf_size) { - dbg(DEBUG_USBREQ, "%s: no receive in progress", __func__); + gig_dbg(DEBUG_USBREQ, "%s: no receive in progress", __func__); spin_unlock_irqrestore(&cs->lock, flags); return; } spin_unlock_irqrestore(&cs->lock, flags); - err("timeout reading AT response"); + dev_err(cs->dev, "timeout reading AT response\n"); error_reset(cs); //FIXME retry? } @@ -412,18 +399,15 @@ static void read_ctrl_callback(struct urb *urb, struct pt_regs *regs); */ static int atread_submit(struct cardstate *cs, int timeout) { - struct bas_cardstate *ucs; + struct bas_cardstate *ucs = cs->hw.bas; int ret; - IFNULLRETVAL(cs, -EINVAL); - ucs = cs->hw.bas; - IFNULLRETVAL(ucs, -EINVAL); - IFNULLRETVAL(ucs->urb_cmd_in, -EINVAL); - - dbg(DEBUG_USBREQ, "-------> HD_READ_ATMESSAGE (%d)", ucs->rcvbuf_size); + gig_dbg(DEBUG_USBREQ, "-------> HD_READ_ATMESSAGE (%d)", + ucs->rcvbuf_size); if (ucs->urb_cmd_in->status == -EINPROGRESS) { - err("could not submit HD_READ_ATMESSAGE: URB busy"); + dev_err(cs->dev, + "could not submit HD_READ_ATMESSAGE: URB busy\n"); return -EBUSY; } @@ -433,19 +417,19 @@ static int atread_submit(struct cardstate *cs, int timeout) ucs->dr_cmd_in.wIndex = 0; ucs->dr_cmd_in.wLength = cpu_to_le16(ucs->rcvbuf_size); usb_fill_control_urb(ucs->urb_cmd_in, ucs->udev, - usb_rcvctrlpipe(ucs->udev, 0), - (unsigned char*) & ucs->dr_cmd_in, - ucs->rcvbuf, ucs->rcvbuf_size, - read_ctrl_callback, cs->inbuf); + usb_rcvctrlpipe(ucs->udev, 0), + (unsigned char*) & ucs->dr_cmd_in, + ucs->rcvbuf, ucs->rcvbuf_size, + read_ctrl_callback, cs->inbuf); if ((ret = usb_submit_urb(ucs->urb_cmd_in, SLAB_ATOMIC)) != 0) { - err("could not submit HD_READ_ATMESSAGE: %s", - get_usb_statmsg(ret)); + dev_err(cs->dev, "could not submit HD_READ_ATMESSAGE: %s\n", + get_usb_statmsg(ret)); return ret; } if (timeout > 0) { - dbg(DEBUG_USBREQ, "setting timeout of %d/10 secs", timeout); + gig_dbg(DEBUG_USBREQ, "setting timeout of %d/10 secs", timeout); ucs->timer_cmd_in.expires = jiffies + timeout * HZ / 10; ucs->timer_cmd_in.data = (unsigned long) cs; ucs->timer_cmd_in.function = cmd_in_timeout; @@ -483,25 +467,14 @@ inline static void update_basstate(struct bas_cardstate *ucs, */ static void read_int_callback(struct urb *urb, struct pt_regs *regs) { - struct cardstate *cs; - struct bas_cardstate *ucs; + struct cardstate *cs = urb->context; + struct bas_cardstate *ucs = cs->hw.bas; struct bc_state *bcs; unsigned long flags; int status; unsigned l; int channel; - IFNULLRET(urb); - cs = (struct cardstate *) urb->context; - IFNULLRET(cs); - ucs = cs->hw.bas; - IFNULLRET(ucs); - - if (unlikely(!atomic_read(&cs->connected))) { - warn("%s: disconnected", __func__); - return; - } - switch (urb->status) { case 0: /* success */ break; @@ -509,11 +482,12 @@ static void read_int_callback(struct urb *urb, struct pt_regs *regs) case -ECONNRESET: /* canceled (async) */ case -EINPROGRESS: /* pending */ /* ignore silently */ - dbg(DEBUG_USBREQ, - "%s: %s", __func__, get_usb_statmsg(urb->status)); + gig_dbg(DEBUG_USBREQ, "%s: %s", + __func__, get_usb_statmsg(urb->status)); return; default: /* severe trouble */ - warn("interrupt read: %s", get_usb_statmsg(urb->status)); + dev_warn(cs->dev, "interrupt read: %s\n", + get_usb_statmsg(urb->status)); //FIXME corrective action? resubmission always ok? goto resubmit; } @@ -521,10 +495,9 @@ static void read_int_callback(struct urb *urb, struct pt_regs *regs) l = (unsigned) ucs->int_in_buf[1] + (((unsigned) ucs->int_in_buf[2]) << 8); - dbg(DEBUG_USBREQ, - "<-------%d: 0x%02x (%u [0x%02x 0x%02x])", urb->actual_length, - (int)ucs->int_in_buf[0], l, - (int)ucs->int_in_buf[1], (int)ucs->int_in_buf[2]); + gig_dbg(DEBUG_USBREQ, "<-------%d: 0x%02x (%u [0x%02x 0x%02x])", + urb->actual_length, (int)ucs->int_in_buf[0], l, + (int)ucs->int_in_buf[1], (int)ucs->int_in_buf[2]); channel = 0; @@ -570,28 +543,30 @@ static void read_int_callback(struct urb *urb, struct pt_regs *regs) case HD_B1_FLOW_CONTROL: bcs = cs->bcs + channel; atomic_add((l - BAS_NORMFRAME) * BAS_CORRFRAMES, - &bcs->hw.bas->corrbytes); - dbg(DEBUG_ISO, - "Flow control (channel %d, sub %d): 0x%02x => %d", - channel, bcs->hw.bas->numsub, l, - atomic_read(&bcs->hw.bas->corrbytes)); + &bcs->hw.bas->corrbytes); + gig_dbg(DEBUG_ISO, + "Flow control (channel %d, sub %d): 0x%02x => %d", + channel, bcs->hw.bas->numsub, l, + atomic_read(&bcs->hw.bas->corrbytes)); break; case HD_RECEIVEATDATA_ACK: /* AT response ready to be received */ if (!l) { - warn("HD_RECEIVEATDATA_ACK with length 0 ignored"); + dev_warn(cs->dev, + "HD_RECEIVEATDATA_ACK with length 0 ignored\n"); break; } spin_lock_irqsave(&cs->lock, flags); if (ucs->rcvbuf_size) { spin_unlock_irqrestore(&cs->lock, flags); - err("receive AT data overrun, %d bytes lost", l); + dev_err(cs->dev, + "receive AT data overrun, %d bytes lost\n", l); error_reset(cs); //FIXME reschedule break; } if ((ucs->rcvbuf = kmalloc(l, GFP_ATOMIC)) == NULL) { spin_unlock_irqrestore(&cs->lock, flags); - err("%s: out of memory, %d bytes lost", __func__, l); + dev_err(cs->dev, "out of memory, %d bytes lost\n", l); error_reset(cs); //FIXME reschedule break; } @@ -607,25 +582,28 @@ static void read_int_callback(struct urb *urb, struct pt_regs *regs) break; case HD_RESET_INTERRUPT_PIPE_ACK: - dbg(DEBUG_USBREQ, "HD_RESET_INTERRUPT_PIPE_ACK"); + gig_dbg(DEBUG_USBREQ, "HD_RESET_INTERRUPT_PIPE_ACK"); break; case HD_SUSPEND_END: - dbg(DEBUG_USBREQ, "HD_SUSPEND_END"); + gig_dbg(DEBUG_USBREQ, "HD_SUSPEND_END"); break; default: - warn("unknown Gigaset signal 0x%02x (%u) ignored", - (int) ucs->int_in_buf[0], l); + dev_warn(cs->dev, + "unknown Gigaset signal 0x%02x (%u) ignored\n", + (int) ucs->int_in_buf[0], l); } check_pending(ucs); resubmit: - status = usb_submit_urb(urb, SLAB_ATOMIC); + spin_lock_irqsave(&cs->lock, flags); + status = cs->connected ? usb_submit_urb(urb, SLAB_ATOMIC) : -ENODEV; + spin_unlock_irqrestore(&cs->lock, flags); if (unlikely(status)) { - err("could not resubmit interrupt URB: %s", - get_usb_statmsg(status)); + dev_err(cs->dev, "could not resubmit interrupt URB: %s\n", + get_usb_statmsg(status)); error_reset(cs); } } @@ -639,30 +617,22 @@ resubmit: */ static void read_ctrl_callback(struct urb *urb, struct pt_regs *regs) { - struct cardstate *cs; - struct bas_cardstate *ucs; + struct inbuf_t *inbuf = urb->context; + struct cardstate *cs = inbuf->cs; + struct bas_cardstate *ucs = cs->hw.bas; + int have_data = 0; unsigned numbytes; unsigned long flags; - struct inbuf_t *inbuf; - int have_data = 0; - - IFNULLRET(urb); - inbuf = (struct inbuf_t *) urb->context; - IFNULLRET(inbuf); - cs = inbuf->cs; - IFNULLRET(cs); - ucs = cs->hw.bas; - IFNULLRET(ucs); spin_lock_irqsave(&cs->lock, flags); - if (!atomic_read(&cs->connected)) { + if (unlikely(!cs->connected)) { warn("%s: disconnected", __func__); spin_unlock_irqrestore(&cs->lock, flags); return; } if (!ucs->rcvbuf_size) { - warn("%s: no receive in progress", __func__); + dev_warn(cs->dev, "%s: no receive in progress\n", __func__); spin_unlock_irqrestore(&cs->lock, flags); return; } @@ -673,12 +643,14 @@ static void read_ctrl_callback(struct urb *urb, struct pt_regs *regs) case 0: /* normal completion */ numbytes = urb->actual_length; if (unlikely(numbytes == 0)) { - warn("control read: empty block received"); + dev_warn(cs->dev, + "control read: empty block received\n"); goto retry; } if (unlikely(numbytes != ucs->rcvbuf_size)) { - warn("control read: received %d chars, expected %d", - numbytes, ucs->rcvbuf_size); + dev_warn(cs->dev, + "control read: received %d chars, expected %d\n", + numbytes, ucs->rcvbuf_size); if (numbytes > ucs->rcvbuf_size) numbytes = ucs->rcvbuf_size; } @@ -698,23 +670,26 @@ static void read_ctrl_callback(struct urb *urb, struct pt_regs *regs) case -ECONNRESET: /* canceled (async) */ case -EINPROGRESS: /* pending */ /* no action necessary */ - dbg(DEBUG_USBREQ, - "%s: %s", __func__, get_usb_statmsg(urb->status)); + gig_dbg(DEBUG_USBREQ, "%s: %s", + __func__, get_usb_statmsg(urb->status)); break; default: /* severe trouble */ - warn("control read: %s", get_usb_statmsg(urb->status)); + dev_warn(cs->dev, "control read: %s\n", + get_usb_statmsg(urb->status)); retry: if (ucs->retry_cmd_in++ < BAS_RETRY) { - notice("control read: retry %d", ucs->retry_cmd_in); + dev_notice(cs->dev, "control read: retry %d\n", + ucs->retry_cmd_in); if (atread_submit(cs, BAS_TIMEOUT) >= 0) { /* resubmitted - bypass regular exit block */ spin_unlock_irqrestore(&cs->lock, flags); return; } } else { - err("control read: giving up after %d tries", - ucs->retry_cmd_in); + dev_err(cs->dev, + "control read: giving up after %d tries\n", + ucs->retry_cmd_in); } error_reset(cs); } @@ -724,7 +699,7 @@ static void read_ctrl_callback(struct urb *urb, struct pt_regs *regs) ucs->rcvbuf_size = 0; spin_unlock_irqrestore(&cs->lock, flags); if (have_data) { - dbg(DEBUG_INTR, "%s-->BH", __func__); + gig_dbg(DEBUG_INTR, "%s-->BH", __func__); gigaset_schedule_event(cs); } } @@ -743,21 +718,16 @@ static void read_iso_callback(struct urb *urb, struct pt_regs *regs) unsigned long flags; int i, rc; - IFNULLRET(urb); - IFNULLRET(urb->context); - IFNULLRET(cardstate); - /* status codes not worth bothering the tasklet with */ if (unlikely(urb->status == -ENOENT || urb->status == -ECONNRESET || - urb->status == -EINPROGRESS)) { - dbg(DEBUG_ISO, - "%s: %s", __func__, get_usb_statmsg(urb->status)); + urb->status == -EINPROGRESS)) { + gig_dbg(DEBUG_ISO, "%s: %s", + __func__, get_usb_statmsg(urb->status)); return; } - bcs = (struct bc_state *) urb->context; + bcs = urb->context; ubc = bcs->hw.bas; - IFNULLRET(ubc); spin_lock_irqsave(&ubc->isoinlock, flags); if (likely(ubc->isoindone == NULL)) { @@ -777,14 +747,17 @@ static void read_iso_callback(struct urb *urb, struct pt_regs *regs) urb->iso_frame_desc[i].actual_length = 0; } if (likely(atomic_read(&ubc->running))) { - urb->dev = bcs->cs->hw.bas->udev; /* clobbered by USB subsystem */ + /* urb->dev is clobbered by USB subsystem */ + urb->dev = bcs->cs->hw.bas->udev; urb->transfer_flags = URB_ISO_ASAP; urb->number_of_packets = BAS_NUMFRAMES; - dbg(DEBUG_ISO, "%s: isoc read overrun/resubmit", __func__); + gig_dbg(DEBUG_ISO, "%s: isoc read overrun/resubmit", + __func__); rc = usb_submit_urb(urb, SLAB_ATOMIC); if (unlikely(rc != 0)) { - err("could not resubmit isochronous read URB: %s", - get_usb_statmsg(rc)); + dev_err(bcs->cs->dev, + "could not resubmit isochronous read " + "URB: %s\n", get_usb_statmsg(rc)); dump_urb(DEBUG_ISO, "isoc read", urb); error_hangup(bcs); } @@ -806,23 +779,17 @@ static void write_iso_callback(struct urb *urb, struct pt_regs *regs) struct bas_bc_state *ubc; unsigned long flags; - IFNULLRET(urb); - IFNULLRET(urb->context); - IFNULLRET(cardstate); - /* status codes not worth bothering the tasklet with */ if (unlikely(urb->status == -ENOENT || urb->status == -ECONNRESET || - urb->status == -EINPROGRESS)) { - dbg(DEBUG_ISO, - "%s: %s", __func__, get_usb_statmsg(urb->status)); + urb->status == -EINPROGRESS)) { + gig_dbg(DEBUG_ISO, "%s: %s", + __func__, get_usb_statmsg(urb->status)); return; } /* pass URB context to tasklet */ - ucx = (struct isow_urbctx_t *) urb->context; - IFNULLRET(ucx->bcs); + ucx = urb->context; ubc = ucx->bcs->hw.bas; - IFNULLRET(ubc); spin_lock_irqsave(&ubc->isooutlock, flags); ubc->isooutovfl = ubc->isooutdone; @@ -841,15 +808,11 @@ static void write_iso_callback(struct urb *urb, struct pt_regs *regs) */ static int starturbs(struct bc_state *bcs) { + struct bas_bc_state *ubc = bcs->hw.bas; struct urb *urb; - struct bas_bc_state *ubc; int j, k; int rc; - IFNULLRETVAL(bcs, -EFAULT); - ubc = bcs->hw.bas; - IFNULLRETVAL(ubc, -EFAULT); - /* initialize L2 reception */ if (bcs->proto2 == ISDN_PROTO_L2_HDLC) bcs->inputstate |= INS_flag_hunt; @@ -859,7 +822,7 @@ static int starturbs(struct bc_state *bcs) for (k = 0; k < BAS_INURBS; k++) { urb = ubc->isoinurbs[k]; if (!urb) { - err("isoinurbs[%d]==NULL", k); + dev_err(bcs->cs->dev, "isoinurbs[%d]==NULL\n", k); rc = -EFAULT; goto error; } @@ -882,8 +845,9 @@ static int starturbs(struct bc_state *bcs) dump_urb(DEBUG_ISO, "Initial isoc read", urb); if ((rc = usb_submit_urb(urb, SLAB_ATOMIC)) != 0) { - err("could not submit isochronous read URB %d: %s", - k, get_usb_statmsg(rc)); + dev_err(bcs->cs->dev, + "could not submit isochronous read URB %d: %s\n", + k, get_usb_statmsg(rc)); goto error; } } @@ -895,7 +859,7 @@ static int starturbs(struct bc_state *bcs) for (k = 0; k < BAS_OUTURBS; ++k) { urb = ubc->isoouturbs[k].urb; if (!urb) { - err("isoouturbs[%d].urb==NULL", k); + dev_err(bcs->cs->dev, "isoouturbs[%d].urb==NULL\n", k); rc = -EFAULT; goto error; } @@ -922,8 +886,9 @@ static int starturbs(struct bc_state *bcs) dump_urb(DEBUG_ISO, "Initial isoc write", urb); rc = usb_submit_urb(ubc->isoouturbs[k].urb, SLAB_ATOMIC); if (rc != 0) { - err("could not submit isochronous write URB %d: %s", - k, get_usb_statmsg(rc)); + dev_err(bcs->cs->dev, + "could not submit isochronous write URB %d: %s\n", + k, get_usb_statmsg(rc)); goto error; } } @@ -946,20 +911,20 @@ static void stopurbs(struct bas_bc_state *ubc) { int k, rc; - IFNULLRET(ubc); - atomic_set(&ubc->running, 0); for (k = 0; k < BAS_INURBS; ++k) { rc = usb_unlink_urb(ubc->isoinurbs[k]); - dbg(DEBUG_ISO, "%s: isoc input URB %d unlinked, result = %d", - __func__, k, rc); + gig_dbg(DEBUG_ISO, + "%s: isoc input URB %d unlinked, result = %d", + __func__, k, rc); } for (k = 0; k < BAS_OUTURBS; ++k) { rc = usb_unlink_urb(ubc->isoouturbs[k].urb); - dbg(DEBUG_ISO, "%s: isoc output URB %d unlinked, result = %d", - __func__, k, rc); + gig_dbg(DEBUG_ISO, + "%s: isoc output URB %d unlinked, result = %d", + __func__, k, rc); } } @@ -977,19 +942,14 @@ static void stopurbs(struct bas_bc_state *ubc) */ static int submit_iso_write_urb(struct isow_urbctx_t *ucx) { - struct urb *urb; - struct bas_bc_state *ubc; + struct urb *urb = ucx->urb; + struct bas_bc_state *ubc = ucx->bcs->hw.bas; struct usb_iso_packet_descriptor *ifd; int corrbytes, nframe, rc; + unsigned long flags; - IFNULLRETVAL(ucx, -EFAULT); - urb = ucx->urb; - IFNULLRETVAL(urb, -EFAULT); - IFNULLRETVAL(ucx->bcs, -EFAULT); - ubc = ucx->bcs->hw.bas; - IFNULLRETVAL(ubc, -EFAULT); - - urb->dev = ucx->bcs->cs->hw.bas->udev; /* clobbered by USB subsystem */ + /* urb->dev is clobbered by USB subsystem */ + urb->dev = ucx->bcs->cs->hw.bas->udev; urb->transfer_flags = URB_ISO_ASAP; urb->transfer_buffer = ubc->isooutbuf->data; urb->transfer_buffer_length = sizeof(ubc->isooutbuf->data); @@ -1000,7 +960,8 @@ static int submit_iso_write_urb(struct isow_urbctx_t *ucx) /* compute frame length according to flow control */ ifd->length = BAS_NORMFRAME; if ((corrbytes = atomic_read(&ubc->corrbytes)) != 0) { - dbg(DEBUG_ISO, "%s: corrbytes=%d", __func__, corrbytes); + gig_dbg(DEBUG_ISO, "%s: corrbytes=%d", + __func__, corrbytes); if (corrbytes > BAS_HIGHFRAME - BAS_NORMFRAME) corrbytes = BAS_HIGHFRAME - BAS_NORMFRAME; else if (corrbytes < BAS_LOWFRAME - BAS_NORMFRAME) @@ -1008,18 +969,21 @@ static int submit_iso_write_urb(struct isow_urbctx_t *ucx) ifd->length += corrbytes; atomic_add(-corrbytes, &ubc->corrbytes); } - //dbg(DEBUG_ISO, "%s: frame %d length=%d", __func__, nframe, ifd->length); /* retrieve block of data to send */ - ifd->offset = gigaset_isowbuf_getbytes(ubc->isooutbuf, ifd->length); + ifd->offset = gigaset_isowbuf_getbytes(ubc->isooutbuf, + ifd->length); if (ifd->offset < 0) { if (ifd->offset == -EBUSY) { - dbg(DEBUG_ISO, "%s: buffer busy at frame %d", - __func__, nframe); - /* tasklet will be restarted from gigaset_send_skb() */ + gig_dbg(DEBUG_ISO, + "%s: buffer busy at frame %d", + __func__, nframe); + /* tasklet will be restarted from + gigaset_send_skb() */ } else { - err("%s: buffer error %d at frame %d", - __func__, ifd->offset, nframe); + dev_err(ucx->bcs->cs->dev, + "%s: buffer error %d at frame %d\n", + __func__, ifd->offset, nframe); return ifd->offset; } break; @@ -1029,9 +993,14 @@ static int submit_iso_write_urb(struct isow_urbctx_t *ucx) ifd->actual_length = 0; } if ((urb->number_of_packets = nframe) > 0) { - if ((rc = usb_submit_urb(urb, SLAB_ATOMIC)) != 0) { - err("could not submit isochronous write URB: %s", - get_usb_statmsg(rc)); + spin_lock_irqsave(&ucx->bcs->cs->lock, flags); + rc = ucx->bcs->cs->connected ? usb_submit_urb(urb, SLAB_ATOMIC) : -ENODEV; + spin_unlock_irqrestore(&ucx->bcs->cs->lock, flags); + + if (rc) { + dev_err(ucx->bcs->cs->dev, + "could not submit isochronous write URB: %s\n", + get_usb_statmsg(rc)); dump_urb(DEBUG_ISO, "isoc write", urb); return rc; } @@ -1048,9 +1017,9 @@ static int submit_iso_write_urb(struct isow_urbctx_t *ucx) */ static void write_iso_tasklet(unsigned long data) { - struct bc_state *bcs; - struct bas_bc_state *ubc; - struct cardstate *cs; + struct bc_state *bcs = (struct bc_state *) data; + struct bas_bc_state *ubc = bcs->hw.bas; + struct cardstate *cs = bcs->cs; struct isow_urbctx_t *done, *next, *ovfl; struct urb *urb; struct usb_iso_packet_descriptor *ifd; @@ -1060,22 +1029,10 @@ static void write_iso_tasklet(unsigned long data) struct sk_buff *skb; int len; - bcs = (struct bc_state *) data; - IFNULLRET(bcs); - ubc = bcs->hw.bas; - IFNULLRET(ubc); - cs = bcs->cs; - IFNULLRET(cs); - /* loop while completed URBs arrive in time */ for (;;) { - if (unlikely(!atomic_read(&cs->connected))) { - warn("%s: disconnected", __func__); - return; - } - if (unlikely(!(atomic_read(&ubc->running)))) { - dbg(DEBUG_ISO, "%s: not running", __func__); + gig_dbg(DEBUG_ISO, "%s: not running", __func__); return; } @@ -1087,7 +1044,7 @@ static void write_iso_tasklet(unsigned long data) ubc->isooutovfl = NULL; spin_unlock_irqrestore(&ubc->isooutlock, flags); if (ovfl) { - err("isochronous write buffer underrun - buy a faster machine :-)"); + dev_err(cs->dev, "isochronous write buffer underrun\n"); error_hangup(bcs); break; } @@ -1110,7 +1067,8 @@ static void write_iso_tasklet(unsigned long data) spin_unlock_irqrestore(&ubc->isooutlock, flags); if (next) { /* couldn't put it back */ - err("losing isochronous write URB"); + dev_err(cs->dev, + "losing isochronous write URB\n"); error_hangup(bcs); } } @@ -1123,22 +1081,25 @@ static void write_iso_tasklet(unsigned long data) break; case -EXDEV: /* inspect individual frames */ /* assumptions (for lack of documentation): - * - actual_length bytes of the frame in error are successfully sent + * - actual_length bytes of the frame in error are + * successfully sent * - all following frames are not sent at all */ - dbg(DEBUG_ISO, "%s: URB partially completed", __func__); + gig_dbg(DEBUG_ISO, "%s: URB partially completed", + __func__); offset = done->limit; /* just in case */ for (i = 0; i < BAS_NUMFRAMES; i++) { ifd = &urb->iso_frame_desc[i]; if (ifd->status || ifd->actual_length != ifd->length) { - warn("isochronous write: frame %d: %s, " - "only %d of %d bytes sent", + dev_warn(cs->dev, + "isochronous write: frame %d: %s, " + "only %d of %d bytes sent\n", i, get_usb_statmsg(ifd->status), ifd->actual_length, ifd->length); offset = (ifd->offset + - ifd->actual_length) - % BAS_OUTBUFSIZE; + ifd->actual_length) + % BAS_OUTBUFSIZE; break; } } @@ -1148,25 +1109,26 @@ static void write_iso_tasklet(unsigned long data) ifd = &urb->iso_frame_desc[i]; if (ifd->status != -EINPROGRESS || ifd->actual_length != 0) { - warn("isochronous write: frame %d: %s, " - "%d of %d bytes sent", + dev_warn(cs->dev, + "isochronous write: frame %d: %s, " + "%d of %d bytes sent\n", i, get_usb_statmsg(ifd->status), ifd->actual_length, ifd->length); offset = (ifd->offset + - ifd->actual_length) - % BAS_OUTBUFSIZE; + ifd->actual_length) + % BAS_OUTBUFSIZE; break; } } #endif break; - case -EPIPE: //FIXME is this the code for "underrun"? - err("isochronous write stalled"); + case -EPIPE: //FIXME is this the code for "underrun"? + dev_err(cs->dev, "isochronous write stalled\n"); error_hangup(bcs); break; default: /* severe trouble */ - warn("isochronous write: %s", - get_usb_statmsg(urb->status)); + dev_warn(cs->dev, "isochronous write: %s\n", + get_usb_statmsg(urb->status)); } /* mark the write buffer area covered by this URB as free */ @@ -1194,8 +1156,8 @@ static void write_iso_tasklet(unsigned long data) if (gigaset_isoc_buildframe(bcs, skb->data, len) == -EAGAIN) { /* insufficient buffer space, push back onto queue */ skb_queue_head(&bcs->squeue, skb); - dbg(DEBUG_ISO, "%s: skb requeued, qlen=%d", - __func__, skb_queue_len(&bcs->squeue)); + gig_dbg(DEBUG_ISO, "%s: skb requeued, qlen=%d", + __func__, skb_queue_len(&bcs->squeue)); break; } skb_pull(skb, len); @@ -1215,28 +1177,16 @@ static void write_iso_tasklet(unsigned long data) */ static void read_iso_tasklet(unsigned long data) { - struct bc_state *bcs; - struct bas_bc_state *ubc; - struct cardstate *cs; + struct bc_state *bcs = (struct bc_state *) data; + struct bas_bc_state *ubc = bcs->hw.bas; + struct cardstate *cs = bcs->cs; struct urb *urb; char *rcvbuf; unsigned long flags; int totleft, numbytes, offset, frame, rc; - bcs = (struct bc_state *) data; - IFNULLRET(bcs); - ubc = bcs->hw.bas; - IFNULLRET(ubc); - cs = bcs->cs; - IFNULLRET(cs); - /* loop while more completed URBs arrive in the meantime */ for (;;) { - if (!atomic_read(&cs->connected)) { - warn("%s: disconnected", __func__); - return; - } - /* retrieve URB */ spin_lock_irqsave(&ubc->isoinlock, flags); if (!(urb = ubc->isoindone)) { @@ -1245,38 +1195,45 @@ static void read_iso_tasklet(unsigned long data) } ubc->isoindone = NULL; if (unlikely(ubc->loststatus != -EINPROGRESS)) { - warn("isochronous read overrun, dropped URB with status: %s, %d bytes lost", - get_usb_statmsg(ubc->loststatus), ubc->isoinlost); + dev_warn(cs->dev, + "isochronous read overrun, " + "dropped URB with status: %s, %d bytes lost\n", + get_usb_statmsg(ubc->loststatus), + ubc->isoinlost); ubc->loststatus = -EINPROGRESS; } spin_unlock_irqrestore(&ubc->isoinlock, flags); if (unlikely(!(atomic_read(&ubc->running)))) { - dbg(DEBUG_ISO, "%s: channel not running, dropped URB with status: %s", - __func__, get_usb_statmsg(urb->status)); + gig_dbg(DEBUG_ISO, + "%s: channel not running, " + "dropped URB with status: %s", + __func__, get_usb_statmsg(urb->status)); return; } switch (urb->status) { case 0: /* normal completion */ break; - case -EXDEV: /* inspect individual frames (we do that anyway) */ - dbg(DEBUG_ISO, "%s: URB partially completed", __func__); + case -EXDEV: /* inspect individual frames + (we do that anyway) */ + gig_dbg(DEBUG_ISO, "%s: URB partially completed", + __func__); break; case -ENOENT: case -ECONNRESET: - dbg(DEBUG_ISO, "%s: URB canceled", __func__); + gig_dbg(DEBUG_ISO, "%s: URB canceled", __func__); continue; /* -> skip */ case -EINPROGRESS: /* huh? */ - dbg(DEBUG_ISO, "%s: URB still pending", __func__); + gig_dbg(DEBUG_ISO, "%s: URB still pending", __func__); continue; /* -> skip */ case -EPIPE: - err("isochronous read stalled"); + dev_err(cs->dev, "isochronous read stalled\n"); error_hangup(bcs); continue; /* -> skip */ default: /* severe trouble */ - warn("isochronous read: %s", - get_usb_statmsg(urb->status)); + dev_warn(cs->dev, "isochronous read: %s\n", + get_usb_statmsg(urb->status)); goto error; } @@ -1284,33 +1241,44 @@ static void read_iso_tasklet(unsigned long data) totleft = urb->actual_length; for (frame = 0; totleft > 0 && frame < BAS_NUMFRAMES; frame++) { if (unlikely(urb->iso_frame_desc[frame].status)) { - warn("isochronous read: frame %d: %s", - frame, get_usb_statmsg(urb->iso_frame_desc[frame].status)); + dev_warn(cs->dev, + "isochronous read: frame %d: %s\n", + frame, + get_usb_statmsg( + urb->iso_frame_desc[frame].status)); break; } numbytes = urb->iso_frame_desc[frame].actual_length; if (unlikely(numbytes > BAS_MAXFRAME)) { - warn("isochronous read: frame %d: numbytes (%d) > BAS_MAXFRAME", - frame, numbytes); + dev_warn(cs->dev, + "isochronous read: frame %d: " + "numbytes (%d) > BAS_MAXFRAME\n", + frame, numbytes); break; } if (unlikely(numbytes > totleft)) { - warn("isochronous read: frame %d: numbytes (%d) > totleft (%d)", - frame, numbytes, totleft); + dev_warn(cs->dev, + "isochronous read: frame %d: " + "numbytes (%d) > totleft (%d)\n", + frame, numbytes, totleft); break; } offset = urb->iso_frame_desc[frame].offset; if (unlikely(offset + numbytes > BAS_INBUFSIZE)) { - warn("isochronous read: frame %d: offset (%d) + numbytes (%d) > BAS_INBUFSIZE", - frame, offset, numbytes); + dev_warn(cs->dev, + "isochronous read: frame %d: " + "offset (%d) + numbytes (%d) " + "> BAS_INBUFSIZE\n", + frame, offset, numbytes); break; } gigaset_isoc_receive(rcvbuf + offset, numbytes, bcs); totleft -= numbytes; } if (unlikely(totleft > 0)) - warn("isochronous read: %d data bytes missing", - totleft); + dev_warn(cs->dev, + "isochronous read: %d data bytes missing\n", + totleft); error: /* URB processed, resubmit */ @@ -1318,12 +1286,17 @@ static void read_iso_tasklet(unsigned long data) urb->iso_frame_desc[frame].status = 0; urb->iso_frame_desc[frame].actual_length = 0; } - urb->dev = bcs->cs->hw.bas->udev; /* clobbered by USB subsystem */ + /* urb->dev is clobbered by USB subsystem */ + urb->dev = bcs->cs->hw.bas->udev; urb->transfer_flags = URB_ISO_ASAP; urb->number_of_packets = BAS_NUMFRAMES; - if ((rc = usb_submit_urb(urb, SLAB_ATOMIC)) != 0) { - err("could not resubmit isochronous read URB: %s", - get_usb_statmsg(rc)); + spin_lock_irqsave(&cs->lock, flags); + rc = cs->connected ? usb_submit_urb(urb, SLAB_ATOMIC) : -ENODEV; + spin_unlock_irqrestore(&cs->lock, flags); + if (rc) { + dev_err(cs->dev, + "could not resubmit isochronous read URB: %s\n", + get_usb_statmsg(rc)); dump_urb(DEBUG_ISO, "resubmit iso read", urb); error_hangup(bcs); } @@ -1341,15 +1314,10 @@ static void read_iso_tasklet(unsigned long data) static void req_timeout(unsigned long data) { struct bc_state *bcs = (struct bc_state *) data; - struct bas_cardstate *ucs; + struct bas_cardstate *ucs = bcs->cs->hw.bas; int pending; unsigned long flags; - IFNULLRET(bcs); - IFNULLRET(bcs->cs); - ucs = bcs->cs->hw.bas; - IFNULLRET(ucs); - check_pending(ucs); spin_lock_irqsave(&ucs->lock, flags); @@ -1359,33 +1327,34 @@ static void req_timeout(unsigned long data) switch (pending) { case 0: /* no pending request */ - dbg(DEBUG_USBREQ, "%s: no request pending", __func__); + gig_dbg(DEBUG_USBREQ, "%s: no request pending", __func__); break; case HD_OPEN_ATCHANNEL: - err("timeout opening AT channel"); + dev_err(bcs->cs->dev, "timeout opening AT channel\n"); error_reset(bcs->cs); break; case HD_OPEN_B2CHANNEL: case HD_OPEN_B1CHANNEL: - err("timeout opening channel %d", bcs->channel + 1); + dev_err(bcs->cs->dev, "timeout opening channel %d\n", + bcs->channel + 1); error_hangup(bcs); break; case HD_CLOSE_ATCHANNEL: - err("timeout closing AT channel"); - //wake_up_interruptible(cs->initwait); - //FIXME need own wait queue? + dev_err(bcs->cs->dev, "timeout closing AT channel\n"); break; case HD_CLOSE_B2CHANNEL: case HD_CLOSE_B1CHANNEL: - err("timeout closing channel %d", bcs->channel + 1); + dev_err(bcs->cs->dev, "timeout closing channel %d\n", + bcs->channel + 1); break; default: - warn("request 0x%02x timed out, clearing", pending); + dev_warn(bcs->cs->dev, "request 0x%02x timed out, clearing\n", + pending); } } @@ -1398,18 +1367,14 @@ static void req_timeout(unsigned long data) */ static void write_ctrl_callback(struct urb *urb, struct pt_regs *regs) { - struct bas_cardstate *ucs; + struct bas_cardstate *ucs = urb->context; unsigned long flags; - IFNULLRET(urb); - IFNULLRET(urb->context); - IFNULLRET(cardstate); - - ucs = (struct bas_cardstate *) urb->context; spin_lock_irqsave(&ucs->lock, flags); if (urb->status && ucs->pending) { - err("control request 0x%02x failed: %s", - ucs->pending, get_usb_statmsg(urb->status)); + dev_err(&ucs->interface->dev, + "control request 0x%02x failed: %s\n", + ucs->pending, get_usb_statmsg(urb->status)); del_timer(&ucs->timer_ctrl); ucs->pending = 0; } @@ -1438,28 +1403,25 @@ static void write_ctrl_callback(struct urb *urb, struct pt_regs *regs) */ static int req_submit(struct bc_state *bcs, int req, int val, int timeout) { - struct bas_cardstate *ucs; + struct bas_cardstate *ucs = bcs->cs->hw.bas; int ret; unsigned long flags; - IFNULLRETVAL(bcs, -EINVAL); - IFNULLRETVAL(bcs->cs, -EINVAL); - ucs = bcs->cs->hw.bas; - IFNULLRETVAL(ucs, -EINVAL); - IFNULLRETVAL(ucs->urb_ctrl, -EINVAL); - - dbg(DEBUG_USBREQ, "-------> 0x%02x (%d)", req, val); + gig_dbg(DEBUG_USBREQ, "-------> 0x%02x (%d)", req, val); spin_lock_irqsave(&ucs->lock, flags); if (ucs->pending) { spin_unlock_irqrestore(&ucs->lock, flags); - err("submission of request 0x%02x failed: request 0x%02x still pending", - req, ucs->pending); + dev_err(bcs->cs->dev, + "submission of request 0x%02x failed: " + "request 0x%02x still pending\n", + req, ucs->pending); return -EBUSY; } if (ucs->urb_ctrl->status == -EINPROGRESS) { spin_unlock_irqrestore(&ucs->lock, flags); - err("could not submit request 0x%02x: URB busy", req); + dev_err(bcs->cs->dev, + "could not submit request 0x%02x: URB busy\n", req); return -EBUSY; } @@ -1469,19 +1431,19 @@ static int req_submit(struct bc_state *bcs, int req, int val, int timeout) ucs->dr_ctrl.wIndex = 0; ucs->dr_ctrl.wLength = 0; usb_fill_control_urb(ucs->urb_ctrl, ucs->udev, - usb_sndctrlpipe(ucs->udev, 0), - (unsigned char*) &ucs->dr_ctrl, NULL, 0, - write_ctrl_callback, ucs); + usb_sndctrlpipe(ucs->udev, 0), + (unsigned char*) &ucs->dr_ctrl, NULL, 0, + write_ctrl_callback, ucs); if ((ret = usb_submit_urb(ucs->urb_ctrl, SLAB_ATOMIC)) != 0) { - err("could not submit request 0x%02x: %s", - req, get_usb_statmsg(ret)); + dev_err(bcs->cs->dev, "could not submit request 0x%02x: %s\n", + req, get_usb_statmsg(ret)); spin_unlock_irqrestore(&ucs->lock, flags); return ret; } ucs->pending = req; if (timeout > 0) { - dbg(DEBUG_USBREQ, "setting timeout of %d/10 secs", timeout); + gig_dbg(DEBUG_USBREQ, "setting timeout of %d/10 secs", timeout); ucs->timer_ctrl.expires = jiffies + timeout * HZ / 10; ucs->timer_ctrl.data = (unsigned long) bcs; ucs->timer_ctrl.function = req_timeout; @@ -1504,19 +1466,18 @@ static int gigaset_init_bchannel(struct bc_state *bcs) { int req, ret; - IFNULLRETVAL(bcs, -EINVAL); - if ((ret = starturbs(bcs)) < 0) { - err("could not start isochronous I/O for channel %d", - bcs->channel + 1); + dev_err(bcs->cs->dev, + "could not start isochronous I/O for channel %d\n", + bcs->channel + 1); error_hangup(bcs); return ret; } req = bcs->channel ? HD_OPEN_B2CHANNEL : HD_OPEN_B1CHANNEL; if ((ret = req_submit(bcs, req, 0, BAS_TIMEOUT)) < 0) { - err("could not open channel %d: %s", - bcs->channel + 1, get_usb_statmsg(ret)); + dev_err(bcs->cs->dev, "could not open channel %d: %s\n", + bcs->channel + 1, get_usb_statmsg(ret)); stopurbs(bcs->hw.bas); error_hangup(bcs); } @@ -1537,8 +1498,6 @@ static int gigaset_close_bchannel(struct bc_state *bcs) { int req, ret; - IFNULLRETVAL(bcs, -EINVAL); - if (!(atomic_read(&bcs->cs->hw.bas->basstate) & (bcs->channel ? BS_B2OPEN : BS_B1OPEN))) { /* channel not running: just signal common.c */ @@ -1548,8 +1507,9 @@ static int gigaset_close_bchannel(struct bc_state *bcs) req = bcs->channel ? HD_CLOSE_B2CHANNEL : HD_CLOSE_B1CHANNEL; if ((ret = req_submit(bcs, req, 0, BAS_TIMEOUT)) < 0) - err("could not submit HD_CLOSE_BxCHANNEL request: %s", - get_usb_statmsg(ret)); + dev_err(bcs->cs->dev, + "could not submit HD_CLOSE_BxCHANNEL request: %s\n", + get_usb_statmsg(ret)); return ret; } @@ -1564,17 +1524,13 @@ static int gigaset_close_bchannel(struct bc_state *bcs) */ static void complete_cb(struct cardstate *cs) { - struct cmdbuf_t *cb; - - IFNULLRET(cs); - cb = cs->cmdbuf; - IFNULLRET(cb); + struct cmdbuf_t *cb = cs->cmdbuf; /* unqueue completed buffer */ cs->cmdbytes -= cs->curlen; - dbg(DEBUG_TRANSCMD | DEBUG_LOCKCMD, - "write_command: sent %u bytes, %u left", - cs->curlen, cs->cmdbytes); + gig_dbg(DEBUG_TRANSCMD|DEBUG_LOCKCMD, + "write_command: sent %u bytes, %u left", + cs->curlen, cs->cmdbytes); if ((cs->cmdbuf = cb->next) != NULL) { cs->cmdbuf->prev = NULL; cs->curlen = cs->cmdbuf->len; @@ -1600,15 +1556,9 @@ static int atwrite_submit(struct cardstate *cs, unsigned char *buf, int len); */ static void write_command_callback(struct urb *urb, struct pt_regs *regs) { - struct cardstate *cs; + struct cardstate *cs = urb->context; + struct bas_cardstate *ucs = cs->hw.bas; unsigned long flags; - struct bas_cardstate *ucs; - - IFNULLRET(urb); - cs = (struct cardstate *) urb->context; - IFNULLRET(cs); - ucs = cs->hw.bas; - IFNULLRET(ucs); /* check status */ switch (urb->status) { @@ -1618,22 +1568,27 @@ static void write_command_callback(struct urb *urb, struct pt_regs *regs) case -ECONNRESET: /* canceled (async) */ case -EINPROGRESS: /* pending */ /* ignore silently */ - dbg(DEBUG_USBREQ, - "%s: %s", __func__, get_usb_statmsg(urb->status)); + gig_dbg(DEBUG_USBREQ, "%s: %s", + __func__, get_usb_statmsg(urb->status)); return; default: /* any failure */ if (++ucs->retry_cmd_out > BAS_RETRY) { - warn("command write: %s, giving up after %d retries", - get_usb_statmsg(urb->status), ucs->retry_cmd_out); + dev_warn(cs->dev, + "command write: %s, " + "giving up after %d retries\n", + get_usb_statmsg(urb->status), + ucs->retry_cmd_out); break; } if (cs->cmdbuf == NULL) { - warn("command write: %s, cannot retry - cmdbuf gone", - get_usb_statmsg(urb->status)); + dev_warn(cs->dev, + "command write: %s, " + "cannot retry - cmdbuf gone\n", + get_usb_statmsg(urb->status)); break; } - notice("command write: %s, retry %d", - get_usb_statmsg(urb->status), ucs->retry_cmd_out); + dev_notice(cs->dev, "command write: %s, retry %d\n", + get_usb_statmsg(urb->status), ucs->retry_cmd_out); if (atwrite_submit(cs, cs->cmdbuf->buf, cs->cmdbuf->len) >= 0) /* resubmitted - bypass regular exit block */ return; @@ -1655,13 +1610,9 @@ static void write_command_callback(struct urb *urb, struct pt_regs *regs) static void atrdy_timeout(unsigned long data) { struct cardstate *cs = (struct cardstate *) data; - struct bas_cardstate *ucs; - - IFNULLRET(cs); - ucs = cs->hw.bas; - IFNULLRET(ucs); + struct bas_cardstate *ucs = cs->hw.bas; - warn("timeout waiting for HD_READY_SEND_ATDATA"); + dev_warn(cs->dev, "timeout waiting for HD_READY_SEND_ATDATA\n"); /* fake the missing signal - what else can I do? */ update_basstate(ucs, BS_ATREADY, BS_ATTIMER); @@ -1682,18 +1633,15 @@ static void atrdy_timeout(unsigned long data) */ static int atwrite_submit(struct cardstate *cs, unsigned char *buf, int len) { - struct bas_cardstate *ucs; + struct bas_cardstate *ucs = cs->hw.bas; + unsigned long flags; int ret; - IFNULLRETVAL(cs, -EFAULT); - ucs = cs->hw.bas; - IFNULLRETVAL(ucs, -EFAULT); - IFNULLRETVAL(ucs->urb_cmd_out, -EFAULT); - - dbg(DEBUG_USBREQ, "-------> HD_WRITE_ATMESSAGE (%d)", len); + gig_dbg(DEBUG_USBREQ, "-------> HD_WRITE_ATMESSAGE (%d)", len); if (ucs->urb_cmd_out->status == -EINPROGRESS) { - err("could not submit HD_WRITE_ATMESSAGE: URB busy"); + dev_err(cs->dev, + "could not submit HD_WRITE_ATMESSAGE: URB busy\n"); return -EBUSY; } @@ -1707,9 +1655,13 @@ static int atwrite_submit(struct cardstate *cs, unsigned char *buf, int len) (unsigned char*) &ucs->dr_cmd_out, buf, len, write_command_callback, cs); - if ((ret = usb_submit_urb(ucs->urb_cmd_out, SLAB_ATOMIC)) != 0) { - err("could not submit HD_WRITE_ATMESSAGE: %s", - get_usb_statmsg(ret)); + spin_lock_irqsave(&cs->lock, flags); + ret = cs->connected ? usb_submit_urb(ucs->urb_cmd_out, SLAB_ATOMIC) : -ENODEV; + spin_unlock_irqrestore(&cs->lock, flags); + + if (ret) { + dev_err(cs->dev, "could not submit HD_WRITE_ATMESSAGE: %s\n", + get_usb_statmsg(ret)); return ret; } @@ -1718,8 +1670,8 @@ static int atwrite_submit(struct cardstate *cs, unsigned char *buf, int len) /* start timeout if necessary */ if (!(atomic_read(&ucs->basstate) & BS_ATTIMER)) { - dbg(DEBUG_OUTPUT, - "setting ATREADY timeout of %d/10 secs", ATRDY_TIMEOUT); + gig_dbg(DEBUG_OUTPUT, "setting ATREADY timeout of %d/10 secs", + ATRDY_TIMEOUT); ucs->timer_atrdy.expires = jiffies + ATRDY_TIMEOUT * HZ / 10; ucs->timer_atrdy.data = (unsigned long) cs; ucs->timer_atrdy.function = atrdy_timeout; @@ -1740,21 +1692,17 @@ static int atwrite_submit(struct cardstate *cs, unsigned char *buf, int len) static int start_cbsend(struct cardstate *cs) { struct cmdbuf_t *cb; - struct bas_cardstate *ucs; + struct bas_cardstate *ucs = cs->hw.bas; unsigned long flags; int rc; int retval = 0; - IFNULLRETVAL(cs, -EFAULT); - ucs = cs->hw.bas; - IFNULLRETVAL(ucs, -EFAULT); - /* check if AT channel is open */ if (!(atomic_read(&ucs->basstate) & BS_ATOPEN)) { - dbg(DEBUG_TRANSCMD | DEBUG_LOCKCMD, "AT channel not open"); + gig_dbg(DEBUG_TRANSCMD|DEBUG_LOCKCMD, "AT channel not open"); rc = req_submit(cs->bcs, HD_OPEN_ATCHANNEL, 0, BAS_TIMEOUT); if (rc < 0) { - err("could not open AT channel"); + dev_err(cs->dev, "could not open AT channel\n"); /* flush command queue */ spin_lock_irqsave(&cs->cmdlock, flags); while (cs->cmdbuf != NULL) @@ -1792,27 +1740,23 @@ static int start_cbsend(struct cardstate *cs) * cs controller state structure * buf command string to send * len number of bytes to send (max. IF_WRITEBUF) - * wake_tasklet tasklet to run when transmission is completed (NULL if none) + * wake_tasklet tasklet to run when transmission is completed + * (NULL if none) * return value: * number of bytes queued on success * error code < 0 on error */ static int gigaset_write_cmd(struct cardstate *cs, - const unsigned char *buf, int len, - struct tasklet_struct *wake_tasklet) + const unsigned char *buf, int len, + struct tasklet_struct *wake_tasklet) { struct cmdbuf_t *cb; unsigned long flags; int status; gigaset_dbg_buffer(atomic_read(&cs->mstate) != MS_LOCKED ? - DEBUG_TRANSCMD : DEBUG_LOCKCMD, - "CMD Transmit", len, buf, 0); - - if (!atomic_read(&cs->connected)) { - err("%s: not connected", __func__); - return -ENODEV; - } + DEBUG_TRANSCMD : DEBUG_LOCKCMD, + "CMD Transmit", len, buf); if (len <= 0) return 0; /* nothing to do */ @@ -1820,7 +1764,7 @@ static int gigaset_write_cmd(struct cardstate *cs, if (len > IF_WRITEBUF) len = IF_WRITEBUF; if (!(cb = kmalloc(sizeof(struct cmdbuf_t) + len, GFP_ATOMIC))) { - err("%s: out of memory", __func__); + dev_err(cs->dev, "%s: out of memory\n", __func__); return -ENOMEM; } @@ -1849,7 +1793,8 @@ static int gigaset_write_cmd(struct cardstate *cs, /* gigaset_write_room * tty_driver.write_room interface routine - * return number of characters the driver will accept to be written via gigaset_write_cmd + * return number of characters the driver will accept to be written via + * gigaset_write_cmd * parameter: * controller state structure * return value: @@ -1947,7 +1892,7 @@ static int gigaset_initbcshw(struct bc_state *bcs) return 0; } tasklet_init(&ubc->sent_tasklet, - &write_iso_tasklet, (unsigned long) bcs); + &write_iso_tasklet, (unsigned long) bcs); spin_lock_init(&ubc->isoinlock); for (i = 0; i < BAS_INURBS; ++i) @@ -1968,7 +1913,7 @@ static int gigaset_initbcshw(struct bc_state *bcs) ubc->shared0s = 0; ubc->stolen0s = 0; tasklet_init(&ubc->rcvd_tasklet, - &read_iso_tasklet, (unsigned long) bcs); + &read_iso_tasklet, (unsigned long) bcs); return 1; } @@ -2027,57 +1972,56 @@ static int gigaset_initcshw(struct cardstate *cs) */ static void freeurbs(struct cardstate *cs) { - struct bas_cardstate *ucs; + struct bas_cardstate *ucs = cs->hw.bas; struct bas_bc_state *ubc; int i, j; - IFNULLRET(cs); - ucs = cs->hw.bas; - IFNULLRET(ucs); - for (j = 0; j < 2; ++j) { ubc = cs->bcs[j].hw.bas; - IFNULLCONT(ubc); for (i = 0; i < BAS_OUTURBS; ++i) if (ubc->isoouturbs[i].urb) { usb_kill_urb(ubc->isoouturbs[i].urb); - dbg(DEBUG_INIT, - "%s: isoc output URB %d/%d unlinked", - __func__, j, i); + gig_dbg(DEBUG_INIT, + "%s: isoc output URB %d/%d unlinked", + __func__, j, i); usb_free_urb(ubc->isoouturbs[i].urb); ubc->isoouturbs[i].urb = NULL; } for (i = 0; i < BAS_INURBS; ++i) if (ubc->isoinurbs[i]) { usb_kill_urb(ubc->isoinurbs[i]); - dbg(DEBUG_INIT, - "%s: isoc input URB %d/%d unlinked", - __func__, j, i); + gig_dbg(DEBUG_INIT, + "%s: isoc input URB %d/%d unlinked", + __func__, j, i); usb_free_urb(ubc->isoinurbs[i]); ubc->isoinurbs[i] = NULL; } } if (ucs->urb_int_in) { usb_kill_urb(ucs->urb_int_in); - dbg(DEBUG_INIT, "%s: interrupt input URB unlinked", __func__); + gig_dbg(DEBUG_INIT, "%s: interrupt input URB unlinked", + __func__); usb_free_urb(ucs->urb_int_in); ucs->urb_int_in = NULL; } if (ucs->urb_cmd_out) { usb_kill_urb(ucs->urb_cmd_out); - dbg(DEBUG_INIT, "%s: command output URB unlinked", __func__); + gig_dbg(DEBUG_INIT, "%s: command output URB unlinked", + __func__); usb_free_urb(ucs->urb_cmd_out); ucs->urb_cmd_out = NULL; } if (ucs->urb_cmd_in) { usb_kill_urb(ucs->urb_cmd_in); - dbg(DEBUG_INIT, "%s: command input URB unlinked", __func__); + gig_dbg(DEBUG_INIT, "%s: command input URB unlinked", + __func__); usb_free_urb(ucs->urb_cmd_in); ucs->urb_cmd_in = NULL; } if (ucs->urb_ctrl) { usb_kill_urb(ucs->urb_ctrl); - dbg(DEBUG_INIT, "%s: control output URB unlinked", __func__); + gig_dbg(DEBUG_INIT, "%s: control output URB unlinked", + __func__); usb_free_urb(ucs->urb_ctrl); ucs->urb_ctrl = NULL; } @@ -2099,12 +2043,10 @@ static int gigaset_probe(struct usb_interface *interface, int i, j; int ret; - IFNULLRETVAL(udev, -ENODEV); - - dbg(DEBUG_ANY, - "%s: Check if device matches .. (Vendor: 0x%x, Product: 0x%x)", - __func__, le16_to_cpu(udev->descriptor.idVendor), - le16_to_cpu(udev->descriptor.idProduct)); + gig_dbg(DEBUG_ANY, + "%s: Check if device matches .. (Vendor: 0x%x, Product: 0x%x)", + __func__, le16_to_cpu(udev->descriptor.idVendor), + le16_to_cpu(udev->descriptor.idProduct)); /* See if the device offered us matches what we can accept */ if ((le16_to_cpu(udev->descriptor.idVendor) != USB_GIGA_VENDOR_ID) || @@ -2112,20 +2054,21 @@ static int gigaset_probe(struct usb_interface *interface, le16_to_cpu(udev->descriptor.idProduct) != USB_4175_PRODUCT_ID && le16_to_cpu(udev->descriptor.idProduct) != USB_SX303_PRODUCT_ID && le16_to_cpu(udev->descriptor.idProduct) != USB_SX353_PRODUCT_ID)) { - dbg(DEBUG_ANY, "%s: unmatched ID - exiting", __func__); + gig_dbg(DEBUG_ANY, "%s: unmatched ID - exiting", __func__); return -ENODEV; } /* set required alternate setting */ hostif = interface->cur_altsetting; if (hostif->desc.bAlternateSetting != 3) { - dbg(DEBUG_ANY, - "%s: wrong alternate setting %d - trying to switch", - __func__, hostif->desc.bAlternateSetting); + gig_dbg(DEBUG_ANY, + "%s: wrong alternate setting %d - trying to switch", + __func__, hostif->desc.bAlternateSetting); if (usb_set_interface(udev, hostif->desc.bInterfaceNumber, 3) < 0) { - warn("usb_set_interface failed, device %d interface %d altsetting %d", - udev->devnum, hostif->desc.bInterfaceNumber, - hostif->desc.bAlternateSetting); + dev_warn(&udev->dev, "usb_set_interface failed, " + "device %d interface %d altsetting %d\n", + udev->devnum, hostif->desc.bInterfaceNumber, + hostif->desc.bAlternateSetting); return -ENODEV; } hostif = interface->cur_altsetting; @@ -2134,23 +2077,28 @@ static int gigaset_probe(struct usb_interface *interface, /* Reject application specific interfaces */ if (hostif->desc.bInterfaceClass != 255) { - warn("%s: bInterfaceClass == %d", - __func__, hostif->desc.bInterfaceClass); + dev_warn(&udev->dev, "%s: bInterfaceClass == %d\n", + __func__, hostif->desc.bInterfaceClass); return -ENODEV; } - info("%s: Device matched (Vendor: 0x%x, Product: 0x%x)", - __func__, le16_to_cpu(udev->descriptor.idVendor), - le16_to_cpu(udev->descriptor.idProduct)); + dev_info(&udev->dev, + "%s: Device matched (Vendor: 0x%x, Product: 0x%x)\n", + __func__, le16_to_cpu(udev->descriptor.idVendor), + le16_to_cpu(udev->descriptor.idProduct)); cs = gigaset_getunassignedcs(driver); if (!cs) { - err("%s: no free cardstate", __func__); + dev_err(&udev->dev, "no free cardstate\n"); return -ENODEV; } ucs = cs->hw.bas; + + /* save off device structure ptrs for later use */ + usb_get_dev(udev); ucs->udev = udev; ucs->interface = interface; + cs->dev = &interface->dev; /* allocate URBs: * - one for the interrupt pipe @@ -2159,22 +2107,22 @@ static int gigaset_probe(struct usb_interface *interface, */ ucs->urb_int_in = usb_alloc_urb(0, SLAB_KERNEL); if (!ucs->urb_int_in) { - err("No free urbs available"); + dev_err(cs->dev, "no free urbs available\n"); goto error; } ucs->urb_cmd_in = usb_alloc_urb(0, SLAB_KERNEL); if (!ucs->urb_cmd_in) { - err("No free urbs available"); + dev_err(cs->dev, "no free urbs available\n"); goto error; } ucs->urb_cmd_out = usb_alloc_urb(0, SLAB_KERNEL); if (!ucs->urb_cmd_out) { - err("No free urbs available"); + dev_err(cs->dev, "no free urbs available\n"); goto error; } ucs->urb_ctrl = usb_alloc_urb(0, SLAB_KERNEL); if (!ucs->urb_ctrl) { - err("No free urbs available"); + dev_err(cs->dev, "no free urbs available\n"); goto error; } @@ -2184,7 +2132,7 @@ static int gigaset_probe(struct usb_interface *interface, ubc->isoouturbs[i].urb = usb_alloc_urb(BAS_NUMFRAMES, SLAB_KERNEL); if (!ubc->isoouturbs[i].urb) { - err("No free urbs available"); + dev_err(cs->dev, "no free urbs available\n"); goto error; } } @@ -2192,7 +2140,7 @@ static int gigaset_probe(struct usb_interface *interface, ubc->isoinurbs[i] = usb_alloc_urb(BAS_NUMFRAMES, SLAB_KERNEL); if (!ubc->isoinurbs[i]) { - err("No free urbs available"); + dev_err(cs->dev, "no free urbs available\n"); goto error; } } @@ -2204,13 +2152,14 @@ static int gigaset_probe(struct usb_interface *interface, /* Fill the interrupt urb and send it to the core */ endpoint = &hostif->endpoint[0].desc; usb_fill_int_urb(ucs->urb_int_in, udev, - usb_rcvintpipe(udev, - (endpoint->bEndpointAddress) & 0x0f), - ucs->int_in_buf, 3, read_int_callback, cs, - endpoint->bInterval); + usb_rcvintpipe(udev, + (endpoint->bEndpointAddress) & 0x0f), + ucs->int_in_buf, 3, read_int_callback, cs, + endpoint->bInterval); ret = usb_submit_urb(ucs->urb_int_in, SLAB_KERNEL); if (ret) { - err("could not submit interrupt URB: %s", get_usb_statmsg(ret)); + dev_err(cs->dev, "could not submit interrupt URB: %s\n", + get_usb_statmsg(ret)); goto error; } @@ -2221,18 +2170,18 @@ static int gigaset_probe(struct usb_interface *interface, /* tell common part that the device is ready */ if (startmode == SM_LOCKED) atomic_set(&cs->mstate, MS_LOCKED); - if (!gigaset_start(cs)) - goto error; /* save address of controller structure */ usb_set_intfdata(interface, cs); - /* set up device sysfs */ - gigaset_init_dev_sysfs(interface); + if (!gigaset_start(cs)) + goto error; + return 0; error: freeurbs(cs); + usb_set_intfdata(interface, NULL); gigaset_unassign(cs); return -ENODEV; } @@ -2245,23 +2194,22 @@ static void gigaset_disconnect(struct usb_interface *interface) struct cardstate *cs; struct bas_cardstate *ucs; - /* clear device sysfs */ - gigaset_free_dev_sysfs(interface); - cs = usb_get_intfdata(interface); - usb_set_intfdata(interface, NULL); - IFNULLRET(cs); ucs = cs->hw.bas; - IFNULLRET(ucs); - info("disconnecting GigaSet base"); + dev_info(cs->dev, "disconnecting Gigaset base\n"); gigaset_stop(cs); freeurbs(cs); + usb_set_intfdata(interface, NULL); kfree(ucs->rcvbuf); ucs->rcvbuf = NULL; ucs->rcvbuf_size = 0; atomic_set(&ucs->basstate, 0); + usb_put_dev(ucs->udev); + ucs->interface = NULL; + ucs->udev = NULL; + cs->dev = NULL; gigaset_unassign(cs); } @@ -2293,13 +2241,14 @@ static int __init bas_gigaset_init(void) /* allocate memory for our driver state and intialize it */ if ((driver = gigaset_initdriver(GIGASET_MINOR, GIGASET_MINORS, - GIGASET_MODULENAME, GIGASET_DEVNAME, - GIGASET_DEVFSNAME, &gigops, - THIS_MODULE)) == NULL) + GIGASET_MODULENAME, GIGASET_DEVNAME, + GIGASET_DEVFSNAME, &gigops, + THIS_MODULE)) == NULL) goto error; /* allocate memory for our device state and intialize it */ - cardstate = gigaset_initcs(driver, 2, 0, 0, cidmode, GIGASET_MODULENAME); + cardstate = gigaset_initcs(driver, 2, 0, 0, cidmode, + GIGASET_MODULENAME); if (!cardstate) goto error; @@ -2329,19 +2278,18 @@ error: if (cardstate) static void __exit bas_gigaset_exit(void) { gigaset_blockdriver(driver); /* => probe will fail - * => no gigaset_start any more - */ + * => no gigaset_start any more + */ gigaset_shutdown(cardstate); /* from now on, no isdn callback should be possible */ if (atomic_read(&cardstate->hw.bas->basstate) & BS_ATOPEN) { - dbg(DEBUG_ANY, "closing AT channel"); + gig_dbg(DEBUG_ANY, "closing AT channel"); if (req_submit(cardstate->bcs, - HD_CLOSE_ATCHANNEL, 0, BAS_TIMEOUT) >= 0) { - /* successfully submitted - wait for completion */ - //wait_event_interruptible(cs->initwait, !cs->hw.bas->pending); - //FIXME need own wait queue? wakeup? + HD_CLOSE_ATCHANNEL, 0, BAS_TIMEOUT) >= 0) { + /* successfully submitted */ + //FIXME wait for completion? } } diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c index 6437199..749b3da 100644 --- a/drivers/isdn/gigaset/common.c +++ b/drivers/isdn/gigaset/common.c @@ -1,7 +1,7 @@ /* * Stuff used by all variants of the driver * - * Copyright (c) 2001 by Stefan Eilers <Eilers.Stefan@epost.de>, + * Copyright (c) 2001 by Stefan Eilers, * Hansjoerg Lipp <hjlipp@web.de>, * Tilman Schmidt <tilman@imap.cc>. * @@ -11,10 +11,6 @@ * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * ===================================================================== - * ToDo: ... - * ===================================================================== - * Version: $Id: common.c,v 1.104.4.22 2006/02/04 18:28:16 hjlipp Exp $ - * ===================================================================== */ #include "gigaset.h" @@ -23,7 +19,7 @@ #include <linux/moduleparam.h> /* Version Information */ -#define DRIVER_AUTHOR "Hansjoerg Lipp <hjlipp@web.de>, Tilman Schmidt <tilman@imap.cc>, Stefan Eilers <Eilers.Stefan@epost.de>" +#define DRIVER_AUTHOR "Hansjoerg Lipp <hjlipp@web.de>, Tilman Schmidt <tilman@imap.cc>, Stefan Eilers" #define DRIVER_DESC "Driver for Gigaset 307x" /* Module parameters */ @@ -32,21 +28,10 @@ EXPORT_SYMBOL_GPL(gigaset_debuglevel); module_param_named(debug, gigaset_debuglevel, int, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(debug, "debug level"); -/*====================================================================== - Prototypes of internal functions - */ - -//static void gigaset_process_response(int resp_code, int parameter, -// struct at_state_t *at_state, -// unsigned char ** pstring); -static struct cardstate *alloc_cs(struct gigaset_driver *drv); -static void free_cs(struct cardstate *cs); -static void make_valid(struct cardstate *cs, unsigned mask); -static void make_invalid(struct cardstate *cs, unsigned mask); - -#define VALID_MINOR 0x01 -#define VALID_ID 0x02 -#define ASSIGNED 0x04 +/* driver state flags */ +#define VALID_MINOR 0x01 +#define VALID_ID 0x02 +#define ASSIGNED 0x04 /* bitwise byte inversion table */ __u8 gigaset_invtab[256] = { @@ -86,42 +71,40 @@ __u8 gigaset_invtab[256] = { EXPORT_SYMBOL_GPL(gigaset_invtab); void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg, - size_t len, const unsigned char *buf, int from_user) + size_t len, const unsigned char *buf) { unsigned char outbuf[80]; - unsigned char inbuf[80 - 1]; - size_t numin; - const unsigned char *in; + unsigned char c; size_t space = sizeof outbuf - 1; unsigned char *out = outbuf; + size_t numin = len; - if (!from_user) { - in = buf; - numin = len; - } else { - numin = len < sizeof inbuf ? len : sizeof inbuf; - in = inbuf; - if (copy_from_user(inbuf, (const unsigned char __user *) buf, numin)) { - strncpy(inbuf, "<FAULT>", sizeof inbuf); - numin = sizeof "<FAULT>" - 1; + while (numin--) { + c = *buf++; + if (c == '~' || c == '^' || c == '\\') { + if (!space--) + break; + *out++ = '\\'; } - } - - for (; numin && space; --numin, ++in) { - --space; - if (*in >= 32) - *out++ = *in; - else { + if (c & 0x80) { + if (!space--) + break; + *out++ = '~'; + c ^= 0x80; + } + if (c < 0x20 || c == 0x7f) { + if (!space--) + break; *out++ = '^'; - if (space) { - *out++ = '@' + *in; - --space; - } + c ^= 0x40; } + if (!space--) + break; + *out++ = c; } *out = 0; - dbg(level, "%s (%u bytes): %s", msg, (unsigned) len, outbuf); + gig_dbg(level, "%s (%u bytes): %s", msg, (unsigned) len, outbuf); } EXPORT_SYMBOL_GPL(gigaset_dbg_buffer); @@ -146,11 +129,6 @@ int gigaset_enterconfigmode(struct cardstate *cs) { int i, r; - if (!atomic_read(&cs->connected)) { - err("not connected!"); - return -1; - } - cs->control_state = TIOCM_RTS; //FIXME r = setflags(cs, TIOCM_DTR, 200); @@ -174,7 +152,7 @@ int gigaset_enterconfigmode(struct cardstate *cs) return 0; error: - err("error %d on setuartbits!\n", -r); + dev_err(cs->dev, "error %d on setuartbits\n", -r); cs->control_state = TIOCM_RTS|TIOCM_DTR; // FIXME is this a good value? cs->ops->set_modem_ctrl(cs, 0, TIOCM_RTS|TIOCM_DTR); @@ -187,13 +165,13 @@ static int test_timeout(struct at_state_t *at_state) return 0; if (--at_state->timer_expires) { - dbg(DEBUG_MCMD, "decreased timer of %p to %lu", - at_state, at_state->timer_expires); + gig_dbg(DEBUG_MCMD, "decreased timer of %p to %lu", + at_state, at_state->timer_expires); return 0; } if (!gigaset_add_event(at_state->cs, at_state, EV_TIMEOUT, NULL, - atomic_read(&at_state->timer_index), NULL)) { + at_state->timer_index, NULL)) { //FIXME what should we do? } @@ -221,10 +199,10 @@ static void timer_tick(unsigned long data) if (test_timeout(at_state)) timeout = 1; - if (atomic_read(&cs->running)) { - mod_timer(&cs->timer, jiffies + GIG_TICK); + if (cs->running) { + mod_timer(&cs->timer, jiffies + msecs_to_jiffies(GIG_TICK)); if (timeout) { - dbg(DEBUG_CMD, "scheduling timeout"); + gig_dbg(DEBUG_CMD, "scheduling timeout"); tasklet_schedule(&cs->event_tasklet); } } @@ -238,13 +216,14 @@ int gigaset_get_channel(struct bc_state *bcs) spin_lock_irqsave(&bcs->cs->lock, flags); if (bcs->use_count) { - dbg(DEBUG_ANY, "could not allocate channel %d", bcs->channel); + gig_dbg(DEBUG_ANY, "could not allocate channel %d", + bcs->channel); spin_unlock_irqrestore(&bcs->cs->lock, flags); return 0; } ++bcs->use_count; bcs->busy = 1; - dbg(DEBUG_ANY, "allocated channel %d", bcs->channel); + gig_dbg(DEBUG_ANY, "allocated channel %d", bcs->channel); spin_unlock_irqrestore(&bcs->cs->lock, flags); return 1; } @@ -255,13 +234,13 @@ void gigaset_free_channel(struct bc_state *bcs) spin_lock_irqsave(&bcs->cs->lock, flags); if (!bcs->busy) { - dbg(DEBUG_ANY, "could not free channel %d", bcs->channel); + gig_dbg(DEBUG_ANY, "could not free channel %d", bcs->channel); spin_unlock_irqrestore(&bcs->cs->lock, flags); return; } --bcs->use_count; bcs->busy = 0; - dbg(DEBUG_ANY, "freed channel %d", bcs->channel); + gig_dbg(DEBUG_ANY, "freed channel %d", bcs->channel); spin_unlock_irqrestore(&bcs->cs->lock, flags); } @@ -274,14 +253,14 @@ int gigaset_get_channels(struct cardstate *cs) for (i = 0; i < cs->channels; ++i) if (cs->bcs[i].use_count) { spin_unlock_irqrestore(&cs->lock, flags); - dbg(DEBUG_ANY, "could not allocated all channels"); + gig_dbg(DEBUG_ANY, "could not allocate all channels"); return 0; } for (i = 0; i < cs->channels; ++i) ++cs->bcs[i].use_count; spin_unlock_irqrestore(&cs->lock, flags); - dbg(DEBUG_ANY, "allocated all channels"); + gig_dbg(DEBUG_ANY, "allocated all channels"); return 1; } @@ -291,7 +270,7 @@ void gigaset_free_channels(struct cardstate *cs) unsigned long flags; int i; - dbg(DEBUG_ANY, "unblocking all channels"); + gig_dbg(DEBUG_ANY, "unblocking all channels"); spin_lock_irqsave(&cs->lock, flags); for (i = 0; i < cs->channels; ++i) --cs->bcs[i].use_count; @@ -303,7 +282,7 @@ void gigaset_block_channels(struct cardstate *cs) unsigned long flags; int i; - dbg(DEBUG_ANY, "blocking all channels"); + gig_dbg(DEBUG_ANY, "blocking all channels"); spin_lock_irqsave(&cs->lock, flags); for (i = 0; i < cs->channels; ++i) ++cs->bcs[i].use_count; @@ -314,25 +293,27 @@ static void clear_events(struct cardstate *cs) { struct event_t *ev; unsigned head, tail; + unsigned long flags; - /* no locking needed (no reader/writer allowed) */ + spin_lock_irqsave(&cs->ev_lock, flags); - head = atomic_read(&cs->ev_head); - tail = atomic_read(&cs->ev_tail); + head = cs->ev_head; + tail = cs->ev_tail; while (tail != head) { ev = cs->events + head; kfree(ev->ptr); - head = (head + 1) % MAX_EVENTS; } - atomic_set(&cs->ev_head, tail); + cs->ev_head = tail; + + spin_unlock_irqrestore(&cs->ev_lock, flags); } struct event_t *gigaset_add_event(struct cardstate *cs, - struct at_state_t *at_state, int type, - void *ptr, int parameter, void *arg) + struct at_state_t *at_state, int type, + void *ptr, int parameter, void *arg) { unsigned long flags; unsigned next, tail; @@ -340,9 +321,9 @@ struct event_t *gigaset_add_event(struct cardstate *cs, spin_lock_irqsave(&cs->ev_lock, flags); - tail = atomic_read(&cs->ev_tail); + tail = cs->ev_tail; next = (tail + 1) % MAX_EVENTS; - if (unlikely(next == atomic_read(&cs->ev_head))) + if (unlikely(next == cs->ev_head)) err("event queue full"); else { event = cs->events + tail; @@ -352,7 +333,7 @@ struct event_t *gigaset_add_event(struct cardstate *cs, event->ptr = ptr; event->arg = arg; event->parameter = parameter; - atomic_set(&cs->ev_tail, next); + cs->ev_tail = next; } spin_unlock_irqrestore(&cs->ev_lock, flags); @@ -391,14 +372,14 @@ static void gigaset_freebcs(struct bc_state *bcs) { int i; - dbg(DEBUG_INIT, "freeing bcs[%d]->hw", bcs->channel); + gig_dbg(DEBUG_INIT, "freeing bcs[%d]->hw", bcs->channel); if (!bcs->cs->ops->freebcshw(bcs)) { - dbg(DEBUG_INIT, "failed"); + gig_dbg(DEBUG_INIT, "failed"); } - dbg(DEBUG_INIT, "clearing bcs[%d]->at_state", bcs->channel); + gig_dbg(DEBUG_INIT, "clearing bcs[%d]->at_state", bcs->channel); clear_at_state(&bcs->at_state); - dbg(DEBUG_INIT, "freeing bcs[%d]->skb", bcs->channel); + gig_dbg(DEBUG_INIT, "freeing bcs[%d]->skb", bcs->channel); if (bcs->skb) dev_kfree_skb(bcs->skb); @@ -408,6 +389,52 @@ static void gigaset_freebcs(struct bc_state *bcs) } } +static struct cardstate *alloc_cs(struct gigaset_driver *drv) +{ + unsigned long flags; + unsigned i; + static struct cardstate *ret = NULL; + + spin_lock_irqsave(&drv->lock, flags); + for (i = 0; i < drv->minors; ++i) { + if (!(drv->flags[i] & VALID_MINOR)) { + drv->flags[i] = VALID_MINOR; + ret = drv->cs + i; + } + if (ret) + break; + } + spin_unlock_irqrestore(&drv->lock, flags); + return ret; +} + +static void free_cs(struct cardstate *cs) +{ + unsigned long flags; + struct gigaset_driver *drv = cs->driver; + spin_lock_irqsave(&drv->lock, flags); + drv->flags[cs->minor_index] = 0; + spin_unlock_irqrestore(&drv->lock, flags); +} + +static void make_valid(struct cardstate *cs, unsigned mask) +{ + unsigned long flags; + struct gigaset_driver *drv = cs->driver; + spin_lock_irqsave(&drv->lock, flags); + drv->flags[cs->minor_index] |= mask; + spin_unlock_irqrestore(&drv->lock, flags); +} + +static void make_invalid(struct cardstate *cs, unsigned mask) +{ + unsigned long flags; + struct gigaset_driver *drv = cs->driver; + spin_lock_irqsave(&drv->lock, flags); + drv->flags[cs->minor_index] &= ~mask; + spin_unlock_irqrestore(&drv->lock, flags); +} + void gigaset_freecs(struct cardstate *cs) { int i; @@ -416,7 +443,7 @@ void gigaset_freecs(struct cardstate *cs) if (!cs) return; - down(&cs->sem); + mutex_lock(&cs->mutex); if (!cs->bcs) goto f_cs; @@ -424,8 +451,9 @@ void gigaset_freecs(struct cardstate *cs) goto f_bcs; spin_lock_irqsave(&cs->lock, flags); - atomic_set(&cs->running, 0); - spin_unlock_irqrestore(&cs->lock, flags); /* event handler and timer are not rescheduled below */ + cs->running = 0; + spin_unlock_irqrestore(&cs->lock, flags); /* event handler and timer are + not rescheduled below */ tasklet_kill(&cs->event_tasklet); del_timer_sync(&cs->timer); @@ -434,7 +462,7 @@ void gigaset_freecs(struct cardstate *cs) default: gigaset_if_free(cs); - dbg(DEBUG_INIT, "clearing hw"); + gig_dbg(DEBUG_INIT, "clearing hw"); cs->ops->freecshw(cs); //FIXME cmdbuf @@ -443,36 +471,36 @@ void gigaset_freecs(struct cardstate *cs) case 2: /* error in initcshw */ /* Deregister from LL */ make_invalid(cs, VALID_ID); - dbg(DEBUG_INIT, "clearing iif"); + gig_dbg(DEBUG_INIT, "clearing iif"); gigaset_i4l_cmd(cs, ISDN_STAT_UNLOAD); /* fall through */ case 1: /* error when regestering to LL */ - dbg(DEBUG_INIT, "clearing at_state"); + gig_dbg(DEBUG_INIT, "clearing at_state"); clear_at_state(&cs->at_state); dealloc_at_states(cs); /* fall through */ case 0: /* error in one call to initbcs */ for (i = 0; i < cs->channels; ++i) { - dbg(DEBUG_INIT, "clearing bcs[%d]", i); + gig_dbg(DEBUG_INIT, "clearing bcs[%d]", i); gigaset_freebcs(cs->bcs + i); } clear_events(cs); - dbg(DEBUG_INIT, "freeing inbuf"); + gig_dbg(DEBUG_INIT, "freeing inbuf"); kfree(cs->inbuf); } -f_bcs: dbg(DEBUG_INIT, "freeing bcs[]"); +f_bcs: gig_dbg(DEBUG_INIT, "freeing bcs[]"); kfree(cs->bcs); -f_cs: dbg(DEBUG_INIT, "freeing cs"); - up(&cs->sem); +f_cs: gig_dbg(DEBUG_INIT, "freeing cs"); + mutex_unlock(&cs->mutex); free_cs(cs); } EXPORT_SYMBOL_GPL(gigaset_freecs); void gigaset_at_init(struct at_state_t *at_state, struct bc_state *bcs, - struct cardstate *cs, int cid) + struct cardstate *cs, int cid) { int i; @@ -482,8 +510,8 @@ void gigaset_at_init(struct at_state_t *at_state, struct bc_state *bcs, at_state->pending_commands = 0; at_state->timer_expires = 0; at_state->timer_active = 0; - atomic_set(&at_state->timer_index, 0); - atomic_set(&at_state->seq_index, 0); + at_state->timer_index = 0; + at_state->seq_index = 0; at_state->ConState = 0; for (i = 0; i < STR_NUM; ++i) at_state->str_var[i] = NULL; @@ -501,7 +529,7 @@ void gigaset_at_init(struct at_state_t *at_state, struct bc_state *bcs, static void gigaset_inbuf_init(struct inbuf_t *inbuf, struct bc_state *bcs, - struct cardstate *cs, int inputstate) + struct cardstate *cs, int inputstate) /* inbuf->read must be allocated before! */ { atomic_set(&inbuf->head, 0); @@ -512,9 +540,50 @@ static void gigaset_inbuf_init(struct inbuf_t *inbuf, struct bc_state *bcs, inbuf->inputstate = inputstate; } +/* append received bytes to inbuf */ +int gigaset_fill_inbuf(struct inbuf_t *inbuf, const unsigned char *src, + unsigned numbytes) +{ + unsigned n, head, tail, bytesleft; + + gig_dbg(DEBUG_INTR, "received %u bytes", numbytes); + + if (!numbytes) + return 0; + + bytesleft = numbytes; + tail = atomic_read(&inbuf->tail); + head = atomic_read(&inbuf->head); + gig_dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail); + + while (bytesleft) { + if (head > tail) + n = head - 1 - tail; + else if (head == 0) + n = (RBUFSIZE-1) - tail; + else + n = RBUFSIZE - tail; + if (!n) { + dev_err(inbuf->cs->dev, + "buffer overflow (%u bytes lost)", bytesleft); + break; + } + if (n > bytesleft) + n = bytesleft; + memcpy(inbuf->data + tail, src, n); + bytesleft -= n; + tail = (tail + n) % RBUFSIZE; + src += n; + } + gig_dbg(DEBUG_INTR, "setting tail to %u", tail); + atomic_set(&inbuf->tail, tail); + return numbytes != bytesleft; +} +EXPORT_SYMBOL_GPL(gigaset_fill_inbuf); + /* Initialize the b-channel structure */ static struct bc_state *gigaset_initbcs(struct bc_state *bcs, - struct cardstate *cs, int channel) + struct cardstate *cs, int channel) { int i; @@ -526,7 +595,7 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs, bcs->trans_down = 0; bcs->trans_up = 0; - dbg(DEBUG_INIT, "setting up bcs[%d]->at_state", channel); + gig_dbg(DEBUG_INIT, "setting up bcs[%d]->at_state", channel); gigaset_at_init(&bcs->at_state, bcs, cs, -1); bcs->rcvbytes = 0; @@ -535,7 +604,7 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs, bcs->emptycount = 0; #endif - dbg(DEBUG_INIT, "allocating bcs[%d]->skb", channel); + gig_dbg(DEBUG_INIT, "allocating bcs[%d]->skb", channel); bcs->fcs = PPP_INITFCS; bcs->inputstate = 0; if (cs->ignoreframes) { @@ -544,7 +613,7 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs, } else if ((bcs->skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL) skb_reserve(bcs->skb, HW_HDR_LEN); else { - warn("could not allocate skb"); + dev_warn(cs->dev, "could not allocate skb\n"); bcs->inputstate |= INS_skip_frame; } @@ -559,14 +628,13 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs, for (i = 0; i < AT_NUM; ++i) bcs->commands[i] = NULL; - dbg(DEBUG_INIT, " setting up bcs[%d]->hw", channel); + gig_dbg(DEBUG_INIT, " setting up bcs[%d]->hw", channel); if (cs->ops->initbcshw(bcs)) return bcs; -//error: - dbg(DEBUG_INIT, " failed"); + gig_dbg(DEBUG_INIT, " failed"); - dbg(DEBUG_INIT, " freeing bcs[%d]->skb", channel); + gig_dbg(DEBUG_INIT, " freeing bcs[%d]->skb", channel); if (bcs->skb) dev_kfree_skb(bcs->skb); @@ -578,9 +646,10 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs, * Calls hardware dependent gigaset_initcshw() function * Calls B channel initialization function gigaset_initbcs() for each B channel * parameters: - * drv hardware driver the device belongs to + * drv hardware driver the device belongs to * channels number of B channels supported by device - * onechannel !=0: B channel data and AT commands share one communication channel + * onechannel !=0: B channel data and AT commands share one + * communication channel * ==0: B channels have separate communication channels * ignoreframes number of frames to ignore after setting up B channel * cidmode !=0: start in CallID mode @@ -593,17 +662,18 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels, int cidmode, const char *modulename) { struct cardstate *cs = NULL; + unsigned long flags; int i; - dbg(DEBUG_INIT, "allocating cs"); + gig_dbg(DEBUG_INIT, "allocating cs"); cs = alloc_cs(drv); if (!cs) goto error; - dbg(DEBUG_INIT, "allocating bcs[0..%d]", channels - 1); + gig_dbg(DEBUG_INIT, "allocating bcs[0..%d]", channels - 1); cs->bcs = kmalloc(channels * sizeof(struct bc_state), GFP_KERNEL); if (!cs->bcs) goto error; - dbg(DEBUG_INIT, "allocating inbuf"); + gig_dbg(DEBUG_INIT, "allocating inbuf"); cs->inbuf = kmalloc(sizeof(struct inbuf_t), GFP_KERNEL); if (!cs->inbuf) goto error; @@ -613,19 +683,23 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels, cs->onechannel = onechannel; cs->ignoreframes = ignoreframes; INIT_LIST_HEAD(&cs->temp_at_states); - atomic_set(&cs->running, 0); + cs->running = 0; init_timer(&cs->timer); /* clear next & prev */ spin_lock_init(&cs->ev_lock); - atomic_set(&cs->ev_tail, 0); - atomic_set(&cs->ev_head, 0); - init_MUTEX_LOCKED(&cs->sem); - tasklet_init(&cs->event_tasklet, &gigaset_handle_event, (unsigned long) cs); + cs->ev_tail = 0; + cs->ev_head = 0; + mutex_init(&cs->mutex); + mutex_lock(&cs->mutex); + + tasklet_init(&cs->event_tasklet, &gigaset_handle_event, + (unsigned long) cs); atomic_set(&cs->commands_pending, 0); cs->cur_at_seq = 0; cs->gotfwver = -1; cs->open_count = 0; + cs->dev = NULL; cs->tty = NULL; - atomic_set(&cs->cidmode, cidmode != 0); + cs->cidmode = cidmode != 0; //if(onechannel) { //FIXME cs->tabnocid = gigaset_tab_nocid_m10x; @@ -642,50 +716,43 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels, atomic_set(&cs->mstate, MS_UNINITIALIZED); for (i = 0; i < channels; ++i) { - dbg(DEBUG_INIT, "setting up bcs[%d].read", i); + gig_dbg(DEBUG_INIT, "setting up bcs[%d].read", i); if (!gigaset_initbcs(cs->bcs + i, cs, i)) goto error; } ++cs->cs_init; - dbg(DEBUG_INIT, "setting up at_state"); + gig_dbg(DEBUG_INIT, "setting up at_state"); spin_lock_init(&cs->lock); gigaset_at_init(&cs->at_state, NULL, cs, 0); cs->dle = 0; cs->cbytes = 0; - dbg(DEBUG_INIT, "setting up inbuf"); + gig_dbg(DEBUG_INIT, "setting up inbuf"); if (onechannel) { //FIXME distinction necessary? gigaset_inbuf_init(cs->inbuf, cs->bcs, cs, INS_command); } else gigaset_inbuf_init(cs->inbuf, NULL, cs, INS_command); - atomic_set(&cs->connected, 0); + cs->connected = 0; + cs->isdn_up = 0; - dbg(DEBUG_INIT, "setting up cmdbuf"); + gig_dbg(DEBUG_INIT, "setting up cmdbuf"); cs->cmdbuf = cs->lastcmdbuf = NULL; spin_lock_init(&cs->cmdlock); cs->curlen = 0; cs->cmdbytes = 0; - /* - * Tell the ISDN4Linux subsystem (the LL) that - * a driver for a USB-Device is available ! - * If this is done, "isdnctrl" is able to bind a device for this driver even - * if no physical usb-device is currently connected. - * But this device will just be accessable if a physical USB device is connected - * (via "gigaset_probe") . - */ - dbg(DEBUG_INIT, "setting up iif"); + gig_dbg(DEBUG_INIT, "setting up iif"); if (!gigaset_register_to_LL(cs, modulename)) { - err("register_isdn=>error"); + err("register_isdn failed"); goto error; } make_valid(cs, VALID_ID); ++cs->cs_init; - dbg(DEBUG_INIT, "setting up hw"); + gig_dbg(DEBUG_INIT, "setting up hw"); if (!cs->ops->initcshw(cs)) goto error; @@ -693,27 +760,29 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels, gigaset_if_init(cs); - atomic_set(&cs->running, 1); - cs->timer.data = (unsigned long) cs; - cs->timer.function = timer_tick; - cs->timer.expires = jiffies + GIG_TICK; + spin_lock_irqsave(&cs->lock, flags); + cs->running = 1; + spin_unlock_irqrestore(&cs->lock, flags); + setup_timer(&cs->timer, timer_tick, (unsigned long) cs); + cs->timer.expires = jiffies + msecs_to_jiffies(GIG_TICK); /* FIXME: can jiffies increase too much until the timer is added? * Same problem(?) with mod_timer() in timer_tick(). */ add_timer(&cs->timer); - dbg(DEBUG_INIT, "cs initialized!"); - up(&cs->sem); + gig_dbg(DEBUG_INIT, "cs initialized"); + mutex_unlock(&cs->mutex); return cs; error: if (cs) - up(&cs->sem); - dbg(DEBUG_INIT, "failed"); + mutex_unlock(&cs->mutex); + gig_dbg(DEBUG_INIT, "failed"); gigaset_freecs(cs); return NULL; } EXPORT_SYMBOL_GPL(gigaset_initcs); -/* ReInitialize the b-channel structure */ /* e.g. called on hangup, disconnect */ +/* ReInitialize the b-channel structure */ +/* e.g. called on hangup, disconnect */ void gigaset_bcs_reinit(struct bc_state *bcs) { struct sk_buff *skb; @@ -723,12 +792,12 @@ void gigaset_bcs_reinit(struct bc_state *bcs) while ((skb = skb_dequeue(&bcs->squeue)) != NULL) dev_kfree_skb(skb); - spin_lock_irqsave(&cs->lock, flags); //FIXME + spin_lock_irqsave(&cs->lock, flags); clear_at_state(&bcs->at_state); bcs->at_state.ConState = 0; bcs->at_state.timer_active = 0; bcs->at_state.timer_expires = 0; - bcs->at_state.cid = -1; /* No CID defined */ + bcs->at_state.cid = -1; /* No CID defined */ spin_unlock_irqrestore(&cs->lock, flags); bcs->inputstate = 0; @@ -803,11 +872,14 @@ static void cleanup_cs(struct cardstate *cs) int gigaset_start(struct cardstate *cs) { - if (down_interruptible(&cs->sem)) + unsigned long flags; + + if (mutex_lock_interruptible(&cs->mutex)) return 0; - //info("USB device for Gigaset 307x now attached to Dev %d", ucs->minor); - atomic_set(&cs->connected, 1); + spin_lock_irqsave(&cs->lock, flags); + cs->connected = 1; + spin_unlock_irqrestore(&cs->lock, flags); if (atomic_read(&cs->mstate) != MS_LOCKED) { cs->ops->set_modem_ctrl(cs, 0, TIOCM_DTR|TIOCM_RTS); @@ -826,23 +898,26 @@ int gigaset_start(struct cardstate *cs) goto error; } - dbg(DEBUG_CMD, "scheduling START"); + gig_dbg(DEBUG_CMD, "scheduling START"); gigaset_schedule_event(cs); wait_event(cs->waitqueue, !cs->waiting); - up(&cs->sem); + /* set up device sysfs */ + gigaset_init_dev_sysfs(cs); + + mutex_unlock(&cs->mutex); return 1; error: - up(&cs->sem); + mutex_unlock(&cs->mutex); return 0; } EXPORT_SYMBOL_GPL(gigaset_start); void gigaset_shutdown(struct cardstate *cs) { - down(&cs->sem); + mutex_lock(&cs->mutex); cs->waiting = 1; @@ -851,11 +926,11 @@ void gigaset_shutdown(struct cardstate *cs) goto exit; } - dbg(DEBUG_CMD, "scheduling SHUTDOWN"); + gig_dbg(DEBUG_CMD, "scheduling SHUTDOWN"); gigaset_schedule_event(cs); if (wait_event_interruptible(cs->waitqueue, !cs->waiting)) { - warn("aborted"); + warn("%s: aborted", __func__); //FIXME } @@ -872,15 +947,13 @@ void gigaset_shutdown(struct cardstate *cs) cleanup_cs(cs); exit: - up(&cs->sem); + mutex_unlock(&cs->mutex); } EXPORT_SYMBOL_GPL(gigaset_shutdown); void gigaset_stop(struct cardstate *cs) { - down(&cs->sem); - - atomic_set(&cs->connected, 0); + mutex_lock(&cs->mutex); cs->waiting = 1; @@ -889,21 +962,21 @@ void gigaset_stop(struct cardstate *cs) goto exit; } - dbg(DEBUG_CMD, "scheduling STOP"); + gig_dbg(DEBUG_CMD, "scheduling STOP"); gigaset_schedule_event(cs); if (wait_event_interruptible(cs->waitqueue, !cs->waiting)) { - warn("aborted"); + warn("%s: aborted", __func__); //FIXME } - /* Tell the LL that the device is not available .. */ - gigaset_i4l_cmd(cs, ISDN_STAT_STOP); // FIXME move to event layer? + /* clear device sysfs */ + gigaset_free_dev_sysfs(cs); cleanup_cs(cs); exit: - up(&cs->sem); + mutex_unlock(&cs->mutex); } EXPORT_SYMBOL_GPL(gigaset_stop); @@ -947,31 +1020,25 @@ void gigaset_debugdrivers(void) spin_lock_irqsave(&driver_lock, flags); list_for_each_entry(drv, &drivers, list) { - dbg(DEBUG_DRIVER, "driver %p", drv); + gig_dbg(DEBUG_DRIVER, "driver %p", drv); spin_lock(&drv->lock); for (i = 0; i < drv->minors; ++i) { - dbg(DEBUG_DRIVER, " index %u", i); - dbg(DEBUG_DRIVER, " flags 0x%02x", drv->flags[i]); + gig_dbg(DEBUG_DRIVER, " index %u", i); + gig_dbg(DEBUG_DRIVER, " flags 0x%02x", + drv->flags[i]); cs = drv->cs + i; - dbg(DEBUG_DRIVER, " cardstate %p", cs); - dbg(DEBUG_DRIVER, " minor_index %u", cs->minor_index); - dbg(DEBUG_DRIVER, " driver %p", cs->driver); - dbg(DEBUG_DRIVER, " i4l id %d", cs->myid); + gig_dbg(DEBUG_DRIVER, " cardstate %p", cs); + gig_dbg(DEBUG_DRIVER, " minor_index %u", + cs->minor_index); + gig_dbg(DEBUG_DRIVER, " driver %p", cs->driver); + gig_dbg(DEBUG_DRIVER, " i4l id %d", cs->myid); } spin_unlock(&drv->lock); } spin_unlock_irqrestore(&driver_lock, flags); } -EXPORT_SYMBOL_GPL(gigaset_debugdrivers); - -struct cardstate *gigaset_get_cs_by_tty(struct tty_struct *tty) -{ - if (tty->index < 0 || tty->index >= tty->driver->num) - return NULL; - return gigaset_get_cs_by_minor(tty->index + tty->driver->minor_start); -} -struct cardstate *gigaset_get_cs_by_minor(unsigned minor) +static struct cardstate *gigaset_get_cs_by_minor(unsigned minor) { unsigned long flags; static struct cardstate *ret = NULL; @@ -994,6 +1061,13 @@ struct cardstate *gigaset_get_cs_by_minor(unsigned minor) return ret; } +struct cardstate *gigaset_get_cs_by_tty(struct tty_struct *tty) +{ + if (tty->index < 0 || tty->index >= tty->driver->num) + return NULL; + return gigaset_get_cs_by_minor(tty->index + tty->driver->minor_start); +} + void gigaset_freedriver(struct gigaset_driver *drv) { unsigned long flags; @@ -1014,20 +1088,20 @@ EXPORT_SYMBOL_GPL(gigaset_freedriver); /* gigaset_initdriver * Allocate and initialize gigaset_driver structure. Initialize interface. * parameters: - * minor First minor number - * minors Number of minors this driver can handle - * procname Name of the driver (e.g. for /proc/tty/drivers, path in /proc/driver) - * devname Name of the device files (prefix without minor number) - * devfsname Devfs name of the device files without %d + * minor First minor number + * minors Number of minors this driver can handle + * procname Name of the driver + * devname Name of the device files (prefix without minor number) + * devfsname Devfs name of the device files without %d * return value: - * Pointer to the gigaset_driver structure on success, NULL on failure. + * Pointer to the gigaset_driver structure on success, NULL on failure. */ struct gigaset_driver *gigaset_initdriver(unsigned minor, unsigned minors, - const char *procname, - const char *devname, - const char *devfsname, - const struct gigaset_ops *ops, - struct module *owner) + const char *procname, + const char *devname, + const char *devfsname, + const struct gigaset_ops *ops, + struct module *owner) { struct gigaset_driver *drv; unsigned long flags; @@ -1036,8 +1110,9 @@ struct gigaset_driver *gigaset_initdriver(unsigned minor, unsigned minors, drv = kmalloc(sizeof *drv, GFP_KERNEL); if (!drv) return NULL; + if (!try_module_get(owner)) - return NULL; + goto out1; drv->cs = NULL; drv->have_tty = 0; @@ -1051,10 +1126,11 @@ struct gigaset_driver *gigaset_initdriver(unsigned minor, unsigned minors, drv->cs = kmalloc(minors * sizeof *drv->cs, GFP_KERNEL); if (!drv->cs) - goto out1; + goto out2; + drv->flags = kmalloc(minors * sizeof *drv->flags, GFP_KERNEL); if (!drv->flags) - goto out2; + goto out3; for (i = 0; i < minors; ++i) { drv->flags[i] = 0; @@ -1071,61 +1147,16 @@ struct gigaset_driver *gigaset_initdriver(unsigned minor, unsigned minors, return drv; -out2: +out3: kfree(drv->cs); +out2: + module_put(owner); out1: kfree(drv); - module_put(owner); return NULL; } EXPORT_SYMBOL_GPL(gigaset_initdriver); -static struct cardstate *alloc_cs(struct gigaset_driver *drv) -{ - unsigned long flags; - unsigned i; - static struct cardstate *ret = NULL; - - spin_lock_irqsave(&drv->lock, flags); - for (i = 0; i < drv->minors; ++i) { - if (!(drv->flags[i] & VALID_MINOR)) { - drv->flags[i] = VALID_MINOR; - ret = drv->cs + i; - } - if (ret) - break; - } - spin_unlock_irqrestore(&drv->lock, flags); - return ret; -} - -static void free_cs(struct cardstate *cs) -{ - unsigned long flags; - struct gigaset_driver *drv = cs->driver; - spin_lock_irqsave(&drv->lock, flags); - drv->flags[cs->minor_index] = 0; - spin_unlock_irqrestore(&drv->lock, flags); -} - -static void make_valid(struct cardstate *cs, unsigned mask) -{ - unsigned long flags; - struct gigaset_driver *drv = cs->driver; - spin_lock_irqsave(&drv->lock, flags); - drv->flags[cs->minor_index] |= mask; - spin_unlock_irqrestore(&drv->lock, flags); -} - -static void make_invalid(struct cardstate *cs, unsigned mask) -{ - unsigned long flags; - struct gigaset_driver *drv = cs->driver; - spin_lock_irqsave(&drv->lock, flags); - drv->flags[cs->minor_index] &= ~mask; - spin_unlock_irqrestore(&drv->lock, flags); -} - /* For drivers without fixed assignment device<->cardstate (usb) */ struct cardstate *gigaset_getunassignedcs(struct gigaset_driver *drv) { diff --git a/drivers/isdn/gigaset/ev-layer.c b/drivers/isdn/gigaset/ev-layer.c index fdcb80b..1ba3424 100644 --- a/drivers/isdn/gigaset/ev-layer.c +++ b/drivers/isdn/gigaset/ev-layer.c @@ -1,7 +1,7 @@ /* * Stuff used by all variants of the driver * - * Copyright (c) 2001 by Stefan Eilers <Eilers.Stefan@epost.de>, + * Copyright (c) 2001 by Stefan Eilers, * Hansjoerg Lipp <hjlipp@web.de>, * Tilman Schmidt <tilman@imap.cc>. * @@ -11,82 +11,78 @@ * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * ===================================================================== - * ToDo: ... - * ===================================================================== - * Version: $Id: ev-layer.c,v 1.4.2.18 2006/02/04 18:28:16 hjlipp Exp $ - * ===================================================================== */ #include "gigaset.h" /* ========================================================== */ /* bit masks for pending commands */ -#define PC_INIT 0x004 -#define PC_DLE0 0x008 -#define PC_DLE1 0x010 -#define PC_CID 0x080 -#define PC_NOCID 0x100 -#define PC_HUP 0x002 -#define PC_DIAL 0x001 -#define PC_ACCEPT 0x040 -#define PC_SHUTDOWN 0x020 -#define PC_CIDMODE 0x200 -#define PC_UMMODE 0x400 +#define PC_DIAL 0x001 +#define PC_HUP 0x002 +#define PC_INIT 0x004 +#define PC_DLE0 0x008 +#define PC_DLE1 0x010 +#define PC_SHUTDOWN 0x020 +#define PC_ACCEPT 0x040 +#define PC_CID 0x080 +#define PC_NOCID 0x100 +#define PC_CIDMODE 0x200 +#define PC_UMMODE 0x400 /* types of modem responses */ -#define RT_NOTHING 0 -#define RT_ZSAU 1 -#define RT_RING 2 -#define RT_NUMBER 3 -#define RT_STRING 4 -#define RT_HEX 5 -#define RT_ZCAU 6 +#define RT_NOTHING 0 +#define RT_ZSAU 1 +#define RT_RING 2 +#define RT_NUMBER 3 +#define RT_STRING 4 +#define RT_HEX 5 +#define RT_ZCAU 6 /* Possible ASCII responses */ -#define RSP_OK 0 -//#define RSP_BUSY 1 -//#define RSP_CONNECT 2 -#define RSP_ZGCI 3 -#define RSP_RING 4 -#define RSP_ZAOC 5 -#define RSP_ZCSTR 6 -#define RSP_ZCFGT 7 -#define RSP_ZCFG 8 -#define RSP_ZCCR 9 -#define RSP_EMPTY 10 -#define RSP_ZLOG 11 -#define RSP_ZCAU 12 -#define RSP_ZMWI 13 -#define RSP_ZABINFO 14 -#define RSP_ZSMLSTCHG 15 -#define RSP_VAR 100 -#define RSP_ZSAU (RSP_VAR + VAR_ZSAU) -#define RSP_ZDLE (RSP_VAR + VAR_ZDLE) -#define RSP_ZVLS (RSP_VAR + VAR_ZVLS) -#define RSP_ZCTP (RSP_VAR + VAR_ZCTP) -#define RSP_STR (RSP_VAR + VAR_NUM) -#define RSP_NMBR (RSP_STR + STR_NMBR) -#define RSP_ZCPN (RSP_STR + STR_ZCPN) -#define RSP_ZCON (RSP_STR + STR_ZCON) -#define RSP_ZBC (RSP_STR + STR_ZBC) -#define RSP_ZHLC (RSP_STR + STR_ZHLC) -#define RSP_ERROR -1 /* ERROR */ -#define RSP_WRONG_CID -2 /* unknown cid in cmd */ -//#define RSP_EMPTY -3 -#define RSP_UNKNOWN -4 /* unknown response */ -#define RSP_FAIL -5 /* internal error */ -#define RSP_INVAL -6 /* invalid response */ - -#define RSP_NONE -19 -#define RSP_STRING -20 -#define RSP_NULL -21 -//#define RSP_RETRYFAIL -22 -//#define RSP_RETRY -23 -//#define RSP_SKIP -24 -#define RSP_INIT -27 -#define RSP_ANY -26 -#define RSP_LAST -28 -#define RSP_NODEV -9 +#define RSP_OK 0 +//#define RSP_BUSY 1 +//#define RSP_CONNECT 2 +#define RSP_ZGCI 3 +#define RSP_RING 4 +#define RSP_ZAOC 5 +#define RSP_ZCSTR 6 +#define RSP_ZCFGT 7 +#define RSP_ZCFG 8 +#define RSP_ZCCR 9 +#define RSP_EMPTY 10 +#define RSP_ZLOG 11 +#define RSP_ZCAU 12 +#define RSP_ZMWI 13 +#define RSP_ZABINFO 14 +#define RSP_ZSMLSTCHG 15 +#define RSP_VAR 100 +#define RSP_ZSAU (RSP_VAR + VAR_ZSAU) +#define RSP_ZDLE (RSP_VAR + VAR_ZDLE) +#define RSP_ZVLS (RSP_VAR + VAR_ZVLS) +#define RSP_ZCTP (RSP_VAR + VAR_ZCTP) +#define RSP_STR (RSP_VAR + VAR_NUM) +#define RSP_NMBR (RSP_STR + STR_NMBR) +#define RSP_ZCPN (RSP_STR + STR_ZCPN) +#define RSP_ZCON (RSP_STR + STR_ZCON) +#define RSP_ZBC (RSP_STR + STR_ZBC) +#define RSP_ZHLC (RSP_STR + STR_ZHLC) +#define RSP_ERROR -1 /* ERROR */ +#define RSP_WRONG_CID -2 /* unknown cid in cmd */ +//#define RSP_EMPTY -3 +#define RSP_UNKNOWN -4 /* unknown response */ +#define RSP_FAIL -5 /* internal error */ +#define RSP_INVAL -6 /* invalid response */ + +#define RSP_NONE -19 +#define RSP_STRING -20 +#define RSP_NULL -21 +//#define RSP_RETRYFAIL -22 +//#define RSP_RETRY -23 +//#define RSP_SKIP -24 +#define RSP_INIT -27 +#define RSP_ANY -26 +#define RSP_LAST -28 +#define RSP_NODEV -9 /* actions for process_response */ #define ACT_NOTHING 0 @@ -112,7 +108,7 @@ #define ACT_DISCONNECT 20 #define ACT_CONNECT 21 #define ACT_REMOTEREJECT 22 -#define ACT_CONNTIMEOUT 23 +#define ACT_CONNTIMEOUT 23 #define ACT_REMOTEHUP 24 #define ACT_ABORTHUP 25 #define ACT_ICALL 26 @@ -127,40 +123,40 @@ #define ACT_ERROR 35 #define ACT_ABORTCID 36 #define ACT_ZCAU 37 -#define ACT_NOTIFY_BC_DOWN 38 -#define ACT_NOTIFY_BC_UP 39 -#define ACT_DIAL 40 -#define ACT_ACCEPT 41 -#define ACT_PROTO_L2 42 -#define ACT_HUP 43 -#define ACT_IF_LOCK 44 -#define ACT_START 45 -#define ACT_STOP 46 -#define ACT_FAKEDLE0 47 -#define ACT_FAKEHUP 48 -#define ACT_FAKESDOWN 49 -#define ACT_SHUTDOWN 50 -#define ACT_PROC_CIDMODE 51 -#define ACT_UMODESET 52 -#define ACT_FAILUMODE 53 -#define ACT_CMODESET 54 -#define ACT_FAILCMODE 55 -#define ACT_IF_VER 56 +#define ACT_NOTIFY_BC_DOWN 38 +#define ACT_NOTIFY_BC_UP 39 +#define ACT_DIAL 40 +#define ACT_ACCEPT 41 +#define ACT_PROTO_L2 42 +#define ACT_HUP 43 +#define ACT_IF_LOCK 44 +#define ACT_START 45 +#define ACT_STOP 46 +#define ACT_FAKEDLE0 47 +#define ACT_FAKEHUP 48 +#define ACT_FAKESDOWN 49 +#define ACT_SHUTDOWN 50 +#define ACT_PROC_CIDMODE 51 +#define ACT_UMODESET 52 +#define ACT_FAILUMODE 53 +#define ACT_CMODESET 54 +#define ACT_FAILCMODE 55 +#define ACT_IF_VER 56 #define ACT_CMD 100 /* at command sequences */ -#define SEQ_NONE 0 -#define SEQ_INIT 100 -#define SEQ_DLE0 200 -#define SEQ_DLE1 250 -#define SEQ_CID 300 -#define SEQ_NOCID 350 -#define SEQ_HUP 400 -#define SEQ_DIAL 600 -#define SEQ_ACCEPT 720 -#define SEQ_SHUTDOWN 500 -#define SEQ_CIDMODE 10 -#define SEQ_UMMODE 11 +#define SEQ_NONE 0 +#define SEQ_INIT 100 +#define SEQ_DLE0 200 +#define SEQ_DLE1 250 +#define SEQ_CID 300 +#define SEQ_NOCID 350 +#define SEQ_HUP 400 +#define SEQ_DIAL 600 +#define SEQ_ACCEPT 720 +#define SEQ_SHUTDOWN 500 +#define SEQ_CIDMODE 10 +#define SEQ_UMMODE 11 // 100: init, 200: dle0, 250:dle1, 300: get cid (dial), 350: "hup" (no cid), 400: hup, 500: reset, 600: dial, 700: ring @@ -175,7 +171,7 @@ struct reply_t gigaset_tab_nocid_m10x[]= /* with dle mode */ // {ACT_TIMEOUT}}, {RSP_INIT, -1, -1,SEQ_INIT, 100, INIT_TIMEOUT, - {ACT_TIMEOUT}}, /* wait until device is ready */ + {ACT_TIMEOUT}}, /* wait until device is ready */ {EV_TIMEOUT, 100,100, -1, 101, 3, {0}, "Z\r"}, /* device in transparent mode? try to initialize it. */ {RSP_OK, 101,103, -1, 120, 5, {ACT_GETSTRING}, "+GMR\r"}, /* get version */ @@ -190,8 +186,8 @@ struct reply_t gigaset_tab_nocid_m10x[]= /* with dle mode */ {RSP_ERROR, 108,108, -1, 0, 0, {ACT_FAILINIT}}, {EV_TIMEOUT, 108,108, -1, 105, 2, {ACT_SETDLE0, - ACT_HUPMODEM, - ACT_TIMEOUT}}, /* still timeout => connection in unimodem mode? */ + ACT_HUPMODEM, + ACT_TIMEOUT}}, /* still timeout => connection in unimodem mode? */ {EV_TIMEOUT, 105,105, -1, 103, 5, {0}, "Z\r"}, {RSP_ERROR, 102,102, -1, 107, 5, {0}, "^GETPRE\r"}, /* ERROR on ATZ => maybe in config mode? */ @@ -393,7 +389,7 @@ struct reply_t gigaset_tab_cid_m10x[] = /* for M10x */ #if 0 -static struct reply_t tab_nocid[]= /* no dle mode */ //FIXME aenderungen uebernehmen +static struct reply_t tab_nocid[]= /* no dle mode */ //FIXME { /* resp_code, min_ConState, max_ConState, parameter, new_ConState, timeout, action, command */ @@ -401,7 +397,7 @@ static struct reply_t tab_nocid[]= /* no dle mode */ //FIXME aenderungen ueberne {RSP_LAST,0,0,0,0,0,0} }; -static struct reply_t tab_cid[] = /* no dle mode */ //FIXME aenderungen uebernehmen +static struct reply_t tab_cid[] = /* no dle mode */ //FIXME { /* resp_code, min_ConState, max_ConState, parameter, new_ConState, timeout, action, command */ @@ -412,30 +408,30 @@ static struct reply_t tab_cid[] = /* no dle mode */ //FIXME aenderungen ueberneh static struct resp_type_t resp_type[]= { - /*{"", RSP_EMPTY, RT_NOTHING},*/ - {"OK", RSP_OK, RT_NOTHING}, - {"ERROR", RSP_ERROR, RT_NOTHING}, - {"ZSAU", RSP_ZSAU, RT_ZSAU}, - {"ZCAU", RSP_ZCAU, RT_ZCAU}, - {"RING", RSP_RING, RT_RING}, - {"ZGCI", RSP_ZGCI, RT_NUMBER}, - {"ZVLS", RSP_ZVLS, RT_NUMBER}, - {"ZCTP", RSP_ZCTP, RT_NUMBER}, - {"ZDLE", RSP_ZDLE, RT_NUMBER}, - {"ZCFGT", RSP_ZCFGT, RT_NUMBER}, - {"ZCCR", RSP_ZCCR, RT_NUMBER}, - {"ZMWI", RSP_ZMWI, RT_NUMBER}, - {"ZHLC", RSP_ZHLC, RT_STRING}, - {"ZBC", RSP_ZBC, RT_STRING}, - {"NMBR", RSP_NMBR, RT_STRING}, - {"ZCPN", RSP_ZCPN, RT_STRING}, - {"ZCON", RSP_ZCON, RT_STRING}, - {"ZAOC", RSP_ZAOC, RT_STRING}, - {"ZCSTR", RSP_ZCSTR, RT_STRING}, - {"ZCFG", RSP_ZCFG, RT_HEX}, - {"ZLOG", RSP_ZLOG, RT_NOTHING}, - {"ZABINFO", RSP_ZABINFO, RT_NOTHING}, - {"ZSMLSTCHG", RSP_ZSMLSTCHG, RT_NOTHING}, + /*{"", RSP_EMPTY, RT_NOTHING},*/ + {"OK", RSP_OK, RT_NOTHING}, + {"ERROR", RSP_ERROR, RT_NOTHING}, + {"ZSAU", RSP_ZSAU, RT_ZSAU}, + {"ZCAU", RSP_ZCAU, RT_ZCAU}, + {"RING", RSP_RING, RT_RING}, + {"ZGCI", RSP_ZGCI, RT_NUMBER}, + {"ZVLS", RSP_ZVLS, RT_NUMBER}, + {"ZCTP", RSP_ZCTP, RT_NUMBER}, + {"ZDLE", RSP_ZDLE, RT_NUMBER}, + {"ZCFGT", RSP_ZCFGT, RT_NUMBER}, + {"ZCCR", RSP_ZCCR, RT_NUMBER}, + {"ZMWI", RSP_ZMWI, RT_NUMBER}, + {"ZHLC", RSP_ZHLC, RT_STRING}, + {"ZBC", RSP_ZBC, RT_STRING}, + {"NMBR", RSP_NMBR, RT_STRING}, + {"ZCPN", RSP_ZCPN, RT_STRING}, + {"ZCON", RSP_ZCON, RT_STRING}, + {"ZAOC", RSP_ZAOC, RT_STRING}, + {"ZCSTR", RSP_ZCSTR, RT_STRING}, + {"ZCFG", RSP_ZCFG, RT_HEX}, + {"ZLOG", RSP_ZLOG, RT_NOTHING}, + {"ZABINFO", RSP_ZABINFO, RT_NOTHING}, + {"ZSMLSTCHG", RSP_ZSMLSTCHG, RT_NOTHING}, {NULL,0,0} }; @@ -446,9 +442,7 @@ static int isdn_getnum(char *p) { int v = -1; - IFNULLRETVAL(p, -1); - - dbg(DEBUG_TRANSCMD, "string: %s", p); + gig_dbg(DEBUG_TRANSCMD, "string: %s", p); while (*p >= '0' && *p <= '9') v = ((v < 0) ? 0 : (v * 10)) + (int) ((*p++) - '0'); @@ -465,9 +459,7 @@ static int isdn_gethex(char *p) int v = 0; int c; - IFNULLRETVAL(p, -1); - - dbg(DEBUG_TRANSCMD, "string: %s", p); + gig_dbg(DEBUG_TRANSCMD, "string: %s", p); if (!*p) return -1; @@ -490,14 +482,6 @@ static int isdn_gethex(char *p) return v; } -static inline void new_index(atomic_t *index, int max) -{ - if (atomic_read(index) == max) //FIXME race? - atomic_set(index, 0); - else - atomic_inc(index); -} - /* retrieve CID from parsed response * returns 0 if no CID, -1 if invalid CID, or CID value 1..65535 */ @@ -536,16 +520,14 @@ void gigaset_handle_modem_response(struct cardstate *cs) int cid; int rawstring; - IFNULLRET(cs); - len = cs->cbytes; if (!len) { /* ignore additional LFs/CRs (M10x config mode or cx100) */ - dbg(DEBUG_MCMD, "skipped EOL [%02X]", cs->respdata[len]); + gig_dbg(DEBUG_MCMD, "skipped EOL [%02X]", cs->respdata[len]); return; } cs->respdata[len] = 0; - dbg(DEBUG_TRANSCMD, "raw string: '%s'", cs->respdata); + gig_dbg(DEBUG_TRANSCMD, "raw string: '%s'", cs->respdata); argv[0] = cs->respdata; params = 1; if (cs->at_state.getstring) { @@ -561,7 +543,8 @@ void gigaset_handle_modem_response(struct cardstate *cs) case ',': case '=': if (params > MAX_REC_PARAMS) { - warn("too many parameters in response"); + dev_warn(cs->dev, + "too many parameters in response\n"); /* need last parameter (might be CID) */ params--; } @@ -572,33 +555,33 @@ void gigaset_handle_modem_response(struct cardstate *cs) cid = params > 1 ? cid_of_response(argv[params-1]) : 0; if (cid < 0) { gigaset_add_event(cs, &cs->at_state, RSP_INVAL, - NULL, 0, NULL); + NULL, 0, NULL); return; } for (j = 1; j < params; ++j) argv[j][-1] = 0; - dbg(DEBUG_TRANSCMD, "CMD received: %s", argv[0]); + gig_dbg(DEBUG_TRANSCMD, "CMD received: %s", argv[0]); if (cid) { --params; - dbg(DEBUG_TRANSCMD, "CID: %s", argv[params]); + gig_dbg(DEBUG_TRANSCMD, "CID: %s", argv[params]); } - dbg(DEBUG_TRANSCMD, "available params: %d", params - 1); + gig_dbg(DEBUG_TRANSCMD, "available params: %d", params - 1); for (j = 1; j < params; j++) - dbg(DEBUG_TRANSCMD, "param %d: %s", j, argv[j]); + gig_dbg(DEBUG_TRANSCMD, "param %d: %s", j, argv[j]); } spin_lock_irqsave(&cs->ev_lock, flags); - head = atomic_read(&cs->ev_head); - tail = atomic_read(&cs->ev_tail); + head = cs->ev_head; + tail = cs->ev_tail; abort = 1; curarg = 0; while (curarg < params) { next = (tail + 1) % MAX_EVENTS; if (unlikely(next == head)) { - err("event queue full"); + dev_err(cs->dev, "event queue full\n"); break; } @@ -619,8 +602,9 @@ void gigaset_handle_modem_response(struct cardstate *cs) if (!rt->response) { event->type = RSP_UNKNOWN; - warn("unknown modem response: %s", - argv[curarg]); + dev_warn(cs->dev, + "unknown modem response: %s\n", + argv[curarg]); break; } @@ -636,7 +620,8 @@ void gigaset_handle_modem_response(struct cardstate *cs) break; case RT_RING: if (!cid) { - err("received RING without CID!"); + dev_err(cs->dev, + "received RING without CID!\n"); event->type = RSP_INVAL; abort = 1; } else { @@ -664,27 +649,25 @@ void gigaset_handle_modem_response(struct cardstate *cs) event->parameter = ZSAU_DISCONNECT_REQ; else { event->parameter = ZSAU_UNKNOWN; - warn("%s: unknown parameter %s after ZSAU", - __func__, argv[curarg]); + dev_warn(cs->dev, + "%s: unknown parameter %s after ZSAU\n", + __func__, argv[curarg]); } ++curarg; break; case RT_STRING: if (curarg < params) { - len = strlen(argv[curarg]) + 1; - event->ptr = kmalloc(len, GFP_ATOMIC); - if (event->ptr) - memcpy(event->ptr, argv[curarg], len); - else - err("no memory for string!"); + event->ptr = kstrdup(argv[curarg], GFP_ATOMIC); + if (!event->ptr) + dev_err(cs->dev, "out of memory\n"); ++curarg; } #ifdef CONFIG_GIGASET_DEBUG if (!event->ptr) - dbg(DEBUG_CMD, "string==NULL"); + gig_dbg(DEBUG_CMD, "string==NULL"); else - dbg(DEBUG_CMD, - "string==%s", (char *) event->ptr); + gig_dbg(DEBUG_CMD, "string==%s", + (char *) event->ptr); #endif break; case RT_ZCAU: @@ -694,7 +677,7 @@ void gigaset_handle_modem_response(struct cardstate *cs) j = isdn_gethex(argv[curarg + 1]); if (i >= 0 && i < 256 && j >= 0 && j < 256) event->parameter = (unsigned) i << 8 - | j; + | j; curarg += 2; } else curarg = params - 1; @@ -712,7 +695,7 @@ void gigaset_handle_modem_response(struct cardstate *cs) } else event->parameter = -1; #ifdef CONFIG_GIGASET_DEBUG - dbg(DEBUG_CMD, "parameter==%d", event->parameter); + gig_dbg(DEBUG_CMD, "parameter==%d", event->parameter); #endif break; } @@ -724,12 +707,13 @@ void gigaset_handle_modem_response(struct cardstate *cs) break; } - atomic_set(&cs->ev_tail, tail); + cs->ev_tail = tail; spin_unlock_irqrestore(&cs->ev_lock, flags); if (curarg != params) - dbg(DEBUG_ANY, "invalid number of processed parameters: %d/%d", - curarg, params); + gig_dbg(DEBUG_ANY, + "invalid number of processed parameters: %d/%d", + curarg, params); } EXPORT_SYMBOL_GPL(gigaset_handle_modem_response); @@ -739,23 +723,19 @@ EXPORT_SYMBOL_GPL(gigaset_handle_modem_response); static void disconnect(struct at_state_t **at_state_p) { unsigned long flags; - struct bc_state *bcs; - struct cardstate *cs; + struct bc_state *bcs = (*at_state_p)->bcs; + struct cardstate *cs = (*at_state_p)->cs; - IFNULLRET(at_state_p); - IFNULLRET(*at_state_p); - bcs = (*at_state_p)->bcs; - cs = (*at_state_p)->cs; - IFNULLRET(cs); - - new_index(&(*at_state_p)->seq_index, MAX_SEQ_INDEX); + spin_lock_irqsave(&cs->lock, flags); + ++(*at_state_p)->seq_index; /* revert to selected idle mode */ - if (!atomic_read(&cs->cidmode)) { + if (!cs->cidmode) { cs->at_state.pending_commands |= PC_UMMODE; atomic_set(&cs->commands_pending, 1); //FIXME - dbg(DEBUG_CMD, "Scheduling PC_UMMODE"); + gig_dbg(DEBUG_CMD, "Scheduling PC_UMMODE"); } + spin_unlock_irqrestore(&cs->lock, flags); if (bcs) { /* B channel assigned: invoke hardware specific handler */ @@ -777,7 +757,7 @@ static void disconnect(struct at_state_t **at_state_p) * The structure should be freed by calling disconnect() after use. */ static inline struct at_state_t *get_free_channel(struct cardstate *cs, - int cid) + int cid) /* cids: >0: siemens-cid 0: without cid -1: no cid assigned yet @@ -826,7 +806,7 @@ static void init_failed(struct cardstate *cs, int mode) static void schedule_init(struct cardstate *cs, int state) { if (cs->at_state.pending_commands & PC_INIT) { - dbg(DEBUG_CMD, "not scheduling PC_INIT again"); + gig_dbg(DEBUG_CMD, "not scheduling PC_INIT again"); return; } atomic_set(&cs->mstate, state); @@ -834,52 +814,56 @@ static void schedule_init(struct cardstate *cs, int state) gigaset_block_channels(cs); cs->at_state.pending_commands |= PC_INIT; atomic_set(&cs->commands_pending, 1); - dbg(DEBUG_CMD, "Scheduling PC_INIT"); + gig_dbg(DEBUG_CMD, "Scheduling PC_INIT"); } -/* Add "AT" to a command, add the cid, dle encode it, send the result to the hardware. */ +/* Add "AT" to a command, add the cid, dle encode it, send the result to the + hardware. */ static void send_command(struct cardstate *cs, const char *cmd, int cid, - int dle, gfp_t kmallocflags) + int dle, gfp_t kmallocflags) { size_t cmdlen, buflen; char *cmdpos, *cmdbuf, *cmdtail; cmdlen = strlen(cmd); buflen = 11 + cmdlen; + if (unlikely(buflen <= cmdlen)) { + dev_err(cs->dev, "integer overflow in buflen\n"); + return; + } - if (likely(buflen > cmdlen)) { - cmdbuf = kmalloc(buflen, kmallocflags); - if (likely(cmdbuf != NULL)) { - cmdpos = cmdbuf + 9; - cmdtail = cmdpos + cmdlen; - memcpy(cmdpos, cmd, cmdlen); - - if (cid > 0 && cid <= 65535) { - do { - *--cmdpos = '0' + cid % 10; - cid /= 10; - ++cmdlen; - } while (cid); - } + cmdbuf = kmalloc(buflen, kmallocflags); + if (unlikely(!cmdbuf)) { + dev_err(cs->dev, "out of memory\n"); + return; + } - cmdlen += 2; - *--cmdpos = 'T'; - *--cmdpos = 'A'; + cmdpos = cmdbuf + 9; + cmdtail = cmdpos + cmdlen; + memcpy(cmdpos, cmd, cmdlen); - if (dle) { - cmdlen += 4; - *--cmdpos = '('; - *--cmdpos = 0x10; - *cmdtail++ = 0x10; - *cmdtail++ = ')'; - } + if (cid > 0 && cid <= 65535) { + do { + *--cmdpos = '0' + cid % 10; + cid /= 10; + ++cmdlen; + } while (cid); + } - cs->ops->write_cmd(cs, cmdpos, cmdlen, NULL); - kfree(cmdbuf); - } else - err("no memory for command buffer"); - } else - err("overflow in buflen"); + cmdlen += 2; + *--cmdpos = 'T'; + *--cmdpos = 'A'; + + if (dle) { + cmdlen += 4; + *--cmdpos = '('; + *--cmdpos = 0x10; + *cmdtail++ = 0x10; + *cmdtail++ = ')'; + } + + cs->ops->write_cmd(cs, cmdpos, cmdlen, NULL); + kfree(cmdbuf); } static struct at_state_t *at_state_from_cid(struct cardstate *cs, int cid) @@ -910,9 +894,6 @@ static struct at_state_t *at_state_from_cid(struct cardstate *cs, int cid) static void bchannel_down(struct bc_state *bcs) { - IFNULLRET(bcs); - IFNULLRET(bcs->cs); - if (bcs->chstate & CHS_B_UP) { bcs->chstate &= ~CHS_B_UP; gigaset_i4l_channel_cmd(bcs, ISDN_STAT_BHUP); @@ -930,16 +911,15 @@ static void bchannel_down(struct bc_state *bcs) static void bchannel_up(struct bc_state *bcs) { - IFNULLRET(bcs); - if (!(bcs->chstate & CHS_D_UP)) { - notice("%s: D channel not up", __func__); + dev_notice(bcs->cs->dev, "%s: D channel not up\n", __func__); bcs->chstate |= CHS_D_UP; gigaset_i4l_channel_cmd(bcs, ISDN_STAT_DCONN); } if (bcs->chstate & CHS_B_UP) { - notice("%s: B channel already up", __func__); + dev_notice(bcs->cs->dev, "%s: B channel already up\n", + __func__); return; } @@ -947,17 +927,21 @@ static void bchannel_up(struct bc_state *bcs) gigaset_i4l_channel_cmd(bcs, ISDN_STAT_BCONN); } -static void start_dial(struct at_state_t *at_state, void *data, int seq_index) +static void start_dial(struct at_state_t *at_state, void *data, unsigned seq_index) { struct bc_state *bcs = at_state->bcs; struct cardstate *cs = at_state->cs; int retval; + unsigned long flags; bcs->chstate |= CHS_NOTIFY_LL; - //atomic_set(&bcs->status, BCS_INIT); - if (atomic_read(&at_state->seq_index) != seq_index) + spin_lock_irqsave(&cs->lock, flags); + if (at_state->seq_index != seq_index) { + spin_unlock_irqrestore(&cs->lock, flags); goto error; + } + spin_unlock_irqrestore(&cs->lock, flags); retval = gigaset_isdn_setup_dial(at_state, data); if (retval != 0) @@ -965,20 +949,14 @@ static void start_dial(struct at_state_t *at_state, void *data, int seq_index) at_state->pending_commands |= PC_CID; - dbg(DEBUG_CMD, "Scheduling PC_CID"); -//#ifdef GIG_MAYINITONDIAL -// if (atomic_read(&cs->MState) == MS_UNKNOWN) { -// cs->at_state.pending_commands |= PC_INIT; -// dbg(DEBUG_CMD, "Scheduling PC_INIT"); -// } -//#endif - atomic_set(&cs->commands_pending, 1); //FIXME + gig_dbg(DEBUG_CMD, "Scheduling PC_CID"); + atomic_set(&cs->commands_pending, 1); return; error: at_state->pending_commands |= PC_NOCID; - dbg(DEBUG_CMD, "Scheduling PC_NOCID"); - atomic_set(&cs->commands_pending, 1); //FIXME + gig_dbg(DEBUG_CMD, "Scheduling PC_NOCID"); + atomic_set(&cs->commands_pending, 1); return; } @@ -991,13 +969,13 @@ static void start_accept(struct at_state_t *at_state) if (retval == 0) { at_state->pending_commands |= PC_ACCEPT; - dbg(DEBUG_CMD, "Scheduling PC_ACCEPT"); - atomic_set(&cs->commands_pending, 1); //FIXME + gig_dbg(DEBUG_CMD, "Scheduling PC_ACCEPT"); + atomic_set(&cs->commands_pending, 1); } else { //FIXME at_state->pending_commands |= PC_HUP; - dbg(DEBUG_CMD, "Scheduling PC_HUP"); - atomic_set(&cs->commands_pending, 1); //FIXME + gig_dbg(DEBUG_CMD, "Scheduling PC_HUP"); + atomic_set(&cs->commands_pending, 1); } } @@ -1008,9 +986,10 @@ static void do_start(struct cardstate *cs) if (atomic_read(&cs->mstate) != MS_LOCKED) schedule_init(cs, MS_INIT); + cs->isdn_up = 1; gigaset_i4l_cmd(cs, ISDN_STAT_RUN); - // FIXME: not in locked mode - // FIXME 2: only after init sequence + // FIXME: not in locked mode + // FIXME 2: only after init sequence cs->waiting = 0; wake_up(&cs->waitqueue); @@ -1023,6 +1002,12 @@ static void finish_shutdown(struct cardstate *cs) atomic_set(&cs->mode, M_UNKNOWN); } + /* Tell the LL that the device is not available .. */ + if (cs->isdn_up) { + cs->isdn_up = 0; + gigaset_i4l_cmd(cs, ISDN_STAT_STOP); + } + /* The rest is done by cleanup_cs () in user mode. */ cs->cmd_result = -ENODEV; @@ -1037,15 +1022,20 @@ static void do_shutdown(struct cardstate *cs) if (atomic_read(&cs->mstate) == MS_READY) { atomic_set(&cs->mstate, MS_SHUTDOWN); cs->at_state.pending_commands |= PC_SHUTDOWN; - atomic_set(&cs->commands_pending, 1); //FIXME - dbg(DEBUG_CMD, "Scheduling PC_SHUTDOWN"); //FIXME - //gigaset_schedule_event(cs); //FIXME + atomic_set(&cs->commands_pending, 1); + gig_dbg(DEBUG_CMD, "Scheduling PC_SHUTDOWN"); } else finish_shutdown(cs); } static void do_stop(struct cardstate *cs) { + unsigned long flags; + + spin_lock_irqsave(&cs->lock, flags); + cs->connected = 0; + spin_unlock_irqrestore(&cs->lock, flags); + do_shutdown(cs); } @@ -1069,9 +1059,11 @@ static int reinit_and_retry(struct cardstate *cs, int channel) return 0; if (channel < 0) - warn("Could not enter cid mode. Reinit device and try again."); + dev_warn(cs->dev, + "Could not enter cid mode. Reinit device and try again.\n"); else { - warn("Could not get a call id. Reinit device and try again."); + dev_warn(cs->dev, + "Could not get a call id. Reinit device and try again.\n"); cs->bcs[channel].at_state.pending_commands |= PC_CID; } schedule_init(cs, MS_INIT); @@ -1079,7 +1071,7 @@ static int reinit_and_retry(struct cardstate *cs, int channel) } static int at_state_invalid(struct cardstate *cs, - struct at_state_t *test_ptr) + struct at_state_t *test_ptr) { unsigned long flags; unsigned channel; @@ -1116,7 +1108,7 @@ static void handle_icall(struct cardstate *cs, struct bc_state *bcs, case ICALL_ACCEPT: break; default: - err("internal error: disposition=%d", retval); + dev_err(cs->dev, "internal error: disposition=%d\n", retval); /* --v-- fall through --v-- */ case ICALL_IGNORE: case ICALL_REJECT: @@ -1160,7 +1152,6 @@ static int do_lock(struct cardstate *cs) mode = atomic_read(&cs->mode); atomic_set(&cs->mstate, MS_LOCKED); atomic_set(&cs->mode, M_UNKNOWN); - //FIXME reset card state / at states / bcs states return mode; } @@ -1173,8 +1164,7 @@ static int do_unlock(struct cardstate *cs) atomic_set(&cs->mstate, MS_UNINITIALIZED); atomic_set(&cs->mode, M_UNKNOWN); gigaset_free_channels(cs); - //FIXME reset card state / at states / bcs states - if (atomic_read(&cs->connected)) + if (cs->connected) schedule_init(cs, MS_INIT); return 0; @@ -1203,21 +1193,23 @@ static void do_action(int action, struct cardstate *cs, at_state->waiting = 1; break; case ACT_INIT: - //FIXME setup everything cs->at_state.pending_commands &= ~PC_INIT; cs->cur_at_seq = SEQ_NONE; atomic_set(&cs->mode, M_UNIMODEM); - if (!atomic_read(&cs->cidmode)) { + spin_lock_irqsave(&cs->lock, flags); + if (!cs->cidmode) { + spin_unlock_irqrestore(&cs->lock, flags); gigaset_free_channels(cs); atomic_set(&cs->mstate, MS_READY); break; } + spin_unlock_irqrestore(&cs->lock, flags); cs->at_state.pending_commands |= PC_CIDMODE; - atomic_set(&cs->commands_pending, 1); //FIXME - dbg(DEBUG_CMD, "Scheduling PC_CIDMODE"); + atomic_set(&cs->commands_pending, 1); + gig_dbg(DEBUG_CMD, "Scheduling PC_CIDMODE"); break; case ACT_FAILINIT: - warn("Could not initialize the device."); + dev_warn(cs->dev, "Could not initialize the device.\n"); cs->dle = 0; init_failed(cs, M_UNKNOWN); cs->cur_at_seq = SEQ_NONE; @@ -1273,8 +1265,8 @@ static void do_action(int action, struct cardstate *cs, /* get fresh AT state structure for new CID */ at_state2 = get_free_channel(cs, ev->parameter); if (!at_state2) { - warn("RING ignored: " - "could not allocate channel structure"); + dev_warn(cs->dev, + "RING ignored: could not allocate channel structure\n"); break; } @@ -1302,7 +1294,7 @@ static void do_action(int action, struct cardstate *cs, at_state = *p_at_state; break; case ACT_FAILSDOWN: - warn("Could not shut down the device."); + dev_warn(cs->dev, "Could not shut down the device.\n"); /* fall through */ case ACT_FAKESDOWN: case ACT_SDOWN: @@ -1355,7 +1347,7 @@ static void do_action(int action, struct cardstate *cs, break; case ACT_ABORTHUP: cs->cur_at_seq = SEQ_NONE; - warn("Could not hang up."); + dev_warn(cs->dev, "Could not hang up.\n"); at_state->cid = -1; if (bcs && cs->onechannel) at_state->pending_commands |= PC_DLE0; @@ -1367,14 +1359,15 @@ static void do_action(int action, struct cardstate *cs, break; case ACT_FAILDLE0: cs->cur_at_seq = SEQ_NONE; - warn("Could not leave DLE mode."); + dev_warn(cs->dev, "Could not leave DLE mode.\n"); at_state2 = &cs->bcs[cs->curchannel].at_state; disconnect(&at_state2); schedule_init(cs, MS_RECOVER); break; case ACT_FAILDLE1: cs->cur_at_seq = SEQ_NONE; - warn("Could not enter DLE mode. Try to hang up."); + dev_warn(cs->dev, + "Could not enter DLE mode. Trying to hang up.\n"); channel = cs->curchannel; cs->bcs[channel].at_state.pending_commands |= PC_HUP; atomic_set(&cs->commands_pending, 1); @@ -1395,7 +1388,8 @@ static void do_action(int action, struct cardstate *cs, cs->cur_at_seq = SEQ_NONE; channel = cs->curchannel; if (!reinit_and_retry(cs, channel)) { - warn("Could not get a call id. Dialing not possible"); + dev_warn(cs->dev, + "Could not get a call ID. Cannot dial.\n"); at_state2 = &cs->bcs[channel].at_state; disconnect(&at_state2); } @@ -1428,7 +1422,8 @@ static void do_action(int action, struct cardstate *cs, at_state->pending_commands |= PC_HUP; atomic_set(&cs->commands_pending, 1); break; - case ACT_GETSTRING: /* warning: RING, ZDLE, ... are not handled properly any more */ + case ACT_GETSTRING: /* warning: RING, ZDLE, ... + are not handled properly anymore */ at_state->getstring = 1; break; case ACT_SETVER: @@ -1469,16 +1464,16 @@ static void do_action(int action, struct cardstate *cs, case ACT_GOTVER: if (cs->gotfwver == 0) { cs->gotfwver = 1; - dbg(DEBUG_ANY, - "firmware version %02d.%03d.%02d.%02d", - cs->fwver[0], cs->fwver[1], - cs->fwver[2], cs->fwver[3]); + gig_dbg(DEBUG_ANY, + "firmware version %02d.%03d.%02d.%02d", + cs->fwver[0], cs->fwver[1], + cs->fwver[2], cs->fwver[3]); break; } /* fall through */ case ACT_FAILVER: cs->gotfwver = -1; - err("could not read firmware version."); + dev_err(cs->dev, "could not read firmware version.\n"); break; #ifdef CONFIG_GIGASET_DEBUG case ACT_ERROR: @@ -1496,16 +1491,16 @@ static void do_action(int action, struct cardstate *cs, break; #endif case ACT_DEBUG: - dbg(DEBUG_ANY, "%s: resp_code %d in ConState %d", + gig_dbg(DEBUG_ANY, "%s: resp_code %d in ConState %d", __func__, ev->type, at_state->ConState); break; case ACT_WARN: - warn("%s: resp_code %d in ConState %d!", - __func__, ev->type, at_state->ConState); + dev_warn(cs->dev, "%s: resp_code %d in ConState %d!\n", + __func__, ev->type, at_state->ConState); break; case ACT_ZCAU: - warn("cause code %04x in connection state %d.", - ev->parameter, at_state->ConState); + dev_warn(cs->dev, "cause code %04x in connection state %d.\n", + ev->parameter, at_state->ConState); break; /* events from the LL */ @@ -1516,14 +1511,14 @@ static void do_action(int action, struct cardstate *cs, start_accept(at_state); break; case ACT_PROTO_L2: - dbg(DEBUG_CMD, - "set protocol to %u", (unsigned) ev->parameter); + gig_dbg(DEBUG_CMD, "set protocol to %u", + (unsigned) ev->parameter); at_state->bcs->proto2 = ev->parameter; break; case ACT_HUP: at_state->pending_commands |= PC_HUP; - atomic_set(&cs->commands_pending, 1); //FIXME - dbg(DEBUG_CMD, "Scheduling PC_HUP"); + atomic_set(&cs->commands_pending, 1); + gig_dbg(DEBUG_CMD, "Scheduling PC_HUP"); break; /* hotplug events */ @@ -1555,17 +1550,19 @@ static void do_action(int action, struct cardstate *cs, /* events from the proc file system */ // FIXME without ACT_xxxx? case ACT_PROC_CIDMODE: - if (ev->parameter != atomic_read(&cs->cidmode)) { - atomic_set(&cs->cidmode, ev->parameter); + spin_lock_irqsave(&cs->lock, flags); + if (ev->parameter != cs->cidmode) { + cs->cidmode = ev->parameter; if (ev->parameter) { cs->at_state.pending_commands |= PC_CIDMODE; - dbg(DEBUG_CMD, "Scheduling PC_CIDMODE"); + gig_dbg(DEBUG_CMD, "Scheduling PC_CIDMODE"); } else { cs->at_state.pending_commands |= PC_UMMODE; - dbg(DEBUG_CMD, "Scheduling PC_UMMODE"); + gig_dbg(DEBUG_CMD, "Scheduling PC_UMMODE"); } atomic_set(&cs->commands_pending, 1); } + spin_unlock_irqrestore(&cs->lock, flags); cs->waiting = 0; wake_up(&cs->waitqueue); break; @@ -1590,7 +1587,7 @@ static void do_action(int action, struct cardstate *cs, *p_resp_code = RSP_NULL; } } else - err("%s: action==%d!", __func__, action); + dev_err(cs->dev, "%s: action==%d!\n", __func__, action); } } @@ -1609,47 +1606,46 @@ static void process_event(struct cardstate *cs, struct event_t *ev) int curact; unsigned long flags; - IFNULLRET(cs); - IFNULLRET(ev); - if (ev->cid >= 0) { at_state = at_state_from_cid(cs, ev->cid); if (!at_state) { gigaset_add_event(cs, &cs->at_state, RSP_WRONG_CID, - NULL, 0, NULL); + NULL, 0, NULL); return; } } else { at_state = ev->at_state; if (at_state_invalid(cs, at_state)) { - dbg(DEBUG_ANY, - "event for invalid at_state %p", at_state); + gig_dbg(DEBUG_ANY, "event for invalid at_state %p", + at_state); return; } } - dbg(DEBUG_CMD, - "connection state %d, event %d", at_state->ConState, ev->type); + gig_dbg(DEBUG_CMD, "connection state %d, event %d", + at_state->ConState, ev->type); bcs = at_state->bcs; sendcid = at_state->cid; /* Setting the pointer to the dial array */ rep = at_state->replystruct; - IFNULLRET(rep); + spin_lock_irqsave(&cs->lock, flags); if (ev->type == EV_TIMEOUT) { - if (ev->parameter != atomic_read(&at_state->timer_index) + if (ev->parameter != at_state->timer_index || !at_state->timer_active) { ev->type = RSP_NONE; /* old timeout */ - dbg(DEBUG_ANY, "old timeout"); + gig_dbg(DEBUG_ANY, "old timeout"); } else if (!at_state->waiting) - dbg(DEBUG_ANY, "timeout occured"); + gig_dbg(DEBUG_ANY, "timeout occurred"); else - dbg(DEBUG_ANY, "stopped waiting"); + gig_dbg(DEBUG_ANY, "stopped waiting"); } + spin_unlock_irqrestore(&cs->lock, flags); - /* if the response belongs to a variable in at_state->int_var[VAR_XXXX] or at_state->str_var[STR_XXXX], set it */ + /* if the response belongs to a variable in at_state->int_var[VAR_XXXX] + or at_state->str_var[STR_XXXX], set it */ if (ev->type >= RSP_VAR && ev->type < RSP_VAR + VAR_NUM) { index = ev->type - RSP_VAR; at_state->int_var[index] = ev->parameter; @@ -1657,20 +1653,22 @@ static void process_event(struct cardstate *cs, struct event_t *ev) index = ev->type - RSP_STR; kfree(at_state->str_var[index]); at_state->str_var[index] = ev->ptr; - ev->ptr = NULL; /* prevent process_events() from deallocating ptr */ + ev->ptr = NULL; /* prevent process_events() from + deallocating ptr */ } if (ev->type == EV_TIMEOUT || ev->type == RSP_STRING) at_state->getstring = 0; - /* Search row in dial array which matches modem response and current constate */ + /* Search row in dial array which matches modem response and current + constate */ for (;; rep++) { rcode = rep->resp_code; - /* dbg (DEBUG_ANY, "rcode %d", rcode); */ if (rcode == RSP_LAST) { /* found nothing...*/ - warn("%s: rcode=RSP_LAST: resp_code %d in ConState %d!", - __func__, ev->type, at_state->ConState); + dev_warn(cs->dev, "%s: rcode=RSP_LAST: " + "resp_code %d in ConState %d!\n", + __func__, ev->type, at_state->ConState); return; } if ((rcode == RSP_ANY || rcode == ev->type) @@ -1706,14 +1704,14 @@ static void process_event(struct cardstate *cs, struct event_t *ev) } else { /* Send command to modem if not NULL... */ if (p_command/*rep->command*/) { - if (atomic_read(&cs->connected)) + if (cs->connected) send_command(cs, p_command, - sendcid, cs->dle, - GFP_ATOMIC); + sendcid, cs->dle, + GFP_ATOMIC); else gigaset_add_event(cs, at_state, - RSP_NODEV, - NULL, 0, NULL); + RSP_NODEV, + NULL, 0, NULL); } spin_lock_irqsave(&cs->lock, flags); @@ -1723,8 +1721,7 @@ static void process_event(struct cardstate *cs, struct event_t *ev) } else if (rep->timeout > 0) { /* new timeout */ at_state->timer_expires = rep->timeout * 10; at_state->timer_active = 1; - new_index(&at_state->timer_index, - MAX_TIMER_INDEX); + ++at_state->timer_index; } spin_unlock_irqrestore(&cs->lock, flags); } @@ -1744,17 +1741,16 @@ static void process_command_flags(struct cardstate *cs) struct bc_state *bcs; int i; int sequence; - - IFNULLRET(cs); + unsigned long flags; atomic_set(&cs->commands_pending, 0); if (cs->cur_at_seq) { - dbg(DEBUG_CMD, "not searching scheduled commands: busy"); + gig_dbg(DEBUG_CMD, "not searching scheduled commands: busy"); return; } - dbg(DEBUG_CMD, "searching scheduled commands"); + gig_dbg(DEBUG_CMD, "searching scheduled commands"); sequence = SEQ_NONE; @@ -1795,8 +1791,9 @@ static void process_command_flags(struct cardstate *cs) } /* only switch back to unimodem mode, if no commands are pending and no channels are up */ + spin_lock_irqsave(&cs->lock, flags); if (cs->at_state.pending_commands == PC_UMMODE - && !atomic_read(&cs->cidmode) + && !cs->cidmode && list_empty(&cs->temp_at_states) && atomic_read(&cs->mode) == M_CID) { sequence = SEQ_UMMODE; @@ -1810,6 +1807,7 @@ static void process_command_flags(struct cardstate *cs) } } } + spin_unlock_irqrestore(&cs->lock, flags); cs->at_state.pending_commands &= ~PC_UMMODE; if (sequence != SEQ_NONE) { schedule_sequence(cs, at_state, sequence); @@ -1865,11 +1863,7 @@ static void process_command_flags(struct cardstate *cs) if (cs->at_state.pending_commands & PC_CIDMODE) { cs->at_state.pending_commands &= ~PC_CIDMODE; if (atomic_read(&cs->mode) == M_UNIMODEM) { -#if 0 - cs->retry_count = 2; -#else cs->retry_count = 1; -#endif schedule_sequence(cs, &cs->at_state, SEQ_CIDMODE); return; } @@ -1897,7 +1891,7 @@ static void process_command_flags(struct cardstate *cs) switch (atomic_read(&cs->mode)) { case M_UNIMODEM: cs->at_state.pending_commands |= PC_CIDMODE; - dbg(DEBUG_CMD, "Scheduling PC_CIDMODE"); + gig_dbg(DEBUG_CMD, "Scheduling PC_CIDMODE"); atomic_set(&cs->commands_pending, 1); return; #ifdef GIG_MAYINITONDIAL @@ -1926,18 +1920,21 @@ static void process_events(struct cardstate *cs) int i; int check_flags = 0; int was_busy; + unsigned long flags; - /* no locking needed (only one reader) */ - head = atomic_read(&cs->ev_head); + spin_lock_irqsave(&cs->ev_lock, flags); + head = cs->ev_head; for (i = 0; i < 2 * MAX_EVENTS; ++i) { - tail = atomic_read(&cs->ev_tail); + tail = cs->ev_tail; if (tail == head) { if (!check_flags && !atomic_read(&cs->commands_pending)) break; check_flags = 0; + spin_unlock_irqrestore(&cs->ev_lock, flags); process_command_flags(cs); - tail = atomic_read(&cs->ev_tail); + spin_lock_irqsave(&cs->ev_lock, flags); + tail = cs->ev_tail; if (tail == head) { if (!atomic_read(&cs->commands_pending)) break; @@ -1947,18 +1944,23 @@ static void process_events(struct cardstate *cs) ev = cs->events + head; was_busy = cs->cur_at_seq != SEQ_NONE; + spin_unlock_irqrestore(&cs->ev_lock, flags); process_event(cs, ev); + spin_lock_irqsave(&cs->ev_lock, flags); kfree(ev->ptr); ev->ptr = NULL; if (was_busy && cs->cur_at_seq == SEQ_NONE) check_flags = 1; head = (head + 1) % MAX_EVENTS; - atomic_set(&cs->ev_head, head); + cs->ev_head = head; } + spin_unlock_irqrestore(&cs->ev_lock, flags); + if (i == 2 * MAX_EVENTS) { - err("infinite loop in process_events; aborting."); + dev_err(cs->dev, + "infinite loop in process_events; aborting.\n"); } } @@ -1970,12 +1972,9 @@ void gigaset_handle_event(unsigned long data) { struct cardstate *cs = (struct cardstate *) data; - IFNULLRET(cs); - IFNULLRET(cs->inbuf); - /* handle incoming data on control/common channel */ if (atomic_read(&cs->inbuf->head) != atomic_read(&cs->inbuf->tail)) { - dbg(DEBUG_INTR, "processing new data"); + gig_dbg(DEBUG_INTR, "processing new data"); cs->ops->handle_input(cs->inbuf); } diff --git a/drivers/isdn/gigaset/gigaset.h b/drivers/isdn/gigaset/gigaset.h index 729edcd..9d21ba8 100644 --- a/drivers/isdn/gigaset/gigaset.h +++ b/drivers/isdn/gigaset/gigaset.h @@ -1,11 +1,16 @@ -/* Siemens Gigaset 307x driver +/* + * Siemens Gigaset 307x driver * Common header file for all connection variants * - * Written by Stefan Eilers <Eilers.Stefan@epost.de> + * Written by Stefan Eilers * and Hansjoerg Lipp <hjlipp@web.de> * - * Version: $Id: gigaset.h,v 1.97.4.26 2006/02/04 18:28:16 hjlipp Exp $ - * =========================================================================== + * ===================================================================== + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * ===================================================================== */ #ifndef GIGASET_H @@ -15,7 +20,6 @@ #include <linux/kernel.h> #include <linux/compiler.h> #include <linux/types.h> -#include <asm/atomic.h> #include <linux/spinlock.h> #include <linux/isdnif.h> #include <linux/usb.h> @@ -27,21 +31,22 @@ #include <linux/tty.h> #include <linux/tty_driver.h> #include <linux/list.h> +#include <asm/atomic.h> #define GIG_VERSION {0,5,0,0} #define GIG_COMPAT {0,4,0,0} -#define MAX_REC_PARAMS 10 /* Max. number of params in response string */ -#define MAX_RESP_SIZE 512 /* Max. size of a response string */ -#define HW_HDR_LEN 2 /* Header size used to store ack info */ +#define MAX_REC_PARAMS 10 /* Max. number of params in response string */ +#define MAX_RESP_SIZE 512 /* Max. size of a response string */ +#define HW_HDR_LEN 2 /* Header size used to store ack info */ -#define MAX_EVENTS 64 /* size of event queue */ +#define MAX_EVENTS 64 /* size of event queue */ #define RBUFSIZE 8192 -#define SBUFSIZE 4096 /* sk_buff payload size */ +#define SBUFSIZE 4096 /* sk_buff payload size */ -#define MAX_BUF_SIZE (SBUFSIZE - 2) /* Max. size of a data packet from LL */ -#define TRANSBUFSIZE 768 /* bytes per skb for transparent receive */ +#define TRANSBUFSIZE 768 /* bytes per skb for transparent receive */ +#define MAX_BUF_SIZE (SBUFSIZE - 2) /* Max. size of a data packet from LL */ /* compile time options */ #define GIG_MAJOR 0 @@ -50,10 +55,7 @@ #define GIG_RETRYCID #define GIG_X75 -#define MAX_TIMER_INDEX 1000 -#define MAX_SEQ_INDEX 1000 - -#define GIG_TICK (HZ / 10) +#define GIG_TICK 100 /* in milliseconds */ /* timeout values (unit: 1 sec) */ #define INIT_TIMEOUT 1 @@ -67,74 +69,89 @@ #define MAXACT 3 -#define IFNULL(a) if (unlikely(!(a))) -#define IFNULLRET(a) if (unlikely(!(a))) {err("%s==NULL at %s:%d!", #a, __FILE__, __LINE__); return; } -#define IFNULLRETVAL(a,b) if (unlikely(!(a))) {err("%s==NULL at %s:%d!", #a, __FILE__, __LINE__); return (b); } -#define IFNULLCONT(a) if (unlikely(!(a))) {err("%s==NULL at %s:%d!", #a, __FILE__, __LINE__); continue; } -#define IFNULLGOTO(a,b) if (unlikely(!(a))) {err("%s==NULL at %s:%d!", #a, __FILE__, __LINE__); goto b; } - extern int gigaset_debuglevel; /* "needs" cast to (enum debuglevel) */ -/* any combination of these can be given with the 'debug=' parameter to insmod, e.g. - * 'insmod usb_gigaset.o debug=0x2c' will set DEBUG_OPEN, DEBUG_CMD and DEBUG_INTR. */ +/* any combination of these can be given with the 'debug=' parameter to insmod, + * e.g. 'insmod usb_gigaset.o debug=0x2c' will set DEBUG_OPEN, DEBUG_CMD and + * DEBUG_INTR. + */ enum debuglevel { /* up to 24 bits (atomic_t) */ DEBUG_REG = 0x0002, /* serial port I/O register operations */ DEBUG_OPEN = 0x0004, /* open/close serial port */ DEBUG_INTR = 0x0008, /* interrupt processing */ - DEBUG_INTR_DUMP = 0x0010, /* Activating hexdump debug output on interrupt - requests, not available as run-time option */ + DEBUG_INTR_DUMP = 0x0010, /* Activating hexdump debug output on + interrupt requests, not available as + run-time option */ DEBUG_CMD = 0x00020, /* sent/received LL commands */ DEBUG_STREAM = 0x00040, /* application data stream I/O events */ DEBUG_STREAM_DUMP = 0x00080, /* application data stream content */ DEBUG_LLDATA = 0x00100, /* sent/received LL data */ - DEBUG_INTR_0 = 0x00200, /* serial port output interrupt processing */ + DEBUG_INTR_0 = 0x00200, /* serial port interrupt processing */ DEBUG_DRIVER = 0x00400, /* driver structure */ DEBUG_HDLC = 0x00800, /* M10x HDLC processing */ DEBUG_WRITE = 0x01000, /* M105 data write */ - DEBUG_TRANSCMD = 0x02000, /*AT-COMMANDS+RESPONSES*/ - DEBUG_MCMD = 0x04000, /*COMMANDS THAT ARE SENT VERY OFTEN*/ - DEBUG_INIT = 0x08000, /* (de)allocation+initialization of data structures */ + DEBUG_TRANSCMD = 0x02000, /* AT-COMMANDS+RESPONSES */ + DEBUG_MCMD = 0x04000, /* COMMANDS THAT ARE SENT VERY OFTEN */ + DEBUG_INIT = 0x08000, /* (de)allocation+initialization of data + structures */ DEBUG_LOCK = 0x10000, /* semaphore operations */ DEBUG_OUTPUT = 0x20000, /* output to device */ - DEBUG_ISO = 0x40000, /* isochronous transfers */ + DEBUG_ISO = 0x40000, /* isochronous transfers */ DEBUG_IF = 0x80000, /* character device operations */ - DEBUG_USBREQ = 0x100000, /* USB communication (except payload data) */ - DEBUG_LOCKCMD = 0x200000, /* AT commands and responses when MS_LOCKED */ + DEBUG_USBREQ = 0x100000, /* USB communication (except payload + data) */ + DEBUG_LOCKCMD = 0x200000, /* AT commands and responses when + MS_LOCKED */ - DEBUG_ANY = 0x3fffff, /* print message if any of the others is activated */ + DEBUG_ANY = 0x3fffff, /* print message if any of the others is + activated */ }; -#ifdef CONFIG_GIGASET_DEBUG -#define DEBUG_DEFAULT (DEBUG_INIT | DEBUG_TRANSCMD | DEBUG_CMD | DEBUG_USBREQ) -//#define DEBUG_DEFAULT (DEBUG_LOCK | DEBUG_INIT | DEBUG_TRANSCMD | DEBUG_CMD | DEBUF_IF | DEBUG_DRIVER | DEBUG_OUTPUT | DEBUG_INTR) -#else -#define DEBUG_DEFAULT 0 +/* missing from linux/device.h ... */ +#ifndef dev_notice +#define dev_notice(dev, format, arg...) \ + dev_printk(KERN_NOTICE , dev , format , ## arg) #endif -/* redefine syslog macros to prepend module name instead of entire source path */ -/* The space before the comma in ", ##" is needed by gcc 2.95 */ +/* Kernel message macros for situations where dev_printk and friends cannot be + * used for lack of reliable access to a device structure. + * linux/usb.h already contains these but in an obsolete form which clutters + * the log needlessly, and according to the USB maintainer those should be + * removed rather than fixed anyway. + */ +#undef err #undef info -#define info(format, arg...) printk(KERN_INFO "%s: " format "\n", THIS_MODULE ? THIS_MODULE->name : "gigaset_hw" , ## arg) - -#undef notice -#define notice(format, arg...) printk(KERN_NOTICE "%s: " format "\n", THIS_MODULE ? THIS_MODULE->name : "gigaset_hw" , ## arg) - #undef warn -#define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", THIS_MODULE ? THIS_MODULE->name : "gigaset_hw" , ## arg) +#undef notice -#undef err -#define err(format, arg...) printk(KERN_ERR "%s: " format "\n", THIS_MODULE ? THIS_MODULE->name : "gigaset_hw" , ## arg) +#define err(format, arg...) printk(KERN_ERR KBUILD_MODNAME ": " \ + format "\n" , ## arg) +#define info(format, arg...) printk(KERN_INFO KBUILD_MODNAME ": " \ + format "\n" , ## arg) +#define warn(format, arg...) printk(KERN_WARNING KBUILD_MODNAME ": " \ + format "\n" , ## arg) +#define notice(format, arg...) printk(KERN_NOTICE KBUILD_MODNAME ": " \ + format "\n" , ## arg) -#undef dbg #ifdef CONFIG_GIGASET_DEBUG -#define dbg(level, format, arg...) do { if (unlikely(((enum debuglevel)gigaset_debuglevel) & (level))) \ - printk(KERN_DEBUG "%s: " format "\n", THIS_MODULE ? THIS_MODULE->name : "gigaset_hw" , ## arg); } while (0) + +#define gig_dbg(level, format, arg...) \ + do { \ + if (unlikely(((enum debuglevel)gigaset_debuglevel) & (level))) \ + printk(KERN_DEBUG KBUILD_MODNAME ": " format "\n", \ + ## arg); \ + } while (0) +#define DEBUG_DEFAULT (DEBUG_INIT | DEBUG_TRANSCMD | DEBUG_CMD | DEBUG_USBREQ) + #else -#define dbg(level, format, arg...) do {} while (0) + +#define gig_dbg(level, format, arg...) do {} while (0) +#define DEBUG_DEFAULT 0 + #endif void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg, - size_t len, const unsigned char *buf, int from_user); + size_t len, const unsigned char *buf); /* connection state */ #define ZSAU_NONE 0 @@ -148,13 +165,14 @@ void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg, #define ZSAU_UNKNOWN -1 /* USB control transfer requests */ -#define OUT_VENDOR_REQ (USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT) -#define IN_VENDOR_REQ (USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT) +#define OUT_VENDOR_REQ (USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT) +#define IN_VENDOR_REQ (USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT) /* int-in-events 3070 */ #define HD_B1_FLOW_CONTROL 0x80 #define HD_B2_FLOW_CONTROL 0x81 -#define HD_RECEIVEATDATA_ACK (0x35) // 3070 // att: HD_RECEIVE>>AT<<DATA_ACK +#define HD_RECEIVEATDATA_ACK (0x35) // 3070 + // att: HD_RECEIVE>>AT<<DATA_ACK #define HD_READY_SEND_ATDATA (0x36) // 3070 #define HD_OPEN_ATCHANNEL_ACK (0x37) // 3070 #define HD_CLOSE_ATCHANNEL_ACK (0x38) // 3070 @@ -181,17 +199,18 @@ void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg, #define HD_CLOSE_ATCHANNEL (0x29) // 3070 /* USB frames for isochronous transfer */ -#define BAS_FRAMETIME 1 /* number of milliseconds between frames */ -#define BAS_NUMFRAMES 8 /* number of frames per URB */ -#define BAS_MAXFRAME 16 /* allocated bytes per frame */ -#define BAS_NORMFRAME 8 /* send size without flow control */ -#define BAS_HIGHFRAME 10 /* " " with positive flow control */ -#define BAS_LOWFRAME 5 /* " " with negative flow control */ -#define BAS_CORRFRAMES 4 /* flow control multiplicator */ - -#define BAS_INBUFSIZE (BAS_MAXFRAME * BAS_NUMFRAMES) /* size of isochronous input buffer per URB */ -#define BAS_OUTBUFSIZE 4096 /* size of common isochronous output buffer */ -#define BAS_OUTBUFPAD BAS_MAXFRAME /* size of pad area for isochronous output buffer */ +#define BAS_FRAMETIME 1 /* number of milliseconds between frames */ +#define BAS_NUMFRAMES 8 /* number of frames per URB */ +#define BAS_MAXFRAME 16 /* allocated bytes per frame */ +#define BAS_NORMFRAME 8 /* send size without flow control */ +#define BAS_HIGHFRAME 10 /* " " with positive flow control */ +#define BAS_LOWFRAME 5 /* " " with negative flow control */ +#define BAS_CORRFRAMES 4 /* flow control multiplicator */ + +#define BAS_INBUFSIZE (BAS_MAXFRAME * BAS_NUMFRAMES) + /* size of isoc in buf per URB */ +#define BAS_OUTBUFSIZE 4096 /* size of common isoc out buffer */ +#define BAS_OUTBUFPAD BAS_MAXFRAME /* size of pad area for isoc out buf */ #define BAS_INURBS 3 #define BAS_OUTURBS 3 @@ -207,40 +226,40 @@ void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg, #define AT_NUM 7 /* variables in struct at_state_t */ -#define VAR_ZSAU 0 -#define VAR_ZDLE 1 -#define VAR_ZVLS 2 -#define VAR_ZCTP 3 -#define VAR_NUM 4 - -#define STR_NMBR 0 -#define STR_ZCPN 1 -#define STR_ZCON 2 -#define STR_ZBC 3 -#define STR_ZHLC 4 -#define STR_NUM 5 - -#define EV_TIMEOUT -105 -#define EV_IF_VER -106 -#define EV_PROC_CIDMODE -107 -#define EV_SHUTDOWN -108 -#define EV_START -110 -#define EV_STOP -111 -#define EV_IF_LOCK -112 -#define EV_PROTO_L2 -113 -#define EV_ACCEPT -114 -#define EV_DIAL -115 -#define EV_HUP -116 -#define EV_BC_OPEN -117 -#define EV_BC_CLOSED -118 +#define VAR_ZSAU 0 +#define VAR_ZDLE 1 +#define VAR_ZVLS 2 +#define VAR_ZCTP 3 +#define VAR_NUM 4 + +#define STR_NMBR 0 +#define STR_ZCPN 1 +#define STR_ZCON 2 +#define STR_ZBC 3 +#define STR_ZHLC 4 +#define STR_NUM 5 + +#define EV_TIMEOUT -105 +#define EV_IF_VER -106 +#define EV_PROC_CIDMODE -107 +#define EV_SHUTDOWN -108 +#define EV_START -110 +#define EV_STOP -111 +#define EV_IF_LOCK -112 +#define EV_PROTO_L2 -113 +#define EV_ACCEPT -114 +#define EV_DIAL -115 +#define EV_HUP -116 +#define EV_BC_OPEN -117 +#define EV_BC_CLOSED -118 /* input state */ -#define INS_command 0x0001 -#define INS_DLE_char 0x0002 -#define INS_byte_stuff 0x0004 -#define INS_have_data 0x0008 -#define INS_skip_frame 0x0010 -#define INS_DLE_command 0x0020 +#define INS_command 0x0001 +#define INS_DLE_char 0x0002 +#define INS_byte_stuff 0x0004 +#define INS_have_data 0x0008 +#define INS_skip_frame 0x0010 +#define INS_DLE_command 0x0020 #define INS_flag_hunt 0x0040 /* channel state */ @@ -248,27 +267,27 @@ void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg, #define CHS_B_UP 0x02 #define CHS_NOTIFY_LL 0x04 -#define ICALL_REJECT 0 -#define ICALL_ACCEPT 1 -#define ICALL_IGNORE 2 +#define ICALL_REJECT 0 +#define ICALL_ACCEPT 1 +#define ICALL_IGNORE 2 /* device state */ -#define MS_UNINITIALIZED 0 -#define MS_INIT 1 -#define MS_LOCKED 2 -#define MS_SHUTDOWN 3 -#define MS_RECOVER 4 -#define MS_READY 5 +#define MS_UNINITIALIZED 0 +#define MS_INIT 1 +#define MS_LOCKED 2 +#define MS_SHUTDOWN 3 +#define MS_RECOVER 4 +#define MS_READY 5 /* mode */ -#define M_UNKNOWN 0 -#define M_CONFIG 1 -#define M_UNIMODEM 2 -#define M_CID 3 +#define M_UNKNOWN 0 +#define M_CONFIG 1 +#define M_UNIMODEM 2 +#define M_CID 3 /* start mode */ -#define SM_LOCKED 0 -#define SM_ISDN 1 /* default */ +#define SM_LOCKED 0 +#define SM_ISDN 1 /* default */ struct gigaset_ops; struct gigaset_driver; @@ -283,27 +302,26 @@ struct ser_bc_state; struct bas_bc_state; struct reply_t { - int resp_code; /* RSP_XXXX */ - int min_ConState; /* <0 => ignore */ - int max_ConState; /* <0 => ignore */ - int parameter; /* e.g. ZSAU_XXXX <0: ignore*/ - int new_ConState; /* <0 => ignore */ - int timeout; /* >0 => *HZ; <=0 => TOUT_XXXX*/ - int action[MAXACT]; /* ACT_XXXX */ - char *command; /* NULL==none */ + int resp_code; /* RSP_XXXX */ + int min_ConState; /* <0 => ignore */ + int max_ConState; /* <0 => ignore */ + int parameter; /* e.g. ZSAU_XXXX <0: ignore*/ + int new_ConState; /* <0 => ignore */ + int timeout; /* >0 => *HZ; <=0 => TOUT_XXXX*/ + int action[MAXACT]; /* ACT_XXXX */ + char *command; /* NULL==none */ }; extern struct reply_t gigaset_tab_cid_m10x[]; extern struct reply_t gigaset_tab_nocid_m10x[]; struct inbuf_t { - unsigned char *rcvbuf; /* usb-gigaset receive buffer */ + unsigned char *rcvbuf; /* usb-gigaset receive buffer */ struct bc_state *bcs; - struct cardstate *cs; - int inputstate; - - atomic_t head, tail; - unsigned char data[RBUFSIZE]; + struct cardstate *cs; + int inputstate; + atomic_t head, tail; + unsigned char data[RBUFSIZE]; }; /* isochronous write buffer structure @@ -319,16 +337,9 @@ struct inbuf_t { * if writesem <= 0, data[write..read-1] is currently being written to * - idle contains the byte value to repeat when the end of valid data is * reached; if nextread==write (buffer contains no data to send), either the - * BAS_OUTBUFPAD bytes immediately before data[write] (if write>=BAS_OUTBUFPAD) - * or those of the pad area (if write<BAS_OUTBUFPAD) are also filled with that - * value - * - optionally, the following statistics on the buffer's usage can be collected: - * maxfill: maximum number of bytes occupied - * idlefills: number of times a frame of idle bytes is prepared - * emptygets: number of times the buffer was empty when a data frame was requested - * backtoback: number of times two data packets were entered into the buffer - * without intervening idle flags - * nakedback: set if no idle flags have been inserted since the last data packet + * BAS_OUTBUFPAD bytes immediately before data[write] (if + * write>=BAS_OUTBUFPAD) or those of the pad area (if write<BAS_OUTBUFPAD) + * are also filled with that value */ struct isowbuf_t { atomic_t read; @@ -358,34 +369,28 @@ struct isow_urbctx_t { * it is currently assigned a B channel */ struct at_state_t { - struct list_head list; - int waiting; - int getstring; - atomic_t timer_index; + struct list_head list; + int waiting; + int getstring; + unsigned timer_index; unsigned long timer_expires; int timer_active; - unsigned int ConState; /* State of connection */ - struct reply_t *replystruct; - int cid; - int int_var[VAR_NUM]; /* see VAR_XXXX */ - char *str_var[STR_NUM]; /* see STR_XXXX */ - unsigned pending_commands; /* see PC_XXXX */ - atomic_t seq_index; - - struct cardstate *cs; - struct bc_state *bcs; + unsigned int ConState; /* State of connection */ + struct reply_t *replystruct; + int cid; + int int_var[VAR_NUM]; /* see VAR_XXXX */ + char *str_var[STR_NUM]; /* see STR_XXXX */ + unsigned pending_commands; /* see PC_XXXX */ + unsigned seq_index; + + struct cardstate *cs; + struct bc_state *bcs; }; struct resp_type_t { unsigned char *response; - int resp_code; /* RSP_XXXX */ - int type; /* RT_XXXX */ -}; - -struct prot_skb { - atomic_t empty; - struct semaphore *sem; - struct sk_buff *skb; + int resp_code; /* RSP_XXXX */ + int type; /* RT_XXXX */ }; struct event_t { @@ -398,29 +403,29 @@ struct event_t { /* This buffer holds all information about the used B-Channel */ struct bc_state { - struct sk_buff *tx_skb; /* Current transfer buffer to modem */ - struct sk_buff_head squeue; /* B-Channel send Queue */ + struct sk_buff *tx_skb; /* Current transfer buffer to modem */ + struct sk_buff_head squeue; /* B-Channel send Queue */ /* Variables for debugging .. */ - int corrupted; /* Counter for corrupted packages */ - int trans_down; /* Counter of packages (downstream) */ - int trans_up; /* Counter of packages (upstream) */ + int corrupted; /* Counter for corrupted packages */ + int trans_down; /* Counter of packages (downstream) */ + int trans_up; /* Counter of packages (upstream) */ struct at_state_t at_state; unsigned long rcvbytes; __u16 fcs; struct sk_buff *skb; - int inputstate; /* see INS_XXXX */ + int inputstate; /* see INS_XXXX */ int channel; struct cardstate *cs; - unsigned chstate; /* bitmap (CHS_*) */ + unsigned chstate; /* bitmap (CHS_*) */ int ignore; - unsigned proto2; /* Layer 2 protocol (ISDN_PROTO_L2_*) */ - char *commands[AT_NUM]; /* see AT_XXXX */ + unsigned proto2; /* Layer 2 protocol (ISDN_PROTO_L2_*) */ + char *commands[AT_NUM]; /* see AT_XXXX */ #ifdef CONFIG_GIGASET_DEBUG int emptycount; @@ -428,37 +433,39 @@ struct bc_state { int busy; int use_count; - /* hardware drivers */ + /* private data of hardware drivers */ union { - struct ser_bc_state *ser; /* private data of serial hardware driver */ - struct usb_bc_state *usb; /* private data of usb hardware driver */ - struct bas_bc_state *bas; + struct ser_bc_state *ser; /* serial hardware driver */ + struct usb_bc_state *usb; /* usb hardware driver (m105) */ + struct bas_bc_state *bas; /* usb hardware driver (base) */ } hw; }; struct cardstate { struct gigaset_driver *driver; unsigned minor_index; + struct device *dev; const struct gigaset_ops *ops; /* Stuff to handle communication */ - //wait_queue_head_t initwait; wait_queue_head_t waitqueue; int waiting; - atomic_t mode; /* see M_XXXX */ - atomic_t mstate; /* Modem state: see MS_XXXX */ - /* only changed by the event layer */ + atomic_t mode; /* see M_XXXX */ + atomic_t mstate; /* Modem state: see MS_XXXX */ + /* only changed by the event layer */ int cmd_result; int channels; - struct bc_state *bcs; /* Array of struct bc_state */ + struct bc_state *bcs; /* Array of struct bc_state */ - int onechannel; /* data and commands transmitted in one stream (M10x) */ + int onechannel; /* data and commands transmitted in one + stream (M10x) */ spinlock_t lock; - struct at_state_t at_state; /* at_state_t for cid == 0 */ - struct list_head temp_at_states; /* list of temporary "struct at_state_t"s without B channel */ + struct at_state_t at_state; /* at_state_t for cid == 0 */ + struct list_head temp_at_states;/* list of temporary "struct + at_state_t"s without B channel */ struct inbuf_t *inbuf; @@ -474,58 +481,69 @@ struct cardstate { unsigned fwver[4]; int gotfwver; - atomic_t running; /* !=0 if events are handled */ - atomic_t connected; /* !=0 if hardware is connected */ + unsigned running; /* !=0 if events are handled */ + unsigned connected; /* !=0 if hardware is connected */ + unsigned isdn_up; /* !=0 after ISDN_STAT_RUN */ - atomic_t cidmode; + unsigned cidmode; - int myid; /* id for communication with LL */ + int myid; /* id for communication with LL */ isdn_if iif; struct reply_t *tabnocid; struct reply_t *tabcid; int cs_init; - int ignoreframes; /* frames to ignore after setting up the B channel */ - struct semaphore sem; /* locks this structure: */ - /* connected is not changed, */ - /* hardware_up is not changed, */ - /* MState is not changed to or from MS_LOCKED */ + int ignoreframes; /* frames to ignore after setting up the + B channel */ + struct mutex mutex; /* locks this structure: + * connected is not changed, + * hardware_up is not changed, + * MState is not changed to or from + * MS_LOCKED */ struct timer_list timer; int retry_count; - int dle; /* !=0 if modem commands/responses are dle encoded */ - int cur_at_seq; /* sequence of AT commands being processed */ - int curchannel; /* channel, those commands are meant for */ - atomic_t commands_pending; /* flag(s) in xxx.commands_pending have been set */ - struct tasklet_struct event_tasklet; /* tasklet for serializing AT commands. Scheduled - * -> for modem reponses (and incomming data for M10x) - * -> on timeout - * -> after setting bits in xxx.at_state.pending_command - * (e.g. command from LL) */ - struct tasklet_struct write_tasklet; /* tasklet for serial output - * (not used in base driver) */ + int dle; /* !=0 if modem commands/responses are + dle encoded */ + int cur_at_seq; /* sequence of AT commands being + processed */ + int curchannel; /* channel those commands are meant + for */ + atomic_t commands_pending; /* flag(s) in xxx.commands_pending have + been set */ + struct tasklet_struct event_tasklet; + /* tasklet for serializing AT commands. + * Scheduled + * -> for modem reponses (and + * incoming data for M10x) + * -> on timeout + * -> after setting bits in + * xxx.at_state.pending_command + * (e.g. command from LL) */ + struct tasklet_struct write_tasklet; + /* tasklet for serial output + * (not used in base driver) */ /* event queue */ struct event_t events[MAX_EVENTS]; - atomic_t ev_tail, ev_head; + unsigned ev_tail, ev_head; spinlock_t ev_lock; /* current modem response */ unsigned char respdata[MAX_RESP_SIZE]; unsigned cbytes; - /* hardware drivers */ + /* private data of hardware drivers */ union { - struct usb_cardstate *usb; /* private data of USB hardware driver */ - struct ser_cardstate *ser; /* private data of serial hardware driver */ - struct bas_cardstate *bas; /* private data of base hardware driver */ + struct usb_cardstate *usb; /* USB hardware driver (m105) */ + struct ser_cardstate *ser; /* serial hardware driver */ + struct bas_cardstate *bas; /* USB hardware driver (base) */ } hw; }; struct gigaset_driver { struct list_head list; - spinlock_t lock; /* locks minor tables and blocked */ - //struct semaphore sem; /* locks this structure */ + spinlock_t lock; /* locks minor tables and blocked */ struct tty_driver *tty; unsigned have_tty; unsigned minor; @@ -553,37 +571,42 @@ struct bas_bc_state { struct isow_urbctx_t isoouturbs[BAS_OUTURBS]; struct isow_urbctx_t *isooutdone, *isooutfree, *isooutovfl; struct isowbuf_t *isooutbuf; - unsigned numsub; /* submitted URB counter (for diagnostic messages only) */ + unsigned numsub; /* submitted URB counter + (for diagnostic messages only) */ struct tasklet_struct sent_tasklet; /* isochronous input state */ spinlock_t isoinlock; struct urb *isoinurbs[BAS_INURBS]; unsigned char isoinbuf[BAS_INBUFSIZE * BAS_INURBS]; - struct urb *isoindone; /* completed isoc read URB */ - int loststatus; /* status of dropped URB */ - unsigned isoinlost; /* number of bytes lost */ - /* state of bit unstuffing algorithm (in addition to BC_state.inputstate) */ - unsigned seqlen; /* number of '1' bits not yet unstuffed */ - unsigned inbyte, inbits; /* collected bits for next byte */ + struct urb *isoindone; /* completed isoc read URB */ + int loststatus; /* status of dropped URB */ + unsigned isoinlost; /* number of bytes lost */ + /* state of bit unstuffing algorithm + (in addition to BC_state.inputstate) */ + unsigned seqlen; /* number of '1' bits not yet + unstuffed */ + unsigned inbyte, inbits; /* collected bits for next byte */ /* statistics */ - unsigned goodbytes; /* bytes correctly received */ - unsigned alignerrs; /* frames with incomplete byte at end */ - unsigned fcserrs; /* FCS errors */ - unsigned frameerrs; /* framing errors */ - unsigned giants; /* long frames */ - unsigned runts; /* short frames */ - unsigned aborts; /* HDLC aborts */ - unsigned shared0s; /* '0' bits shared between flags */ - unsigned stolen0s; /* '0' stuff bits also serving as leading flag bits */ + unsigned goodbytes; /* bytes correctly received */ + unsigned alignerrs; /* frames with incomplete byte at end */ + unsigned fcserrs; /* FCS errors */ + unsigned frameerrs; /* framing errors */ + unsigned giants; /* long frames */ + unsigned runts; /* short frames */ + unsigned aborts; /* HDLC aborts */ + unsigned shared0s; /* '0' bits shared between flags */ + unsigned stolen0s; /* '0' stuff bits also serving as + leading flag bits */ struct tasklet_struct rcvd_tasklet; }; struct gigaset_ops { - /* Called from ev-layer.c/interface.c for sending AT commands to the device */ + /* Called from ev-layer.c/interface.c for sending AT commands to the + device */ int (*write_cmd)(struct cardstate *cs, - const unsigned char *buf, int len, - struct tasklet_struct *wake_tasklet); + const unsigned char *buf, int len, + struct tasklet_struct *wake_tasklet); /* Called from interface.c for additional device control */ int (*write_room)(struct cardstate *cs); @@ -604,7 +627,8 @@ struct gigaset_ops { /* Called by gigaset_freecs() for freeing bcs->hw.xxx */ int (*freebcshw)(struct bc_state *bcs); - /* Called by gigaset_stop() or gigaset_bchannel_down() for resetting bcs->hw.xxx */ + /* Called by gigaset_stop() or gigaset_bchannel_down() for resetting + bcs->hw.xxx */ void (*reinitbcshw)(struct bc_state *bcs); /* Called by gigaset_initcs() for setting up cs->hw.xxx */ @@ -613,13 +637,10 @@ struct gigaset_ops { /* Called by gigaset_freecs() for freeing cs->hw.xxx */ void (*freecshw)(struct cardstate *cs); - ///* Called by gigaset_stop() for killing URBs, shutting down the device, ... - // hardwareup: ==0: don't try to shut down the device, hardware is really not accessible - // !=0: hardware still up */ - //void (*stophw)(struct cardstate *cs, int hardwareup); - - /* Called from common.c/interface.c for additional serial port control */ - int (*set_modem_ctrl)(struct cardstate *cs, unsigned old_state, unsigned new_state); + /* Called from common.c/interface.c for additional serial port + control */ + int (*set_modem_ctrl)(struct cardstate *cs, unsigned old_state, + unsigned new_state); int (*baud_rate)(struct cardstate *cs, unsigned cflag); int (*set_line_ctrl)(struct cardstate *cs, unsigned cflag); @@ -639,7 +660,7 @@ struct gigaset_ops { * <DLE_FLAG>: 0x10 * <EVENT>: ((a-z)* | (A-Z)* | (0-10)*)+ */ -#define DLE_FLAG 0x10 +#define DLE_FLAG 0x10 /* =========================================================================== * Functions implemented in asyncdata.c @@ -667,7 +688,8 @@ void gigaset_isoc_input(struct inbuf_t *inbuf); /* Called from bas-gigaset.c to process a block of data * received through the isochronous channel */ -void gigaset_isoc_receive(unsigned char *src, unsigned count, struct bc_state *bcs); +void gigaset_isoc_receive(unsigned char *src, unsigned count, + struct bc_state *bcs); /* Called from bas-gigaset.c to put a block of data * into the isochronous output buffer */ @@ -703,7 +725,7 @@ static inline void gigaset_isdn_rcv_err(struct bc_state *bcs) isdn_ctrl response; /* error -> LL */ - dbg(DEBUG_CMD, "sending L1ERR"); + gig_dbg(DEBUG_CMD, "sending L1ERR"); response.driver = bcs->cs->myid; response.command = ISDN_STAT_L1ERR; response.arg = bcs->channel; @@ -727,8 +749,8 @@ void gigaset_handle_modem_response(struct cardstate *cs); */ /* initialize sysfs for device */ -void gigaset_init_dev_sysfs(struct usb_interface *interface); -void gigaset_free_dev_sysfs(struct usb_interface *interface); +void gigaset_init_dev_sysfs(struct cardstate *cs); +void gigaset_free_dev_sysfs(struct cardstate *cs); /* =========================================================================== * Functions implemented in common.c/gigaset.h @@ -736,7 +758,7 @@ void gigaset_free_dev_sysfs(struct usb_interface *interface); void gigaset_bcs_reinit(struct bc_state *bcs); void gigaset_at_init(struct at_state_t *at_state, struct bc_state *bcs, - struct cardstate *cs, int cid); + struct cardstate *cs, int cid); int gigaset_get_channel(struct bc_state *bcs); void gigaset_free_channel(struct bc_state *bcs); int gigaset_get_channels(struct cardstate *cs); @@ -745,16 +767,15 @@ void gigaset_block_channels(struct cardstate *cs); /* Allocate and initialize driver structure. */ struct gigaset_driver *gigaset_initdriver(unsigned minor, unsigned minors, - const char *procname, - const char *devname, - const char *devfsname, - const struct gigaset_ops *ops, - struct module *owner); + const char *procname, + const char *devname, + const char *devfsname, + const struct gigaset_ops *ops, + struct module *owner); /* Deallocate driver structure. */ void gigaset_freedriver(struct gigaset_driver *drv); void gigaset_debugdrivers(void); -struct cardstate *gigaset_get_cs_by_minor(unsigned minor); struct cardstate *gigaset_get_cs_by_tty(struct tty_struct *tty); struct cardstate *gigaset_get_cs_by_id(int id); @@ -763,7 +784,8 @@ struct cardstate *gigaset_getunassignedcs(struct gigaset_driver *drv); void gigaset_unassign(struct cardstate *cs); void gigaset_blockdriver(struct gigaset_driver *drv); -/* Allocate and initialize card state. Calls hardware dependent gigaset_init[b]cs(). */ +/* Allocate and initialize card state. Calls hardware dependent + gigaset_init[b]cs(). */ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels, int onechannel, int ignoreframes, int cidmode, const char *modulename); @@ -788,8 +810,8 @@ void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb); * ptr must be kmalloc()ed (and not be freed by the caller). */ struct event_t *gigaset_add_event(struct cardstate *cs, - struct at_state_t *at_state, int type, - void *ptr, int parameter, void *arg); + struct at_state_t *at_state, int type, + void *ptr, int parameter, void *arg); /* Called on CONFIG1 command from frontend. */ int gigaset_enterconfigmode(struct cardstate *cs); //0: success <0: errorcode @@ -799,7 +821,7 @@ static inline void gigaset_schedule_event(struct cardstate *cs) { unsigned long flags; spin_lock_irqsave(&cs->lock, flags); - if (atomic_read(&cs->running)) + if (cs->running) tasklet_schedule(&cs->event_tasklet); spin_unlock_irqrestore(&cs->lock, flags); } @@ -810,7 +832,7 @@ static inline void gigaset_bchannel_down(struct bc_state *bcs) { gigaset_add_event(bcs->cs, &bcs->at_state, EV_BC_CLOSED, NULL, 0, NULL); - dbg(DEBUG_CMD, "scheduling BC_CLOSED"); + gig_dbg(DEBUG_CMD, "scheduling BC_CLOSED"); gigaset_schedule_event(bcs->cs); } @@ -820,36 +842,19 @@ static inline void gigaset_bchannel_up(struct bc_state *bcs) { gigaset_add_event(bcs->cs, &bcs->at_state, EV_BC_OPEN, NULL, 0, NULL); - dbg(DEBUG_CMD, "scheduling BC_OPEN"); + gig_dbg(DEBUG_CMD, "scheduling BC_OPEN"); gigaset_schedule_event(bcs->cs); } /* handling routines for sk_buff */ /* ============================= */ -/* private version of __skb_put() - * append 'len' bytes to the content of 'skb', already knowing that the - * existing buffer can accomodate them - * returns a pointer to the location where the new bytes should be copied to - * This function does not take any locks so it must be called with the - * appropriate locks held only. - */ -static inline unsigned char *gigaset_skb_put_quick(struct sk_buff *skb, - unsigned int len) -{ - unsigned char *tmp = skb->tail; - /*SKB_LINEAR_ASSERT(skb);*/ /* not needed here */ - skb->tail += len; - skb->len += len; - return tmp; -} - /* pass received skb to LL * Warning: skb must not be accessed anymore! */ static inline void gigaset_rcv_skb(struct sk_buff *skb, - struct cardstate *cs, - struct bc_state *bcs) + struct cardstate *cs, + struct bc_state *bcs) { cs->iif.rcvcallb_skb(cs->myid, bcs->channel, skb); bcs->trans_down++; @@ -859,8 +864,8 @@ static inline void gigaset_rcv_skb(struct sk_buff *skb, * Warning: skb must not be accessed anymore! */ static inline void gigaset_rcv_error(struct sk_buff *procskb, - struct cardstate *cs, - struct bc_state *bcs) + struct cardstate *cs, + struct bc_state *bcs) { if (procskb) dev_kfree_skb(procskb); @@ -877,46 +882,9 @@ static inline void gigaset_rcv_error(struct sk_buff *procskb, /* bitwise byte inversion table */ extern __u8 gigaset_invtab[]; /* in common.c */ - /* append received bytes to inbuf */ -static inline int gigaset_fill_inbuf(struct inbuf_t *inbuf, - const unsigned char *src, - unsigned numbytes) -{ - unsigned n, head, tail, bytesleft; - - dbg(DEBUG_INTR, "received %u bytes", numbytes); - - if (!numbytes) - return 0; - - bytesleft = numbytes; - tail = atomic_read(&inbuf->tail); - head = atomic_read(&inbuf->head); - dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail); - - while (bytesleft) { - if (head > tail) - n = head - 1 - tail; - else if (head == 0) - n = (RBUFSIZE-1) - tail; - else - n = RBUFSIZE - tail; - if (!n) { - err("buffer overflow (%u bytes lost)", bytesleft); - break; - } - if (n > bytesleft) - n = bytesleft; - memcpy(inbuf->data + tail, src, n); - bytesleft -= n; - tail = (tail + n) % RBUFSIZE; - src += n; - } - dbg(DEBUG_INTR, "setting tail to %u", tail); - atomic_set(&inbuf->tail, tail); - return numbytes != bytesleft; -} +int gigaset_fill_inbuf(struct inbuf_t *inbuf, const unsigned char *src, + unsigned numbytes); /* =========================================================================== * Functions implemented in interface.c @@ -924,7 +892,7 @@ static inline int gigaset_fill_inbuf(struct inbuf_t *inbuf, /* initialize interface */ void gigaset_if_initdriver(struct gigaset_driver *drv, const char *procname, - const char *devname, const char *devfsname); + const char *devname, const char *devfsname); /* release interface */ void gigaset_if_freedriver(struct gigaset_driver *drv); /* add minor */ @@ -933,6 +901,6 @@ void gigaset_if_init(struct cardstate *cs); void gigaset_if_free(struct cardstate *cs); /* device received data */ void gigaset_if_receive(struct cardstate *cs, - unsigned char *buffer, size_t len); + unsigned char *buffer, size_t len); #endif diff --git a/drivers/isdn/gigaset/i4l.c b/drivers/isdn/gigaset/i4l.c index 731a675..0815dbf 100644 --- a/drivers/isdn/gigaset/i4l.c +++ b/drivers/isdn/gigaset/i4l.c @@ -1,9 +1,9 @@ /* * Stuff used by all variants of the driver * - * Copyright (c) 2001 by Stefan Eilers (Eilers.Stefan@epost.de), - * Hansjoerg Lipp (hjlipp@web.de), - * Tilman Schmidt (tilman@imap.cc). + * Copyright (c) 2001 by Stefan Eilers, + * Hansjoerg Lipp <hjlipp@web.de>, + * Tilman Schmidt <tilman@imap.cc>. * * ===================================================================== * This program is free software; you can redistribute it and/or @@ -11,15 +11,11 @@ * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * ===================================================================== - * ToDo: ... - * ===================================================================== - * Version: $Id: i4l.c,v 1.3.2.9 2006/02/04 18:28:16 hjlipp Exp $ - * ===================================================================== */ #include "gigaset.h" -/* == Handling of I4L IO ============================================================================*/ +/* == Handling of I4L IO =====================================================*/ /* writebuf_from_LL * called by LL to transmit data on an open channel @@ -29,14 +25,16 @@ * parameters: * driverID driver ID as assigned by LL * channel channel number - * ack if != 0 LL wants to be notified on completion via statcallb(ISDN_STAT_BSENT) + * ack if != 0 LL wants to be notified on completion via + * statcallb(ISDN_STAT_BSENT) * skb skb containing data to send * return value: * number of accepted bytes * 0 if temporarily unable to accept data (out of buffer space) * <0 on error (eg. -EINVAL) */ -static int writebuf_from_LL(int driverID, int channel, int ack, struct sk_buff *skb) +static int writebuf_from_LL(int driverID, int channel, int ack, + struct sk_buff *skb) { struct cardstate *cs; struct bc_state *bcs; @@ -54,31 +52,28 @@ static int writebuf_from_LL(int driverID, int channel, int ack, struct sk_buff * bcs = &cs->bcs[channel]; len = skb->len; - dbg(DEBUG_LLDATA, - "Receiving data from LL (id: %d, channel: %d, ack: %d, size: %d)", - driverID, channel, ack, len); + gig_dbg(DEBUG_LLDATA, + "Receiving data from LL (id: %d, ch: %d, ack: %d, sz: %d)", + driverID, channel, ack, len); if (!len) { if (ack) - warn("not ACKing empty packet from LL"); + notice("%s: not ACKing empty packet", __func__); return 0; } if (len > MAX_BUF_SIZE) { - err("%s: packet too large (%d bytes)", __func__, channel); + err("%s: packet too large (%d bytes)", __func__, len); return -EINVAL; } - if (!atomic_read(&cs->connected)) - return -ENODEV; - skblen = ack ? len : 0; skb->head[0] = skblen & 0xff; skb->head[1] = skblen >> 8; - dbg(DEBUG_MCMD, "skb: len=%u, skblen=%u: %02x %02x", len, skblen, - (unsigned) skb->head[0], (unsigned) skb->head[1]); + gig_dbg(DEBUG_MCMD, "skb: len=%u, skblen=%u: %02x %02x", + len, skblen, (unsigned) skb->head[0], (unsigned) skb->head[1]); /* pass to device-specific module */ - return cs->ops->send_skb(bcs, skb); + return cs->ops->send_skb(bcs, skb); //FIXME cs->ops->send_skb() must handle !cs->connected correctly } void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb) @@ -89,14 +84,14 @@ void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb) ++bcs->trans_up; if (skb->len) - warn("%s: skb->len==%d", __func__, skb->len); + dev_warn(bcs->cs->dev, "%s: skb->len==%d\n", + __func__, skb->len); len = (unsigned char) skb->head[0] | (unsigned) (unsigned char) skb->head[1] << 8; if (len) { - dbg(DEBUG_MCMD, - "Acknowledge sending to LL (id: %d, channel: %d size: %u)", - bcs->cs->myid, bcs->channel, len); + gig_dbg(DEBUG_MCMD, "ACKing to LL (id: %d, ch: %d, sz: %u)", + bcs->cs->myid, bcs->channel, len); response.driver = bcs->cs->myid; response.command = ISDN_STAT_BSENT; @@ -119,15 +114,12 @@ static int command_from_LL(isdn_ctrl *cntrl) struct bc_state *bcs; int retval = 0; struct setup_parm *sp; + unsigned param; + unsigned long flags; - //dbg(DEBUG_ANY, "Gigaset_HW: Receiving command"); gigaset_debugdrivers(); - /* Terminate this call if no device is present. Bt if the command is "ISDN_CMD_LOCK" or - * "ISDN_CMD_UNLOCK" then execute it due to the fact that they are device independent ! - */ - //FIXME "remove test for &connected" - if ((!cs || !atomic_read(&cs->connected))) { + if (!cs) { warn("LL tried to access unknown device with nr. %d", cntrl->driver); return -ENODEV; @@ -135,29 +127,30 @@ static int command_from_LL(isdn_ctrl *cntrl) switch (cntrl->command) { case ISDN_CMD_IOCTL: - - dbg(DEBUG_ANY, "ISDN_CMD_IOCTL (driver:%d,arg: %ld)", - cntrl->driver, cntrl->arg); + gig_dbg(DEBUG_ANY, "ISDN_CMD_IOCTL (driver: %d, arg: %ld)", + cntrl->driver, cntrl->arg); warn("ISDN_CMD_IOCTL is not supported."); return -EINVAL; case ISDN_CMD_DIAL: - dbg(DEBUG_ANY, "ISDN_CMD_DIAL (driver: %d, channel: %ld, " - "phone: %s,ownmsn: %s, si1: %d, si2: %d)", - cntrl->driver, cntrl->arg, - cntrl->parm.setup.phone, cntrl->parm.setup.eazmsn, - cntrl->parm.setup.si1, cntrl->parm.setup.si2); + gig_dbg(DEBUG_ANY, + "ISDN_CMD_DIAL (driver: %d, ch: %ld, " + "phone: %s, ownmsn: %s, si1: %d, si2: %d)", + cntrl->driver, cntrl->arg, + cntrl->parm.setup.phone, cntrl->parm.setup.eazmsn, + cntrl->parm.setup.si1, cntrl->parm.setup.si2); if (cntrl->arg >= cs->channels) { - err("invalid channel (%d)", (int) cntrl->arg); + err("ISDN_CMD_DIAL: invalid channel (%d)", + (int) cntrl->arg); return -EINVAL; } bcs = cs->bcs + cntrl->arg; if (!gigaset_get_channel(bcs)) { - err("channel not free"); + err("ISDN_CMD_DIAL: channel not free"); return -EBUSY; } @@ -169,42 +162,46 @@ static int command_from_LL(isdn_ctrl *cntrl) } *sp = cntrl->parm.setup; - if (!gigaset_add_event(cs, &bcs->at_state, EV_DIAL, sp, - atomic_read(&bcs->at_state.seq_index), - NULL)) { + spin_lock_irqsave(&cs->lock, flags); + param = bcs->at_state.seq_index; + spin_unlock_irqrestore(&cs->lock, flags); + + if (!gigaset_add_event(cs, &bcs->at_state, EV_DIAL, sp, param, + NULL)) { //FIXME what should we do? kfree(sp); gigaset_free_channel(bcs); return -ENOMEM; } - dbg(DEBUG_CMD, "scheduling DIAL"); + gig_dbg(DEBUG_CMD, "scheduling DIAL"); gigaset_schedule_event(cs); break; case ISDN_CMD_ACCEPTD: //FIXME - dbg(DEBUG_ANY, "ISDN_CMD_ACCEPTD"); + gig_dbg(DEBUG_ANY, "ISDN_CMD_ACCEPTD"); if (cntrl->arg >= cs->channels) { - err("invalid channel (%d)", (int) cntrl->arg); + err("ISDN_CMD_ACCEPTD: invalid channel (%d)", + (int) cntrl->arg); return -EINVAL; } if (!gigaset_add_event(cs, &cs->bcs[cntrl->arg].at_state, - EV_ACCEPT, NULL, 0, NULL)) { + EV_ACCEPT, NULL, 0, NULL)) { //FIXME what should we do? return -ENOMEM; } - dbg(DEBUG_CMD, "scheduling ACCEPT"); + gig_dbg(DEBUG_CMD, "scheduling ACCEPT"); gigaset_schedule_event(cs); break; case ISDN_CMD_ACCEPTB: - dbg(DEBUG_ANY, "ISDN_CMD_ACCEPTB"); + gig_dbg(DEBUG_ANY, "ISDN_CMD_ACCEPTB"); break; case ISDN_CMD_HANGUP: - dbg(DEBUG_ANY, - "ISDN_CMD_HANGUP (channel: %d)", (int) cntrl->arg); + gig_dbg(DEBUG_ANY, "ISDN_CMD_HANGUP (ch: %d)", + (int) cntrl->arg); if (cntrl->arg >= cs->channels) { err("ISDN_CMD_HANGUP: invalid channel (%u)", @@ -213,66 +210,68 @@ static int command_from_LL(isdn_ctrl *cntrl) } if (!gigaset_add_event(cs, &cs->bcs[cntrl->arg].at_state, - EV_HUP, NULL, 0, NULL)) { + EV_HUP, NULL, 0, NULL)) { //FIXME what should we do? return -ENOMEM; } - dbg(DEBUG_CMD, "scheduling HUP"); + gig_dbg(DEBUG_CMD, "scheduling HUP"); gigaset_schedule_event(cs); break; - case ISDN_CMD_CLREAZ: /* Do not signal incoming signals */ //FIXME - dbg(DEBUG_ANY, "ISDN_CMD_CLREAZ"); + case ISDN_CMD_CLREAZ: /* Do not signal incoming signals */ //FIXME + gig_dbg(DEBUG_ANY, "ISDN_CMD_CLREAZ"); break; - case ISDN_CMD_SETEAZ: /* Signal incoming calls for given MSN */ //FIXME - dbg(DEBUG_ANY, - "ISDN_CMD_SETEAZ (id:%d, channel: %ld, number: %s)", - cntrl->driver, cntrl->arg, cntrl->parm.num); + case ISDN_CMD_SETEAZ: /* Signal incoming calls for given MSN */ //FIXME + gig_dbg(DEBUG_ANY, + "ISDN_CMD_SETEAZ (id: %d, ch: %ld, number: %s)", + cntrl->driver, cntrl->arg, cntrl->parm.num); break; - case ISDN_CMD_SETL2: /* Set L2 to given protocol */ - dbg(DEBUG_ANY, "ISDN_CMD_SETL2 (Channel: %ld, Proto: %lx)", - cntrl->arg & 0xff, (cntrl->arg >> 8)); + case ISDN_CMD_SETL2: /* Set L2 to given protocol */ + gig_dbg(DEBUG_ANY, "ISDN_CMD_SETL2 (ch: %ld, proto: %lx)", + cntrl->arg & 0xff, (cntrl->arg >> 8)); if ((cntrl->arg & 0xff) >= cs->channels) { - err("invalid channel (%u)", + err("ISDN_CMD_SETL2: invalid channel (%u)", (unsigned) cntrl->arg & 0xff); return -EINVAL; } if (!gigaset_add_event(cs, &cs->bcs[cntrl->arg & 0xff].at_state, - EV_PROTO_L2, NULL, cntrl->arg >> 8, - NULL)) { + EV_PROTO_L2, NULL, cntrl->arg >> 8, + NULL)) { //FIXME what should we do? return -ENOMEM; } - dbg(DEBUG_CMD, "scheduling PROTO_L2"); + gig_dbg(DEBUG_CMD, "scheduling PROTO_L2"); gigaset_schedule_event(cs); break; - case ISDN_CMD_SETL3: /* Set L3 to given protocol */ - dbg(DEBUG_ANY, "ISDN_CMD_SETL3 (Channel: %ld, Proto: %lx)", - cntrl->arg & 0xff, (cntrl->arg >> 8)); + case ISDN_CMD_SETL3: /* Set L3 to given protocol */ + gig_dbg(DEBUG_ANY, "ISDN_CMD_SETL3 (ch: %ld, proto: %lx)", + cntrl->arg & 0xff, (cntrl->arg >> 8)); if ((cntrl->arg & 0xff) >= cs->channels) { - err("invalid channel (%u)", + err("ISDN_CMD_SETL3: invalid channel (%u)", (unsigned) cntrl->arg & 0xff); return -EINVAL; } if (cntrl->arg >> 8 != ISDN_PROTO_L3_TRANS) { - err("invalid protocol %lu", cntrl->arg >> 8); + err("ISDN_CMD_SETL3: invalid protocol %lu", + cntrl->arg >> 8); return -EINVAL; } break; case ISDN_CMD_PROCEED: - dbg(DEBUG_ANY, "ISDN_CMD_PROCEED"); //FIXME + gig_dbg(DEBUG_ANY, "ISDN_CMD_PROCEED"); //FIXME break; case ISDN_CMD_ALERT: - dbg(DEBUG_ANY, "ISDN_CMD_ALERT"); //FIXME + gig_dbg(DEBUG_ANY, "ISDN_CMD_ALERT"); //FIXME if (cntrl->arg >= cs->channels) { - err("invalid channel (%d)", (int) cntrl->arg); + err("ISDN_CMD_ALERT: invalid channel (%d)", + (int) cntrl->arg); return -EINVAL; } //bcs = cs->bcs + cntrl->arg; @@ -280,32 +279,31 @@ static int command_from_LL(isdn_ctrl *cntrl) // FIXME break; case ISDN_CMD_REDIR: - dbg(DEBUG_ANY, "ISDN_CMD_REDIR"); //FIXME + gig_dbg(DEBUG_ANY, "ISDN_CMD_REDIR"); //FIXME break; case ISDN_CMD_PROT_IO: - dbg(DEBUG_ANY, "ISDN_CMD_PROT_IO"); + gig_dbg(DEBUG_ANY, "ISDN_CMD_PROT_IO"); break; case ISDN_CMD_FAXCMD: - dbg(DEBUG_ANY, "ISDN_CMD_FAXCMD"); + gig_dbg(DEBUG_ANY, "ISDN_CMD_FAXCMD"); break; case ISDN_CMD_GETL2: - dbg(DEBUG_ANY, "ISDN_CMD_GETL2"); + gig_dbg(DEBUG_ANY, "ISDN_CMD_GETL2"); break; case ISDN_CMD_GETL3: - dbg(DEBUG_ANY, "ISDN_CMD_GETL3"); + gig_dbg(DEBUG_ANY, "ISDN_CMD_GETL3"); break; case ISDN_CMD_GETEAZ: - dbg(DEBUG_ANY, "ISDN_CMD_GETEAZ"); + gig_dbg(DEBUG_ANY, "ISDN_CMD_GETEAZ"); break; case ISDN_CMD_SETSIL: - dbg(DEBUG_ANY, "ISDN_CMD_SETSIL"); + gig_dbg(DEBUG_ANY, "ISDN_CMD_SETSIL"); break; case ISDN_CMD_GETSIL: - dbg(DEBUG_ANY, "ISDN_CMD_GETSIL"); + gig_dbg(DEBUG_ANY, "ISDN_CMD_GETSIL"); break; default: - err("unknown command %d from LL", - cntrl->command); + err("unknown command %d from LL", cntrl->command); return -EINVAL; } @@ -350,7 +348,8 @@ int gigaset_isdn_setup_dial(struct at_state_t *at_state, void *data) proto = 2; /* 0: Bitsynchron, 1: HDLC, 2: voice */ break; default: - err("invalid protocol: %u", bcs->proto2); + dev_err(bcs->cs->dev, "%s: invalid L2 protocol: %u\n", + __func__, bcs->proto2); return -EINVAL; } @@ -378,7 +377,7 @@ int gigaset_isdn_setup_dial(struct at_state_t *at_state, void *data) bcs->commands[i] = NULL; if (length[i] && !(bcs->commands[i] = kmalloc(length[i], GFP_ATOMIC))) { - err("out of memory"); + dev_err(bcs->cs->dev, "out of memory\n"); return -ENOMEM; } } @@ -396,10 +395,14 @@ int gigaset_isdn_setup_dial(struct at_state_t *at_state, void *data) } if (bcs->commands[AT_MSN]) - snprintf(bcs->commands[AT_MSN], length[AT_MSN], "^SMSN=%s\r", sp->eazmsn); - snprintf(bcs->commands[AT_BC ], length[AT_BC ], "^SBC=%s\r", bc); - snprintf(bcs->commands[AT_PROTO], length[AT_PROTO], "^SBPR=%u\r", proto); - snprintf(bcs->commands[AT_ISO ], length[AT_ISO ], "^SISO=%u\r", (unsigned)bcs->channel + 1); + snprintf(bcs->commands[AT_MSN], length[AT_MSN], + "^SMSN=%s\r", sp->eazmsn); + snprintf(bcs->commands[AT_BC ], length[AT_BC ], + "^SBC=%s\r", bc); + snprintf(bcs->commands[AT_PROTO], length[AT_PROTO], + "^SBPR=%u\r", proto); + snprintf(bcs->commands[AT_ISO ], length[AT_ISO ], + "^SISO=%u\r", (unsigned)bcs->channel + 1); return 0; } @@ -419,7 +422,8 @@ int gigaset_isdn_setup_accept(struct at_state_t *at_state) proto = 2; /* 0: Bitsynchron, 1: HDLC, 2: voice */ break; default: - err("invalid protocol: %u", bcs->proto2); + dev_err(at_state->cs->dev, "%s: invalid protocol: %u\n", + __func__, bcs->proto2); return -EINVAL; } @@ -436,13 +440,15 @@ int gigaset_isdn_setup_accept(struct at_state_t *at_state) bcs->commands[i] = NULL; if (length[i] && !(bcs->commands[i] = kmalloc(length[i], GFP_ATOMIC))) { - err("out of memory"); + dev_err(at_state->cs->dev, "out of memory\n"); return -ENOMEM; } } - snprintf(bcs->commands[AT_PROTO], length[AT_PROTO], "^SBPR=%u\r", proto); - snprintf(bcs->commands[AT_ISO ], length[AT_ISO ], "^SISO=%u\r", (unsigned) bcs->channel + 1); + snprintf(bcs->commands[AT_PROTO], length[AT_PROTO], + "^SBPR=%u\r", proto); + snprintf(bcs->commands[AT_ISO ], length[AT_ISO ], + "^SISO=%u\r", (unsigned) bcs->channel + 1); return 0; } @@ -473,7 +479,7 @@ int gigaset_isdn_icall(struct at_state_t *at_state) response.parm.setup.si1 = 1; response.parm.setup.si2 = 2; } else { - warn("RING ignored - unsupported BC %s", + dev_warn(cs->dev, "RING ignored - unsupported BC %s\n", at_state->str_var[STR_ZBC]); return ICALL_IGNORE; } @@ -491,18 +497,17 @@ int gigaset_isdn_icall(struct at_state_t *at_state) response.parm.setup.eazmsn[0] = 0; if (!bcs) { - notice("no channel for incoming call"); - dbg(DEBUG_CMD, "Sending ICALLW"); + dev_notice(cs->dev, "no channel for incoming call\n"); response.command = ISDN_STAT_ICALLW; response.arg = 0; //FIXME } else { - dbg(DEBUG_CMD, "Sending ICALL"); + gig_dbg(DEBUG_CMD, "Sending ICALL"); response.command = ISDN_STAT_ICALL; response.arg = bcs->channel; //FIXME } response.driver = cs->myid; retval = cs->iif.statcallb(&response); - dbg(DEBUG_CMD, "Response: %d", retval); + gig_dbg(DEBUG_CMD, "Response: %d", retval); switch (retval) { case 0: /* no takers */ return ICALL_IGNORE; @@ -512,7 +517,8 @@ int gigaset_isdn_icall(struct at_state_t *at_state) case 2: /* reject */ return ICALL_REJECT; case 3: /* incomplete */ - warn("LL requested unsupported feature: Incomplete Number"); + dev_warn(cs->dev, + "LL requested unsupported feature: Incomplete Number\n"); return ICALL_IGNORE; case 4: /* proceeding */ /* Gigaset will send ALERTING anyway. @@ -520,10 +526,11 @@ int gigaset_isdn_icall(struct at_state_t *at_state) */ return ICALL_ACCEPT; case 5: /* deflect */ - warn("LL requested unsupported feature: Call Deflection"); + dev_warn(cs->dev, + "LL requested unsupported feature: Call Deflection\n"); return ICALL_IGNORE; default: - err("LL error %d on ICALL", retval); + dev_err(cs->dev, "LL error %d on ICALL\n", retval); return ICALL_IGNORE; } } @@ -533,7 +540,7 @@ int gigaset_register_to_LL(struct cardstate *cs, const char *isdnid) { isdn_if *iif = &cs->iif; - dbg(DEBUG_ANY, "Register driver capabilities to LL"); + gig_dbg(DEBUG_ANY, "Register driver capabilities to LL"); //iif->id[sizeof(iif->id) - 1]=0; //strncpy(iif->id, isdnid, sizeof(iif->id) - 1); @@ -542,26 +549,26 @@ int gigaset_register_to_LL(struct cardstate *cs, const char *isdnid) return -ENOMEM; //FIXME EINVAL/...?? iif->owner = THIS_MODULE; - iif->channels = cs->channels; /* I am supporting just one channel *//* I was supporting...*/ + iif->channels = cs->channels; iif->maxbufsize = MAX_BUF_SIZE; - iif->features = ISDN_FEATURE_L2_TRANS | /* Our device is very advanced, therefore */ + iif->features = ISDN_FEATURE_L2_TRANS | ISDN_FEATURE_L2_HDLC | #ifdef GIG_X75 ISDN_FEATURE_L2_X75I | #endif ISDN_FEATURE_L3_TRANS | ISDN_FEATURE_P_EURO; - iif->hl_hdrlen = HW_HDR_LEN; /* Area for storing ack */ + iif->hl_hdrlen = HW_HDR_LEN; /* Area for storing ack */ iif->command = command_from_LL; iif->writebuf_skb = writebuf_from_LL; - iif->writecmd = NULL; /* Don't support isdnctrl */ - iif->readstat = NULL; /* Don't support isdnctrl */ - iif->rcvcallb_skb = NULL; /* Will be set by LL */ - iif->statcallb = NULL; /* Will be set by LL */ + iif->writecmd = NULL; /* Don't support isdnctrl */ + iif->readstat = NULL; /* Don't support isdnctrl */ + iif->rcvcallb_skb = NULL; /* Will be set by LL */ + iif->statcallb = NULL; /* Will be set by LL */ if (!register_isdn(iif)) return 0; - cs->myid = iif->channels; /* Set my device id */ + cs->myid = iif->channels; /* Set my device id */ return 1; } diff --git a/drivers/isdn/gigaset/interface.c b/drivers/isdn/gigaset/interface.c index 3a81d9c..08e4c4e 100644 --- a/drivers/isdn/gigaset/interface.c +++ b/drivers/isdn/gigaset/interface.c @@ -9,8 +9,6 @@ * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * ===================================================================== - * Version: $Id: interface.c,v 1.14.4.15 2006/02/04 18:28:16 hjlipp Exp $ - * ===================================================================== */ #include "gigaset.h" @@ -24,7 +22,7 @@ static int if_lock(struct cardstate *cs, int *arg) { int cmd = *arg; - dbg(DEBUG_IF, "%u: if_lock (%d)", cs->minor_index, cmd); + gig_dbg(DEBUG_IF, "%u: if_lock (%d)", cs->minor_index, cmd); if (cmd > 1) return -EINVAL; @@ -35,7 +33,7 @@ static int if_lock(struct cardstate *cs, int *arg) } if (!cmd && atomic_read(&cs->mstate) == MS_LOCKED - && atomic_read(&cs->connected)) { + && cs->connected) { cs->ops->set_modem_ctrl(cs, 0, TIOCM_DTR|TIOCM_RTS); cs->ops->baud_rate(cs, B115200); cs->ops->set_line_ctrl(cs, CS8); @@ -44,12 +42,12 @@ static int if_lock(struct cardstate *cs, int *arg) cs->waiting = 1; if (!gigaset_add_event(cs, &cs->at_state, EV_IF_LOCK, - NULL, cmd, NULL)) { + NULL, cmd, NULL)) { cs->waiting = 0; return -ENOMEM; } - dbg(DEBUG_CMD, "scheduling IF_LOCK"); + gig_dbg(DEBUG_CMD, "scheduling IF_LOCK"); gigaset_schedule_event(cs); wait_event(cs->waitqueue, !cs->waiting); @@ -68,7 +66,7 @@ static int if_version(struct cardstate *cs, unsigned arg[4]) static const unsigned compat[4] = GIG_COMPAT; unsigned cmd = arg[0]; - dbg(DEBUG_IF, "%u: if_version (%d)", cs->minor_index, cmd); + gig_dbg(DEBUG_IF, "%u: if_version (%d)", cs->minor_index, cmd); switch (cmd) { case GIGVER_DRIVER: @@ -80,12 +78,12 @@ static int if_version(struct cardstate *cs, unsigned arg[4]) case GIGVER_FWBASE: cs->waiting = 1; if (!gigaset_add_event(cs, &cs->at_state, EV_IF_VER, - NULL, 0, arg)) { + NULL, 0, arg)) { cs->waiting = 0; return -ENOMEM; } - dbg(DEBUG_CMD, "scheduling IF_VER"); + gig_dbg(DEBUG_CMD, "scheduling IF_VER"); gigaset_schedule_event(cs); wait_event(cs->waitqueue, !cs->waiting); @@ -101,7 +99,7 @@ static int if_version(struct cardstate *cs, unsigned arg[4]) static int if_config(struct cardstate *cs, int *arg) { - dbg(DEBUG_IF, "%u: if_config (%d)", cs->minor_index, *arg); + gig_dbg(DEBUG_IF, "%u: if_config (%d)", cs->minor_index, *arg); if (*arg != 1) return -EINVAL; @@ -109,6 +107,11 @@ static int if_config(struct cardstate *cs, int *arg) if (atomic_read(&cs->mstate) != MS_LOCKED) return -EBUSY; + if (!cs->connected) { + err("not connected!"); + return -ENODEV; + } + *arg = 0; return gigaset_enterconfigmode(cs); } @@ -119,7 +122,7 @@ static int if_config(struct cardstate *cs, int *arg) static int if_open(struct tty_struct *tty, struct file *filp); static void if_close(struct tty_struct *tty, struct file *filp); static int if_ioctl(struct tty_struct *tty, struct file *file, - unsigned int cmd, unsigned long arg); + unsigned int cmd, unsigned long arg); static int if_write_room(struct tty_struct *tty); static int if_chars_in_buffer(struct tty_struct *tty); static void if_throttle(struct tty_struct *tty); @@ -127,9 +130,9 @@ static void if_unthrottle(struct tty_struct *tty); static void if_set_termios(struct tty_struct *tty, struct termios *old); static int if_tiocmget(struct tty_struct *tty, struct file *file); static int if_tiocmset(struct tty_struct *tty, struct file *file, - unsigned int set, unsigned int clear); + unsigned int set, unsigned int clear); static int if_write(struct tty_struct *tty, - const unsigned char *buf, int count); + const unsigned char *buf, int count); static struct tty_operations if_ops = { .open = if_open, @@ -153,8 +156,8 @@ static int if_open(struct tty_struct *tty, struct file *filp) struct cardstate *cs; unsigned long flags; - dbg(DEBUG_IF, "%d+%d: %s()", tty->driver->minor_start, tty->index, - __FUNCTION__); + gig_dbg(DEBUG_IF, "%d+%d: %s()", + tty->driver->minor_start, tty->index, __func__); tty->driver_data = NULL; @@ -162,7 +165,7 @@ static int if_open(struct tty_struct *tty, struct file *filp) if (!cs) return -ENODEV; - if (down_interruptible(&cs->sem)) + if (mutex_lock_interruptible(&cs->mutex)) return -ERESTARTSYS; // FIXME -EINTR? tty->driver_data = cs; @@ -173,10 +176,9 @@ static int if_open(struct tty_struct *tty, struct file *filp) cs->tty = tty; spin_unlock_irqrestore(&cs->lock, flags); tty->low_latency = 1; //FIXME test - //FIXME } - up(&cs->sem); + mutex_unlock(&cs->mutex); return 0; } @@ -187,30 +189,29 @@ static void if_close(struct tty_struct *tty, struct file *filp) cs = (struct cardstate *) tty->driver_data; if (!cs) { - err("cs==NULL in %s", __FUNCTION__); + err("cs==NULL in %s", __func__); return; } - dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __FUNCTION__); + gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__); - down(&cs->sem); + mutex_lock(&cs->mutex); if (!cs->open_count) - warn("%s: device not opened", __FUNCTION__); + warn("%s: device not opened", __func__); else { if (!--cs->open_count) { spin_lock_irqsave(&cs->lock, flags); cs->tty = NULL; spin_unlock_irqrestore(&cs->lock, flags); - //FIXME } } - up(&cs->sem); + mutex_unlock(&cs->mutex); } static int if_ioctl(struct tty_struct *tty, struct file *file, - unsigned int cmd, unsigned long arg) + unsigned int cmd, unsigned long arg) { struct cardstate *cs; int retval = -ENODEV; @@ -220,17 +221,17 @@ static int if_ioctl(struct tty_struct *tty, struct file *file, cs = (struct cardstate *) tty->driver_data; if (!cs) { - err("cs==NULL in %s", __FUNCTION__); + err("cs==NULL in %s", __func__); return -ENODEV; } - dbg(DEBUG_IF, "%u: %s(0x%x)", cs->minor_index, __FUNCTION__, cmd); + gig_dbg(DEBUG_IF, "%u: %s(0x%x)", cs->minor_index, __func__, cmd); - if (down_interruptible(&cs->sem)) + if (mutex_lock_interruptible(&cs->mutex)) return -ERESTARTSYS; // FIXME -EINTR? if (!cs->open_count) - warn("%s: device not opened", __FUNCTION__); + warn("%s: device not opened", __func__); else { retval = 0; switch (cmd) { @@ -250,37 +251,40 @@ static int if_ioctl(struct tty_struct *tty, struct file *file, break; case GIGASET_BRKCHARS: //FIXME test if MS_LOCKED - gigaset_dbg_buffer(DEBUG_IF, "GIGASET_BRKCHARS", - 6, (const unsigned char *) arg, 1); - if (!atomic_read(&cs->connected)) { - dbg(DEBUG_ANY, "can't communicate with unplugged device"); + if (!cs->connected) { + gig_dbg(DEBUG_ANY, + "can't communicate with unplugged device"); retval = -ENODEV; break; } retval = copy_from_user(&buf, - (const unsigned char __user *) arg, 6) - ? -EFAULT : 0; - if (retval >= 0) + (const unsigned char __user *) arg, 6) + ? -EFAULT : 0; + if (retval >= 0) { + gigaset_dbg_buffer(DEBUG_IF, "GIGASET_BRKCHARS", + 6, (const unsigned char *) arg); retval = cs->ops->brkchars(cs, buf); + } break; case GIGASET_VERSION: - retval = copy_from_user(version, (unsigned __user *) arg, - sizeof version) ? -EFAULT : 0; + retval = copy_from_user(version, + (unsigned __user *) arg, sizeof version) + ? -EFAULT : 0; if (retval >= 0) retval = if_version(cs, version); if (retval >= 0) - retval = copy_to_user((unsigned __user *) arg, version, - sizeof version) - ? -EFAULT : 0; + retval = copy_to_user((unsigned __user *) arg, + version, sizeof version) + ? -EFAULT : 0; break; - default: - dbg(DEBUG_ANY, "%s: arg not supported - 0x%04x", - __FUNCTION__, cmd); + default: + gig_dbg(DEBUG_ANY, "%s: arg not supported - 0x%04x", + __func__, cmd); retval = -ENOIOCTLCMD; } } - up(&cs->sem); + mutex_unlock(&cs->mutex); return retval; } @@ -292,25 +296,25 @@ static int if_tiocmget(struct tty_struct *tty, struct file *file) cs = (struct cardstate *) tty->driver_data; if (!cs) { - err("cs==NULL in %s", __FUNCTION__); + err("cs==NULL in %s", __func__); return -ENODEV; } - dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __FUNCTION__); + gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__); - if (down_interruptible(&cs->sem)) + if (mutex_lock_interruptible(&cs->mutex)) return -ERESTARTSYS; // FIXME -EINTR? // FIXME read from device? retval = cs->control_state & (TIOCM_RTS|TIOCM_DTR); - up(&cs->sem); + mutex_unlock(&cs->mutex); return retval; } static int if_tiocmset(struct tty_struct *tty, struct file *file, - unsigned int set, unsigned int clear) + unsigned int set, unsigned int clear) { struct cardstate *cs; int retval; @@ -318,18 +322,18 @@ static int if_tiocmset(struct tty_struct *tty, struct file *file, cs = (struct cardstate *) tty->driver_data; if (!cs) { - err("cs==NULL in %s", __FUNCTION__); + err("cs==NULL in %s", __func__); return -ENODEV; } - dbg(DEBUG_IF, - "%u: %s(0x%x, 0x%x)", cs->minor_index, __FUNCTION__, set, clear); + gig_dbg(DEBUG_IF, "%u: %s(0x%x, 0x%x)", + cs->minor_index, __func__, set, clear); - if (down_interruptible(&cs->sem)) + if (mutex_lock_interruptible(&cs->mutex)) return -ERESTARTSYS; // FIXME -EINTR? - if (!atomic_read(&cs->connected)) { - dbg(DEBUG_ANY, "can't communicate with unplugged device"); + if (!cs->connected) { + gig_dbg(DEBUG_ANY, "can't communicate with unplugged device"); retval = -ENODEV; } else { mc = (cs->control_state | set) & ~clear & (TIOCM_RTS|TIOCM_DTR); @@ -337,7 +341,7 @@ static int if_tiocmset(struct tty_struct *tty, struct file *file, cs->control_state = mc; } - up(&cs->sem); + mutex_unlock(&cs->mutex); return retval; } @@ -349,29 +353,29 @@ static int if_write(struct tty_struct *tty, const unsigned char *buf, int count) cs = (struct cardstate *) tty->driver_data; if (!cs) { - err("cs==NULL in %s", __FUNCTION__); + err("cs==NULL in %s", __func__); return -ENODEV; } - dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __FUNCTION__); + gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__); - if (down_interruptible(&cs->sem)) + if (mutex_lock_interruptible(&cs->mutex)) return -ERESTARTSYS; // FIXME -EINTR? if (!cs->open_count) - warn("%s: device not opened", __FUNCTION__); + warn("%s: device not opened", __func__); else if (atomic_read(&cs->mstate) != MS_LOCKED) { warn("can't write to unlocked device"); retval = -EBUSY; - } else if (!atomic_read(&cs->connected)) { - dbg(DEBUG_ANY, "can't write to unplugged device"); + } else if (!cs->connected) { + gig_dbg(DEBUG_ANY, "can't write to unplugged device"); retval = -EBUSY; //FIXME } else { retval = cs->ops->write_cmd(cs, buf, count, - &cs->if_wake_tasklet); + &cs->if_wake_tasklet); } - up(&cs->sem); + mutex_unlock(&cs->mutex); return retval; } @@ -383,27 +387,27 @@ static int if_write_room(struct tty_struct *tty) cs = (struct cardstate *) tty->driver_data; if (!cs) { - err("cs==NULL in %s", __FUNCTION__); + err("cs==NULL in %s", __func__); return -ENODEV; } - dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __FUNCTION__); + gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__); - if (down_interruptible(&cs->sem)) + if (mutex_lock_interruptible(&cs->mutex)) return -ERESTARTSYS; // FIXME -EINTR? if (!cs->open_count) - warn("%s: device not opened", __FUNCTION__); + warn("%s: device not opened", __func__); else if (atomic_read(&cs->mstate) != MS_LOCKED) { warn("can't write to unlocked device"); retval = -EBUSY; //FIXME - } else if (!atomic_read(&cs->connected)) { - dbg(DEBUG_ANY, "can't write to unplugged device"); + } else if (!cs->connected) { + gig_dbg(DEBUG_ANY, "can't write to unplugged device"); retval = -EBUSY; //FIXME } else retval = cs->ops->write_room(cs); - up(&cs->sem); + mutex_unlock(&cs->mutex); return retval; } @@ -415,27 +419,27 @@ static int if_chars_in_buffer(struct tty_struct *tty) cs = (struct cardstate *) tty->driver_data; if (!cs) { - err("cs==NULL in %s", __FUNCTION__); + err("cs==NULL in %s", __func__); return -ENODEV; } - dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __FUNCTION__); + gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__); - if (down_interruptible(&cs->sem)) + if (mutex_lock_interruptible(&cs->mutex)) return -ERESTARTSYS; // FIXME -EINTR? if (!cs->open_count) - warn("%s: device not opened", __FUNCTION__); + warn("%s: device not opened", __func__); else if (atomic_read(&cs->mstate) != MS_LOCKED) { warn("can't write to unlocked device"); retval = -EBUSY; - } else if (!atomic_read(&cs->connected)) { - dbg(DEBUG_ANY, "can't write to unplugged device"); + } else if (!cs->connected) { + gig_dbg(DEBUG_ANY, "can't write to unplugged device"); retval = -EBUSY; //FIXME } else retval = cs->ops->chars_in_buffer(cs); - up(&cs->sem); + mutex_unlock(&cs->mutex); return retval; } @@ -446,21 +450,21 @@ static void if_throttle(struct tty_struct *tty) cs = (struct cardstate *) tty->driver_data; if (!cs) { - err("cs==NULL in %s", __FUNCTION__); + err("cs==NULL in %s", __func__); return; } - dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __FUNCTION__); + gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__); - down(&cs->sem); + mutex_lock(&cs->mutex); if (!cs->open_count) - warn("%s: device not opened", __FUNCTION__); + warn("%s: device not opened", __func__); else { //FIXME } - up(&cs->sem); + mutex_unlock(&cs->mutex); } static void if_unthrottle(struct tty_struct *tty) @@ -469,21 +473,21 @@ static void if_unthrottle(struct tty_struct *tty) cs = (struct cardstate *) tty->driver_data; if (!cs) { - err("cs==NULL in %s", __FUNCTION__); + err("cs==NULL in %s", __func__); return; } - dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __FUNCTION__); + gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__); - down(&cs->sem); + mutex_lock(&cs->mutex); if (!cs->open_count) - warn("%s: device not opened", __FUNCTION__); + warn("%s: device not opened", __func__); else { //FIXME } - up(&cs->sem); + mutex_unlock(&cs->mutex); } static void if_set_termios(struct tty_struct *tty, struct termios *old) @@ -496,21 +500,21 @@ static void if_set_termios(struct tty_struct *tty, struct termios *old) cs = (struct cardstate *) tty->driver_data; if (!cs) { - err("cs==NULL in %s", __FUNCTION__); + err("cs==NULL in %s", __func__); return; } - dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __FUNCTION__); + gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__); - down(&cs->sem); + mutex_lock(&cs->mutex); if (!cs->open_count) { - warn("%s: device not opened", __FUNCTION__); + warn("%s: device not opened", __func__); goto out; } - if (!atomic_read(&cs->connected)) { - dbg(DEBUG_ANY, "can't communicate with unplugged device"); + if (!cs->connected) { + gig_dbg(DEBUG_ANY, "can't communicate with unplugged device"); goto out; } @@ -518,8 +522,8 @@ static void if_set_termios(struct tty_struct *tty, struct termios *old) iflag = tty->termios->c_iflag; cflag = tty->termios->c_cflag; old_cflag = old ? old->c_cflag : cflag; //FIXME? - dbg(DEBUG_IF, "%u: iflag %x cflag %x old %x", cs->minor_index, - iflag, cflag, old_cflag); + gig_dbg(DEBUG_IF, "%u: iflag %x cflag %x old %x", + cs->minor_index, iflag, cflag, old_cflag); /* get a local copy of the current port settings */ control_state = cs->control_state; @@ -531,14 +535,15 @@ static void if_set_termios(struct tty_struct *tty, struct termios *old) * Premature optimization is the root of all evil. */ - /* reassert DTR and (maybe) RTS on transition from B0 */ + /* reassert DTR and (maybe) RTS on transition from B0 */ if ((old_cflag & CBAUD) == B0) { new_state = control_state | TIOCM_DTR; /* don't set RTS if using hardware flow control */ if (!(old_cflag & CRTSCTS)) new_state |= TIOCM_RTS; - dbg(DEBUG_IF, "%u: from B0 - set DTR%s", cs->minor_index, - (new_state & TIOCM_RTS) ? " only" : "/RTS"); + gig_dbg(DEBUG_IF, "%u: from B0 - set DTR%s", + cs->minor_index, + (new_state & TIOCM_RTS) ? " only" : "/RTS"); cs->ops->set_modem_ctrl(cs, control_state, new_state); control_state = new_state; } @@ -547,7 +552,7 @@ static void if_set_termios(struct tty_struct *tty, struct termios *old) if ((cflag & CBAUD) == B0) { /* Drop RTS and DTR */ - dbg(DEBUG_IF, "%u: to B0 - drop DTR/RTS", cs->minor_index); + gig_dbg(DEBUG_IF, "%u: to B0 - drop DTR/RTS", cs->minor_index); new_state = control_state & ~(TIOCM_DTR | TIOCM_RTS); cs->ops->set_modem_ctrl(cs, control_state, new_state); control_state = new_state; @@ -567,15 +572,17 @@ static void if_set_termios(struct tty_struct *tty, struct termios *old) * Just do what we have seen with SniffUSB on Win98. */ /* Drop DTR/RTS if no flow control otherwise assert */ - dbg(DEBUG_IF, "%u: control_state %x", cs->minor_index, control_state); + gig_dbg(DEBUG_IF, "%u: control_state %x", + cs->minor_index, control_state); new_state = control_state; if ((iflag & IXOFF) || (iflag & IXON) || (cflag & CRTSCTS)) new_state |= TIOCM_DTR | TIOCM_RTS; else new_state &= ~(TIOCM_DTR | TIOCM_RTS); if (new_state != control_state) { - dbg(DEBUG_IF, "%u: new_state %x", cs->minor_index, new_state); - gigaset_set_modem_ctrl(cs, control_state, new_state); // FIXME: mct_u232.c sets the old state here. is this a bug? + gig_dbg(DEBUG_IF, "%u: new_state %x", + cs->minor_index, new_state); + gigaset_set_modem_ctrl(cs, control_state, new_state); control_state = new_state; } #endif @@ -584,7 +591,7 @@ static void if_set_termios(struct tty_struct *tty, struct termios *old) cs->control_state = control_state; out: - up(&cs->sem); + mutex_unlock(&cs->mutex); } @@ -600,7 +607,7 @@ static void if_wake(unsigned long data) if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) { - dbg(DEBUG_IF, "write wakeup call"); + gig_dbg(DEBUG_IF, "write wakeup call"); tty->ldisc.write_wakeup(tty); } @@ -635,14 +642,14 @@ void gigaset_if_free(struct cardstate *cs) } void gigaset_if_receive(struct cardstate *cs, - unsigned char *buffer, size_t len) + unsigned char *buffer, size_t len) { unsigned long flags; struct tty_struct *tty; spin_lock_irqsave(&cs->lock, flags); if ((tty = cs->tty) == NULL) - dbg(DEBUG_ANY, "receive on closed device"); + gig_dbg(DEBUG_ANY, "receive on closed device"); else { tty_buffer_request_room(tty, len); tty_insert_flip_string(tty, buffer, len); @@ -655,13 +662,13 @@ EXPORT_SYMBOL_GPL(gigaset_if_receive); /* gigaset_if_initdriver * Initialize tty interface. * parameters: - * drv Driver - * procname Name of the driver (e.g. for /proc/tty/drivers) - * devname Name of the device files (prefix without minor number) - * devfsname Devfs name of the device files without %d + * drv Driver + * procname Name of the driver (e.g. for /proc/tty/drivers) + * devname Name of the device files (prefix without minor number) + * devfsname Devfs name of the device files without %d */ void gigaset_if_initdriver(struct gigaset_driver *drv, const char *procname, - const char *devname, const char *devfsname) + const char *devname, const char *devfsname) { unsigned minors = drv->minors; int ret; @@ -696,7 +703,7 @@ void gigaset_if_initdriver(struct gigaset_driver *drv, const char *procname, warn("failed to register tty driver (error %d)", ret); goto error; } - dbg(DEBUG_IF, "tty driver initialized"); + gig_dbg(DEBUG_IF, "tty driver initialized"); drv->have_tty = 1; return; diff --git a/drivers/isdn/gigaset/isocdata.c b/drivers/isdn/gigaset/isocdata.c index 5744eb9..45f017e 100644 --- a/drivers/isdn/gigaset/isocdata.c +++ b/drivers/isdn/gigaset/isocdata.c @@ -10,10 +10,6 @@ * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * ===================================================================== - * ToDo: ... - * ===================================================================== - * Version: $Id: isocdata.c,v 1.2.2.5 2005/11/13 23:05:19 hjlipp Exp $ - * ===================================================================== */ #include "gigaset.h" @@ -87,14 +83,14 @@ static inline int isowbuf_startwrite(struct isowbuf_t *iwb) { if (!atomic_dec_and_test(&iwb->writesem)) { atomic_inc(&iwb->writesem); - dbg(DEBUG_ISO, - "%s: couldn't acquire iso write semaphore", __func__); + gig_dbg(DEBUG_ISO, "%s: couldn't acquire iso write semaphore", + __func__); return 0; } #ifdef CONFIG_GIGASET_DEBUG - dbg(DEBUG_ISO, - "%s: acquired iso write semaphore, data[write]=%02x, nbits=%d", - __func__, iwb->data[atomic_read(&iwb->write)], iwb->wbits); + gig_dbg(DEBUG_ISO, + "%s: acquired iso write semaphore, data[write]=%02x, nbits=%d", + __func__, iwb->data[atomic_read(&iwb->write)], iwb->wbits); #endif return 1; } @@ -147,7 +143,7 @@ static inline void isowbuf_putflag(struct isowbuf_t *iwb) /* recover the idle flag byte */ write = atomic_read(&iwb->write); iwb->idle = iwb->data[write]; - dbg(DEBUG_ISO, "idle fill byte %02x", iwb->idle); + gig_dbg(DEBUG_ISO, "idle fill byte %02x", iwb->idle); /* mask extraneous bits in buffer */ iwb->data[write] &= (1 << iwb->wbits) - 1; } @@ -166,15 +162,14 @@ int gigaset_isowbuf_getbytes(struct isowbuf_t *iwb, int size) read = atomic_read(&iwb->nextread); write = atomic_read(&iwb->write); if (likely(read == write)) { - //dbg(DEBUG_STREAM, "%s: send buffer empty", __func__); /* return idle frame */ return read < BAS_OUTBUFPAD ? - BAS_OUTBUFSIZE : read - BAS_OUTBUFPAD; + BAS_OUTBUFSIZE : read - BAS_OUTBUFPAD; } limit = read + size; - dbg(DEBUG_STREAM, - "%s: read=%d write=%d limit=%d", __func__, read, write, limit); + gig_dbg(DEBUG_STREAM, "%s: read=%d write=%d limit=%d", + __func__, read, write, limit); #ifdef CONFIG_GIGASET_DEBUG if (unlikely(size < 0 || size > BAS_OUTBUFPAD)) { err("invalid size %d", size); @@ -196,11 +191,12 @@ int gigaset_isowbuf_getbytes(struct isowbuf_t *iwb, int size) return -EBUSY; /* write position could have changed */ if (limit >= (write = atomic_read(&iwb->write))) { - pbyte = iwb->data[write]; /* save partial byte */ + pbyte = iwb->data[write]; /* save + partial byte */ limit = write + BAS_OUTBUFPAD; - dbg(DEBUG_STREAM, - "%s: filling %d->%d with %02x", - __func__, write, limit, iwb->idle); + gig_dbg(DEBUG_STREAM, + "%s: filling %d->%d with %02x", + __func__, write, limit, iwb->idle); if (write + BAS_OUTBUFPAD < BAS_OUTBUFSIZE) memset(iwb->data + write, iwb->idle, BAS_OUTBUFPAD); @@ -211,9 +207,11 @@ int gigaset_isowbuf_getbytes(struct isowbuf_t *iwb, int size) - write); limit = 0; } - dbg(DEBUG_STREAM, "%s: restoring %02x at %d", - __func__, pbyte, limit); - iwb->data[limit] = pbyte; /* restore partial byte */ + gig_dbg(DEBUG_STREAM, + "%s: restoring %02x at %d", + __func__, pbyte, limit); + iwb->data[limit] = pbyte; /* restore + partial byte */ atomic_set(&iwb->write, limit); } isowbuf_donewrite(iwb); @@ -242,19 +240,17 @@ int gigaset_isowbuf_getbytes(struct isowbuf_t *iwb, int size) * write hex bytes to syslog for debugging */ static inline void dump_bytes(enum debuglevel level, const char *tag, - unsigned char *bytes, int count) + unsigned char *bytes, int count) { #ifdef CONFIG_GIGASET_DEBUG unsigned char c; static char dbgline[3 * 32 + 1]; static const char hexdigit[] = "0123456789abcdef"; int i = 0; - IFNULLRET(tag); - IFNULLRET(bytes); while (count-- > 0) { if (i > sizeof(dbgline) - 4) { dbgline[i] = '\0'; - dbg(level, "%s:%s", tag, dbgline); + gig_dbg(level, "%s:%s", tag, dbgline); i = 0; } c = *bytes++; @@ -264,7 +260,7 @@ static inline void dump_bytes(enum debuglevel level, const char *tag, dbgline[i++] = hexdigit[c & 0x0f]; } dbgline[i] = '\0'; - dbg(level, "%s:%s", tag, dbgline); + gig_dbg(level, "%s:%s", tag, dbgline); #endif } @@ -380,7 +376,7 @@ static u16 stufftab[5 * 256] = { */ static inline int hdlc_bitstuff_byte(struct isowbuf_t *iwb, unsigned char cin, - int ones) + int ones) { u16 stuff; int shiftinc, newones; @@ -422,7 +418,7 @@ static inline int hdlc_bitstuff_byte(struct isowbuf_t *iwb, unsigned char cin, */ static inline int hdlc_buildframe(struct isowbuf_t *iwb, - unsigned char *in, int count) + unsigned char *in, int count) { int ones; u16 fcs; @@ -431,8 +427,8 @@ static inline int hdlc_buildframe(struct isowbuf_t *iwb, if (isowbuf_freebytes(iwb) < count + count / 5 + 6 || !isowbuf_startwrite(iwb)) { - dbg(DEBUG_ISO, "%s: %d bytes free -> -EAGAIN", - __func__, isowbuf_freebytes(iwb)); + gig_dbg(DEBUG_ISO, "%s: %d bytes free -> -EAGAIN", + __func__, isowbuf_freebytes(iwb)); return -EAGAIN; } @@ -484,11 +480,11 @@ static inline int trans_buildframe(struct isowbuf_t *iwb, if (isowbuf_freebytes(iwb) < count || !isowbuf_startwrite(iwb)) { - dbg(DEBUG_ISO, "can't put %d bytes", count); + gig_dbg(DEBUG_ISO, "can't put %d bytes", count); return -EAGAIN; } - dbg(DEBUG_STREAM, "put %d bytes", count); + gig_dbg(DEBUG_STREAM, "put %d bytes", count); write = atomic_read(&iwb->write); do { c = gigaset_invtab[*in++]; @@ -508,11 +504,13 @@ int gigaset_isoc_buildframe(struct bc_state *bcs, unsigned char *in, int len) switch (bcs->proto2) { case ISDN_PROTO_L2_HDLC: result = hdlc_buildframe(bcs->hw.bas->isooutbuf, in, len); - dbg(DEBUG_ISO, "%s: %d bytes HDLC -> %d", __func__, len, result); + gig_dbg(DEBUG_ISO, "%s: %d bytes HDLC -> %d", + __func__, len, result); break; default: /* assume transparent */ result = trans_buildframe(bcs->hw.bas->isooutbuf, in, len); - dbg(DEBUG_ISO, "%s: %d bytes trans -> %d", __func__, len, result); + gig_dbg(DEBUG_ISO, "%s: %d bytes trans -> %d", + __func__, len, result); } return result; } @@ -528,13 +526,13 @@ static inline void hdlc_putbyte(unsigned char c, struct bc_state *bcs) return; } if (unlikely(bcs->skb->len == SBUFSIZE)) { - warn("received oversized packet discarded"); + dev_warn(bcs->cs->dev, "received oversized packet discarded\n"); bcs->hw.bas->giants++; dev_kfree_skb_any(bcs->skb); bcs->skb = NULL; return; } - *gigaset_skb_put_quick(bcs->skb, 1) = c; + *__skb_put(bcs->skb, 1) = c; } /* hdlc_flush @@ -549,7 +547,7 @@ static inline void hdlc_flush(struct bc_state *bcs) if ((bcs->skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL) skb_reserve(bcs->skb, HW_HDR_LEN); else - err("could not allocate skb"); + dev_err(bcs->cs->dev, "could not allocate skb\n"); } /* reset packet state */ @@ -571,23 +569,25 @@ static inline void hdlc_done(struct bc_state *bcs) if ((procskb = bcs->skb) == NULL) { /* previous error */ - dbg(DEBUG_ISO, "%s: skb=NULL", __func__); + gig_dbg(DEBUG_ISO, "%s: skb=NULL", __func__); gigaset_rcv_error(NULL, bcs->cs, bcs); } else if (procskb->len < 2) { - notice("received short frame (%d octets)", procskb->len); + dev_notice(bcs->cs->dev, "received short frame (%d octets)\n", + procskb->len); bcs->hw.bas->runts++; gigaset_rcv_error(procskb, bcs->cs, bcs); } else if (bcs->fcs != PPP_GOODFCS) { - notice("frame check error (0x%04x)", bcs->fcs); + dev_notice(bcs->cs->dev, "frame check error (0x%04x)\n", + bcs->fcs); bcs->hw.bas->fcserrs++; gigaset_rcv_error(procskb, bcs->cs, bcs); } else { procskb->len -= 2; /* subtract FCS */ procskb->tail -= 2; - dbg(DEBUG_ISO, - "%s: good frame (%d octets)", __func__, procskb->len); + gig_dbg(DEBUG_ISO, "%s: good frame (%d octets)", + __func__, procskb->len); dump_bytes(DEBUG_STREAM, - "rcv data", procskb->data, procskb->len); + "rcv data", procskb->data, procskb->len); bcs->hw.bas->goodbytes += procskb->len; gigaset_rcv_skb(procskb, bcs->cs, bcs); } @@ -595,7 +595,7 @@ static inline void hdlc_done(struct bc_state *bcs) if ((bcs->skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL) skb_reserve(bcs->skb, HW_HDR_LEN); else - err("could not allocate skb"); + dev_err(bcs->cs->dev, "could not allocate skb\n"); bcs->fcs = PPP_INITFCS; } @@ -610,14 +610,14 @@ static inline void hdlc_frag(struct bc_state *bcs, unsigned inbits) return; } - notice("received partial byte (%d bits)", inbits); + dev_notice(bcs->cs->dev, "received partial byte (%d bits)\n", inbits); bcs->hw.bas->alignerrs++; gigaset_rcv_error(bcs->skb, bcs->cs, bcs); if ((bcs->skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL) skb_reserve(bcs->skb, HW_HDR_LEN); else - err("could not allocate skb"); + dev_err(bcs->cs->dev, "could not allocate skb\n"); bcs->fcs = PPP_INITFCS; } @@ -659,16 +659,12 @@ static unsigned char bitcounts[256] = { * bcs receiving B channel structure */ static inline void hdlc_unpack(unsigned char *src, unsigned count, - struct bc_state *bcs) + struct bc_state *bcs) { - struct bas_bc_state *ubc; + struct bas_bc_state *ubc = bcs->hw.bas; int inputstate; unsigned seqlen, inbyte, inbits; - IFNULLRET(bcs); - ubc = bcs->hw.bas; - IFNULLRET(ubc); - /* load previous state: * inputstate = set of flag bits: * - INS_flag_hunt: no complete opening flag received since connection setup or last abort @@ -856,7 +852,7 @@ static inline void hdlc_unpack(unsigned char *src, unsigned count, * bcs receiving B channel structure */ static inline void trans_receive(unsigned char *src, unsigned count, - struct bc_state *bcs) + struct bc_state *bcs) { struct sk_buff *skb; int dobytes; @@ -870,7 +866,7 @@ static inline void trans_receive(unsigned char *src, unsigned count, if (unlikely((skb = bcs->skb) == NULL)) { bcs->skb = skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN); if (!skb) { - err("could not allocate skb"); + dev_err(bcs->cs->dev, "could not allocate skb\n"); return; } skb_reserve(skb, HW_HDR_LEN); @@ -888,7 +884,8 @@ static inline void trans_receive(unsigned char *src, unsigned count, gigaset_rcv_skb(skb, bcs->cs, bcs); bcs->skb = skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN); if (!skb) { - err("could not allocate skb"); + dev_err(bcs->cs->dev, + "could not allocate skb\n"); return; } skb_reserve(bcs->skb, HW_HDR_LEN); @@ -921,8 +918,8 @@ static void cmd_loop(unsigned char *src, int numbytes, struct inbuf_t *inbuf) case '\r': case '\n': /* end of line */ - dbg(DEBUG_TRANSCMD, "%s: End of Command (%d Bytes)", - __func__, cbytes); + gig_dbg(DEBUG_TRANSCMD, "%s: End of Command (%d Bytes)", + __func__, cbytes); cs->cbytes = cbytes; gigaset_handle_modem_response(cs); cbytes = 0; @@ -932,7 +929,7 @@ static void cmd_loop(unsigned char *src, int numbytes, struct inbuf_t *inbuf) if (cbytes < MAX_RESP_SIZE - 1) cbytes++; else - warn("response too large"); + dev_warn(cs->dev, "response too large\n"); } } @@ -951,27 +948,27 @@ void gigaset_isoc_input(struct inbuf_t *inbuf) head = atomic_read(&inbuf->head); while (head != (tail = atomic_read(&inbuf->tail))) { - dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail); + gig_dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail); if (head > tail) tail = RBUFSIZE; src = inbuf->data + head; numbytes = tail - head; - dbg(DEBUG_INTR, "processing %u bytes", numbytes); + gig_dbg(DEBUG_INTR, "processing %u bytes", numbytes); if (atomic_read(&cs->mstate) == MS_LOCKED) { gigaset_dbg_buffer(DEBUG_LOCKCMD, "received response", - numbytes, src, 0); + numbytes, src); gigaset_if_receive(inbuf->cs, src, numbytes); } else { gigaset_dbg_buffer(DEBUG_CMD, "received response", - numbytes, src, 0); + numbytes, src); cmd_loop(src, numbytes, inbuf); } head += numbytes; if (head == RBUFSIZE) head = 0; - dbg(DEBUG_INTR, "setting head to %u", head); + gig_dbg(DEBUG_INTR, "setting head to %u", head); atomic_set(&inbuf->head, head); } } @@ -992,18 +989,18 @@ void gigaset_isoc_input(struct inbuf_t *inbuf) */ int gigaset_isoc_send_skb(struct bc_state *bcs, struct sk_buff *skb) { - int len; - - IFNULLRETVAL(bcs, -EFAULT); - IFNULLRETVAL(skb, -EFAULT); - len = skb->len; + int len = skb->len; + unsigned long flags; skb_queue_tail(&bcs->squeue, skb); - dbg(DEBUG_ISO, - "%s: skb queued, qlen=%d", __func__, skb_queue_len(&bcs->squeue)); + gig_dbg(DEBUG_ISO, "%s: skb queued, qlen=%d", + __func__, skb_queue_len(&bcs->squeue)); /* tasklet submits URB if necessary */ - tasklet_schedule(&bcs->hw.bas->sent_tasklet); + spin_lock_irqsave(&bcs->cs->lock, flags); + if (bcs->cs->connected) + tasklet_schedule(&bcs->hw.bas->sent_tasklet); + spin_unlock_irqrestore(&bcs->cs->lock, flags); return len; /* ok so far */ } diff --git a/drivers/isdn/gigaset/proc.c b/drivers/isdn/gigaset/proc.c index c6915fa..d267a63 100644 --- a/drivers/isdn/gigaset/proc.c +++ b/drivers/isdn/gigaset/proc.c @@ -1,7 +1,7 @@ /* * Stuff used by all variants of the driver * - * Copyright (c) 2001 by Stefan Eilers <Eilers.Stefan@epost.de>, + * Copyright (c) 2001 by Stefan Eilers, * Hansjoerg Lipp <hjlipp@web.de>, * Tilman Schmidt <tilman@imap.cc>. * @@ -11,26 +11,29 @@ * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * ===================================================================== - * ToDo: ... - * ===================================================================== - * Version: $Id: proc.c,v 1.5.2.13 2006/02/04 18:28:16 hjlipp Exp $ - * ===================================================================== */ #include "gigaset.h" #include <linux/ctype.h> -static ssize_t show_cidmode(struct device *dev, struct device_attribute *attr, char *buf) +static ssize_t show_cidmode(struct device *dev, struct device_attribute *attr, + char *buf) { - struct usb_interface *intf = to_usb_interface(dev); - struct cardstate *cs = usb_get_intfdata(intf); - return sprintf(buf, "%d\n", atomic_read(&cs->cidmode)); // FIXME use scnprintf for 13607 bit architectures (if PAGE_SIZE==4096) + int ret; + unsigned long flags; + struct cardstate *cs = dev_get_drvdata(dev); + + spin_lock_irqsave(&cs->lock, flags); + ret = sprintf(buf, "%u\n", cs->cidmode); + spin_unlock_irqrestore(&cs->lock, flags); + + return ret; } -static ssize_t set_cidmode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +static ssize_t set_cidmode(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { - struct usb_interface *intf = to_usb_interface(dev); - struct cardstate *cs = usb_get_intfdata(intf); + struct cardstate *cs = dev_get_drvdata(dev); long int value; char *end; @@ -41,23 +44,23 @@ static ssize_t set_cidmode(struct device *dev, struct device_attribute *attr, co if (value < 0 || value > 1) return -EINVAL; - if (down_interruptible(&cs->sem)) + if (mutex_lock_interruptible(&cs->mutex)) return -ERESTARTSYS; // FIXME -EINTR? cs->waiting = 1; if (!gigaset_add_event(cs, &cs->at_state, EV_PROC_CIDMODE, - NULL, value, NULL)) { + NULL, value, NULL)) { cs->waiting = 0; - up(&cs->sem); + mutex_unlock(&cs->mutex); return -ENOMEM; } - dbg(DEBUG_CMD, "scheduling PROC_CIDMODE"); + gig_dbg(DEBUG_CMD, "scheduling PROC_CIDMODE"); gigaset_schedule_event(cs); wait_event(cs->waitqueue, !cs->waiting); - up(&cs->sem); + mutex_unlock(&cs->mutex); return count; } @@ -65,17 +68,15 @@ static ssize_t set_cidmode(struct device *dev, struct device_attribute *attr, co static DEVICE_ATTR(cidmode, S_IRUGO|S_IWUSR, show_cidmode, set_cidmode); /* free sysfs for device */ -void gigaset_free_dev_sysfs(struct usb_interface *interface) +void gigaset_free_dev_sysfs(struct cardstate *cs) { - dbg(DEBUG_INIT, "removing sysfs entries"); - device_remove_file(&interface->dev, &dev_attr_cidmode); + gig_dbg(DEBUG_INIT, "removing sysfs entries"); + device_remove_file(cs->dev, &dev_attr_cidmode); } -EXPORT_SYMBOL_GPL(gigaset_free_dev_sysfs); /* initialize sysfs for device */ -void gigaset_init_dev_sysfs(struct usb_interface *interface) +void gigaset_init_dev_sysfs(struct cardstate *cs) { - dbg(DEBUG_INIT, "setting up sysfs"); - device_create_file(&interface->dev, &dev_attr_cidmode); + gig_dbg(DEBUG_INIT, "setting up sysfs"); + device_create_file(cs->dev, &dev_attr_cidmode); } -EXPORT_SYMBOL_GPL(gigaset_init_dev_sysfs); diff --git a/drivers/isdn/gigaset/usb-gigaset.c b/drivers/isdn/gigaset/usb-gigaset.c index 323fc73..bfb73fd 100644 --- a/drivers/isdn/gigaset/usb-gigaset.c +++ b/drivers/isdn/gigaset/usb-gigaset.c @@ -1,7 +1,7 @@ /* * USB driver for Gigaset 307x directly or using M105 Data. * - * Copyright (c) 2001 by Stefan Eilers <Eilers.Stefan@epost.de> + * Copyright (c) 2001 by Stefan Eilers * and Hansjoerg Lipp <hjlipp@web.de>. * * This driver was derived from the USB skeleton driver by @@ -13,10 +13,6 @@ * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * ===================================================================== - * ToDo: ... - * ===================================================================== - * Version: $Id: usb-gigaset.c,v 1.85.4.18 2006/02/04 18:28:16 hjlipp Exp $ - * ===================================================================== */ #include "gigaset.h" @@ -29,7 +25,7 @@ #include <linux/moduleparam.h> /* Version Information */ -#define DRIVER_AUTHOR "Hansjoerg Lipp <hjlipp@web.de>, Stefan Eilers <Eilers.Stefan@epost.de>" +#define DRIVER_AUTHOR "Hansjoerg Lipp <hjlipp@web.de>, Stefan Eilers" #define DRIVER_DESC "USB Driver for Gigaset 307x using M105" /* Module parameters */ @@ -62,10 +58,6 @@ static struct usb_device_id gigaset_table [] = { MODULE_DEVICE_TABLE(usb, gigaset_table); -/* Get a minor range for your devices from the usb maintainer */ -#define USB_SKEL_MINOR_BASE 200 - - /* * Control requests (empty fields: 00) * @@ -114,7 +106,7 @@ MODULE_DEVICE_TABLE(usb, gigaset_table); */ static int gigaset_probe(struct usb_interface *interface, - const struct usb_device_id *id); + const struct usb_device_id *id); static void gigaset_disconnect(struct usb_interface *interface); static struct gigaset_driver *driver = NULL; @@ -122,29 +114,29 @@ static struct cardstate *cardstate = NULL; /* usb specific object needed to register this driver with the usb subsystem */ static struct usb_driver gigaset_usb_driver = { - .name = GIGASET_MODULENAME, - .probe = gigaset_probe, - .disconnect = gigaset_disconnect, - .id_table = gigaset_table, + .name = GIGASET_MODULENAME, + .probe = gigaset_probe, + .disconnect = gigaset_disconnect, + .id_table = gigaset_table, }; struct usb_cardstate { - struct usb_device *udev; /* save off the usb device pointer */ - struct usb_interface *interface; /* the interface for this device */ - atomic_t busy; /* bulk output in progress */ - - /* Output buffer for commands (M105: and data)*/ - unsigned char *bulk_out_buffer; /* the buffer to send data */ - int bulk_out_size; /* the size of the send buffer */ - __u8 bulk_out_endpointAddr; /* the address of the bulk out endpoint */ - struct urb *bulk_out_urb; /* the urb used to transmit data */ - - /* Input buffer for command responses (M105: and data)*/ - int rcvbuf_size; /* the size of the receive buffer */ - struct urb *read_urb; /* the urb used to receive data */ - __u8 int_in_endpointAddr; /* the address of the bulk in endpoint */ - - char bchars[6]; /* req. 0x19 */ + struct usb_device *udev; /* usb device pointer */ + struct usb_interface *interface; /* interface for this device */ + atomic_t busy; /* bulk output in progress */ + + /* Output buffer */ + unsigned char *bulk_out_buffer; + int bulk_out_size; + __u8 bulk_out_endpointAddr; + struct urb *bulk_out_urb; + + /* Input buffer */ + int rcvbuf_size; + struct urb *read_urb; + __u8 int_in_endpointAddr; + + char bchars[6]; /* for request 0x19 */ }; struct usb_bc_state {}; @@ -157,19 +149,20 @@ static inline unsigned tiocm_to_gigaset(unsigned state) #ifdef CONFIG_GIGASET_UNDOCREQ /* WARNING: EXPERIMENTAL! */ static int gigaset_set_modem_ctrl(struct cardstate *cs, unsigned old_state, - unsigned new_state) + unsigned new_state) { + struct usb_device *udev = cs->hw.usb->udev; unsigned mask, val; int r; mask = tiocm_to_gigaset(old_state ^ new_state); val = tiocm_to_gigaset(new_state); - dbg(DEBUG_USBREQ, "set flags 0x%02x with mask 0x%02x", val, mask); - r = usb_control_msg(cs->hw.usb->udev, - usb_sndctrlpipe(cs->hw.usb->udev, 0), 7, 0x41, - (val & 0xff) | ((mask & 0xff) << 8), 0, - NULL, 0, 2000 /*timeout??*/); // don't use this in an interrupt/BH + gig_dbg(DEBUG_USBREQ, "set flags 0x%02x with mask 0x%02x", val, mask); + // don't use this in an interrupt/BH + r = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 7, 0x41, + (val & 0xff) | ((mask & 0xff) << 8), 0, + NULL, 0, 2000 /* timeout? */); if (r < 0) return r; //.. @@ -178,30 +171,29 @@ static int gigaset_set_modem_ctrl(struct cardstate *cs, unsigned old_state, static int set_value(struct cardstate *cs, u8 req, u16 val) { + struct usb_device *udev = cs->hw.usb->udev; int r, r2; - dbg(DEBUG_USBREQ, "request %02x (%04x)", (unsigned)req, (unsigned)val); - r = usb_control_msg(cs->hw.usb->udev, - usb_sndctrlpipe(cs->hw.usb->udev, 0), 0x12, 0x41, - 0xf /*?*/, 0, - NULL, 0, 2000 /*?*/); /* no idea, what this does */ + gig_dbg(DEBUG_USBREQ, "request %02x (%04x)", + (unsigned)req, (unsigned)val); + r = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x12, 0x41, + 0xf /*?*/, 0, NULL, 0, 2000 /*?*/); + /* no idea what this does */ if (r < 0) { - err("error %d on request 0x12", -r); + dev_err(&udev->dev, "error %d on request 0x12\n", -r); return r; } - r = usb_control_msg(cs->hw.usb->udev, - usb_sndctrlpipe(cs->hw.usb->udev, 0), req, 0x41, - val, 0, - NULL, 0, 2000 /*?*/); + r = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), req, 0x41, + val, 0, NULL, 0, 2000 /*?*/); if (r < 0) - err("error %d on request 0x%02x", -r, (unsigned)req); + dev_err(&udev->dev, "error %d on request 0x%02x\n", + -r, (unsigned)req); - r2 = usb_control_msg(cs->hw.usb->udev, - usb_sndctrlpipe(cs->hw.usb->udev, 0), 0x19, 0x41, - 0, 0, cs->hw.usb->bchars, 6, 2000 /*?*/); + r2 = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x19, 0x41, + 0, 0, cs->hw.usb->bchars, 6, 2000 /*?*/); if (r2 < 0) - err("error %d on request 0x19", -r2); + dev_err(&udev->dev, "error %d on request 0x19\n", -r2); return r < 0 ? r : (r2 < 0 ? r2 : 0); } @@ -229,8 +221,8 @@ static int gigaset_baud_rate(struct cardstate *cs, unsigned cflag) case B115200: rate = 115200; break; default: rate = 9600; - err("unsupported baudrate request 0x%x," - " using default of B9600", cflag); + dev_err(cs->dev, "unsupported baudrate request 0x%x," + " using default of B9600\n", cflag); } val = 0x383fff / rate + 1; @@ -259,7 +251,7 @@ static int gigaset_set_line_ctrl(struct cardstate *cs, unsigned cflag) case CS8: val |= 8 << 8; break; default: - err("CSIZE was not CS5-CS8, using default of 8"); + dev_err(cs->dev, "CSIZE was not CS5-CS8, using default of 8\n"); val |= 8 << 8; break; } @@ -277,7 +269,7 @@ static int gigaset_set_line_ctrl(struct cardstate *cs, unsigned cflag) #else static int gigaset_set_modem_ctrl(struct cardstate *cs, unsigned old_state, - unsigned new_state) + unsigned new_state) { return -EINVAL; } @@ -309,15 +301,12 @@ static int gigaset_close_bchannel(struct bc_state *bcs) return 0; } -//void send_ack_to_LL(void *data); static int write_modem(struct cardstate *cs); static int send_cb(struct cardstate *cs, struct cmdbuf_t *cb); -/* Handling of send queue. If there is already a skb opened, put data to - * the transfer buffer by calling "write_modem". Otherwise take a new skb out of the queue. - * This function will be called by the ISR via "transmit_chars" (USB: B-Channel Bulk callback handler - * via immediate task queue) or by writebuf_from_LL if the LL wants to transmit data. +/* Write tasklet handler: Continue sending current skb, or send command, or + * start sending an skb from the send queue. */ static void gigaset_modem_fill(unsigned long data) { @@ -327,10 +316,10 @@ static void gigaset_modem_fill(unsigned long data) unsigned long flags; int again; - dbg(DEBUG_OUTPUT, "modem_fill"); + gig_dbg(DEBUG_OUTPUT, "modem_fill"); if (atomic_read(&cs->hw.usb->busy)) { - dbg(DEBUG_OUTPUT, "modem_fill: busy"); + gig_dbg(DEBUG_OUTPUT, "modem_fill: busy"); return; } @@ -341,26 +330,27 @@ static void gigaset_modem_fill(unsigned long data) cb = cs->cmdbuf; spin_unlock_irqrestore(&cs->cmdlock, flags); if (cb) { /* commands to send? */ - dbg(DEBUG_OUTPUT, "modem_fill: cb"); + gig_dbg(DEBUG_OUTPUT, "modem_fill: cb"); if (send_cb(cs, cb) < 0) { - dbg(DEBUG_OUTPUT, - "modem_fill: send_cb failed"); - again = 1; /* no callback will be called! */ + gig_dbg(DEBUG_OUTPUT, + "modem_fill: send_cb failed"); + again = 1; /* no callback will be + called! */ } } else { /* skbs to send? */ bcs->tx_skb = skb_dequeue(&bcs->squeue); if (bcs->tx_skb) - dbg(DEBUG_INTR, - "Dequeued skb (Adr: %lx)!", - (unsigned long) bcs->tx_skb); + gig_dbg(DEBUG_INTR, + "Dequeued skb (Adr: %lx)!", + (unsigned long) bcs->tx_skb); } } if (bcs->tx_skb) { - dbg(DEBUG_OUTPUT, "modem_fill: tx_skb"); + gig_dbg(DEBUG_OUTPUT, "modem_fill: tx_skb"); if (write_modem(cs) < 0) { - dbg(DEBUG_OUTPUT, - "modem_fill: write_modem failed"); + gig_dbg(DEBUG_OUTPUT, + "modem_fill: write_modem failed"); // FIXME should we tell the LL? again = 1; /* no callback will be called! */ } @@ -371,88 +361,85 @@ static void gigaset_modem_fill(unsigned long data) /** * gigaset_read_int_callback * - * It is called if the data was received from the device. This is almost similiar to - * the interrupt service routine in the serial device. + * It is called if the data was received from the device. */ static void gigaset_read_int_callback(struct urb *urb, struct pt_regs *regs) { + struct inbuf_t *inbuf = urb->context; + struct cardstate *cs = inbuf->cs; int resubmit = 0; int r; - struct cardstate *cs; unsigned numbytes; unsigned char *src; - //unsigned long flags; - struct inbuf_t *inbuf; - - IFNULLRET(urb); - inbuf = (struct inbuf_t *) urb->context; - IFNULLRET(inbuf); - //spin_lock_irqsave(&inbuf->lock, flags); - cs = inbuf->cs; - IFNULLGOTO(cs, exit); - IFNULLGOTO(cardstate, exit); - - if (!atomic_read(&cs->connected)) { - err("%s: disconnected", __func__); - goto exit; - } + unsigned long flags; if (!urb->status) { + if (!cs->connected) { + err("%s: disconnected", __func__); /* should never happen */ + return; + } + numbytes = urb->actual_length; if (numbytes) { src = inbuf->rcvbuf; if (unlikely(*src)) - warn("%s: There was no leading 0, but 0x%02x!", - __func__, (unsigned) *src); + dev_warn(cs->dev, + "%s: There was no leading 0, but 0x%02x!\n", + __func__, (unsigned) *src); ++src; /* skip leading 0x00 */ --numbytes; if (gigaset_fill_inbuf(inbuf, src, numbytes)) { - dbg(DEBUG_INTR, "%s-->BH", __func__); + gig_dbg(DEBUG_INTR, "%s-->BH", __func__); gigaset_schedule_event(inbuf->cs); } } else - dbg(DEBUG_INTR, "Received zero block length"); + gig_dbg(DEBUG_INTR, "Received zero block length"); resubmit = 1; } else { /* The urb might have been killed. */ - dbg(DEBUG_ANY, "%s - nonzero read bulk status received: %d", - __func__, urb->status); - if (urb->status != -ENOENT) /* not killed */ + gig_dbg(DEBUG_ANY, "%s - nonzero read bulk status received: %d", + __func__, urb->status); + if (urb->status != -ENOENT) { /* not killed */ + if (!cs->connected) { + err("%s: disconnected", __func__); /* should never happen */ + return; + } resubmit = 1; + } } -exit: - //spin_unlock_irqrestore(&inbuf->lock, flags); + if (resubmit) { - r = usb_submit_urb(urb, SLAB_ATOMIC); + spin_lock_irqsave(&cs->lock, flags); + r = cs->connected ? usb_submit_urb(urb, SLAB_ATOMIC) : -ENODEV; + spin_unlock_irqrestore(&cs->lock, flags); if (r) - err("error %d when resubmitting urb.", -r); + dev_err(cs->dev, "error %d when resubmitting urb.\n", + -r); } } -/* This callback routine is called when data was transmitted to a B-Channel. - * Therefore it has to check if there is still data to transmit. This - * happens by calling modem_fill via task queue. - * - */ +/* This callback routine is called when data was transmitted to the device. */ static void gigaset_write_bulk_callback(struct urb *urb, struct pt_regs *regs) { - struct cardstate *cs = (struct cardstate *) urb->context; + struct cardstate *cs = urb->context; + unsigned long flags; - IFNULLRET(cs); -#ifdef CONFIG_GIGASET_DEBUG - if (!atomic_read(&cs->connected)) { - err("%s:not connected", __func__); - return; - } -#endif if (urb->status) - err("bulk transfer failed (status %d)", -urb->status); /* That's all we can do. Communication problems - are handeled by timeouts or network protocols */ + dev_err(cs->dev, "bulk transfer failed (status %d)\n", + -urb->status); + /* That's all we can do. Communication problems + are handled by timeouts or network protocols. */ - atomic_set(&cs->hw.usb->busy, 0); - tasklet_schedule(&cs->write_tasklet); + spin_lock_irqsave(&cs->lock, flags); + if (!cs->connected) { + err("%s: not connected", __func__); + } else { + atomic_set(&cs->hw.usb->busy, 0); + tasklet_schedule(&cs->write_tasklet); + } + spin_unlock_irqrestore(&cs->lock, flags); } static int send_cb(struct cardstate *cs, struct cmdbuf_t *cb) @@ -469,8 +456,8 @@ static int send_cb(struct cardstate *cs, struct cmdbuf_t *cb) spin_lock_irqsave(&cs->cmdlock, flags); cs->cmdbytes -= cs->curlen; - dbg(DEBUG_OUTPUT, "send_cb: sent %u bytes, %u left", - cs->curlen, cs->cmdbytes); + gig_dbg(DEBUG_OUTPUT, "send_cb: sent %u bytes, %u left", + cs->curlen, cs->cmdbytes); cs->cmdbuf = cb = cb->next; if (cb) { cb->prev = NULL; @@ -487,52 +474,51 @@ static int send_cb(struct cardstate *cs, struct cmdbuf_t *cb) } if (cb) { count = min(cb->len, ucs->bulk_out_size); + gig_dbg(DEBUG_OUTPUT, "send_cb: send %d bytes", count); + usb_fill_bulk_urb(ucs->bulk_out_urb, ucs->udev, - usb_sndbulkpipe(ucs->udev, - ucs->bulk_out_endpointAddr & 0x0f), - cb->buf + cb->offset, count, - gigaset_write_bulk_callback, cs); + usb_sndbulkpipe(ucs->udev, + ucs->bulk_out_endpointAddr & 0x0f), + cb->buf + cb->offset, count, + gigaset_write_bulk_callback, cs); cb->offset += count; cb->len -= count; atomic_set(&ucs->busy, 1); - dbg(DEBUG_OUTPUT, "send_cb: send %d bytes", count); - status = usb_submit_urb(ucs->bulk_out_urb, SLAB_ATOMIC); + spin_lock_irqsave(&cs->lock, flags); + status = cs->connected ? usb_submit_urb(ucs->bulk_out_urb, SLAB_ATOMIC) : -ENODEV; + spin_unlock_irqrestore(&cs->lock, flags); + if (status) { atomic_set(&ucs->busy, 0); - err("could not submit urb (error %d).", + err("could not submit urb (error %d)\n", -status); - cb->len = 0; /* skip urb => remove cb+wakeup in next loop cycle */ + cb->len = 0; /* skip urb => remove cb+wakeup + in next loop cycle */ } } - } while (cb && status); /* bei Fehler naechster Befehl //FIXME: ist das OK? */ + } while (cb && status); /* next command on error */ return status; } -/* Write string into transbuf and send it to modem. - */ +/* Send command to device. */ static int gigaset_write_cmd(struct cardstate *cs, const unsigned char *buf, - int len, struct tasklet_struct *wake_tasklet) + int len, struct tasklet_struct *wake_tasklet) { struct cmdbuf_t *cb; unsigned long flags; gigaset_dbg_buffer(atomic_read(&cs->mstate) != MS_LOCKED ? - DEBUG_TRANSCMD : DEBUG_LOCKCMD, - "CMD Transmit", len, buf, 0); - - if (!atomic_read(&cs->connected)) { - err("%s: not connected", __func__); - return -ENODEV; - } + DEBUG_TRANSCMD : DEBUG_LOCKCMD, + "CMD Transmit", len, buf); if (len <= 0) return 0; if (!(cb = kmalloc(sizeof(struct cmdbuf_t) + len, GFP_ATOMIC))) { - err("%s: out of memory", __func__); + dev_err(cs->dev, "%s: out of memory\n", __func__); return -ENOMEM; } @@ -554,7 +540,10 @@ static int gigaset_write_cmd(struct cardstate *cs, const unsigned char *buf, cs->lastcmdbuf = cb; spin_unlock_irqrestore(&cs->cmdlock, flags); - tasklet_schedule(&cs->write_tasklet); + spin_lock_irqsave(&cs->lock, flags); + if (cs->connected) + tasklet_schedule(&cs->write_tasklet); + spin_unlock_irqrestore(&cs->lock, flags); return len; } @@ -578,11 +567,12 @@ static int gigaset_chars_in_buffer(struct cardstate *cs) static int gigaset_brkchars(struct cardstate *cs, const unsigned char buf[6]) { #ifdef CONFIG_GIGASET_UNDOCREQ - gigaset_dbg_buffer(DEBUG_USBREQ, "brkchars", 6, buf, 0); + struct usb_device *udev = cs->hw.usb->udev; + + gigaset_dbg_buffer(DEBUG_USBREQ, "brkchars", 6, buf); memcpy(cs->hw.usb->bchars, buf, 6); - return usb_control_msg(cs->hw.usb->udev, - usb_sndctrlpipe(cs->hw.usb->udev, 0), 0x19, 0x41, - 0, 0, &buf, 6, 2000); + return usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x19, 0x41, + 0, 0, &buf, 6, 2000); #else return -EINVAL; #endif @@ -604,7 +594,6 @@ static int gigaset_initbcshw(struct bc_state *bcs) if (!bcs->hw.usb) return 0; - //bcs->hw.usb->trans_flg = READY_TO_TRNSMIT; /* B-Channel ready to transmit */ return 1; } @@ -614,7 +603,6 @@ static void gigaset_reinitbcshw(struct bc_state *bcs) static void gigaset_freecshw(struct cardstate *cs) { - //FIXME tasklet_kill(&cs->write_tasklet); kfree(cs->hw.usb); } @@ -639,33 +627,21 @@ static int gigaset_initcshw(struct cardstate *cs) //ucs->urb_cmd_out = NULL; ucs->read_urb = NULL; tasklet_init(&cs->write_tasklet, - &gigaset_modem_fill, (unsigned long) cs); + &gigaset_modem_fill, (unsigned long) cs); return 1; } -/* Writes the data of the current open skb into the modem. - * We have to protect against multiple calls until the - * callback handler () is called , due to the fact that we - * are just allowed to send data once to an endpoint. Therefore - * we using "trans_flg" to synchonize ... - */ +/* Send data from current skb to the device. */ static int write_modem(struct cardstate *cs) { - int ret; + int ret = 0; int count; struct bc_state *bcs = &cs->bcs[0]; /* only one channel */ struct usb_cardstate *ucs = cs->hw.usb; - //unsigned long flags; - - IFNULLRETVAL(bcs->tx_skb, -EINVAL); - - dbg(DEBUG_WRITE, "len: %d...", bcs->tx_skb->len); + unsigned long flags; - ret = -ENODEV; - IFNULLGOTO(ucs->bulk_out_buffer, error); - IFNULLGOTO(ucs->bulk_out_urb, error); - ret = 0; + gig_dbg(DEBUG_WRITE, "len: %d...", bcs->tx_skb->len); if (!bcs->tx_skb->len) { dev_kfree_skb_any(bcs->tx_skb); @@ -679,40 +655,42 @@ static int write_modem(struct cardstate *cs) count = min(bcs->tx_skb->len, (unsigned) ucs->bulk_out_size); memcpy(ucs->bulk_out_buffer, bcs->tx_skb->data, count); skb_pull(bcs->tx_skb, count); - - usb_fill_bulk_urb(ucs->bulk_out_urb, ucs->udev, - usb_sndbulkpipe(ucs->udev, - ucs->bulk_out_endpointAddr & 0x0f), - ucs->bulk_out_buffer, count, - gigaset_write_bulk_callback, cs); atomic_set(&ucs->busy, 1); - dbg(DEBUG_OUTPUT, "write_modem: send %d bytes", count); + gig_dbg(DEBUG_OUTPUT, "write_modem: send %d bytes", count); + + spin_lock_irqsave(&cs->lock, flags); + if (cs->connected) { + usb_fill_bulk_urb(ucs->bulk_out_urb, ucs->udev, + usb_sndbulkpipe(ucs->udev, + ucs->bulk_out_endpointAddr & 0x0f), + ucs->bulk_out_buffer, count, + gigaset_write_bulk_callback, cs); + ret = usb_submit_urb(ucs->bulk_out_urb, SLAB_ATOMIC); + } else { + ret = -ENODEV; + } + spin_unlock_irqrestore(&cs->lock, flags); - ret = usb_submit_urb(ucs->bulk_out_urb, SLAB_ATOMIC); if (ret) { - err("could not submit urb (error %d).", -ret); + err("could not submit urb (error %d)\n", -ret); atomic_set(&ucs->busy, 0); } + if (!bcs->tx_skb->len) { /* skb sent completely */ gigaset_skb_sent(bcs, bcs->tx_skb); //FIXME also, when ret<0? - dbg(DEBUG_INTR, - "kfree skb (Adr: %lx)!", (unsigned long) bcs->tx_skb); + gig_dbg(DEBUG_INTR, "kfree skb (Adr: %lx)!", + (unsigned long) bcs->tx_skb); dev_kfree_skb_any(bcs->tx_skb); bcs->tx_skb = NULL; } return ret; -error: - dev_kfree_skb_any(bcs->tx_skb); - bcs->tx_skb = NULL; - return ret; - } static int gigaset_probe(struct usb_interface *interface, - const struct usb_device_id *id) + const struct usb_device_id *id) { int retval; struct usb_device *udev = interface_to_usbdev(interface); @@ -720,16 +698,14 @@ static int gigaset_probe(struct usb_interface *interface, struct usb_host_interface *hostif; struct cardstate *cs = NULL; struct usb_cardstate *ucs = NULL; - //struct usb_interface_descriptor *iface_desc; struct usb_endpoint_descriptor *endpoint; - //isdn_ctrl command; int buffer_size; int alt; - //unsigned long flags; - info("%s: Check if device matches .. (Vendor: 0x%x, Product: 0x%x)", - __func__, le16_to_cpu(udev->descriptor.idVendor), - le16_to_cpu(udev->descriptor.idProduct)); + gig_dbg(DEBUG_ANY, + "%s: Check if device matches .. (Vendor: 0x%x, Product: 0x%x)", + __func__, le16_to_cpu(udev->descriptor.idVendor), + le16_to_cpu(udev->descriptor.idProduct)); retval = -ENODEV; //FIXME @@ -744,7 +720,7 @@ static int gigaset_probe(struct usb_interface *interface, ifnum = hostif->desc.bInterfaceNumber; // FIXME ? if (alt != 0 || ifnum != 0) { - warn("ifnum %d, alt %d", ifnum, alt); + dev_warn(&udev->dev, "ifnum %d, alt %d\n", ifnum, alt); return -ENODEV; } @@ -752,42 +728,29 @@ static int gigaset_probe(struct usb_interface *interface, * */ if (hostif->desc.bInterfaceClass != 255) { - info("%s: Device matched, but iface_desc[%d]->bInterfaceClass==%d !", - __func__, ifnum, hostif->desc.bInterfaceClass); + dev_info(&udev->dev, + "%s: Device matched but iface_desc[%d]->bInterfaceClass==%d!\n", + __func__, ifnum, hostif->desc.bInterfaceClass); return -ENODEV; } - info("%s: Device matched ... !", __func__); + dev_info(&udev->dev, "%s: Device matched ... !\n", __func__); cs = gigaset_getunassignedcs(driver); if (!cs) { - warn("No free cardstate!"); + dev_warn(&udev->dev, "no free cardstate\n"); return -ENODEV; } ucs = cs->hw.usb; -#if 0 - if (usb_set_configuration(udev, udev->config[0].desc.bConfigurationValue) < 0) { - warn("set_configuration failed"); - goto error; - } - - - if (usb_set_interface(udev, ifnum/*==0*/, alt/*==0*/) < 0) { - warn("usb_set_interface failed, device %d interface %d altsetting %d", - udev->devnum, ifnum, alt); - goto error; - } -#endif + /* save off device structure ptrs for later use */ + usb_get_dev(udev); + ucs->udev = udev; + ucs->interface = interface; + cs->dev = &interface->dev; - /* set up the endpoint information */ - /* check out the endpoints */ - /* We will get 2 endpoints: One for sending commands to the device (bulk out) and one to - * poll messages from the device(int in). - * Therefore we will have an almost similiar situation as with our serial port handler. - * If an connection will be established, we will have to create data in/out pipes - * dynamically... - */ + /* save address of controller structure */ + usb_set_intfdata(interface, cs); // dev_set_drvdata(&interface->dev, cs); endpoint = &hostif->endpoint[0].desc; @@ -796,14 +759,14 @@ static int gigaset_probe(struct usb_interface *interface, ucs->bulk_out_endpointAddr = endpoint->bEndpointAddress; ucs->bulk_out_buffer = kmalloc(buffer_size, GFP_KERNEL); if (!ucs->bulk_out_buffer) { - err("Couldn't allocate bulk_out_buffer"); + dev_err(cs->dev, "Couldn't allocate bulk_out_buffer\n"); retval = -ENOMEM; goto error; } ucs->bulk_out_urb = usb_alloc_urb(0, SLAB_KERNEL); if (!ucs->bulk_out_urb) { - err("Couldn't allocate bulk_out_buffer"); + dev_err(cs->dev, "Couldn't allocate bulk_out_urb\n"); retval = -ENOMEM; goto error; } @@ -811,12 +774,10 @@ static int gigaset_probe(struct usb_interface *interface, endpoint = &hostif->endpoint[1].desc; atomic_set(&ucs->busy, 0); - ucs->udev = udev; - ucs->interface = interface; ucs->read_urb = usb_alloc_urb(0, SLAB_KERNEL); if (!ucs->read_urb) { - err("No free urbs available"); + dev_err(cs->dev, "No free urbs available\n"); retval = -ENOMEM; goto error; } @@ -825,38 +786,33 @@ static int gigaset_probe(struct usb_interface *interface, ucs->int_in_endpointAddr = endpoint->bEndpointAddress; cs->inbuf[0].rcvbuf = kmalloc(buffer_size, GFP_KERNEL); if (!cs->inbuf[0].rcvbuf) { - err("Couldn't allocate rcvbuf"); + dev_err(cs->dev, "Couldn't allocate rcvbuf\n"); retval = -ENOMEM; goto error; } /* Fill the interrupt urb and send it to the core */ usb_fill_int_urb(ucs->read_urb, udev, - usb_rcvintpipe(udev, - endpoint->bEndpointAddress & 0x0f), - cs->inbuf[0].rcvbuf, buffer_size, - gigaset_read_int_callback, - cs->inbuf + 0, endpoint->bInterval); + usb_rcvintpipe(udev, + endpoint->bEndpointAddress & 0x0f), + cs->inbuf[0].rcvbuf, buffer_size, + gigaset_read_int_callback, + cs->inbuf + 0, endpoint->bInterval); retval = usb_submit_urb(ucs->read_urb, SLAB_KERNEL); if (retval) { - err("Could not submit URB!"); + dev_err(cs->dev, "Could not submit URB (error %d)\n", -retval); goto error; } /* tell common part that the device is ready */ if (startmode == SM_LOCKED) atomic_set(&cs->mstate, MS_LOCKED); + if (!gigaset_start(cs)) { tasklet_kill(&cs->write_tasklet); retval = -ENODEV; //FIXME goto error; } - - /* save address of controller structure */ - usb_set_intfdata(interface, cs); - - /* set up device sysfs */ - gigaset_init_dev_sysfs(interface); return 0; error: @@ -868,48 +824,45 @@ error: kfree(cs->inbuf[0].rcvbuf); if (ucs->read_urb != NULL) usb_free_urb(ucs->read_urb); + usb_set_intfdata(interface, NULL); ucs->read_urb = ucs->bulk_out_urb = NULL; cs->inbuf[0].rcvbuf = ucs->bulk_out_buffer = NULL; + usb_put_dev(ucs->udev); + ucs->udev = NULL; + ucs->interface = NULL; gigaset_unassign(cs); return retval; } -/** - * skel_disconnect - */ static void gigaset_disconnect(struct usb_interface *interface) { struct cardstate *cs; struct usb_cardstate *ucs; cs = usb_get_intfdata(interface); - - /* clear device sysfs */ - gigaset_free_dev_sysfs(interface); - - usb_set_intfdata(interface, NULL); ucs = cs->hw.usb; usb_kill_urb(ucs->read_urb); - //info("GigaSet USB device #%d will be disconnected", minor); gigaset_stop(cs); + usb_set_intfdata(interface, NULL); tasklet_kill(&cs->write_tasklet); - usb_kill_urb(ucs->bulk_out_urb); /* FIXME: nur, wenn noetig */ - //usb_kill_urb(ucs->urb_cmd_out); /* FIXME: nur, wenn noetig */ + usb_kill_urb(ucs->bulk_out_urb); /* FIXME: only if active? */ kfree(ucs->bulk_out_buffer); if (ucs->bulk_out_urb != NULL) usb_free_urb(ucs->bulk_out_urb); - //if(ucs->urb_cmd_out != NULL) - // usb_free_urb(ucs->urb_cmd_out); kfree(cs->inbuf[0].rcvbuf); if (ucs->read_urb != NULL) usb_free_urb(ucs->read_urb); - ucs->read_urb = ucs->bulk_out_urb/*=ucs->urb_cmd_out*/=NULL; + ucs->read_urb = ucs->bulk_out_urb = NULL; cs->inbuf[0].rcvbuf = ucs->bulk_out_buffer = NULL; + usb_put_dev(ucs->udev); + ucs->interface = NULL; + ucs->udev = NULL; + cs->dev = NULL; gigaset_unassign(cs); } @@ -942,9 +895,9 @@ static int __init usb_gigaset_init(void) /* allocate memory for our driver state and intialize it */ if ((driver = gigaset_initdriver(GIGASET_MINOR, GIGASET_MINORS, - GIGASET_MODULENAME, GIGASET_DEVNAME, - GIGASET_DEVFSNAME, &ops, - THIS_MODULE)) == NULL) + GIGASET_MODULENAME, GIGASET_DEVNAME, + GIGASET_DEVFSNAME, &ops, + THIS_MODULE)) == NULL) goto error; /* allocate memory for our device state and intialize it */ @@ -981,8 +934,8 @@ error: if (cardstate) static void __exit usb_gigaset_exit(void) { gigaset_blockdriver(driver); /* => probe will fail - * => no gigaset_start any more - */ + * => no gigaset_start any more + */ gigaset_shutdown(cardstate); /* from now on, no isdn callback should be possible */ diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 2c4f20b..3f5b647 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -14,13 +14,7 @@ config LEDS_CLASS This option enables the led sysfs class in /sys/class/leds. You'll need this to do anything useful with LEDs. If unsure, say N. -config LEDS_TRIGGERS - bool "LED Trigger support" - depends NEW_LEDS - help - This option enables trigger support for the leds class. - These triggers allow kernel events to drive the LEDs and can - be configured via sysfs. If unsure, say Y. +comment "LED drivers" config LEDS_CORGI tristate "LED Support for the Sharp SL-C7x0 series" @@ -59,6 +53,23 @@ config LEDS_TOSA This option enables support for the LEDs on Sharp Zaurus SL-6000 series. +config LEDS_S3C24XX + tristate "LED Support for Samsung S3C24XX GPIO LEDs" + depends on LEDS_CLASS && ARCH_S3C2410 + help + This option enables support for LEDs connected to GPIO lines + on Samsung S3C24XX series CPUs, such as the S3C2410 and S3C2440. + +comment "LED Triggers" + +config LEDS_TRIGGERS + bool "LED Trigger support" + depends NEW_LEDS + help + This option enables trigger support for the leds class. + These triggers allow kernel events to drive the LEDs and can + be configured via sysfs. If unsure, say Y. + config LEDS_TRIGGER_TIMER tristate "LED Timer Trigger" depends LEDS_TRIGGERS @@ -67,7 +78,7 @@ config LEDS_TRIGGER_TIMER via sysfs. If unsure, say Y. config LEDS_TRIGGER_IDE_DISK - bool "LED Timer Trigger" + bool "LED IDE Disk Trigger" depends LEDS_TRIGGERS && BLK_DEV_IDEDISK help This allows LEDs to be controlled by IDE disk activity. diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index 40699d3..40f0426 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile @@ -10,6 +10,7 @@ obj-$(CONFIG_LEDS_LOCOMO) += leds-locomo.o obj-$(CONFIG_LEDS_SPITZ) += leds-spitz.o obj-$(CONFIG_LEDS_IXP4XX) += leds-ixp4xx-gpio.o obj-$(CONFIG_LEDS_TOSA) += leds-tosa.o +obj-$(CONFIG_LEDS_S3C24XX) += leds-s3c24xx.o # LED Triggers obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o diff --git a/drivers/leds/leds-s3c24xx.c b/drivers/leds/leds-s3c24xx.c new file mode 100644 index 0000000..650cf72 --- /dev/null +++ b/drivers/leds/leds-s3c24xx.c @@ -0,0 +1,163 @@ +/* drivers/leds/leds-s3c24xx.c + * + * (c) 2006 Simtec Electronics + * http://armlinux.simtec.co.uk/ + * Ben Dooks <ben@simtec.co.uk> + * + * S3C24XX - LEDs GPIO driver + * + * 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 + * published by the Free Software Foundation. +*/ + +#include <linux/config.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/leds.h> + +#include <asm/arch/hardware.h> +#include <asm/arch/regs-gpio.h> +#include <asm/arch/leds-gpio.h> + +/* our context */ + +struct s3c24xx_gpio_led { + struct led_classdev cdev; + struct s3c24xx_led_platdata *pdata; +}; + +static inline struct s3c24xx_gpio_led *pdev_to_gpio(struct platform_device *dev) +{ + return platform_get_drvdata(dev); +} + +static inline struct s3c24xx_gpio_led *to_gpio(struct led_classdev *led_cdev) +{ + return container_of(led_cdev, struct s3c24xx_gpio_led, cdev); +} + +static void s3c24xx_led_set(struct led_classdev *led_cdev, + enum led_brightness value) +{ + struct s3c24xx_gpio_led *led = to_gpio(led_cdev); + struct s3c24xx_led_platdata *pd = led->pdata; + + /* there will be a sort delay between setting the output and + * going from output to input when using tristate. */ + + s3c2410_gpio_setpin(pd->gpio, (value ? 1 : 0) ^ + (pd->flags & S3C24XX_LEDF_ACTLOW)); + + if (pd->flags & S3C24XX_LEDF_TRISTATE) + s3c2410_gpio_cfgpin(pd->gpio, + value ? S3C2410_GPIO_OUTPUT : S3C2410_GPIO_INPUT); + +} + +static int s3c24xx_led_remove(struct platform_device *dev) +{ + struct s3c24xx_gpio_led *led = pdev_to_gpio(dev); + + led_classdev_unregister(&led->cdev); + kfree(led); + + return 0; +} + +static int s3c24xx_led_probe(struct platform_device *dev) +{ + struct s3c24xx_led_platdata *pdata = dev->dev.platform_data; + struct s3c24xx_gpio_led *led; + int ret; + + led = kzalloc(sizeof(struct s3c24xx_gpio_led), GFP_KERNEL); + if (led == NULL) { + dev_err(&dev->dev, "No memory for device\n"); + return -ENOMEM; + } + + platform_set_drvdata(dev, led); + + led->cdev.brightness_set = s3c24xx_led_set; + led->cdev.default_trigger = pdata->def_trigger; + led->cdev.name = pdata->name; + + led->pdata = pdata; + + /* no point in having a pull-up if we are always driving */ + + if (pdata->flags & S3C24XX_LEDF_TRISTATE) { + s3c2410_gpio_setpin(pdata->gpio, 0); + s3c2410_gpio_cfgpin(pdata->gpio, S3C2410_GPIO_INPUT); + } else { + s3c2410_gpio_pullup(pdata->gpio, 0); + s3c2410_gpio_setpin(pdata->gpio, 0); + s3c2410_gpio_cfgpin(pdata->gpio, S3C2410_GPIO_OUTPUT); + } + + /* register our new led device */ + + ret = led_classdev_register(&dev->dev, &led->cdev); + if (ret < 0) { + dev_err(&dev->dev, "led_classdev_register failed\n"); + goto exit_err1; + } + + return 0; + + exit_err1: + kfree(led); + return ret; +} + + +#ifdef CONFIG_PM +static int s3c24xx_led_suspend(struct platform_device *dev, pm_message_t state) +{ + struct s3c24xx_gpio_led *led = pdev_to_gpio(dev); + + led_classdev_suspend(&led->cdev); + return 0; +} + +static int s3c24xx_led_resume(struct platform_device *dev) +{ + struct s3c24xx_gpio_led *led = pdev_to_gpio(dev); + + led_classdev_resume(&led->cdev); + return 0; +} +#else +#define s3c24xx_led_suspend NULL +#define s3c24xx_led_resume NULL +#endif + +static struct platform_driver s3c24xx_led_driver = { + .probe = s3c24xx_led_probe, + .remove = s3c24xx_led_remove, + .suspend = s3c24xx_led_suspend, + .resume = s3c24xx_led_resume, + .driver = { + .name = "s3c24xx_led", + .owner = THIS_MODULE, + }, +}; + +static int __init s3c24xx_led_init(void) +{ + return platform_driver_register(&s3c24xx_led_driver); +} + +static void __exit s3c24xx_led_exit(void) +{ + platform_driver_unregister(&s3c24xx_led_driver); +} + +module_init(s3c24xx_led_init); +module_exit(s3c24xx_led_exit); + +MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>"); +MODULE_DESCRIPTION("S3C24XX LED driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/md/Kconfig b/drivers/md/Kconfig index fd2aae1..ac25a48 100644 --- a/drivers/md/Kconfig +++ b/drivers/md/Kconfig @@ -139,11 +139,12 @@ config MD_RAID5_RESHAPE is online. However it is still EXPERIMENTAL code. It should work, but please be sure that you have backups. - You will need a version of mdadm newer than 2.3.1. During the - early stage of reshape there is a critical section where live data - is being over-written. A crash during this time needs extra care - for recovery. The newer mdadm takes a copy of the data in the - critical section and will restore it, if necessary, after a crash. + You will need mdadm verion 2.4.1 or later to use this + feature safely. During the early stage of reshape there is + a critical section where live data is being over-written. A + crash during this time needs extra care for recovery. The + newer mdadm takes a copy of the data in the critical section + and will restore it, if necessary, after a crash. The mdadm usage is e.g. mdadm --grow /dev/md1 --raid-disks=6 diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index 4092a5e..b3ea2d6 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -84,4 +84,4 @@ obj-$(CONFIG_USB_IBMCAM) += usbvideo/ obj-$(CONFIG_USB_KONICAWC) += usbvideo/ obj-$(CONFIG_USB_VICAM) += usbvideo/ -EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/dvb-core +EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core diff --git a/drivers/media/video/bt8xx/Makefile b/drivers/media/video/bt8xx/Makefile index 94350f2..db641a3 100644 --- a/drivers/media/video/bt8xx/Makefile +++ b/drivers/media/video/bt8xx/Makefile @@ -9,4 +9,4 @@ bttv-objs := bttv-driver.o bttv-cards.o bttv-if.o \ obj-$(CONFIG_VIDEO_BT848) += bttv.o EXTRA_CFLAGS += -I$(src)/.. -EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/dvb-core +EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core diff --git a/drivers/media/video/cx25840/Makefile b/drivers/media/video/cx25840/Makefile index 32a896c..6e8665b 100644 --- a/drivers/media/video/cx25840/Makefile +++ b/drivers/media/video/cx25840/Makefile @@ -3,4 +3,4 @@ cx25840-objs := cx25840-core.o cx25840-audio.o cx25840-firmware.o \ obj-$(CONFIG_VIDEO_CX25840) += cx25840.o -EXTRA_CFLAGS += -I$(src)/.. +EXTRA_CFLAGS += -Idrivers/media/video diff --git a/drivers/media/video/cx88/Makefile b/drivers/media/video/cx88/Makefile index 6482b9a..0dcd09b 100644 --- a/drivers/media/video/cx88/Makefile +++ b/drivers/media/video/cx88/Makefile @@ -8,9 +8,9 @@ obj-$(CONFIG_VIDEO_CX88_DVB) += cx88-dvb.o obj-$(CONFIG_VIDEO_CX88_ALSA) += cx88-alsa.o obj-$(CONFIG_VIDEO_CX88_VP3054) += cx88-vp3054-i2c.o -EXTRA_CFLAGS += -I$(src)/.. -EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/dvb-core -EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/frontends +EXTRA_CFLAGS += -Idrivers/media/video +EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core +EXTRA_CFLAGS += -Idrivers/media/dvb/frontends extra-cflags-$(CONFIG_VIDEO_BUF_DVB) += -DHAVE_VIDEO_BUF_DVB=1 extra-cflags-$(CONFIG_DVB_CX22702) += -DHAVE_CX22702=1 diff --git a/drivers/media/video/em28xx/Makefile b/drivers/media/video/em28xx/Makefile index da457a0..826d0e3 100644 --- a/drivers/media/video/em28xx/Makefile +++ b/drivers/media/video/em28xx/Makefile @@ -3,4 +3,4 @@ em28xx-objs := em28xx-video.o em28xx-i2c.o em28xx-cards.o em28xx-core.o \ obj-$(CONFIG_VIDEO_EM28XX) += em28xx.o -EXTRA_CFLAGS += -I$(src)/.. +EXTRA_CFLAGS += -Idrivers/media/video diff --git a/drivers/media/video/saa7134/Makefile b/drivers/media/video/saa7134/Makefile index 1ba9984..be7b9ee 100644 --- a/drivers/media/video/saa7134/Makefile +++ b/drivers/media/video/saa7134/Makefile @@ -11,9 +11,9 @@ obj-$(CONFIG_VIDEO_SAA7134_OSS) += saa7134-oss.o obj-$(CONFIG_VIDEO_SAA7134_DVB) += saa7134-dvb.o -EXTRA_CFLAGS += -I$(src)/.. -EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/dvb-core -EXTRA_CFLAGS += -I$(srctree)/drivers/media/dvb/frontends +EXTRA_CFLAGS += -Idrivers/media/video +EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core +EXTRA_CFLAGS += -Idrivers/media/dvb/frontends extra-cflags-$(CONFIG_VIDEO_BUF_DVB) += -DHAVE_VIDEO_BUF_DVB=1 extra-cflags-$(CONFIG_DVB_MT352) += -DHAVE_MT352=1 diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index c98571c..13de055 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c @@ -32,6 +32,7 @@ #include <linux/interrupt.h> #include <linux/delay.h> #include <linux/mutex.h> +#include <linux/dma-mapping.h> #include "saa7134-reg.h" #include "saa7134.h" @@ -870,7 +871,7 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, pci_name(pci_dev), dev->pci_rev, pci_dev->irq, dev->pci_lat,pci_resource_start(pci_dev,0)); pci_set_master(pci_dev); - if (!pci_dma_supported(pci_dev,0xffffffff)) { + if (!pci_dma_supported(pci_dev, DMA_32BIT_MASK)) { printk("%s: Oops: no 32bit PCI DMA ???\n",dev->name); err = -EIO; goto fail1; diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig index dd628cb..7fac438 100644 --- a/drivers/mtd/devices/Kconfig +++ b/drivers/mtd/devices/Kconfig @@ -129,8 +129,8 @@ config MTDRAM_ABS_POS allocating space from Linux's available memory. Otherwise, leave this set to zero. Most people will want to leave this as zero. -config MTD_BLKMTD - tristate "MTD emulation using block device" +config MTD_BLOCK2MTD + tristate "MTD using block device" depends on MTD help This driver allows a block device to appear as an MTD. It would @@ -141,15 +141,6 @@ config MTD_BLKMTD Testing MTD users (eg JFFS2) on large media and media that might be removed during a write (using the floppy drive). -config MTD_BLOCK2MTD - tristate "MTD using block device (rewrite)" - depends on MTD && EXPERIMENTAL - help - This driver is basically the same at MTD_BLKMTD above, but - experienced some interface changes plus serious speedups. In - the long term, it should replace MTD_BLKMTD. Right now, you - shouldn't entrust important data to it yet. - comment "Disk-On-Chip Device Drivers" config MTD_DOC2000 diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile index 7c5ed21..b657367 100644 --- a/drivers/mtd/devices/Makefile +++ b/drivers/mtd/devices/Makefile @@ -21,7 +21,6 @@ obj-$(CONFIG_MTD_PMC551) += pmc551.o obj-$(CONFIG_MTD_MS02NV) += ms02-nv.o obj-$(CONFIG_MTD_MTDRAM) += mtdram.o obj-$(CONFIG_MTD_LART) += lart.o -obj-$(CONFIG_MTD_BLKMTD) += blkmtd.o obj-$(CONFIG_MTD_BLOCK2MTD) += block2mtd.o obj-$(CONFIG_MTD_DATAFLASH) += mtd_dataflash.o obj-$(CONFIG_MTD_M25P80) += m25p80.o diff --git a/drivers/mtd/devices/blkmtd.c b/drivers/mtd/devices/blkmtd.c deleted file mode 100644 index 79f2e1f..0000000 --- a/drivers/mtd/devices/blkmtd.c +++ /dev/null @@ -1,819 +0,0 @@ -/* - * $Id: blkmtd.c,v 1.27 2005/11/07 11:14:24 gleixner Exp $ - * - * blkmtd.c - use a block device as a fake MTD - * - * Author: Simon Evans <spse@secret.org.uk> - * - * Copyright (C) 2001,2002 Simon Evans - * - * Licence: GPL - * - * How it works: - * The driver uses raw/io to read/write the device and the page - * cache to cache access. Writes update the page cache with the - * new data and mark it dirty and add the page into a BIO which - * is then written out. - * - * It can be loaded Read-Only to prevent erases and writes to the - * medium. - * - */ - -#include <linux/config.h> -#include <linux/module.h> -#include <linux/fs.h> -#include <linux/blkdev.h> -#include <linux/bio.h> -#include <linux/pagemap.h> -#include <linux/list.h> -#include <linux/init.h> -#include <linux/mount.h> -#include <linux/mtd/mtd.h> -#include <linux/mutex.h> - -#define err(format, arg...) printk(KERN_ERR "blkmtd: " format "\n" , ## arg) -#define info(format, arg...) printk(KERN_INFO "blkmtd: " format "\n" , ## arg) -#define warn(format, arg...) printk(KERN_WARNING "blkmtd: " format "\n" , ## arg) -#define crit(format, arg...) printk(KERN_CRIT "blkmtd: " format "\n" , ## arg) - - -/* Default erase size in K, always make it a multiple of PAGE_SIZE */ -#define CONFIG_MTD_BLKDEV_ERASESIZE (128 << 10) /* 128KiB */ -#define VERSION "$Revision: 1.27 $" - -/* Info for the block device */ -struct blkmtd_dev { - struct list_head list; - struct block_device *blkdev; - struct mtd_info mtd_info; - struct mutex wrbuf_mutex; -}; - - -/* Static info about the MTD, used in cleanup_module */ -static LIST_HEAD(blkmtd_device_list); - - -static void blkmtd_sync(struct mtd_info *mtd); - -#define MAX_DEVICES 4 - -/* Module parameters passed by insmod/modprobe */ -static char *device[MAX_DEVICES]; /* the block device to use */ -static int erasesz[MAX_DEVICES]; /* optional default erase size */ -static int ro[MAX_DEVICES]; /* optional read only flag */ -static int sync; - - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Simon Evans <spse@secret.org.uk>"); -MODULE_DESCRIPTION("Emulate an MTD using a block device"); -module_param_array(device, charp, NULL, 0); -MODULE_PARM_DESC(device, "block device to use"); -module_param_array(erasesz, int, NULL, 0); -MODULE_PARM_DESC(erasesz, "optional erase size to use in KiB. eg 4=4KiB."); -module_param_array(ro, bool, NULL, 0); -MODULE_PARM_DESC(ro, "1=Read only, writes and erases cause errors"); -module_param(sync, bool, 0); -MODULE_PARM_DESC(sync, "1=Synchronous writes"); - - -/* completion handler for BIO reads */ -static int bi_read_complete(struct bio *bio, unsigned int bytes_done, int error) -{ - if (bio->bi_size) - return 1; - - complete((struct completion*)bio->bi_private); - return 0; -} - - -/* completion handler for BIO writes */ -static int bi_write_complete(struct bio *bio, unsigned int bytes_done, int error) -{ - const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); - struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1; - - if (bio->bi_size) - return 1; - - if(!uptodate) - err("bi_write_complete: not uptodate\n"); - - do { - struct page *page = bvec->bv_page; - DEBUG(3, "Cleaning up page %ld\n", page->index); - if (--bvec >= bio->bi_io_vec) - prefetchw(&bvec->bv_page->flags); - - if (uptodate) { - SetPageUptodate(page); - } else { - ClearPageUptodate(page); - SetPageError(page); - } - clear_page_dirty(page); - unlock_page(page); - page_cache_release(page); - } while (bvec >= bio->bi_io_vec); - - complete((struct completion*)bio->bi_private); - return 0; -} - - -/* read one page from the block device */ -static int blkmtd_readpage(struct blkmtd_dev *dev, struct page *page) -{ - struct bio *bio; - struct completion event; - int err = -ENOMEM; - - if(PageUptodate(page)) { - DEBUG(2, "blkmtd: readpage page %ld is already upto date\n", page->index); - unlock_page(page); - return 0; - } - - ClearPageUptodate(page); - ClearPageError(page); - - bio = bio_alloc(GFP_KERNEL, 1); - if(bio) { - init_completion(&event); - bio->bi_bdev = dev->blkdev; - bio->bi_sector = page->index << (PAGE_SHIFT-9); - bio->bi_private = &event; - bio->bi_end_io = bi_read_complete; - if(bio_add_page(bio, page, PAGE_SIZE, 0) == PAGE_SIZE) { - submit_bio(READ_SYNC, bio); - wait_for_completion(&event); - err = test_bit(BIO_UPTODATE, &bio->bi_flags) ? 0 : -EIO; - bio_put(bio); - } - } - - if(err) - SetPageError(page); - else - SetPageUptodate(page); - flush_dcache_page(page); - unlock_page(page); - return err; -} - - -/* write out the current BIO and wait for it to finish */ -static int blkmtd_write_out(struct bio *bio) -{ - struct completion event; - int err; - - if(!bio->bi_vcnt) { - bio_put(bio); - return 0; - } - - init_completion(&event); - bio->bi_private = &event; - bio->bi_end_io = bi_write_complete; - submit_bio(WRITE_SYNC, bio); - wait_for_completion(&event); - DEBUG(3, "submit_bio completed, bi_vcnt = %d\n", bio->bi_vcnt); - err = test_bit(BIO_UPTODATE, &bio->bi_flags) ? 0 : -EIO; - bio_put(bio); - return err; -} - - -/** - * blkmtd_add_page - add a page to the current BIO - * @bio: bio to add to (NULL to alloc initial bio) - * @blkdev: block device - * @page: page to add - * @pagecnt: pages left to add - * - * Adds a page to the current bio, allocating it if necessary. If it cannot be - * added, the current bio is written out and a new one is allocated. Returns - * the new bio to add or NULL on error - */ -static struct bio *blkmtd_add_page(struct bio *bio, struct block_device *blkdev, - struct page *page, int pagecnt) -{ - - retry: - if(!bio) { - bio = bio_alloc(GFP_KERNEL, pagecnt); - if(!bio) - return NULL; - bio->bi_sector = page->index << (PAGE_SHIFT-9); - bio->bi_bdev = blkdev; - } - - if(bio_add_page(bio, page, PAGE_SIZE, 0) != PAGE_SIZE) { - blkmtd_write_out(bio); - bio = NULL; - goto retry; - } - return bio; -} - - -/** - * write_pages - write block of data to device via the page cache - * @dev: device to write to - * @buf: data source or NULL if erase (output is set to 0xff) - * @to: offset into output device - * @len: amount to data to write - * @retlen: amount of data written - * - * Grab pages from the page cache and fill them with the source data. - * Non page aligned start and end result in a readin of the page and - * part of the page being modified. Pages are added to the bio and then written - * out. - */ -static int write_pages(struct blkmtd_dev *dev, const u_char *buf, loff_t to, - size_t len, size_t *retlen) -{ - int pagenr, offset; - size_t start_len = 0, end_len; - int pagecnt = 0; - int err = 0; - struct bio *bio = NULL; - size_t thislen = 0; - - pagenr = to >> PAGE_SHIFT; - offset = to & ~PAGE_MASK; - - DEBUG(2, "blkmtd: write_pages: buf = %p to = %ld len = %zd pagenr = %d offset = %d\n", - buf, (long)to, len, pagenr, offset); - - /* see if we have to do a partial write at the start */ - if(offset) { - start_len = ((offset + len) > PAGE_SIZE) ? PAGE_SIZE - offset : len; - len -= start_len; - } - - /* calculate the length of the other two regions */ - end_len = len & ~PAGE_MASK; - len -= end_len; - - if(start_len) - pagecnt++; - - if(len) - pagecnt += len >> PAGE_SHIFT; - - if(end_len) - pagecnt++; - - mutex_lock(&dev->wrbuf_mutex); - - DEBUG(3, "blkmtd: write: start_len = %zd len = %zd end_len = %zd pagecnt = %d\n", - start_len, len, end_len, pagecnt); - - if(start_len) { - /* do partial start region */ - struct page *page; - - DEBUG(3, "blkmtd: write: doing partial start, page = %d len = %zd offset = %d\n", - pagenr, start_len, offset); - - BUG_ON(!buf); - page = read_cache_page(dev->blkdev->bd_inode->i_mapping, pagenr, (filler_t *)blkmtd_readpage, dev); - lock_page(page); - if(PageDirty(page)) { - err("to = %lld start_len = %zd len = %zd end_len = %zd pagenr = %d\n", - to, start_len, len, end_len, pagenr); - BUG(); - } - memcpy(page_address(page)+offset, buf, start_len); - set_page_dirty(page); - SetPageUptodate(page); - buf += start_len; - thislen = start_len; - bio = blkmtd_add_page(bio, dev->blkdev, page, pagecnt); - if(!bio) { - err = -ENOMEM; - err("bio_add_page failed\n"); - goto write_err; - } - pagecnt--; - pagenr++; - } - - /* Now do the main loop to a page aligned, n page sized output */ - if(len) { - int pagesc = len >> PAGE_SHIFT; - DEBUG(3, "blkmtd: write: whole pages start = %d, count = %d\n", - pagenr, pagesc); - while(pagesc) { - struct page *page; - - /* see if page is in the page cache */ - DEBUG(3, "blkmtd: write: grabbing page %d from page cache\n", pagenr); - page = grab_cache_page(dev->blkdev->bd_inode->i_mapping, pagenr); - if(PageDirty(page)) { - BUG(); - } - if(!page) { - warn("write: cannot grab cache page %d", pagenr); - err = -ENOMEM; - goto write_err; - } - if(!buf) { - memset(page_address(page), 0xff, PAGE_SIZE); - } else { - memcpy(page_address(page), buf, PAGE_SIZE); - buf += PAGE_SIZE; - } - bio = blkmtd_add_page(bio, dev->blkdev, page, pagecnt); - if(!bio) { - err = -ENOMEM; - err("bio_add_page failed\n"); - goto write_err; - } - pagenr++; - pagecnt--; - set_page_dirty(page); - SetPageUptodate(page); - pagesc--; - thislen += PAGE_SIZE; - } - } - - if(end_len) { - /* do the third region */ - struct page *page; - DEBUG(3, "blkmtd: write: doing partial end, page = %d len = %zd\n", - pagenr, end_len); - BUG_ON(!buf); - page = read_cache_page(dev->blkdev->bd_inode->i_mapping, pagenr, (filler_t *)blkmtd_readpage, dev); - lock_page(page); - if(PageDirty(page)) { - err("to = %lld start_len = %zd len = %zd end_len = %zd pagenr = %d\n", - to, start_len, len, end_len, pagenr); - BUG(); - } - memcpy(page_address(page), buf, end_len); - set_page_dirty(page); - SetPageUptodate(page); - DEBUG(3, "blkmtd: write: writing out partial end\n"); - thislen += end_len; - bio = blkmtd_add_page(bio, dev->blkdev, page, pagecnt); - if(!bio) { - err = -ENOMEM; - err("bio_add_page failed\n"); - goto write_err; - } - pagenr++; - } - - DEBUG(3, "blkmtd: write: got %d vectors to write\n", bio->bi_vcnt); - write_err: - if(bio) - blkmtd_write_out(bio); - - DEBUG(2, "blkmtd: write: end, retlen = %zd, err = %d\n", *retlen, err); - mutex_unlock(&dev->wrbuf_mutex); - - if(retlen) - *retlen = thislen; - return err; -} - - -/* erase a specified part of the device */ -static int blkmtd_erase(struct mtd_info *mtd, struct erase_info *instr) -{ - struct blkmtd_dev *dev = mtd->priv; - struct mtd_erase_region_info *einfo = mtd->eraseregions; - int numregions = mtd->numeraseregions; - size_t from; - u_long len; - int err = -EIO; - size_t retlen; - - instr->state = MTD_ERASING; - from = instr->addr; - len = instr->len; - - /* check erase region has valid start and length */ - DEBUG(2, "blkmtd: erase: dev = `%s' from = 0x%zx len = 0x%lx\n", - mtd->name+9, from, len); - while(numregions) { - DEBUG(3, "blkmtd: checking erase region = 0x%08X size = 0x%X num = 0x%x\n", - einfo->offset, einfo->erasesize, einfo->numblocks); - if(from >= einfo->offset - && from < einfo->offset + (einfo->erasesize * einfo->numblocks)) { - if(len == einfo->erasesize - && ( (from - einfo->offset) % einfo->erasesize == 0)) - break; - } - numregions--; - einfo++; - } - - if(!numregions) { - /* Not a valid erase block */ - err("erase: invalid erase request 0x%lX @ 0x%08zX", len, from); - instr->state = MTD_ERASE_FAILED; - err = -EIO; - } - - if(instr->state != MTD_ERASE_FAILED) { - /* do the erase */ - DEBUG(3, "Doing erase from = %zd len = %ld\n", from, len); - err = write_pages(dev, NULL, from, len, &retlen); - if(err || retlen != len) { - err("erase failed err = %d", err); - instr->state = MTD_ERASE_FAILED; - } else { - instr->state = MTD_ERASE_DONE; - } - } - - DEBUG(3, "blkmtd: erase: checking callback\n"); - mtd_erase_callback(instr); - DEBUG(2, "blkmtd: erase: finished (err = %d)\n", err); - return err; -} - - -/* read a range of the data via the page cache */ -static int blkmtd_read(struct mtd_info *mtd, loff_t from, size_t len, - size_t *retlen, u_char *buf) -{ - struct blkmtd_dev *dev = mtd->priv; - int err = 0; - int offset; - int pagenr, pages; - size_t thislen = 0; - - DEBUG(2, "blkmtd: read: dev = `%s' from = %lld len = %zd buf = %p\n", - mtd->name+9, from, len, buf); - - if(from > mtd->size) - return -EINVAL; - if(from + len > mtd->size) - len = mtd->size - from; - - pagenr = from >> PAGE_SHIFT; - offset = from - (pagenr << PAGE_SHIFT); - - pages = (offset+len+PAGE_SIZE-1) >> PAGE_SHIFT; - DEBUG(3, "blkmtd: read: pagenr = %d offset = %d, pages = %d\n", - pagenr, offset, pages); - - while(pages) { - struct page *page; - int cpylen; - - DEBUG(3, "blkmtd: read: looking for page: %d\n", pagenr); - page = read_cache_page(dev->blkdev->bd_inode->i_mapping, pagenr, (filler_t *)blkmtd_readpage, dev); - if(IS_ERR(page)) { - err = -EIO; - goto readerr; - } - - cpylen = (PAGE_SIZE > len) ? len : PAGE_SIZE; - if(offset+cpylen > PAGE_SIZE) - cpylen = PAGE_SIZE-offset; - - memcpy(buf + thislen, page_address(page) + offset, cpylen); - offset = 0; - len -= cpylen; - thislen += cpylen; - pagenr++; - pages--; - if(!PageDirty(page)) - page_cache_release(page); - } - - readerr: - if(retlen) - *retlen = thislen; - DEBUG(2, "blkmtd: end read: retlen = %zd, err = %d\n", thislen, err); - return err; -} - - -/* write data to the underlying device */ -static int blkmtd_write(struct mtd_info *mtd, loff_t to, size_t len, - size_t *retlen, const u_char *buf) -{ - struct blkmtd_dev *dev = mtd->priv; - int err; - - if(!len) - return 0; - - DEBUG(2, "blkmtd: write: dev = `%s' to = %lld len = %zd buf = %p\n", - mtd->name+9, to, len, buf); - - if(to >= mtd->size) { - return -ENOSPC; - } - - if(to + len > mtd->size) { - len = mtd->size - to; - } - - err = write_pages(dev, buf, to, len, retlen); - if(err > 0) - err = 0; - DEBUG(2, "blkmtd: write: end, err = %d\n", err); - return err; -} - - -/* sync the device - wait until the write queue is empty */ -static void blkmtd_sync(struct mtd_info *mtd) -{ - /* Currently all writes are synchronous */ -} - - -static void free_device(struct blkmtd_dev *dev) -{ - DEBUG(2, "blkmtd: free_device() dev = %p\n", dev); - if(dev) { - kfree(dev->mtd_info.eraseregions); - kfree(dev->mtd_info.name); - if(dev->blkdev) { - invalidate_inode_pages(dev->blkdev->bd_inode->i_mapping); - close_bdev_excl(dev->blkdev); - } - kfree(dev); - } -} - - -/* For a given size and initial erase size, calculate the number - * and size of each erase region. Goes round the loop twice, - * once to find out how many regions, then allocates space, - * then round the loop again to fill it in. - */ -static struct mtd_erase_region_info *calc_erase_regions( - size_t erase_size, size_t total_size, int *regions) -{ - struct mtd_erase_region_info *info = NULL; - - DEBUG(2, "calc_erase_regions, es = %zd size = %zd regions = %d\n", - erase_size, total_size, *regions); - /* Make any user specified erasesize be a power of 2 - and at least PAGE_SIZE */ - if(erase_size) { - int es = erase_size; - erase_size = 1; - while(es != 1) { - es >>= 1; - erase_size <<= 1; - } - if(erase_size < PAGE_SIZE) - erase_size = PAGE_SIZE; - } else { - erase_size = CONFIG_MTD_BLKDEV_ERASESIZE; - } - - *regions = 0; - - do { - int tot_size = total_size; - int er_size = erase_size; - int count = 0, offset = 0, regcnt = 0; - - while(tot_size) { - count = tot_size / er_size; - if(count) { - tot_size = tot_size % er_size; - if(info) { - DEBUG(2, "adding to erase info off=%d er=%d cnt=%d\n", - offset, er_size, count); - (info+regcnt)->offset = offset; - (info+regcnt)->erasesize = er_size; - (info+regcnt)->numblocks = count; - (*regions)++; - } - regcnt++; - offset += (count * er_size); - } - while(er_size > tot_size) - er_size >>= 1; - } - if(info == NULL) { - info = kmalloc(regcnt * sizeof(struct mtd_erase_region_info), GFP_KERNEL); - if(!info) - break; - } - } while(!(*regions)); - DEBUG(2, "calc_erase_regions done, es = %zd size = %zd regions = %d\n", - erase_size, total_size, *regions); - return info; -} - - -static struct blkmtd_dev *add_device(char *devname, int readonly, int erase_size) -{ - struct block_device *bdev; - int mode; - struct blkmtd_dev *dev; - - if(!devname) - return NULL; - - /* Get a handle on the device */ - - -#ifdef MODULE - mode = (readonly) ? O_RDONLY : O_RDWR; - bdev = open_bdev_excl(devname, mode, NULL); -#else - mode = (readonly) ? FMODE_READ : FMODE_WRITE; - bdev = open_by_devnum(name_to_dev_t(devname), mode); -#endif - if(IS_ERR(bdev)) { - err("error: cannot open device %s", devname); - DEBUG(2, "blkmtd: opening bdev returned %ld\n", PTR_ERR(bdev)); - return NULL; - } - - DEBUG(1, "blkmtd: found a block device major = %d, minor = %d\n", - MAJOR(bdev->bd_dev), MINOR(bdev->bd_dev)); - - if(MAJOR(bdev->bd_dev) == MTD_BLOCK_MAJOR) { - err("attempting to use an MTD device as a block device"); - blkdev_put(bdev); - return NULL; - } - - dev = kmalloc(sizeof(struct blkmtd_dev), GFP_KERNEL); - if(dev == NULL) { - blkdev_put(bdev); - return NULL; - } - - memset(dev, 0, sizeof(struct blkmtd_dev)); - dev->blkdev = bdev; - if(!readonly) { - mutex_init(&dev->wrbuf_mutex); - } - - dev->mtd_info.size = dev->blkdev->bd_inode->i_size & PAGE_MASK; - - /* Setup the MTD structure */ - /* make the name contain the block device in */ - dev->mtd_info.name = kmalloc(sizeof("blkmtd: ") + strlen(devname), GFP_KERNEL); - if(dev->mtd_info.name == NULL) - goto devinit_err; - - sprintf(dev->mtd_info.name, "blkmtd: %s", devname); - dev->mtd_info.eraseregions = calc_erase_regions(erase_size, dev->mtd_info.size, - &dev->mtd_info.numeraseregions); - if(dev->mtd_info.eraseregions == NULL) - goto devinit_err; - - dev->mtd_info.erasesize = dev->mtd_info.eraseregions->erasesize; - DEBUG(1, "blkmtd: init: found %d erase regions\n", - dev->mtd_info.numeraseregions); - - if(readonly) { - dev->mtd_info.type = MTD_ROM; - dev->mtd_info.flags = MTD_CAP_ROM; - } else { - dev->mtd_info.type = MTD_RAM; - dev->mtd_info.flags = MTD_CAP_RAM; - dev->mtd_info.erase = blkmtd_erase; - dev->mtd_info.write = blkmtd_write; - dev->mtd_info.writev = default_mtd_writev; - dev->mtd_info.sync = blkmtd_sync; - } - dev->mtd_info.read = blkmtd_read; - dev->mtd_info.readv = default_mtd_readv; - dev->mtd_info.priv = dev; - dev->mtd_info.owner = THIS_MODULE; - - list_add(&dev->list, &blkmtd_device_list); - if (add_mtd_device(&dev->mtd_info)) { - /* Device didnt get added, so free the entry */ - list_del(&dev->list); - goto devinit_err; - } else { - info("mtd%d: [%s] erase_size = %dKiB %s", - dev->mtd_info.index, dev->mtd_info.name + strlen("blkmtd: "), - dev->mtd_info.erasesize >> 10, - readonly ? "(read-only)" : ""); - } - - return dev; - - devinit_err: - free_device(dev); - return NULL; -} - - -/* Cleanup and exit - sync the device and kill of the kernel thread */ -static void __devexit cleanup_blkmtd(void) -{ - struct list_head *temp1, *temp2; - - /* Remove the MTD devices */ - list_for_each_safe(temp1, temp2, &blkmtd_device_list) { - struct blkmtd_dev *dev = list_entry(temp1, struct blkmtd_dev, - list); - blkmtd_sync(&dev->mtd_info); - del_mtd_device(&dev->mtd_info); - info("mtd%d: [%s] removed", dev->mtd_info.index, - dev->mtd_info.name + strlen("blkmtd: ")); - list_del(&dev->list); - free_device(dev); - } -} - -#ifndef MODULE - -/* Handle kernel boot params */ - - -static int __init param_blkmtd_device(char *str) -{ - int i; - - for(i = 0; i < MAX_DEVICES; i++) { - device[i] = str; - DEBUG(2, "blkmtd: device setup: %d = %s\n", i, device[i]); - strsep(&str, ","); - } - return 1; -} - - -static int __init param_blkmtd_erasesz(char *str) -{ - int i; - for(i = 0; i < MAX_DEVICES; i++) { - char *val = strsep(&str, ","); - if(val) - erasesz[i] = simple_strtoul(val, NULL, 0); - DEBUG(2, "blkmtd: erasesz setup: %d = %d\n", i, erasesz[i]); - } - - return 1; -} - - -static int __init param_blkmtd_ro(char *str) -{ - int i; - for(i = 0; i < MAX_DEVICES; i++) { - char *val = strsep(&str, ","); - if(val) - ro[i] = simple_strtoul(val, NULL, 0); - DEBUG(2, "blkmtd: ro setup: %d = %d\n", i, ro[i]); - } - - return 1; -} - - -static int __init param_blkmtd_sync(char *str) -{ - if(str[0] == '1') - sync = 1; - return 1; -} - -__setup("blkmtd_device=", param_blkmtd_device); -__setup("blkmtd_erasesz=", param_blkmtd_erasesz); -__setup("blkmtd_ro=", param_blkmtd_ro); -__setup("blkmtd_sync=", param_blkmtd_sync); - -#endif - - -/* Startup */ -static int __init init_blkmtd(void) -{ - int i; - - info("version " VERSION); - /* Check args - device[0] is the bare minimum*/ - if(!device[0]) { - err("error: missing `device' name\n"); - return -EINVAL; - } - - for(i = 0; i < MAX_DEVICES; i++) - add_device(device[i], ro[i], erasesz[i] << 10); - - if(list_empty(&blkmtd_device_list)) - return -EINVAL; - - return 0; -} - -module_init(init_blkmtd); -module_exit(cleanup_blkmtd); diff --git a/drivers/net/chelsio/Makefile b/drivers/net/chelsio/Makefile index 91e9278..54c78d9 100644 --- a/drivers/net/chelsio/Makefile +++ b/drivers/net/chelsio/Makefile @@ -4,7 +4,7 @@ obj-$(CONFIG_CHELSIO_T1) += cxgb.o -EXTRA_CFLAGS += -I$(TOPDIR)/drivers/net/chelsio $(DEBUG_FLAGS) +EXTRA_CFLAGS += -Idrivers/net/chelsio $(DEBUG_FLAGS) cxgb-objs := cxgb2.o espi.o pm3393.o sge.o subr.o mv88x201x.o diff --git a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c index 6e2ec56..606243d 100644 --- a/drivers/net/irda/irda-usb.c +++ b/drivers/net/irda/irda-usb.c @@ -1,7 +1,7 @@ /***************************************************************************** * * Filename: irda-usb.c - * Version: 0.9b + * Version: 0.10 * Description: IrDA-USB Driver * Status: Experimental * Author: Dag Brattli <dag@brattli.net> @@ -9,6 +9,9 @@ * Copyright (C) 2000, Roman Weissgaerber <weissg@vienna.at> * Copyright (C) 2001, Dag Brattli <dag@brattli.net> * Copyright (C) 2001, Jean Tourrilhes <jt@hpl.hp.com> + * Copyright (C) 2004, SigmaTel, Inc. <irquality@sigmatel.com> + * Copyright (C) 2005, Milan Beno <beno@pobox.sk> + * Copyright (C) 2006, Nick Fedchik <nick@fedchik.org.ua> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -61,6 +64,7 @@ #include <linux/slab.h> #include <linux/rtnetlink.h> #include <linux/usb.h> +#include <linux/firmware.h> #include "irda-usb.h" @@ -78,8 +82,12 @@ static struct usb_device_id dongles[] = { { USB_DEVICE(0x50f, 0x180), .driver_info = IUC_SPEED_BUG | IUC_NO_WINDOW }, /* Extended Systems, Inc., XTNDAccess IrDA USB (ESI-9685) */ { USB_DEVICE(0x8e9, 0x100), .driver_info = IUC_SPEED_BUG | IUC_NO_WINDOW }, + /* SigmaTel STIR4210/4220/4116 USB IrDA (VFIR) Bridge */ + { USB_DEVICE(0x66f, 0x4210), .driver_info = IUC_STIR_4210 | IUC_SPEED_BUG }, + { USB_DEVICE(0x66f, 0x4220), .driver_info = IUC_STIR_4210 | IUC_SPEED_BUG }, + { USB_DEVICE(0x66f, 0x4116), .driver_info = IUC_STIR_4210 | IUC_SPEED_BUG }, { .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS | - USB_DEVICE_ID_MATCH_INT_SUBCLASS, + USB_DEVICE_ID_MATCH_INT_SUBCLASS, .bInterfaceClass = USB_CLASS_APP_SPEC, .bInterfaceSubClass = USB_CLASS_IRDA, .driver_info = IUC_DEFAULT, }, @@ -99,6 +107,7 @@ MODULE_DEVICE_TABLE(usb, dongles); /*------------------------------------------------------------------*/ +static void irda_usb_init_qos(struct irda_usb_cb *self) ; static struct irda_class_desc *irda_usb_find_class_desc(struct usb_interface *intf); static void irda_usb_disconnect(struct usb_interface *intf); static void irda_usb_change_speed_xbofs(struct irda_usb_cb *self); @@ -141,7 +150,24 @@ static void irda_usb_build_header(struct irda_usb_cb *self, __u8 *header, int force) { - /* Set the negotiated link speed */ + /* Here we check if we have an STIR421x chip, + * and if either speed or xbofs (or both) needs + * to be changed. + */ + if (self->capability & IUC_STIR_4210 && + ((self->new_speed != -1) || (self->new_xbofs != -1))) { + + /* With STIR421x, speed and xBOFs must be set at the same + * time, even if only one of them changes. + */ + if (self->new_speed == -1) + self->new_speed = self->speed ; + + if (self->new_xbofs == -1) + self->new_xbofs = self->xbofs ; + } + + /* Set the link speed */ if (self->new_speed != -1) { /* Hum... Ugly hack :-( * Some device are not compliant with the spec and change @@ -191,7 +217,11 @@ static void irda_usb_build_header(struct irda_usb_cb *self, *header = SPEED_4000000; self->new_xbofs = 0; break; - } + case 16000000: + *header = SPEED_16000000; + self->new_xbofs = 0; + break; + } } else /* No change */ *header = 0; @@ -235,6 +265,32 @@ static void irda_usb_build_header(struct irda_usb_cb *self, } } +/* +* calculate turnaround time for SigmaTel header +*/ +static __u8 get_turnaround_time(struct sk_buff *skb) +{ + int turnaround_time = irda_get_mtt(skb); + + if ( turnaround_time == 0 ) + return 0; + else if ( turnaround_time <= 10 ) + return 1; + else if ( turnaround_time <= 50 ) + return 2; + else if ( turnaround_time <= 100 ) + return 3; + else if ( turnaround_time <= 500 ) + return 4; + else if ( turnaround_time <= 1000 ) + return 5; + else if ( turnaround_time <= 5000 ) + return 6; + else + return 7; +} + + /*------------------------------------------------------------------*/ /* * Send a command to change the speed of the dongle @@ -262,12 +318,18 @@ static void irda_usb_change_speed_xbofs(struct irda_usb_cb *self) /* Set the new speed and xbofs in this fake frame */ irda_usb_build_header(self, frame, 1); + if ( self->capability & IUC_STIR_4210 ) { + if (frame[0] == 0) return ; // do nothing if no change + frame[1] = 0; // other parameters don't change here + frame[2] = 0; + } + /* Submit the 0 length IrDA frame to trigger new speed settings */ usb_fill_bulk_urb(urb, self->usbdev, usb_sndbulkpipe(self->usbdev, self->bulk_out_ep), frame, IRDA_USB_SPEED_MTU, speed_bulk_callback, self); - urb->transfer_buffer_length = USB_IRDA_HEADER; + urb->transfer_buffer_length = self->header_length; urb->transfer_flags = 0; /* Irq disabled -> GFP_ATOMIC */ @@ -383,16 +445,35 @@ static int irda_usb_hard_xmit(struct sk_buff *skb, struct net_device *netdev) * allocation will be done lower in skb_push(). * Also, we don't use directly skb_cow(), because it require * headroom >= 16, which force unnecessary copies - Jean II */ - if (skb_headroom(skb) < USB_IRDA_HEADER) { + if (skb_headroom(skb) < self->header_length) { IRDA_DEBUG(0, "%s(), Insuficient skb headroom.\n", __FUNCTION__); - if (skb_cow(skb, USB_IRDA_HEADER)) { + if (skb_cow(skb, self->header_length)) { IRDA_WARNING("%s(), failed skb_cow() !!!\n", __FUNCTION__); goto drop; } } /* Change setting for next frame */ - irda_usb_build_header(self, skb_push(skb, USB_IRDA_HEADER), 0); + + if ( self->capability & IUC_STIR_4210 ) { + __u8 turnaround_time; + __u8* frame; + turnaround_time = get_turnaround_time( skb ); + frame= skb_push(skb, self->header_length); + irda_usb_build_header(self, frame, 0); + frame[2] = turnaround_time; + if ((skb->len != 0) && + ((skb->len % 128) == 0) && + ((skb->len % 512) != 0)) { + /* add extra byte for special SigmaTel feature */ + frame[1] = 1; + skb_put(skb, 1); + } else { + frame[1] = 0; + } + } else { + irda_usb_build_header(self, skb_push(skb, self->header_length), 0); + } /* FIXME: Make macro out of this one */ ((struct irda_skb_cb *)skb->cb)->context = self; @@ -795,7 +876,7 @@ static void irda_usb_receive(struct urb *urb, struct pt_regs *regs) } /* Check for empty frames */ - if (urb->actual_length <= USB_IRDA_HEADER) { + if (urb->actual_length <= self->header_length) { IRDA_WARNING("%s(), empty frame!\n", __FUNCTION__); goto done; } @@ -816,7 +897,11 @@ static void irda_usb_receive(struct urb *urb, struct pt_regs *regs) docopy = (urb->actual_length < IRDA_RX_COPY_THRESHOLD); /* Allocate a new skb */ - newskb = dev_alloc_skb(docopy ? urb->actual_length : IRDA_SKB_MAX_MTU); + if ( self->capability & IUC_STIR_4210 ) + newskb = dev_alloc_skb(docopy ? urb->actual_length : IRDA_SKB_MAX_MTU + USB_IRDA_SIGMATEL_HEADER); + else + newskb = dev_alloc_skb(docopy ? urb->actual_length : IRDA_SKB_MAX_MTU); + if (!newskb) { self->stats.rx_dropped++; /* We could deliver the current skb, but this would stall @@ -845,7 +930,7 @@ static void irda_usb_receive(struct urb *urb, struct pt_regs *regs) /* Set proper length on skb & remove USB-IrDA header */ skb_put(dataskb, urb->actual_length); - skb_pull(dataskb, USB_IRDA_HEADER); + skb_pull(dataskb, self->header_length); /* Ask the networking layer to queue the packet for the IrDA stack */ dataskb->dev = self->netdev; @@ -937,6 +1022,191 @@ static int irda_usb_is_receiving(struct irda_usb_cb *self) return 0; /* For now */ } + +#define STIR421X_PATCH_PRODUCT_VERSION_STR "Product Version: " +#define STIR421X_PATCH_COMPONENT_VERSION_STR "Component Version: " +#define STIR421X_PATCH_DATA_TAG_STR "STMP" +#define STIR421X_PATCH_FILE_VERSION_MAX_OFFSET 512 /* version info is before here */ +#define STIR421X_PATCH_FILE_IMAGE_MAX_OFFSET 512 /* patch image starts before here */ +#define STIR421X_PATCH_FILE_END_OF_HEADER_TAG 0x1A /* marks end of patch file header (PC DOS text file EOF character) */ + +/* + * Known firmware patches for STIR421x dongles + */ +static char * stir421x_patches[] = { + "42101001.sb", + "42101002.sb", +}; + +static int stir421x_get_patch_version(unsigned char * patch, const unsigned long patch_len) +{ + unsigned int version_offset; + unsigned long version_major, version_minor, version_build; + unsigned char * version_start; + int version_found = 0; + + for (version_offset = 0; + version_offset < STIR421X_PATCH_FILE_END_OF_HEADER_TAG; + version_offset++) { + if (!memcmp(patch + version_offset, + STIR421X_PATCH_PRODUCT_VERSION_STR, + sizeof(STIR421X_PATCH_PRODUCT_VERSION_STR) - 1)) { + version_found = 1; + version_start = patch + + version_offset + + sizeof(STIR421X_PATCH_PRODUCT_VERSION_STR) - 1; + break; + } + } + + /* We couldn't find a product version on this patch */ + if (!version_found) + return -EINVAL; + + /* Let's check if the product version is dotted */ + if (version_start[3] != '.' || + version_start[7] != '.') + return -EINVAL; + + version_major = simple_strtoul(version_start, NULL, 10); + version_minor = simple_strtoul(version_start + 4, NULL, 10); + version_build = simple_strtoul(version_start + 8, NULL, 10); + + IRDA_DEBUG(2, "%s(), Major: %ld Minor: %ld Build: %ld\n", + __FUNCTION__, + version_major, version_minor, version_build); + + return (((version_major) << 12) + + ((version_minor) << 8) + + ((version_build / 10) << 4) + + (version_build % 10)); + +} + + +static int stir421x_upload_patch (struct irda_usb_cb *self, + unsigned char * patch, + const unsigned int patch_len) +{ + int retval = 0; + int actual_len; + unsigned int i = 0, download_amount = 0; + unsigned char * patch_chunk; + + IRDA_DEBUG (2, "%s(), Uploading STIR421x Patch\n", __FUNCTION__); + + patch_chunk = kzalloc(STIR421X_MAX_PATCH_DOWNLOAD_SIZE, GFP_KERNEL); + if (patch_chunk == NULL) + return -ENOMEM; + + /* break up patch into 1023-byte sections */ + for (i = 0; retval >= 0 && i < patch_len; i += download_amount) { + download_amount = patch_len - i; + if (download_amount > STIR421X_MAX_PATCH_DOWNLOAD_SIZE) + download_amount = STIR421X_MAX_PATCH_DOWNLOAD_SIZE; + + /* download the patch section */ + memcpy(patch_chunk, patch + i, download_amount); + + retval = usb_bulk_msg (self->usbdev, + usb_sndbulkpipe (self->usbdev, + self->bulk_out_ep), + patch_chunk, download_amount, + &actual_len, msecs_to_jiffies (500)); + IRDA_DEBUG (2, "%s(), Sent %u bytes\n", __FUNCTION__, + actual_len); + if (retval == 0) + mdelay(10); + } + + kfree(patch_chunk); + + if (i != patch_len) { + IRDA_ERROR ("%s(), Pushed %d bytes (!= patch_len (%d))\n", + __FUNCTION__, i, patch_len); + retval = -EIO; + } + + if (retval < 0) + /* todo - mark device as not ready */ + IRDA_ERROR ("%s(), STIR421x patch upload failed (%d)\n", + __FUNCTION__, retval); + + return retval; +} + + +static int stir421x_patch_device(struct irda_usb_cb *self) +{ + unsigned int i, patch_found = 0, data_found = 0, data_offset; + int patch_version, ret = 0; + const struct firmware *fw_entry; + + for (i = 0; i < ARRAY_SIZE(stir421x_patches); i++) { + if(request_firmware(&fw_entry, stir421x_patches[i], &self->usbdev->dev) != 0) { + IRDA_ERROR( "%s(), Patch %s is not available\n", __FUNCTION__, stir421x_patches[i]); + continue; + } + + /* We found a patch from userspace */ + patch_version = stir421x_get_patch_version (fw_entry->data, fw_entry->size); + + if (patch_version < 0) { + /* Couldn't fetch a version, let's move on to the next file */ + IRDA_ERROR("%s(), version parsing failed\n", __FUNCTION__); + ret = patch_version; + release_firmware(fw_entry); + continue; + } + + if (patch_version != self->usbdev->descriptor.bcdDevice) { + /* Patch version and device don't match */ + IRDA_ERROR ("%s(), wrong patch version (%d <-> %d)\n", + __FUNCTION__, + patch_version, self->usbdev->descriptor.bcdDevice); + ret = -EINVAL; + release_firmware(fw_entry); + continue; + } + + /* If we're here, we've found a correct patch */ + patch_found = 1; + break; + + } + + /* We couldn't find a valid firmware, let's leave */ + if (!patch_found) + return ret; + + /* The actual image starts after the "STMP" keyword */ + for (data_offset = 0; data_offset < STIR421X_PATCH_FILE_IMAGE_MAX_OFFSET; data_offset++) { + if (!memcmp(fw_entry->data + data_offset, + STIR421X_PATCH_DATA_TAG_STR, + sizeof(STIR421X_PATCH_FILE_IMAGE_MAX_OFFSET))) { + IRDA_DEBUG(2, "%s(), found patch data for STIR421x at offset %d\n", + __FUNCTION__, data_offset); + data_found = 1; + break; + } + } + + /* We couldn't find "STMP" from the header */ + if (!data_found) + return -EINVAL; + + /* Let's upload the patch to the target */ + ret = stir421x_upload_patch(self, + &fw_entry->data[data_offset + sizeof(STIR421X_PATCH_FILE_IMAGE_MAX_OFFSET)], + fw_entry->size - (data_offset + sizeof(STIR421X_PATCH_FILE_IMAGE_MAX_OFFSET))); + + release_firmware(fw_entry); + + return ret; + +} + + /********************** IRDA DEVICE CALLBACKS **********************/ /* * Main calls from the IrDA/Network subsystem. @@ -972,6 +1242,11 @@ static int irda_usb_net_open(struct net_device *netdev) return -1; } + if(self->needspatch) { + IRDA_WARNING("%s(), device needs patch\n", __FUNCTION__) ; + return -EIO ; + } + /* Initialise default speed and xbofs value * (IrLAP will change that soon) */ self->speed = -1; @@ -1050,7 +1325,7 @@ static int irda_usb_net_close(struct net_device *netdev) del_timer(&self->rx_defer_timer); /* Deallocate all the Rx path buffers (URBs and skb) */ - for (i = 0; i < IU_MAX_RX_URBS; i++) { + for (i = 0; i < self->max_rx_urb; i++) { struct urb *urb = self->rx_urb[i]; struct sk_buff *skb = (struct sk_buff *) urb->context; /* Cancel the receive command */ @@ -1426,8 +1701,22 @@ static int irda_usb_probe(struct usb_interface *intf, spin_lock_init(&self->lock); init_timer(&self->rx_defer_timer); + self->capability = id->driver_info; + self->needspatch = ((self->capability & IUC_STIR_4210) != 0) ; + /* Create all of the needed urbs */ - for (i = 0; i < IU_MAX_RX_URBS; i++) { + if (self->capability & IUC_STIR_4210) { + self->max_rx_urb = IU_SIGMATEL_MAX_RX_URBS; + self->header_length = USB_IRDA_SIGMATEL_HEADER; + } else { + self->max_rx_urb = IU_MAX_RX_URBS; + self->header_length = USB_IRDA_HEADER; + } + + self->rx_urb = kzalloc(self->max_rx_urb * sizeof(struct urb *), + GFP_KERNEL); + + for (i = 0; i < self->max_rx_urb; i++) { self->rx_urb[i] = usb_alloc_urb(0, GFP_KERNEL); if (!self->rx_urb[i]) { goto err_out_1; @@ -1479,17 +1768,28 @@ static int irda_usb_probe(struct usb_interface *intf, goto err_out_3; } + self->usbdev = dev; + /* Find IrDA class descriptor */ irda_desc = irda_usb_find_class_desc(intf); ret = -ENODEV; if (irda_desc == NULL) goto err_out_3; + if (self->needspatch) { + ret = usb_control_msg (self->usbdev, usb_sndctrlpipe (self->usbdev, 0), + 0x02, 0x40, 0, 0, 0, 0, msecs_to_jiffies(500)); + if (ret < 0) { + IRDA_DEBUG (0, "usb_control_msg failed %d\n", ret); + goto err_out_3; + } else { + mdelay(10); + } + } + self->irda_desc = irda_desc; self->present = 1; self->netopen = 0; - self->capability = id->driver_info; - self->usbdev = dev; self->usbintf = intf; /* Allocate the buffer for speed changes */ @@ -1508,6 +1808,28 @@ static int irda_usb_probe(struct usb_interface *intf, IRDA_MESSAGE("IrDA: Registered device %s\n", net->name); usb_set_intfdata(intf, self); + + if (self->needspatch) { + /* Now we fetch and upload the firmware patch */ + ret = stir421x_patch_device(self); + self->needspatch = (ret < 0); + if (ret < 0) { + printk("patch_device failed\n"); + goto err_out_4; + } + + /* replace IrDA class descriptor with what patched device is now reporting */ + irda_desc = irda_usb_find_class_desc (self->usbintf); + if (irda_desc == NULL) { + ret = -ENODEV; + goto err_out_4; + } + if (self->irda_desc) + kfree (self->irda_desc); + self->irda_desc = irda_desc; + irda_usb_init_qos(self); + } + return 0; err_out_4: @@ -1518,7 +1840,7 @@ err_out_3: err_out_2: usb_free_urb(self->tx_urb); err_out_1: - for (i = 0; i < IU_MAX_RX_URBS; i++) { + for (i = 0; i < self->max_rx_urb; i++) { if (self->rx_urb[i]) usb_free_urb(self->rx_urb[i]); } @@ -1571,7 +1893,7 @@ static void irda_usb_disconnect(struct usb_interface *intf) /*netif_device_detach(self->netdev);*/ netif_stop_queue(self->netdev); /* Stop all the receive URBs. Must be synchronous. */ - for (i = 0; i < IU_MAX_RX_URBS; i++) + for (i = 0; i < self->max_rx_urb; i++) usb_kill_urb(self->rx_urb[i]); /* Cancel Tx and speed URB. * Make sure it's synchronous to avoid races. */ @@ -1586,8 +1908,9 @@ static void irda_usb_disconnect(struct usb_interface *intf) self->usbintf = NULL; /* Clean up our urbs */ - for (i = 0; i < IU_MAX_RX_URBS; i++) + for (i = 0; i < self->max_rx_urb; i++) usb_free_urb(self->rx_urb[i]); + kfree(self->rx_urb); /* Clean up Tx and speed URB */ usb_free_urb(self->tx_urb); usb_free_urb(self->speed_urb); @@ -1648,6 +1971,6 @@ module_exit(usb_irda_cleanup); */ module_param(qos_mtt_bits, int, 0); MODULE_PARM_DESC(qos_mtt_bits, "Minimum Turn Time"); -MODULE_AUTHOR("Roman Weissgaerber <weissg@vienna.at>, Dag Brattli <dag@brattli.net> and Jean Tourrilhes <jt@hpl.hp.com>"); -MODULE_DESCRIPTION("IrDA-USB Dongle Driver"); +MODULE_AUTHOR("Roman Weissgaerber <weissg@vienna.at>, Dag Brattli <dag@brattli.net>, Jean Tourrilhes <jt@hpl.hp.com> and Nick Fedchik <nick@fedchik.org.ua>"); +MODULE_DESCRIPTION("IrDA-USB Dongle Driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/net/irda/irda-usb.h b/drivers/net/irda/irda-usb.h index 4026af4..d833db5 100644 --- a/drivers/net/irda/irda-usb.h +++ b/drivers/net/irda/irda-usb.h @@ -1,7 +1,7 @@ /***************************************************************************** * * Filename: irda-usb.h - * Version: 0.9b + * Version: 0.10 * Description: IrDA-USB Driver * Status: Experimental * Author: Dag Brattli <dag@brattli.net> @@ -9,6 +9,9 @@ * Copyright (C) 2001, Roman Weissgaerber <weissg@vienna.at> * Copyright (C) 2000, Dag Brattli <dag@brattli.net> * Copyright (C) 2001, Jean Tourrilhes <jt@hpl.hp.com> + * Copyright (C) 2004, SigmaTel, Inc. <irquality@sigmatel.com> + * Copyright (C) 2005, Milan Beno <beno@pobox.sk> + * Copyright (C) 2006, Nick FEdchik <nick@fedchik.org.ua> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -31,6 +34,9 @@ #include <net/irda/irda.h> #include <net/irda/irda_device.h> /* struct irlap_cb */ +#define PATCH_FILE_SIZE_MAX 65536 +#define PATCH_FILE_SIZE_MIN 80 + #define RX_COPY_THRESHOLD 200 #define IRDA_USB_MAX_MTU 2051 #define IRDA_USB_SPEED_MTU 64 /* Weird, but work like this */ @@ -79,15 +85,16 @@ /* Inbound header */ #define MEDIA_BUSY 0x80 -#define SPEED_2400 0x01 -#define SPEED_9600 0x02 -#define SPEED_19200 0x03 -#define SPEED_38400 0x04 -#define SPEED_57600 0x05 -#define SPEED_115200 0x06 -#define SPEED_576000 0x07 -#define SPEED_1152000 0x08 -#define SPEED_4000000 0x09 +#define SPEED_2400 0x01 +#define SPEED_9600 0x02 +#define SPEED_19200 0x03 +#define SPEED_38400 0x04 +#define SPEED_57600 0x05 +#define SPEED_115200 0x06 +#define SPEED_576000 0x07 +#define SPEED_1152000 0x08 +#define SPEED_4000000 0x09 +#define SPEED_16000000 0x0a /* Basic capabilities */ #define IUC_DEFAULT 0x00 /* Basic device compliant with 1.0 spec */ @@ -100,11 +107,14 @@ #define IUC_SMALL_PKT 0x10 /* Device doesn't behave with big Rx packets */ #define IUC_MAX_WINDOW 0x20 /* Device underestimate the Rx window */ #define IUC_MAX_XBOFS 0x40 /* Device need more xbofs than advertised */ +#define IUC_STIR_4210 0x80 /* SigmaTel 4210/4220/4116 VFIR */ /* USB class definitions */ -#define USB_IRDA_HEADER 0x01 -#define USB_CLASS_IRDA 0x02 /* USB_CLASS_APP_SPEC subclass */ -#define USB_DT_IRDA 0x21 +#define USB_IRDA_HEADER 0x01 +#define USB_CLASS_IRDA 0x02 /* USB_CLASS_APP_SPEC subclass */ +#define USB_DT_IRDA 0x21 +#define USB_IRDA_SIGMATEL_HEADER 0x03 +#define IU_SIGMATEL_MAX_RX_URBS (IU_MAX_ACTIVE_RX_URBS + USB_IRDA_SIGMATEL_HEADER) struct irda_class_desc { __u8 bLength; @@ -123,6 +133,7 @@ struct irda_class_desc { * (6.2.5, USB-IrDA class spec 1.0) */ #define IU_REQ_GET_CLASS_DESC 0x06 +#define STIR421X_MAX_PATCH_DOWNLOAD_SIZE 1023 struct irda_usb_cb { struct irda_class_desc *irda_desc; @@ -136,7 +147,8 @@ struct irda_usb_cb { __u16 bulk_out_mtu; /* Max Tx packet size in bytes */ __u8 bulk_int_ep; /* Interrupt Endpoint assignments */ - struct urb *rx_urb[IU_MAX_RX_URBS]; /* URBs used to receive data frames */ + __u8 max_rx_urb; + struct urb **rx_urb; /* URBs used to receive data frames */ struct urb *idle_rx_urb; /* Pointer to idle URB in Rx path */ struct urb *tx_urb; /* URB used to send data frames */ struct urb *speed_urb; /* URB used to send speed commands */ @@ -157,6 +169,9 @@ struct irda_usb_cb { __u32 speed; /* Current speed */ __s32 new_speed; /* speed we need to set */ + __u8 header_length; /* USB-IrDA frame header size */ + int needspatch; /* device needs firmware patch */ + struct timer_list rx_defer_timer; /* Wait for Rx error to clear */ }; diff --git a/drivers/net/irda/smsc-ircc2.c b/drivers/net/irda/smsc-ircc2.c index ec94ecd..bbcfc8e 100644 --- a/drivers/net/irda/smsc-ircc2.c +++ b/drivers/net/irda/smsc-ircc2.c @@ -11,6 +11,7 @@ * Copyright (c) 2002 Daniele Peri * All Rights Reserved. * Copyright (c) 2002 Jean Tourrilhes + * Copyright (c) 2006 Linus Walleij * * * Based on smc-ircc.c: @@ -61,6 +62,9 @@ #include <linux/spinlock.h> #include <linux/pm.h> +#ifdef CONFIG_PCI +#include <linux/pci.h> +#endif #include <net/irda/wrapper.h> #include <net/irda/irda.h> @@ -100,6 +104,22 @@ MODULE_PARM_DESC(ircc_transceiver, "Transceiver type"); /* Types */ +#ifdef CONFIG_PCI +struct smsc_ircc_subsystem_configuration { + unsigned short vendor; /* PCI vendor ID */ + unsigned short device; /* PCI vendor ID */ + unsigned short subvendor; /* PCI subsystem vendor ID */ + unsigned short subdevice; /* PCI sybsystem device ID */ + unsigned short sir_io; /* I/O port for SIR */ + unsigned short fir_io; /* I/O port for FIR */ + unsigned char fir_irq; /* FIR IRQ */ + unsigned char fir_dma; /* FIR DMA */ + unsigned short cfg_base; /* I/O port for chip configuration */ + int (*preconfigure)(struct pci_dev *dev, struct smsc_ircc_subsystem_configuration *conf); /* Preconfig function */ + const char *name; /* name shown as info */ +}; +#endif + struct smsc_transceiver { char *name; void (*set_for_speed)(int fir_base, u32 speed); @@ -202,6 +222,16 @@ static int __init smsc_superio_flat(const struct smsc_chip *chips, unsigned shor static int __init smsc_superio_paged(const struct smsc_chip *chips, unsigned short cfg_base, char *type); static int __init smsc_superio_fdc(unsigned short cfg_base); static int __init smsc_superio_lpc(unsigned short cfg_base); +#ifdef CONFIG_PCI +static int __init preconfigure_smsc_chip(struct smsc_ircc_subsystem_configuration *conf); +static int __init preconfigure_through_82801(struct pci_dev *dev, struct smsc_ircc_subsystem_configuration *conf); +static int __init preconfigure_through_ali(struct pci_dev *dev, struct smsc_ircc_subsystem_configuration *conf); +static int __init smsc_ircc_preconfigure_subsystems(unsigned short ircc_cfg, + unsigned short ircc_fir, + unsigned short ircc_sir, + unsigned char ircc_dma, + unsigned char ircc_irq); +#endif /* Transceivers specific functions */ @@ -353,6 +383,13 @@ static int __init smsc_ircc_init(void) return ret; } +#ifdef CONFIG_PCI + if (smsc_ircc_preconfigure_subsystems(ircc_cfg, ircc_fir, ircc_sir, ircc_dma, ircc_irq) < 0) { + /* Ignore errors from preconfiguration */ + IRDA_ERROR("%s, Preconfiguration failed !\n", driver_name); + } +#endif + dev_count = 0; if (ircc_fir > 0 && ircc_sir > 0) { @@ -2285,6 +2322,280 @@ static int __init smsc_superio_lpc(unsigned short cfg_base) return ret; } +/* + * Look for some specific subsystem setups that need + * pre-configuration not properly done by the BIOS (especially laptops) + * This code is based in part on smcinit.c, tosh1800-smcinit.c + * and tosh2450-smcinit.c. The table lists the device entries + * for ISA bridges with an LPC (Local Peripheral Configurator) + * that are in turn used to configure the SMSC device with default + * SIR and FIR I/O ports, DMA and IRQ. + */ +#ifdef CONFIG_PCI +#define PCIID_VENDOR_INTEL 0x8086 +#define PCIID_VENDOR_ALI 0x10b9 +static struct smsc_ircc_subsystem_configuration subsystem_configurations[] __devinitdata = { + { + .vendor = PCIID_VENDOR_INTEL, /* Intel 82801DBM LPC bridge */ + .device = 0x24cc, + .subvendor = 0x103c, + .subdevice = 0x088c, + .sir_io = 0x02f8, /* Quite certain these are the same for nc8000 as for nc6000 */ + .fir_io = 0x0130, + .fir_irq = 0x09, + .fir_dma = 0x03, + .cfg_base = 0x004e, + .preconfigure = preconfigure_through_82801, + .name = "HP nc8000", + }, + { + .vendor = PCIID_VENDOR_INTEL, /* Intel 82801DBM LPC bridge */ + .device = 0x24cc, + .subvendor = 0x103c, + .subdevice = 0x0890, + .sir_io = 0x02f8, + .fir_io = 0x0130, + .fir_irq = 0x09, + .fir_dma = 0x03, + .cfg_base = 0x004e, + .preconfigure = preconfigure_through_82801, + .name = "HP nc6000", + }, + { + .vendor = PCIID_VENDOR_INTEL, /* Intel 82801DB/DBL (ICH4/ICH4-L) LPC Interface Bridge */ + .device = 0x24c0, + .subvendor = 0x1179, + .subdevice = 0xffff, /* 0xffff is "any", Not sure, 0x0001 or 0x0002 */ + .sir_io = 0x03f8, + .fir_io = 0x0130, + .fir_irq = 0x07, + .fir_dma = 0x01, + .cfg_base = 0x002e, + .preconfigure = preconfigure_through_82801, + .name = "Toshiba Satellite 2450", + }, + { + .vendor = PCIID_VENDOR_INTEL, /* Intel 82801CAM ISA bridge */ + .device = 0x248c, /* Some use 24cc? */ + .subvendor = 0x1179, + .subdevice = 0xffff, /* 0xffff is "any", Not sure, 0x0001 or 0x0002 */ + .sir_io = 0x03f8, + .fir_io = 0x0130, + .fir_irq = 0x03, + .fir_dma = 0x03, + .cfg_base = 0x002e, + .preconfigure = preconfigure_through_82801, + .name = "Toshiba Satellite 5100/5200, Tecra 9100", + }, + { + .vendor = PCIID_VENDOR_ALI, /* ALi M1533/M1535 PCI to ISA Bridge [Aladdin IV/V/V+] */ + .device = 0x1533, + .subvendor = 0x1179, + .subdevice = 0xffff, /* 0xffff is "any", Not sure, 0x0001 or 0x0002 */ + .sir_io = 0x02e8, + .fir_io = 0x02f8, + .fir_irq = 0x07, + .fir_dma = 0x03, + .cfg_base = 0x002e, + .preconfigure = preconfigure_through_ali, + .name = "Toshiba Satellite 1800", + }, + { } // Terminator +}; + + +/* + * This sets up the basic SMSC parameters (FIR port, SIR port, FIR DMA, FIR IRQ) + * through the chip configuration port. + */ +static int __init preconfigure_smsc_chip(struct smsc_ircc_subsystem_configuration *conf) +{ + unsigned short iobase = conf->cfg_base; + unsigned char tmpbyte; + + outb(LPC47N227_CFGACCESSKEY, iobase); // enter configuration state + outb(SMSCSIOFLAT_DEVICEID_REG, iobase); // set for device ID + tmpbyte = inb(iobase +1); // Read device ID + IRDA_DEBUG(0, "Detected Chip id: 0x%02x, setting up registers...\n",tmpbyte); + + /* Disable UART1 and set up SIR I/O port */ + outb(0x24, iobase); // select CR24 - UART1 base addr + outb(0x00, iobase + 1); // disable UART1 + outb(SMSCSIOFLAT_UART2BASEADDR_REG, iobase); // select CR25 - UART2 base addr + outb( (conf->sir_io >> 2), iobase + 1); // bits 2-9 of 0x3f8 + tmpbyte = inb(iobase + 1); + if (tmpbyte != (conf->sir_io >> 2) ) { + IRDA_WARNING("ERROR: could not configure SIR ioport.\n"); + return -ENXIO; + } + + /* Set up FIR IRQ channel for UART2 */ + outb(SMSCSIOFLAT_UARTIRQSELECT_REG, iobase); // select CR28 - UART1,2 IRQ select + tmpbyte = inb(iobase + 1); + tmpbyte &= SMSCSIOFLAT_UART1IRQSELECT_MASK; // Do not touch the UART1 portion + tmpbyte |= (conf->fir_irq & SMSCSIOFLAT_UART2IRQSELECT_MASK); + outb(tmpbyte, iobase + 1); + tmpbyte = inb(iobase + 1) & SMSCSIOFLAT_UART2IRQSELECT_MASK; + if (tmpbyte != conf->fir_irq) { + IRDA_WARNING("ERROR: could not configure FIR IRQ channel.\n"); + return -ENXIO; + } + + /* Set up FIR I/O port */ + outb(SMSCSIOFLAT_FIRBASEADDR_REG, iobase); // CR2B - SCE (FIR) base addr + outb((conf->fir_io >> 3), iobase + 1); + tmpbyte = inb(iobase + 1); + if (tmpbyte != (conf->fir_io >> 3) ) { + IRDA_WARNING("ERROR: could not configure FIR I/O port.\n"); + return -ENXIO; + } + + /* Set up FIR DMA channel */ + outb(SMSCSIOFLAT_FIRDMASELECT_REG, iobase); // CR2C - SCE (FIR) DMA select + outb((conf->fir_dma & LPC47N227_FIRDMASELECT_MASK), iobase + 1); // DMA + tmpbyte = inb(iobase + 1) & LPC47N227_FIRDMASELECT_MASK; + if (tmpbyte != (conf->fir_dma & LPC47N227_FIRDMASELECT_MASK)) { + IRDA_WARNING("ERROR: could not configure FIR DMA channel.\n"); + return -ENXIO; + } + + outb(SMSCSIOFLAT_UARTMODE0C_REG, iobase); // CR0C - UART mode + tmpbyte = inb(iobase + 1); + tmpbyte &= ~SMSCSIOFLAT_UART2MODE_MASK | SMSCSIOFLAT_UART2MODE_VAL_IRDA; + outb(tmpbyte, iobase + 1); // enable IrDA (HPSIR) mode, high speed + + outb(LPC47N227_APMBOOTDRIVE_REG, iobase); // CR07 - Auto Pwr Mgt/boot drive sel + tmpbyte = inb(iobase + 1); + outb(tmpbyte | LPC47N227_UART2AUTOPWRDOWN_MASK, iobase + 1); // enable UART2 autopower down + + /* This one was not part of tosh1800 */ + outb(0x0a, iobase); // CR0a - ecp fifo / ir mux + tmpbyte = inb(iobase + 1); + outb(tmpbyte | 0x40, iobase + 1); // send active device to ir port + + outb(LPC47N227_UART12POWER_REG, iobase); // CR02 - UART 1,2 power + tmpbyte = inb(iobase + 1); + outb(tmpbyte | LPC47N227_UART2POWERDOWN_MASK, iobase + 1); // UART2 power up mode, UART1 power down + + outb(LPC47N227_FDCPOWERVALIDCONF_REG, iobase); // CR00 - FDC Power/valid config cycle + tmpbyte = inb(iobase + 1); + outb(tmpbyte | LPC47N227_VALID_MASK, iobase + 1); // valid config cycle done + + outb(LPC47N227_CFGEXITKEY, iobase); // Exit configuration + + return 0; +} + +/* 82801CAM registers */ +#define VID 0x00 +#define DID 0x02 +#define PIRQA_ROUT 0x60 +#define PCI_DMA_C 0x90 +#define COM_DEC 0xe0 +#define LPC_EN 0xe6 +#define GEN2_DEC 0xec +/* + * Sets up the I/O range using the 82801CAM ISA bridge, 82801DBM LPC bridge or + * Intel 82801DB/DBL (ICH4/ICH4-L) LPC Interface Bridge. They all work the same way! + */ +static int __init preconfigure_through_82801(struct pci_dev *dev, + struct smsc_ircc_subsystem_configuration *conf) +{ + unsigned short tmpword; + int ret; + + IRDA_MESSAGE("Setting up the SMSC device via the 82801 controller.\n"); + pci_write_config_byte(dev, COM_DEC, 0x10); + + /* Enable LPC */ + pci_read_config_word(dev, LPC_EN, &tmpword); /* LPC_EN register */ + tmpword &= 0xfffd; /* mask bit 1 */ + tmpword |= 0x0001; /* set bit 0 : COMA addr range enable */ + pci_write_config_word(dev, LPC_EN, tmpword); + + /* Setup DMA */ + pci_write_config_word(dev, PCI_DMA_C, 0xc0c0); /* LPC I/F DMA on, channel 3 -- rtm (?? PCI DMA ?) */ + pci_write_config_word(dev, GEN2_DEC, 0x131); /* LPC I/F 2nd decode range */ + + /* Pre-configure chip */ + ret = preconfigure_smsc_chip(conf); + + /* Disable LPC */ + pci_read_config_word(dev, LPC_EN, &tmpword); /* LPC_EN register */ + tmpword &= 0xfffc; /* mask bit 1 and bit 0, COMA addr range disable */ + pci_write_config_word(dev, LPC_EN, tmpword); + return ret; +} + +static int __init preconfigure_through_ali(struct pci_dev *dev, + struct smsc_ircc_subsystem_configuration *conf) +{ + /* TODO: put in ALi 1533 configuration here. */ + IRDA_MESSAGE("SORRY: %s has an unsupported bridge controller (ALi): not pre-configured.\n", conf->name); + return -ENODEV; +} + +static int __init smsc_ircc_preconfigure_subsystems(unsigned short ircc_cfg, + unsigned short ircc_fir, + unsigned short ircc_sir, + unsigned char ircc_dma, + unsigned char ircc_irq) +{ + struct pci_dev *dev = NULL; + unsigned short ss_vendor = 0x0000; + unsigned short ss_device = 0x0000; + int ret = 0; + + dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev); + + while (dev != NULL) { + struct smsc_ircc_subsystem_configuration *conf; + + /* + * Cache the subsystem vendor/device: some manufacturers fail to set + * this for all components, so we save it in case there is just + * 0x0000 0x0000 on the device we want to check. + */ + if (dev->subsystem_vendor != 0x0000U) { + ss_vendor = dev->subsystem_vendor; + ss_device = dev->subsystem_device; + } + conf = subsystem_configurations; + for( ; conf->subvendor; conf++) { + if(conf->vendor == dev->vendor && + conf->device == dev->device && + conf->subvendor == ss_vendor && /* Sometimes these are cached values */ + (conf->subdevice == ss_device || conf->subdevice == 0xffff)) { + struct smsc_ircc_subsystem_configuration tmpconf; + + memcpy(&tmpconf, conf, sizeof(struct smsc_ircc_subsystem_configuration)); + + /* Override the default values with anything passed in as parameter */ + if (ircc_cfg != 0) + tmpconf.cfg_base = ircc_cfg; + if (ircc_fir != 0) + tmpconf.fir_io = ircc_fir; + if (ircc_sir != 0) + tmpconf.sir_io = ircc_sir; + if (ircc_dma != 0xff) + tmpconf.fir_dma = ircc_dma; + if (ircc_irq != 0xff) + tmpconf.fir_irq = ircc_irq; + + IRDA_MESSAGE("Detected unconfigured %s SMSC IrDA chip, pre-configuring device.\n", conf->name); + if (conf->preconfigure) + ret = conf->preconfigure(dev, &tmpconf); + else + ret = -ENODEV; + } + } + dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev); + } + + return ret; +} +#endif // CONFIG_PCI + /************************************************ * * Transceivers specific functions diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c index 75b35ad..66e74f7 100644 --- a/drivers/net/netconsole.c +++ b/drivers/net/netconsole.c @@ -87,6 +87,7 @@ static void write_msg(struct console *con, const char *msg, unsigned int len) } static struct console netconsole = { + .name = "netcon", .flags = CON_ENABLED | CON_PRINTBUFFER, .write = write_msg }; diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 0b53580..73e271e 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -497,21 +497,20 @@ static void tg3_write_mem(struct tg3 *tp, u32 off, u32 val) unsigned long flags; spin_lock_irqsave(&tp->indirect_lock, flags); - pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off); - pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val); + if (tp->tg3_flags & TG3_FLAG_SRAM_USE_CONFIG) { + pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off); + pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val); - /* Always leave this as zero. */ - pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0); - spin_unlock_irqrestore(&tp->indirect_lock, flags); -} + /* Always leave this as zero. */ + pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0); + } else { + tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, off); + tw32_f(TG3PCI_MEM_WIN_DATA, val); -static void tg3_write_mem_fast(struct tg3 *tp, u32 off, u32 val) -{ - /* If no workaround is needed, write to mem space directly */ - if (tp->write32 != tg3_write_indirect_reg32) - tw32(NIC_SRAM_WIN_BASE + off, val); - else - tg3_write_mem(tp, off, val); + /* Always leave this as zero. */ + tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, 0); + } + spin_unlock_irqrestore(&tp->indirect_lock, flags); } static void tg3_read_mem(struct tg3 *tp, u32 off, u32 *val) @@ -519,11 +518,19 @@ static void tg3_read_mem(struct tg3 *tp, u32 off, u32 *val) unsigned long flags; spin_lock_irqsave(&tp->indirect_lock, flags); - pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off); - pci_read_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val); + if (tp->tg3_flags & TG3_FLAG_SRAM_USE_CONFIG) { + pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off); + pci_read_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val); - /* Always leave this as zero. */ - pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0); + /* Always leave this as zero. */ + pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0); + } else { + tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, off); + *val = tr32(TG3PCI_MEM_WIN_DATA); + + /* Always leave this as zero. */ + tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, 0); + } spin_unlock_irqrestore(&tp->indirect_lock, flags); } @@ -1367,12 +1374,12 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state) } } + tg3_write_sig_post_reset(tp, RESET_KIND_SHUTDOWN); + /* Finally, set the new power state. */ pci_write_config_word(tp->pdev, pm + PCI_PM_CTRL, power_control); udelay(100); /* Delay after power state change */ - tg3_write_sig_post_reset(tp, RESET_KIND_SHUTDOWN); - return 0; } @@ -5828,10 +5835,14 @@ static int tg3_reset_hw(struct tg3 *tp) GRC_MODE_NO_TX_PHDR_CSUM | GRC_MODE_NO_RX_PHDR_CSUM); tp->grc_mode |= GRC_MODE_HOST_SENDBDS; - if (tp->tg3_flags & TG3_FLAG_NO_TX_PSEUDO_CSUM) - tp->grc_mode |= GRC_MODE_NO_TX_PHDR_CSUM; - if (tp->tg3_flags & TG3_FLAG_NO_RX_PSEUDO_CSUM) - tp->grc_mode |= GRC_MODE_NO_RX_PHDR_CSUM; + + /* Pseudo-header checksum is done by hardware logic and not + * the offload processers, so make the chip do the pseudo- + * header checksums on receive. For transmit it is more + * convenient to do the pseudo-header checksum in software + * as Linux does that on transmit for us in all cases. + */ + tp->grc_mode |= GRC_MODE_NO_TX_PHDR_CSUM; tw32(GRC_MODE, tp->grc_mode | @@ -6535,11 +6546,11 @@ static void tg3_timer(unsigned long __opaque) if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) { u32 val; - tg3_write_mem_fast(tp, NIC_SRAM_FW_CMD_MBOX, - FWCMD_NICDRV_ALIVE2); - tg3_write_mem_fast(tp, NIC_SRAM_FW_CMD_LEN_MBOX, 4); + tg3_write_mem(tp, NIC_SRAM_FW_CMD_MBOX, + FWCMD_NICDRV_ALIVE2); + tg3_write_mem(tp, NIC_SRAM_FW_CMD_LEN_MBOX, 4); /* 5 seconds timeout */ - tg3_write_mem_fast(tp, NIC_SRAM_FW_CMD_DATA_MBOX, 5); + tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX, 5); val = tr32(GRC_RX_CPU_EVENT); val |= (1 << 14); tw32(GRC_RX_CPU_EVENT, val); @@ -8034,9 +8045,13 @@ static int tg3_test_nvram(struct tg3 *tp) for (i = 0; i < size; i++) csum8 += buf8[i]; - if (csum8 == 0) - return 0; - return -EIO; + if (csum8 == 0) { + err = 0; + goto out; + } + + err = -EIO; + goto out; } /* Bootstrap checksum at offset 0x10 */ @@ -9531,8 +9546,11 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp) tp->led_ctrl = LED_CTRL_MODE_PHY_1; /* Do not even try poking around in here on Sun parts. */ - if (tp->tg3_flags2 & TG3_FLG2_SUN_570X) + if (tp->tg3_flags2 & TG3_FLG2_SUN_570X) { + /* All SUN chips are built-in LOMs. */ + tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT; return; + } tg3_read_mem(tp, NIC_SRAM_DATA_SIG, &val); if (val == NIC_SRAM_DATA_SIG_MAGIC) { @@ -9630,9 +9648,7 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp) tp->pdev->subsystem_vendor == PCI_VENDOR_ID_DELL) tp->led_ctrl = LED_CTRL_MODE_PHY_2; - if ((GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700) && - (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701) && - (nic_cfg & NIC_SRAM_DATA_CFG_EEPROM_WP)) + if (nic_cfg & NIC_SRAM_DATA_CFG_EEPROM_WP) tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT; if (nic_cfg & NIC_SRAM_DATA_CFG_ASF_ENABLE) { @@ -10257,6 +10273,13 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) pci_write_config_word(tp->pdev, PCI_COMMAND, pci_cmd); } + if (tp->write32 == tg3_write_indirect_reg32 || + ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) && + (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701)) || + (tp->tg3_flags2 & TG3_FLG2_SUN_570X)) + tp->tg3_flags |= TG3_FLAG_SRAM_USE_CONFIG; + /* Get eeprom hw config before calling tg3_set_power_state(). * In particular, the TG3_FLAG_EEPROM_WRITE_PROT flag must be * determined before calling tg3_set_power_state() so that @@ -10299,15 +10322,6 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) if (tp->pci_chip_rev_id == CHIPREV_ID_5700_B0) tp->tg3_flags |= TG3_FLAG_BROKEN_CHECKSUMS; - /* Pseudo-header checksum is done by hardware logic and not - * the offload processers, so make the chip do the pseudo- - * header checksums on receive. For transmit it is more - * convenient to do the pseudo-header checksum in software - * as Linux does that on transmit for us in all cases. - */ - tp->tg3_flags |= TG3_FLAG_NO_TX_PSEUDO_CSUM; - tp->tg3_flags &= ~TG3_FLAG_NO_RX_PSEUDO_CSUM; - /* Derive initial jumbo mode from MTU assigned in * ether_setup() via the alloc_etherdev() call */ diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index c43cc32..8c8b987 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -2171,8 +2171,7 @@ struct tg3 { #define TG3_FLAG_PCIX_MODE 0x00020000 #define TG3_FLAG_PCI_HIGH_SPEED 0x00040000 #define TG3_FLAG_PCI_32BIT 0x00080000 -#define TG3_FLAG_NO_TX_PSEUDO_CSUM 0x00100000 -#define TG3_FLAG_NO_RX_PSEUDO_CSUM 0x00200000 +#define TG3_FLAG_SRAM_USE_CONFIG 0x00100000 #define TG3_FLAG_SERDES_WOL_CAP 0x00400000 #define TG3_FLAG_JUMBO_RING_ENABLE 0x00800000 #define TG3_FLAG_10_100_ONLY 0x01000000 diff --git a/drivers/parport/parport_serial.c b/drivers/parport/parport_serial.c index d121644..98b83a8 100644 --- a/drivers/parport/parport_serial.c +++ b/drivers/parport/parport_serial.c @@ -100,8 +100,6 @@ static struct pci_device_id parport_serial_pci_tbl[] = { PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9xx5_combo }, { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9835, PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9xx5_combo }, - { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9835, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9xx5_combo }, { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9845, PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9xx5_combo }, { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9855, diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 929dd80..65d090d 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -147,6 +147,16 @@ config RTC_DRV_SA1100 To compile this driver as a module, choose M here: the module will be called rtc-sa1100. +config RTC_DRV_VR41XX + tristate "NEC VR41XX" + depends on RTC_CLASS && CPU_VR41XX + help + If you say Y here you will get access to the real time clock + built into your NEC VR41XX CPU. + + To compile this driver as a module, choose M here: the + module will be called rtc-vr41xx. + config RTC_DRV_TEST tristate "Test driver/device" depends on RTC_CLASS diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 8d4c7fe..a9ca0f1 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -19,3 +19,4 @@ obj-$(CONFIG_RTC_DRV_RS5C372) += rtc-rs5c372.o obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.o obj-$(CONFIG_RTC_DRV_EP93XX) += rtc-ep93xx.o obj-$(CONFIG_RTC_DRV_SA1100) += rtc-sa1100.o +obj-$(CONFIG_RTC_DRV_VR41XX) += rtc-vr41xx.o diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c index 8533936..413c7d5 100644 --- a/drivers/rtc/class.c +++ b/drivers/rtc/class.c @@ -96,6 +96,8 @@ exit_idr: idr_remove(&rtc_idr, id); exit: + dev_err(dev, "rtc core: unable to register %s, err = %d\n", + name, err); return ERR_PTR(err); } EXPORT_SYMBOL_GPL(rtc_device_register); diff --git a/drivers/rtc/rtc-ds1672.c b/drivers/rtc/rtc-ds1672.c index 358695a..9be81fd 100644 --- a/drivers/rtc/rtc-ds1672.c +++ b/drivers/rtc/rtc-ds1672.c @@ -1,6 +1,8 @@ /* * An rtc/i2c driver for the Dallas DS1672 - * Copyright 2005 Alessandro Zummo + * Copyright 2005-06 Tower Technologies + * + * Author: Alessandro Zummo <a.zummo@towertech.it> * * 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 @@ -11,7 +13,7 @@ #include <linux/i2c.h> #include <linux/rtc.h> -#define DRV_VERSION "0.2" +#define DRV_VERSION "0.3" /* Addresses to scan: none. This chip cannot be detected. */ static unsigned short normal_i2c[] = { I2C_CLIENT_END }; @@ -25,6 +27,7 @@ I2C_CLIENT_INSMOD; #define DS1672_REG_CONTROL 4 #define DS1672_REG_TRICKLE 5 +#define DS1672_REG_CONTROL_EOSC 0x80 /* Prototypes */ static int ds1672_probe(struct i2c_adapter *adapter, int address, int kind); @@ -53,8 +56,7 @@ static int ds1672_get_datetime(struct i2c_client *client, struct rtc_time *tm) dev_dbg(&client->dev, "%s: raw read data - counters=%02x,%02x,%02x,%02x\n" - __FUNCTION__, - buf[0], buf[1], buf[2], buf[3]); + __FUNCTION__, buf[0], buf[1], buf[2], buf[3]); time = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0]; @@ -62,8 +64,7 @@ static int ds1672_get_datetime(struct i2c_client *client, struct rtc_time *tm) dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, " "mday=%d, mon=%d, year=%d, wday=%d\n", - __FUNCTION__, - tm->tm_sec, tm->tm_min, tm->tm_hour, + __FUNCTION__, tm->tm_sec, tm->tm_min, tm->tm_hour, tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); return 0; @@ -72,16 +73,17 @@ static int ds1672_get_datetime(struct i2c_client *client, struct rtc_time *tm) static int ds1672_set_mmss(struct i2c_client *client, unsigned long secs) { int xfer; - unsigned char buf[5]; + unsigned char buf[6]; buf[0] = DS1672_REG_CNT_BASE; buf[1] = secs & 0x000000FF; buf[2] = (secs & 0x0000FF00) >> 8; buf[3] = (secs & 0x00FF0000) >> 16; buf[4] = (secs & 0xFF000000) >> 24; + buf[5] = 0; /* set control reg to enable counting */ - xfer = i2c_master_send(client, buf, 5); - if (xfer != 5) { + xfer = i2c_master_send(client, buf, 6); + if (xfer != 6) { dev_err(&client->dev, "%s: send: %d\n", __FUNCTION__, xfer); return -EIO; } @@ -120,6 +122,40 @@ static int ds1672_rtc_set_mmss(struct device *dev, unsigned long secs) return ds1672_set_mmss(to_i2c_client(dev), secs); } +static int ds1672_get_control(struct i2c_client *client, u8 *status) +{ + unsigned char addr = DS1672_REG_CONTROL; + + struct i2c_msg msgs[] = { + { client->addr, 0, 1, &addr }, /* setup read ptr */ + { client->addr, I2C_M_RD, 1, status }, /* read control */ + }; + + /* read control register */ + if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) { + dev_err(&client->dev, "%s: read error\n", __FUNCTION__); + return -EIO; + } + + return 0; +} + +/* following are the sysfs callback functions */ +static ssize_t show_control(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 control; + int err; + + err = ds1672_get_control(client, &control); + if (err) + return err; + + return sprintf(buf, "%s\n", (control & DS1672_REG_CONTROL_EOSC) + ? "disabled" : "enabled"); +} +static DEVICE_ATTR(control, S_IRUGO, show_control, NULL); + static struct rtc_class_ops ds1672_rtc_ops = { .read_time = ds1672_rtc_read_time, .set_time = ds1672_rtc_set_time, @@ -128,7 +164,6 @@ static struct rtc_class_ops ds1672_rtc_ops = { static int ds1672_attach(struct i2c_adapter *adapter) { - dev_dbg(&adapter->dev, "%s\n", __FUNCTION__); return i2c_probe(adapter, &addr_data, ds1672_probe); } @@ -137,8 +172,6 @@ static int ds1672_detach(struct i2c_client *client) int err; struct rtc_device *rtc = i2c_get_clientdata(client); - dev_dbg(&client->dev, "%s\n", __FUNCTION__); - if (rtc) rtc_device_unregister(rtc); @@ -162,6 +195,7 @@ static struct i2c_driver ds1672_driver = { static int ds1672_probe(struct i2c_adapter *adapter, int address, int kind) { int err = 0; + u8 control; struct i2c_client *client; struct rtc_device *rtc; @@ -195,13 +229,23 @@ static int ds1672_probe(struct i2c_adapter *adapter, int address, int kind) if (IS_ERR(rtc)) { err = PTR_ERR(rtc); - dev_err(&client->dev, - "unable to register the class device\n"); goto exit_detach; } i2c_set_clientdata(client, rtc); + /* read control register */ + err = ds1672_get_control(client, &control); + if (err) + goto exit_detach; + + if (control & DS1672_REG_CONTROL_EOSC) + dev_warn(&client->dev, "Oscillator not enabled. " + "Set time to enable.\n"); + + /* Register sysfs hooks */ + device_create_file(&client->dev, &dev_attr_control); + return 0; exit_detach: diff --git a/drivers/rtc/rtc-ep93xx.c b/drivers/rtc/rtc-ep93xx.c index 0dd80ea..e1a1169 100644 --- a/drivers/rtc/rtc-ep93xx.c +++ b/drivers/rtc/rtc-ep93xx.c @@ -67,7 +67,6 @@ static int ep93xx_rtc_proc(struct device *dev, struct seq_file *seq) ep93xx_get_swcomp(dev, &preload, &delete); - seq_printf(seq, "24hr\t\t: yes\n"); seq_printf(seq, "preload\t\t: %d\n", preload); seq_printf(seq, "delete\t\t: %d\n", delete); @@ -110,7 +109,6 @@ static int __devinit ep93xx_rtc_probe(struct platform_device *dev) &dev->dev, &ep93xx_rtc_ops, THIS_MODULE); if (IS_ERR(rtc)) { - dev_err(&dev->dev, "unable to register\n"); return PTR_ERR(rtc); } diff --git a/drivers/rtc/rtc-m48t86.c b/drivers/rtc/rtc-m48t86.c index db445c8..f6e7ee0 100644 --- a/drivers/rtc/rtc-m48t86.c +++ b/drivers/rtc/rtc-m48t86.c @@ -23,7 +23,7 @@ #define M48T86_REG_SECALRM 0x01 #define M48T86_REG_MIN 0x02 #define M48T86_REG_MINALRM 0x03 -#define M48T86_REG_HOUR 0x04 +#define M48T86_REG_HOUR 0x04 #define M48T86_REG_HOURALRM 0x05 #define M48T86_REG_DOW 0x06 /* 1 = sunday */ #define M48T86_REG_DOM 0x07 @@ -127,9 +127,6 @@ static int m48t86_rtc_proc(struct device *dev, struct seq_file *seq) reg = ops->readb(M48T86_REG_B); - seq_printf(seq, "24hr\t\t: %s\n", - (reg & M48T86_REG_B_H24) ? "yes" : "no"); - seq_printf(seq, "mode\t\t: %s\n", (reg & M48T86_REG_B_DM) ? "binary" : "bcd"); @@ -154,10 +151,8 @@ static int __devinit m48t86_rtc_probe(struct platform_device *dev) struct rtc_device *rtc = rtc_device_register("m48t86", &dev->dev, &m48t86_rtc_ops, THIS_MODULE); - if (IS_ERR(rtc)) { - dev_err(&dev->dev, "unable to register\n"); + if (IS_ERR(rtc)) return PTR_ERR(rtc); - } platform_set_drvdata(dev, rtc); diff --git a/drivers/rtc/rtc-pcf8563.c b/drivers/rtc/rtc-pcf8563.c index d857d45..ba9a583 100644 --- a/drivers/rtc/rtc-pcf8563.c +++ b/drivers/rtc/rtc-pcf8563.c @@ -227,14 +227,7 @@ static int pcf8563_rtc_set_time(struct device *dev, struct rtc_time *tm) return pcf8563_set_datetime(to_i2c_client(dev), tm); } -static int pcf8563_rtc_proc(struct device *dev, struct seq_file *seq) -{ - seq_printf(seq, "24hr\t\t: yes\n"); - return 0; -} - static struct rtc_class_ops pcf8563_rtc_ops = { - .proc = pcf8563_rtc_proc, .read_time = pcf8563_rtc_read_time, .set_time = pcf8563_rtc_set_time, }; @@ -297,8 +290,6 @@ static int pcf8563_probe(struct i2c_adapter *adapter, int address, int kind) if (IS_ERR(rtc)) { err = PTR_ERR(rtc); - dev_err(&client->dev, - "unable to register the class device\n"); goto exit_detach; } @@ -321,8 +312,6 @@ static int pcf8563_detach(struct i2c_client *client) int err; struct rtc_device *rtc = i2c_get_clientdata(client); - dev_dbg(&client->dev, "%s\n", __FUNCTION__); - if (rtc) rtc_device_unregister(rtc); diff --git a/drivers/rtc/rtc-proc.c b/drivers/rtc/rtc-proc.c index 90b8a97..cef5f5a 100644 --- a/drivers/rtc/rtc-proc.c +++ b/drivers/rtc/rtc-proc.c @@ -71,6 +71,8 @@ static int rtc_proc_show(struct seq_file *seq, void *offset) alrm.pending ? "yes" : "no"); } + seq_printf(seq, "24hr\t\t: yes\n"); + if (ops->proc) ops->proc(class_dev->dev, seq); diff --git a/drivers/rtc/rtc-rs5c372.c b/drivers/rtc/rtc-rs5c372.c index 396c868..7553d79 100644 --- a/drivers/rtc/rtc-rs5c372.c +++ b/drivers/rtc/rtc-rs5c372.c @@ -151,9 +151,8 @@ static int rs5c372_rtc_proc(struct device *dev, struct seq_file *seq) { int err, osc, trim; - seq_printf(seq, "24hr\t\t: yes\n"); - - if ((err = rs5c372_get_trim(to_i2c_client(dev), &osc, &trim)) == 0) { + err = rs5c372_get_trim(to_i2c_client(dev), &osc, &trim); + if (err == 0) { seq_printf(seq, "%d.%03d KHz\n", osc / 1000, osc % 1000); seq_printf(seq, "trim\t: %d\n", trim); } @@ -170,30 +169,31 @@ static struct rtc_class_ops rs5c372_rtc_ops = { static ssize_t rs5c372_sysfs_show_trim(struct device *dev, struct device_attribute *attr, char *buf) { - int trim; + int err, trim; - if (rs5c372_get_trim(to_i2c_client(dev), NULL, &trim) == 0) - return sprintf(buf, "0x%2x\n", trim); + err = rs5c372_get_trim(to_i2c_client(dev), NULL, &trim); + if (err) + return err; - return 0; + return sprintf(buf, "0x%2x\n", trim); } static DEVICE_ATTR(trim, S_IRUGO, rs5c372_sysfs_show_trim, NULL); static ssize_t rs5c372_sysfs_show_osc(struct device *dev, struct device_attribute *attr, char *buf) { - int osc; + int err, osc; - if (rs5c372_get_trim(to_i2c_client(dev), &osc, NULL) == 0) - return sprintf(buf, "%d.%03d KHz\n", osc / 1000, osc % 1000); + err = rs5c372_get_trim(to_i2c_client(dev), &osc, NULL); + if (err) + return err; - return 0; + return sprintf(buf, "%d.%03d KHz\n", osc / 1000, osc % 1000); } static DEVICE_ATTR(osc, S_IRUGO, rs5c372_sysfs_show_osc, NULL); static int rs5c372_attach(struct i2c_adapter *adapter) { - dev_dbg(&adapter->dev, "%s\n", __FUNCTION__); return i2c_probe(adapter, &addr_data, rs5c372_probe); } @@ -233,8 +233,6 @@ static int rs5c372_probe(struct i2c_adapter *adapter, int address, int kind) if (IS_ERR(rtc)) { err = PTR_ERR(rtc); - dev_err(&client->dev, - "unable to register the class device\n"); goto exit_detach; } @@ -260,8 +258,6 @@ static int rs5c372_detach(struct i2c_client *client) int err; struct rtc_device *rtc = i2c_get_clientdata(client); - dev_dbg(&client->dev, "%s\n", __FUNCTION__); - if (rtc) rtc_device_unregister(rtc); diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c index 83b2bb4..a23ec54 100644 --- a/drivers/rtc/rtc-sa1100.c +++ b/drivers/rtc/rtc-sa1100.c @@ -160,19 +160,19 @@ static int sa1100_rtc_open(struct device *dev) ret = request_irq(IRQ_RTC1Hz, sa1100_rtc_interrupt, SA_INTERRUPT, "rtc 1Hz", dev); if (ret) { - printk(KERN_ERR "rtc: IRQ%d already in use.\n", IRQ_RTC1Hz); + dev_err(dev, "IRQ %d already in use.\n", IRQ_RTC1Hz); goto fail_ui; } ret = request_irq(IRQ_RTCAlrm, sa1100_rtc_interrupt, SA_INTERRUPT, "rtc Alrm", dev); if (ret) { - printk(KERN_ERR "rtc: IRQ%d already in use.\n", IRQ_RTCAlrm); + dev_err(dev, "IRQ %d already in use.\n", IRQ_RTCAlrm); goto fail_ai; } ret = request_irq(IRQ_OST1, timer1_interrupt, SA_INTERRUPT, "rtc timer", dev); if (ret) { - printk(KERN_ERR "rtc: IRQ%d already in use.\n", IRQ_OST1); + dev_err(dev, "IRQ %d already in use.\n", IRQ_OST1); goto fail_pi; } return 0; @@ -332,7 +332,7 @@ static int sa1100_rtc_probe(struct platform_device *pdev) */ if (RTTR == 0) { RTTR = RTC_DEF_DIVIDER + (RTC_DEF_TRIM << 16); - printk(KERN_WARNING "rtc: warning: initializing default clock divider/trim value\n"); + dev_warn(&pdev->dev, "warning: initializing default clock divider/trim value\n"); /* The current RTC value probably doesn't make sense either */ RCNR = 0; } @@ -340,15 +340,11 @@ static int sa1100_rtc_probe(struct platform_device *pdev) rtc = rtc_device_register(pdev->name, &pdev->dev, &sa1100_rtc_ops, THIS_MODULE); - if (IS_ERR(rtc)) { - dev_err(&pdev->dev, "Unable to register the RTC device\n"); + if (IS_ERR(rtc)) return PTR_ERR(rtc); - } platform_set_drvdata(pdev, rtc); - dev_info(&pdev->dev, "SA11xx/PXA2xx RTC Registered\n"); - return 0; } diff --git a/drivers/rtc/rtc-test.c b/drivers/rtc/rtc-test.c index 43d1074..e1f7e8e 100644 --- a/drivers/rtc/rtc-test.c +++ b/drivers/rtc/rtc-test.c @@ -49,7 +49,6 @@ static int test_rtc_proc(struct device *dev, struct seq_file *seq) { struct platform_device *plat_dev = to_platform_device(dev); - seq_printf(seq, "24hr\t\t: yes\n"); seq_printf(seq, "test\t\t: yes\n"); seq_printf(seq, "id\t\t: %d\n", plat_dev->id); @@ -120,8 +119,6 @@ static int test_probe(struct platform_device *plat_dev) &test_rtc_ops, THIS_MODULE); if (IS_ERR(rtc)) { err = PTR_ERR(rtc); - dev_err(&plat_dev->dev, - "unable to register the class device\n"); return err; } device_create_file(&plat_dev->dev, &dev_attr_irq); diff --git a/drivers/char/vr41xx_rtc.c b/drivers/rtc/rtc-vr41xx.c index b109d9a..4d49fd5 100644 --- a/drivers/char/vr41xx_rtc.c +++ b/drivers/rtc/rtc-vr41xx.c @@ -1,7 +1,7 @@ /* - * Driver for NEC VR4100 series Real Time Clock unit. + * Driver for NEC VR4100 series Real Time Clock unit. * - * Copyright (C) 2003-2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * Copyright (C) 2003-2006 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -17,23 +17,18 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include <linux/platform_device.h> #include <linux/fs.h> #include <linux/init.h> #include <linux/ioport.h> #include <linux/irq.h> -#include <linux/mc146818rtc.h> -#include <linux/miscdevice.h> #include <linux/module.h> -#include <linux/poll.h> +#include <linux/platform_device.h> #include <linux/rtc.h> #include <linux/spinlock.h> #include <linux/types.h> -#include <linux/wait.h> #include <asm/div64.h> #include <asm/io.h> -#include <asm/time.h> #include <asm/uaccess.h> #include <asm/vr41xx/vr41xx.h> @@ -99,27 +94,11 @@ static void __iomem *rtc2_base; static unsigned long epoch = 1970; /* Jan 1 1970 00:00:00 */ -static spinlock_t rtc_task_lock; -static wait_queue_head_t rtc_wait; -static unsigned long rtc_irq_data; -static struct fasync_struct *rtc_async_queue; -static rtc_task_t *rtc_callback; +static spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED; static char rtc_name[] = "RTC"; static unsigned long periodic_frequency; static unsigned long periodic_count; -typedef enum { - RTC_RELEASE, - RTC_OPEN, -} rtc_status_t; - -static rtc_status_t rtc_status; - -typedef enum { - FUNCTION_RTC_IOCTL, - FUNCTION_RTC_CONTROL, -} rtc_callfrom_t; - struct resource rtc_resource[2] = { { .name = rtc_name, .flags = IORESOURCE_MEM, }, @@ -129,7 +108,9 @@ struct resource rtc_resource[2] = { static inline unsigned long read_elapsed_second(void) { + unsigned long first_low, first_mid, first_high; + unsigned long second_low, second_mid, second_high; do { @@ -156,50 +137,36 @@ static inline void write_elapsed_second(unsigned long sec) spin_unlock_irq(&rtc_lock); } -static void set_alarm(struct rtc_time *time) +static void vr41xx_rtc_release(struct device *dev) { - unsigned long alarm_sec; - - alarm_sec = mktime(time->tm_year + 1900, time->tm_mon + 1, time->tm_mday, - time->tm_hour, time->tm_min, time->tm_sec); - - spin_lock_irq(&rtc_lock); - - rtc1_write(ECMPLREG, (uint16_t)(alarm_sec << 15)); - rtc1_write(ECMPMREG, (uint16_t)(alarm_sec >> 1)); - rtc1_write(ECMPHREG, (uint16_t)(alarm_sec >> 17)); - - spin_unlock_irq(&rtc_lock); -} - -static void read_alarm(struct rtc_time *time) -{ - unsigned long low, mid, high; spin_lock_irq(&rtc_lock); - low = rtc1_read(ECMPLREG); - mid = rtc1_read(ECMPMREG); - high = rtc1_read(ECMPHREG); + rtc1_write(ECMPLREG, 0); + rtc1_write(ECMPMREG, 0); + rtc1_write(ECMPHREG, 0); + rtc1_write(RTCL1LREG, 0); + rtc1_write(RTCL1HREG, 0); spin_unlock_irq(&rtc_lock); - to_tm((high << 17) | (mid << 1) | (low >> 15), time); - time->tm_year -= 1900; + disable_irq(ELAPSEDTIME_IRQ); + disable_irq(RTCLONG1_IRQ); } -static void read_time(struct rtc_time *time) +static int vr41xx_rtc_read_time(struct device *dev, struct rtc_time *time) { unsigned long epoch_sec, elapsed_sec; epoch_sec = mktime(epoch, 1, 1, 0, 0, 0); elapsed_sec = read_elapsed_second(); - to_tm(epoch_sec + elapsed_sec, time); - time->tm_year -= 1900; + rtc_time_to_tm(epoch_sec + elapsed_sec, time); + + return 0; } -static void set_time(struct rtc_time *time) +static int vr41xx_rtc_set_time(struct device *dev, struct rtc_time *time) { unsigned long epoch_sec, current_sec; @@ -208,73 +175,49 @@ static void set_time(struct rtc_time *time) time->tm_hour, time->tm_min, time->tm_sec); write_elapsed_second(current_sec - epoch_sec); + + return 0; } -static ssize_t rtc_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) +static int vr41xx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *wkalrm) { - DECLARE_WAITQUEUE(wait, current); - unsigned long irq_data; - int retval = 0; - - if (count != sizeof(unsigned int) && count != sizeof(unsigned long)) - return -EINVAL; - - add_wait_queue(&rtc_wait, &wait); - - do { - __set_current_state(TASK_INTERRUPTIBLE); + unsigned long low, mid, high; + struct rtc_time *time = &wkalrm->time; - spin_lock_irq(&rtc_lock); - irq_data = rtc_irq_data; - rtc_irq_data = 0; - spin_unlock_irq(&rtc_lock); + spin_lock_irq(&rtc_lock); - if (irq_data != 0) - break; + low = rtc1_read(ECMPLREG); + mid = rtc1_read(ECMPMREG); + high = rtc1_read(ECMPHREG); - if (file->f_flags & O_NONBLOCK) { - retval = -EAGAIN; - break; - } + spin_unlock_irq(&rtc_lock); - if (signal_pending(current)) { - retval = -ERESTARTSYS; - break; - } - } while (1); + rtc_time_to_tm((high << 17) | (mid << 1) | (low >> 15), time); - if (retval == 0) { - if (count == sizeof(unsigned int)) { - retval = put_user(irq_data, (unsigned int __user *)buf); - if (retval == 0) - retval = sizeof(unsigned int); - } else { - retval = put_user(irq_data, (unsigned long __user *)buf); - if (retval == 0) - retval = sizeof(unsigned long); - } + return 0; +} - } +static int vr41xx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *wkalrm) +{ + unsigned long alarm_sec; + struct rtc_time *time = &wkalrm->time; - __set_current_state(TASK_RUNNING); - remove_wait_queue(&rtc_wait, &wait); + alarm_sec = mktime(time->tm_year + 1900, time->tm_mon + 1, time->tm_mday, + time->tm_hour, time->tm_min, time->tm_sec); - return retval; -} + spin_lock_irq(&rtc_lock); -static unsigned int rtc_poll(struct file *file, struct poll_table_struct *table) -{ - poll_wait(file, &rtc_wait, table); + rtc1_write(ECMPLREG, (uint16_t)(alarm_sec << 15)); + rtc1_write(ECMPMREG, (uint16_t)(alarm_sec >> 1)); + rtc1_write(ECMPHREG, (uint16_t)(alarm_sec >> 17)); - if (rtc_irq_data != 0) - return POLLIN | POLLRDNORM; + spin_unlock_irq(&rtc_lock); return 0; } -static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, rtc_callfrom_t from) +static int vr41xx_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) { - struct rtc_time time; unsigned long count; switch (cmd) { @@ -290,33 +233,6 @@ static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, rtc_callfrom_t from case RTC_PIE_OFF: disable_irq(RTCLONG1_IRQ); break; - case RTC_ALM_SET: - if (copy_from_user(&time, (struct rtc_time __user *)arg, - sizeof(struct rtc_time))) - return -EFAULT; - - set_alarm(&time); - break; - case RTC_ALM_READ: - memset(&time, 0, sizeof(struct rtc_time)); - read_alarm(&time); - break; - case RTC_RD_TIME: - memset(&time, 0, sizeof(struct rtc_time)); - read_time(&time); - if (copy_to_user((void __user *)arg, &time, sizeof(struct rtc_time))) - return -EFAULT; - break; - case RTC_SET_TIME: - if (capable(CAP_SYS_TIME) == 0) - return -EACCES; - - if (copy_from_user(&time, (struct rtc_time __user *)arg, - sizeof(struct rtc_time))) - return -EFAULT; - - set_time(&time); - break; case RTC_IRQP_READ: return put_user(periodic_frequency, (unsigned long __user *)arg); break; @@ -324,8 +240,7 @@ static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, rtc_callfrom_t from if (arg > MAX_PERIODIC_RATE) return -EINVAL; - if (from == FUNCTION_RTC_IOCTL && arg > MAX_USER_PERIODIC_RATE && - capable(CAP_SYS_RESOURCE) == 0) + if (arg > MAX_USER_PERIODIC_RATE && capable(CAP_SYS_RESOURCE) == 0) return -EACCES; periodic_frequency = arg; @@ -361,205 +276,46 @@ static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, rtc_callfrom_t from return 0; } -static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, - unsigned long arg) -{ - return rtc_do_ioctl(cmd, arg, FUNCTION_RTC_IOCTL); -} - -static int rtc_open(struct inode *inode, struct file *file) -{ - spin_lock_irq(&rtc_lock); - - if (rtc_status == RTC_OPEN) { - spin_unlock_irq(&rtc_lock); - return -EBUSY; - } - - rtc_status = RTC_OPEN; - rtc_irq_data = 0; - - spin_unlock_irq(&rtc_lock); - - return 0; -} - -static int rtc_release(struct inode *inode, struct file *file) -{ - if (file->f_flags & FASYNC) - (void)fasync_helper(-1, file, 0, &rtc_async_queue); - - spin_lock_irq(&rtc_lock); - - rtc1_write(ECMPLREG, 0); - rtc1_write(ECMPMREG, 0); - rtc1_write(ECMPHREG, 0); - rtc1_write(RTCL1LREG, 0); - rtc1_write(RTCL1HREG, 0); - - rtc_status = RTC_RELEASE; - - spin_unlock_irq(&rtc_lock); - - disable_irq(ELAPSEDTIME_IRQ); - disable_irq(RTCLONG1_IRQ); - - return 0; -} - -static int rtc_fasync(int fd, struct file *file, int on) -{ - return fasync_helper(fd, file, on, &rtc_async_queue); -} - -static struct file_operations rtc_fops = { - .owner = THIS_MODULE, - .llseek = no_llseek, - .read = rtc_read, - .poll = rtc_poll, - .ioctl = rtc_ioctl, - .open = rtc_open, - .release = rtc_release, - .fasync = rtc_fasync, -}; - static irqreturn_t elapsedtime_interrupt(int irq, void *dev_id, struct pt_regs *regs) { - spin_lock(&rtc_lock); - rtc2_write(RTCINTREG, ELAPSEDTIME_INT); - - rtc_irq_data += 0x100; - rtc_irq_data &= ~0xff; - rtc_irq_data |= RTC_AF; - spin_unlock(&rtc_lock); + struct platform_device *pdev = (struct platform_device *)dev_id; + struct rtc_device *rtc = platform_get_drvdata(pdev); - spin_lock(&rtc_lock); - if (rtc_callback) - rtc_callback->func(rtc_callback->private_data); - spin_unlock(&rtc_lock); - - wake_up_interruptible(&rtc_wait); + rtc2_write(RTCINTREG, ELAPSEDTIME_INT); - kill_fasync(&rtc_async_queue, SIGIO, POLL_IN); + rtc_update_irq(&rtc->class_dev, 1, RTC_AF); return IRQ_HANDLED; } static irqreturn_t rtclong1_interrupt(int irq, void *dev_id, struct pt_regs *regs) { + struct platform_device *pdev = (struct platform_device *)dev_id; + struct rtc_device *rtc = platform_get_drvdata(pdev); unsigned long count = periodic_count; - spin_lock(&rtc_lock); rtc2_write(RTCINTREG, RTCLONG1_INT); rtc1_write(RTCL1LREG, count); rtc1_write(RTCL1HREG, count >> 16); - rtc_irq_data += 0x100; - rtc_irq_data &= ~0xff; - rtc_irq_data |= RTC_PF; - spin_unlock(&rtc_lock); - - spin_lock(&rtc_task_lock); - if (rtc_callback) - rtc_callback->func(rtc_callback->private_data); - spin_unlock(&rtc_task_lock); - - wake_up_interruptible(&rtc_wait); - - kill_fasync(&rtc_async_queue, SIGIO, POLL_IN); + rtc_update_irq(&rtc->class_dev, 1, RTC_PF); return IRQ_HANDLED; } -int rtc_register(rtc_task_t *task) -{ - if (task == NULL || task->func == NULL) - return -EINVAL; - - spin_lock_irq(&rtc_lock); - if (rtc_status == RTC_OPEN) { - spin_unlock_irq(&rtc_lock); - return -EBUSY; - } - - spin_lock(&rtc_task_lock); - if (rtc_callback != NULL) { - spin_unlock(&rtc_task_lock); - spin_unlock_irq(&rtc_task_lock); - return -EBUSY; - } - - rtc_callback = task; - spin_unlock(&rtc_task_lock); - - rtc_status = RTC_OPEN; - - spin_unlock_irq(&rtc_lock); - - return 0; -} - -EXPORT_SYMBOL_GPL(rtc_register); - -int rtc_unregister(rtc_task_t *task) -{ - spin_lock_irq(&rtc_task_lock); - if (task == NULL || rtc_callback != task) { - spin_unlock_irq(&rtc_task_lock); - return -ENXIO; - } - - spin_lock(&rtc_lock); - - rtc1_write(ECMPLREG, 0); - rtc1_write(ECMPMREG, 0); - rtc1_write(ECMPHREG, 0); - rtc1_write(RTCL1LREG, 0); - rtc1_write(RTCL1HREG, 0); - - rtc_status = RTC_RELEASE; - - spin_unlock(&rtc_lock); - - rtc_callback = NULL; - - spin_unlock_irq(&rtc_task_lock); - - disable_irq(ELAPSEDTIME_IRQ); - disable_irq(RTCLONG1_IRQ); - - return 0; -} - -EXPORT_SYMBOL_GPL(rtc_unregister); - -int rtc_control(rtc_task_t *task, unsigned int cmd, unsigned long arg) -{ - int retval = 0; - - spin_lock_irq(&rtc_task_lock); - - if (rtc_callback != task) - retval = -ENXIO; - else - rtc_do_ioctl(cmd, arg, FUNCTION_RTC_CONTROL); - - spin_unlock_irq(&rtc_task_lock); - - return retval; -} - -EXPORT_SYMBOL_GPL(rtc_control); - -static struct miscdevice rtc_miscdevice = { - .minor = RTC_MINOR, - .name = rtc_name, - .fops = &rtc_fops, +static struct rtc_class_ops vr41xx_rtc_ops = { + .release = vr41xx_rtc_release, + .ioctl = vr41xx_rtc_ioctl, + .read_time = vr41xx_rtc_read_time, + .set_time = vr41xx_rtc_set_time, + .read_alarm = vr41xx_rtc_read_alarm, + .set_alarm = vr41xx_rtc_set_alarm, }; static int __devinit rtc_probe(struct platform_device *pdev) { + struct rtc_device *rtc; unsigned int irq; int retval; @@ -577,13 +333,13 @@ static int __devinit rtc_probe(struct platform_device *pdev) return -EBUSY; } - retval = misc_register(&rtc_miscdevice); - if (retval < 0) { + rtc = rtc_device_register(rtc_name, &pdev->dev, &vr41xx_rtc_ops, THIS_MODULE); + if (IS_ERR(rtc)) { iounmap(rtc1_base); iounmap(rtc2_base); rtc1_base = NULL; rtc2_base = NULL; - return retval; + return PTR_ERR(rtc); } spin_lock_irq(&rtc_lock); @@ -594,24 +350,20 @@ static int __devinit rtc_probe(struct platform_device *pdev) rtc1_write(RTCL1LREG, 0); rtc1_write(RTCL1HREG, 0); - rtc_status = RTC_RELEASE; - rtc_irq_data = 0; - spin_unlock_irq(&rtc_lock); - init_waitqueue_head(&rtc_wait); - irq = ELAPSEDTIME_IRQ; retval = request_irq(irq, elapsedtime_interrupt, SA_INTERRUPT, - "elapsed_time", NULL); + "elapsed_time", pdev); if (retval == 0) { irq = RTCLONG1_IRQ; retval = request_irq(irq, rtclong1_interrupt, SA_INTERRUPT, - "rtclong1", NULL); + "rtclong1", pdev); } if (retval < 0) { printk(KERN_ERR "rtc: IRQ%d is busy\n", irq); + rtc_device_unregister(rtc); if (irq == RTCLONG1_IRQ) free_irq(ELAPSEDTIME_IRQ, NULL); iounmap(rtc1_base); @@ -621,23 +373,25 @@ static int __devinit rtc_probe(struct platform_device *pdev) return retval; } + platform_set_drvdata(pdev, rtc); + disable_irq(ELAPSEDTIME_IRQ); disable_irq(RTCLONG1_IRQ); - spin_lock_init(&rtc_task_lock); - printk(KERN_INFO "rtc: Real Time Clock of NEC VR4100 series\n"); return 0; } -static int __devexit rtc_remove(struct platform_device *dev) +static int __devexit rtc_remove(struct platform_device *pdev) { - int retval; + struct rtc_device *rtc; - retval = misc_deregister(&rtc_miscdevice); - if (retval < 0) - return retval; + rtc = platform_get_drvdata(pdev); + if (rtc != NULL) + rtc_device_unregister(rtc); + + platform_set_drvdata(pdev, NULL); free_irq(ELAPSEDTIME_IRQ, NULL); free_irq(RTCLONG1_IRQ, NULL); @@ -651,7 +405,7 @@ static int __devexit rtc_remove(struct platform_device *dev) static struct platform_device *rtc_platform_device; -static struct platform_driver rtc_device_driver = { +static struct platform_driver rtc_platform_driver = { .probe = rtc_probe, .remove = __devexit_p(rtc_remove), .driver = { @@ -686,7 +440,7 @@ static int __init vr41xx_rtc_init(void) } rtc_platform_device = platform_device_alloc("RTC", -1); - if (!rtc_platform_device) + if (rtc_platform_device == NULL) return -ENOMEM; retval = platform_device_add_resources(rtc_platform_device, @@ -700,7 +454,7 @@ static int __init vr41xx_rtc_init(void) return retval; } - retval = platform_driver_register(&rtc_device_driver); + retval = platform_driver_register(&rtc_platform_driver); if (retval < 0) platform_device_unregister(rtc_platform_device); @@ -709,7 +463,7 @@ static int __init vr41xx_rtc_init(void) static void __exit vr41xx_rtc_exit(void) { - platform_driver_unregister(&rtc_device_driver); + platform_driver_unregister(&rtc_platform_driver); platform_device_unregister(rtc_platform_device); } diff --git a/drivers/rtc/rtc-x1205.c b/drivers/rtc/rtc-x1205.c index 621d17a..788b6d1 100644 --- a/drivers/rtc/rtc-x1205.c +++ b/drivers/rtc/rtc-x1205.c @@ -19,7 +19,7 @@ #include <linux/rtc.h> #include <linux/delay.h> -#define DRV_VERSION "1.0.6" +#define DRV_VERSION "1.0.7" /* Addresses to scan: none. This chip is located at * 0x6f and uses a two bytes register addressing. @@ -451,8 +451,6 @@ static int x1205_rtc_proc(struct device *dev, struct seq_file *seq) { int err, dtrim, atrim; - seq_printf(seq, "24hr\t\t: yes\n"); - if ((err = x1205_get_dtrim(to_i2c_client(dev), &dtrim)) == 0) seq_printf(seq, "digital_trim\t: %d ppm\n", dtrim); @@ -473,30 +471,31 @@ static struct rtc_class_ops x1205_rtc_ops = { static ssize_t x1205_sysfs_show_atrim(struct device *dev, struct device_attribute *attr, char *buf) { - int atrim; + int err, atrim; - if (x1205_get_atrim(to_i2c_client(dev), &atrim) == 0) - return sprintf(buf, "%d.%02d pF\n", - atrim / 1000, atrim % 1000); - return 0; + err = x1205_get_atrim(to_i2c_client(dev), &atrim); + if (err) + return err; + + return sprintf(buf, "%d.%02d pF\n", atrim / 1000, atrim % 1000); } static DEVICE_ATTR(atrim, S_IRUGO, x1205_sysfs_show_atrim, NULL); static ssize_t x1205_sysfs_show_dtrim(struct device *dev, struct device_attribute *attr, char *buf) { - int dtrim; + int err, dtrim; - if (x1205_get_dtrim(to_i2c_client(dev), &dtrim) == 0) - return sprintf(buf, "%d ppm\n", dtrim); + err = x1205_get_dtrim(to_i2c_client(dev), &dtrim); + if (err) + return err; - return 0; + return sprintf(buf, "%d ppm\n", dtrim); } static DEVICE_ATTR(dtrim, S_IRUGO, x1205_sysfs_show_dtrim, NULL); static int x1205_attach(struct i2c_adapter *adapter) { - dev_dbg(&adapter->dev, "%s\n", __FUNCTION__); return i2c_probe(adapter, &addr_data, x1205_probe); } @@ -545,8 +544,6 @@ static int x1205_probe(struct i2c_adapter *adapter, int address, int kind) if (IS_ERR(rtc)) { err = PTR_ERR(rtc); - dev_err(&client->dev, - "unable to register the class device\n"); goto exit_detach; } @@ -585,8 +582,6 @@ static int x1205_detach(struct i2c_client *client) int err; struct rtc_device *rtc = i2c_get_clientdata(client); - dev_dbg(&client->dev, "%s\n", __FUNCTION__); - if (rtc) rtc_device_unregister(rtc); diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 0a9f12c..a3bfebc 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -1257,25 +1257,28 @@ __dasd_start_head(struct dasd_device * device) if (list_empty(&device->ccw_queue)) return; cqr = list_entry(device->ccw_queue.next, struct dasd_ccw_req, list); - /* check FAILFAST */ + if (cqr->status != DASD_CQR_QUEUED) + return; + /* Non-temporary stop condition will trigger fail fast */ if (device->stopped & ~DASD_STOPPED_PENDING && test_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags) && (!dasd_eer_enabled(device))) { cqr->status = DASD_CQR_FAILED; dasd_schedule_bh(device); + return; } - if ((cqr->status == DASD_CQR_QUEUED) && - (!device->stopped)) { - /* try to start the first I/O that can be started */ - rc = device->discipline->start_IO(cqr); - if (rc == 0) - dasd_set_timer(device, cqr->expires); - else if (rc == -EACCES) { - dasd_schedule_bh(device); - } else - /* Hmpf, try again in 1/2 sec */ - dasd_set_timer(device, 50); - } + /* Don't try to start requests if device is stopped */ + if (device->stopped) + return; + + rc = device->discipline->start_IO(cqr); + if (rc == 0) + dasd_set_timer(device, cqr->expires); + else if (rc == -EACCES) { + dasd_schedule_bh(device); + } else + /* Hmpf, try again in 1/2 sec */ + dasd_set_timer(device, 50); } /* @@ -1968,7 +1971,7 @@ int dasd_generic_set_offline (struct ccw_device *cdev) { struct dasd_device *device; - int max_count; + int max_count, open_count; device = dasd_device_from_cdev(cdev); if (IS_ERR(device)) @@ -1985,10 +1988,16 @@ dasd_generic_set_offline (struct ccw_device *cdev) * in the other openers. */ max_count = device->bdev ? 0 : -1; - if (atomic_read(&device->open_count) > max_count) { - printk (KERN_WARNING "Can't offline dasd device with open" - " count = %i.\n", - atomic_read(&device->open_count)); + open_count = (int) atomic_read(&device->open_count); + if (open_count > max_count) { + if (open_count > 0) + printk (KERN_WARNING "Can't offline dasd device with " + "open count = %i.\n", + open_count); + else + printk (KERN_WARNING "%s", + "Can't offline dasd device due to internal " + "use\n"); clear_bit(DASD_FLAG_OFFLINE, &device->flags); dasd_put_device(device); return -EBUSY; diff --git a/drivers/s390/block/dasd_proc.c b/drivers/s390/block/dasd_proc.c index 1aa3c26..ad23aed 100644 --- a/drivers/s390/block/dasd_proc.c +++ b/drivers/s390/block/dasd_proc.c @@ -294,23 +294,40 @@ out_error: #endif /* CONFIG_DASD_PROFILE */ } +/* + * Create dasd proc-fs entries. + * In case creation failed, cleanup and return -ENOENT. + */ int dasd_proc_init(void) { dasd_proc_root_entry = proc_mkdir("dasd", &proc_root); + if (!dasd_proc_root_entry) + goto out_nodasd; dasd_proc_root_entry->owner = THIS_MODULE; dasd_devices_entry = create_proc_entry("devices", S_IFREG | S_IRUGO | S_IWUSR, dasd_proc_root_entry); + if (!dasd_devices_entry) + goto out_nodevices; dasd_devices_entry->proc_fops = &dasd_devices_file_ops; dasd_devices_entry->owner = THIS_MODULE; dasd_statistics_entry = create_proc_entry("statistics", S_IFREG | S_IRUGO | S_IWUSR, dasd_proc_root_entry); + if (!dasd_statistics_entry) + goto out_nostatistics; dasd_statistics_entry->read_proc = dasd_statistics_read; dasd_statistics_entry->write_proc = dasd_statistics_write; dasd_statistics_entry->owner = THIS_MODULE; return 0; + + out_nostatistics: + remove_proc_entry("devices", dasd_proc_root_entry); + out_nodevices: + remove_proc_entry("dasd", &proc_root); + out_nodasd: + return -ENOENT; } void diff --git a/drivers/s390/char/keyboard.c b/drivers/s390/char/keyboard.c index 6badd84..d4d2ff0 100644 --- a/drivers/s390/char/keyboard.c +++ b/drivers/s390/char/keyboard.c @@ -54,7 +54,7 @@ kbd_alloc(void) { if (!kbd) goto out; kbd->key_maps = kzalloc(sizeof(key_maps), GFP_KERNEL); - if (!key_maps) + if (!kbd->key_maps) goto out_kbd; for (i = 0; i < ARRAY_SIZE(key_maps); i++) { if (key_maps[i]) { diff --git a/drivers/s390/char/tape_block.c b/drivers/s390/char/tape_block.c index 5c65cf3..b70d926 100644 --- a/drivers/s390/char/tape_block.c +++ b/drivers/s390/char/tape_block.c @@ -432,8 +432,8 @@ tapeblock_ioctl( ) { int rc; int minor; - struct gendisk *disk = inode->i_bdev->bd_disk; - struct tape_device *device = disk->private_data; + struct gendisk *disk; + struct tape_device *device; rc = 0; disk = inode->i_bdev->bd_disk; diff --git a/drivers/s390/char/tape_core.c b/drivers/s390/char/tape_core.c index 389ee2c..e6e4086 100644 --- a/drivers/s390/char/tape_core.c +++ b/drivers/s390/char/tape_core.c @@ -210,18 +210,14 @@ tape_state_set(struct tape_device *device, enum tape_state newstate) return; } DBF_EVENT(4, "ts. dev: %x\n", device->first_minor); - if (device->tape_state < TO_SIZE && device->tape_state >= 0) - str = tape_state_verbose[device->tape_state]; - else - str = "UNKNOWN TS"; - DBF_EVENT(4, "old ts: %s\n", str); - if (device->tape_state < TO_SIZE && device->tape_state >=0 ) + DBF_EVENT(4, "old ts:\t\n"); + if (device->tape_state < TS_SIZE && device->tape_state >=0 ) str = tape_state_verbose[device->tape_state]; else str = "UNKNOWN TS"; DBF_EVENT(4, "%s\n", str); DBF_EVENT(4, "new ts:\t\n"); - if (newstate < TO_SIZE && newstate >= 0) + if (newstate < TS_SIZE && newstate >= 0) str = tape_state_verbose[newstate]; else str = "UNKNOWN TS"; diff --git a/drivers/s390/cio/blacklist.c b/drivers/s390/cio/blacklist.c index cb8e2e6..0960bef 100644 --- a/drivers/s390/cio/blacklist.c +++ b/drivers/s390/cio/blacklist.c @@ -414,11 +414,11 @@ cio_ignore_proc_init (void) entry = create_proc_entry ("cio_ignore", S_IFREG | S_IRUGO | S_IWUSR, &proc_root); if (!entry) - return 0; + return -ENOENT; entry->proc_fops = &cio_ignore_proc_fops; - return 1; + return 0; } __initcall (cio_ignore_proc_init); diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c index cbb86fa..5b20d8c 100644 --- a/drivers/s390/cio/cio.c +++ b/drivers/s390/cio/cio.c @@ -67,7 +67,7 @@ cio_debug_init (void) goto out_unregister; debug_register_view (cio_debug_msg_id, &debug_sprintf_view); debug_set_level (cio_debug_msg_id, 2); - cio_debug_trace_id = debug_register ("cio_trace", 16, 4, 8); + cio_debug_trace_id = debug_register ("cio_trace", 16, 4, 16); if (!cio_debug_trace_id) goto out_unregister; debug_register_view (cio_debug_trace_id, &debug_hex_ascii_view); diff --git a/drivers/s390/cio/cio_debug.h b/drivers/s390/cio/cio_debug.h index 6af8b27..f88844a 100644 --- a/drivers/s390/cio/cio_debug.h +++ b/drivers/s390/cio/cio_debug.h @@ -3,6 +3,11 @@ #include <asm/debug.h> +/* for use of debug feature */ +extern debug_info_t *cio_debug_msg_id; +extern debug_info_t *cio_debug_trace_id; +extern debug_info_t *cio_debug_crw_id; + #define CIO_TRACE_EVENT(imp, txt) do { \ debug_text_event(cio_debug_trace_id, imp, txt); \ } while (0) @@ -15,18 +20,19 @@ debug_sprintf_event(cio_debug_crw_id, imp , ##args); \ } while (0) -#define CIO_HEX_EVENT(imp, args...) do { \ - debug_event(cio_debug_trace_id, imp, ##args); \ - } while (0) +static inline void +CIO_HEX_EVENT(int level, void *data, int length) +{ + while (length > 0) { + debug_event(cio_debug_trace_id, level, data, length); + length -= cio_debug_trace_id->buf_size; + data += cio_debug_trace_id->buf_size; + } +} #define CIO_DEBUG(printk_level,event_level,msg...) ({ \ if (cio_show_msg) printk(printk_level msg); \ CIO_MSG_EVENT (event_level, msg); \ }) -/* for use of debug feature */ -extern debug_info_t *cio_debug_msg_id; -extern debug_info_t *cio_debug_trace_id; -extern debug_info_t *cio_debug_crw_id; - #endif diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c index 25f678d..e8e41e6 100644 --- a/drivers/scsi/3w-xxxx.c +++ b/drivers/scsi/3w-xxxx.c @@ -1508,10 +1508,12 @@ static void tw_transfer_internal(TW_Device_Extension *tw_dev, int request_id, struct scsi_cmnd *cmd = tw_dev->srb[request_id]; void *buf; unsigned int transfer_len; + unsigned long flags = 0; if (cmd->use_sg) { struct scatterlist *sg = (struct scatterlist *)cmd->request_buffer; + local_irq_save(flags); buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset; transfer_len = min(sg->length, len); } else { @@ -1526,6 +1528,7 @@ static void tw_transfer_internal(TW_Device_Extension *tw_dev, int request_id, sg = (struct scatterlist *)cmd->request_buffer; kunmap_atomic(buf - sg->offset, KM_IRQ0); + local_irq_restore(flags); } } diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index ff48066..1b8429c 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -207,7 +207,6 @@ static struct scsi_host_template ahci_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, - .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, .sg_tablesize = AHCI_MAX_SG, @@ -517,25 +516,7 @@ static void ahci_fill_cmd_slot(struct ahci_port_priv *pp, u32 opts) pp->cmd_slot[0].tbl_addr_hi = cpu_to_le32((pp->cmd_tbl_dma >> 16) >> 16); } -static int ahci_poll_register(void __iomem *reg, u32 mask, u32 val, - unsigned long interval_msec, - unsigned long timeout_msec) -{ - unsigned long timeout; - u32 tmp; - - timeout = jiffies + (timeout_msec * HZ) / 1000; - do { - tmp = readl(reg); - if ((tmp & mask) == val) - return 0; - msleep(interval_msec); - } while (time_before(jiffies, timeout)); - - return -1; -} - -static int ahci_softreset(struct ata_port *ap, int verbose, unsigned int *class) +static int ahci_softreset(struct ata_port *ap, unsigned int *class) { struct ahci_host_priv *hpriv = ap->host_set->private_data; struct ahci_port_priv *pp = ap->private_data; @@ -544,6 +525,7 @@ static int ahci_softreset(struct ata_port *ap, int verbose, unsigned int *class) const u32 cmd_fis_len = 5; /* five dwords */ const char *reason = NULL; struct ata_taskfile tf; + u32 tmp; u8 *fis; int rc; @@ -565,8 +547,6 @@ static int ahci_softreset(struct ata_port *ap, int verbose, unsigned int *class) /* check BUSY/DRQ, perform Command List Override if necessary */ ahci_tf_read(ap, &tf); if (tf.command & (ATA_BUSY | ATA_DRQ)) { - u32 tmp; - if (!(hpriv->cap & HOST_CAP_CLO)) { rc = -EIO; reason = "port busy but no CLO"; @@ -576,10 +556,10 @@ static int ahci_softreset(struct ata_port *ap, int verbose, unsigned int *class) tmp = readl(port_mmio + PORT_CMD); tmp |= PORT_CMD_CLO; writel(tmp, port_mmio + PORT_CMD); - readl(port_mmio + PORT_CMD); /* flush */ - if (ahci_poll_register(port_mmio + PORT_CMD, PORT_CMD_CLO, 0x0, - 1, 500)) { + tmp = ata_wait_register(port_mmio + PORT_CMD, + PORT_CMD_CLO, PORT_CMD_CLO, 1, 500); + if (tmp & PORT_CMD_CLO) { rc = -EIO; reason = "CLO failed"; goto fail_restart; @@ -600,9 +580,9 @@ static int ahci_softreset(struct ata_port *ap, int verbose, unsigned int *class) fis[1] &= ~(1 << 7); /* turn off Command FIS bit */ writel(1, port_mmio + PORT_CMD_ISSUE); - readl(port_mmio + PORT_CMD_ISSUE); /* flush */ - if (ahci_poll_register(port_mmio + PORT_CMD_ISSUE, 0x1, 0x0, 1, 500)) { + tmp = ata_wait_register(port_mmio + PORT_CMD_ISSUE, 0x1, 0x1, 1, 500); + if (tmp & 0x1) { rc = -EIO; reason = "1st FIS failed"; goto fail; @@ -647,22 +627,19 @@ static int ahci_softreset(struct ata_port *ap, int verbose, unsigned int *class) fail_restart: ahci_start_engine(ap); fail: - if (verbose) - printk(KERN_ERR "ata%u: softreset failed (%s)\n", - ap->id, reason); - else - DPRINTK("EXIT, rc=%d reason=\"%s\"\n", rc, reason); + printk(KERN_ERR "ata%u: softreset failed (%s)\n", + ap->id, reason); return rc; } -static int ahci_hardreset(struct ata_port *ap, int verbose, unsigned int *class) +static int ahci_hardreset(struct ata_port *ap, unsigned int *class) { int rc; DPRINTK("ENTER\n"); ahci_stop_engine(ap); - rc = sata_std_hardreset(ap, verbose, class); + rc = sata_std_hardreset(ap, class); ahci_start_engine(ap); if (rc == 0) diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c index 8383970..62dabf7 100644 --- a/drivers/scsi/ata_piix.c +++ b/drivers/scsi/ata_piix.c @@ -209,7 +209,6 @@ static struct scsi_host_template piix_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, - .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, .sg_tablesize = LIBATA_MAX_PRD, diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index ef57f25..dfcb96f 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c @@ -294,18 +294,6 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize) if (sht->unchecked_isa_dma && privsize) gfp_mask |= __GFP_DMA; - /* Check to see if this host has any error handling facilities */ - if (!sht->eh_strategy_handler && !sht->eh_abort_handler && - !sht->eh_device_reset_handler && !sht->eh_bus_reset_handler && - !sht->eh_host_reset_handler) { - printk(KERN_ERR "ERROR: SCSI host `%s' has no error handling\n" - "ERROR: This is not a safe way to run your " - "SCSI host\n" - "ERROR: The error handling must be added to " - "this driver\n", sht->proc_name); - dump_stack(); - } - shost = kzalloc(sizeof(struct Scsi_Host) + privsize, gfp_mask); if (!shost) return NULL; diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 2b2feb6..5d38a6c 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -1425,12 +1425,9 @@ static int ata_bus_probe(struct ata_port *ap) /* read IDENTIFY page and configure devices */ for (i = 0; i < ATA_MAX_DEVICES; i++) { dev = &ap->device[i]; - dev->class = classes[i]; - if (!tries[i]) { - ata_down_xfermask_limit(ap, dev, 1); - ata_dev_disable(ap, dev); - } + if (tries[i]) + dev->class = classes[i]; if (!ata_dev_enabled(dev)) continue; @@ -1458,12 +1455,12 @@ static int ata_bus_probe(struct ata_port *ap) break; } rc = 0; - } else { + } else rc = ata_set_mode(ap, &dev); - if (rc) { - down_xfermask = 1; - goto fail; - } + + if (rc) { + down_xfermask = 1; + goto fail; } for (i = 0; i < ATA_MAX_DEVICES; i++) @@ -1491,6 +1488,11 @@ static int ata_bus_probe(struct ata_port *ap) tries[dev->devno] = 0; } + if (!tries[dev->devno]) { + ata_down_xfermask_limit(ap, dev, 1); + ata_dev_disable(ap, dev); + } + goto retry; } @@ -1750,7 +1752,7 @@ int ata_set_sata_spd_needed(struct ata_port *ap) * 0 if spd doesn't need to be changed, 1 if spd has been * changed. -EOPNOTSUPP if SCR registers are inaccessible. */ -static int ata_set_sata_spd(struct ata_port *ap) +int ata_set_sata_spd(struct ata_port *ap) { u32 scontrol; @@ -2246,8 +2248,10 @@ static unsigned int ata_bus_softreset(struct ata_port *ap, * the bus shows 0xFF because the odd clown forgets the D7 * pulldown resistor. */ - if (ata_check_status(ap) == 0xFF) + if (ata_check_status(ap) == 0xFF) { + printk(KERN_ERR "ata%u: SRST failed (status 0xFF)\n", ap->id); return AC_ERR_OTHER; + } ata_bus_post_reset(ap, devmask); @@ -2383,12 +2387,16 @@ void ata_std_probeinit(struct ata_port *ap) if ((ap->flags & ATA_FLAG_SATA) && ap->ops->scr_read) { u32 spd; + /* set cable type and resume link */ + ap->cbl = ATA_CBL_SATA; sata_phy_resume(ap); + /* init sata_spd_limit to the current value */ spd = (scr_read(ap, SCR_CONTROL) & 0xf0) >> 4; if (spd) ap->sata_spd_limit &= (1 << spd) - 1; + /* wait for device */ if (sata_dev_present(ap)) ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT); } @@ -2397,7 +2405,6 @@ void ata_std_probeinit(struct ata_port *ap) /** * ata_std_softreset - reset host port via ATA SRST * @ap: port to reset - * @verbose: fail verbosely * @classes: resulting classes of attached devices * * Reset host port using ATA SRST. This function is to be used @@ -2409,7 +2416,7 @@ void ata_std_probeinit(struct ata_port *ap) * RETURNS: * 0 on success, -errno otherwise. */ -int ata_std_softreset(struct ata_port *ap, int verbose, unsigned int *classes) +int ata_std_softreset(struct ata_port *ap, unsigned int *classes) { unsigned int slave_possible = ap->flags & ATA_FLAG_SLAVE_POSS; unsigned int devmask = 0, err_mask; @@ -2435,12 +2442,8 @@ int ata_std_softreset(struct ata_port *ap, int verbose, unsigned int *classes) DPRINTK("about to softreset, devmask=%x\n", devmask); err_mask = ata_bus_softreset(ap, devmask); if (err_mask) { - if (verbose) - printk(KERN_ERR "ata%u: SRST failed (err_mask=0x%x)\n", - ap->id, err_mask); - else - DPRINTK("EXIT, softreset failed (err_mask=0x%x)\n", - err_mask); + printk(KERN_ERR "ata%u: SRST failed (err_mask=0x%x)\n", + ap->id, err_mask); return -EIO; } @@ -2457,7 +2460,6 @@ int ata_std_softreset(struct ata_port *ap, int verbose, unsigned int *classes) /** * sata_std_hardreset - reset host port via SATA phy reset * @ap: port to reset - * @verbose: fail verbosely * @class: resulting class of attached device * * SATA phy-reset host port using DET bits of SControl register. @@ -2470,7 +2472,7 @@ int ata_std_softreset(struct ata_port *ap, int verbose, unsigned int *classes) * RETURNS: * 0 on success, -errno otherwise. */ -int sata_std_hardreset(struct ata_port *ap, int verbose, unsigned int *class) +int sata_std_hardreset(struct ata_port *ap, unsigned int *class) { u32 scontrol; @@ -2510,11 +2512,8 @@ int sata_std_hardreset(struct ata_port *ap, int verbose, unsigned int *class) } if (ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT)) { - if (verbose) - printk(KERN_ERR "ata%u: COMRESET failed " - "(device not ready)\n", ap->id); - else - DPRINTK("EXIT, device not ready\n"); + printk(KERN_ERR + "ata%u: COMRESET failed (device not ready)\n", ap->id); return -EIO; } @@ -2545,10 +2544,6 @@ void ata_std_postreset(struct ata_port *ap, unsigned int *classes) { DPRINTK("ENTER\n"); - /* set cable type if it isn't already set */ - if (ap->cbl == ATA_CBL_NONE && ap->flags & ATA_FLAG_SATA) - ap->cbl = ATA_CBL_SATA; - /* print link status */ if (ap->cbl == ATA_CBL_SATA) sata_print_link_status(ap); @@ -2598,7 +2593,7 @@ int ata_std_probe_reset(struct ata_port *ap, unsigned int *classes) ata_reset_fn_t hardreset; hardreset = NULL; - if (ap->flags & ATA_FLAG_SATA && ap->ops->scr_read) + if (ap->cbl == ATA_CBL_SATA && ap->ops->scr_read) hardreset = sata_std_hardreset; return ata_drive_probe_reset(ap, ata_std_probeinit, @@ -2606,16 +2601,15 @@ int ata_std_probe_reset(struct ata_port *ap, unsigned int *classes) ata_std_postreset, classes); } -int ata_do_reset(struct ata_port *ap, - ata_reset_fn_t reset, ata_postreset_fn_t postreset, - int verbose, unsigned int *classes) +int ata_do_reset(struct ata_port *ap, ata_reset_fn_t reset, + ata_postreset_fn_t postreset, unsigned int *classes) { int i, rc; for (i = 0; i < ATA_MAX_DEVICES; i++) classes[i] = ATA_DEV_UNKNOWN; - rc = reset(ap, verbose, classes); + rc = reset(ap, classes); if (rc) return rc; @@ -2659,8 +2653,6 @@ int ata_do_reset(struct ata_port *ap, * - If classification is supported, fill classes[] with * recognized class codes. * - If classification is not supported, leave classes[] alone. - * - If verbose is non-zero, print error message on failure; - * otherwise, shut up. * * LOCKING: * Kernel thread context (may sleep) @@ -2680,7 +2672,7 @@ int ata_drive_probe_reset(struct ata_port *ap, ata_probeinit_fn_t probeinit, probeinit(ap); if (softreset && !ata_set_sata_spd_needed(ap)) { - rc = ata_do_reset(ap, softreset, postreset, 0, classes); + rc = ata_do_reset(ap, softreset, postreset, classes); if (rc == 0 && classes[0] != ATA_DEV_UNKNOWN) goto done; printk(KERN_INFO "ata%u: softreset failed, will try " @@ -2692,7 +2684,7 @@ int ata_drive_probe_reset(struct ata_port *ap, ata_probeinit_fn_t probeinit, goto done; while (1) { - rc = ata_do_reset(ap, hardreset, postreset, 0, classes); + rc = ata_do_reset(ap, hardreset, postreset, classes); if (rc == 0) { if (classes[0] != ATA_DEV_UNKNOWN) goto done; @@ -2713,7 +2705,7 @@ int ata_drive_probe_reset(struct ata_port *ap, ata_probeinit_fn_t probeinit, ap->id); ssleep(5); - rc = ata_do_reset(ap, softreset, postreset, 0, classes); + rc = ata_do_reset(ap, softreset, postreset, classes); } done: @@ -4846,7 +4838,7 @@ static struct ata_port * ata_host_add(const struct ata_probe_ent *ent, host->transportt = &ata_scsi_transport_template; - ap = (struct ata_port *) &host->hostdata[0]; + ap = ata_shost_to_port(host); ata_host_init(ap, host, host_set, ent, port_no); @@ -5059,7 +5051,7 @@ void ata_host_set_remove(struct ata_host_set *host_set) int ata_scsi_release(struct Scsi_Host *host) { - struct ata_port *ap = (struct ata_port *) &host->hostdata[0]; + struct ata_port *ap = ata_shost_to_port(host); int i; DPRINTK("ENTER\n"); @@ -5226,6 +5218,52 @@ int ata_ratelimit(void) return rc; } +/** + * ata_wait_register - wait until register value changes + * @reg: IO-mapped register + * @mask: Mask to apply to read register value + * @val: Wait condition + * @interval_msec: polling interval in milliseconds + * @timeout_msec: timeout in milliseconds + * + * Waiting for some bits of register to change is a common + * operation for ATA controllers. This function reads 32bit LE + * IO-mapped register @reg and tests for the following condition. + * + * (*@reg & mask) != val + * + * If the condition is met, it returns; otherwise, the process is + * repeated after @interval_msec until timeout. + * + * LOCKING: + * Kernel thread context (may sleep) + * + * RETURNS: + * The final register value. + */ +u32 ata_wait_register(void __iomem *reg, u32 mask, u32 val, + unsigned long interval_msec, + unsigned long timeout_msec) +{ + unsigned long timeout; + u32 tmp; + + tmp = ioread32(reg); + + /* Calculate timeout _after_ the first read to make sure + * preceding writes reach the controller before starting to + * eat away the timeout. + */ + timeout = jiffies + (timeout_msec * HZ) / 1000; + + while ((tmp & mask) == val && time_before(jiffies, timeout)) { + msleep(interval_msec); + tmp = ioread32(reg); + } + + return tmp; +} + /* * libata is essentially a library of internal helper functions for * low-level ATA host controller drivers. As such, the API/ABI is @@ -5262,6 +5300,7 @@ EXPORT_SYMBOL_GPL(ata_bmdma_irq_clear); EXPORT_SYMBOL_GPL(ata_bmdma_status); EXPORT_SYMBOL_GPL(ata_bmdma_stop); EXPORT_SYMBOL_GPL(ata_port_probe); +EXPORT_SYMBOL_GPL(ata_set_sata_spd); EXPORT_SYMBOL_GPL(sata_phy_reset); EXPORT_SYMBOL_GPL(__sata_phy_reset); EXPORT_SYMBOL_GPL(ata_bus_reset); @@ -5276,6 +5315,7 @@ EXPORT_SYMBOL_GPL(ata_dev_classify); EXPORT_SYMBOL_GPL(ata_dev_pair); EXPORT_SYMBOL_GPL(ata_port_disable); EXPORT_SYMBOL_GPL(ata_ratelimit); +EXPORT_SYMBOL_GPL(ata_wait_register); EXPORT_SYMBOL_GPL(ata_busy_sleep); EXPORT_SYMBOL_GPL(ata_port_queue_task); EXPORT_SYMBOL_GPL(ata_scsi_ioctl); diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c index 9a8eea1..16db622 100644 --- a/drivers/scsi/libata-eh.c +++ b/drivers/scsi/libata-eh.c @@ -64,7 +64,7 @@ enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd) { struct Scsi_Host *host = cmd->device->host; - struct ata_port *ap = (struct ata_port *) &host->hostdata[0]; + struct ata_port *ap = ata_shost_to_port(host); unsigned long flags; struct ata_queued_cmd *qc; enum scsi_eh_timer_return ret = EH_HANDLED; @@ -97,9 +97,9 @@ enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd) * RETURNS: * Zero. */ -int ata_scsi_error(struct Scsi_Host *host) +void ata_scsi_error(struct Scsi_Host *host) { - struct ata_port *ap = (struct ata_port *)&host->hostdata[0]; + struct ata_port *ap = ata_shost_to_port(host); DPRINTK("ENTER\n"); @@ -116,7 +116,6 @@ int ata_scsi_error(struct Scsi_Host *host) scsi_eh_flush_done_q(&ap->eh_done_q); DPRINTK("EXIT\n"); - return 0; } /** diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index c9c0014..9871f82 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -98,6 +98,7 @@ static const u8 def_control_mpage[CONTROL_MPAGE_LEN] = { * It just needs the eh_timed_out hook. */ struct scsi_transport_template ata_scsi_transport_template = { + .eh_strategy_handler = ata_scsi_error, .eh_timed_out = ata_scsi_timed_out, }; @@ -394,7 +395,7 @@ void ata_dump_status(unsigned id, struct ata_taskfile *tf) int ata_scsi_device_resume(struct scsi_device *sdev) { - struct ata_port *ap = (struct ata_port *) &sdev->host->hostdata[0]; + struct ata_port *ap = ata_shost_to_port(sdev->host); struct ata_device *dev = &ap->device[sdev->id]; return ata_device_resume(ap, dev); @@ -402,7 +403,7 @@ int ata_scsi_device_resume(struct scsi_device *sdev) int ata_scsi_device_suspend(struct scsi_device *sdev, pm_message_t state) { - struct ata_port *ap = (struct ata_port *) &sdev->host->hostdata[0]; + struct ata_port *ap = ata_shost_to_port(sdev->host); struct ata_device *dev = &ap->device[sdev->id]; return ata_device_suspend(ap, dev, state); @@ -703,7 +704,7 @@ int ata_scsi_slave_config(struct scsi_device *sdev) struct ata_port *ap; struct ata_device *dev; - ap = (struct ata_port *) &sdev->host->hostdata[0]; + ap = ata_shost_to_port(sdev->host); dev = &ap->device[sdev->id]; ata_scsi_dev_config(sdev, dev); @@ -2477,7 +2478,7 @@ int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) struct scsi_device *scsidev = cmd->device; struct Scsi_Host *shost = scsidev->host; - ap = (struct ata_port *) &shost->hostdata[0]; + ap = ata_shost_to_port(shost); spin_unlock(shost->host_lock); spin_lock(&ap->host_set->lock); diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h index 652c08e..3f8b0a8 100644 --- a/drivers/scsi/libata.h +++ b/drivers/scsi/libata.h @@ -56,10 +56,8 @@ extern int ata_set_sata_spd_needed(struct ata_port *ap); extern int ata_down_xfermask_limit(struct ata_port *ap, struct ata_device *dev, int force_pio0); extern int ata_set_mode(struct ata_port *ap, struct ata_device **r_failed_dev); -extern int ata_do_reset(struct ata_port *ap, - ata_reset_fn_t reset, - ata_postreset_fn_t postreset, - int verbose, unsigned int *classes); +extern int ata_do_reset(struct ata_port *ap, ata_reset_fn_t reset, + ata_postreset_fn_t postreset, unsigned int *classes); extern void ata_qc_free(struct ata_queued_cmd *qc); extern void ata_qc_issue(struct ata_queued_cmd *qc); extern int ata_check_atapi_dma(struct ata_queued_cmd *qc); @@ -105,5 +103,6 @@ extern void ata_scsi_rbuf_fill(struct ata_scsi_args *args, /* libata-eh.c */ extern enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd); +extern void ata_scsi_error(struct Scsi_Host *host); #endif /* __LIBATA_H__ */ diff --git a/drivers/scsi/pdc_adma.c b/drivers/scsi/pdc_adma.c index 1fca6f1..a341fa8 100644 --- a/drivers/scsi/pdc_adma.c +++ b/drivers/scsi/pdc_adma.c @@ -143,7 +143,6 @@ static struct scsi_host_template adma_ata_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, - .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, .sg_tablesize = LIBATA_MAX_PRD, diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c index fd9f217..08665ea 100644 --- a/drivers/scsi/sata_mv.c +++ b/drivers/scsi/sata_mv.c @@ -378,7 +378,6 @@ static struct scsi_host_template mv_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, - .eh_strategy_handler = ata_scsi_error, .can_queue = MV_USE_Q_DEPTH, .this_id = ATA_SHT_THIS_ID, .sg_tablesize = MV_MAX_SG_CT / 2, diff --git a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c index 3a0004c..70c5108 100644 --- a/drivers/scsi/sata_nv.c +++ b/drivers/scsi/sata_nv.c @@ -201,7 +201,6 @@ static struct scsi_host_template nv_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, - .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, .sg_tablesize = LIBATA_MAX_PRD, diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c index 03c647c..aaf896a 100644 --- a/drivers/scsi/sata_promise.c +++ b/drivers/scsi/sata_promise.c @@ -112,7 +112,6 @@ static struct scsi_host_template pdc_ata_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, - .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, .sg_tablesize = LIBATA_MAX_PRD, diff --git a/drivers/scsi/sata_qstor.c b/drivers/scsi/sata_qstor.c index 1b7a931..54283e0 100644 --- a/drivers/scsi/sata_qstor.c +++ b/drivers/scsi/sata_qstor.c @@ -132,7 +132,6 @@ static struct scsi_host_template qs_ata_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, - .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, .sg_tablesize = QS_MAX_PRD, diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c index f29c3e7..c933357 100644 --- a/drivers/scsi/sata_sil.c +++ b/drivers/scsi/sata_sil.c @@ -146,7 +146,6 @@ static struct scsi_host_template sil_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, - .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, .sg_tablesize = LIBATA_MAX_PRD, diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index 646756a..e9fd869 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c @@ -86,6 +86,13 @@ enum { /* HOST_SLOT_STAT bits */ HOST_SSTAT_ATTN = (1 << 31), + /* HOST_CTRL bits */ + HOST_CTRL_M66EN = (1 << 16), /* M66EN PCI bus signal */ + HOST_CTRL_TRDY = (1 << 17), /* latched PCI TRDY */ + HOST_CTRL_STOP = (1 << 18), /* latched PCI STOP */ + HOST_CTRL_DEVSEL = (1 << 19), /* latched PCI DEVSEL */ + HOST_CTRL_REQ64 = (1 << 20), /* latched PCI REQ64 */ + /* * Port registers * (8192 bytes @ +0x0000, +0x2000, +0x4000 and +0x6000 @ BAR2) @@ -142,8 +149,12 @@ enum { PORT_IRQ_PWR_CHG = (1 << 3), /* power management change */ PORT_IRQ_PHYRDY_CHG = (1 << 4), /* PHY ready change */ PORT_IRQ_COMWAKE = (1 << 5), /* COMWAKE received */ - PORT_IRQ_UNK_FIS = (1 << 6), /* Unknown FIS received */ - PORT_IRQ_SDB_FIS = (1 << 11), /* SDB FIS received */ + PORT_IRQ_UNK_FIS = (1 << 6), /* unknown FIS received */ + PORT_IRQ_DEV_XCHG = (1 << 7), /* device exchanged */ + PORT_IRQ_8B10B = (1 << 8), /* 8b/10b decode error threshold */ + PORT_IRQ_CRC = (1 << 9), /* CRC error threshold */ + PORT_IRQ_HANDSHAKE = (1 << 10), /* handshake error threshold */ + PORT_IRQ_SDB_NOTIFY = (1 << 11), /* SDB notify received */ /* bits[27:16] are unmasked (raw) */ PORT_IRQ_RAW_SHIFT = 16, @@ -174,7 +185,7 @@ enum { PORT_CERR_CMD_PCIPERR = 27, /* ctrl[15:13] 110 - PCI parity err while fetching PRB */ PORT_CERR_XFR_UNDEF = 32, /* PSD ecode 00 - undefined */ PORT_CERR_XFR_TGTABRT = 33, /* PSD ecode 01 - target abort */ - PORT_CERR_XFR_MSGABRT = 34, /* PSD ecode 10 - master abort */ + PORT_CERR_XFR_MSTABRT = 34, /* PSD ecode 10 - master abort */ PORT_CERR_XFR_PCIPERR = 35, /* PSD ecode 11 - PCI prity err during transfer */ PORT_CERR_SENDSERVICE = 36, /* FIS received while sending service */ @@ -207,6 +218,11 @@ enum { BID_SIL3132 = 1, BID_SIL3131 = 2, + /* host flags */ + SIL24_COMMON_FLAGS = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | + ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA, + SIL24_FLAG_PCIX_IRQ_WOC = (1 << 24), /* IRQ loss errata on PCI-X */ + IRQ_STAT_4PORTS = 0xf, }; @@ -281,7 +297,6 @@ static struct scsi_host_template sil24_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, - .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, .sg_tablesize = LIBATA_MAX_PRD, @@ -334,9 +349,8 @@ static struct ata_port_info sil24_port_info[] = { /* sil_3124 */ { .sht = &sil24_sht, - .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | - ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | - SIL24_NPORTS2FLAG(4), + .host_flags = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(4) | + SIL24_FLAG_PCIX_IRQ_WOC, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x3f, /* udma0-5 */ @@ -345,9 +359,7 @@ static struct ata_port_info sil24_port_info[] = { /* sil_3132 */ { .sht = &sil24_sht, - .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | - ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | - SIL24_NPORTS2FLAG(2), + .host_flags = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(2), .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x3f, /* udma0-5 */ @@ -356,9 +368,7 @@ static struct ata_port_info sil24_port_info[] = { /* sil_3131/sil_3531 */ { .sht = &sil24_sht, - .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | - ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | - SIL24_NPORTS2FLAG(1), + .host_flags = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(1), .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ .udma_mask = 0x3f, /* udma0-5 */ @@ -427,15 +437,30 @@ static void sil24_tf_read(struct ata_port *ap, struct ata_taskfile *tf) *tf = pp->tf; } -static int sil24_softreset(struct ata_port *ap, int verbose, - unsigned int *class) +static int sil24_init_port(struct ata_port *ap) +{ + void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr; + u32 tmp; + + writel(PORT_CS_INIT, port + PORT_CTRL_STAT); + ata_wait_register(port + PORT_CTRL_STAT, + PORT_CS_INIT, PORT_CS_INIT, 10, 100); + tmp = ata_wait_register(port + PORT_CTRL_STAT, + PORT_CS_RDY, 0, 10, 100); + + if ((tmp & (PORT_CS_INIT | PORT_CS_RDY)) != PORT_CS_RDY) + return -EIO; + return 0; +} + +static int sil24_softreset(struct ata_port *ap, unsigned int *class) { void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr; struct sil24_port_priv *pp = ap->private_data; struct sil24_prb *prb = &pp->cmd_block[0].ata.prb; dma_addr_t paddr = pp->cmd_block_dma; - unsigned long timeout = jiffies + ATA_TMOUT_BOOT * HZ; - u32 irq_enable, irq_stat; + u32 mask, irq_enable, irq_stat; + const char *reason; DPRINTK("ENTER\n"); @@ -449,34 +474,35 @@ static int sil24_softreset(struct ata_port *ap, int verbose, irq_enable = readl(port + PORT_IRQ_ENABLE_SET); writel(irq_enable, port + PORT_IRQ_ENABLE_CLR); - /* - * XXX: Not sure whether the following sleep is needed or not. - * The original driver had it. So.... - */ - msleep(10); + /* put the port into known state */ + if (sil24_init_port(ap)) { + reason ="port not ready"; + goto err; + } - prb->ctrl = PRB_CTRL_SRST; + /* do SRST */ + prb->ctrl = cpu_to_le16(PRB_CTRL_SRST); prb->fis[1] = 0; /* no PM yet */ writel((u32)paddr, port + PORT_CMD_ACTIVATE); + writel((u64)paddr >> 32, port + PORT_CMD_ACTIVATE + 4); - do { - irq_stat = readl(port + PORT_IRQ_STAT); - writel(irq_stat, port + PORT_IRQ_STAT); /* clear irq */ - - irq_stat >>= PORT_IRQ_RAW_SHIFT; - if (irq_stat & (PORT_IRQ_COMPLETE | PORT_IRQ_ERROR)) - break; + mask = (PORT_IRQ_COMPLETE | PORT_IRQ_ERROR) << PORT_IRQ_RAW_SHIFT; + irq_stat = ata_wait_register(port + PORT_IRQ_STAT, mask, 0x0, + 100, ATA_TMOUT_BOOT / HZ * 1000); - msleep(100); - } while (time_before(jiffies, timeout)); + writel(irq_stat, port + PORT_IRQ_STAT); /* clear IRQs */ + irq_stat >>= PORT_IRQ_RAW_SHIFT; /* restore IRQs */ writel(irq_enable, port + PORT_IRQ_ENABLE_SET); if (!(irq_stat & PORT_IRQ_COMPLETE)) { - DPRINTK("EXIT, srst failed\n"); - return -EIO; + if (irq_stat & PORT_IRQ_ERROR) + reason = "SRST command error"; + else + reason = "timeout"; + goto err; } sil24_update_tf(ap); @@ -488,15 +514,55 @@ static int sil24_softreset(struct ata_port *ap, int verbose, out: DPRINTK("EXIT, class=%u\n", *class); return 0; + + err: + printk(KERN_ERR "ata%u: softreset failed (%s)\n", ap->id, reason); + return -EIO; } -static int sil24_hardreset(struct ata_port *ap, int verbose, - unsigned int *class) +static int sil24_hardreset(struct ata_port *ap, unsigned int *class) { - unsigned int dummy_class; + void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr; + const char *reason; + int tout_msec; + u32 tmp; + + /* sil24 does the right thing(tm) without any protection */ + ata_set_sata_spd(ap); + + tout_msec = 100; + if (sata_dev_present(ap)) + tout_msec = 5000; - /* sil24 doesn't report device signature after hard reset */ - return sata_std_hardreset(ap, verbose, &dummy_class); + writel(PORT_CS_DEV_RST, port + PORT_CTRL_STAT); + tmp = ata_wait_register(port + PORT_CTRL_STAT, + PORT_CS_DEV_RST, PORT_CS_DEV_RST, 10, tout_msec); + + /* SStatus oscillates between zero and valid status for short + * duration after DEV_RST, give it time to settle. + */ + msleep(100); + + if (tmp & PORT_CS_DEV_RST) { + if (!sata_dev_present(ap)) + return 0; + reason = "link not ready"; + goto err; + } + + if (ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT)) { + reason = "device not ready"; + goto err; + } + + /* sil24 doesn't report device class code after hardreset, + * leave *class alone. + */ + return 0; + + err: + printk(KERN_ERR "ata%u: hardreset failed (%s)\n", ap->id, reason); + return -EIO; } static int sil24_probe_reset(struct ata_port *ap, unsigned int *classes) @@ -532,6 +598,7 @@ static void sil24_qc_prep(struct ata_queued_cmd *qc) union sil24_cmd_block *cb = pp->cmd_block + qc->tag; struct sil24_prb *prb; struct sil24_sge *sge; + u16 ctrl = 0; switch (qc->tf.protocol) { case ATA_PROT_PIO: @@ -539,7 +606,6 @@ static void sil24_qc_prep(struct ata_queued_cmd *qc) case ATA_PROT_NODATA: prb = &cb->ata.prb; sge = cb->ata.sge; - prb->ctrl = 0; break; case ATA_PROT_ATAPI: @@ -552,12 +618,10 @@ static void sil24_qc_prep(struct ata_queued_cmd *qc) if (qc->tf.protocol != ATA_PROT_ATAPI_NODATA) { if (qc->tf.flags & ATA_TFLAG_WRITE) - prb->ctrl = PRB_CTRL_PACKET_WRITE; + ctrl = PRB_CTRL_PACKET_WRITE; else - prb->ctrl = PRB_CTRL_PACKET_READ; - } else - prb->ctrl = 0; - + ctrl = PRB_CTRL_PACKET_READ; + } break; default: @@ -566,6 +630,7 @@ static void sil24_qc_prep(struct ata_queued_cmd *qc) BUG(); } + prb->ctrl = cpu_to_le16(ctrl); ata_tf_to_fis(&qc->tf, prb->fis, 0); if (qc->flags & ATA_QCFLAG_DMAMAP) @@ -580,6 +645,8 @@ static unsigned int sil24_qc_issue(struct ata_queued_cmd *qc) dma_addr_t paddr = pp->cmd_block_dma + qc->tag * sizeof(*pp->cmd_block); writel((u32)paddr, port + PORT_CMD_ACTIVATE); + writel((u64)paddr >> 32, port + PORT_CMD_ACTIVATE + 4); + return 0; } @@ -728,6 +795,10 @@ static inline void sil24_host_intr(struct ata_port *ap) slot_stat = readl(port + PORT_SLOT_STAT); if (!(slot_stat & HOST_SSTAT_ATTN)) { struct sil24_port_priv *pp = ap->private_data; + + if (ap->flags & SIL24_FLAG_PCIX_IRQ_WOC) + writel(PORT_IRQ_COMPLETE, port + PORT_IRQ_STAT); + /* * !HOST_SSAT_ATTN guarantees successful completion, * so reading back tf registers is unnecessary for @@ -859,6 +930,7 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) void __iomem *host_base = NULL; void __iomem *port_base = NULL; int i, rc; + u32 tmp; if (!printed_version++) dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); @@ -911,35 +983,51 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) /* * Configure the device */ - /* - * FIXME: This device is certainly 64-bit capable. We just - * don't know how to use it. After fixing 32bit activation in - * this function, enable 64bit masks here. - */ - rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK); - if (rc) { - dev_printk(KERN_ERR, &pdev->dev, - "32-bit DMA enable failed\n"); - goto out_free; - } - rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); - if (rc) { - dev_printk(KERN_ERR, &pdev->dev, - "32-bit consistent DMA enable failed\n"); - goto out_free; + if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) { + rc = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK); + if (rc) { + rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); + if (rc) { + dev_printk(KERN_ERR, &pdev->dev, + "64-bit DMA enable failed\n"); + goto out_free; + } + } + } else { + rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK); + if (rc) { + dev_printk(KERN_ERR, &pdev->dev, + "32-bit DMA enable failed\n"); + goto out_free; + } + rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); + if (rc) { + dev_printk(KERN_ERR, &pdev->dev, + "32-bit consistent DMA enable failed\n"); + goto out_free; + } } /* GPIO off */ writel(0, host_base + HOST_FLASH_CMD); - /* Mask interrupts during initialization */ + /* Apply workaround for completion IRQ loss on PCI-X errata */ + if (probe_ent->host_flags & SIL24_FLAG_PCIX_IRQ_WOC) { + tmp = readl(host_base + HOST_CTRL); + if (tmp & (HOST_CTRL_TRDY | HOST_CTRL_STOP | HOST_CTRL_DEVSEL)) + dev_printk(KERN_INFO, &pdev->dev, + "Applying completion IRQ loss on PCI-X " + "errata fix\n"); + else + probe_ent->host_flags &= ~SIL24_FLAG_PCIX_IRQ_WOC; + } + + /* clear global reset & mask interrupts during initialization */ writel(0, host_base + HOST_CTRL); for (i = 0; i < probe_ent->n_ports; i++) { void __iomem *port = port_base + i * PORT_REGS_SIZE; unsigned long portu = (unsigned long)port; - u32 tmp; - int cnt; probe_ent->port[i].cmd_addr = portu + PORT_PRB; probe_ent->port[i].scr_addr = portu + PORT_SCONTROL; @@ -953,18 +1041,20 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) tmp = readl(port + PORT_CTRL_STAT); if (tmp & PORT_CS_PORT_RST) { writel(PORT_CS_PORT_RST, port + PORT_CTRL_CLR); - readl(port + PORT_CTRL_STAT); /* sync */ - for (cnt = 0; cnt < 10; cnt++) { - msleep(10); - tmp = readl(port + PORT_CTRL_STAT); - if (!(tmp & PORT_CS_PORT_RST)) - break; - } + tmp = ata_wait_register(port + PORT_CTRL_STAT, + PORT_CS_PORT_RST, + PORT_CS_PORT_RST, 10, 100); if (tmp & PORT_CS_PORT_RST) dev_printk(KERN_ERR, &pdev->dev, "failed to clear port RST\n"); } + /* Configure IRQ WoC */ + if (probe_ent->host_flags & SIL24_FLAG_PCIX_IRQ_WOC) + writel(PORT_CS_IRQ_WOC, port + PORT_CTRL_STAT); + else + writel(PORT_CS_IRQ_WOC, port + PORT_CTRL_CLR); + /* Zero error counters. */ writel(0x8000, port + PORT_DECODE_ERR_THRESH); writel(0x8000, port + PORT_CRC_ERR_THRESH); @@ -973,14 +1063,13 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) writel(0x0000, port + PORT_CRC_ERR_CNT); writel(0x0000, port + PORT_HSHK_ERR_CNT); - /* FIXME: 32bit activation? */ - writel(0, port + PORT_ACTIVATE_UPPER_ADDR); - writel(PORT_CS_32BIT_ACTV, port + PORT_CTRL_STAT); + /* Always use 64bit activation */ + writel(PORT_CS_32BIT_ACTV, port + PORT_CTRL_CLR); /* Configure interrupts */ writel(0xffff, port + PORT_IRQ_ENABLE_CLR); - writel(PORT_IRQ_COMPLETE | PORT_IRQ_ERROR | PORT_IRQ_SDB_FIS, - port + PORT_IRQ_ENABLE_SET); + writel(PORT_IRQ_COMPLETE | PORT_IRQ_ERROR | + PORT_IRQ_SDB_NOTIFY, port + PORT_IRQ_ENABLE_SET); /* Clear interrupts */ writel(0x0fff0fff, port + PORT_IRQ_STAT); @@ -988,11 +1077,6 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) /* Clear port multiplier enable and resume bits */ writel(PORT_CS_PM_EN | PORT_CS_RESUME, port + PORT_CTRL_CLR); - - /* Reset itself */ - if (__sil24_reset_controller(port)) - dev_printk(KERN_ERR, &pdev->dev, - "failed to reset controller\n"); } /* Turn on interrupts */ diff --git a/drivers/scsi/sata_sis.c b/drivers/scsi/sata_sis.c index eb3cf5b..3097821 100644 --- a/drivers/scsi/sata_sis.c +++ b/drivers/scsi/sata_sis.c @@ -87,7 +87,6 @@ static struct scsi_host_template sis_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, - .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, .sg_tablesize = ATA_MAX_PRD, diff --git a/drivers/scsi/sata_svw.c b/drivers/scsi/sata_svw.c index a20bc81..d5eb537 100644 --- a/drivers/scsi/sata_svw.c +++ b/drivers/scsi/sata_svw.c @@ -257,7 +257,7 @@ static int k2_sata_proc_info(struct Scsi_Host *shost, char *page, char **start, int len, index; /* Find the ata_port */ - ap = (struct ata_port *) &shost->hostdata[0]; + ap = ata_shost_to_port(shost); if (ap == NULL) return 0; @@ -290,7 +290,6 @@ static struct scsi_host_template k2_sata_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, - .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, .sg_tablesize = LIBATA_MAX_PRD, diff --git a/drivers/scsi/sata_sx4.c b/drivers/scsi/sata_sx4.c index 13dba63..4c07ba1 100644 --- a/drivers/scsi/sata_sx4.c +++ b/drivers/scsi/sata_sx4.c @@ -182,7 +182,6 @@ static struct scsi_host_template pdc_sata_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, - .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, .sg_tablesize = LIBATA_MAX_PRD, diff --git a/drivers/scsi/sata_uli.c b/drivers/scsi/sata_uli.c index 513dd78..15f81bf 100644 --- a/drivers/scsi/sata_uli.c +++ b/drivers/scsi/sata_uli.c @@ -81,7 +81,6 @@ static struct scsi_host_template uli_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, - .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, .sg_tablesize = LIBATA_MAX_PRD, diff --git a/drivers/scsi/sata_via.c b/drivers/scsi/sata_via.c index de4e0eb..17aefab 100644 --- a/drivers/scsi/sata_via.c +++ b/drivers/scsi/sata_via.c @@ -94,7 +94,6 @@ static struct scsi_host_template svia_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, - .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, .sg_tablesize = LIBATA_MAX_PRD, diff --git a/drivers/scsi/sata_vsc.c b/drivers/scsi/sata_vsc.c index b7d6a31..0372be7 100644 --- a/drivers/scsi/sata_vsc.c +++ b/drivers/scsi/sata_vsc.c @@ -270,7 +270,6 @@ static struct scsi_host_template vsc_sata_sht = { .name = DRV_NAME, .ioctl = ata_scsi_ioctl, .queuecommand = ata_scsi_queuecmd, - .eh_strategy_handler = ata_scsi_error, .can_queue = ATA_DEF_QUEUE, .this_id = ATA_SHT_THIS_ID, .sg_tablesize = LIBATA_MAX_PRD, diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 5f0fdfb..1c75646 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -1537,8 +1537,8 @@ int scsi_error_handler(void *data) * what we need to do to get it up and online again (if we can). * If we fail, we end up taking the thing offline. */ - if (shost->hostt->eh_strategy_handler) - shost->hostt->eh_strategy_handler(shost); + if (shost->transportt->eh_strategy_handler) + shost->transportt->eh_strategy_handler(shost); else scsi_unjam_host(shost); diff --git a/drivers/sn/ioc3.c b/drivers/sn/ioc3.c index 93449a1..0b49ff7 100644 --- a/drivers/sn/ioc3.c +++ b/drivers/sn/ioc3.c @@ -11,6 +11,7 @@ #include <linux/errno.h> #include <linux/module.h> #include <linux/pci.h> +#include <linux/dma-mapping.h> #include <linux/interrupt.h> #include <linux/spinlock.h> #include <linux/delay.h> @@ -619,9 +620,9 @@ static int ioc3_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) pci_set_master(pdev); #ifdef USE_64BIT_DMA - ret = pci_set_dma_mask(pdev, 0xffffffffffffffffULL); + ret = pci_set_dma_mask(pdev, DMA_64BIT_MASK); if (!ret) { - ret = pci_set_consistent_dma_mask(pdev, 0xffffffffffffffffULL); + ret = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK); if (ret < 0) { printk(KERN_WARNING "%s: Unable to obtain 64 bit DMA " "for consistent allocations\n", diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 495db57..5cf2b80 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -28,6 +28,7 @@ 2005-09-10 v0.4.3 added HUAWEI E600 card and Audiovox AirCard 2005-09-20 v0.4.4 increased recv buffer size: the card sometimes wants to send >2000 bytes. + 2006-04-10 v0.4.2 fixed two array overrun errors :-/ Work sponsored by: Sigos GmbH, Germany <info@sigos.de> @@ -582,14 +583,14 @@ static void option_setup_urbs(struct usb_serial *serial) portdata = usb_get_serial_port_data(port); /* Do indat endpoints first */ - for (j = 0; j <= N_IN_URB; ++j) { + for (j = 0; j < N_IN_URB; ++j) { portdata->in_urbs[j] = option_setup_urb (serial, port->bulk_in_endpointAddress, USB_DIR_IN, port, portdata->in_buffer[j], IN_BUFLEN, option_indat_callback); } /* outdat endpoints */ - for (j = 0; j <= N_OUT_URB; ++j) { + for (j = 0; j < N_OUT_URB; ++j) { portdata->out_urbs[j] = option_setup_urb (serial, port->bulk_out_endpointAddress, USB_DIR_OUT, port, portdata->out_buffer[j], OUT_BUFLEN, option_outdat_callback); diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index f87c017..9060e71 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -961,7 +961,7 @@ config FB_ATY128 config FB_ATY tristate "ATI Mach64 display support" if PCI || ATARI - depends on FB + depends on FB && !SPARC32 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c index b39e72d..d9d7d3c 100644 --- a/drivers/video/aty/atyfb_base.c +++ b/drivers/video/aty/atyfb_base.c @@ -3400,7 +3400,7 @@ static int __devinit atyfb_pci_probe(struct pci_dev *pdev, const struct pci_devi struct atyfb_par *par; int i, rc = -ENOMEM; - for (i = ARRAY_SIZE(aty_chips); i >= 0; i--) + for (i = ARRAY_SIZE(aty_chips) - 1; i >= 0; i--) if (pdev->device == aty_chips[i].pci_id) break; diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 944855b..8d8eadb 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -435,6 +435,11 @@ int fb_prepare_logo(struct fb_info *info, int rotate) depth = info->var.green.length; } + if (info->fix.visual == FB_VISUAL_STATIC_PSEUDOCOLOR) { + /* assume console colormap */ + depth = 4; + } + if (depth >= 8) { switch (info->fix.visual) { case FB_VISUAL_TRUECOLOR: diff --git a/drivers/video/vesafb.c b/drivers/video/vesafb.c index 8982e54..b0b9acf 100644 --- a/drivers/video/vesafb.c +++ b/drivers/video/vesafb.c @@ -57,7 +57,7 @@ static unsigned short *pmi_base = NULL; static void (*pmi_start)(void); static void (*pmi_pal)(void); static int depth; - +static int vga_compat; /* --------------------------------------------------------------------- */ static int vesafb_pan_display(struct fb_var_screeninfo *var, @@ -83,9 +83,10 @@ static int vesafb_pan_display(struct fb_var_screeninfo *var, static void vesa_setpalette(int regno, unsigned red, unsigned green, unsigned blue) { + int shift = 16 - depth; + #ifdef __i386__ struct { u_char blue, green, red, pad; } entry; - int shift = 16 - depth; if (pmi_setpal) { entry.red = red >> shift; @@ -101,14 +102,20 @@ static void vesa_setpalette(int regno, unsigned red, unsigned green, "d" (regno), /* EDX */ "D" (&entry), /* EDI */ "S" (&pmi_pal)); /* ESI */ - } else { - /* without protected mode interface, try VGA registers... */ + return; + } +#endif + +/* + * without protected mode interface and if VGA compatible, + * try VGA registers... + */ + if (vga_compat) { outb_p(regno, dac_reg); outb_p(red >> shift, dac_val); outb_p(green >> shift, dac_val); outb_p(blue >> shift, dac_val); } -#endif } static int vesafb_setcolreg(unsigned regno, unsigned red, unsigned green, @@ -214,6 +221,7 @@ static int __init vesafb_probe(struct platform_device *dev) if (screen_info.orig_video_isVGA != VIDEO_TYPE_VLFB) return -ENODEV; + vga_compat = (screen_info.capabilities & 2) ? 0 : 1; vesafb_fix.smem_start = screen_info.lfb_base; vesafb_defined.bits_per_pixel = screen_info.lfb_depth; if (15 == vesafb_defined.bits_per_pixel) @@ -318,6 +326,12 @@ static int __init vesafb_probe(struct platform_device *dev) } } + if (vesafb_defined.bits_per_pixel == 8 && !pmi_setpal && !vga_compat) { + printk(KERN_WARNING "vesafb: hardware palette is unchangeable,\n" + " colors may be incorrect\n"); + vesafb_fix.visual = FB_VISUAL_STATIC_PSEUDOCOLOR; + } + vesafb_defined.xres_virtual = vesafb_defined.xres; vesafb_defined.yres_virtual = vesafb_fix.smem_len / vesafb_fix.line_length; if (ypan && vesafb_defined.yres_virtual > vesafb_defined.yres) { @@ -354,7 +368,8 @@ static int __init vesafb_probe(struct platform_device *dev) printk(KERN_INFO "vesafb: %s: " "size=%d:%d:%d:%d, shift=%d:%d:%d:%d\n", (vesafb_defined.bits_per_pixel > 8) ? - "Truecolor" : "Pseudocolor", + "Truecolor" : (vga_compat || pmi_setpal) ? + "Pseudocolor" : "Static Pseudocolor", screen_info.rsvd_size, screen_info.red_size, screen_info.green_size, |