diff options
Diffstat (limited to 'drivers/char')
75 files changed, 2529 insertions, 2223 deletions
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index a26d91743b24..2df42fdcdc91 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -127,7 +127,7 @@ config ROCKETPORT config CYCLADES tristate "Cyclades async mux support" - depends on SERIAL_NONSTANDARD + depends on SERIAL_NONSTANDARD && (PCI || ISA) ---help--- This driver supports Cyclades Z and Y multiserial boards. You would need something like this to connect more than two modems to @@ -631,7 +631,8 @@ config HVC_CONSOLE config HVC_ISERIES bool "iSeries Hypervisor Virtual Console support" - depends on PPC_ISERIES && !VIOCONS + depends on PPC_ISERIES + default y select HVC_DRIVER help iSeries machines support a hypervisor virtual console. @@ -1071,5 +1072,11 @@ config TELCLOCK /sys/devices/platform/telco_clock, with a number of files for controlling the behavior of this hardware. +config DEVPORT + bool + depends on !M68K + depends on ISA || PCI + default y + endmenu diff --git a/drivers/char/agp/uninorth-agp.c b/drivers/char/agp/uninorth-agp.c index 91b062126a68..42c0a600b1ac 100644 --- a/drivers/char/agp/uninorth-agp.c +++ b/drivers/char/agp/uninorth-agp.c @@ -613,7 +613,7 @@ static int __devinit agp_uninorth_probe(struct pci_dev *pdev, uninorth_node = of_find_node_by_name(NULL, "u3"); } if (uninorth_node) { - const int *revprop = get_property(uninorth_node, + const int *revprop = of_get_property(uninorth_node, "device-rev", NULL); if (revprop != NULL) uninorth_rev = *revprop & 0x3f; diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c index 0e2b72f2b887..4eaceabd8cea 100644 --- a/drivers/char/amiserial.c +++ b/drivers/char/amiserial.c @@ -1574,7 +1574,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout) if (timeout && time_after(jiffies, orig_jiffies + timeout)) break; } - current->state = TASK_RUNNING; + __set_current_state(TASK_RUNNING); #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies); #endif @@ -1700,7 +1700,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, #endif schedule(); } - current->state = TASK_RUNNING; + __set_current_state(TASK_RUNNING); remove_wait_queue(&info->open_wait, &wait); if (extra_count) state->count++; diff --git a/drivers/char/briq_panel.c b/drivers/char/briq_panel.c index c70d52ace8b2..ed53f541d9e8 100644 --- a/drivers/char/briq_panel.c +++ b/drivers/char/briq_panel.c @@ -206,7 +206,7 @@ static int __init briq_panel_init(void) const char *machine; int i; - machine = get_property(root, "model", NULL); + machine = of_get_property(root, "model", NULL); if (!machine || strncmp(machine, "TotalImpact,BRIQ-1", 18) != 0) { of_node_put(root); return -ENODEV; diff --git a/drivers/char/consolemap.c b/drivers/char/consolemap.c index b99b7561260d..fd40b959afdd 100644 --- a/drivers/char/consolemap.c +++ b/drivers/char/consolemap.c @@ -626,10 +626,10 @@ conv_uni_to_pc(struct vc_data *conp, long ucs) /* Only 16-bit codes supported at this time */ if (ucs > 0xffff) - ucs = 0xfffd; /* U+FFFD: REPLACEMENT CHARACTER */ - else if (ucs < 0x20 || ucs >= 0xfffe) + return -4; /* Not found */ + else if (ucs < 0x20) return -1; /* Not a printable character */ - else if (ucs == 0xfeff || (ucs >= 0x200a && ucs <= 0x200f)) + else if (ucs == 0xfeff || (ucs >= 0x200b && ucs <= 0x200f)) return -2; /* Zero-width space */ /* * UNI_DIRECT_BASE indicates the start of the region in the User Zone diff --git a/drivers/char/cs5535_gpio.c b/drivers/char/cs5535_gpio.c index c02d9e99e050..fe6d2407baed 100644 --- a/drivers/char/cs5535_gpio.c +++ b/drivers/char/cs5535_gpio.c @@ -44,6 +44,7 @@ static struct pci_device_id divil_pci[] = { { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA) }, { } /* NULL entry */ }; +MODULE_DEVICE_TABLE(pci, divil_pci); static struct cdev cs5535_gpio_cdev; diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c index 16dc5d1d3cb4..c72ee97d3892 100644 --- a/drivers/char/cyclades.c +++ b/drivers/char/cyclades.c @@ -10,15 +10,14 @@ * * Initially written by Randolph Bentson <bentson@grieg.seaslug.org>. * Modified and maintained by Marcio Saito <marcio@cyclades.com>. - * Currently maintained by Cyclades team <async@cyclades.com>. * - * For Technical support and installation problems, please send e-mail - * to support@cyclades.com. + * Copyright (C) 2007 Jiri Slaby <jirislaby@gmail.com> * * Much of the design and some of the code came from serial.c * which was copyright (C) 1991, 1992 Linus Torvalds. It was * extensively rewritten by Theodore Ts'o, 8/16/92 -- 9/14/92, * and then fixed as suggested by Michael K. Johnson 12/12/92. + * Converted to pci probing and cleaned up by Jiri Slaby. * * This version supports shared IRQ's (only for PCI boards). * @@ -591,7 +590,7 @@ * */ -#define CY_VERSION "2.4" +#define CY_VERSION "2.5" /* If you need to install more boards than NR_CARDS, change the constant in the definition below. No other change is necessary to support up to @@ -624,12 +623,6 @@ #undef CY_ENABLE_MONITORING #undef CY_PCI_DEBUG -#if 0 -#define PAUSE __asm__("nop") -#else -#define PAUSE do {} while (0) -#endif - /* * Include section */ @@ -659,17 +652,6 @@ #include <asm/irq.h> #include <asm/uaccess.h> -#define CY_LOCK(info,flags) \ - do { \ - spin_lock_irqsave(&cy_card[info->card].card_lock, flags); \ - } while (0) - -#define CY_UNLOCK(info,flags) \ - do { \ - spin_unlock_irqrestore(&cy_card[info->card].card_lock, flags); \ - } while (0) - -#include <linux/types.h> #include <linux/kernel.h> #include <linux/pci.h> @@ -682,13 +664,13 @@ static void cy_send_xchar(struct tty_struct *tty, char ch); #define IS_CYC_Z(card) ((card).num_chips == -1) #define Z_FPGA_CHECK(card) \ - ((cy_readl(&((struct RUNTIME_9060 __iomem *) \ + ((readl(&((struct RUNTIME_9060 __iomem *) \ ((card).ctl_addr))->init_ctrl) & (1<<17)) != 0) -#define ISZLOADED(card) (((ZO_V1==cy_readl(&((struct RUNTIME_9060 __iomem *) \ +#define ISZLOADED(card) (((ZO_V1==readl(&((struct RUNTIME_9060 __iomem *) \ ((card).ctl_addr))->mail_box_0)) || \ Z_FPGA_CHECK(card)) && \ - (ZFIRM_ID==cy_readl(&((struct FIRM_ID __iomem *) \ + (ZFIRM_ID==readl(&((struct FIRM_ID __iomem *) \ ((card).base_addr+ID_ADDRESS))->signature))) #ifndef SERIAL_XMIT_SIZE @@ -725,8 +707,8 @@ static unsigned int cy_isa_addresses[] = { #define NR_ISA_ADDRS ARRAY_SIZE(cy_isa_addresses) #ifdef MODULE -static long maddr[NR_CARDS] = { 0, }; -static int irq[NR_CARDS] = { 0, }; +static long maddr[NR_CARDS]; +static int irq[NR_CARDS]; module_param_array(maddr, long, NULL, 0); module_param_array(irq, int, NULL, 0); @@ -739,11 +721,6 @@ module_param_array(irq, int, NULL, 0); */ static struct cyclades_card cy_card[NR_CARDS]; -/* This is the per-channel data structure containing pointers, flags - and variables for the port. This driver supports a maximum of NR_PORTS. -*/ -static struct cyclades_port cy_port[NR_PORTS]; - static int cy_next_channel; /* next minor available */ /* @@ -825,9 +802,6 @@ static int cy_chip_offset[] = { 0x0000, /* PCI related definitions */ -static unsigned short cy_pci_nboard; -static unsigned short cy_isa_nboard; -static unsigned short cy_nboard; #ifdef CONFIG_PCI static struct pci_device_id cy_pci_dev_id[] __devinitdata = { { PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_Y_Lo) }, /* PCI < 1Mb */ @@ -845,7 +819,7 @@ MODULE_DEVICE_TABLE(pci, cy_pci_dev_id); static void cy_start(struct tty_struct *); static void set_line_char(struct cyclades_port *); -static int cyz_issue_cmd(struct cyclades_card *, uclong, ucchar, uclong); +static int cyz_issue_cmd(struct cyclades_card *, __u32, __u8, __u32); #ifdef CONFIG_ISA static unsigned detect_isa_irq(void __iomem *); #endif /* CONFIG_ISA */ @@ -858,7 +832,6 @@ static void cyz_poll(unsigned long); /* The Cyclades-Z polling cycle is defined by this variable */ static long cyz_polling_cycle = CZ_DEF_POLL; -static int cyz_timeron = 0; static DEFINE_TIMER(cyz_timerlist, cyz_poll, 0, 0); #else /* CONFIG_CYZ_INTR */ @@ -871,21 +844,14 @@ static inline int serial_paranoia_check(struct cyclades_port *info, { #ifdef SERIAL_PARANOIA_CHECK if (!info) { - printk("cyc Warning: null cyclades_port for (%s) in %s\n", - name, routine); - return 1; - } - - if ((long)info < (long)(&cy_port[0]) || - (long)(&cy_port[NR_PORTS]) < (long)info) { - printk("cyc Warning: cyclades_port out of range for (%s) in " - "%s\n", name, routine); + printk(KERN_WARNING "cyc Warning: null cyclades_port for (%s) " + "in %s\n", name, routine); return 1; } if (info->magic != CYCLADES_MAGIC) { - printk("cyc Warning: bad magic number for serial struct (%s) " - "in %s\n", name, routine); + printk(KERN_WARNING "cyc Warning: bad magic number for serial " + "struct (%s) in %s\n", name, routine); return 1; } #endif @@ -943,22 +909,16 @@ do_softint(struct work_struct *work) if (test_and_clear_bit(Cy_EVENT_OPEN_WAKEUP, &info->event)) wake_up_interruptible(&info->open_wait); #ifdef CONFIG_CYZ_INTR - if (test_and_clear_bit(Cy_EVENT_Z_RX_FULL, &info->event)) { - if (cyz_rx_full_timer[info->line].function == NULL) { - cyz_rx_full_timer[info->line].expires = jiffies + 1; - cyz_rx_full_timer[info->line].function = cyz_rx_restart; - cyz_rx_full_timer[info->line].data = - (unsigned long)info; - add_timer(&cyz_rx_full_timer[info->line]); - } - } + if (test_and_clear_bit(Cy_EVENT_Z_RX_FULL, &info->event) && + !timer_pending(&cyz_rx_full_timer[info->line])) + mod_timer(&cyz_rx_full_timer[info->line], jiffies + 1); #endif if (test_and_clear_bit(Cy_EVENT_DELTA_WAKEUP, &info->event)) wake_up_interruptible(&info->delta_msr_wait); tty_wakeup(tty); #ifdef Z_WAKE if (test_and_clear_bit(Cy_EVENT_SHUTDOWN_WAKEUP, &info->event)) - wake_up_interruptible(&info->shutdown_wait); + complete(&info->shutdown_wait); #endif } /* do_softint */ @@ -975,11 +935,11 @@ do_softint(struct work_struct *work) */ static int cyy_issue_cmd(void __iomem * base_addr, u_char cmd, int index) { - volatile int i; + unsigned int i; /* Check to see that the previous command has completed */ for (i = 0; i < 100; i++) { - if (cy_readb(base_addr + (CyCCR << index)) == 0) { + if (readb(base_addr + (CyCCR << index)) == 0) { break; } udelay(10L); @@ -1022,7 +982,7 @@ static unsigned detect_isa_irq(void __iomem * address) cy_writeb(address + (CyCAR << index), 0); cy_writeb(address + (CySRER << index), - cy_readb(address + (CySRER << index)) | CyTxRdy); + readb(address + (CySRER << index)) | CyTxRdy); local_irq_restore(flags); /* Wait ... */ @@ -1032,11 +992,11 @@ static unsigned detect_isa_irq(void __iomem * address) irq = probe_irq_off(irqs); /* Clean up */ - save_xir = (u_char) cy_readb(address + (CyTIR << index)); - save_car = cy_readb(address + (CyCAR << index)); + save_xir = (u_char) readb(address + (CyTIR << index)); + save_car = readb(address + (CyCAR << index)); cy_writeb(address + (CyCAR << index), (save_xir & 0x3)); cy_writeb(address + (CySRER << index), - cy_readb(address + (CySRER << index)) & ~CyTxRdy); + readb(address + (CySRER << index)) & ~CyTxRdy); cy_writeb(address + (CyTIR << index), (save_xir & 0x3f)); cy_writeb(address + (CyCAR << index), (save_car)); cy_writeb(address + (Cy_ClrIntr << index), 0); @@ -1051,45 +1011,43 @@ static void cyy_intr_chip(struct cyclades_card *cinfo, int chip, { struct cyclades_port *info; struct tty_struct *tty; - volatile int char_count; - int i, j, len, mdm_change, mdm_status, outch; + int char_count; + int j, len, mdm_change, mdm_status, outch; int save_xir, channel, save_car; char data; if (status & CySRReceive) { /* reception interrupt */ #ifdef CY_DEBUG_INTERRUPTS - printk("cyy_interrupt: rcvd intr, chip %d\n\r", chip); + printk(KERN_DEBUG "cyy_interrupt: rcvd intr, chip %d\n", chip); #endif /* determine the channel & change to that context */ spin_lock(&cinfo->card_lock); - save_xir = (u_char) cy_readb(base_addr + (CyRIR << index)); + save_xir = (u_char) readb(base_addr + (CyRIR << index)); channel = (u_short) (save_xir & CyIRChannel); - i = channel + chip * 4 + cinfo->first_line; - info = &cy_port[i]; - info->last_active = jiffies; - save_car = cy_readb(base_addr + (CyCAR << index)); + info = &cinfo->ports[channel + chip * 4]; + save_car = readb(base_addr + (CyCAR << index)); cy_writeb(base_addr + (CyCAR << index), save_xir); /* if there is nowhere to put the data, discard it */ - if (info->tty == 0) { - j = (cy_readb(base_addr + (CyRIVR << index)) & + if (info->tty == NULL) { + j = (readb(base_addr + (CyRIVR << index)) & CyIVRMask); if (j == CyIVRRxEx) { /* exception */ - data = cy_readb(base_addr + (CyRDSR << index)); + data = readb(base_addr + (CyRDSR << index)); } else { /* normal character reception */ - char_count = cy_readb(base_addr + + char_count = readb(base_addr + (CyRDCR << index)); while (char_count--) { - data = cy_readb(base_addr + + data = readb(base_addr + (CyRDSR << index)); } } } else { /* there is an open port for this data */ tty = info->tty; - j = (cy_readb(base_addr + (CyRIVR << index)) & + j = (readb(base_addr + (CyRIVR << index)) & CyIVRMask); if (j == CyIVRRxEx) { /* exception */ - data = cy_readb(base_addr + (CyRDSR << index)); + data = readb(base_addr + (CyRDSR << index)); /* For statistics only */ if (data & CyBREAK) @@ -1110,7 +1068,7 @@ static void cyy_intr_chip(struct cyclades_card *cinfo, int chip, if (data & CyBREAK) { tty_insert_flip_char( tty, - cy_readb( + readb( base_addr + (CyRDSR << index)), @@ -1123,7 +1081,7 @@ static void cyy_intr_chip(struct cyclades_card *cinfo, int chip, } else if (data & CyFRAME) { tty_insert_flip_char( tty, - cy_readb( + readb( base_addr + (CyRDSR << index)), @@ -1135,7 +1093,7 @@ static void cyy_intr_chip(struct cyclades_card *cinfo, int chip, /* Pieces of seven... */ tty_insert_flip_char( tty, - cy_readb( + readb( base_addr + (CyRDSR << index)), @@ -1154,7 +1112,7 @@ static void cyy_intr_chip(struct cyclades_card *cinfo, int chip, */ tty_insert_flip_char( tty, - cy_readb( + readb( base_addr + (CyRDSR << index)), @@ -1186,7 +1144,7 @@ static void cyy_intr_chip(struct cyclades_card *cinfo, int chip, } } else { /* normal character reception */ /* load # chars available from the chip */ - char_count = cy_readb(base_addr + + char_count = readb(base_addr + (CyRDCR << index)); #ifdef CY_ENABLE_MONITORING @@ -1198,7 +1156,7 @@ static void cyy_intr_chip(struct cyclades_card *cinfo, int chip, #endif len = tty_buffer_request_room(tty, char_count); while (len--) { - data = cy_readb(base_addr + + data = readb(base_addr + (CyRDSR << index)); tty_insert_flip_char(tty, data, TTY_NORMAL); @@ -1223,29 +1181,27 @@ static void cyy_intr_chip(struct cyclades_card *cinfo, int chip, is empty, we know we can always stuff a dozen characters. */ #ifdef CY_DEBUG_INTERRUPTS - printk("cyy_interrupt: xmit intr, chip %d\n\r", chip); + printk(KERN_DEBUG "cyy_interrupt: xmit intr, chip %d\n", chip); #endif /* determine the channel & change to that context */ spin_lock(&cinfo->card_lock); - save_xir = (u_char) cy_readb(base_addr + (CyTIR << index)); + save_xir = (u_char) readb(base_addr + (CyTIR << index)); channel = (u_short) (save_xir & CyIRChannel); - i = channel + chip * 4 + cinfo->first_line; - save_car = cy_readb(base_addr + (CyCAR << index)); + save_car = readb(base_addr + (CyCAR << index)); cy_writeb(base_addr + (CyCAR << index), save_xir); /* validate the port# (as configured and open) */ - if ((i < 0) || (NR_PORTS <= i)) { + if (channel + chip * 4 >= cinfo->nports) { cy_writeb(base_addr + (CySRER << index), - cy_readb(base_addr + (CySRER << index)) & + readb(base_addr + (CySRER << index)) & ~CyTxRdy); goto txend; } - info = &cy_port[i]; - info->last_active = jiffies; - if (info->tty == 0) { + info = &cinfo->ports[channel + chip * 4]; + if (info->tty == NULL) { cy_writeb(base_addr + (CySRER << index), - cy_readb(base_addr + (CySRER << index)) & + readb(base_addr + (CySRER << index)) & ~CyTxRdy); goto txdone; } @@ -1278,29 +1234,29 @@ static void cyy_intr_chip(struct cyclades_card *cinfo, int chip, while (char_count-- > 0) { if (!info->xmit_cnt) { - if (cy_readb(base_addr + (CySRER << index)) & + if (readb(base_addr + (CySRER << index)) & CyTxMpty) { cy_writeb(base_addr + (CySRER << index), - cy_readb(base_addr + + readb(base_addr + (CySRER << index)) & ~CyTxMpty); } else { cy_writeb(base_addr + (CySRER << index), - (cy_readb(base_addr + + (readb(base_addr + (CySRER << index)) & ~CyTxRdy) | CyTxMpty); } goto txdone; } - if (info->xmit_buf == 0) { + if (info->xmit_buf == NULL) { cy_writeb(base_addr + (CySRER << index), - cy_readb(base_addr + (CySRER << index))& + readb(base_addr + (CySRER << index)) & ~CyTxRdy); goto txdone; } if (info->tty->stopped || info->tty->hw_stopped) { cy_writeb(base_addr + (CySRER << index), - cy_readb(base_addr + (CySRER << index))& + readb(base_addr + (CySRER << index)) & ~CyTxRdy); goto txdone; } @@ -1333,7 +1289,6 @@ static void cyy_intr_chip(struct cyclades_card *cinfo, int chip, 0); info->icount.tx++; char_count--; - } else { } } } @@ -1353,19 +1308,16 @@ txend: /* determine the channel & change to that context */ spin_lock(&cinfo->card_lock); - save_xir = (u_char) cy_readb(base_addr + (CyMIR << index)); + save_xir = (u_char) readb(base_addr + (CyMIR << index)); channel = (u_short) (save_xir & CyIRChannel); - info = &cy_port[channel + chip * 4 + cinfo->first_line]; - info->last_active = jiffies; - save_car = cy_readb(base_addr + (CyCAR << index)); + info = &cinfo->ports[channel + chip * 4]; + save_car = readb(base_addr + (CyCAR << index)); cy_writeb(base_addr + (CyCAR << index), save_xir); - mdm_change = cy_readb(base_addr + (CyMISR << index)); - mdm_status = cy_readb(base_addr + (CyMSVR1 << index)); + mdm_change = readb(base_addr + (CyMISR << index)); + mdm_status = readb(base_addr + (CyMSVR1 << index)); - if (info->tty == 0) { /* no place for data, ignore it */ - ; - } else { + if (info->tty) { if (mdm_change & CyANY_DELTA) { /* For statistics only */ if (mdm_change & CyDCD) @@ -1398,7 +1350,7 @@ txend: info->tty->hw_stopped = 0; cy_writeb(base_addr + (CySRER << index), - cy_readb(base_addr + + readb(base_addr + (CySRER << index))| CyTxRdy); @@ -1412,17 +1364,17 @@ txend: info->tty->hw_stopped = 1; cy_writeb(base_addr + (CySRER << index), - cy_readb(base_addr + + readb(base_addr + (CySRER << index)) & ~CyTxRdy); } } } - if (mdm_change & CyDSR) { +/* if (mdm_change & CyDSR) { } if (mdm_change & CyRI) { - } + }*/ } /* end of service */ cy_writeb(base_addr + (CyMIR << index), (save_xir & 0x3f)); @@ -1438,16 +1390,16 @@ txend: static irqreturn_t cyy_interrupt(int irq, void *dev_id) { int status; - struct cyclades_card *cinfo; + struct cyclades_card *cinfo = dev_id; void __iomem *base_addr, *card_base_addr; int chip; int index; int too_many; int had_work; - if ((cinfo = (struct cyclades_card *)dev_id) == 0) { + if (unlikely(cinfo == NULL)) { #ifdef CY_DEBUG_INTERRUPTS - printk("cyy_interrupt: spurious interrupt %d\n\r", irq); + printk(KERN_DEBUG "cyy_interrupt: spurious interrupt %d\n",irq); #endif return IRQ_NONE; /* spurious interrupt */ } @@ -1455,6 +1407,10 @@ static irqreturn_t cyy_interrupt(int irq, void *dev_id) card_base_addr = cinfo->base_addr; index = cinfo->bus_index; + /* card was not initialized yet (e.g. DEBUG_SHIRQ) */ + if (unlikely(card_base_addr == NULL)) + return IRQ_HANDLED; + /* This loop checks all chips in the card. Make a note whenever _any_ chip had some work to do, as this is considered an indication that there will be more to do. Only when no chip @@ -1466,7 +1422,7 @@ static irqreturn_t cyy_interrupt(int irq, void *dev_id) base_addr = cinfo->base_addr + (cy_chip_offset[chip] << index); too_many = 0; - while ((status = cy_readb(base_addr + + while ((status = readb(base_addr + (CySVRR << index))) != 0x00) { had_work++; /* The purpose of the following test is to ensure that @@ -1498,7 +1454,7 @@ static irqreturn_t cyy_interrupt(int irq, void *dev_id) static int cyz_fetch_msg(struct cyclades_card *cinfo, - uclong * channel, ucchar * cmd, uclong * param) + __u32 * channel, __u8 * cmd, __u32 * param) { struct FIRM_ID __iomem *firm_id; struct ZFW_CTRL __iomem *zfw_ctrl; @@ -1509,16 +1465,15 @@ cyz_fetch_msg(struct cyclades_card *cinfo, if (!ISZLOADED(*cinfo)) { return -1; } - zfw_ctrl = cinfo->base_addr + (cy_readl(&firm_id->zfwctrl_addr) & - 0xfffff); + zfw_ctrl = cinfo->base_addr + (readl(&firm_id->zfwctrl_addr) & 0xfffff); board_ctrl = &zfw_ctrl->board_ctrl; - loc_doorbell = cy_readl(&((struct RUNTIME_9060 __iomem *) + loc_doorbell = readl(&((struct RUNTIME_9060 __iomem *) (cinfo->ctl_addr))->loc_doorbell); if (loc_doorbell) { *cmd = (char)(0xff & loc_doorbell); - *channel = cy_readl(&board_ctrl->fwcmd_channel); - *param = (uclong) cy_readl(&board_ctrl->fwcmd_param); + *channel = readl(&board_ctrl->fwcmd_channel); + *param = (__u32) readl(&board_ctrl->fwcmd_param); cy_writel(&((struct RUNTIME_9060 __iomem *)(cinfo->ctl_addr))-> loc_doorbell, 0xffffffff); return 1; @@ -1528,28 +1483,27 @@ cyz_fetch_msg(struct cyclades_card *cinfo, static int cyz_issue_cmd(struct cyclades_card *cinfo, - uclong channel, ucchar cmd, uclong param) + __u32 channel, __u8 cmd, __u32 param) { struct FIRM_ID __iomem *firm_id; struct ZFW_CTRL __iomem *zfw_ctrl; struct BOARD_CTRL __iomem *board_ctrl; - unsigned long __iomem *pci_doorbell; + __u32 __iomem *pci_doorbell; int index; firm_id = cinfo->base_addr + ID_ADDRESS; if (!ISZLOADED(*cinfo)) { return -1; } - zfw_ctrl = cinfo->base_addr + (cy_readl(&firm_id->zfwctrl_addr) & - 0xfffff); + zfw_ctrl = cinfo->base_addr + (readl(&firm_id->zfwctrl_addr) & 0xfffff); board_ctrl = &zfw_ctrl->board_ctrl; index = 0; pci_doorbell = &((struct RUNTIME_9060 __iomem *)(cinfo->ctl_addr))->pci_doorbell; - while ((cy_readl(pci_doorbell) & 0xff) != 0) { + while ((readl(pci_doorbell) & 0xff) != 0) { if (index++ == 1000) { - return (int)(cy_readl(pci_doorbell) & 0xff); + return (int)(readl(pci_doorbell) & 0xff); } udelay(50L); } @@ -1561,34 +1515,30 @@ cyz_issue_cmd(struct cyclades_card *cinfo, } /* cyz_issue_cmd */ static void -cyz_handle_rx(struct cyclades_port *info, - volatile struct CH_CTRL __iomem * ch_ctrl, - volatile struct BUF_CTRL __iomem * buf_ctrl) +cyz_handle_rx(struct cyclades_port *info, struct CH_CTRL __iomem *ch_ctrl, + struct BUF_CTRL __iomem *buf_ctrl) { - struct cyclades_card *cinfo = &cy_card[info->card]; + struct cyclades_card *cinfo = info->card; struct tty_struct *tty = info->tty; - volatile int char_count; + int char_count; int len; #ifdef BLOCKMOVE - int small_count; + unsigned char *buf; #else char data; #endif - volatile uclong rx_put, rx_get, new_rx_get, rx_bufsize, rx_bufaddr; + __u32 rx_put, rx_get, new_rx_get, rx_bufsize, rx_bufaddr; - rx_get = new_rx_get = cy_readl(&buf_ctrl->rx_get); - rx_put = cy_readl(&buf_ctrl->rx_put); - rx_bufsize = cy_readl(&buf_ctrl->rx_bufsize); - rx_bufaddr = cy_readl(&buf_ctrl->rx_bufaddr); + rx_get = new_rx_get = readl(&buf_ctrl->rx_get); + rx_put = readl(&buf_ctrl->rx_put); + rx_bufsize = readl(&buf_ctrl->rx_bufsize); + rx_bufaddr = readl(&buf_ctrl->rx_bufaddr); if (rx_put >= rx_get) char_count = rx_put - rx_get; else char_count = rx_put - rx_get + rx_bufsize; if (char_count) { - info->last_active = jiffies; - info->jiffies[1] = jiffies; - #ifdef CY_ENABLE_MONITORING info->mon.int_count++; info->mon.char_count += char_count; @@ -1596,7 +1546,7 @@ cyz_handle_rx(struct cyclades_port *info, info->mon.char_max = char_count; info->mon.char_last = char_count; #endif - if (tty == 0) { + if (tty == NULL) { /* flush received characters */ new_rx_get = (new_rx_get + char_count) & (rx_bufsize - 1); @@ -1606,30 +1556,28 @@ cyz_handle_rx(struct cyclades_port *info, /* we'd like to use memcpy(t, f, n) and memset(s, c, count) for performance, but because of buffer boundaries, there may be several steps to the operation */ - while (0 < (small_count = min_t(unsigned int, - rx_bufsize - new_rx_get, - min_t(unsigned int, TTY_FLIPBUF_SIZE - - tty->flip.count, char_count)))){ - memcpy_fromio(tty->flip.char_buf_ptr, - (char *)(cinfo->base_addr + rx_bufaddr + - new_rx_get), - small_count); + while (1) { + len = tty_prepare_flip_string(tty, &buf, + char_count); + if (!len) + break; - tty->flip.char_buf_ptr += small_count; - memset(tty->flip.flag_buf_ptr, TTY_NORMAL, - small_count); - tty->flip.flag_buf_ptr += small_count; - new_rx_get = (new_rx_get + small_count) & + len = min_t(unsigned int, min(len, char_count), + rx_bufsize - new_rx_get); + + memcpy_fromio(buf, cinfo->base_addr + + rx_bufaddr + new_rx_get, len); + + new_rx_get = (new_rx_get + len) & (rx_bufsize - 1); - char_count -= small_count; - info->icount.rx += small_count; - info->idle_stats.recv_bytes += small_count; - tty->flip.count += small_count; + char_count -= len; + info->icount.rx += len; + info->idle_stats.recv_bytes += len; } #else len = tty_buffer_request_room(tty, char_count); while (len--) { - data = cy_readb(cinfo->base_addr + rx_bufaddr + + data = readb(cinfo->base_addr + rx_bufaddr + new_rx_get); new_rx_get = (new_rx_get + 1)& (rx_bufsize - 1); tty_insert_flip_char(tty, data, TTY_NORMAL); @@ -1640,13 +1588,12 @@ cyz_handle_rx(struct cyclades_port *info, #ifdef CONFIG_CYZ_INTR /* Recalculate the number of chars in the RX buffer and issue a cmd in case it's higher than the RX high water mark */ - rx_put = cy_readl(&buf_ctrl->rx_put); + rx_put = readl(&buf_ctrl->rx_put); if (rx_put >= rx_get) char_count = rx_put - rx_get; else char_count = rx_put - rx_get + rx_bufsize; - if (char_count >= (int)cy_readl(&buf_ctrl-> - rx_threshold)) { + if (char_count >= (int)readl(&buf_ctrl->rx_threshold)) { cy_sched_event(info, Cy_EVENT_Z_RX_FULL); } #endif @@ -1659,26 +1606,25 @@ cyz_handle_rx(struct cyclades_port *info, } static void -cyz_handle_tx(struct cyclades_port *info, - volatile struct CH_CTRL __iomem * ch_ctrl, - volatile struct BUF_CTRL __iomem * buf_ctrl) +cyz_handle_tx(struct cyclades_port *info, struct CH_CTRL __iomem *ch_ctrl, + struct BUF_CTRL __iomem *buf_ctrl) { - struct cyclades_card *cinfo = &cy_card[info->card]; + struct cyclades_card *cinfo = info->card; struct tty_struct *tty = info->tty; char data; - volatile int char_count; + int char_count; #ifdef BLOCKMOVE int small_count; #endif - volatile uclong tx_put, tx_get, tx_bufsize, tx_bufaddr; + __u32 tx_put, tx_get, tx_bufsize, tx_bufaddr; if (info->xmit_cnt <= 0) /* Nothing to transmit */ return; - tx_get = cy_readl(&buf_ctrl->tx_get); - tx_put = cy_readl(&buf_ctrl->tx_put); - tx_bufsize = cy_readl(&buf_ctrl->tx_bufsize); - tx_bufaddr = cy_readl(&buf_ctrl->tx_bufaddr); + tx_get = readl(&buf_ctrl->tx_get); + tx_put = readl(&buf_ctrl->tx_put); + tx_bufsize = readl(&buf_ctrl->tx_bufsize); + tx_bufaddr = readl(&buf_ctrl->tx_bufaddr); if (tx_put >= tx_get) char_count = tx_get - tx_put - 1 + tx_bufsize; else @@ -1686,9 +1632,8 @@ cyz_handle_tx(struct cyclades_port *info, if (char_count) { - if (tty == 0) { + if (tty == NULL) goto ztxdone; - } if (info->x_char) { /* send special char */ data = info->x_char; @@ -1698,8 +1643,6 @@ cyz_handle_tx(struct cyclades_port *info, info->x_char = 0; char_count--; info->icount.tx++; - info->last_active = jiffies; - info->jiffies[2] = jiffies; } #ifdef BLOCKMOVE while (0 < (small_count = min_t(unsigned int, @@ -1719,8 +1662,6 @@ cyz_handle_tx(struct cyclades_port *info, info->xmit_cnt -= small_count; info->xmit_tail = (info->xmit_tail + small_count) & (SERIAL_XMIT_SIZE - 1); - info->last_active = jiffies; - info->jiffies[2] = jiffies; } #else while (info->xmit_cnt && char_count) { @@ -1733,8 +1674,6 @@ cyz_handle_tx(struct cyclades_port *info, tx_put = (tx_put + 1) & (tx_bufsize - 1); char_count--; info->icount.tx++; - info->last_active = jiffies; - info->jiffies[2] = jiffies; } #endif ztxdone: @@ -1750,33 +1689,32 @@ static void cyz_handle_cmd(struct cyclades_card *cinfo) { struct tty_struct *tty; struct cyclades_port *info; - static volatile struct FIRM_ID __iomem *firm_id; - static volatile struct ZFW_CTRL __iomem *zfw_ctrl; - static volatile struct BOARD_CTRL __iomem *board_ctrl; - static volatile struct CH_CTRL __iomem *ch_ctrl; - static volatile struct BUF_CTRL __iomem *buf_ctrl; - uclong channel; - ucchar cmd; - uclong param; - uclong hw_ver, fw_ver; + static struct FIRM_ID __iomem *firm_id; + static struct ZFW_CTRL __iomem *zfw_ctrl; + static struct BOARD_CTRL __iomem *board_ctrl; + static struct CH_CTRL __iomem *ch_ctrl; + static struct BUF_CTRL __iomem *buf_ctrl; + __u32 channel; + __u8 cmd; + __u32 param; + __u32 hw_ver, fw_ver; int special_count; int delta_count; firm_id = cinfo->base_addr + ID_ADDRESS; - zfw_ctrl = cinfo->base_addr + (cy_readl(&firm_id->zfwctrl_addr) & - 0xfffff); + zfw_ctrl = cinfo->base_addr + (readl(&firm_id->zfwctrl_addr) & 0xfffff); board_ctrl = &zfw_ctrl->board_ctrl; - fw_ver = cy_readl(&board_ctrl->fw_version); - hw_ver = cy_readl(&((struct RUNTIME_9060 __iomem *)(cinfo->ctl_addr))-> + fw_ver = readl(&board_ctrl->fw_version); + hw_ver = readl(&((struct RUNTIME_9060 __iomem *)(cinfo->ctl_addr))-> mail_box_0); while (cyz_fetch_msg(cinfo, &channel, &cmd, ¶m) == 1) { special_count = 0; delta_count = 0; - info = &cy_port[channel + cinfo->first_line]; - if ((tty = info->tty) == 0) { + info = &cinfo->ports[channel]; + if ((tty = info->tty) == NULL) continue; - } + ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]); buf_ctrl = &(zfw_ctrl->buf_ctrl[channel]); @@ -1801,7 +1739,7 @@ static void cyz_handle_cmd(struct cyclades_card *cinfo) delta_count++; if (info->flags & ASYNC_CHECK_CD) { if ((fw_ver > 241 ? ((u_long) param) : - cy_readl(&ch_ctrl->rs_status)) & + readl(&ch_ctrl->rs_status)) & C_RS_DCD) { cy_sched_event(info, Cy_EVENT_OPEN_WAKEUP); @@ -1833,8 +1771,8 @@ static void cyz_handle_cmd(struct cyclades_card *cinfo) case C_CM_INTBACK2: /* Reception Interrupt */ #ifdef CY_DEBUG_INTERRUPTS - printk("cyz_interrupt: rcvd intr, card %d, " - "port %ld\n\r", info->card, channel); + printk(KERN_DEBUG "cyz_interrupt: rcvd intr, card %d, " + "port %ld\n", info->card, channel); #endif cyz_handle_rx(info, ch_ctrl, buf_ctrl); break; @@ -1843,8 +1781,8 @@ static void cyz_handle_cmd(struct cyclades_card *cinfo) case C_CM_INTBACK: /* Transmission Interrupt */ #ifdef CY_DEBUG_INTERRUPTS - printk("cyz_interrupt: xmit intr, card %d, " - "port %ld\n\r", info->card, channel); + printk(KERN_DEBUG "cyz_interrupt: xmit intr, card %d, " + "port %ld\n", info->card, channel); #endif cyz_handle_tx(info, ch_ctrl, buf_ctrl); break; @@ -1865,18 +1803,19 @@ static void cyz_handle_cmd(struct cyclades_card *cinfo) #ifdef CONFIG_CYZ_INTR static irqreturn_t cyz_interrupt(int irq, void *dev_id) { - struct cyclades_card *cinfo; + struct cyclades_card *cinfo = dev_id; - if ((cinfo = (struct cyclades_card *)dev_id) == 0) { + if (unlikely(cinfo == NULL)) { #ifdef CY_DEBUG_INTERRUPTS - printk("cyz_interrupt: spurious interrupt %d\n\r", irq); + printk(KERN_DEBUG "cyz_interrupt: spurious interrupt %d\n",irq); #endif return IRQ_NONE; /* spurious interrupt */ } - if (!ISZLOADED(*cinfo)) { + if (unlikely(!ISZLOADED(*cinfo))) { #ifdef CY_DEBUG_INTERRUPTS - printk("cyz_interrupt: board not yet loaded (IRQ%d).\n\r", irq); + printk(KERN_DEBUG "cyz_interrupt: board not yet loaded " + "(IRQ%d).\n", irq); #endif return IRQ_NONE; } @@ -1890,19 +1829,18 @@ static irqreturn_t cyz_interrupt(int irq, void *dev_id) static void cyz_rx_restart(unsigned long arg) { struct cyclades_port *info = (struct cyclades_port *)arg; + struct cyclades_card *card = info->card; int retval; - int card = info->card; - uclong channel = (info->line) - (cy_card[card].first_line); + __u32 channel = info->line - card->first_line; unsigned long flags; - CY_LOCK(info, flags); - retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_INTBACK2, 0L); + spin_lock_irqsave(&card->card_lock, flags); + retval = cyz_issue_cmd(card, channel, C_CM_INTBACK2, 0L); if (retval != 0) { - printk("cyc:cyz_rx_restart retval on ttyC%d was %x\n", + printk(KERN_ERR "cyc:cyz_rx_restart retval on ttyC%d was %x\n", info->line, retval); } - cyz_rx_full_timer[info->line].function = NULL; - CY_UNLOCK(info, flags); + spin_unlock_irqrestore(&card->card_lock, flags); } #else /* CONFIG_CYZ_INTR */ @@ -1912,14 +1850,14 @@ static void cyz_poll(unsigned long arg) struct cyclades_card *cinfo; struct cyclades_port *info; struct tty_struct *tty; - static volatile struct FIRM_ID *firm_id; - static volatile struct ZFW_CTRL *zfw_ctrl; - static volatile struct BOARD_CTRL *board_ctrl; - static volatile struct CH_CTRL *ch_ctrl; - static volatile struct BUF_CTRL *buf_ctrl; + static struct FIRM_ID *firm_id; + static struct ZFW_CTRL *zfw_ctrl; + static struct BOARD_CTRL *board_ctrl; + static struct CH_CTRL *ch_ctrl; + static struct BUF_CTRL *buf_ctrl; + unsigned long expires = jiffies + HZ; int card, port; - cyz_timerlist.expires = jiffies + (HZ); for (card = 0; card < NR_CARDS; card++) { cinfo = &cy_card[card]; @@ -1930,12 +1868,12 @@ static void cyz_poll(unsigned long arg) firm_id = cinfo->base_addr + ID_ADDRESS; zfw_ctrl = cinfo->base_addr + - (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff); + (readl(&firm_id->zfwctrl_addr) & 0xfffff); board_ctrl = &(zfw_ctrl->board_ctrl); /* Skip first polling cycle to avoid racing conditions with the FW */ if (!cinfo->intr_enabled) { - cinfo->nports = (int)cy_readl(&board_ctrl->n_channel); + cinfo->nports = (int)readl(&board_ctrl->n_channel); cinfo->intr_enabled = 1; continue; } @@ -1943,7 +1881,7 @@ static void cyz_poll(unsigned long arg) cyz_handle_cmd(cinfo); for (port = 0; port < cinfo->nports; port++) { - info = &cy_port[port + cinfo->first_line]; + info = &cinfo->ports[port]; tty = info->tty; ch_ctrl = &(zfw_ctrl->ch_ctrl[port]); buf_ctrl = &(zfw_ctrl->buf_ctrl[port]); @@ -1953,9 +1891,9 @@ static void cyz_poll(unsigned long arg) cyz_handle_tx(info, ch_ctrl, buf_ctrl); } /* poll every 'cyz_polling_cycle' period */ - cyz_timerlist.expires = jiffies + cyz_polling_cycle; + expires = jiffies + cyz_polling_cycle; } - add_timer(&cyz_timerlist); + mod_timer(&cyz_timerlist, expires); } /* cyz_poll */ #endif /* CONFIG_CYZ_INTR */ @@ -1968,20 +1906,21 @@ static void cyz_poll(unsigned long arg) */ static int startup(struct cyclades_port *info) { + struct cyclades_card *card; unsigned long flags; int retval = 0; void __iomem *base_addr; - int card, chip, channel, index; + int chip, channel, index; unsigned long page; card = info->card; - channel = (info->line) - (cy_card[card].first_line); + channel = info->line - card->first_line; page = get_zeroed_page(GFP_KERNEL); if (!page) return -ENOMEM; - CY_LOCK(info, flags); + spin_lock_irqsave(&card->card_lock, flags); if (info->flags & ASYNC_INITIALIZED) { free_page(page); @@ -2001,24 +1940,22 @@ static int startup(struct cyclades_port *info) else info->xmit_buf = (unsigned char *)page; - CY_UNLOCK(info, flags); + spin_unlock_irqrestore(&card->card_lock, flags); set_line_char(info); - if (!IS_CYC_Z(cy_card[card])) { + if (!IS_CYC_Z(*card)) { chip = channel >> 2; channel &= 0x03; - index = cy_card[card].bus_index; - base_addr = cy_card[card].base_addr + - (cy_chip_offset[chip] << index); + index = card->bus_index; + base_addr = card->base_addr + (cy_chip_offset[chip] << index); #ifdef CY_DEBUG_OPEN - printk("cyc startup card %d, chip %d, channel %d, " - "base_addr %lx\n", - card, chip, channel, (long)base_addr); - /**/ + printk(KERN_DEBUG "cyc startup card %d, chip %d, channel %d, " + "base_addr %p\n", + card, chip, channel, base_addr); #endif - CY_LOCK(info, flags); + spin_lock_irqsave(&card->card_lock, flags); cy_writeb(base_addr + (CyCAR << index), (u_char) channel); @@ -2034,14 +1971,14 @@ static int startup(struct cyclades_port *info) cy_writeb(base_addr + (CyMSVR2 << index), CyDTR); #ifdef CY_DEBUG_DTR - printk("cyc:startup raising DTR\n"); - printk(" status: 0x%x, 0x%x\n", - cy_readb(base_addr + (CyMSVR1 << index)), - cy_readb(base_addr + (CyMSVR2 << index))); + printk(KERN_DEBUG "cyc:startup raising DTR\n"); + printk(KERN_DEBUG " status: 0x%x, 0x%x\n", + readb(base_addr + (CyMSVR1 << index)), + readb(base_addr + (CyMSVR2 << index))); #endif cy_writeb(base_addr + (CySRER << index), - cy_readb(base_addr + (CySRER << index)) | CyRxData); + readb(base_addr + (CySRER << index)) | CyRxData); info->flags |= ASYNC_INITIALIZED; if (info->tty) { @@ -2054,7 +1991,7 @@ static int startup(struct cyclades_port *info) info->idle_stats.recv_idle = info->idle_stats.xmit_idle = jiffies; - CY_UNLOCK(info, flags); + spin_unlock_irqrestore(&card->card_lock, flags); } else { struct FIRM_ID __iomem *firm_id; @@ -2063,24 +2000,23 @@ static int startup(struct cyclades_port *info) struct CH_CTRL __iomem *ch_ctrl; int retval; - base_addr = cy_card[card].base_addr; + base_addr = card->base_addr; firm_id = base_addr + ID_ADDRESS; - if (!ISZLOADED(cy_card[card])) { + if (!ISZLOADED(*card)) { return -ENODEV; } - zfw_ctrl = cy_card[card].base_addr + - (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff); + zfw_ctrl = card->base_addr + + (readl(&firm_id->zfwctrl_addr) & 0xfffff); board_ctrl = &zfw_ctrl->board_ctrl; ch_ctrl = zfw_ctrl->ch_ctrl; #ifdef CY_DEBUG_OPEN - printk("cyc startup Z card %d, channel %d, base_addr %lx\n", - card, channel, (long)base_addr); - /**/ + printk(KERN_DEBUG "cyc startup Z card %d, channel %d, " + "base_addr %p\n", card, channel, base_addr); #endif - CY_LOCK(info, flags); + spin_lock_irqsave(&card->card_lock, flags); cy_writel(&ch_ctrl[channel].op_mode, C_CH_ENABLE); #ifdef Z_WAKE @@ -2102,33 +2038,31 @@ static int startup(struct cyclades_port *info) #endif /* CONFIG_CYZ_INTR */ #endif /* Z_WAKE */ - retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_IOCTL, 0L); + retval = cyz_issue_cmd(card, channel, C_CM_IOCTL, 0L); if (retval != 0) { - printk("cyc:startup(1) retval on ttyC%d was %x\n", - info->line, retval); + printk(KERN_ERR "cyc:startup(1) retval on ttyC%d was " + "%x\n", info->line, retval); } /* Flush RX buffers before raising DTR and RTS */ - retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_FLUSH_RX, - 0L); + retval = cyz_issue_cmd(card, channel, C_CM_FLUSH_RX, 0L); if (retval != 0) { - printk("cyc:startup(2) retval on ttyC%d was %x\n", - info->line, retval); + printk(KERN_ERR "cyc:startup(2) retval on ttyC%d was " + "%x\n", info->line, retval); } /* set timeout !!! */ /* set RTS and DTR !!! */ cy_writel(&ch_ctrl[channel].rs_control, - cy_readl(&ch_ctrl[channel].rs_control) | C_RS_RTS | + readl(&ch_ctrl[channel].rs_control) | C_RS_RTS | C_RS_DTR); - retval = cyz_issue_cmd(&cy_card[info->card], channel, - C_CM_IOCTLM, 0L); + retval = cyz_issue_cmd(card, channel, C_CM_IOCTLM, 0L); if (retval != 0) { - printk("cyc:startup(3) retval on ttyC%d was %x\n", - info->line, retval); + printk(KERN_ERR "cyc:startup(3) retval on ttyC%d was " + "%x\n", info->line, retval); } #ifdef CY_DEBUG_DTR - printk("cyc:startup raising Z DTR\n"); + printk(KERN_DEBUG "cyc:startup raising Z DTR\n"); #endif /* enable send, recv, modem !!! */ @@ -2144,51 +2078,50 @@ static int startup(struct cyclades_port *info) info->idle_stats.recv_idle = info->idle_stats.xmit_idle = jiffies; - CY_UNLOCK(info, flags); + spin_unlock_irqrestore(&card->card_lock, flags); } #ifdef CY_DEBUG_OPEN - printk(" cyc startup done\n"); + printk(KERN_DEBUG "cyc startup done\n"); #endif return 0; errout: - CY_UNLOCK(info, flags); + spin_unlock_irqrestore(&card->card_lock, flags); return retval; } /* startup */ static void start_xmit(struct cyclades_port *info) { + struct cyclades_card *card; unsigned long flags; void __iomem *base_addr; - int card, chip, channel, index; + int chip, channel, index; card = info->card; - channel = (info->line) - (cy_card[card].first_line); - if (!IS_CYC_Z(cy_card[card])) { + channel = info->line - card->first_line; + if (!IS_CYC_Z(*card)) { chip = channel >> 2; channel &= 0x03; - index = cy_card[card].bus_index; - base_addr = cy_card[card].base_addr + - (cy_chip_offset[chip] << index); + index = card->bus_index; + base_addr = card->base_addr + (cy_chip_offset[chip] << index); - CY_LOCK(info, flags); + spin_lock_irqsave(&card->card_lock, flags); cy_writeb(base_addr + (CyCAR << index), channel); cy_writeb(base_addr + (CySRER << index), - cy_readb(base_addr + (CySRER << index)) | CyTxRdy); - CY_UNLOCK(info, flags); + readb(base_addr + (CySRER << index)) | CyTxRdy); + spin_unlock_irqrestore(&card->card_lock, flags); } else { #ifdef CONFIG_CYZ_INTR int retval; - CY_LOCK(info, flags); - retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_INTBACK, - 0L); + spin_lock_irqsave(&card->card_lock, flags); + retval = cyz_issue_cmd(card, channel, C_CM_INTBACK, 0L); if (retval != 0) { - printk("cyc:start_xmit retval on ttyC%d was %x\n", - info->line, retval); + printk(KERN_ERR "cyc:start_xmit retval on ttyC%d was " + "%x\n", info->line, retval); } - CY_UNLOCK(info, flags); + spin_unlock_irqrestore(&card->card_lock, flags); #else /* CONFIG_CYZ_INTR */ /* Don't have to do anything at this time */ #endif /* CONFIG_CYZ_INTR */ @@ -2201,30 +2134,30 @@ static void start_xmit(struct cyclades_port *info) */ static void shutdown(struct cyclades_port *info) { + struct cyclades_card *card; unsigned long flags; void __iomem *base_addr; - int card, chip, channel, index; + int chip, channel, index; if (!(info->flags & ASYNC_INITIALIZED)) { return; } card = info->card; - channel = info->line - cy_card[card].first_line; - if (!IS_CYC_Z(cy_card[card])) { + channel = info->line - card->first_line; + if (!IS_CYC_Z(*card)) { chip = channel >> 2; channel &= 0x03; - index = cy_card[card].bus_index; - base_addr = cy_card[card].base_addr + - (cy_chip_offset[chip] << index); + index = card->bus_index; + base_addr = card->base_addr + (cy_chip_offset[chip] << index); #ifdef CY_DEBUG_OPEN - printk("cyc shutdown Y card %d, chip %d, channel %d, " - "base_addr %lx\n", - card, chip, channel, (long)base_addr); + printk(KERN_DEBUG "cyc shutdown Y card %d, chip %d, " + "channel %d, base_addr %p\n", + card, chip, channel, base_addr); #endif - CY_LOCK(info, flags); + spin_lock_irqsave(&card->card_lock, flags); /* Clear delta_msr_wait queue to avoid mem leaks. */ wake_up_interruptible(&info->delta_msr_wait); @@ -2240,10 +2173,10 @@ static void shutdown(struct cyclades_port *info) cy_writeb(base_addr + (CyMSVR1 << index), ~CyRTS); cy_writeb(base_addr + (CyMSVR2 << index), ~CyDTR); #ifdef CY_DEBUG_DTR - printk("cyc shutdown dropping DTR\n"); - printk(" status: 0x%x, 0x%x\n", - cy_readb(base_addr + (CyMSVR1 << index)), - cy_readb(base_addr + (CyMSVR2 << index))); + printk(KERN_DEBUG "cyc shutdown dropping DTR\n"); + printk(KERN_DEBUG " status: 0x%x, 0x%x\n", + readb(base_addr + (CyMSVR1 << index)), + readb(base_addr + (CyMSVR2 << index))); #endif } cyy_issue_cmd(base_addr, CyCHAN_CTL | CyDIS_RCVR, index); @@ -2254,7 +2187,7 @@ static void shutdown(struct cyclades_port *info) set_bit(TTY_IO_ERROR, &info->tty->flags); } info->flags &= ~ASYNC_INITIALIZED; - CY_UNLOCK(info, flags); + spin_unlock_irqrestore(&card->card_lock, flags); } else { struct FIRM_ID __iomem *firm_id; struct ZFW_CTRL __iomem *zfw_ctrl; @@ -2262,23 +2195,23 @@ static void shutdown(struct cyclades_port *info) struct CH_CTRL __iomem *ch_ctrl; int retval; - base_addr = cy_card[card].base_addr; + base_addr = card->base_addr; #ifdef CY_DEBUG_OPEN - printk("cyc shutdown Z card %d, channel %d, base_addr %lx\n", - card, channel, (long)base_addr); + printk(KERN_DEBUG "cyc shutdown Z card %d, channel %d, " + "base_addr %p\n", card, channel, base_addr); #endif firm_id = base_addr + ID_ADDRESS; - if (!ISZLOADED(cy_card[card])) { + if (!ISZLOADED(*card)) { return; } - zfw_ctrl = cy_card[card].base_addr + - (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff); + zfw_ctrl = card->base_addr + + (readl(&firm_id->zfwctrl_addr) & 0xfffff); board_ctrl = &zfw_ctrl->board_ctrl; ch_ctrl = zfw_ctrl->ch_ctrl; - CY_LOCK(info, flags); + spin_lock_irqsave(&card->card_lock, flags); if (info->xmit_buf) { unsigned char *temp; @@ -2289,16 +2222,16 @@ static void shutdown(struct cyclades_port *info) if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) { cy_writel(&ch_ctrl[channel].rs_control, - (uclong)(cy_readl(&ch_ctrl[channel].rs_control)& + (__u32)(readl(&ch_ctrl[channel].rs_control) & ~(C_RS_RTS | C_RS_DTR))); - retval = cyz_issue_cmd(&cy_card[info->card], channel, + retval = cyz_issue_cmd(info->card, channel, C_CM_IOCTLM, 0L); if (retval != 0) { - printk("cyc:shutdown retval on ttyC%d was %x\n", - info->line, retval); + printk(KERN_ERR"cyc:shutdown retval on ttyC%d " + "was %x\n", info->line, retval); } #ifdef CY_DEBUG_DTR - printk("cyc:shutdown dropping Z DTR\n"); + printk(KERN_DEBUG "cyc:shutdown dropping Z DTR\n"); #endif } @@ -2307,11 +2240,11 @@ static void shutdown(struct cyclades_port *info) } info->flags &= ~ASYNC_INITIALIZED; - CY_UNLOCK(info, flags); + spin_unlock_irqrestore(&card->card_lock, flags); } #ifdef CY_DEBUG_OPEN - printk(" cyc shutdown done\n"); + printk(KERN_DEBUG "cyc shutdown done\n"); #endif } /* shutdown */ @@ -2332,7 +2265,7 @@ block_til_ready(struct tty_struct *tty, struct file *filp, int retval; void __iomem *base_addr; - cinfo = &cy_card[info->card]; + cinfo = info->card; channel = info->line - cinfo->first_line; /* @@ -2340,9 +2273,8 @@ block_til_ready(struct tty_struct *tty, struct file *filp, * until it's done, and then try again. */ if (tty_hung_up_p(filp) || (info->flags & ASYNC_CLOSING)) { - if (info->flags & ASYNC_CLOSING) { - interruptible_sleep_on(&info->close_wait); - } + wait_event_interruptible(info->close_wait, + !(info->flags & ASYNC_CLOSING)); return (info->flags & ASYNC_HUP_NOTIFY) ? -EAGAIN: -ERESTARTSYS; } @@ -2365,17 +2297,16 @@ block_til_ready(struct tty_struct *tty, struct file *filp, retval = 0; add_wait_queue(&info->open_wait, &wait); #ifdef CY_DEBUG_OPEN - printk("cyc block_til_ready before block: ttyC%d, count = %d\n", - info->line, info->count); - /**/ + printk(KERN_DEBUG "cyc block_til_ready before block: ttyC%d, " + "count = %d\n", info->line, info->count); #endif - CY_LOCK(info, flags); + spin_lock_irqsave(&cinfo->card_lock, flags); if (!tty_hung_up_p(filp)) info->count--; - CY_UNLOCK(info, flags); + spin_unlock_irqrestore(&cinfo->card_lock, flags); #ifdef CY_DEBUG_COUNT - printk("cyc block_til_ready: (%d): decrementing count to %d\n", - current->pid, info->count); + printk(KERN_DEBUG "cyc block_til_ready: (%d): decrementing count to " + "%d\n", current->pid, info->count); #endif info->blocked_open++; @@ -2386,7 +2317,7 @@ block_til_ready(struct tty_struct *tty, struct file *filp, base_addr = cinfo->base_addr + (cy_chip_offset[chip] << index); while (1) { - CY_LOCK(info, flags); + spin_lock_irqsave(&cinfo->card_lock, flags); if ((tty->termios->c_cflag & CBAUD)) { cy_writeb(base_addr + (CyCAR << index), (u_char) channel); @@ -2395,15 +2326,14 @@ block_til_ready(struct tty_struct *tty, struct file *filp, cy_writeb(base_addr + (CyMSVR2 << index), CyDTR); #ifdef CY_DEBUG_DTR - printk("cyc:block_til_ready raising DTR\n"); - printk(" status: 0x%x, 0x%x\n", - cy_readb(base_addr + - (CyMSVR1 << index)), - cy_readb(base_addr + - (CyMSVR2 << index))); + printk(KERN_DEBUG "cyc:block_til_ready raising " + "DTR\n"); + printk(KERN_DEBUG " status: 0x%x, 0x%x\n", + readb(base_addr + (CyMSVR1 << index)), + readb(base_addr + (CyMSVR2 << index))); #endif } - CY_UNLOCK(info, flags); + spin_unlock_irqrestore(&cinfo->card_lock, flags); set_current_state(TASK_INTERRUPTIBLE); if (tty_hung_up_p(filp) || @@ -2413,26 +2343,25 @@ block_til_ready(struct tty_struct *tty, struct file *filp, break; } - CY_LOCK(info, flags); + spin_lock_irqsave(&cinfo->card_lock, flags); cy_writeb(base_addr + (CyCAR << index), (u_char) channel); if (!(info->flags & ASYNC_CLOSING) && (C_CLOCAL(tty) || - (cy_readb(base_addr + + (readb(base_addr + (CyMSVR1 << index)) & CyDCD))) { - CY_UNLOCK(info, flags); + spin_unlock_irqrestore(&cinfo->card_lock, flags); break; } - CY_UNLOCK(info, flags); + spin_unlock_irqrestore(&cinfo->card_lock, flags); if (signal_pending(current)) { retval = -ERESTARTSYS; break; } #ifdef CY_DEBUG_OPEN - printk("cyc block_til_ready blocking: ttyC%d, " - "count = %d\n", - info->line, info->count); - /**/ + printk(KERN_DEBUG "cyc block_til_ready blocking: " + "ttyC%d, count = %d\n", + info->line, info->count); #endif schedule(); } @@ -2446,31 +2375,30 @@ block_til_ready(struct tty_struct *tty, struct file *filp, base_addr = cinfo->base_addr; firm_id = base_addr + ID_ADDRESS; if (!ISZLOADED(*cinfo)) { - current->state = TASK_RUNNING; + __set_current_state(TASK_RUNNING); remove_wait_queue(&info->open_wait, &wait); return -EINVAL; } - zfw_ctrl = base_addr + (cy_readl(&firm_id->zfwctrl_addr) & - 0xfffff); + zfw_ctrl = base_addr + (readl(&firm_id->zfwctrl_addr)& 0xfffff); board_ctrl = &zfw_ctrl->board_ctrl; ch_ctrl = zfw_ctrl->ch_ctrl; while (1) { if ((tty->termios->c_cflag & CBAUD)) { cy_writel(&ch_ctrl[channel].rs_control, - cy_readl(&ch_ctrl[channel]. - rs_control) | (C_RS_RTS | - C_RS_DTR)); - retval = cyz_issue_cmd(&cy_card[info->card], - channel, C_CM_IOCTLM, 0L); + readl(&ch_ctrl[channel].rs_control) | + C_RS_RTS | C_RS_DTR); + retval = cyz_issue_cmd(cinfo, + channel, C_CM_IOCTLM, 0L); if (retval != 0) { - printk("cyc:block_til_ready retval on " - "ttyC%d was %x\n", + printk(KERN_ERR "cyc:block_til_ready " + "retval on ttyC%d was %x\n", info->line, retval); } #ifdef CY_DEBUG_DTR - printk("cyc:block_til_ready raising Z DTR\n"); + printk(KERN_DEBUG "cyc:block_til_ready raising " + "Z DTR\n"); #endif } @@ -2482,7 +2410,7 @@ block_til_ready(struct tty_struct *tty, struct file *filp, break; } if (!(info->flags & ASYNC_CLOSING) && (C_CLOCAL(tty) || - (cy_readl(&ch_ctrl[channel].rs_status) & + (readl(&ch_ctrl[channel].rs_status) & C_RS_DCD))) { break; } @@ -2491,28 +2419,26 @@ block_til_ready(struct tty_struct *tty, struct file *filp, break; } #ifdef CY_DEBUG_OPEN - printk("cyc block_til_ready blocking: ttyC%d, " - "count = %d\n", - info->line, info->count); - /**/ + printk(KERN_DEBUG "cyc block_til_ready blocking: " + "ttyC%d, count = %d\n", + info->line, info->count); #endif schedule(); } } - current->state = TASK_RUNNING; + __set_current_state(TASK_RUNNING); remove_wait_queue(&info->open_wait, &wait); if (!tty_hung_up_p(filp)) { info->count++; #ifdef CY_DEBUG_COUNT - printk("cyc:block_til_ready (%d): incrementing count to %d\n", - current->pid, info->count); + printk(KERN_DEBUG "cyc:block_til_ready (%d): incrementing " + "count to %d\n", current->pid, info->count); #endif } info->blocked_open--; #ifdef CY_DEBUG_OPEN - printk("cyc:block_til_ready after blocking: ttyC%d, count = %d\n", - info->line, info->count); - /**/ + printk(KERN_DEBUG "cyc:block_til_ready after blocking: ttyC%d, " + "count = %d\n", info->line, info->count); #endif if (retval) return retval; @@ -2527,13 +2453,20 @@ block_til_ready(struct tty_struct *tty, struct file *filp, static int cy_open(struct tty_struct *tty, struct file *filp) { struct cyclades_port *info; + unsigned int i; int retval, line; line = tty->index; if ((line < 0) || (NR_PORTS <= line)) { return -ENODEV; } - info = &cy_port[line]; + for (i = 0; i < NR_CARDS; i++) + if (line < cy_card[i].first_line + cy_card[i].nports && + line >= cy_card[i].first_line) + break; + if (i >= NR_CARDS) + return -ENODEV; + info = &cy_card[i].ports[line - cy_card[i].first_line]; if (info->line < 0) { return -ENODEV; } @@ -2542,23 +2475,23 @@ static int cy_open(struct tty_struct *tty, struct file *filp) treat it as absent from the system. This will make the user pay attention. */ - if (IS_CYC_Z(cy_card[info->card])) { - struct cyclades_card *cinfo = &cy_card[info->card]; + if (IS_CYC_Z(*info->card)) { + struct cyclades_card *cinfo = info->card; struct FIRM_ID __iomem *firm_id = cinfo->base_addr + ID_ADDRESS; if (!ISZLOADED(*cinfo)) { - if (((ZE_V1 == cy_readl( - &((struct RUNTIME_9060 __iomem *) + if (((ZE_V1 == readl(&((struct RUNTIME_9060 __iomem *) (cinfo->ctl_addr))->mail_box_0)) && Z_FPGA_CHECK(*cinfo)) && - (ZFIRM_HLT == cy_readl( + (ZFIRM_HLT == readl( &firm_id->signature))) { - printk("cyc:Cyclades-Z Error: you need an " - "external power supply for this number " - "of ports.\n\rFirmware halted.\r\n"); + printk(KERN_ERR "cyc:Cyclades-Z Error: you " + "need an external power supply for " + "this number of ports.\nFirmware " + "halted.\n"); } else { - printk("cyc:Cyclades-Z firmware not yet " - "loaded\n"); + printk(KERN_ERR "cyc:Cyclades-Z firmware not " + "yet loaded\n"); } return -ENODEV; } @@ -2572,24 +2505,23 @@ static int cy_open(struct tty_struct *tty, struct file *filp) struct BOARD_CTRL __iomem *board_ctrl; zfw_ctrl = cinfo->base_addr + - (cy_readl(&firm_id->zfwctrl_addr) & - 0xfffff); + (readl(&firm_id->zfwctrl_addr) & + 0xfffff); board_ctrl = &zfw_ctrl->board_ctrl; /* Enable interrupts on the PLX chip */ cy_writew(cinfo->ctl_addr + 0x68, - cy_readw(cinfo->ctl_addr + - 0x68) | 0x0900); + readw(cinfo->ctl_addr + 0x68) | 0x0900); /* Enable interrupts on the FW */ retval = cyz_issue_cmd(cinfo, 0, C_CM_IRQ_ENBL, 0L); if (retval != 0) { - printk("cyc:IRQ enable retval was %x\n", - retval); + printk(KERN_ERR "cyc:IRQ enable retval " + "was %x\n", retval); } cinfo->nports = - (int)cy_readl(&board_ctrl->n_channel); + (int)readl(&board_ctrl->n_channel); cinfo->intr_enabled = 1; } } @@ -2599,7 +2531,7 @@ static int cy_open(struct tty_struct *tty, struct file *filp) return -ENODEV; } #ifdef CY_DEBUG_OTHER - printk("cyc:cy_open ttyC%d\n", info->line); /* */ + printk(KERN_DEBUG "cyc:cy_open ttyC%d\n", info->line); #endif tty->driver_data = info; info->tty = tty; @@ -2607,12 +2539,12 @@ static int cy_open(struct tty_struct *tty, struct file *filp) return -ENODEV; } #ifdef CY_DEBUG_OPEN - printk("cyc:cy_open ttyC%d, count = %d\n", info->line, info->count); - /**/ + printk(KERN_DEBUG "cyc:cy_open ttyC%d, count = %d\n", info->line, + info->count); #endif info->count++; #ifdef CY_DEBUG_COUNT - printk("cyc:cy_open (%d): incrementing count to %d\n", + printk(KERN_DEBUG "cyc:cy_open (%d): incrementing count to %d\n", current->pid, info->count); #endif @@ -2620,8 +2552,8 @@ static int cy_open(struct tty_struct *tty, struct file *filp) * If the port is the middle of closing, bail out now */ if (tty_hung_up_p(filp) || (info->flags & ASYNC_CLOSING)) { - if (info->flags & ASYNC_CLOSING) - interruptible_sleep_on(&info->close_wait); + wait_event_interruptible(info->close_wait, + !(info->flags & ASYNC_CLOSING)); return (info->flags & ASYNC_HUP_NOTIFY) ? -EAGAIN: -ERESTARTSYS; } @@ -2636,8 +2568,8 @@ static int cy_open(struct tty_struct *tty, struct file *filp) retval = block_til_ready(tty, filp, info); if (retval) { #ifdef CY_DEBUG_OPEN - printk("cyc:cy_open returning after block_til_ready with %d\n", - retval); + printk(KERN_DEBUG "cyc:cy_open returning after block_til_ready " + "with %d\n", retval); #endif return retval; } @@ -2645,8 +2577,7 @@ static int cy_open(struct tty_struct *tty, struct file *filp) info->throttle = 0; #ifdef CY_DEBUG_OPEN - printk(" cyc:cy_open done\n"); - /**/ + printk(KERN_DEBUG "cyc:cy_open done\n"); #endif return 0; } /* cy_open */ @@ -2656,9 +2587,10 @@ static int cy_open(struct tty_struct *tty, struct file *filp) */ static void cy_wait_until_sent(struct tty_struct *tty, int timeout) { - struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; + struct cyclades_card *card; + struct cyclades_port *info = tty->driver_data; void __iomem *base_addr; - int card, chip, channel, index; + int chip, channel, index; unsigned long orig_jiffies; int char_time; @@ -2697,20 +2629,19 @@ static void cy_wait_until_sent(struct tty_struct *tty, int timeout) if (!timeout || timeout > 2 * info->timeout) timeout = 2 * info->timeout; #ifdef CY_DEBUG_WAIT_UNTIL_SENT - printk("In cy_wait_until_sent(%d) check=%lu...", timeout, char_time); - printk("jiff=%lu...", jiffies); + printk(KERN_DEBUG "In cy_wait_until_sent(%d) check=%d, jiff=%lu...", + timeout, char_time, jiffies); #endif card = info->card; - channel = (info->line) - (cy_card[card].first_line); - if (!IS_CYC_Z(cy_card[card])) { + channel = (info->line) - (card->first_line); + if (!IS_CYC_Z(*card)) { chip = channel >> 2; channel &= 0x03; - index = cy_card[card].bus_index; - base_addr = - cy_card[card].base_addr + (cy_chip_offset[chip] << index); - while (cy_readb(base_addr + (CySRER << index)) & CyTxRdy) { + index = card->bus_index; + base_addr = card->base_addr + (cy_chip_offset[chip] << index); + while (readb(base_addr + (CySRER << index)) & CyTxRdy) { #ifdef CY_DEBUG_WAIT_UNTIL_SENT - printk("Not clean (jiff=%lu)...", jiffies); + printk(KERN_DEBUG "Not clean (jiff=%lu)...", jiffies); #endif if (msleep_interruptible(jiffies_to_msecs(char_time))) break; @@ -2718,13 +2649,11 @@ static void cy_wait_until_sent(struct tty_struct *tty, int timeout) timeout)) break; } - } else { - /* Nothing to do! */ } /* Run one more char cycle */ msleep_interruptible(jiffies_to_msecs(char_time * 5)); #ifdef CY_DEBUG_WAIT_UNTIL_SENT - printk("Clean (jiff=%lu)...done\n", jiffies); + printk(KERN_DEBUG "Clean (jiff=%lu)...done\n", jiffies); #endif } @@ -2733,25 +2662,29 @@ static void cy_wait_until_sent(struct tty_struct *tty, int timeout) */ static void cy_close(struct tty_struct *tty, struct file *filp) { - struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; + struct cyclades_port *info = tty->driver_data; + struct cyclades_card *card; unsigned long flags; #ifdef CY_DEBUG_OTHER - printk("cyc:cy_close ttyC%d\n", info->line); + printk(KERN_DEBUG "cyc:cy_close ttyC%d\n", info->line); #endif if (!info || serial_paranoia_check(info, tty->name, "cy_close")) { return; } - CY_LOCK(info, flags); + card = info->card; + + spin_lock_irqsave(&card->card_lock, flags); /* If the TTY is being hung up, nothing to do */ if (tty_hung_up_p(filp)) { - CY_UNLOCK(info, flags); + spin_unlock_irqrestore(&card->card_lock, flags); return; } #ifdef CY_DEBUG_OPEN - printk("cyc:cy_close ttyC%d, count = %d\n", info->line, info->count); + printk(KERN_DEBUG "cyc:cy_close ttyC%d, count = %d\n", info->line, + info->count); #endif if ((tty->count == 1) && (info->count != 1)) { /* @@ -2761,22 +2694,22 @@ static void cy_close(struct tty_struct *tty, struct file *filp) * one, we've got real problems, since it means the * serial port won't be shutdown. */ - printk("cyc:cy_close: bad serial port count; tty->count is 1, " - "info->count is %d\n", info->count); + printk(KERN_ERR "cyc:cy_close: bad serial port count; " + "tty->count is 1, info->count is %d\n", info->count); info->count = 1; } #ifdef CY_DEBUG_COUNT - printk("cyc:cy_close at (%d): decrementing count to %d\n", + printk(KERN_DEBUG "cyc:cy_close at (%d): decrementing count to %d\n", current->pid, info->count - 1); #endif if (--info->count < 0) { #ifdef CY_DEBUG_COUNT - printk("cyc:cyc_close setting count to 0\n"); + printk(KERN_DEBUG "cyc:cyc_close setting count to 0\n"); #endif info->count = 0; } if (info->count) { - CY_UNLOCK(info, flags); + spin_unlock_irqrestore(&card->card_lock, flags); return; } info->flags |= ASYNC_CLOSING; @@ -2786,81 +2719,80 @@ static void cy_close(struct tty_struct *tty, struct file *filp) * the line discipline to only process XON/XOFF characters. */ tty->closing = 1; - CY_UNLOCK(info, flags); + spin_unlock_irqrestore(&card->card_lock, flags); if (info->closing_wait != CY_CLOSING_WAIT_NONE) { tty_wait_until_sent(tty, info->closing_wait); } - CY_LOCK(info, flags); + spin_lock_irqsave(&card->card_lock, flags); - if (!IS_CYC_Z(cy_card[info->card])) { - int channel = info->line - cy_card[info->card].first_line; - int index = cy_card[info->card].bus_index; - void __iomem *base_addr = cy_card[info->card].base_addr + + if (!IS_CYC_Z(*card)) { + int channel = info->line - card->first_line; + int index = card->bus_index; + void __iomem *base_addr = card->base_addr + (cy_chip_offset[channel >> 2] << index); /* Stop accepting input */ channel &= 0x03; cy_writeb(base_addr + (CyCAR << index), (u_char) channel); cy_writeb(base_addr + (CySRER << index), - cy_readb(base_addr + (CySRER << index)) & ~CyRxData); + readb(base_addr + (CySRER << index)) & ~CyRxData); if (info->flags & ASYNC_INITIALIZED) { /* Waiting for on-board buffers to be empty before closing the port */ - CY_UNLOCK(info, flags); + spin_unlock_irqrestore(&card->card_lock, flags); cy_wait_until_sent(tty, info->timeout); - CY_LOCK(info, flags); + spin_lock_irqsave(&card->card_lock, flags); } } else { #ifdef Z_WAKE /* Waiting for on-board buffers to be empty before closing the port */ - void __iomem *base_addr = cy_card[info->card].base_addr; + void __iomem *base_addr = card->base_addr; struct FIRM_ID __iomem *firm_id = base_addr + ID_ADDRESS; struct ZFW_CTRL __iomem *zfw_ctrl = - base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff); + base_addr + (readl(&firm_id->zfwctrl_addr) & 0xfffff); struct CH_CTRL __iomem *ch_ctrl = zfw_ctrl->ch_ctrl; - int channel = info->line - cy_card[info->card].first_line; + int channel = info->line - card->first_line; int retval; - if (cy_readl(&ch_ctrl[channel].flow_status) != C_FS_TXIDLE) { - retval = cyz_issue_cmd(&cy_card[info->card], channel, - C_CM_IOCTLW, 0L); + if (readl(&ch_ctrl[channel].flow_status) != C_FS_TXIDLE) { + retval = cyz_issue_cmd(card, channel, C_CM_IOCTLW, 0L); if (retval != 0) { - printk("cyc:cy_close retval on ttyC%d was %x\n", - info->line, retval); + printk(KERN_DEBUG "cyc:cy_close retval on " + "ttyC%d was %x\n", info->line, retval); } - CY_UNLOCK(info, flags); - interruptible_sleep_on(&info->shutdown_wait); - CY_LOCK(info, flags); + spin_unlock_irqrestore(&card->card_lock, flags); + wait_for_completion_interruptible(&info->shutdown_wait); + spin_lock_irqsave(&card->card_lock, flags); } #endif } - CY_UNLOCK(info, flags); + spin_unlock_irqrestore(&card->card_lock, flags); shutdown(info); if (tty->driver->flush_buffer) tty->driver->flush_buffer(tty); tty_ldisc_flush(tty); - CY_LOCK(info, flags); + spin_lock_irqsave(&card->card_lock, flags); tty->closing = 0; info->event = 0; info->tty = NULL; if (info->blocked_open) { - CY_UNLOCK(info, flags); + spin_unlock_irqrestore(&card->card_lock, flags); if (info->close_delay) { msleep_interruptible(jiffies_to_msecs (info->close_delay)); } wake_up_interruptible(&info->open_wait); - CY_LOCK(info, flags); + spin_lock_irqsave(&card->card_lock, flags); } info->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING); wake_up_interruptible(&info->close_wait); #ifdef CY_DEBUG_OTHER - printk(" cyc:cy_close done\n"); + printk(KERN_DEBUG "cyc:cy_close done\n"); #endif - CY_UNLOCK(info, flags); + spin_unlock_irqrestore(&card->card_lock, flags); } /* cy_close */ /* This routine gets called when tty_write has put something into @@ -2878,12 +2810,12 @@ static void cy_close(struct tty_struct *tty, struct file *filp) */ static int cy_write(struct tty_struct *tty, const unsigned char *buf, int count) { - struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; + struct cyclades_port *info = tty->driver_data; unsigned long flags; int c, ret = 0; #ifdef CY_DEBUG_IO - printk("cyc:cy_write ttyC%d\n", info->line); /* */ + printk(KERN_DEBUG "cyc:cy_write ttyC%d\n", info->line); #endif if (serial_paranoia_check(info, tty->name, "cy_write")) { @@ -2893,7 +2825,7 @@ static int cy_write(struct tty_struct *tty, const unsigned char *buf, int count) if (!info->xmit_buf) return 0; - CY_LOCK(info, flags); + spin_lock_irqsave(&info->card->card_lock, flags); while (1) { c = min(count, min((int)(SERIAL_XMIT_SIZE - info->xmit_cnt - 1), (int)(SERIAL_XMIT_SIZE - info->xmit_head))); @@ -2909,7 +2841,7 @@ static int cy_write(struct tty_struct *tty, const unsigned char *buf, int count) count -= c; ret += c; } - CY_UNLOCK(info, flags); + spin_unlock_irqrestore(&info->card->card_lock, flags); info->idle_stats.xmit_bytes += ret; info->idle_stats.xmit_idle = jiffies; @@ -2929,11 +2861,11 @@ static int cy_write(struct tty_struct *tty, const unsigned char *buf, int count) */ static void cy_put_char(struct tty_struct *tty, unsigned char ch) { - struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; + struct cyclades_port *info = tty->driver_data; unsigned long flags; #ifdef CY_DEBUG_IO - printk("cyc:cy_put_char ttyC%d\n", info->line); + printk(KERN_DEBUG "cyc:cy_put_char ttyC%d\n", info->line); #endif if (serial_paranoia_check(info, tty->name, "cy_put_char")) @@ -2942,9 +2874,9 @@ static void cy_put_char(struct tty_struct *tty, unsigned char ch) if (!info->xmit_buf) return; - CY_LOCK(info, flags); + spin_lock_irqsave(&info->card->card_lock, flags); if (info->xmit_cnt >= (int)(SERIAL_XMIT_SIZE - 1)) { - CY_UNLOCK(info, flags); + spin_unlock_irqrestore(&info->card->card_lock, flags); return; } @@ -2953,7 +2885,7 @@ static void cy_put_char(struct tty_struct *tty, unsigned char ch) info->xmit_cnt++; info->idle_stats.xmit_bytes++; info->idle_stats.xmit_idle = jiffies; - CY_UNLOCK(info, flags); + spin_unlock_irqrestore(&info->card->card_lock, flags); } /* cy_put_char */ /* @@ -2962,10 +2894,10 @@ static void cy_put_char(struct tty_struct *tty, unsigned char ch) */ static void cy_flush_chars(struct tty_struct *tty) { - struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; + struct cyclades_port *info = tty->driver_data; #ifdef CY_DEBUG_IO - printk("cyc:cy_flush_chars ttyC%d\n", info->line); /* */ + printk(KERN_DEBUG "cyc:cy_flush_chars ttyC%d\n", info->line); #endif if (serial_paranoia_check(info, tty->name, "cy_flush_chars")) @@ -2986,11 +2918,11 @@ static void cy_flush_chars(struct tty_struct *tty) */ static int cy_write_room(struct tty_struct *tty) { - struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; + struct cyclades_port *info = tty->driver_data; int ret; #ifdef CY_DEBUG_IO - printk("cyc:cy_write_room ttyC%d\n", info->line); /* */ + printk(KERN_DEBUG "cyc:cy_write_room ttyC%d\n", info->line); #endif if (serial_paranoia_check(info, tty->name, "cy_write_room")) @@ -3003,46 +2935,49 @@ static int cy_write_room(struct tty_struct *tty) static int cy_chars_in_buffer(struct tty_struct *tty) { - struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; - int card, channel; + struct cyclades_card *card; + struct cyclades_port *info = tty->driver_data; + int channel; if (serial_paranoia_check(info, tty->name, "cy_chars_in_buffer")) return 0; card = info->card; - channel = (info->line) - (cy_card[card].first_line); + channel = (info->line) - (card->first_line); #ifdef Z_EXT_CHARS_IN_BUFFER if (!IS_CYC_Z(cy_card[card])) { #endif /* Z_EXT_CHARS_IN_BUFFER */ #ifdef CY_DEBUG_IO - printk("cyc:cy_chars_in_buffer ttyC%d %d\n", info->line, info->xmit_cnt); /* */ + printk(KERN_DEBUG "cyc:cy_chars_in_buffer ttyC%d %d\n", + info->line, info->xmit_cnt); #endif return info->xmit_cnt; #ifdef Z_EXT_CHARS_IN_BUFFER } else { - static volatile struct FIRM_ID *firm_id; - static volatile struct ZFW_CTRL *zfw_ctrl; - static volatile struct CH_CTRL *ch_ctrl; - static volatile struct BUF_CTRL *buf_ctrl; + static struct FIRM_ID *firm_id; + static struct ZFW_CTRL *zfw_ctrl; + static struct CH_CTRL *ch_ctrl; + static struct BUF_CTRL *buf_ctrl; int char_count; - volatile uclong tx_put, tx_get, tx_bufsize; + __u32 tx_put, tx_get, tx_bufsize; - firm_id = cy_card[card].base_addr + ID_ADDRESS; - zfw_ctrl = cy_card[card].base_addr + - (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff); + firm_id = card->base_addr + ID_ADDRESS; + zfw_ctrl = card->base_addr + + (readl(&firm_id->zfwctrl_addr) & 0xfffff); ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]); buf_ctrl = &(zfw_ctrl->buf_ctrl[channel]); - tx_get = cy_readl(&buf_ctrl->tx_get); - tx_put = cy_readl(&buf_ctrl->tx_put); - tx_bufsize = cy_readl(&buf_ctrl->tx_bufsize); + tx_get = readl(&buf_ctrl->tx_get); + tx_put = readl(&buf_ctrl->tx_put); + tx_bufsize = readl(&buf_ctrl->tx_bufsize); if (tx_put >= tx_get) char_count = tx_put - tx_get; else char_count = tx_put - tx_get + tx_bufsize; #ifdef CY_DEBUG_IO - printk("cyc:cy_chars_in_buffer ttyC%d %d\n", info->line, info->xmit_cnt + char_count); /* */ + printk(KERN_DEBUG "cyc:cy_chars_in_buffer ttyC%d %d\n", + info->line, info->xmit_cnt + char_count); #endif return info->xmit_cnt + char_count; } @@ -3055,10 +2990,10 @@ static int cy_chars_in_buffer(struct tty_struct *tty) * ------------------------------------------------------------ */ -static void cyy_baud_calc(struct cyclades_port *info, uclong baud) +static void cyy_baud_calc(struct cyclades_port *info, __u32 baud) { int co, co_val, bpr; - uclong cy_clock = ((info->chip_rev >= CD1400_REV_J) ? 60000000 : + __u32 cy_clock = ((info->chip_rev >= CD1400_REV_J) ? 60000000 : 25000000); if (baud == 0) { @@ -3086,9 +3021,10 @@ static void cyy_baud_calc(struct cyclades_port *info, uclong baud) */ static void set_line_char(struct cyclades_port *info) { + struct cyclades_card *card; unsigned long flags; void __iomem *base_addr; - int card, chip, channel, index; + int chip, channel, index; unsigned cflag, iflag; unsigned short chip_number; int baud, baud_rate = 0; @@ -3118,12 +3054,12 @@ static void set_line_char(struct cyclades_port *info) } card = info->card; - channel = (info->line) - (cy_card[card].first_line); + channel = info->line - card->first_line; chip_number = channel / 4; - if (!IS_CYC_Z(cy_card[card])) { + if (!IS_CYC_Z(*card)) { - index = cy_card[card].bus_index; + index = card->bus_index; /* baud rate */ baud = tty_get_baud_rate(info->tty); @@ -3241,10 +3177,9 @@ static void set_line_char(struct cyclades_port *info) chip = channel >> 2; channel &= 0x03; - base_addr = cy_card[card].base_addr + - (cy_chip_offset[chip] << index); + base_addr = card->base_addr + (cy_chip_offset[chip] << index); - CY_LOCK(info, flags); + spin_lock_irqsave(&card->card_lock, flags); cy_writeb(base_addr + (CyCAR << index), (u_char) channel); /* tx and rx baud rate */ @@ -3276,8 +3211,7 @@ static void set_line_char(struct cyclades_port *info) if (C_CLOCAL(info->tty)) { /* without modem intr */ cy_writeb(base_addr + (CySRER << index), - cy_readb(base_addr + - (CySRER << index)) | CyMdmCh); + readb(base_addr + (CySRER << index)) | CyMdmCh); /* act on 1->0 modem transitions */ if ((cflag & CRTSCTS) && info->rflow) { cy_writeb(base_addr + (CyMCOR1 << index), @@ -3291,7 +3225,7 @@ static void set_line_char(struct cyclades_port *info) } else { /* without modem intr */ cy_writeb(base_addr + (CySRER << index), - cy_readb(base_addr + + readb(base_addr + (CySRER << index)) | CyMdmCh); /* act on 1->0 modem transitions */ if ((cflag & CRTSCTS) && info->rflow) { @@ -3316,10 +3250,10 @@ static void set_line_char(struct cyclades_port *info) ~CyDTR); } #ifdef CY_DEBUG_DTR - printk("cyc:set_line_char dropping DTR\n"); - printk(" status: 0x%x, 0x%x\n", - cy_readb(base_addr + (CyMSVR1 << index)), - cy_readb(base_addr + (CyMSVR2 << index))); + printk(KERN_DEBUG "cyc:set_line_char dropping DTR\n"); + printk(KERN_DEBUG " status: 0x%x, 0x%x\n", + readb(base_addr + (CyMSVR1 << index)), + readb(base_addr + (CyMSVR2 << index))); #endif } else { if (info->rtsdtr_inv) { @@ -3330,17 +3264,17 @@ static void set_line_char(struct cyclades_port *info) CyDTR); } #ifdef CY_DEBUG_DTR - printk("cyc:set_line_char raising DTR\n"); - printk(" status: 0x%x, 0x%x\n", - cy_readb(base_addr + (CyMSVR1 << index)), - cy_readb(base_addr + (CyMSVR2 << index))); + printk(KERN_DEBUG "cyc:set_line_char raising DTR\n"); + printk(KERN_DEBUG " status: 0x%x, 0x%x\n", + readb(base_addr + (CyMSVR1 << index)), + readb(base_addr + (CyMSVR2 << index))); #endif } if (info->tty) { clear_bit(TTY_IO_ERROR, &info->tty->flags); } - CY_UNLOCK(info, flags); + spin_unlock_irqrestore(&card->card_lock, flags); } else { struct FIRM_ID __iomem *firm_id; @@ -3348,16 +3282,16 @@ static void set_line_char(struct cyclades_port *info) struct BOARD_CTRL __iomem *board_ctrl; struct CH_CTRL __iomem *ch_ctrl; struct BUF_CTRL __iomem *buf_ctrl; - uclong sw_flow; + __u32 sw_flow; int retval; - firm_id = cy_card[card].base_addr + ID_ADDRESS; - if (!ISZLOADED(cy_card[card])) { + firm_id = card->base_addr + ID_ADDRESS; + if (!ISZLOADED(*card)) { return; } - zfw_ctrl = cy_card[card].base_addr + - (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff); + zfw_ctrl = card->base_addr + + (readl(&firm_id->zfwctrl_addr) & 0xfffff); board_ctrl = &zfw_ctrl->board_ctrl; ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]); buf_ctrl = &zfw_ctrl->buf_ctrl[channel]; @@ -3408,10 +3342,10 @@ static void set_line_char(struct cyclades_port *info) } if (cflag & CSTOPB) { cy_writel(&ch_ctrl->comm_data_l, - cy_readl(&ch_ctrl->comm_data_l) | C_DL_2STOP); + readl(&ch_ctrl->comm_data_l) | C_DL_2STOP); } else { cy_writel(&ch_ctrl->comm_data_l, - cy_readl(&ch_ctrl->comm_data_l) | C_DL_1STOP); + readl(&ch_ctrl->comm_data_l) | C_DL_1STOP); } if (cflag & PARENB) { if (cflag & PARODD) { @@ -3426,12 +3360,10 @@ static void set_line_char(struct cyclades_port *info) /* CTS flow control flag */ if (cflag & CRTSCTS) { cy_writel(&ch_ctrl->hw_flow, - cy_readl(&ch_ctrl-> - hw_flow) | C_RS_CTS | C_RS_RTS); + readl(&ch_ctrl->hw_flow) | C_RS_CTS | C_RS_RTS); } else { - cy_writel(&ch_ctrl->hw_flow, - cy_readl(&ch_ctrl-> - hw_flow) & ~(C_RS_CTS | C_RS_RTS)); + cy_writel(&ch_ctrl->hw_flow, readl(&ch_ctrl->hw_flow) & + ~(C_RS_CTS | C_RS_RTS)); } /* As the HW flow control is done in firmware, the driver doesn't need to care about it */ @@ -3446,10 +3378,10 @@ static void set_line_char(struct cyclades_port *info) } cy_writel(&ch_ctrl->sw_flow, sw_flow); - retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_IOCTL, 0L); + retval = cyz_issue_cmd(card, channel, C_CM_IOCTL, 0L); if (retval != 0) { - printk("cyc:set_line_char retval on ttyC%d was %x\n", - info->line, retval); + printk(KERN_ERR "cyc:set_line_char retval on ttyC%d " + "was %x\n", info->line, retval); } /* CD sensitivity */ @@ -3461,22 +3393,22 @@ static void set_line_char(struct cyclades_port *info) if (baud == 0) { /* baud rate is zero, turn off line */ cy_writel(&ch_ctrl->rs_control, - cy_readl(&ch_ctrl->rs_control) & ~C_RS_DTR); + readl(&ch_ctrl->rs_control) & ~C_RS_DTR); #ifdef CY_DEBUG_DTR - printk("cyc:set_line_char dropping Z DTR\n"); + printk(KERN_DEBUG "cyc:set_line_char dropping Z DTR\n"); #endif } else { cy_writel(&ch_ctrl->rs_control, - cy_readl(&ch_ctrl->rs_control) | C_RS_DTR); + readl(&ch_ctrl->rs_control) | C_RS_DTR); #ifdef CY_DEBUG_DTR - printk("cyc:set_line_char raising Z DTR\n"); + printk(KERN_DEBUG "cyc:set_line_char raising Z DTR\n"); #endif } - retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_IOCTLM,0L); + retval = cyz_issue_cmd(card, channel, C_CM_IOCTLM,0L); if (retval != 0) { - printk("cyc:set_line_char(2) retval on ttyC%d was %x\n", - info->line, retval); + printk(KERN_ERR "cyc:set_line_char(2) retval on ttyC%d " + "was %x\n", info->line, retval); } if (info->tty) { @@ -3490,14 +3422,15 @@ get_serial_info(struct cyclades_port *info, struct serial_struct __user * retinfo) { struct serial_struct tmp; - struct cyclades_card *cinfo = &cy_card[info->card]; + struct cyclades_card *cinfo = info->card; if (!retinfo) return -EFAULT; memset(&tmp, 0, sizeof(tmp)); tmp.type = info->type; tmp.line = info->line; - tmp.port = info->card * 0x100 + info->line - cinfo->first_line; + tmp.port = (info->card - cy_card) * 0x100 + info->line - + cinfo->first_line; tmp.irq = cinfo->irq; tmp.flags = info->flags; tmp.close_delay = info->close_delay; @@ -3566,25 +3499,25 @@ check_and_exit: */ static int get_lsr_info(struct cyclades_port *info, unsigned int __user * value) { - int card, chip, channel, index; + struct cyclades_card *card; + int chip, channel, index; unsigned char status; unsigned int result; unsigned long flags; void __iomem *base_addr; card = info->card; - channel = (info->line) - (cy_card[card].first_line); - if (!IS_CYC_Z(cy_card[card])) { + channel = (info->line) - (card->first_line); + if (!IS_CYC_Z(*card)) { chip = channel >> 2; channel &= 0x03; - index = cy_card[card].bus_index; - base_addr = - cy_card[card].base_addr + (cy_chip_offset[chip] << index); + index = card->bus_index; + base_addr = card->base_addr + (cy_chip_offset[chip] << index); - CY_LOCK(info, flags); - status = cy_readb(base_addr + (CySRER << index)) & + spin_lock_irqsave(&card->card_lock, flags); + status = readb(base_addr + (CySRER << index)) & (CyTxRdy | CyTxMpty); - CY_UNLOCK(info, flags); + spin_unlock_irqrestore(&card->card_lock, flags); result = (status ? 0 : TIOCSER_TEMT); } else { /* Not supported yet */ @@ -3595,8 +3528,9 @@ static int get_lsr_info(struct cyclades_port *info, unsigned int __user * value) static int cy_tiocmget(struct tty_struct *tty, struct file *file) { - struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; - int card, chip, channel, index; + struct cyclades_port *info = tty->driver_data; + struct cyclades_card *card; + int chip, channel, index; void __iomem *base_addr; unsigned long flags; unsigned char status; @@ -3611,19 +3545,18 @@ static int cy_tiocmget(struct tty_struct *tty, struct file *file) return -ENODEV; card = info->card; - channel = (info->line) - (cy_card[card].first_line); - if (!IS_CYC_Z(cy_card[card])) { + channel = info->line - card->first_line; + if (!IS_CYC_Z(*card)) { chip = channel >> 2; channel &= 0x03; - index = cy_card[card].bus_index; - base_addr = - cy_card[card].base_addr + (cy_chip_offset[chip] << index); + index = card->bus_index; + base_addr = card->base_addr + (cy_chip_offset[chip] << index); - CY_LOCK(info, flags); + spin_lock_irqsave(&card->card_lock, flags); cy_writeb(base_addr + (CyCAR << index), (u_char) channel); - status = cy_readb(base_addr + (CyMSVR1 << index)); - status |= cy_readb(base_addr + (CyMSVR2 << index)); - CY_UNLOCK(info, flags); + status = readb(base_addr + (CyMSVR1 << index)); + status |= readb(base_addr + (CyMSVR2 << index)); + spin_unlock_irqrestore(&card->card_lock, flags); if (info->rtsdtr_inv) { result = ((status & CyRTS) ? TIOCM_DTR : 0) | @@ -3637,19 +3570,14 @@ static int cy_tiocmget(struct tty_struct *tty, struct file *file) ((status & CyDSR) ? TIOCM_DSR : 0) | ((status & CyCTS) ? TIOCM_CTS : 0); } else { - base_addr = cy_card[card].base_addr; - - if (cy_card[card].num_chips != -1) { - return -EINVAL; - } - - firm_id = cy_card[card].base_addr + ID_ADDRESS; - if (ISZLOADED(cy_card[card])) { - zfw_ctrl = cy_card[card].base_addr + - (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff); + base_addr = card->base_addr; + firm_id = card->base_addr + ID_ADDRESS; + if (ISZLOADED(*card)) { + zfw_ctrl = card->base_addr + + (readl(&firm_id->zfwctrl_addr) & 0xfffff); board_ctrl = &zfw_ctrl->board_ctrl; ch_ctrl = zfw_ctrl->ch_ctrl; - lstatus = cy_readl(&ch_ctrl[channel].rs_status); + lstatus = readl(&ch_ctrl[channel].rs_status); result = ((lstatus & C_RS_RTS) ? TIOCM_RTS : 0) | ((lstatus & C_RS_DTR) ? TIOCM_DTR : 0) | ((lstatus & C_RS_DCD) ? TIOCM_CAR : 0) | @@ -3669,8 +3597,9 @@ static int cy_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear) { - struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; - int card, chip, channel, index; + struct cyclades_port *info = tty->driver_data; + struct cyclades_card *card; + int chip, channel, index; void __iomem *base_addr; unsigned long flags; struct FIRM_ID __iomem *firm_id; @@ -3683,16 +3612,15 @@ cy_tiocmset(struct tty_struct *tty, struct file *file, return -ENODEV; card = info->card; - channel = (info->line) - (cy_card[card].first_line); - if (!IS_CYC_Z(cy_card[card])) { + channel = (info->line) - (card->first_line); + if (!IS_CYC_Z(*card)) { chip = channel >> 2; channel &= 0x03; - index = cy_card[card].bus_index; - base_addr = - cy_card[card].base_addr + (cy_chip_offset[chip] << index); + index = card->bus_index; + base_addr = card->base_addr + (cy_chip_offset[chip] << index); if (set & TIOCM_RTS) { - CY_LOCK(info, flags); + spin_lock_irqsave(&card->card_lock, flags); cy_writeb(base_addr + (CyCAR << index), (u_char) channel); if (info->rtsdtr_inv) { @@ -3702,10 +3630,10 @@ cy_tiocmset(struct tty_struct *tty, struct file *file, cy_writeb(base_addr + (CyMSVR1 << index), CyRTS); } - CY_UNLOCK(info, flags); + spin_unlock_irqrestore(&card->card_lock, flags); } if (clear & TIOCM_RTS) { - CY_LOCK(info, flags); + spin_lock_irqsave(&card->card_lock, flags); cy_writeb(base_addr + (CyCAR << index), (u_char) channel); if (info->rtsdtr_inv) { @@ -3715,10 +3643,10 @@ cy_tiocmset(struct tty_struct *tty, struct file *file, cy_writeb(base_addr + (CyMSVR1 << index), ~CyRTS); } - CY_UNLOCK(info, flags); + spin_unlock_irqrestore(&card->card_lock, flags); } if (set & TIOCM_DTR) { - CY_LOCK(info, flags); + spin_lock_irqsave(&card->card_lock, flags); cy_writeb(base_addr + (CyCAR << index), (u_char) channel); if (info->rtsdtr_inv) { @@ -3729,15 +3657,15 @@ cy_tiocmset(struct tty_struct *tty, struct file *file, CyDTR); } #ifdef CY_DEBUG_DTR - printk("cyc:set_modem_info raising DTR\n"); - printk(" status: 0x%x, 0x%x\n", - cy_readb(base_addr + (CyMSVR1 << index)), - cy_readb(base_addr + (CyMSVR2 << index))); + printk(KERN_DEBUG "cyc:set_modem_info raising DTR\n"); + printk(KERN_DEBUG " status: 0x%x, 0x%x\n", + readb(base_addr + (CyMSVR1 << index)), + readb(base_addr + (CyMSVR2 << index))); #endif - CY_UNLOCK(info, flags); + spin_unlock_irqrestore(&card->card_lock, flags); } if (clear & TIOCM_DTR) { - CY_LOCK(info, flags); + spin_lock_irqsave(&card->card_lock, flags); cy_writeb(base_addr + (CyCAR << index), (u_char) channel); if (info->rtsdtr_inv) { @@ -3749,68 +3677,69 @@ cy_tiocmset(struct tty_struct *tty, struct file *file, } #ifdef CY_DEBUG_DTR - printk("cyc:set_modem_info dropping DTR\n"); - printk(" status: 0x%x, 0x%x\n", - cy_readb(base_addr + (CyMSVR1 << index)), - cy_readb(base_addr + (CyMSVR2 << index))); + printk(KERN_DEBUG "cyc:set_modem_info dropping DTR\n"); + printk(KERN_DEBUG " status: 0x%x, 0x%x\n", + readb(base_addr + (CyMSVR1 << index)), + readb(base_addr + (CyMSVR2 << index))); #endif - CY_UNLOCK(info, flags); + spin_unlock_irqrestore(&card->card_lock, flags); } } else { - base_addr = cy_card[card].base_addr; + base_addr = card->base_addr; - firm_id = cy_card[card].base_addr + ID_ADDRESS; - if (ISZLOADED(cy_card[card])) { - zfw_ctrl = cy_card[card].base_addr + - (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff); + firm_id = card->base_addr + ID_ADDRESS; + if (ISZLOADED(*card)) { + zfw_ctrl = card->base_addr + + (readl(&firm_id->zfwctrl_addr) & 0xfffff); board_ctrl = &zfw_ctrl->board_ctrl; ch_ctrl = zfw_ctrl->ch_ctrl; if (set & TIOCM_RTS) { - CY_LOCK(info, flags); + spin_lock_irqsave(&card->card_lock, flags); cy_writel(&ch_ctrl[channel].rs_control, - cy_readl(&ch_ctrl[channel]. - rs_control) | C_RS_RTS); - CY_UNLOCK(info, flags); + readl(&ch_ctrl[channel].rs_control) | + C_RS_RTS); + spin_unlock_irqrestore(&card->card_lock, flags); } if (clear & TIOCM_RTS) { - CY_LOCK(info, flags); + spin_lock_irqsave(&card->card_lock, flags); cy_writel(&ch_ctrl[channel].rs_control, - cy_readl(&ch_ctrl[channel]. - rs_control) & ~C_RS_RTS); - CY_UNLOCK(info, flags); + readl(&ch_ctrl[channel].rs_control) & + ~C_RS_RTS); + spin_unlock_irqrestore(&card->card_lock, flags); } if (set & TIOCM_DTR) { - CY_LOCK(info, flags); + spin_lock_irqsave(&card->card_lock, flags); cy_writel(&ch_ctrl[channel].rs_control, - cy_readl(&ch_ctrl[channel]. - rs_control) | C_RS_DTR); + readl(&ch_ctrl[channel].rs_control) | + C_RS_DTR); #ifdef CY_DEBUG_DTR - printk("cyc:set_modem_info raising Z DTR\n"); + printk(KERN_DEBUG "cyc:set_modem_info raising " + "Z DTR\n"); #endif - CY_UNLOCK(info, flags); + spin_unlock_irqrestore(&card->card_lock, flags); } if (clear & TIOCM_DTR) { - CY_LOCK(info, flags); + spin_lock_irqsave(&card->card_lock, flags); cy_writel(&ch_ctrl[channel].rs_control, - cy_readl(&ch_ctrl[channel]. - rs_control) & ~C_RS_DTR); + readl(&ch_ctrl[channel].rs_control) & + ~C_RS_DTR); #ifdef CY_DEBUG_DTR - printk("cyc:set_modem_info clearing Z DTR\n"); + printk(KERN_DEBUG "cyc:set_modem_info clearing " + "Z DTR\n"); #endif - CY_UNLOCK(info, flags); + spin_unlock_irqrestore(&card->card_lock, flags); } } else { return -ENODEV; } - CY_LOCK(info, flags); - retval = cyz_issue_cmd(&cy_card[info->card], - channel, C_CM_IOCTLM, 0L); + spin_lock_irqsave(&card->card_lock, flags); + retval = cyz_issue_cmd(card, channel, C_CM_IOCTLM, 0L); if (retval != 0) { - printk("cyc:set_modem_info retval on ttyC%d was %x\n", - info->line, retval); + printk(KERN_ERR "cyc:set_modem_info retval on ttyC%d " + "was %x\n", info->line, retval); } - CY_UNLOCK(info, flags); + spin_unlock_irqrestore(&card->card_lock, flags); } return 0; } /* cy_tiocmset */ @@ -3820,14 +3749,17 @@ cy_tiocmset(struct tty_struct *tty, struct file *file, */ static void cy_break(struct tty_struct *tty, int break_state) { - struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; + struct cyclades_port *info = tty->driver_data; + struct cyclades_card *card; unsigned long flags; if (serial_paranoia_check(info, tty->name, "cy_break")) return; - CY_LOCK(info, flags); - if (!IS_CYC_Z(cy_card[info->card])) { + card = info->card; + + spin_lock_irqsave(&card->card_lock, flags); + if (!IS_CYC_Z(*card)) { /* Let the transmit ISR take care of this (since it requires stuffing characters into the output stream). */ @@ -3835,18 +3767,18 @@ static void cy_break(struct tty_struct *tty, int break_state) if (!info->breakon) { info->breakon = 1; if (!info->xmit_cnt) { - CY_UNLOCK(info, flags); + spin_unlock_irqrestore(&card->card_lock, flags); start_xmit(info); - CY_LOCK(info, flags); + spin_lock_irqsave(&card->card_lock, flags); } } } else { if (!info->breakoff) { info->breakoff = 1; if (!info->xmit_cnt) { - CY_UNLOCK(info, flags); + spin_unlock_irqrestore(&card->card_lock, flags); start_xmit(info); - CY_LOCK(info, flags); + spin_lock_irqsave(&card->card_lock, flags); } } } @@ -3854,24 +3786,25 @@ static void cy_break(struct tty_struct *tty, int break_state) int retval; if (break_state == -1) { - retval = cyz_issue_cmd(&cy_card[info->card], - info->line - cy_card[info->card].first_line, + retval = cyz_issue_cmd(card, + info->line - card->first_line, C_CM_SET_BREAK, 0L); if (retval != 0) { - printk("cyc:cy_break (set) retval on ttyC%d " - "was %x\n", info->line, retval); + printk(KERN_ERR "cyc:cy_break (set) retval on " + "ttyC%d was %x\n", info->line, retval); } } else { - retval = cyz_issue_cmd(&cy_card[info->card], - info->line - cy_card[info->card].first_line, + retval = cyz_issue_cmd(card, + info->line - card->first_line, C_CM_CLR_BREAK, 0L); if (retval != 0) { - printk("cyc:cy_break (clr) retval on ttyC%d " - "was %x\n", info->line, retval); + printk(KERN_DEBUG "cyc:cy_break (clr) retval " + "on ttyC%d was %x\n", info->line, + retval); } } } - CY_UNLOCK(info, flags); + spin_unlock_irqrestore(&card->card_lock, flags); } /* cy_break */ static int @@ -3889,28 +3822,27 @@ get_mon_info(struct cyclades_port *info, struct cyclades_monitor __user * mon) static int set_threshold(struct cyclades_port *info, unsigned long value) { + struct cyclades_card *card; void __iomem *base_addr; - int card, channel, chip, index; + int channel, chip, index; unsigned long flags; card = info->card; - channel = info->line - cy_card[card].first_line; - if (!IS_CYC_Z(cy_card[card])) { + channel = info->line - card->first_line; + if (!IS_CYC_Z(*card)) { chip = channel >> 2; channel &= 0x03; - index = cy_card[card].bus_index; + index = card->bus_index; base_addr = - cy_card[card].base_addr + (cy_chip_offset[chip] << index); + card->base_addr + (cy_chip_offset[chip] << index); info->cor3 &= ~CyREC_FIFO; info->cor3 |= value & CyREC_FIFO; - CY_LOCK(info, flags); + spin_lock_irqsave(&card->card_lock, flags); cy_writeb(base_addr + (CyCOR3 << index), info->cor3); cyy_issue_cmd(base_addr, CyCOR_CHANGE | CyCOR3ch, index); - CY_UNLOCK(info, flags); - } else { - /* Nothing to do! */ + spin_unlock_irqrestore(&card->card_lock, flags); } return 0; } /* set_threshold */ @@ -3918,25 +3850,23 @@ static int set_threshold(struct cyclades_port *info, unsigned long value) static int get_threshold(struct cyclades_port *info, unsigned long __user * value) { + struct cyclades_card *card; void __iomem *base_addr; - int card, channel, chip, index; + int channel, chip, index; unsigned long tmp; card = info->card; - channel = info->line - cy_card[card].first_line; - if (!IS_CYC_Z(cy_card[card])) { + channel = info->line - card->first_line; + if (!IS_CYC_Z(*card)) { chip = channel >> 2; channel &= 0x03; - index = cy_card[card].bus_index; - base_addr = - cy_card[card].base_addr + (cy_chip_offset[chip] << index); + index = card->bus_index; + base_addr = card->base_addr + (cy_chip_offset[chip] << index); - tmp = cy_readb(base_addr + (CyCOR3 << index)) & CyREC_FIFO; + tmp = readb(base_addr + (CyCOR3 << index)) & CyREC_FIFO; return put_user(tmp, value); - } else { - /* Nothing to do! */ - return 0; } + return 0; } /* get_threshold */ static int @@ -3954,49 +3884,45 @@ get_default_threshold(struct cyclades_port *info, unsigned long __user * value) static int set_timeout(struct cyclades_port *info, unsigned long value) { + struct cyclades_card *card; void __iomem *base_addr; - int card, channel, chip, index; + int channel, chip, index; unsigned long flags; card = info->card; - channel = info->line - cy_card[card].first_line; - if (!IS_CYC_Z(cy_card[card])) { + channel = info->line - card->first_line; + if (!IS_CYC_Z(*card)) { chip = channel >> 2; channel &= 0x03; - index = cy_card[card].bus_index; - base_addr = - cy_card[card].base_addr + (cy_chip_offset[chip] << index); + index = card->bus_index; + base_addr = card->base_addr + (cy_chip_offset[chip] << index); - CY_LOCK(info, flags); + spin_lock_irqsave(&card->card_lock, flags); cy_writeb(base_addr + (CyRTPR << index), value & 0xff); - CY_UNLOCK(info, flags); - } else { - /* Nothing to do! */ + spin_unlock_irqrestore(&card->card_lock, flags); } return 0; } /* set_timeout */ static int get_timeout(struct cyclades_port *info, unsigned long __user * value) { + struct cyclades_card *card; void __iomem *base_addr; - int card, channel, chip, index; + int channel, chip, index; unsigned long tmp; card = info->card; - channel = info->line - cy_card[card].first_line; - if (!IS_CYC_Z(cy_card[card])) { + channel = info->line - card->first_line; + if (!IS_CYC_Z(*card)) { chip = channel >> 2; channel &= 0x03; - index = cy_card[card].bus_index; - base_addr = - cy_card[card].base_addr + (cy_chip_offset[chip] << index); + index = card->bus_index; + base_addr = card->base_addr + (cy_chip_offset[chip] << index); - tmp = cy_readb(base_addr + (CyRTPR << index)); + tmp = readb(base_addr + (CyRTPR << index)); return put_user(tmp, value); - } else { - /* Nothing to do! */ - return 0; } + return 0; } /* get_timeout */ static int set_default_timeout(struct cyclades_port *info, unsigned long value) @@ -4020,7 +3946,7 @@ static int cy_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg) { - struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; + struct cyclades_port *info = tty->driver_data; struct cyclades_icount cprev, cnow; /* kernel counter temps */ struct serial_icounter_struct __user *p_cuser; /* user space */ int ret_val = 0; @@ -4031,7 +3957,8 @@ cy_ioctl(struct tty_struct *tty, struct file *file, return -ENODEV; #ifdef CY_DEBUG_OTHER - printk("cyc:cy_ioctl ttyC%d, cmd = %x arg = %lx\n", info->line, cmd, arg); /* */ + printk(KERN_DEBUG "cyc:cy_ioctl ttyC%d, cmd = %x arg = %lx\n", + info->line, cmd, arg); #endif switch (cmd) { @@ -4076,14 +4003,6 @@ cy_ioctl(struct tty_struct *tty, struct file *file, case CYGETRTSDTR_INV: ret_val = info->rtsdtr_inv; break; - case CYGETCARDINFO: - if (copy_to_user(argp, &cy_card[info->card], - sizeof(struct cyclades_card))) { - ret_val = -EFAULT; - break; - } - ret_val = 0; - break; case CYGETCD1400VER: ret_val = info->chip_rev; break; @@ -4119,34 +4038,22 @@ cy_ioctl(struct tty_struct *tty, struct file *file, * Caller should use TIOCGICOUNT to see which one it was */ case TIOCMIWAIT: - CY_LOCK(info, flags); + spin_lock_irqsave(&info->card->card_lock, flags); /* note the counters on entry */ - cprev = info->icount; - CY_UNLOCK(info, flags); - while (1) { - interruptible_sleep_on(&info->delta_msr_wait); - /* see if a signal did it */ - if (signal_pending(current)) { - return -ERESTARTSYS; - } - - CY_LOCK(info, flags); + cnow = info->icount; + spin_unlock_irqrestore(&info->card->card_lock, flags); + ret_val = wait_event_interruptible(info->delta_msr_wait, ({ + cprev = cnow; + spin_lock_irqsave(&info->card->card_lock, flags); cnow = info->icount; /* atomic copy */ - CY_UNLOCK(info, flags); + spin_unlock_irqrestore(&info->card->card_lock, flags); - if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && - cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) { - return -EIO; /* no change => error */ - } - if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || - ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || - ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || - ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) { - return 0; - } - cprev = cnow; - } - /* NOTREACHED */ + ((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || + ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || + ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || + ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)); + })); + break; /* * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) @@ -4155,9 +4062,9 @@ cy_ioctl(struct tty_struct *tty, struct file *file, * RI where only 0->1 is counted. */ case TIOCGICOUNT: - CY_LOCK(info, flags); + spin_lock_irqsave(&info->card->card_lock, flags); cnow = info->icount; - CY_UNLOCK(info, flags); + spin_unlock_irqrestore(&info->card->card_lock, flags); p_cuser = argp; ret_val = put_user(cnow.cts, &p_cuser->cts); if (ret_val) @@ -4199,7 +4106,7 @@ cy_ioctl(struct tty_struct *tty, struct file *file, } #ifdef CY_DEBUG_OTHER - printk(" cyc:cy_ioctl done\n"); + printk(KERN_DEBUG "cyc:cy_ioctl done\n"); #endif return ret_val; @@ -4213,10 +4120,10 @@ cy_ioctl(struct tty_struct *tty, struct file *file, */ static void cy_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { - struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; + struct cyclades_port *info = tty->driver_data; #ifdef CY_DEBUG_OTHER - printk("cyc:cy_set_termios ttyC%d\n", info->line); + printk(KERN_DEBUG "cyc:cy_set_termios ttyC%d\n", info->line); #endif if (tty->termios->c_cflag == old_termios->c_cflag && @@ -4248,8 +4155,9 @@ static void cy_set_termios(struct tty_struct *tty, struct ktermios *old_termios) */ static void cy_send_xchar(struct tty_struct *tty, char ch) { - struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; - int card, channel; + struct cyclades_port *info = tty->driver_data; + struct cyclades_card *card; + int channel; if (serial_paranoia_check(info, tty->name, "cy_send_xchar")) return; @@ -4260,15 +4168,13 @@ static void cy_send_xchar(struct tty_struct *tty, char ch) cy_start(tty); card = info->card; - channel = info->line - cy_card[card].first_line; + channel = info->line - card->first_line; - if (IS_CYC_Z(cy_card[card])) { + if (IS_CYC_Z(*card)) { if (ch == STOP_CHAR(tty)) - cyz_issue_cmd(&cy_card[card], channel, C_CM_SENDXOFF, - 0L); + cyz_issue_cmd(card, channel, C_CM_SENDXOFF, 0L); else if (ch == START_CHAR(tty)) - cyz_issue_cmd(&cy_card[card], channel, C_CM_SENDXON, - 0L); + cyz_issue_cmd(card, channel, C_CM_SENDXON, 0L); } } @@ -4278,15 +4184,16 @@ static void cy_send_xchar(struct tty_struct *tty, char ch) */ static void cy_throttle(struct tty_struct *tty) { - struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; + struct cyclades_port *info = tty->driver_data; + struct cyclades_card *card; unsigned long flags; void __iomem *base_addr; - int card, chip, channel, index; + int chip, channel, index; #ifdef CY_DEBUG_THROTTLE char buf[64]; - printk("cyc:throttle %s: %d....ttyC%d\n", tty_name(tty, buf), + printk(KERN_DEBUG "cyc:throttle %s: %ld...ttyC%d\n", tty_name(tty, buf), tty->ldisc.chars_in_buffer(tty), info->line); #endif @@ -4297,22 +4204,22 @@ static void cy_throttle(struct tty_struct *tty) card = info->card; if (I_IXOFF(tty)) { - if (!IS_CYC_Z(cy_card[card])) + if (!IS_CYC_Z(*card)) cy_send_xchar(tty, STOP_CHAR(tty)); else info->throttle = 1; } if (tty->termios->c_cflag & CRTSCTS) { - channel = info->line - cy_card[card].first_line; - if (!IS_CYC_Z(cy_card[card])) { + channel = info->line - card->first_line; + if (!IS_CYC_Z(*card)) { chip = channel >> 2; channel &= 0x03; - index = cy_card[card].bus_index; - base_addr = cy_card[card].base_addr + + index = card->bus_index; + base_addr = card->base_addr + (cy_chip_offset[chip] << index); - CY_LOCK(info, flags); + spin_lock_irqsave(&card->card_lock, flags); cy_writeb(base_addr + (CyCAR << index), (u_char) channel); if (info->rtsdtr_inv) { @@ -4322,7 +4229,7 @@ static void cy_throttle(struct tty_struct *tty) cy_writeb(base_addr + (CyMSVR1 << index), ~CyRTS); } - CY_UNLOCK(info, flags); + spin_unlock_irqrestore(&card->card_lock, flags); } else { info->throttle = 1; } @@ -4336,16 +4243,17 @@ static void cy_throttle(struct tty_struct *tty) */ static void cy_unthrottle(struct tty_struct *tty) { - struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; + struct cyclades_port *info = tty->driver_data; + struct cyclades_card *card; unsigned long flags; void __iomem *base_addr; - int card, chip, channel, index; + int chip, channel, index; #ifdef CY_DEBUG_THROTTLE char buf[64]; - printk("cyc:unthrottle %s: %d....ttyC%d\n", tty_name(tty, buf), - tty->ldisc.chars_in_buffer(tty), info->line); + printk(KERN_DEBUG "cyc:unthrottle %s: %ld...ttyC%d\n", + tty_name(tty, buf), tty->ldisc.chars_in_buffer(tty),info->line); #endif if (serial_paranoia_check(info, tty->name, "cy_unthrottle")) { @@ -4361,15 +4269,15 @@ static void cy_unthrottle(struct tty_struct *tty) if (tty->termios->c_cflag & CRTSCTS) { card = info->card; - channel = info->line - cy_card[card].first_line; - if (!IS_CYC_Z(cy_card[card])) { + channel = info->line - card->first_line; + if (!IS_CYC_Z(*card)) { chip = channel >> 2; channel &= 0x03; - index = cy_card[card].bus_index; - base_addr = cy_card[card].base_addr + + index = card->bus_index; + base_addr = card->base_addr + (cy_chip_offset[chip] << index); - CY_LOCK(info, flags); + spin_lock_irqsave(&card->card_lock, flags); cy_writeb(base_addr + (CyCAR << index), (u_char) channel); if (info->rtsdtr_inv) { @@ -4379,7 +4287,7 @@ static void cy_unthrottle(struct tty_struct *tty) cy_writeb(base_addr + (CyMSVR1 << index), CyRTS); } - CY_UNLOCK(info, flags); + spin_unlock_irqrestore(&card->card_lock, flags); } else { info->throttle = 0; } @@ -4392,102 +4300,96 @@ static void cy_unthrottle(struct tty_struct *tty) static void cy_stop(struct tty_struct *tty) { struct cyclades_card *cinfo; - struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; + struct cyclades_port *info = tty->driver_data; void __iomem *base_addr; int chip, channel, index; unsigned long flags; #ifdef CY_DEBUG_OTHER - printk("cyc:cy_stop ttyC%d\n", info->line); /* */ + printk(KERN_DEBUG "cyc:cy_stop ttyC%d\n", info->line); #endif if (serial_paranoia_check(info, tty->name, "cy_stop")) return; - cinfo = &cy_card[info->card]; + cinfo = info->card; channel = info->line - cinfo->first_line; if (!IS_CYC_Z(*cinfo)) { index = cinfo->bus_index; chip = channel >> 2; channel &= 0x03; - base_addr = cy_card[info->card].base_addr + - (cy_chip_offset[chip] << index); + base_addr = cinfo->base_addr + (cy_chip_offset[chip] << index); - CY_LOCK(info, flags); + spin_lock_irqsave(&cinfo->card_lock, flags); cy_writeb(base_addr + (CyCAR << index), (u_char)(channel & 0x0003)); /* index channel */ cy_writeb(base_addr + (CySRER << index), - cy_readb(base_addr + (CySRER << index)) & ~CyTxRdy); - CY_UNLOCK(info, flags); - } else { - /* Nothing to do! */ + readb(base_addr + (CySRER << index)) & ~CyTxRdy); + spin_unlock_irqrestore(&cinfo->card_lock, flags); } } /* cy_stop */ static void cy_start(struct tty_struct *tty) { struct cyclades_card *cinfo; - struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; + struct cyclades_port *info = tty->driver_data; void __iomem *base_addr; int chip, channel, index; unsigned long flags; #ifdef CY_DEBUG_OTHER - printk("cyc:cy_start ttyC%d\n", info->line); /* */ + printk(KERN_DEBUG "cyc:cy_start ttyC%d\n", info->line); #endif if (serial_paranoia_check(info, tty->name, "cy_start")) return; - cinfo = &cy_card[info->card]; + cinfo = info->card; channel = info->line - cinfo->first_line; index = cinfo->bus_index; if (!IS_CYC_Z(*cinfo)) { chip = channel >> 2; channel &= 0x03; - base_addr = cy_card[info->card].base_addr + - (cy_chip_offset[chip] << index); + base_addr = cinfo->base_addr + (cy_chip_offset[chip] << index); - CY_LOCK(info, flags); + spin_lock_irqsave(&cinfo->card_lock, flags); cy_writeb(base_addr + (CyCAR << index), (u_char) (channel & 0x0003)); /* index channel */ cy_writeb(base_addr + (CySRER << index), - cy_readb(base_addr + (CySRER << index)) | CyTxRdy); - CY_UNLOCK(info, flags); - } else { - /* Nothing to do! */ + readb(base_addr + (CySRER << index)) | CyTxRdy); + spin_unlock_irqrestore(&cinfo->card_lock, flags); } } /* cy_start */ static void cy_flush_buffer(struct tty_struct *tty) { - struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; - int card, channel, retval; + struct cyclades_port *info = tty->driver_data; + struct cyclades_card *card; + int channel, retval; unsigned long flags; #ifdef CY_DEBUG_IO - printk("cyc:cy_flush_buffer ttyC%d\n", info->line); /* */ + printk(KERN_DEBUG "cyc:cy_flush_buffer ttyC%d\n", info->line); #endif if (serial_paranoia_check(info, tty->name, "cy_flush_buffer")) return; card = info->card; - channel = (info->line) - (cy_card[card].first_line); + channel = info->line - card->first_line; - CY_LOCK(info, flags); + spin_lock_irqsave(&card->card_lock, flags); info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; - CY_UNLOCK(info, flags); + spin_unlock_irqrestore(&card->card_lock, flags); - if (IS_CYC_Z(cy_card[card])) { /* If it is a Z card, flush the on-board + if (IS_CYC_Z(*card)) { /* If it is a Z card, flush the on-board buffers as well */ - CY_LOCK(info, flags); - retval = - cyz_issue_cmd(&cy_card[card], channel, C_CM_FLUSH_TX, 0L); + spin_lock_irqsave(&card->card_lock, flags); + retval = cyz_issue_cmd(card, channel, C_CM_FLUSH_TX, 0L); if (retval != 0) { - printk("cyc: flush_buffer retval on ttyC%d was %x\n", - info->line, retval); + printk(KERN_ERR "cyc: flush_buffer retval on ttyC%d " + "was %x\n", info->line, retval); } - CY_UNLOCK(info, flags); + spin_unlock_irqrestore(&card->card_lock, flags); } tty_wakeup(tty); } /* cy_flush_buffer */ @@ -4497,10 +4399,10 @@ static void cy_flush_buffer(struct tty_struct *tty) */ static void cy_hangup(struct tty_struct *tty) { - struct cyclades_port *info = (struct cyclades_port *)tty->driver_data; + struct cyclades_port *info = tty->driver_data; #ifdef CY_DEBUG_OTHER - printk("cyc:cy_hangup ttyC%d\n", info->line); /* */ + printk(KERN_DEBUG "cyc:cy_hangup ttyC%d\n", info->line); #endif if (serial_paranoia_check(info, tty->name, "cy_hangup")) @@ -4511,7 +4413,8 @@ static void cy_hangup(struct tty_struct *tty) info->event = 0; info->count = 0; #ifdef CY_DEBUG_COUNT - printk("cyc:cy_hangup (%d): setting count to 0\n", current->pid); + printk(KERN_DEBUG "cyc:cy_hangup (%d): setting count to 0\n", + current->pid); #endif info->tty = NULL; info->flags &= ~ASYNC_NORMAL_ACTIVE; @@ -4526,10 +4429,107 @@ static void cy_hangup(struct tty_struct *tty) * --------------------------------------------------------------------- */ +static int __devinit cy_init_card(struct cyclades_card *cinfo) +{ + struct cyclades_port *info; + u32 mailbox; + unsigned int nports; + unsigned short chip_number; + int index, port; + + spin_lock_init(&cinfo->card_lock); + + if (IS_CYC_Z(*cinfo)) { /* Cyclades-Z */ + mailbox = readl(&((struct RUNTIME_9060 __iomem *) + cinfo->ctl_addr)->mail_box_0); + nports = (mailbox == ZE_V1) ? ZE_V1_NPORTS : 8; + cinfo->intr_enabled = 0; + cinfo->nports = 0; /* Will be correctly set later, after + Z FW is loaded */ + } else { + index = cinfo->bus_index; + nports = cinfo->nports = CyPORTS_PER_CHIP * cinfo->num_chips; + } + + cinfo->ports = kzalloc(sizeof(*cinfo->ports) * nports, GFP_KERNEL); + if (cinfo->ports == NULL) { + printk(KERN_ERR "Cyclades: cannot allocate ports\n"); + cinfo->nports = 0; + return -ENOMEM; + } + + for (port = cinfo->first_line; port < cinfo->first_line + nports; + port++) { + info = &cinfo->ports[port - cinfo->first_line]; + info->magic = CYCLADES_MAGIC; + info->card = cinfo; + info->line = port; + info->flags = STD_COM_FLAGS; + info->closing_wait = CLOSING_WAIT_DELAY; + info->close_delay = 5 * HZ / 10; + + INIT_WORK(&info->tqueue, do_softint); + init_waitqueue_head(&info->open_wait); + init_waitqueue_head(&info->close_wait); + init_completion(&info->shutdown_wait); + init_waitqueue_head(&info->delta_msr_wait); + + if (IS_CYC_Z(*cinfo)) { + info->type = PORT_STARTECH; + if (mailbox == ZO_V1) + info->xmit_fifo_size = CYZ_FIFO_SIZE; + else + info->xmit_fifo_size = 4 * CYZ_FIFO_SIZE; +#ifdef CONFIG_CYZ_INTR + setup_timer(&cyz_rx_full_timer[port], + cyz_rx_restart, (unsigned long)info); +#endif + } else { + info->type = PORT_CIRRUS; + info->xmit_fifo_size = CyMAX_CHAR_FIFO; + info->cor1 = CyPARITY_NONE | Cy_1_STOP | Cy_8_BITS; + info->cor2 = CyETC; + info->cor3 = 0x08; /* _very_ small rcv threshold */ + + chip_number = (port - cinfo->first_line) / 4; + if ((info->chip_rev = readb(cinfo->base_addr + + (cy_chip_offset[chip_number] << + index) + (CyGFRCR << index))) >= + CD1400_REV_J) { + /* It is a CD1400 rev. J or later */ + info->tbpr = baud_bpr_60[13]; /* Tx BPR */ + info->tco = baud_co_60[13]; /* Tx CO */ + info->rbpr = baud_bpr_60[13]; /* Rx BPR */ + info->rco = baud_co_60[13]; /* Rx CO */ + info->rtsdtr_inv = 1; + } else { + info->tbpr = baud_bpr_25[13]; /* Tx BPR */ + info->tco = baud_co_25[13]; /* Tx CO */ + info->rbpr = baud_bpr_25[13]; /* Rx BPR */ + info->rco = baud_co_25[13]; /* Rx CO */ + info->rtsdtr_inv = 0; + } + info->read_status_mask = CyTIMEOUT | CySPECHAR | + CyBREAK | CyPARITY | CyFRAME | CyOVERRUN; + } + + } + +#ifndef CONFIG_CYZ_INTR + if (IS_CYC_Z(*cinfo) && !timer_pending(&cyz_timerlist)) { + mod_timer(&cyz_timerlist, jiffies + 1); +#ifdef CY_PCI_DEBUG + printk(KERN_DEBUG "Cyclades-Z polling initialized\n"); +#endif + } +#endif + return 0; +} + /* initialize chips on Cyclom-Y card -- return number of valid chips (which is number of ports/4) */ -static unsigned short __init -cyy_init_card(void __iomem * true_base_addr, int index) +static unsigned short __devinit cyy_init_card(void __iomem *true_base_addr, + int index) { unsigned int chip_number; void __iomem *base_addr; @@ -4544,7 +4544,7 @@ cyy_init_card(void __iomem * true_base_addr, int index) base_addr = true_base_addr + (cy_chip_offset[chip_number] << index); mdelay(1); - if (cy_readb(base_addr + (CyCCR << index)) != 0x00) { + if (readb(base_addr + (CyCCR << index)) != 0x00) { /************* printk(" chip #%d at %#6lx is never idle (CCR != 0)\n", chip_number, (unsigned long)base_addr); @@ -4561,7 +4561,7 @@ cyy_init_card(void __iomem * true_base_addr, int index) chip 4 GFRCR register appears at chip 0, there is no chip 4 and this must be a Cyclom-16Y, not a Cyclom-32Ye. */ - if (chip_number == 4 && cy_readb(true_base_addr + + if (chip_number == 4 && readb(true_base_addr + (cy_chip_offset[0] << index) + (CyGFRCR << index)) == 0) { return chip_number; @@ -4570,7 +4570,7 @@ cyy_init_card(void __iomem * true_base_addr, int index) cy_writeb(base_addr + (CyCCR << index), CyCHIP_RESET); mdelay(1); - if (cy_readb(base_addr + (CyGFRCR << index)) == 0x00) { + if (readb(base_addr + (CyGFRCR << index)) == 0x00) { /* printk(" chip #%d at %#6lx is not responding ", chip_number, (unsigned long)base_addr); @@ -4578,7 +4578,7 @@ cyy_init_card(void __iomem * true_base_addr, int index) */ return chip_number; } - if ((0xf0 & (cy_readb(base_addr + (CyGFRCR << index)))) != + if ((0xf0 & (readb(base_addr + (CyGFRCR << index)))) != 0x40) { /* printk(" chip #%d at %#6lx is not valid (GFRCR == " @@ -4589,7 +4589,7 @@ cyy_init_card(void __iomem * true_base_addr, int index) return chip_number; } cy_writeb(base_addr + (CyGCR << index), CyCH0_SERIAL); - if (cy_readb(base_addr + (CyGFRCR << index)) >= CD1400_REV_J) { + if (readb(base_addr + (CyGFRCR << index)) >= CD1400_REV_J) { /* It is a CD1400 rev. J or later */ /* Impossible to reach 5ms with this chip. Changed to 2ms instead (f = 500 Hz). */ @@ -4602,7 +4602,7 @@ cyy_init_card(void __iomem * true_base_addr, int index) /* printk(" chip #%d at %#6lx is rev 0x%2x\n", chip_number, (unsigned long)base_addr, - cy_readb(base_addr+(CyGFRCR<<index))); + readb(base_addr+(CyGFRCR<<index))); */ } return chip_number; @@ -4647,9 +4647,15 @@ static int __init cy_detect_isa(void) /* probe for CD1400... */ cy_isa_address = ioremap(isa_address, CyISA_Ywin); + if (cy_isa_address == NULL) { + printk(KERN_ERR "Cyclom-Y/ISA: can't remap base " + "address\n"); + continue; + } cy_isa_nchan = CyPORTS_PER_CHIP * cyy_init_card(cy_isa_address, 0); if (cy_isa_nchan == 0) { + iounmap(cy_isa_address); continue; } #ifdef MODULE @@ -4660,40 +4666,42 @@ static int __init cy_detect_isa(void) /* find out the board's irq by probing */ cy_isa_irq = detect_isa_irq(cy_isa_address); if (cy_isa_irq == 0) { - printk("Cyclom-Y/ISA found at 0x%lx ", + printk(KERN_ERR "Cyclom-Y/ISA found at 0x%lx, but the " + "IRQ could not be detected.\n", (unsigned long)cy_isa_address); - printk("but the IRQ could not be detected.\n"); + iounmap(cy_isa_address); continue; } if ((cy_next_channel + cy_isa_nchan) > NR_PORTS) { - printk("Cyclom-Y/ISA found at 0x%lx ", + printk(KERN_ERR "Cyclom-Y/ISA found at 0x%lx, but no " + "more channels are available. Change NR_PORTS " + "in cyclades.c and recompile kernel.\n", (unsigned long)cy_isa_address); - printk("but no more channels are available.\n"); - printk("Change NR_PORTS in cyclades.c and recompile " - "kernel.\n"); + iounmap(cy_isa_address); return nboard; } /* fill the next cy_card structure available */ for (j = 0; j < NR_CARDS; j++) { - if (cy_card[j].base_addr == 0) + if (cy_card[j].base_addr == NULL) break; } if (j == NR_CARDS) { /* no more cy_cards available */ - printk("Cyclom-Y/ISA found at 0x%lx ", + printk(KERN_ERR "Cyclom-Y/ISA found at 0x%lx, but no " + "more cards can be used. Change NR_CARDS in " + "cyclades.c and recompile kernel.\n", (unsigned long)cy_isa_address); - printk("but no more cards can be used .\n"); - printk("Change NR_CARDS in cyclades.c and recompile " - "kernel.\n"); + iounmap(cy_isa_address); return nboard; } /* allocate IRQ */ if (request_irq(cy_isa_irq, cyy_interrupt, IRQF_DISABLED, "Cyclom-Y", &cy_card[j])) { - printk("Cyclom-Y/ISA found at 0x%lx ", - (unsigned long)cy_isa_address); - printk("but could not allocate IRQ#%d.\n", cy_isa_irq); + printk(KERN_ERR "Cyclom-Y/ISA found at 0x%lx, but " + "could not allocate IRQ#%d.\n", + (unsigned long)cy_isa_address, cy_isa_irq); + iounmap(cy_isa_address); return nboard; } @@ -4704,15 +4712,23 @@ static int __init cy_detect_isa(void) cy_card[j].bus_index = 0; cy_card[j].first_line = cy_next_channel; cy_card[j].num_chips = cy_isa_nchan / 4; + if (cy_init_card(&cy_card[j])) { + cy_card[j].base_addr = NULL; + free_irq(cy_isa_irq, &cy_card[j]); + iounmap(cy_isa_address); + continue; + } nboard++; - /* print message */ - printk("Cyclom-Y/ISA #%d: 0x%lx-0x%lx, IRQ%d, ", + printk(KERN_INFO "Cyclom-Y/ISA #%d: 0x%lx-0x%lx, IRQ%d found: " + "%d channels starting from port %d\n", j + 1, (unsigned long)cy_isa_address, (unsigned long)(cy_isa_address + (CyISA_Ywin - 1)), - cy_isa_irq); - printk("%d channels starting from port %d.\n", - cy_isa_nchan, cy_next_channel); + cy_isa_irq, cy_isa_nchan, cy_next_channel); + + for (j = cy_next_channel; + j < cy_next_channel + cy_isa_nchan; j++) + tty_register_device(cy_serial_driver, j, NULL); cy_next_channel += cy_isa_nchan; } return nboard; @@ -4721,510 +4737,310 @@ static int __init cy_detect_isa(void) #endif /* CONFIG_ISA */ } /* cy_detect_isa */ -static void plx_init(void __iomem * addr, uclong initctl) +#ifdef CONFIG_PCI +static void __devinit plx_init(void __iomem * addr, __u32 initctl) { /* Reset PLX */ - cy_writel(addr + initctl, cy_readl(addr + initctl) | 0x40000000); + cy_writel(addr + initctl, readl(addr + initctl) | 0x40000000); udelay(100L); - cy_writel(addr + initctl, cy_readl(addr + initctl) & ~0x40000000); + cy_writel(addr + initctl, readl(addr + initctl) & ~0x40000000); /* Reload Config. Registers from EEPROM */ - cy_writel(addr + initctl, cy_readl(addr + initctl) | 0x20000000); + cy_writel(addr + initctl, readl(addr + initctl) | 0x20000000); udelay(100L); - cy_writel(addr + initctl, cy_readl(addr + initctl) & ~0x20000000); + cy_writel(addr + initctl, readl(addr + initctl) & ~0x20000000); } -/* - * --------------------------------------------------------------------- - * cy_detect_pci() - Test PCI bus presence and Cyclom-Ye/PCI. - * sets global variables and return the number of PCI boards found. - * --------------------------------------------------------------------- - */ -static int __init cy_detect_pci(void) +static int __devinit cy_pci_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) { -#ifdef CONFIG_PCI - - struct pci_dev *pdev = NULL; - unsigned char cyy_rev_id; - unsigned char cy_pci_irq = 0; - uclong cy_pci_phys0, cy_pci_phys2; - void __iomem *cy_pci_addr0, *cy_pci_addr2; - unsigned short i, j, cy_pci_nchan, plx_ver; - unsigned short device_id, dev_index = 0; - uclong mailbox; - uclong ZeIndex = 0; - void __iomem *Ze_addr0[NR_CARDS], *Ze_addr2[NR_CARDS]; - uclong Ze_phys0[NR_CARDS], Ze_phys2[NR_CARDS]; - unsigned char Ze_irq[NR_CARDS]; - struct pci_dev *Ze_pdev[NR_CARDS]; - - for (i = 0; i < NR_CARDS; i++) { - /* look for a Cyclades card by vendor and device id */ - while ((device_id = cy_pci_dev_id[dev_index].device) != 0) { - if ((pdev = pci_get_device(PCI_VENDOR_ID_CYCLADES, - device_id, pdev)) == NULL) { - dev_index++; /* try next device id */ - } else { - break; /* found a board */ - } - } - - if (device_id == 0) - break; - - if (pci_enable_device(pdev)) - continue; - - /* read PCI configuration area */ - cy_pci_irq = pdev->irq; - cy_pci_phys0 = pci_resource_start(pdev, 0); - cy_pci_phys2 = pci_resource_start(pdev, 2); - pci_read_config_byte(pdev, PCI_REVISION_ID, &cyy_rev_id); + void __iomem *addr0 = NULL, *addr2 = NULL; + char *card_name = NULL; + u32 mailbox; + unsigned int device_id, nchan = 0, card_no, i; + unsigned char plx_ver; + int retval, irq; + + retval = pci_enable_device(pdev); + if (retval) { + dev_err(&pdev->dev, "cannot enable device\n"); + goto err; + } - device_id &= ~PCI_DEVICE_ID_MASK; + /* read PCI configuration area */ + irq = pdev->irq; + device_id = pdev->device & ~PCI_DEVICE_ID_MASK; - if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo || - device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi) { -#ifdef CY_PCI_DEBUG - printk("Cyclom-Y/PCI (bus=0x0%x, pci_id=0x%x, ", - pdev->bus->number, pdev->devfn); - printk("rev_id=%d) IRQ%d\n", - cyy_rev_id, (int)cy_pci_irq); - printk("Cyclom-Y/PCI:found winaddr=0x%lx " - "ctladdr=0x%lx\n", - (ulong)cy_pci_phys2, (ulong)cy_pci_phys0); +#if defined(__alpha__) + if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo) { /* below 1M? */ + dev_err(&pdev->dev, "Cyclom-Y/PCI not supported for low " + "addresses on Alpha systems.\n"); + retval = -EIO; + goto err_dis; + } #endif + if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Lo) { + dev_err(&pdev->dev, "Cyclades-Z/PCI not supported for low " + "addresses\n"); + retval = -EIO; + goto err_dis; + } - if (pci_resource_flags(pdev, 2) & IORESOURCE_IO) { - printk(" Warning: PCI I/O bit incorrectly " - "set. Ignoring it...\n"); - pdev->resource[2].flags &= ~IORESOURCE_IO; - } + if (pci_resource_flags(pdev, 2) & IORESOURCE_IO) { + dev_warn(&pdev->dev, "PCI I/O bit incorrectly set. Ignoring " + "it...\n"); + pdev->resource[2].flags &= ~IORESOURCE_IO; + } - /* Although we don't use this I/O region, we should - request it from the kernel anyway, to avoid problems - with other drivers accessing it. */ - if (pci_request_regions(pdev, "Cyclom-Y") != 0) { - printk(KERN_ERR "cyclades: failed to reserve " - "PCI resources\n"); - continue; - } -#if defined(__alpha__) - if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo) { /* below 1M? */ - printk("Cyclom-Y/PCI (bus=0x0%x, pci_id=0x%x, ", - pdev->bus->number, pdev->devfn); - printk("rev_id=%d) IRQ%d\n", - cyy_rev_id, (int)cy_pci_irq); - printk("Cyclom-Y/PCI:found winaddr=0x%lx " - "ctladdr=0x%lx\n", - (ulong)cy_pci_phys2, - (ulong)cy_pci_phys0); - printk("Cyclom-Y/PCI not supported for low " - "addresses in Alpha systems.\n"); - i--; - continue; - } -#endif - cy_pci_addr0 = ioremap(cy_pci_phys0, CyPCI_Yctl); - cy_pci_addr2 = ioremap(cy_pci_phys2, CyPCI_Ywin); + retval = pci_request_regions(pdev, "cyclades"); + if (retval) { + dev_err(&pdev->dev, "failed to reserve resources\n"); + goto err_dis; + } -#ifdef CY_PCI_DEBUG - printk("Cyclom-Y/PCI: relocate winaddr=0x%lx " - "ctladdr=0x%lx\n", - (u_long)cy_pci_addr2, (u_long)cy_pci_addr0); -#endif - cy_pci_nchan = (unsigned short)(CyPORTS_PER_CHIP * - cyy_init_card(cy_pci_addr2, 1)); - if (cy_pci_nchan == 0) { - printk("Cyclom-Y PCI host card with "); - printk("no Serial-Modules at 0x%lx.\n", - (ulong) cy_pci_phys2); - i--; - continue; - } - if ((cy_next_channel + cy_pci_nchan) > NR_PORTS) { - printk("Cyclom-Y/PCI found at 0x%lx ", - (ulong) cy_pci_phys2); - printk("but no channels are available.\n"); - printk("Change NR_PORTS in cyclades.c and " - "recompile kernel.\n"); - return i; - } - /* fill the next cy_card structure available */ - for (j = 0; j < NR_CARDS; j++) { - if (cy_card[j].base_addr == 0) - break; - } - if (j == NR_CARDS) { /* no more cy_cards available */ - printk("Cyclom-Y/PCI found at 0x%lx ", - (ulong) cy_pci_phys2); - printk("but no more cards can be used.\n"); - printk("Change NR_CARDS in cyclades.c and " - "recompile kernel.\n"); - return i; - } + retval = -EIO; + if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo || + device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi) { + card_name = "Cyclom-Y"; - /* allocate IRQ */ - if (request_irq(cy_pci_irq, cyy_interrupt, - IRQF_SHARED, "Cyclom-Y", &cy_card[j])) { - printk("Cyclom-Y/PCI found at 0x%lx ", - (ulong) cy_pci_phys2); - printk("but could not allocate IRQ%d.\n", - cy_pci_irq); - return i; - } + addr0 = pci_iomap(pdev, 0, CyPCI_Yctl); + if (addr0 == NULL) { + dev_err(&pdev->dev, "can't remap ctl region\n"); + goto err_reg; + } + addr2 = pci_iomap(pdev, 2, CyPCI_Ywin); + if (addr2 == NULL) { + dev_err(&pdev->dev, "can't remap base region\n"); + goto err_unmap; + } - /* set cy_card */ - cy_card[j].base_phys = (ulong) cy_pci_phys2; - cy_card[j].ctl_phys = (ulong) cy_pci_phys0; - cy_card[j].base_addr = cy_pci_addr2; - cy_card[j].ctl_addr = cy_pci_addr0; - cy_card[j].irq = (int)cy_pci_irq; - cy_card[j].bus_index = 1; - cy_card[j].first_line = cy_next_channel; - cy_card[j].num_chips = cy_pci_nchan / 4; - cy_card[j].pdev = pdev; - - /* enable interrupts in the PCI interface */ - plx_ver = cy_readb(cy_pci_addr2 + CyPLX_VER) & 0x0f; - switch (plx_ver) { - case PLX_9050: - - cy_writeb(cy_pci_addr0 + 0x4c, 0x43); - break; + nchan = CyPORTS_PER_CHIP * cyy_init_card(addr2, 1); + if (nchan == 0) { + dev_err(&pdev->dev, "Cyclom-Y PCI host card with no " + "Serial-Modules\n"); + return -EIO; + } + } else if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Hi) { + struct RUNTIME_9060 __iomem *ctl_addr; - case PLX_9060: - case PLX_9080: - default: /* Old boards, use PLX_9060 */ - - plx_init(cy_pci_addr0, 0x6c); - /* For some yet unknown reason, once the PLX9060 reloads - the EEPROM, the IRQ is lost and, thus, we have to - re-write it to the PCI config. registers. - This will remain here until we find a permanent - fix. */ - pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, - cy_pci_irq); - - cy_writew(cy_pci_addr0 + 0x68, - cy_readw(cy_pci_addr0 + - 0x68) | 0x0900); - break; - } + ctl_addr = addr0 = pci_iomap(pdev, 0, CyPCI_Zctl); + if (addr0 == NULL) { + dev_err(&pdev->dev, "can't remap ctl region\n"); + goto err_reg; + } - /* print message */ - printk("Cyclom-Y/PCI #%d: 0x%lx-0x%lx, IRQ%d, ", - j + 1, (ulong)cy_pci_phys2, - (ulong) (cy_pci_phys2 + CyPCI_Ywin - 1), - (int)cy_pci_irq); - printk("%d channels starting from port %d.\n", - cy_pci_nchan, cy_next_channel); - - cy_next_channel += cy_pci_nchan; - } else if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Lo) { - /* print message */ - printk("Cyclades-Z/PCI (bus=0x0%x, pci_id=0x%x, ", - pdev->bus->number, pdev->devfn); - printk("rev_id=%d) IRQ%d\n", - cyy_rev_id, (int)cy_pci_irq); - printk("Cyclades-Z/PCI: found winaddr=0x%lx " - "ctladdr=0x%lx\n", - (ulong)cy_pci_phys2, (ulong)cy_pci_phys0); - printk("Cyclades-Z/PCI not supported for low " - "addresses\n"); - break; - } else if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Hi) { -#ifdef CY_PCI_DEBUG - printk("Cyclades-Z/PCI (bus=0x0%x, pci_id=0x%x, ", - pdev->bus->number, pdev->devfn); - printk("rev_id=%d) IRQ%d\n", - cyy_rev_id, (int)cy_pci_irq); - printk("Cyclades-Z/PCI: found winaddr=0x%lx " - "ctladdr=0x%lx\n", - (ulong) cy_pci_phys2, (ulong) cy_pci_phys0); -#endif - cy_pci_addr0 = ioremap(cy_pci_phys0, CyPCI_Zctl); - - /* Disable interrupts on the PLX before resetting it */ - cy_writew(cy_pci_addr0 + 0x68, - cy_readw(cy_pci_addr0 + 0x68) & ~0x0900); - - plx_init(cy_pci_addr0, 0x6c); - /* For some yet unknown reason, once the PLX9060 reloads - the EEPROM, the IRQ is lost and, thus, we have to - re-write it to the PCI config. registers. - This will remain here until we find a permanent - fix. */ - pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, - cy_pci_irq); - - mailbox = - (uclong)cy_readl(&((struct RUNTIME_9060 __iomem *) - cy_pci_addr0)->mail_box_0); - - if (pci_resource_flags(pdev, 2) & IORESOURCE_IO) { - printk(" Warning: PCI I/O bit incorrectly " - "set. Ignoring it...\n"); - pdev->resource[2].flags &= ~IORESOURCE_IO; - } + /* Disable interrupts on the PLX before resetting it */ + cy_writew(addr0 + 0x68, + readw(addr0 + 0x68) & ~0x0900); + + plx_init(addr0, 0x6c); + /* For some yet unknown reason, once the PLX9060 reloads + the EEPROM, the IRQ is lost and, thus, we have to + re-write it to the PCI config. registers. + This will remain here until we find a permanent + fix. */ + pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, irq); + + mailbox = (u32)readl(&ctl_addr->mail_box_0); + + addr2 = pci_iomap(pdev, 2, mailbox == ZE_V1 ? + CyPCI_Ze_win : CyPCI_Zwin); + if (addr2 == NULL) { + dev_err(&pdev->dev, "can't remap base region\n"); + goto err_unmap; + } - /* Although we don't use this I/O region, we should - request it from the kernel anyway, to avoid problems - with other drivers accessing it. */ - if (pci_request_regions(pdev, "Cyclades-Z") != 0) { - printk(KERN_ERR "cyclades: failed to reserve " - "PCI resources\n"); - continue; - } + if (mailbox == ZE_V1) { + card_name = "Cyclades-Ze"; - if (mailbox == ZE_V1) { - cy_pci_addr2 = ioremap(cy_pci_phys2, - CyPCI_Ze_win); - if (ZeIndex == NR_CARDS) { - printk("Cyclades-Ze/PCI found at " - "0x%lx but no more cards can " - "be used.\nChange NR_CARDS in " - "cyclades.c and recompile " - "kernel.\n", - (ulong)cy_pci_phys2); - } else { - Ze_phys0[ZeIndex] = cy_pci_phys0; - Ze_phys2[ZeIndex] = cy_pci_phys2; - Ze_addr0[ZeIndex] = cy_pci_addr0; - Ze_addr2[ZeIndex] = cy_pci_addr2; - Ze_irq[ZeIndex] = cy_pci_irq; - Ze_pdev[ZeIndex] = pdev; - ZeIndex++; - } - i--; - continue; - } else { - cy_pci_addr2 = ioremap(cy_pci_phys2,CyPCI_Zwin); - } + readl(&ctl_addr->mail_box_0); + nchan = ZE_V1_NPORTS; + } else { + card_name = "Cyclades-8Zo"; #ifdef CY_PCI_DEBUG - printk("Cyclades-Z/PCI: relocate winaddr=0x%lx " - "ctladdr=0x%lx\n", - (ulong) cy_pci_addr2, (ulong) cy_pci_addr0); if (mailbox == ZO_V1) { - cy_writel(&((struct RUNTIME_9060 *) - (cy_pci_addr0))->loc_addr_base, - WIN_CREG); - PAUSE; - printk("Cyclades-8Zo/PCI: FPGA id %lx, ver " - "%lx\n", (ulong) (0xff & - cy_readl(&((struct CUSTOM_REG *) - (cy_pci_addr2))->fpga_id)), - (ulong)(0xff & - cy_readl(&((struct CUSTOM_REG *) - (cy_pci_addr2))-> - fpga_version))); - cy_writel(&((struct RUNTIME_9060 *) - (cy_pci_addr0))->loc_addr_base, - WIN_RAM); + cy_writel(&ctl_addr->loc_addr_base, WIN_CREG); + dev_info(&pdev->dev, "Cyclades-8Zo/PCI: FPGA " + "id %lx, ver %lx\n", (ulong)(0xff & + readl(&((struct CUSTOM_REG *)addr2)-> + fpga_id)), (ulong)(0xff & + readl(&((struct CUSTOM_REG *)addr2)-> + fpga_version))); + cy_writel(&ctl_addr->loc_addr_base, WIN_RAM); } else { - printk("Cyclades-Z/PCI: New Cyclades-Z board. " - "FPGA not loaded\n"); + dev_info(&pdev->dev, "Cyclades-Z/PCI: New " + "Cyclades-Z board. FPGA not loaded\n"); } #endif /* The following clears the firmware id word. This ensures that the driver will not attempt to talk to the board until it has been properly initialized. */ - PAUSE; if ((mailbox == ZO_V1) || (mailbox == ZO_V2)) - cy_writel(cy_pci_addr2 + ID_ADDRESS, 0L); + cy_writel(addr2 + ID_ADDRESS, 0L); /* This must be a Cyclades-8Zo/PCI. The extendable version will have a different device_id and will be allocated its maximum number of ports. */ - cy_pci_nchan = 8; - - if ((cy_next_channel + cy_pci_nchan) > NR_PORTS) { - printk("Cyclades-8Zo/PCI found at 0x%lx but" - "no channels are available.\nChange " - "NR_PORTS in cyclades.c and recompile " - "kernel.\n", (ulong)cy_pci_phys2); - return i; - } - - /* fill the next cy_card structure available */ - for (j = 0; j < NR_CARDS; j++) { - if (cy_card[j].base_addr == 0) - break; - } - if (j == NR_CARDS) { /* no more cy_cards available */ - printk("Cyclades-8Zo/PCI found at 0x%lx but" - "no more cards can be used.\nChange " - "NR_CARDS in cyclades.c and recompile " - "kernel.\n", (ulong)cy_pci_phys2); - return i; - } -#ifdef CONFIG_CYZ_INTR - /* allocate IRQ only if board has an IRQ */ - if ((cy_pci_irq != 0) && (cy_pci_irq != 255)) { - if (request_irq(cy_pci_irq, cyz_interrupt, - IRQF_SHARED, "Cyclades-Z", - &cy_card[j])) { - printk("Cyclom-8Zo/PCI found at 0x%lx " - "but could not allocate " - "IRQ%d.\n", (ulong)cy_pci_phys2, - cy_pci_irq); - return i; - } - } -#endif /* CONFIG_CYZ_INTR */ - - /* set cy_card */ - cy_card[j].base_phys = cy_pci_phys2; - cy_card[j].ctl_phys = cy_pci_phys0; - cy_card[j].base_addr = cy_pci_addr2; - cy_card[j].ctl_addr = cy_pci_addr0; - cy_card[j].irq = (int)cy_pci_irq; - cy_card[j].bus_index = 1; - cy_card[j].first_line = cy_next_channel; - cy_card[j].num_chips = -1; - cy_card[j].pdev = pdev; - - /* print message */ -#ifdef CONFIG_CYZ_INTR - /* don't report IRQ if board is no IRQ */ - if ((cy_pci_irq != 0) && (cy_pci_irq != 255)) - printk("Cyclades-8Zo/PCI #%d: 0x%lx-0x%lx, " - "IRQ%d, ", j + 1, (ulong)cy_pci_phys2, - (ulong) (cy_pci_phys2 + CyPCI_Zwin - 1), - (int)cy_pci_irq); - else -#endif /* CONFIG_CYZ_INTR */ - printk("Cyclades-8Zo/PCI #%d: 0x%lx-0x%lx, ", - j + 1, (ulong)cy_pci_phys2, - (ulong)(cy_pci_phys2 + CyPCI_Zwin - 1)); - - printk("%d channels starting from port %d.\n", - cy_pci_nchan, cy_next_channel); - cy_next_channel += cy_pci_nchan; + nchan = 8; } } - for (; ZeIndex != 0 && i < NR_CARDS; i++) { - cy_pci_phys0 = Ze_phys0[0]; - cy_pci_phys2 = Ze_phys2[0]; - cy_pci_addr0 = Ze_addr0[0]; - cy_pci_addr2 = Ze_addr2[0]; - cy_pci_irq = Ze_irq[0]; - pdev = Ze_pdev[0]; - for (j = 0; j < ZeIndex - 1; j++) { - Ze_phys0[j] = Ze_phys0[j + 1]; - Ze_phys2[j] = Ze_phys2[j + 1]; - Ze_addr0[j] = Ze_addr0[j + 1]; - Ze_addr2[j] = Ze_addr2[j + 1]; - Ze_irq[j] = Ze_irq[j + 1]; - Ze_pdev[j] = Ze_pdev[j + 1]; - } - ZeIndex--; - mailbox = (uclong)cy_readl(&((struct RUNTIME_9060 __iomem *) - cy_pci_addr0)->mail_box_0); -#ifdef CY_PCI_DEBUG - printk("Cyclades-Z/PCI: relocate winaddr=0x%lx ctladdr=0x%lx\n", - (ulong)cy_pci_addr2, (ulong)cy_pci_addr0); - printk("Cyclades-Z/PCI: New Cyclades-Z board. FPGA not " - "loaded\n"); -#endif - PAUSE; - /* This must be the new Cyclades-Ze/PCI. */ - cy_pci_nchan = ZE_V1_NPORTS; - - if ((cy_next_channel + cy_pci_nchan) > NR_PORTS) { - printk("Cyclades-Ze/PCI found at 0x%lx but no channels " - "are available.\nChange NR_PORTS in cyclades.c " - "and recompile kernel.\n", - (ulong) cy_pci_phys2); - return i; - } + if ((cy_next_channel + nchan) > NR_PORTS) { + dev_err(&pdev->dev, "Cyclades-8Zo/PCI found, but no " + "channels are available. Change NR_PORTS in " + "cyclades.c and recompile kernel.\n"); + goto err_unmap; + } + /* fill the next cy_card structure available */ + for (card_no = 0; card_no < NR_CARDS; card_no++) { + if (cy_card[card_no].base_addr == NULL) + break; + } + if (card_no == NR_CARDS) { /* no more cy_cards available */ + dev_err(&pdev->dev, "Cyclades-8Zo/PCI found, but no " + "more cards can be used. Change NR_CARDS in " + "cyclades.c and recompile kernel.\n"); + goto err_unmap; + } - /* fill the next cy_card structure available */ - for (j = 0; j < NR_CARDS; j++) { - if (cy_card[j].base_addr == 0) - break; - } - if (j == NR_CARDS) { /* no more cy_cards available */ - printk("Cyclades-Ze/PCI found at 0x%lx but no more " - "cards can be used.\nChange NR_CARDS in " - "cyclades.c and recompile kernel.\n", - (ulong) cy_pci_phys2); - return i; + if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo || + device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi) { + /* allocate IRQ */ + retval = request_irq(irq, cyy_interrupt, + IRQF_SHARED, "Cyclom-Y", &cy_card[card_no]); + if (retval) { + dev_err(&pdev->dev, "could not allocate IRQ\n"); + goto err_unmap; } + cy_card[card_no].num_chips = nchan / 4; + } else { #ifdef CONFIG_CYZ_INTR /* allocate IRQ only if board has an IRQ */ - if ((cy_pci_irq != 0) && (cy_pci_irq != 255)) { - if (request_irq(cy_pci_irq, cyz_interrupt, + if (irq != 0 && irq != 255) { + retval = request_irq(irq, cyz_interrupt, IRQF_SHARED, "Cyclades-Z", - &cy_card[j])) { - printk("Cyclom-Ze/PCI found at 0x%lx ", - (ulong) cy_pci_phys2); - printk("but could not allocate IRQ%d.\n", - cy_pci_irq); - return i; + &cy_card[card_no]); + if (retval) { + dev_err(&pdev->dev, "could not allocate IRQ\n"); + goto err_unmap; } } #endif /* CONFIG_CYZ_INTR */ + cy_card[card_no].num_chips = -1; + } - /* set cy_card */ - cy_card[j].base_phys = cy_pci_phys2; - cy_card[j].ctl_phys = cy_pci_phys0; - cy_card[j].base_addr = cy_pci_addr2; - cy_card[j].ctl_addr = cy_pci_addr0; - cy_card[j].irq = (int)cy_pci_irq; - cy_card[j].bus_index = 1; - cy_card[j].first_line = cy_next_channel; - cy_card[j].num_chips = -1; - cy_card[j].pdev = pdev; + /* set cy_card */ + cy_card[card_no].base_addr = addr2; + cy_card[card_no].ctl_addr = addr0; + cy_card[card_no].irq = irq; + cy_card[card_no].bus_index = 1; + cy_card[card_no].first_line = cy_next_channel; + retval = cy_init_card(&cy_card[card_no]); + if (retval) + goto err_null; - /* print message */ -#ifdef CONFIG_CYZ_INTR - /* don't report IRQ if board is no IRQ */ - if ((cy_pci_irq != 0) && (cy_pci_irq != 255)) - printk("Cyclades-Ze/PCI #%d: 0x%lx-0x%lx, IRQ%d, ", - j + 1, (ulong) cy_pci_phys2, - (ulong) (cy_pci_phys2 + CyPCI_Ze_win - 1), - (int)cy_pci_irq); - else -#endif /* CONFIG_CYZ_INTR */ - printk("Cyclades-Ze/PCI #%d: 0x%lx-0x%lx, ", - j + 1, (ulong) cy_pci_phys2, - (ulong) (cy_pci_phys2 + CyPCI_Ze_win - 1)); + pci_set_drvdata(pdev, &cy_card[card_no]); - printk("%d channels starting from port %d.\n", - cy_pci_nchan, cy_next_channel); - cy_next_channel += cy_pci_nchan; - } - if (ZeIndex != 0) { - printk("Cyclades-Ze/PCI found at 0x%x but no more cards can be " - "used.\nChange NR_CARDS in cyclades.c and recompile " - "kernel.\n", (unsigned int)Ze_phys2[0]); + if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo || + device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi) { + /* enable interrupts in the PCI interface */ + plx_ver = readb(addr2 + CyPLX_VER) & 0x0f; + switch (plx_ver) { + case PLX_9050: + + cy_writeb(addr0 + 0x4c, 0x43); + break; + + case PLX_9060: + case PLX_9080: + default: /* Old boards, use PLX_9060 */ + + plx_init(addr0, 0x6c); + /* For some yet unknown reason, once the PLX9060 reloads + the EEPROM, the IRQ is lost and, thus, we have to + re-write it to the PCI config. registers. + This will remain here until we find a permanent + fix. */ + pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, irq); + + cy_writew(addr0 + 0x68, readw(addr0 + 0x68) | 0x0900); + break; + } } - return i; -#else + + dev_info(&pdev->dev, "%s/PCI #%d found: %d channels starting from " + "port %d.\n", card_name, card_no + 1, nchan, cy_next_channel); + for (i = cy_next_channel; i < cy_next_channel + nchan; i++) + tty_register_device(cy_serial_driver, i, &pdev->dev); + cy_next_channel += nchan; + return 0; -#endif /* ifdef CONFIG_PCI */ -} /* cy_detect_pci */ +err_null: + cy_card[card_no].base_addr = NULL; + free_irq(irq, &cy_card[card_no]); +err_unmap: + pci_iounmap(pdev, addr0); + if (addr2) + pci_iounmap(pdev, addr2); +err_reg: + pci_release_regions(pdev); +err_dis: + pci_disable_device(pdev); +err: + return retval; +} -/* - * This routine prints out the appropriate serial driver version number - * and identifies which options were configured into this driver. - */ -static inline void show_version(void) +static void __devexit cy_pci_remove(struct pci_dev *pdev) { - printk("Cyclades driver " CY_VERSION "\n"); - printk(" built %s %s\n", __DATE__, __TIME__); -} /* show_version */ + struct cyclades_card *cinfo = pci_get_drvdata(pdev); + unsigned int i; + + /* non-Z with old PLX */ + if (!IS_CYC_Z(*cinfo) && (readb(cinfo->base_addr + CyPLX_VER) & 0x0f) == + PLX_9050) + cy_writeb(cinfo->ctl_addr + 0x4c, 0); + else +#ifndef CONFIG_CYZ_INTR + if (!IS_CYC_Z(*cinfo)) +#endif + cy_writew(cinfo->ctl_addr + 0x68, + readw(cinfo->ctl_addr + 0x68) & ~0x0900); + + pci_iounmap(pdev, cinfo->base_addr); + if (cinfo->ctl_addr) + pci_iounmap(pdev, cinfo->ctl_addr); + if (cinfo->irq +#ifndef CONFIG_CYZ_INTR + && !IS_CYC_Z(*cinfo) +#endif /* CONFIG_CYZ_INTR */ + ) + free_irq(cinfo->irq, cinfo); + pci_release_regions(pdev); + + cinfo->base_addr = NULL; + for (i = cinfo->first_line; i < cinfo->first_line + + cinfo->nports; i++) + tty_unregister_device(cy_serial_driver, i); + cinfo->nports = 0; + kfree(cinfo->ports); +} + +static struct pci_driver cy_pci_driver = { + .name = "cyclades", + .id_table = cy_pci_dev_id, + .probe = cy_pci_probe, + .remove = __devexit_p(cy_pci_remove) +}; +#endif static int cyclades_get_proc_info(char *buf, char **start, off_t offset, int length, int *eof, void *data) { struct cyclades_port *info; - int i; + unsigned int i, j; int len = 0; off_t begin = 0; off_t pos = 0; @@ -5238,33 +5054,34 @@ cyclades_get_proc_info(char *buf, char **start, off_t offset, int length, len += size; /* Output one line for each known port */ - for (i = 0; i < NR_PORTS && cy_port[i].line >= 0; i++) { - info = &cy_port[i]; - - if (info->count) - size = sprintf(buf + len, "%3d %8lu %10lu %8lu %10lu " - "%8lu %9lu %6ld\n", info->line, - (cur_jifs - info->idle_stats.in_use) / HZ, - info->idle_stats.xmit_bytes, - (cur_jifs - info->idle_stats.xmit_idle) / HZ, - info->idle_stats.recv_bytes, - (cur_jifs - info->idle_stats.recv_idle) / HZ, - info->idle_stats.overruns, - (long)info->tty->ldisc.num); - else - size = sprintf(buf + len, "%3d %8lu %10lu %8lu %10lu " - "%8lu %9lu %6ld\n", - info->line, 0L, 0L, 0L, 0L, 0L, 0L, 0L); - len += size; - pos = begin + len; - - if (pos < offset) { - len = 0; - begin = pos; + for (i = 0; i < NR_CARDS; i++) + for (j = 0; j < cy_card[i].nports; j++) { + info = &cy_card[i].ports[j]; + + if (info->count) + size = sprintf(buf + len, "%3d %8lu %10lu %8lu " + "%10lu %8lu %9lu %6ld\n", info->line, + (cur_jifs - info->idle_stats.in_use) / + HZ, info->idle_stats.xmit_bytes, + (cur_jifs - info->idle_stats.xmit_idle)/ + HZ, info->idle_stats.recv_bytes, + (cur_jifs - info->idle_stats.recv_idle)/ + HZ, info->idle_stats.overruns, + (long)info->tty->ldisc.num); + else + size = sprintf(buf + len, "%3d %8lu %10lu %8lu " + "%10lu %8lu %9lu %6ld\n", + info->line, 0L, 0L, 0L, 0L, 0L, 0L, 0L); + len += size; + pos = begin + len; + + if (pos < offset) { + len = 0; + begin = pos; + } + if (pos > offset + length) + goto done; } - if (pos > offset + length) - goto done; - } *eof = 1; done: *start = buf + (offset - begin); /* Start of wanted data */ @@ -5319,18 +5136,15 @@ static const struct tty_operations cy_ops = { static int __init cy_init(void) { - struct cyclades_port *info; - struct cyclades_card *cinfo; - int number_z_boards = 0; - int board, port, i, index; - unsigned long mailbox; - unsigned short chip_number; - int nports; + unsigned int nboards; + int retval = -ENOMEM; cy_serial_driver = alloc_tty_driver(NR_PORTS); if (!cy_serial_driver) - return -ENOMEM; - show_version(); + goto err; + + printk(KERN_INFO "Cyclades driver " CY_VERSION " (built %s %s)\n", + __DATE__, __TIME__); /* Initialize the tty_driver structure */ @@ -5344,15 +5158,13 @@ static int __init cy_init(void) cy_serial_driver->init_termios = tty_std_termios; cy_serial_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; - cy_serial_driver->flags = TTY_DRIVER_REAL_RAW; + cy_serial_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; tty_set_operations(cy_serial_driver, &cy_ops); - if (tty_register_driver(cy_serial_driver)) - panic("Couldn't register Cyclades serial driver\n"); - - for (i = 0; i < NR_CARDS; i++) { - /* base_addr=0 indicates board not found */ - cy_card[i].base_addr = NULL; + retval = tty_register_driver(cy_serial_driver); + if (retval) { + printk(KERN_ERR "Couldn't register Cyclades serial driver\n"); + goto err_frtty; } /* the code below is responsible to find the boards. Each different @@ -5363,223 +5175,68 @@ static int __init cy_init(void) the cy_next_channel. */ /* look for isa boards */ - cy_isa_nboard = cy_detect_isa(); + nboards = cy_detect_isa(); +#ifdef CONFIG_PCI /* look for pci boards */ - cy_pci_nboard = cy_detect_pci(); - - cy_nboard = cy_isa_nboard + cy_pci_nboard; - - /* invalidate remaining cy_card structures */ - for (i = 0; i < NR_CARDS; i++) { - if (cy_card[i].base_addr == 0) { - cy_card[i].first_line = -1; - cy_card[i].ctl_addr = NULL; - cy_card[i].irq = 0; - cy_card[i].bus_index = 0; - cy_card[i].first_line = 0; - cy_card[i].num_chips = 0; - } - } - /* invalidate remaining cy_port structures */ - for (i = cy_next_channel; i < NR_PORTS; i++) { - cy_port[i].line = -1; - cy_port[i].magic = -1; - } - - /* initialize per-port data structures for each valid board found */ - for (board = 0; board < cy_nboard; board++) { - cinfo = &cy_card[board]; - if (cinfo->num_chips == -1) { /* Cyclades-Z */ - number_z_boards++; - mailbox = cy_readl(&((struct RUNTIME_9060 __iomem *) - cy_card[board].ctl_addr)-> - mail_box_0); - nports = (mailbox == ZE_V1) ? ZE_V1_NPORTS : 8; - cinfo->intr_enabled = 0; - cinfo->nports = 0; /* Will be correctly set later, after - Z FW is loaded */ - spin_lock_init(&cinfo->card_lock); - for (port = cinfo->first_line; - port < cinfo->first_line + nports; port++) { - info = &cy_port[port]; - info->magic = CYCLADES_MAGIC; - info->type = PORT_STARTECH; - info->card = board; - info->line = port; - info->chip_rev = 0; - info->flags = STD_COM_FLAGS; - info->tty = NULL; - if (mailbox == ZO_V1) - info->xmit_fifo_size = CYZ_FIFO_SIZE; - else - info->xmit_fifo_size = - 4 * CYZ_FIFO_SIZE; - info->cor1 = 0; - info->cor2 = 0; - info->cor3 = 0; - info->cor4 = 0; - info->cor5 = 0; - info->tbpr = 0; - info->tco = 0; - info->rbpr = 0; - info->rco = 0; - info->custom_divisor = 0; - info->close_delay = 5 * HZ / 10; - info->closing_wait = CLOSING_WAIT_DELAY; - info->icount.cts = info->icount.dsr = - info->icount.rng = info->icount.dcd = 0; - info->icount.rx = info->icount.tx = 0; - info->icount.frame = info->icount.parity = 0; - info->icount.overrun = info->icount.brk = 0; - info->x_char = 0; - info->event = 0; - info->count = 0; - info->blocked_open = 0; - info->default_threshold = 0; - info->default_timeout = 0; - INIT_WORK(&info->tqueue, do_softint); - init_waitqueue_head(&info->open_wait); - init_waitqueue_head(&info->close_wait); - init_waitqueue_head(&info->shutdown_wait); - init_waitqueue_head(&info->delta_msr_wait); - /* info->session */ - /* info->pgrp */ - info->read_status_mask = 0; - /* info->timeout */ - /* Bentson's vars */ - info->jiffies[0] = 0; - info->jiffies[1] = 0; - info->jiffies[2] = 0; - info->rflush_count = 0; -#ifdef CONFIG_CYZ_INTR - init_timer(&cyz_rx_full_timer[port]); - cyz_rx_full_timer[port].function = NULL; + retval = pci_register_driver(&cy_pci_driver); + if (retval && !nboards) + goto err_unr; #endif - } - continue; - } else { /* Cyclom-Y of some kind */ - index = cinfo->bus_index; - spin_lock_init(&cinfo->card_lock); - cinfo->nports = CyPORTS_PER_CHIP * cinfo->num_chips; - for (port = cinfo->first_line; - port < cinfo->first_line + cinfo->nports; port++) { - info = &cy_port[port]; - info->magic = CYCLADES_MAGIC; - info->type = PORT_CIRRUS; - info->card = board; - info->line = port; - info->flags = STD_COM_FLAGS; - info->tty = NULL; - info->xmit_fifo_size = CyMAX_CHAR_FIFO; - info->cor1 = - CyPARITY_NONE | Cy_1_STOP | Cy_8_BITS; - info->cor2 = CyETC; - info->cor3 = 0x08; /* _very_ small rcv threshold */ - info->cor4 = 0; - info->cor5 = 0; - info->custom_divisor = 0; - info->close_delay = 5 * HZ / 10; - info->closing_wait = CLOSING_WAIT_DELAY; - info->icount.cts = info->icount.dsr = - info->icount.rng = info->icount.dcd = 0; - info->icount.rx = info->icount.tx = 0; - info->icount.frame = info->icount.parity = 0; - info->icount.overrun = info->icount.brk = 0; - chip_number = (port - cinfo->first_line) / 4; - if ((info->chip_rev = - cy_readb(cinfo->base_addr + - (cy_chip_offset[chip_number] << - index) + (CyGFRCR << index))) >= - CD1400_REV_J) { - /* It is a CD1400 rev. J or later */ - info->tbpr = baud_bpr_60[13]; /* Tx BPR */ - info->tco = baud_co_60[13]; /* Tx CO */ - info->rbpr = baud_bpr_60[13]; /* Rx BPR */ - info->rco = baud_co_60[13]; /* Rx CO */ - info->rflow = 0; - info->rtsdtr_inv = 1; - } else { - info->tbpr = baud_bpr_25[13]; /* Tx BPR */ - info->tco = baud_co_25[13]; /* Tx CO */ - info->rbpr = baud_bpr_25[13]; /* Rx BPR */ - info->rco = baud_co_25[13]; /* Rx CO */ - info->rflow = 0; - info->rtsdtr_inv = 0; - } - info->x_char = 0; - info->event = 0; - info->count = 0; - info->blocked_open = 0; - info->default_threshold = 0; - info->default_timeout = 0; - INIT_WORK(&info->tqueue, do_softint); - init_waitqueue_head(&info->open_wait); - init_waitqueue_head(&info->close_wait); - init_waitqueue_head(&info->shutdown_wait); - init_waitqueue_head(&info->delta_msr_wait); - /* info->session */ - /* info->pgrp */ - info->read_status_mask = - CyTIMEOUT | CySPECHAR | CyBREAK - | CyPARITY | CyFRAME | CyOVERRUN; - /* info->timeout */ - } - } - } - -#ifndef CONFIG_CYZ_INTR - if (number_z_boards && !cyz_timeron) { - cyz_timeron++; - cyz_timerlist.expires = jiffies + 1; - add_timer(&cyz_timerlist); -#ifdef CY_PCI_DEBUG - printk("Cyclades-Z polling initialized\n"); -#endif - } -#endif /* CONFIG_CYZ_INTR */ return 0; - +err_unr: + tty_unregister_driver(cy_serial_driver); +err_frtty: + put_tty_driver(cy_serial_driver); +err: + return retval; } /* cy_init */ static void __exit cy_cleanup_module(void) { + struct cyclades_card *card; int i, e1; #ifndef CONFIG_CYZ_INTR - if (cyz_timeron){ - cyz_timeron = 0; - del_timer(&cyz_timerlist); - } + del_timer_sync(&cyz_timerlist); #endif /* CONFIG_CYZ_INTR */ if ((e1 = tty_unregister_driver(cy_serial_driver))) - printk("cyc: failed to unregister Cyclades serial driver(%d)\n", - e1); + printk(KERN_ERR "failed to unregister Cyclades serial " + "driver(%d)\n", e1); - put_tty_driver(cy_serial_driver); +#ifdef CONFIG_PCI + pci_unregister_driver(&cy_pci_driver); +#endif for (i = 0; i < NR_CARDS; i++) { - if (cy_card[i].base_addr) { - iounmap(cy_card[i].base_addr); - if (cy_card[i].ctl_addr) - iounmap(cy_card[i].ctl_addr); - if (cy_card[i].irq + card = &cy_card[i]; + if (card->base_addr) { + /* clear interrupt */ + cy_writeb(card->base_addr + Cy_ClrIntr, 0); + iounmap(card->base_addr); + if (card->ctl_addr) + iounmap(card->ctl_addr); + if (card->irq #ifndef CONFIG_CYZ_INTR - && cy_card[i].num_chips != -1 /* not a Z card */ + && !IS_CYC_Z(*card) #endif /* CONFIG_CYZ_INTR */ ) - free_irq(cy_card[i].irq, &cy_card[i]); -#ifdef CONFIG_PCI - if (cy_card[i].pdev) - pci_release_regions(cy_card[i].pdev); -#endif + free_irq(card->irq, card); + for (e1 = card->first_line; + e1 < card->first_line + + card->nports; e1++) + tty_unregister_device(cy_serial_driver, e1); + kfree(card->ports); } } + + put_tty_driver(cy_serial_driver); } /* cy_cleanup_module */ module_init(cy_init); module_exit(cy_cleanup_module); MODULE_LICENSE("GPL"); +MODULE_VERSION(CY_VERSION); diff --git a/drivers/char/digi.h b/drivers/char/digi.h deleted file mode 100644 index 19df0e879b1b..000000000000 --- a/drivers/char/digi.h +++ /dev/null @@ -1,71 +0,0 @@ -/* Definitions for DigiBoard ditty(1) command. */ - -#if !defined(TIOCMODG) -#define TIOCMODG (('d'<<8) | 250) /* get modem ctrl state */ -#define TIOCMODS (('d'<<8) | 251) /* set modem ctrl state */ -#endif - -#if !defined(TIOCMSET) -#define TIOCMSET (('d'<<8) | 252) /* set modem ctrl state */ -#define TIOCMGET (('d'<<8) | 253) /* set modem ctrl state */ -#endif - -#if !defined(TIOCMBIC) -#define TIOCMBIC (('d'<<8) | 254) /* set modem ctrl state */ -#define TIOCMBIS (('d'<<8) | 255) /* set modem ctrl state */ -#endif - -#if !defined(TIOCSDTR) -#define TIOCSDTR (('e'<<8) | 0) /* set DTR */ -#define TIOCCDTR (('e'<<8) | 1) /* clear DTR */ -#endif - -/************************************************************************ - * Ioctl command arguments for DIGI parameters. - ************************************************************************/ -#define DIGI_GETA (('e'<<8) | 94) /* Read params */ - -#define DIGI_SETA (('e'<<8) | 95) /* Set params */ -#define DIGI_SETAW (('e'<<8) | 96) /* Drain & set params */ -#define DIGI_SETAF (('e'<<8) | 97) /* Drain, flush & set params */ - -#define DIGI_GETFLOW (('e'<<8) | 99) /* Get startc/stopc flow */ - /* control characters */ -#define DIGI_SETFLOW (('e'<<8) | 100) /* Set startc/stopc flow */ - /* control characters */ -#define DIGI_GETAFLOW (('e'<<8) | 101) /* Get Aux. startc/stopc */ - /* flow control chars */ -#define DIGI_SETAFLOW (('e'<<8) | 102) /* Set Aux. startc/stopc */ - /* flow control chars */ - -struct digiflow_struct { - unsigned char startc; /* flow cntl start char */ - unsigned char stopc; /* flow cntl stop char */ -}; - -typedef struct digiflow_struct digiflow_t; - - -/************************************************************************ - * Values for digi_flags - ************************************************************************/ -#define DIGI_IXON 0x0001 /* Handle IXON in the FEP */ -#define DIGI_FAST 0x0002 /* Fast baud rates */ -#define RTSPACE 0x0004 /* RTS input flow control */ -#define CTSPACE 0x0008 /* CTS output flow control */ -#define DSRPACE 0x0010 /* DSR output flow control */ -#define DCDPACE 0x0020 /* DCD output flow control */ -#define DTRPACE 0x0040 /* DTR input flow control */ -#define DIGI_FORCEDCD 0x0100 /* Force carrier */ -#define DIGI_ALTPIN 0x0200 /* Alternate RJ-45 pin config */ -#define DIGI_AIXON 0x0400 /* Aux flow control in fep */ - - -/************************************************************************ - * Structure used with ioctl commands for DIGI parameters. - ************************************************************************/ -struct digi_struct { - unsigned short digi_flags; /* Flags (see above) */ -}; - -typedef struct digi_struct digi_t; diff --git a/drivers/char/drm/ati_pcigart.c b/drivers/char/drm/ati_pcigart.c index bd7be09ea53d..5b91bc04ea4e 100644 --- a/drivers/char/drm/ati_pcigart.c +++ b/drivers/char/drm/ati_pcigart.c @@ -33,59 +33,44 @@ #include "drmP.h" -#if PAGE_SIZE == 65536 -# define ATI_PCIGART_TABLE_ORDER 0 -# define ATI_PCIGART_TABLE_PAGES (1 << 0) -#elif PAGE_SIZE == 16384 -# define ATI_PCIGART_TABLE_ORDER 1 -# define ATI_PCIGART_TABLE_PAGES (1 << 1) -#elif PAGE_SIZE == 8192 -# define ATI_PCIGART_TABLE_ORDER 2 -# define ATI_PCIGART_TABLE_PAGES (1 << 2) -#elif PAGE_SIZE == 4096 -# define ATI_PCIGART_TABLE_ORDER 3 -# define ATI_PCIGART_TABLE_PAGES (1 << 3) -#else -# error - PAGE_SIZE not 64K, 16K, 8K or 4K -#endif - -# define ATI_MAX_PCIGART_PAGES 8192 /**< 32 MB aperture, 4K pages */ # define ATI_PCIGART_PAGE_SIZE 4096 /**< PCI GART page size */ -static void *drm_ati_alloc_pcigart_table(void) +static void *drm_ati_alloc_pcigart_table(int order) { unsigned long address; struct page *page; int i; - DRM_DEBUG("%s\n", __FUNCTION__); + + DRM_DEBUG("%s: alloc %d order\n", __FUNCTION__, order); address = __get_free_pages(GFP_KERNEL | __GFP_COMP, - ATI_PCIGART_TABLE_ORDER); + order); if (address == 0UL) { return NULL; } page = virt_to_page(address); - for (i = 0; i < ATI_PCIGART_TABLE_PAGES; i++, page++) + for (i = 0; i < order; i++, page++) SetPageReserved(page); DRM_DEBUG("%s: returning 0x%08lx\n", __FUNCTION__, address); return (void *)address; } -static void drm_ati_free_pcigart_table(void *address) +static void drm_ati_free_pcigart_table(void *address, int order) { struct page *page; int i; + int num_pages = 1 << order; DRM_DEBUG("%s\n", __FUNCTION__); page = virt_to_page((unsigned long)address); - for (i = 0; i < ATI_PCIGART_TABLE_PAGES; i++, page++) + for (i = 0; i < num_pages; i++, page++) ClearPageReserved(page); - free_pages((unsigned long)address, ATI_PCIGART_TABLE_ORDER); + free_pages((unsigned long)address, order); } int drm_ati_pcigart_cleanup(drm_device_t *dev, drm_ati_pcigart_info *gart_info) @@ -93,6 +78,8 @@ int drm_ati_pcigart_cleanup(drm_device_t *dev, drm_ati_pcigart_info *gart_info) drm_sg_mem_t *entry = dev->sg; unsigned long pages; int i; + int order; + int num_pages, max_pages; /* we need to support large memory configurations */ if (!entry) { @@ -100,15 +87,19 @@ int drm_ati_pcigart_cleanup(drm_device_t *dev, drm_ati_pcigart_info *gart_info) return 0; } + order = drm_order((gart_info->table_size + (PAGE_SIZE-1)) / PAGE_SIZE); + num_pages = 1 << order; + if (gart_info->bus_addr) { if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) { pci_unmap_single(dev->pdev, gart_info->bus_addr, - ATI_PCIGART_TABLE_PAGES * PAGE_SIZE, + num_pages * PAGE_SIZE, PCI_DMA_TODEVICE); } - pages = (entry->pages <= ATI_MAX_PCIGART_PAGES) - ? entry->pages : ATI_MAX_PCIGART_PAGES; + max_pages = (gart_info->table_size / sizeof(u32)); + pages = (entry->pages <= max_pages) + ? entry->pages : max_pages; for (i = 0; i < pages; i++) { if (!entry->busaddr[i]) @@ -123,13 +114,12 @@ int drm_ati_pcigart_cleanup(drm_device_t *dev, drm_ati_pcigart_info *gart_info) if (gart_info->gart_table_location == DRM_ATI_GART_MAIN && gart_info->addr) { - drm_ati_free_pcigart_table(gart_info->addr); + drm_ati_free_pcigart_table(gart_info->addr, order); gart_info->addr = NULL; } return 1; } - EXPORT_SYMBOL(drm_ati_pcigart_cleanup); int drm_ati_pcigart_init(drm_device_t *dev, drm_ati_pcigart_info *gart_info) @@ -139,6 +129,9 @@ int drm_ati_pcigart_init(drm_device_t *dev, drm_ati_pcigart_info *gart_info) unsigned long pages; u32 *pci_gart, page_base, bus_address = 0; int i, j, ret = 0; + int order; + int max_pages; + int num_pages; if (!entry) { DRM_ERROR("no scatter/gather memory!\n"); @@ -148,7 +141,10 @@ int drm_ati_pcigart_init(drm_device_t *dev, drm_ati_pcigart_info *gart_info) if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) { DRM_DEBUG("PCI: no table in VRAM: using normal RAM\n"); - address = drm_ati_alloc_pcigart_table(); + order = drm_order((gart_info->table_size + + (PAGE_SIZE-1)) / PAGE_SIZE); + num_pages = 1 << order; + address = drm_ati_alloc_pcigart_table(order); if (!address) { DRM_ERROR("cannot allocate PCI GART page!\n"); goto done; @@ -160,11 +156,13 @@ int drm_ati_pcigart_init(drm_device_t *dev, drm_ati_pcigart_info *gart_info) } bus_address = pci_map_single(dev->pdev, address, - ATI_PCIGART_TABLE_PAGES * - PAGE_SIZE, PCI_DMA_TODEVICE); + num_pages * PAGE_SIZE, + PCI_DMA_TODEVICE); if (bus_address == 0) { DRM_ERROR("unable to map PCIGART pages!\n"); - drm_ati_free_pcigart_table(address); + order = drm_order((gart_info->table_size + + (PAGE_SIZE-1)) / PAGE_SIZE); + drm_ati_free_pcigart_table(address, order); address = NULL; goto done; } @@ -177,10 +175,11 @@ int drm_ati_pcigart_init(drm_device_t *dev, drm_ati_pcigart_info *gart_info) pci_gart = (u32 *) address; - pages = (entry->pages <= ATI_MAX_PCIGART_PAGES) - ? entry->pages : ATI_MAX_PCIGART_PAGES; + max_pages = (gart_info->table_size / sizeof(u32)); + pages = (entry->pages <= max_pages) + ? entry->pages : max_pages; - memset(pci_gart, 0, ATI_MAX_PCIGART_PAGES * sizeof(u32)); + memset(pci_gart, 0, max_pages * sizeof(u32)); for (i = 0; i < pages; i++) { /* we need to support large memory configurations */ @@ -198,10 +197,18 @@ int drm_ati_pcigart_init(drm_device_t *dev, drm_ati_pcigart_info *gart_info) page_base = (u32) entry->busaddr[i]; for (j = 0; j < (PAGE_SIZE / ATI_PCIGART_PAGE_SIZE); j++) { - if (gart_info->is_pcie) + switch(gart_info->gart_reg_if) { + case DRM_ATI_GART_IGP: + *pci_gart = cpu_to_le32((page_base) | 0xc); + break; + case DRM_ATI_GART_PCIE: *pci_gart = cpu_to_le32((page_base >> 8) | 0xc); - else + break; + default: + case DRM_ATI_GART_PCI: *pci_gart = cpu_to_le32(page_base); + break; + } pci_gart++; page_base += ATI_PCIGART_PAGE_SIZE; } @@ -220,5 +227,4 @@ int drm_ati_pcigart_init(drm_device_t *dev, drm_ati_pcigart_info *gart_info) gart_info->bus_addr = bus_address; return ret; } - EXPORT_SYMBOL(drm_ati_pcigart_init); diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h index 80041d5b792d..d494315752a2 100644 --- a/drivers/char/drm/drmP.h +++ b/drivers/char/drm/drmP.h @@ -519,12 +519,17 @@ typedef struct drm_vbl_sig { #define DRM_ATI_GART_MAIN 1 #define DRM_ATI_GART_FB 2 +#define DRM_ATI_GART_PCI 1 +#define DRM_ATI_GART_PCIE 2 +#define DRM_ATI_GART_IGP 3 + typedef struct ati_pcigart_info { int gart_table_location; - int is_pcie; + int gart_reg_if; void *addr; dma_addr_t bus_addr; drm_local_map_t mapping; + int table_size; } drm_ati_pcigart_info; /* diff --git a/drivers/char/drm/drm_dma.c b/drivers/char/drm/drm_dma.c index 892db7096986..32ed19c9ec1c 100644 --- a/drivers/char/drm/drm_dma.c +++ b/drivers/char/drm/drm_dma.c @@ -65,7 +65,7 @@ int drm_dma_setup(drm_device_t * dev) * \param dev DRM device. * * Free all pages associated with DMA buffers, the buffers and pages lists, and - * finally the the drm_device::dma structure itself. + * finally the drm_device::dma structure itself. */ void drm_dma_takedown(drm_device_t * dev) { diff --git a/drivers/char/drm/drm_drv.c b/drivers/char/drm/drm_drv.c index 26bec30ee86e..8e77b7ed0f44 100644 --- a/drivers/char/drm/drm_drv.c +++ b/drivers/char/drm/drm_drv.c @@ -15,8 +15,6 @@ * #define DRIVER_DESC "Matrox G200/G400" * #define DRIVER_DATE "20001127" * - * #define DRIVER_IOCTL_COUNT DRM_ARRAY_SIZE( mga_ioctls ) - * * #define drm_x mga_##x * \endcode */ @@ -120,7 +118,7 @@ static drm_ioctl_desc_t drm_ioctls[] = { [DRM_IOCTL_NR(DRM_IOCTL_UPDATE_DRAW)] = {drm_update_drawable_info, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, }; -#define DRIVER_IOCTL_COUNT ARRAY_SIZE( drm_ioctls ) +#define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls ) /** * Take down the DRM device. @@ -496,11 +494,11 @@ int drm_ioctl(struct inode *inode, struct file *filp, (long)old_encode_dev(priv->head->device), priv->authenticated); - if ((nr >= DRIVER_IOCTL_COUNT) && + if ((nr >= DRM_CORE_IOCTL_COUNT) && ((nr < DRM_COMMAND_BASE) || (nr >= DRM_COMMAND_END))) goto err_i1; - if ((nr >= DRM_COMMAND_BASE) && (nr < DRM_COMMAND_END) - && (nr < DRM_COMMAND_BASE + dev->driver->num_ioctls)) + if ((nr >= DRM_COMMAND_BASE) && (nr < DRM_COMMAND_END) && + (nr < DRM_COMMAND_BASE + dev->driver->num_ioctls)) ioctl = &dev->driver->ioctls[nr - DRM_COMMAND_BASE]; else if ((nr >= DRM_COMMAND_END) || (nr < DRM_COMMAND_BASE)) ioctl = &drm_ioctls[nr]; diff --git a/drivers/char/drm/drm_os_linux.h b/drivers/char/drm/drm_os_linux.h index 2908b72daa6e..0fe7b4497927 100644 --- a/drivers/char/drm/drm_os_linux.h +++ b/drivers/char/drm/drm_os_linux.h @@ -70,9 +70,6 @@ static __inline__ int mtrr_del(int reg, unsigned long base, unsigned long size) #endif -/** Task queue handler arguments */ -#define DRM_TASKQUEUE_ARGS void *arg - /** For data going into the kernel through the ioctl argument */ #define DRM_COPY_FROM_USER_IOCTL(arg1, arg2, arg3) \ if ( copy_from_user(&arg1, arg2, arg3) ) \ diff --git a/drivers/char/drm/drm_pciids.h b/drivers/char/drm/drm_pciids.h index 01cf482d2d00..31cdde83713b 100644 --- a/drivers/char/drm/drm_pciids.h +++ b/drivers/char/drm/drm_pciids.h @@ -102,6 +102,7 @@ {0x1002, 0x5653, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV410|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ {0x1002, 0x5834, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|RADEON_IS_IGP}, \ {0x1002, 0x5835, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|RADEON_IS_IGP|RADEON_IS_MOBILITY}, \ + {0x1002, 0x5955, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS400|RADEON_IS_IGP|RADEON_IS_MOBILITY|RADEON_IS_IGPGART}, \ {0x1002, 0x5960, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ {0x1002, 0x5961, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ {0x1002, 0x5962, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ diff --git a/drivers/char/drm/drm_vm.c b/drivers/char/drm/drm_vm.c index 35540cfb43dd..b5c5b9fa84c3 100644 --- a/drivers/char/drm/drm_vm.c +++ b/drivers/char/drm/drm_vm.c @@ -157,7 +157,7 @@ static __inline__ struct page *drm_do_vm_nopage(struct vm_area_struct *vma, * \param address access address. * \return pointer to the page structure. * - * Get the the mapping, find the real physical page to map, get the page, and + * Get the mapping, find the real physical page to map, get the page, and * return it. */ static __inline__ struct page *drm_do_vm_shm_nopage(struct vm_area_struct *vma, diff --git a/drivers/char/drm/r128_cce.c b/drivers/char/drm/r128_cce.c index db5a60450e68..1014602c43a7 100644 --- a/drivers/char/drm/r128_cce.c +++ b/drivers/char/drm/r128_cce.c @@ -560,9 +560,10 @@ static int r128_do_init_cce(drm_device_t * dev, drm_r128_init_t * init) if (dev_priv->is_pci) { #endif dev_priv->gart_info.gart_table_location = DRM_ATI_GART_MAIN; + dev_priv->gart_info.table_size = R128_PCIGART_TABLE_SIZE; dev_priv->gart_info.addr = NULL; dev_priv->gart_info.bus_addr = 0; - dev_priv->gart_info.is_pcie = 0; + dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_PCI; if (!drm_ati_pcigart_init(dev, &dev_priv->gart_info)) { DRM_ERROR("failed to init PCI GART!\n"); dev->dev_private = (void *)dev_priv; diff --git a/drivers/char/drm/r128_drv.h b/drivers/char/drm/r128_drv.h index f1efb49de8df..9086835686dc 100644 --- a/drivers/char/drm/r128_drv.h +++ b/drivers/char/drm/r128_drv.h @@ -383,6 +383,8 @@ extern long r128_compat_ioctl(struct file *filp, unsigned int cmd, #define R128_PERFORMANCE_BOXES 0 +#define R128_PCIGART_TABLE_SIZE 32768 + #define R128_READ(reg) DRM_READ32( dev_priv->mmio, (reg) ) #define R128_WRITE(reg,val) DRM_WRITE32( dev_priv->mmio, (reg), (val) ) #define R128_READ8(reg) DRM_READ8( dev_priv->mmio, (reg) ) diff --git a/drivers/char/drm/r300_reg.h b/drivers/char/drm/r300_reg.h index a881f96c983e..ecda760ae8c0 100644 --- a/drivers/char/drm/r300_reg.h +++ b/drivers/char/drm/r300_reg.h @@ -293,7 +293,7 @@ I am fairly certain that they are correct unless stated otherwise in comments. # define R300_PVS_CNTL_1_PROGRAM_START_SHIFT 0 # define R300_PVS_CNTL_1_POS_END_SHIFT 10 # define R300_PVS_CNTL_1_PROGRAM_END_SHIFT 20 -/* Addresses are relative the the vertex program parameters area. */ +/* Addresses are relative to the vertex program parameters area. */ #define R300_VAP_PVS_CNTL_2 0x22D4 # define R300_PVS_CNTL_2_PARAM_OFFSET_SHIFT 0 # define R300_PVS_CNTL_2_PARAM_COUNT_SHIFT 16 diff --git a/drivers/char/drm/radeon_cp.c b/drivers/char/drm/radeon_cp.c index c1850ecac302..68338389d836 100644 --- a/drivers/char/drm/radeon_cp.c +++ b/drivers/char/drm/radeon_cp.c @@ -830,6 +830,15 @@ static int RADEON_READ_PCIE(drm_radeon_private_t *dev_priv, int addr) return RADEON_READ(RADEON_PCIE_DATA); } +static u32 RADEON_READ_IGPGART(drm_radeon_private_t *dev_priv, int addr) +{ + u32 ret; + RADEON_WRITE(RADEON_IGPGART_INDEX, addr & 0x7f); + ret = RADEON_READ(RADEON_IGPGART_DATA); + RADEON_WRITE(RADEON_IGPGART_INDEX, 0x7f); + return ret; +} + #if RADEON_FIFO_DEBUG static void radeon_status(drm_radeon_private_t * dev_priv) { @@ -1267,7 +1276,44 @@ static void radeon_test_writeback(drm_radeon_private_t * dev_priv) } } -/* Enable or disable PCI-E GART on the chip */ +/* Enable or disable IGP GART on the chip */ +static void radeon_set_igpgart(drm_radeon_private_t * dev_priv, int on) +{ + u32 temp, tmp; + + tmp = RADEON_READ(RADEON_AIC_CNTL); + if (on) { + DRM_DEBUG("programming igpgart %08X %08lX %08X\n", + dev_priv->gart_vm_start, + (long)dev_priv->gart_info.bus_addr, + dev_priv->gart_size); + + RADEON_WRITE_IGPGART(RADEON_IGPGART_UNK_18, 0x1000); + RADEON_WRITE_IGPGART(RADEON_IGPGART_ENABLE, 0x1); + RADEON_WRITE_IGPGART(RADEON_IGPGART_CTRL, 0x42040800); + RADEON_WRITE_IGPGART(RADEON_IGPGART_BASE_ADDR, + dev_priv->gart_info.bus_addr); + + temp = RADEON_READ_IGPGART(dev_priv, RADEON_IGPGART_UNK_39); + RADEON_WRITE_IGPGART(RADEON_IGPGART_UNK_39, temp); + + RADEON_WRITE(RADEON_AGP_BASE, (unsigned int)dev_priv->gart_vm_start); + dev_priv->gart_size = 32*1024*1024; + RADEON_WRITE(RADEON_MC_AGP_LOCATION, + (((dev_priv->gart_vm_start - 1 + + dev_priv->gart_size) & 0xffff0000) | + (dev_priv->gart_vm_start >> 16))); + + temp = RADEON_READ_IGPGART(dev_priv, RADEON_IGPGART_ENABLE); + RADEON_WRITE_IGPGART(RADEON_IGPGART_ENABLE, temp); + + RADEON_READ_IGPGART(dev_priv, RADEON_IGPGART_FLUSH); + RADEON_WRITE_IGPGART(RADEON_IGPGART_FLUSH, 0x1); + RADEON_READ_IGPGART(dev_priv, RADEON_IGPGART_FLUSH); + RADEON_WRITE_IGPGART(RADEON_IGPGART_FLUSH, 0x0); + } +} + static void radeon_set_pciegart(drm_radeon_private_t * dev_priv, int on) { u32 tmp = RADEON_READ_PCIE(dev_priv, RADEON_PCIE_TX_GART_CNTL); @@ -1302,6 +1348,11 @@ static void radeon_set_pcigart(drm_radeon_private_t * dev_priv, int on) { u32 tmp; + if (dev_priv->flags & RADEON_IS_IGPGART) { + radeon_set_igpgart(dev_priv, on); + return; + } + if (dev_priv->flags & RADEON_IS_PCIE) { radeon_set_pciegart(dev_priv, on); return; @@ -1620,20 +1671,22 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) #endif { /* if we have an offset set from userspace */ - if (dev_priv->pcigart_offset) { + if (dev_priv->pcigart_offset_set) { dev_priv->gart_info.bus_addr = dev_priv->pcigart_offset + dev_priv->fb_location; dev_priv->gart_info.mapping.offset = dev_priv->gart_info.bus_addr; dev_priv->gart_info.mapping.size = - RADEON_PCIGART_TABLE_SIZE; + dev_priv->gart_info.table_size; drm_core_ioremap(&dev_priv->gart_info.mapping, dev); dev_priv->gart_info.addr = dev_priv->gart_info.mapping.handle; - dev_priv->gart_info.is_pcie = - !!(dev_priv->flags & RADEON_IS_PCIE); + if (dev_priv->flags & RADEON_IS_PCIE) + dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_PCIE; + else + dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_PCI; dev_priv->gart_info.gart_table_location = DRM_ATI_GART_FB; @@ -1641,6 +1694,10 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) dev_priv->gart_info.addr, dev_priv->pcigart_offset); } else { + if (dev_priv->flags & RADEON_IS_IGPGART) + dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_IGP; + else + dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_PCI; dev_priv->gart_info.gart_table_location = DRM_ATI_GART_MAIN; dev_priv->gart_info.addr = NULL; @@ -1714,7 +1771,7 @@ static int radeon_do_cleanup_cp(drm_device_t * dev) if (dev_priv->gart_info.gart_table_location == DRM_ATI_GART_FB) { drm_core_ioremapfree(&dev_priv->gart_info.mapping, dev); - dev_priv->gart_info.addr = NULL; + dev_priv->gart_info.addr = 0; } } /* only clear to the start of flags */ @@ -2222,6 +2279,8 @@ int radeon_driver_firstopen(struct drm_device *dev) drm_local_map_t *map; drm_radeon_private_t *dev_priv = dev->dev_private; + dev_priv->gart_info.table_size = RADEON_PCIGART_TABLE_SIZE; + ret = drm_addmap(dev, drm_get_resource_start(dev, 2), drm_get_resource_len(dev, 2), _DRM_REGISTERS, _DRM_READ_ONLY, &dev_priv->mmio); diff --git a/drivers/char/drm/radeon_drm.h b/drivers/char/drm/radeon_drm.h index 8d6350dd5360..66c4b6fed04f 100644 --- a/drivers/char/drm/radeon_drm.h +++ b/drivers/char/drm/radeon_drm.h @@ -707,6 +707,7 @@ typedef struct drm_radeon_setparam { #define RADEON_SETPARAM_SWITCH_TILING 2 /* enable/disable color tiling */ #define RADEON_SETPARAM_PCIGART_LOCATION 3 /* PCI Gart Location */ #define RADEON_SETPARAM_NEW_MEMMAP 4 /* Use new memory map */ +#define RADEON_SETPARAM_PCIGART_TABLE_SIZE 5 /* PCI GART Table Size */ /* 1.14: Clients can allocate/free a surface */ diff --git a/drivers/char/drm/radeon_drv.h b/drivers/char/drm/radeon_drv.h index 8b105f1460a7..54f49ef4bef0 100644 --- a/drivers/char/drm/radeon_drv.h +++ b/drivers/char/drm/radeon_drv.h @@ -95,9 +95,11 @@ * 1.24- Add general-purpose packet for manipulating scratch registers (r300) * 1.25- Add support for r200 vertex programs (R200_EMIT_VAP_PVS_CNTL, * new packet type) + * 1.26- Add support for variable size PCI(E) gart aperture + * 1.27- Add support for IGP GART */ #define DRIVER_MAJOR 1 -#define DRIVER_MINOR 25 +#define DRIVER_MINOR 27 #define DRIVER_PATCHLEVEL 0 /* @@ -143,6 +145,7 @@ enum radeon_chip_flags { RADEON_IS_PCIE = 0x00200000UL, RADEON_NEW_MEMMAP = 0x00400000UL, RADEON_IS_PCI = 0x00800000UL, + RADEON_IS_IGPGART = 0x01000000UL, }; #define GET_RING_HEAD(dev_priv) (dev_priv->writeback_works ? \ @@ -240,7 +243,6 @@ typedef struct drm_radeon_private { int do_boxes; int page_flipping; - int current_page; u32 color_fmt; unsigned int front_offset; @@ -280,6 +282,7 @@ typedef struct drm_radeon_private { struct radeon_virt_surface virt_surfaces[2 * RADEON_MAX_SURFACES]; unsigned long pcigart_offset; + unsigned int pcigart_offset_set; drm_ati_pcigart_info gart_info; u32 scratch_ages[5]; @@ -432,6 +435,15 @@ extern int r300_do_cp_cmdbuf(drm_device_t * dev, DRMFILE filp, #define RADEON_PCIE_TX_GART_END_LO 0x16 #define RADEON_PCIE_TX_GART_END_HI 0x17 +#define RADEON_IGPGART_INDEX 0x168 +#define RADEON_IGPGART_DATA 0x16c +#define RADEON_IGPGART_UNK_18 0x18 +#define RADEON_IGPGART_CTRL 0x2b +#define RADEON_IGPGART_BASE_ADDR 0x2c +#define RADEON_IGPGART_FLUSH 0x2e +#define RADEON_IGPGART_ENABLE 0x38 +#define RADEON_IGPGART_UNK_39 0x39 + #define RADEON_MPP_TB_CONFIG 0x01c0 #define RADEON_MEM_CNTL 0x0140 #define RADEON_MEM_SDRAM_MODE_REG 0x0158 @@ -964,6 +976,14 @@ do { \ RADEON_WRITE( RADEON_CLOCK_CNTL_DATA, (val) ); \ } while (0) +#define RADEON_WRITE_IGPGART( addr, val ) \ +do { \ + RADEON_WRITE( RADEON_IGPGART_INDEX, \ + ((addr) & 0x7f) | (1 << 8)); \ + RADEON_WRITE( RADEON_IGPGART_DATA, (val) ); \ + RADEON_WRITE( RADEON_IGPGART_INDEX, 0x7f ); \ +} while (0) + #define RADEON_WRITE_PCIE( addr, val ) \ do { \ RADEON_WRITE8( RADEON_PCIE_INDEX, \ diff --git a/drivers/char/drm/radeon_state.c b/drivers/char/drm/radeon_state.c index 938eccb78cc0..98c5f1d3a8e7 100644 --- a/drivers/char/drm/radeon_state.c +++ b/drivers/char/drm/radeon_state.c @@ -773,7 +773,7 @@ static void radeon_clear_box(drm_radeon_private_t * dev_priv, RADEON_GMC_SRC_DATATYPE_COLOR | RADEON_ROP3_P | RADEON_GMC_CLR_CMP_CNTL_DIS); - if (dev_priv->page_flipping && dev_priv->current_page == 1) { + if (dev_priv->sarea_priv->pfCurrentPage == 1) { OUT_RING(dev_priv->front_pitch_offset); } else { OUT_RING(dev_priv->back_pitch_offset); @@ -861,7 +861,7 @@ static void radeon_cp_dispatch_clear(drm_device_t * dev, dev_priv->stats.clears++; - if (dev_priv->page_flipping && dev_priv->current_page == 1) { + if (dev_priv->sarea_priv->pfCurrentPage == 1) { unsigned int tmp = flags; flags &= ~(RADEON_FRONT | RADEON_BACK); @@ -1382,7 +1382,7 @@ static void radeon_cp_dispatch_swap(drm_device_t * dev) /* Make this work even if front & back are flipped: */ OUT_RING(CP_PACKET0(RADEON_SRC_PITCH_OFFSET, 1)); - if (dev_priv->current_page == 0) { + if (dev_priv->sarea_priv->pfCurrentPage == 0) { OUT_RING(dev_priv->back_pitch_offset); OUT_RING(dev_priv->front_pitch_offset); } else { @@ -1416,12 +1416,12 @@ static void radeon_cp_dispatch_flip(drm_device_t * dev) { drm_radeon_private_t *dev_priv = dev->dev_private; drm_sarea_t *sarea = (drm_sarea_t *) dev_priv->sarea->handle; - int offset = (dev_priv->current_page == 1) + int offset = (dev_priv->sarea_priv->pfCurrentPage == 1) ? dev_priv->front_offset : dev_priv->back_offset; RING_LOCALS; - DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n", + DRM_DEBUG("%s: pfCurrentPage=%d\n", __FUNCTION__, - dev_priv->current_page, dev_priv->sarea_priv->pfCurrentPage); + dev_priv->sarea_priv->pfCurrentPage); /* Do some trivial performance monitoring... */ @@ -1449,8 +1449,8 @@ static void radeon_cp_dispatch_flip(drm_device_t * dev) * performing the swapbuffer ioctl. */ dev_priv->sarea_priv->last_frame++; - dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page = - 1 - dev_priv->current_page; + dev_priv->sarea_priv->pfCurrentPage = + 1 - dev_priv->sarea_priv->pfCurrentPage; BEGIN_RING(2); @@ -2152,24 +2152,10 @@ static int radeon_do_init_pageflip(drm_device_t * dev) ADVANCE_RING(); dev_priv->page_flipping = 1; - dev_priv->current_page = 0; - dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page; - return 0; -} - -/* Called whenever a client dies, from drm_release. - * NOTE: Lock isn't necessarily held when this is called! - */ -static int radeon_do_cleanup_pageflip(drm_device_t * dev) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - DRM_DEBUG("\n"); - - if (dev_priv->current_page != 0) - radeon_cp_dispatch_flip(dev); + if (dev_priv->sarea_priv->pfCurrentPage != 1) + dev_priv->sarea_priv->pfCurrentPage = 0; - dev_priv->page_flipping = 0; return 0; } @@ -3145,10 +3131,16 @@ static int radeon_cp_setparam(DRM_IOCTL_ARGS) break; case RADEON_SETPARAM_PCIGART_LOCATION: dev_priv->pcigart_offset = sp.value; + dev_priv->pcigart_offset_set = 1; break; case RADEON_SETPARAM_NEW_MEMMAP: dev_priv->new_memmap = sp.value; break; + case RADEON_SETPARAM_PCIGART_TABLE_SIZE: + dev_priv->gart_info.table_size = sp.value; + if (dev_priv->gart_info.table_size < RADEON_PCIGART_TABLE_SIZE) + dev_priv->gart_info.table_size = RADEON_PCIGART_TABLE_SIZE; + break; default: DRM_DEBUG("Invalid parameter %d\n", sp.param); return DRM_ERR(EINVAL); @@ -3168,9 +3160,7 @@ void radeon_driver_preclose(drm_device_t * dev, DRMFILE filp) { if (dev->dev_private) { drm_radeon_private_t *dev_priv = dev->dev_private; - if (dev_priv->page_flipping) { - radeon_do_cleanup_pageflip(dev); - } + dev_priv->page_flipping = 0; radeon_mem_release(filp, dev_priv->gart_heap); radeon_mem_release(filp, dev_priv->fb_heap); radeon_surfaces_release(filp, dev_priv); @@ -3179,6 +3169,14 @@ void radeon_driver_preclose(drm_device_t * dev, DRMFILE filp) void radeon_driver_lastclose(drm_device_t * dev) { + if (dev->dev_private) { + drm_radeon_private_t *dev_priv = dev->dev_private; + + if (dev_priv->sarea_priv && + dev_priv->sarea_priv->pfCurrentPage != 0) + radeon_cp_dispatch_flip(dev); + } + radeon_do_release(dev); } diff --git a/drivers/char/drm/via_dma.c b/drivers/char/drm/via_dma.c index c0539c6299cf..13a9c5ca4593 100644 --- a/drivers/char/drm/via_dma.c +++ b/drivers/char/drm/via_dma.c @@ -252,7 +252,7 @@ static int via_dma_init(DRM_IOCTL_ARGS) break; case VIA_DMA_INITIALIZED: retcode = (dev_priv->ring.virtual_start != NULL) ? - 0 : DRM_ERR(EFAULT); + 0 : DRM_ERR(EFAULT); break; default: retcode = DRM_ERR(EINVAL); @@ -432,56 +432,34 @@ static int via_hook_segment(drm_via_private_t * dev_priv, { int paused, count; volatile uint32_t *paused_at = dev_priv->last_pause_ptr; + uint32_t reader,ptr; + paused = 0; via_flush_write_combine(); - while (!*(via_get_dma(dev_priv) - 1)) ; - *dev_priv->last_pause_ptr = pause_addr_lo; + (void) *(volatile uint32_t *)(via_get_dma(dev_priv) -1); + *paused_at = pause_addr_lo; via_flush_write_combine(); - - /* - * The below statement is inserted to really force the flush. - * Not sure it is needed. - */ - - while (!*dev_priv->last_pause_ptr) ; + (void) *paused_at; + reader = *(dev_priv->hw_addr_ptr); + ptr = ((volatile char *)paused_at - dev_priv->dma_ptr) + + dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr + 4; dev_priv->last_pause_ptr = via_get_dma(dev_priv) - 1; - while (!*dev_priv->last_pause_ptr) ; - paused = 0; - count = 20; - - while (!(paused = (VIA_READ(0x41c) & 0x80000000)) && count--) ; - if ((count <= 8) && (count >= 0)) { - uint32_t rgtr, ptr; - rgtr = *(dev_priv->hw_addr_ptr); - ptr = ((volatile char *)dev_priv->last_pause_ptr - - dev_priv->dma_ptr) + dev_priv->dma_offset + - (uint32_t) dev_priv->agpAddr + 4 - CMDBUF_ALIGNMENT_SIZE; - if (rgtr <= ptr) { - DRM_ERROR - ("Command regulator\npaused at count %d, address %x, " - "while current pause address is %x.\n" - "Please mail this message to " - "<unichrome-devel@lists.sourceforge.net>\n", count, - rgtr, ptr); - } + if ((ptr - reader) <= dev_priv->dma_diff ) { + count = 10000000; + while (!(paused = (VIA_READ(0x41c) & 0x80000000)) && count--); } if (paused && !no_pci_fire) { - uint32_t rgtr, ptr; - uint32_t ptr_low; + reader = *(dev_priv->hw_addr_ptr); + if ((ptr - reader) == dev_priv->dma_diff) { - count = 1000000; - while ((VIA_READ(VIA_REG_STATUS) & VIA_CMD_RGTR_BUSY) - && count--) ; + /* + * There is a concern that these writes may stall the PCI bus + * if the GPU is not idle. However, idling the GPU first + * doesn't make a difference. + */ - rgtr = *(dev_priv->hw_addr_ptr); - ptr = ((volatile char *)paused_at - dev_priv->dma_ptr) + - dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr + 4; - - ptr_low = (ptr > 3 * CMDBUF_ALIGNMENT_SIZE) ? - ptr - 3 * CMDBUF_ALIGNMENT_SIZE : 0; - if (rgtr <= ptr && rgtr >= ptr_low) { VIA_WRITE(VIA_REG_TRANSET, (HC_ParaType_PreCR << 16)); VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_hi); VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_lo); @@ -494,6 +472,9 @@ static int via_hook_segment(drm_via_private_t * dev_priv, static int via_wait_idle(drm_via_private_t * dev_priv) { int count = 10000000; + + while (!(VIA_READ(VIA_REG_STATUS) & VIA_VR_QUEUE_BUSY) && count--); + while (count-- && (VIA_READ(VIA_REG_STATUS) & (VIA_CMD_RGTR_BUSY | VIA_2D_ENG_BUSY | VIA_3D_ENG_BUSY))) ; @@ -537,6 +518,9 @@ static void via_cmdbuf_start(drm_via_private_t * dev_priv) uint32_t end_addr, end_addr_lo; uint32_t command; uint32_t agp_base; + uint32_t ptr; + uint32_t reader; + int count; dev_priv->dma_low = 0; @@ -554,7 +538,7 @@ static void via_cmdbuf_start(drm_via_private_t * dev_priv) &pause_addr_hi, &pause_addr_lo, 1) - 1; via_flush_write_combine(); - while (!*dev_priv->last_pause_ptr) ; + (void) *(volatile uint32_t *)dev_priv->last_pause_ptr; VIA_WRITE(VIA_REG_TRANSET, (HC_ParaType_PreCR << 16)); VIA_WRITE(VIA_REG_TRANSPACE, command); @@ -566,6 +550,24 @@ static void via_cmdbuf_start(drm_via_private_t * dev_priv) DRM_WRITEMEMORYBARRIER(); VIA_WRITE(VIA_REG_TRANSPACE, command | HC_HAGPCMNT_MASK); VIA_READ(VIA_REG_TRANSPACE); + + dev_priv->dma_diff = 0; + + count = 10000000; + while (!(VIA_READ(0x41c) & 0x80000000) && count--); + + reader = *(dev_priv->hw_addr_ptr); + ptr = ((volatile char *)dev_priv->last_pause_ptr - dev_priv->dma_ptr) + + dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr + 4; + + /* + * This is the difference between where we tell the + * command reader to pause and where it actually pauses. + * This differs between hw implementation so we need to + * detect it. + */ + + dev_priv->dma_diff = ptr - reader; } static void via_pad_cache(drm_via_private_t * dev_priv, int qwords) @@ -592,7 +594,6 @@ static void via_cmdbuf_jump(drm_via_private_t * dev_priv) uint32_t pause_addr_lo, pause_addr_hi; uint32_t jump_addr_lo, jump_addr_hi; volatile uint32_t *last_pause_ptr; - uint32_t dma_low_save1, dma_low_save2; agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr; via_align_cmd(dev_priv, HC_HAGPBpID_JUMP, 0, &jump_addr_hi, @@ -619,31 +620,11 @@ static void via_cmdbuf_jump(drm_via_private_t * dev_priv) &pause_addr_lo, 0); *last_pause_ptr = pause_addr_lo; - dma_low_save1 = dev_priv->dma_low; - - /* - * Now, set a trap that will pause the regulator if it tries to rerun the old - * command buffer. (Which may happen if via_hook_segment detecs a command regulator pause - * and reissues the jump command over PCI, while the regulator has already taken the jump - * and actually paused at the current buffer end). - * There appears to be no other way to detect this condition, since the hw_addr_pointer - * does not seem to get updated immediately when a jump occurs. - */ - last_pause_ptr = - via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi, - &pause_addr_lo, 0) - 1; - via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi, - &pause_addr_lo, 0); - *last_pause_ptr = pause_addr_lo; - - dma_low_save2 = dev_priv->dma_low; - dev_priv->dma_low = dma_low_save1; - via_hook_segment(dev_priv, jump_addr_hi, jump_addr_lo, 0); - dev_priv->dma_low = dma_low_save2; - via_hook_segment(dev_priv, pause_addr_hi, pause_addr_lo, 0); + via_hook_segment( dev_priv, jump_addr_hi, jump_addr_lo, 0); } + static void via_cmdbuf_rewind(drm_via_private_t * dev_priv) { via_cmdbuf_jump(dev_priv); diff --git a/drivers/char/drm/via_drv.h b/drivers/char/drm/via_drv.h index 8b8778d4a423..b46ca8e6306d 100644 --- a/drivers/char/drm/via_drv.h +++ b/drivers/char/drm/via_drv.h @@ -29,11 +29,11 @@ #define DRIVER_NAME "via" #define DRIVER_DESC "VIA Unichrome / Pro" -#define DRIVER_DATE "20061227" +#define DRIVER_DATE "20070202" #define DRIVER_MAJOR 2 #define DRIVER_MINOR 11 -#define DRIVER_PATCHLEVEL 0 +#define DRIVER_PATCHLEVEL 1 #include "via_verifier.h" @@ -93,6 +93,7 @@ typedef struct drm_via_private { unsigned long vram_offset; unsigned long agp_offset; drm_via_blitq_t blit_queues[VIA_NUM_BLIT_ENGINES]; + uint32_t dma_diff; } drm_via_private_t; enum via_family { diff --git a/drivers/char/ds1620.c b/drivers/char/ds1620.c index 3d7efc26aad6..334ad5bbe6b6 100644 --- a/drivers/char/ds1620.c +++ b/drivers/char/ds1620.c @@ -4,7 +4,6 @@ */ #include <linux/module.h> #include <linux/miscdevice.h> -#include <linux/smp_lock.h> #include <linux/delay.h> #include <linux/proc_fs.h> #include <linux/capability.h> diff --git a/drivers/char/dsp56k.c b/drivers/char/dsp56k.c index db984e481d4c..9b8278e1f4f8 100644 --- a/drivers/char/dsp56k.c +++ b/drivers/char/dsp56k.c @@ -32,7 +32,6 @@ #include <linux/fs.h> #include <linux/mm.h> #include <linux/init.h> -#include <linux/smp_lock.h> #include <linux/device.h> #include <asm/atarihw.h> diff --git a/drivers/char/dtlk.c b/drivers/char/dtlk.c index d8dbdb916232..abde6ddefe69 100644 --- a/drivers/char/dtlk.c +++ b/drivers/char/dtlk.c @@ -62,7 +62,6 @@ #include <linux/init.h> /* for __init, module_{init,exit} */ #include <linux/poll.h> /* for POLLIN, etc. */ #include <linux/dtlk.h> /* local header file for DoubleTalk values */ -#include <linux/smp_lock.h> #ifdef TRACING #define TRACE_TEXT(str) printk(str); @@ -325,16 +324,22 @@ static int dtlk_release(struct inode *inode, struct file *file) static int __init dtlk_init(void) { + int err; + dtlk_port_lpc = 0; dtlk_port_tts = 0; dtlk_busy = 0; dtlk_major = register_chrdev(0, "dtlk", &dtlk_fops); - if (dtlk_major == 0) { + if (dtlk_major < 0) { printk(KERN_ERR "DoubleTalk PC - cannot register device\n"); - return 0; + return dtlk_major; + } + err = dtlk_dev_probe(); + if (err) { + unregister_chrdev(dtlk_major, "dtlk"); + return err; } - if (dtlk_dev_probe() == 0) - printk(", MAJOR %d\n", dtlk_major); + printk(", MAJOR %d\n", dtlk_major); init_waitqueue_head(&dtlk_process_list); diff --git a/drivers/char/ec3104_keyb.c b/drivers/char/ec3104_keyb.c index 77f58ed6d59a..020011495d91 100644 --- a/drivers/char/ec3104_keyb.c +++ b/drivers/char/ec3104_keyb.c @@ -41,7 +41,6 @@ #include <linux/miscdevice.h> #include <linux/slab.h> #include <linux/kbd_kern.h> -#include <linux/smp_lock.h> #include <linux/bitops.h> #include <asm/keyboard.h> diff --git a/drivers/char/epca.c b/drivers/char/epca.c index de5be30484ad..c6c56fb8ba50 100644 --- a/drivers/char/epca.c +++ b/drivers/char/epca.c @@ -949,7 +949,7 @@ static int block_til_ready(struct tty_struct *tty, } /* End forever while */ - current->state = TASK_RUNNING; + __set_current_state(TASK_RUNNING); remove_wait_queue(&ch->open_wait, &wait); if (!tty_hung_up_p(filp)) ch->count++; diff --git a/drivers/char/genrtc.c b/drivers/char/genrtc.c index 23b25ada65ea..9e1fc02967ff 100644 --- a/drivers/char/genrtc.c +++ b/drivers/char/genrtc.c @@ -12,7 +12,7 @@ * * This driver allows use of the real time clock (built into * nearly all computers) from user space. It exports the /dev/rtc - * interface supporting various ioctl() and also the /proc/dev/rtc + * interface supporting various ioctl() and also the /proc/driver/rtc * pseudo-file for status information. * * The ioctls can be used to set the interrupt behaviour where @@ -207,7 +207,7 @@ static ssize_t gen_rtc_read(struct file *file, char __user *buf, sizeof(unsigned long); } out: - current->state = TASK_RUNNING; + __set_current_state(TASK_RUNNING); remove_wait_queue(&gen_rtc_wait, &wait); return retval; @@ -377,7 +377,7 @@ static int gen_rtc_release(struct inode *inode, struct file *file) #ifdef CONFIG_PROC_FS /* - * Info exported via "/proc/rtc". + * Info exported via "/proc/driver/rtc". */ static int gen_rtc_proc_output(char *buf) diff --git a/drivers/char/hangcheck-timer.c b/drivers/char/hangcheck-timer.c index ae76a9ffe89f..f0e7263dfcde 100644 --- a/drivers/char/hangcheck-timer.c +++ b/drivers/char/hangcheck-timer.c @@ -44,7 +44,6 @@ #include <linux/fs.h> #include <linux/mm.h> #include <linux/reboot.h> -#include <linux/smp_lock.h> #include <linux/init.h> #include <linux/delay.h> #include <asm/uaccess.h> diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c index 0f9ed7b46a6d..322bc5f7d86b 100644 --- a/drivers/char/hvc_console.c +++ b/drivers/char/hvc_console.c @@ -111,7 +111,7 @@ static int last_hvc = -1; * lock held. If successful, this function increments the kobject reference * count against the target hvc_struct so it should be released when finished. */ -struct hvc_struct *hvc_get_by_index(int index) +static struct hvc_struct *hvc_get_by_index(int index) { struct hvc_struct *hp; unsigned long flags; @@ -150,7 +150,8 @@ static uint32_t vtermnos[MAX_NR_HVC_CONSOLES] = * hvc_console_setup() finds adapters. */ -void hvc_console_print(struct console *co, const char *b, unsigned count) +static void hvc_console_print(struct console *co, const char *b, + unsigned count) { char c[N_OUTBUF] __ALIGNED__; unsigned i = 0, n = 0; @@ -208,7 +209,7 @@ static int __init hvc_console_setup(struct console *co, char *options) return 0; } -struct console hvc_con_driver = { +static struct console hvc_con_driver = { .name = "hvc", .write = hvc_console_print, .device = hvc_console_device, @@ -278,7 +279,6 @@ int hvc_instantiate(uint32_t vtermno, int index, struct hv_ops *ops) return 0; } -EXPORT_SYMBOL(hvc_instantiate); /* Wake the sleeping khvcd */ static void hvc_kick(void) @@ -792,7 +792,6 @@ struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int irq, return hp; } -EXPORT_SYMBOL(hvc_alloc); int __devexit hvc_remove(struct hvc_struct *hp) { @@ -828,11 +827,10 @@ int __devexit hvc_remove(struct hvc_struct *hp) tty_hangup(tty); return 0; } -EXPORT_SYMBOL(hvc_remove); /* Driver initialization. Follow console initialization. This is where the TTY * interfaces start to become available. */ -int __init hvc_init(void) +static int __init hvc_init(void) { struct tty_driver *drv; diff --git a/drivers/char/hvc_iseries.c b/drivers/char/hvc_iseries.c index ec420fe8a908..b37f1d5a5be6 100644 --- a/drivers/char/hvc_iseries.c +++ b/drivers/char/hvc_iseries.c @@ -579,7 +579,7 @@ static int hvc_find_vtys(void) if (!vtermno) continue; - if (!device_is_compatible(vty, "IBM,iSeries-vty")) + if (!of_device_is_compatible(vty, "IBM,iSeries-vty")) continue; if (num_found == 0) diff --git a/drivers/char/hvc_vio.c b/drivers/char/hvc_vio.c index 94a542e20efb..79711aa4b41d 100644 --- a/drivers/char/hvc_vio.c +++ b/drivers/char/hvc_vio.c @@ -157,7 +157,7 @@ static int hvc_find_vtys(void) if (!vtermno) continue; - if (device_is_compatible(vty, "hvterm1")) { + if (of_device_is_compatible(vty, "hvterm1")) { hvc_instantiate(*vtermno, num_found, &hvc_get_put_ops); ++num_found; } diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig index 5f3acd8e64b8..7cda04b33534 100644 --- a/drivers/char/hw_random/Kconfig +++ b/drivers/char/hw_random/Kconfig @@ -91,3 +91,17 @@ config HW_RANDOM_OMAP module will be called omap-rng. If unsure, say Y. + +config HW_RANDOM_PASEMI + tristate "PA Semi HW Random Number Generator support" + depends on HW_RANDOM && PPC_PASEMI + default HW_RANDOM + ---help--- + This driver provides kernel-side support for the Random Number + Generator hardware found on PA6T-1682M processor. + + To compile this driver as a module, choose M here: the + module will be called pasemi-rng. + + If unsure, say Y. + diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile index c41fa19454e3..c8b7300e2fb1 100644 --- a/drivers/char/hw_random/Makefile +++ b/drivers/char/hw_random/Makefile @@ -10,3 +10,4 @@ obj-$(CONFIG_HW_RANDOM_GEODE) += geode-rng.o obj-$(CONFIG_HW_RANDOM_VIA) += via-rng.o obj-$(CONFIG_HW_RANDOM_IXP4XX) += ixp4xx-rng.o obj-$(CONFIG_HW_RANDOM_OMAP) += omap-rng.o +obj-$(CONFIG_HW_RANDOM_PASEMI) += pasemi-rng.o diff --git a/drivers/char/hw_random/intel-rng.c b/drivers/char/hw_random/intel-rng.c index cc1046e6ee02..4ae9811d1a6c 100644 --- a/drivers/char/hw_random/intel-rng.c +++ b/drivers/char/hw_random/intel-rng.c @@ -24,10 +24,11 @@ * warranty of any kind, whether express or implied. */ -#include <linux/module.h> +#include <linux/hw_random.h> #include <linux/kernel.h> +#include <linux/module.h> #include <linux/pci.h> -#include <linux/hw_random.h> +#include <linux/stop_machine.h> #include <asm/io.h> @@ -217,30 +218,117 @@ static struct hwrng intel_rng = { .data_read = intel_rng_data_read, }; +struct intel_rng_hw { + struct pci_dev *dev; + void __iomem *mem; + u8 bios_cntl_off; + u8 bios_cntl_val; + u8 fwh_dec_en1_off; + u8 fwh_dec_en1_val; +}; -#ifdef CONFIG_SMP -static char __initdata waitflag; +static int __init intel_rng_hw_init(void *_intel_rng_hw) +{ + struct intel_rng_hw *intel_rng_hw = _intel_rng_hw; + u8 mfc, dvc; + + /* interrupts disabled in stop_machine_run call */ + + if (!(intel_rng_hw->fwh_dec_en1_val & FWH_F8_EN_MASK)) + pci_write_config_byte(intel_rng_hw->dev, + intel_rng_hw->fwh_dec_en1_off, + intel_rng_hw->fwh_dec_en1_val | + FWH_F8_EN_MASK); + if (!(intel_rng_hw->bios_cntl_val & BIOS_CNTL_WRITE_ENABLE_MASK)) + pci_write_config_byte(intel_rng_hw->dev, + intel_rng_hw->bios_cntl_off, + intel_rng_hw->bios_cntl_val | + BIOS_CNTL_WRITE_ENABLE_MASK); + + writeb(INTEL_FWH_RESET_CMD, intel_rng_hw->mem); + writeb(INTEL_FWH_READ_ID_CMD, intel_rng_hw->mem); + mfc = readb(intel_rng_hw->mem + INTEL_FWH_MANUFACTURER_CODE_ADDRESS); + dvc = readb(intel_rng_hw->mem + INTEL_FWH_DEVICE_CODE_ADDRESS); + writeb(INTEL_FWH_RESET_CMD, intel_rng_hw->mem); + + if (!(intel_rng_hw->bios_cntl_val & + (BIOS_CNTL_LOCK_ENABLE_MASK|BIOS_CNTL_WRITE_ENABLE_MASK))) + pci_write_config_byte(intel_rng_hw->dev, + intel_rng_hw->bios_cntl_off, + intel_rng_hw->bios_cntl_val); + if (!(intel_rng_hw->fwh_dec_en1_val & FWH_F8_EN_MASK)) + pci_write_config_byte(intel_rng_hw->dev, + intel_rng_hw->fwh_dec_en1_off, + intel_rng_hw->fwh_dec_en1_val); -static void __init intel_init_wait(void *unused) + if (mfc != INTEL_FWH_MANUFACTURER_CODE || + (dvc != INTEL_FWH_DEVICE_CODE_8M && + dvc != INTEL_FWH_DEVICE_CODE_4M)) { + printk(KERN_ERR PFX "FWH not detected\n"); + return -ENODEV; + } + + return 0; +} + +static int __init intel_init_hw_struct(struct intel_rng_hw *intel_rng_hw, + struct pci_dev *dev) { - while (waitflag) - cpu_relax(); + intel_rng_hw->bios_cntl_val = 0xff; + intel_rng_hw->fwh_dec_en1_val = 0xff; + intel_rng_hw->dev = dev; + + /* Check for Intel 82802 */ + if (dev->device < 0x2640) { + intel_rng_hw->fwh_dec_en1_off = FWH_DEC_EN1_REG_OLD; + intel_rng_hw->bios_cntl_off = BIOS_CNTL_REG_OLD; + } else { + intel_rng_hw->fwh_dec_en1_off = FWH_DEC_EN1_REG_NEW; + intel_rng_hw->bios_cntl_off = BIOS_CNTL_REG_NEW; + } + + pci_read_config_byte(dev, intel_rng_hw->fwh_dec_en1_off, + &intel_rng_hw->fwh_dec_en1_val); + pci_read_config_byte(dev, intel_rng_hw->bios_cntl_off, + &intel_rng_hw->bios_cntl_val); + + if ((intel_rng_hw->bios_cntl_val & + (BIOS_CNTL_LOCK_ENABLE_MASK|BIOS_CNTL_WRITE_ENABLE_MASK)) + == BIOS_CNTL_LOCK_ENABLE_MASK) { + static __initdata /*const*/ char warning[] = + KERN_WARNING PFX "Firmware space is locked read-only. " + KERN_WARNING PFX "If you can't or\n don't want to " + KERN_WARNING PFX "disable this in firmware setup, and " + KERN_WARNING PFX "if\n you are certain that your " + KERN_WARNING PFX "system has a functional\n RNG, try" + KERN_WARNING PFX "using the 'no_fwh_detect' option.\n"; + + if (no_fwh_detect) + return -ENODEV; + printk(warning); + return -EBUSY; + } + + intel_rng_hw->mem = ioremap_nocache(INTEL_FWH_ADDR, INTEL_FWH_ADDR_LEN); + if (intel_rng_hw->mem == NULL) + return -EBUSY; + + return 0; } -#endif + static int __init mod_init(void) { int err = -ENODEV; - unsigned i; + int i; struct pci_dev *dev = NULL; - void __iomem *mem; - unsigned long flags; - u8 bios_cntl_off, fwh_dec_en1_off; - u8 bios_cntl_val = 0xff, fwh_dec_en1_val = 0xff; - u8 hw_status, mfc, dvc; + void __iomem *mem = mem; + u8 hw_status; + struct intel_rng_hw *intel_rng_hw; for (i = 0; !dev && pci_tbl[i].vendor; ++i) - dev = pci_get_device(pci_tbl[i].vendor, pci_tbl[i].device, NULL); + dev = pci_get_device(pci_tbl[i].vendor, pci_tbl[i].device, + NULL); if (!dev) goto out; /* Device not found. */ @@ -250,39 +338,18 @@ static int __init mod_init(void) goto fwh_done; } - /* Check for Intel 82802 */ - if (dev->device < 0x2640) { - fwh_dec_en1_off = FWH_DEC_EN1_REG_OLD; - bios_cntl_off = BIOS_CNTL_REG_OLD; - } else { - fwh_dec_en1_off = FWH_DEC_EN1_REG_NEW; - bios_cntl_off = BIOS_CNTL_REG_NEW; - } - - pci_read_config_byte(dev, fwh_dec_en1_off, &fwh_dec_en1_val); - pci_read_config_byte(dev, bios_cntl_off, &bios_cntl_val); - - if ((bios_cntl_val & - (BIOS_CNTL_LOCK_ENABLE_MASK|BIOS_CNTL_WRITE_ENABLE_MASK)) - == BIOS_CNTL_LOCK_ENABLE_MASK) { - static __initdata /*const*/ char warning[] = - KERN_WARNING PFX "Firmware space is locked read-only. If you can't or\n" - KERN_WARNING PFX "don't want to disable this in firmware setup, and if\n" - KERN_WARNING PFX "you are certain that your system has a functional\n" - KERN_WARNING PFX "RNG, try using the 'no_fwh_detect' option.\n"; - + intel_rng_hw = kmalloc(sizeof(*intel_rng_hw), GFP_KERNEL); + if (!intel_rng_hw) { pci_dev_put(dev); - if (no_fwh_detect) - goto fwh_done; - printk(warning); - err = -EBUSY; goto out; } - mem = ioremap_nocache(INTEL_FWH_ADDR, INTEL_FWH_ADDR_LEN); - if (mem == NULL) { + err = intel_init_hw_struct(intel_rng_hw, dev); + if (err) { pci_dev_put(dev); - err = -EBUSY; + kfree(intel_rng_hw); + if (err == -ENODEV) + goto fwh_done; goto out; } @@ -290,59 +357,18 @@ static int __init mod_init(void) * Since the BIOS code/data is going to disappear from its normal * location with the Read ID command, all activity on the system * must be stopped until the state is back to normal. + * + * Use stop_machine_run because IPIs can be blocked by disabling + * interrupts. */ -#ifdef CONFIG_SMP - set_mb(waitflag, 1); - if (smp_call_function(intel_init_wait, NULL, 1, 0) != 0) { - set_mb(waitflag, 0); - pci_dev_put(dev); - printk(KERN_ERR PFX "cannot run on all processors\n"); - err = -EAGAIN; - goto err_unmap; - } -#endif - local_irq_save(flags); - - if (!(fwh_dec_en1_val & FWH_F8_EN_MASK)) - pci_write_config_byte(dev, - fwh_dec_en1_off, - fwh_dec_en1_val | FWH_F8_EN_MASK); - if (!(bios_cntl_val & BIOS_CNTL_WRITE_ENABLE_MASK)) - pci_write_config_byte(dev, - bios_cntl_off, - bios_cntl_val | BIOS_CNTL_WRITE_ENABLE_MASK); - - writeb(INTEL_FWH_RESET_CMD, mem); - writeb(INTEL_FWH_READ_ID_CMD, mem); - mfc = readb(mem + INTEL_FWH_MANUFACTURER_CODE_ADDRESS); - dvc = readb(mem + INTEL_FWH_DEVICE_CODE_ADDRESS); - writeb(INTEL_FWH_RESET_CMD, mem); - - if (!(bios_cntl_val & - (BIOS_CNTL_LOCK_ENABLE_MASK|BIOS_CNTL_WRITE_ENABLE_MASK))) - pci_write_config_byte(dev, bios_cntl_off, bios_cntl_val); - if (!(fwh_dec_en1_val & FWH_F8_EN_MASK)) - pci_write_config_byte(dev, fwh_dec_en1_off, fwh_dec_en1_val); - - local_irq_restore(flags); -#ifdef CONFIG_SMP - /* Tell other CPUs to resume. */ - set_mb(waitflag, 0); -#endif - - iounmap(mem); + err = stop_machine_run(intel_rng_hw_init, intel_rng_hw, NR_CPUS); pci_dev_put(dev); - - if (mfc != INTEL_FWH_MANUFACTURER_CODE || - (dvc != INTEL_FWH_DEVICE_CODE_8M && - dvc != INTEL_FWH_DEVICE_CODE_4M)) { - printk(KERN_ERR PFX "FWH not detected\n"); - err = -ENODEV; + iounmap(intel_rng_hw->mem); + kfree(intel_rng_hw); + if (err) goto out; - } fwh_done: - err = -ENOMEM; mem = ioremap(INTEL_RNG_ADDR, INTEL_RNG_ADDR_LEN); if (!mem) @@ -352,22 +378,21 @@ fwh_done: /* Check for Random Number Generator */ err = -ENODEV; hw_status = hwstatus_get(mem); - if ((hw_status & INTEL_RNG_PRESENT) == 0) - goto err_unmap; + if ((hw_status & INTEL_RNG_PRESENT) == 0) { + iounmap(mem); + goto out; + } printk(KERN_INFO "Intel 82802 RNG detected\n"); err = hwrng_register(&intel_rng); if (err) { printk(KERN_ERR PFX "RNG registering failed (%d)\n", err); - goto err_unmap; + iounmap(mem); } out: return err; -err_unmap: - iounmap(mem); - goto out; } static void __exit mod_exit(void) diff --git a/drivers/char/hw_random/pasemi-rng.c b/drivers/char/hw_random/pasemi-rng.c new file mode 100644 index 000000000000..fa6040b6c8f2 --- /dev/null +++ b/drivers/char/hw_random/pasemi-rng.c @@ -0,0 +1,156 @@ +/* + * Copyright (C) 2006-2007 PA Semi, Inc + * + * Maintained by: Olof Johansson <olof@lixom.net> + * + * Driver for the PWRficient onchip rng + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * 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/module.h> +#include <linux/kernel.h> +#include <linux/platform_device.h> +#include <linux/hw_random.h> +#include <asm/of_platform.h> +#include <asm/io.h> + +#define SDCRNG_CTL_REG 0x00 +#define SDCRNG_CTL_FVLD_M 0x0000f000 +#define SDCRNG_CTL_FVLD_S 12 +#define SDCRNG_CTL_KSZ 0x00000800 +#define SDCRNG_CTL_RSRC_CRG 0x00000010 +#define SDCRNG_CTL_RSRC_RRG 0x00000000 +#define SDCRNG_CTL_CE 0x00000004 +#define SDCRNG_CTL_RE 0x00000002 +#define SDCRNG_CTL_DR 0x00000001 +#define SDCRNG_CTL_SELECT_RRG_RNG (SDCRNG_CTL_RE | SDCRNG_CTL_RSRC_RRG) +#define SDCRNG_CTL_SELECT_CRG_RNG (SDCRNG_CTL_CE | SDCRNG_CTL_RSRC_CRG) +#define SDCRNG_VAL_REG 0x20 + +#define MODULE_NAME "pasemi_rng" + +static int pasemi_rng_data_present(struct hwrng *rng) +{ + void __iomem *rng_regs = (void __iomem *)rng->priv; + + return (in_le32(rng_regs + SDCRNG_CTL_REG) + & SDCRNG_CTL_FVLD_M) ? 1 : 0; +} + +static int pasemi_rng_data_read(struct hwrng *rng, u32 *data) +{ + void __iomem *rng_regs = (void __iomem *)rng->priv; + *data = in_le32(rng_regs + SDCRNG_VAL_REG); + return 4; +} + +static int pasemi_rng_init(struct hwrng *rng) +{ + void __iomem *rng_regs = (void __iomem *)rng->priv; + u32 ctl; + + ctl = SDCRNG_CTL_DR | SDCRNG_CTL_SELECT_RRG_RNG | SDCRNG_CTL_KSZ; + out_le32(rng_regs + SDCRNG_CTL_REG, ctl); + out_le32(rng_regs + SDCRNG_CTL_REG, ctl & ~SDCRNG_CTL_DR); + + return 0; +} + +static void pasemi_rng_cleanup(struct hwrng *rng) +{ + void __iomem *rng_regs = (void __iomem *)rng->priv; + u32 ctl; + + ctl = SDCRNG_CTL_RE | SDCRNG_CTL_CE; + out_le32(rng_regs + SDCRNG_CTL_REG, + in_le32(rng_regs + SDCRNG_CTL_REG) & ~ctl); +} + +static struct hwrng pasemi_rng = { + .name = MODULE_NAME, + .init = pasemi_rng_init, + .cleanup = pasemi_rng_cleanup, + .data_present = pasemi_rng_data_present, + .data_read = pasemi_rng_data_read, +}; + +static int __devinit rng_probe(struct of_device *ofdev, + const struct of_device_id *match) +{ + void __iomem *rng_regs; + struct device_node *rng_np = ofdev->node; + struct resource res; + int err = 0; + + err = of_address_to_resource(rng_np, 0, &res); + if (err) + return -ENODEV; + + rng_regs = ioremap(res.start, 0x100); + + if (!rng_regs) + return -ENOMEM; + + pasemi_rng.priv = (unsigned long)rng_regs; + + printk(KERN_INFO "Registering PA Semi RNG\n"); + + err = hwrng_register(&pasemi_rng); + + if (err) + iounmap(rng_regs); + + return err; +} + +static int __devexit rng_remove(struct of_device *dev) +{ + void __iomem *rng_regs = (void __iomem *)pasemi_rng.priv; + + hwrng_unregister(&pasemi_rng); + iounmap(rng_regs); + + return 0; +} + +static struct of_device_id rng_match[] = { + { + .compatible = "1682m-rng", + }, + {}, +}; + +static struct of_platform_driver rng_driver = { + .name = "pasemi-rng", + .match_table = rng_match, + .probe = rng_probe, + .remove = rng_remove, +}; + +static int __init rng_init(void) +{ + return of_register_platform_driver(&rng_driver); +} +module_init(rng_init); + +static void __exit rng_exit(void) +{ + of_unregister_platform_driver(&rng_driver); +} +module_exit(rng_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Egor Martovetsky <egor@pasemi.com>"); +MODULE_DESCRIPTION("H/W RNG driver for PA Semi processor"); diff --git a/drivers/char/i8k.c b/drivers/char/i8k.c index 353d9f3cf8d7..0289705967de 100644 --- a/drivers/char/i8k.c +++ b/drivers/char/i8k.c @@ -22,6 +22,7 @@ #include <linux/proc_fs.h> #include <linux/seq_file.h> #include <linux/dmi.h> +#include <linux/capability.h> #include <asm/uaccess.h> #include <asm/io.h> diff --git a/drivers/char/ip27-rtc.c b/drivers/char/ip27-rtc.c index a48da02aad2f..932264a657d0 100644 --- a/drivers/char/ip27-rtc.c +++ b/drivers/char/ip27-rtc.c @@ -35,7 +35,6 @@ #include <linux/init.h> #include <linux/poll.h> #include <linux/proc_fs.h> -#include <linux/smp_lock.h> #include <asm/m48t35.h> #include <asm/sn/ioc3.h> diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index e22146546add..6c5d15de3317 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -9,6 +9,7 @@ * source@mvista.com * * Copyright 2002 MontaVista Software Inc. + * Copyright 2006 IBM Corp., Christian Krafft <krafft@de.ibm.com> * * 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 @@ -64,6 +65,11 @@ #include <linux/string.h> #include <linux/ctype.h> +#ifdef CONFIG_PPC_OF +#include <asm/of_device.h> +#include <asm/of_platform.h> +#endif + #define PFX "ipmi_si: " /* Measure times between events in the driver. */ @@ -76,6 +82,12 @@ #define SI_SHORT_TIMEOUT_USEC 250 /* .25ms when the SM request a short timeout */ +/* Bit for BMC global enables. */ +#define IPMI_BMC_RCV_MSG_INTR 0x01 +#define IPMI_BMC_EVT_MSG_INTR 0x02 +#define IPMI_BMC_EVT_MSG_BUFF 0x04 +#define IPMI_BMC_SYS_LOG 0x08 + enum si_intf_state { SI_NORMAL, SI_GETTING_FLAGS, @@ -84,7 +96,9 @@ enum si_intf_state { SI_CLEARING_FLAGS_THEN_SET_IRQ, SI_GETTING_MESSAGES, SI_ENABLE_INTERRUPTS1, - SI_ENABLE_INTERRUPTS2 + SI_ENABLE_INTERRUPTS2, + SI_DISABLE_INTERRUPTS1, + SI_DISABLE_INTERRUPTS2 /* FIXME - add watchdog stuff. */ }; @@ -333,6 +347,17 @@ static void start_enable_irq(struct smi_info *smi_info) smi_info->si_state = SI_ENABLE_INTERRUPTS1; } +static void start_disable_irq(struct smi_info *smi_info) +{ + unsigned char msg[2]; + + msg[0] = (IPMI_NETFN_APP_REQUEST << 2); + msg[1] = IPMI_GET_BMC_GLOBAL_ENABLES_CMD; + + smi_info->handlers->start_transaction(smi_info->si_sm, msg, 2); + smi_info->si_state = SI_DISABLE_INTERRUPTS1; +} + static void start_clear_flags(struct smi_info *smi_info) { unsigned char msg[3]; @@ -353,7 +378,7 @@ static void start_clear_flags(struct smi_info *smi_info) static inline void disable_si_irq(struct smi_info *smi_info) { if ((smi_info->irq) && (!smi_info->interrupt_disabled)) { - disable_irq_nosync(smi_info->irq); + start_disable_irq(smi_info); smi_info->interrupt_disabled = 1; } } @@ -361,7 +386,7 @@ static inline void disable_si_irq(struct smi_info *smi_info) static inline void enable_si_irq(struct smi_info *smi_info) { if ((smi_info->irq) && (smi_info->interrupt_disabled)) { - enable_irq(smi_info->irq); + start_enable_irq(smi_info); smi_info->interrupt_disabled = 0; } } @@ -583,7 +608,9 @@ static void handle_transaction_done(struct smi_info *smi_info) } else { msg[0] = (IPMI_NETFN_APP_REQUEST << 2); msg[1] = IPMI_SET_BMC_GLOBAL_ENABLES_CMD; - msg[2] = msg[3] | 1; /* enable msg queue int */ + msg[2] = (msg[3] | + IPMI_BMC_RCV_MSG_INTR | + IPMI_BMC_EVT_MSG_INTR); smi_info->handlers->start_transaction( smi_info->si_sm, msg, 3); smi_info->si_state = SI_ENABLE_INTERRUPTS2; @@ -605,6 +632,45 @@ static void handle_transaction_done(struct smi_info *smi_info) smi_info->si_state = SI_NORMAL; break; } + + case SI_DISABLE_INTERRUPTS1: + { + unsigned char msg[4]; + + /* We got the flags from the SMI, now handle them. */ + smi_info->handlers->get_result(smi_info->si_sm, msg, 4); + if (msg[2] != 0) { + printk(KERN_WARNING + "ipmi_si: Could not disable interrupts" + ", failed get.\n"); + smi_info->si_state = SI_NORMAL; + } else { + msg[0] = (IPMI_NETFN_APP_REQUEST << 2); + msg[1] = IPMI_SET_BMC_GLOBAL_ENABLES_CMD; + msg[2] = (msg[3] & + ~(IPMI_BMC_RCV_MSG_INTR | + IPMI_BMC_EVT_MSG_INTR)); + smi_info->handlers->start_transaction( + smi_info->si_sm, msg, 3); + smi_info->si_state = SI_DISABLE_INTERRUPTS2; + } + break; + } + + case SI_DISABLE_INTERRUPTS2: + { + unsigned char msg[4]; + + /* We got the flags from the SMI, now handle them. */ + smi_info->handlers->get_result(smi_info->si_sm, msg, 4); + if (msg[2] != 0) { + printk(KERN_WARNING + "ipmi_si: Could not disable interrupts" + ", failed set.\n"); + } + smi_info->si_state = SI_NORMAL; + break; + } } } @@ -858,9 +924,6 @@ static void smi_timeout(unsigned long data) struct timeval t; #endif - if (atomic_read(&smi_info->stop_operation)) - return; - spin_lock_irqsave(&(smi_info->si_lock), flags); #ifdef DEBUG_TIMING do_gettimeofday(&t); @@ -916,15 +979,11 @@ static irqreturn_t si_irq_handler(int irq, void *data) smi_info->interrupts++; spin_unlock(&smi_info->count_lock); - if (atomic_read(&smi_info->stop_operation)) - goto out; - #ifdef DEBUG_TIMING do_gettimeofday(&t); printk("**Interrupt: %d.%9.9d\n", t.tv_sec, t.tv_usec); #endif smi_event_handler(smi_info, 0); - out: spin_unlock_irqrestore(&(smi_info->si_lock), flags); return IRQ_HANDLED; } @@ -1006,6 +1065,7 @@ static DEFINE_MUTEX(smi_infos_lock); static int smi_num; /* Used to sequence the SMIs */ #define DEFAULT_REGSPACING 1 +#define DEFAULT_REGSIZE 1 static int si_trydefaults = 1; static char *si_type[SI_MAX_PARMS]; @@ -1111,7 +1171,7 @@ static int std_irq_setup(struct smi_info *info) if (info->si_type == SI_BT) { rv = request_irq(info->irq, si_bt_irq_handler, - IRQF_DISABLED, + IRQF_SHARED | IRQF_DISABLED, DEVICE_NAME, info); if (!rv) @@ -1121,7 +1181,7 @@ static int std_irq_setup(struct smi_info *info) } else rv = request_irq(info->irq, si_irq_handler, - IRQF_DISABLED, + IRQF_SHARED | IRQF_DISABLED, DEVICE_NAME, info); if (rv) { @@ -1701,15 +1761,11 @@ static u32 ipmi_acpi_gpe(void *context) smi_info->interrupts++; spin_unlock(&smi_info->count_lock); - if (atomic_read(&smi_info->stop_operation)) - goto out; - #ifdef DEBUG_TIMING do_gettimeofday(&t); printk("**ACPI_GPE: %d.%9.9d\n", t.tv_sec, t.tv_usec); #endif smi_event_handler(smi_info, 0); - out: spin_unlock_irqrestore(&(smi_info->si_lock), flags); return ACPI_INTERRUPT_HANDLED; @@ -2133,12 +2189,15 @@ static int __devinit ipmi_pci_probe(struct pci_dev *pdev, info->irq_setup = std_irq_setup; info->dev = &pdev->dev; + pci_set_drvdata(pdev, info); return try_smi_init(info); } static void __devexit ipmi_pci_remove(struct pci_dev *pdev) { + struct smi_info *info = pci_get_drvdata(pdev); + cleanup_one_si(info); } #ifdef CONFIG_PM @@ -2172,6 +2231,99 @@ static struct pci_driver ipmi_pci_driver = { #endif /* CONFIG_PCI */ +#ifdef CONFIG_PPC_OF +static int __devinit ipmi_of_probe(struct of_device *dev, + const struct of_device_id *match) +{ + struct smi_info *info; + struct resource resource; + const int *regsize, *regspacing, *regshift; + struct device_node *np = dev->node; + int ret; + int proplen; + + dev_info(&dev->dev, PFX "probing via device tree\n"); + + ret = of_address_to_resource(np, 0, &resource); + if (ret) { + dev_warn(&dev->dev, PFX "invalid address from OF\n"); + return ret; + } + + regsize = get_property(np, "reg-size", &proplen); + if (regsize && proplen != 4) { + dev_warn(&dev->dev, PFX "invalid regsize from OF\n"); + return -EINVAL; + } + + regspacing = get_property(np, "reg-spacing", &proplen); + if (regspacing && proplen != 4) { + dev_warn(&dev->dev, PFX "invalid regspacing from OF\n"); + return -EINVAL; + } + + regshift = get_property(np, "reg-shift", &proplen); + if (regshift && proplen != 4) { + dev_warn(&dev->dev, PFX "invalid regshift from OF\n"); + return -EINVAL; + } + + info = kzalloc(sizeof(*info), GFP_KERNEL); + + if (!info) { + dev_err(&dev->dev, + PFX "could not allocate memory for OF probe\n"); + return -ENOMEM; + } + + info->si_type = (enum si_type) match->data; + info->addr_source = "device-tree"; + info->io_setup = mem_setup; + info->irq_setup = std_irq_setup; + + info->io.addr_type = IPMI_MEM_ADDR_SPACE; + info->io.addr_data = resource.start; + + info->io.regsize = regsize ? *regsize : DEFAULT_REGSIZE; + info->io.regspacing = regspacing ? *regspacing : DEFAULT_REGSPACING; + info->io.regshift = regshift ? *regshift : 0; + + info->irq = irq_of_parse_and_map(dev->node, 0); + info->dev = &dev->dev; + + dev_dbg(&dev->dev, "addr 0x%lx regsize %ld spacing %ld irq %x\n", + info->io.addr_data, info->io.regsize, info->io.regspacing, + info->irq); + + dev->dev.driver_data = (void*) info; + + return try_smi_init(info); +} + +static int __devexit ipmi_of_remove(struct of_device *dev) +{ + cleanup_one_si(dev->dev.driver_data); + return 0; +} + +static struct of_device_id ipmi_match[] = +{ + { .type = "ipmi", .compatible = "ipmi-kcs", .data = (void *)(unsigned long) SI_KCS }, + { .type = "ipmi", .compatible = "ipmi-smic", .data = (void *)(unsigned long) SI_SMIC }, + { .type = "ipmi", .compatible = "ipmi-bt", .data = (void *)(unsigned long) SI_BT }, + {}, +}; + +static struct of_platform_driver ipmi_of_platform_driver = +{ + .name = "ipmi", + .match_table = ipmi_match, + .probe = ipmi_of_probe, + .remove = __devexit_p(ipmi_of_remove), +}; +#endif /* CONFIG_PPC_OF */ + + static int try_get_dev_id(struct smi_info *smi_info) { unsigned char msg[2]; @@ -2801,6 +2953,10 @@ static __devinit int init_ipmi_si(void) } #endif +#ifdef CONFIG_PPC_OF + of_register_platform_driver(&ipmi_of_platform_driver); +#endif + if (si_trydefaults) { mutex_lock(&smi_infos_lock); if (list_empty(&smi_infos)) { @@ -2838,28 +2994,33 @@ static void cleanup_one_si(struct smi_info *to_clean) list_del(&to_clean->link); - /* Tell the timer and interrupt handlers that we are shutting - down. */ - spin_lock_irqsave(&(to_clean->si_lock), flags); - spin_lock(&(to_clean->msg_lock)); - + /* Tell the driver that we are shutting down. */ atomic_inc(&to_clean->stop_operation); - if (to_clean->irq_cleanup) - to_clean->irq_cleanup(to_clean); - - spin_unlock(&(to_clean->msg_lock)); - spin_unlock_irqrestore(&(to_clean->si_lock), flags); - - /* Wait until we know that we are out of any interrupt - handlers might have been running before we freed the - interrupt. */ - synchronize_sched(); - + /* Make sure the timer and thread are stopped and will not run + again. */ wait_for_timer_and_thread(to_clean); - /* Interrupts and timeouts are stopped, now make sure the - interface is in a clean state. */ + /* Timeouts are stopped, now make sure the interrupts are off + for the device. A little tricky with locks to make sure + there are no races. */ + spin_lock_irqsave(&to_clean->si_lock, flags); + while (to_clean->curr_msg || (to_clean->si_state != SI_NORMAL)) { + spin_unlock_irqrestore(&to_clean->si_lock, flags); + poll(to_clean); + schedule_timeout_uninterruptible(1); + spin_lock_irqsave(&to_clean->si_lock, flags); + } + disable_si_irq(to_clean); + spin_unlock_irqrestore(&to_clean->si_lock, flags); + while (to_clean->curr_msg || (to_clean->si_state != SI_NORMAL)) { + poll(to_clean); + schedule_timeout_uninterruptible(1); + } + + /* Clean up interrupts and make sure that everything is done. */ + if (to_clean->irq_cleanup) + to_clean->irq_cleanup(to_clean); while (to_clean->curr_msg || (to_clean->si_state != SI_NORMAL)) { poll(to_clean); schedule_timeout_uninterruptible(1); @@ -2898,6 +3059,10 @@ static __exit void cleanup_ipmi_si(void) pci_unregister_driver(&ipmi_pci_driver); #endif +#ifdef CONFIG_PPC_OF + of_unregister_platform_driver(&ipmi_of_platform_driver); +#endif + mutex_lock(&smi_infos_lock); list_for_each_entry_safe(e, tmp_e, &smi_infos, link) cleanup_one_si(e); diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c index 6b634e8d9519..147c12047cf3 100644 --- a/drivers/char/ipmi/ipmi_watchdog.c +++ b/drivers/char/ipmi/ipmi_watchdog.c @@ -39,6 +39,7 @@ #include <linux/miscdevice.h> #include <linux/init.h> #include <linux/completion.h> +#include <linux/kdebug.h> #include <linux/rwsem.h> #include <linux/errno.h> #include <asm/uaccess.h> @@ -49,9 +50,18 @@ #include <linux/poll.h> #include <linux/string.h> #include <linux/ctype.h> +#include <linux/delay.h> #include <asm/atomic.h> -#ifdef CONFIG_X86_LOCAL_APIC -#include <asm/apic.h> + +#ifdef CONFIG_X86 +/* This is ugly, but I've determined that x86 is the only architecture + that can reasonably support the IPMI NMI watchdog timeout at this + time. If another architecture adds this capability somehow, it + will have to be a somewhat different mechanism and I have no idea + how it will work. So in the unlikely event that another + architecture supports this, we can figure out a good generic + mechanism for it at that time. */ +#define HAVE_DIE_NMI_POST #endif #define PFX "IPMI Watchdog: " @@ -317,6 +327,11 @@ static unsigned char ipmi_version_minor; /* If a pretimeout occurs, this is used to allow only one panic to happen. */ static atomic_t preop_panic_excl = ATOMIC_INIT(-1); +#ifdef HAVE_DIE_NMI_POST +static int testing_nmi; +static int nmi_handler_registered; +#endif + static int ipmi_heartbeat(void); static void panic_halt_ipmi_heartbeat(void); @@ -358,6 +373,10 @@ static int i_ipmi_set_timeout(struct ipmi_smi_msg *smi_msg, int hbnow = 0; + /* These can be cleared as we are setting the timeout. */ + ipmi_start_timer_on_heartbeat = 0; + pretimeout_since_last_heartbeat = 0; + data[0] = 0; WDOG_SET_TIMER_USE(data[0], WDOG_TIMER_USE_SMS_OS); @@ -432,13 +451,12 @@ static int ipmi_set_timeout(int do_heartbeat) wait_for_completion(&set_timeout_wait); + mutex_unlock(&set_timeout_lock); + if ((do_heartbeat == IPMI_SET_TIMEOUT_FORCE_HB) || ((send_heartbeat_now) && (do_heartbeat == IPMI_SET_TIMEOUT_HB_IF_NECESSARY))) - { rv = ipmi_heartbeat(); - } - mutex_unlock(&set_timeout_lock); out: return rv; @@ -518,12 +536,10 @@ static int ipmi_heartbeat(void) int rv; struct ipmi_system_interface_addr addr; - if (ipmi_ignore_heartbeat) { + if (ipmi_ignore_heartbeat) return 0; - } if (ipmi_start_timer_on_heartbeat) { - ipmi_start_timer_on_heartbeat = 0; ipmi_watchdog_state = action_val; return ipmi_set_timeout(IPMI_SET_TIMEOUT_FORCE_HB); } else if (pretimeout_since_last_heartbeat) { @@ -531,7 +547,6 @@ static int ipmi_heartbeat(void) We don't want to set the action, though, we want to leave that alone (thus it can't be combined with the above operation. */ - pretimeout_since_last_heartbeat = 0; return ipmi_set_timeout(IPMI_SET_TIMEOUT_HB_IF_NECESSARY); } @@ -919,6 +934,45 @@ static void ipmi_register_watchdog(int ipmi_intf) printk(KERN_CRIT PFX "Unable to register misc device\n"); } +#ifdef HAVE_DIE_NMI_POST + if (nmi_handler_registered) { + int old_pretimeout = pretimeout; + int old_timeout = timeout; + int old_preop_val = preop_val; + + /* Set the pretimeout to go off in a second and give + ourselves plenty of time to stop the timer. */ + ipmi_watchdog_state = WDOG_TIMEOUT_RESET; + preop_val = WDOG_PREOP_NONE; /* Make sure nothing happens */ + pretimeout = 99; + timeout = 100; + + testing_nmi = 1; + + rv = ipmi_set_timeout(IPMI_SET_TIMEOUT_FORCE_HB); + if (rv) { + printk(KERN_WARNING PFX "Error starting timer to" + " test NMI: 0x%x. The NMI pretimeout will" + " likely not work\n", rv); + rv = 0; + goto out_restore; + } + + msleep(1500); + + if (testing_nmi != 2) { + printk(KERN_WARNING PFX "IPMI NMI didn't seem to" + " occur. The NMI pretimeout will" + " likely not work\n"); + } + out_restore: + testing_nmi = 0; + preop_val = old_preop_val; + pretimeout = old_pretimeout; + timeout = old_timeout; + } +#endif + out: up_write(®ister_sem); @@ -928,6 +982,10 @@ static void ipmi_register_watchdog(int ipmi_intf) ipmi_watchdog_state = action_val; ipmi_set_timeout(IPMI_SET_TIMEOUT_FORCE_HB); printk(KERN_INFO PFX "Starting now!\n"); + } else { + /* Stop the timer now. */ + ipmi_watchdog_state = WDOG_TIMEOUT_NONE; + ipmi_set_timeout(IPMI_SET_TIMEOUT_NO_HB); } } @@ -964,17 +1022,28 @@ static void ipmi_unregister_watchdog(int ipmi_intf) up_write(®ister_sem); } -#ifdef HAVE_NMI_HANDLER +#ifdef HAVE_DIE_NMI_POST static int -ipmi_nmi(void *dev_id, int cpu, int handled) +ipmi_nmi(struct notifier_block *self, unsigned long val, void *data) { + if (val != DIE_NMI_POST) + return NOTIFY_OK; + + if (testing_nmi) { + testing_nmi = 2; + return NOTIFY_STOP; + } + /* If we are not expecting a timeout, ignore it. */ if (ipmi_watchdog_state == WDOG_TIMEOUT_NONE) - return NOTIFY_DONE; + return NOTIFY_OK; + + if (preaction_val != WDOG_PRETIMEOUT_NMI) + return NOTIFY_OK; /* If no one else handled the NMI, we assume it was the IPMI watchdog. */ - if ((!handled) && (preop_val == WDOG_PREOP_PANIC)) { + if (preop_val == WDOG_PREOP_PANIC) { /* On some machines, the heartbeat will give an error and not work unless we re-enable the timer. So do so. */ @@ -983,18 +1052,12 @@ ipmi_nmi(void *dev_id, int cpu, int handled) panic(PFX "pre-timeout"); } - return NOTIFY_DONE; + return NOTIFY_STOP; } -static struct nmi_handler ipmi_nmi_handler = -{ - .link = LIST_HEAD_INIT(ipmi_nmi_handler.link), - .dev_name = "ipmi_watchdog", - .dev_id = NULL, - .handler = ipmi_nmi, - .priority = 0, /* Call us last. */ +static struct notifier_block ipmi_nmi_handler = { + .notifier_call = ipmi_nmi }; -int nmi_handler_registered; #endif static int wdog_reboot_handler(struct notifier_block *this, @@ -1111,7 +1174,7 @@ static int preaction_op(const char *inval, char *outval) preaction_val = WDOG_PRETIMEOUT_NONE; else if (strcmp(inval, "pre_smi") == 0) preaction_val = WDOG_PRETIMEOUT_SMI; -#ifdef HAVE_NMI_HANDLER +#ifdef HAVE_DIE_NMI_POST else if (strcmp(inval, "pre_nmi") == 0) preaction_val = WDOG_PRETIMEOUT_NMI; #endif @@ -1145,7 +1208,7 @@ static int preop_op(const char *inval, char *outval) static void check_parms(void) { -#ifdef HAVE_NMI_HANDLER +#ifdef HAVE_DIE_NMI_POST int do_nmi = 0; int rv; @@ -1158,20 +1221,9 @@ static void check_parms(void) preop_op("preop_none", NULL); do_nmi = 0; } -#ifdef CONFIG_X86_LOCAL_APIC - if (nmi_watchdog == NMI_IO_APIC) { - printk(KERN_WARNING PFX "nmi_watchdog is set to IO APIC" - " mode (value is %d), that is incompatible" - " with using NMI in the IPMI watchdog." - " Disabling IPMI nmi pretimeout.\n", - nmi_watchdog); - preaction_val = WDOG_PRETIMEOUT_NONE; - do_nmi = 0; - } -#endif } if (do_nmi && !nmi_handler_registered) { - rv = request_nmi(&ipmi_nmi_handler); + rv = register_die_notifier(&ipmi_nmi_handler); if (rv) { printk(KERN_WARNING PFX "Can't register nmi handler\n"); @@ -1179,7 +1231,7 @@ static void check_parms(void) } else nmi_handler_registered = 1; } else if (!do_nmi && nmi_handler_registered) { - release_nmi(&ipmi_nmi_handler); + unregister_die_notifier(&ipmi_nmi_handler); nmi_handler_registered = 0; } #endif @@ -1215,9 +1267,9 @@ static int __init ipmi_wdog_init(void) rv = ipmi_smi_watcher_register(&smi_watcher); if (rv) { -#ifdef HAVE_NMI_HANDLER - if (preaction_val == WDOG_PRETIMEOUT_NMI) - release_nmi(&ipmi_nmi_handler); +#ifdef HAVE_DIE_NMI_POST + if (nmi_handler_registered) + unregister_die_notifier(&ipmi_nmi_handler); #endif atomic_notifier_chain_unregister(&panic_notifier_list, &wdog_panic_notifier); @@ -1236,9 +1288,9 @@ static void __exit ipmi_wdog_exit(void) ipmi_smi_watcher_unregister(&smi_watcher); ipmi_unregister_watchdog(watchdog_ifnum); -#ifdef HAVE_NMI_HANDLER +#ifdef HAVE_DIE_NMI_POST if (nmi_handler_registered) - release_nmi(&ipmi_nmi_handler); + unregister_die_notifier(&ipmi_nmi_handler); #endif atomic_notifier_chain_unregister(&panic_notifier_list, diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c index 43ab9edc76f5..761f77740d67 100644 --- a/drivers/char/isicom.c +++ b/drivers/char/isicom.c @@ -137,11 +137,10 @@ #define InterruptTheCard(base) outw(0, (base) + 0xc) #define ClearInterrupt(base) inw((base) + 0x0a) +#define pr_dbg(str...) pr_debug("ISICOM: " str) #ifdef DEBUG -#define pr_dbg(str...) printk(KERN_DEBUG "ISICOM: " str) #define isicom_paranoia_check(a, b, c) __isicom_paranoia_check((a), (b), (c)) #else -#define pr_dbg(str...) do { } while (0) #define isicom_paranoia_check(a, b, c) 0 #endif diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c index c06e86ad1dab..1b094509b1d2 100644 --- a/drivers/char/keyboard.c +++ b/drivers/char/keyboard.c @@ -109,7 +109,7 @@ struct kbd_struct kbd_table[MAX_NR_CONSOLES]; static struct kbd_struct *kbd = kbd_table; struct vt_spawn_console vt_spawn_con = { - .lock = SPIN_LOCK_UNLOCKED, + .lock = __SPIN_LOCK_UNLOCKED(vt_spawn_con.lock), .pid = NULL, .sig = 0, }; diff --git a/drivers/char/lp.c b/drivers/char/lp.c index b51d08be0bcf..62051f8b0910 100644 --- a/drivers/char/lp.c +++ b/drivers/char/lp.c @@ -118,7 +118,6 @@ #include <linux/kernel.h> #include <linux/major.h> #include <linux/sched.h> -#include <linux/smp_lock.h> #include <linux/slab.h> #include <linux/fcntl.h> #include <linux/delay.h> @@ -139,9 +138,6 @@ /* if you have more than 8 printers, remember to increase LP_NO */ #define LP_NO 8 -/* ROUND_UP macro from fs/select.c */ -#define ROUND_UP(x,y) (((x)+(y)-1)/(y)) - static struct lp_struct lp_table[LP_NO]; static unsigned int lp_count = 0; @@ -652,7 +648,7 @@ static int lp_ioctl(struct inode *inode, struct file *file, (par_timeout.tv_usec < 0)) { return -EINVAL; } - to_jiffies = ROUND_UP(par_timeout.tv_usec, 1000000/HZ); + to_jiffies = DIV_ROUND_UP(par_timeout.tv_usec, 1000000/HZ); to_jiffies += par_timeout.tv_sec * (long) HZ; if (to_jiffies <= 0) { return -EINVAL; @@ -803,7 +799,7 @@ static int lp_register(int nr, struct parport *port) if (reset) lp_reset(nr); - class_device_create(lp_class, NULL, MKDEV(LP_MAJOR, nr), NULL, + class_device_create(lp_class, NULL, MKDEV(LP_MAJOR, nr), port->dev, "lp%d", nr); printk(KERN_INFO "lp%d: using %s (%s).\n", nr, port->name, diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 5f066963f171..cc9a9d0df979 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -18,7 +18,6 @@ #include <linux/raw.h> #include <linux/tty.h> #include <linux/capability.h> -#include <linux/smp_lock.h> #include <linux/ptrace.h> #include <linux/device.h> #include <linux/highmem.h> @@ -552,7 +551,7 @@ static ssize_t write_kmem(struct file * file, const char __user * buf, return virtr + wrote; } -#if (defined(CONFIG_ISA) || defined(CONFIG_PCI)) && !defined(__mc68000__) +#ifdef CONFIG_DEVPORT static ssize_t read_port(struct file * file, char __user * buf, size_t count, loff_t *ppos) { @@ -835,7 +834,7 @@ static const struct file_operations null_fops = { .splice_write = splice_write_null, }; -#if (defined(CONFIG_ISA) || defined(CONFIG_PCI)) && !defined(__mc68000__) +#ifdef CONFIG_DEVPORT static const struct file_operations port_fops = { .llseek = memory_lseek, .read = read_port, @@ -913,7 +912,7 @@ static int memory_open(struct inode * inode, struct file * filp) case 3: filp->f_op = &null_fops; break; -#if (defined(CONFIG_ISA) || defined(CONFIG_PCI)) && !defined(__mc68000__) +#ifdef CONFIG_DEVPORT case 4: filp->f_op = &port_fops; break; @@ -960,7 +959,7 @@ static const struct { {1, "mem", S_IRUSR | S_IWUSR | S_IRGRP, &mem_fops}, {2, "kmem", S_IRUSR | S_IWUSR | S_IRGRP, &kmem_fops}, {3, "null", S_IRUGO | S_IWUGO, &null_fops}, -#if (defined(CONFIG_ISA) || defined(CONFIG_PCI)) && !defined(__mc68000__) +#ifdef CONFIG_DEVPORT {4, "port", S_IRUSR | S_IWUSR | S_IRGRP, &port_fops}, #endif {5, "zero", S_IRUGO | S_IWUGO, &zero_fops}, diff --git a/drivers/char/misc.c b/drivers/char/misc.c index 7e975f606924..4e6fb9651a16 100644 --- a/drivers/char/misc.c +++ b/drivers/char/misc.c @@ -41,6 +41,7 @@ #include <linux/kernel.h> #include <linux/major.h> #include <linux/slab.h> +#include <linux/mutex.h> #include <linux/proc_fs.h> #include <linux/seq_file.h> #include <linux/stat.h> @@ -53,7 +54,7 @@ * Head entry for the doubly linked miscdevice list */ static LIST_HEAD(misc_list); -static DECLARE_MUTEX(misc_sem); +static DEFINE_MUTEX(misc_mtx); /* * Assigned numbers, used for dynamic minors @@ -69,7 +70,7 @@ static void *misc_seq_start(struct seq_file *seq, loff_t *pos) struct miscdevice *p; loff_t off = 0; - down(&misc_sem); + mutex_lock(&misc_mtx); list_for_each_entry(p, &misc_list, list) { if (*pos == off++) return p; @@ -89,7 +90,7 @@ static void *misc_seq_next(struct seq_file *seq, void *v, loff_t *pos) static void misc_seq_stop(struct seq_file *seq, void *v) { - up(&misc_sem); + mutex_unlock(&misc_mtx); } static int misc_seq_show(struct seq_file *seq, void *v) @@ -129,7 +130,7 @@ static int misc_open(struct inode * inode, struct file * file) int err = -ENODEV; const struct file_operations *old_fops, *new_fops = NULL; - down(&misc_sem); + mutex_lock(&misc_mtx); list_for_each_entry(c, &misc_list, list) { if (c->minor == minor) { @@ -139,9 +140,9 @@ static int misc_open(struct inode * inode, struct file * file) } if (!new_fops) { - up(&misc_sem); + mutex_unlock(&misc_mtx); request_module("char-major-%d-%d", MISC_MAJOR, minor); - down(&misc_sem); + mutex_lock(&misc_mtx); list_for_each_entry(c, &misc_list, list) { if (c->minor == minor) { @@ -165,7 +166,7 @@ static int misc_open(struct inode * inode, struct file * file) } fops_put(old_fops); fail: - up(&misc_sem); + mutex_unlock(&misc_mtx); return err; } @@ -201,10 +202,10 @@ int misc_register(struct miscdevice * misc) INIT_LIST_HEAD(&misc->list); - down(&misc_sem); + mutex_lock(&misc_mtx); list_for_each_entry(c, &misc_list, list) { if (c->minor == misc->minor) { - up(&misc_sem); + mutex_unlock(&misc_mtx); return -EBUSY; } } @@ -215,7 +216,7 @@ int misc_register(struct miscdevice * misc) if ( (misc_minors[i>>3] & (1 << (i&7))) == 0) break; if (i<0) { - up(&misc_sem); + mutex_unlock(&misc_mtx); return -EBUSY; } misc->minor = i; @@ -238,7 +239,7 @@ int misc_register(struct miscdevice * misc) */ list_add(&misc->list, &misc_list); out: - up(&misc_sem); + mutex_unlock(&misc_mtx); return err; } @@ -259,13 +260,13 @@ int misc_deregister(struct miscdevice * misc) if (list_empty(&misc->list)) return -EINVAL; - down(&misc_sem); + mutex_lock(&misc_mtx); list_del(&misc->list); device_destroy(misc_class, MKDEV(MISC_MAJOR, misc->minor)); if (i < DYNAMIC_MINORS && i>0) { misc_minors[i>>3] &= ~(1 << (misc->minor & 7)); } - up(&misc_sem); + mutex_unlock(&misc_mtx); return 0; } diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c index 7dbaee8d9402..e0d35c20c04f 100644 --- a/drivers/char/moxa.c +++ b/drivers/char/moxa.c @@ -1582,7 +1582,7 @@ copy: if(copy_from_user(&dltmp, argp, sizeof(struct dl_str))) return -EFAULT; - if(dltmp.cardno < 0 || dltmp.cardno >= MAX_BOARDS) + if(dltmp.cardno < 0 || dltmp.cardno >= MAX_BOARDS || dltmp.len < 0) return -EINVAL; switch(cmd) @@ -2529,6 +2529,8 @@ static int moxaloadbios(int cardno, unsigned char __user *tmp, int len) void __iomem *baseAddr; int i; + if(len < 0 || len > sizeof(moxaBuff)) + return -EINVAL; if(copy_from_user(moxaBuff, tmp, len)) return -EFAULT; baseAddr = moxa_boards[cardno].basemem; @@ -2576,7 +2578,7 @@ static int moxaload320b(int cardno, unsigned char __user *tmp, int len) void __iomem *baseAddr; int i; - if(len > sizeof(moxaBuff)) + if(len < 0 || len > sizeof(moxaBuff)) return -EINVAL; if(copy_from_user(moxaBuff, tmp, len)) return -EFAULT; @@ -2596,6 +2598,8 @@ static int moxaloadcode(int cardno, unsigned char __user *tmp, int len) void __iomem *baseAddr, *ofsAddr; int retval, port, i; + if(len < 0 || len > sizeof(moxaBuff)) + return -EINVAL; if(copy_from_user(moxaBuff, tmp, len)) return -EFAULT; baseAddr = moxa_boards[cardno].basemem; diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c index 80a01150b86c..5953a45d7e96 100644 --- a/drivers/char/mxser.c +++ b/drivers/char/mxser.c @@ -54,7 +54,6 @@ #include <linux/gfp.h> #include <linux/ioport.h> #include <linux/mm.h> -#include <linux/smp_lock.h> #include <linux/delay.h> #include <linux/pci.h> diff --git a/drivers/char/mxser_new.c b/drivers/char/mxser_new.c index f7603b6aeb87..6cde448cd5b2 100644 --- a/drivers/char/mxser_new.c +++ b/drivers/char/mxser_new.c @@ -37,7 +37,6 @@ #include <linux/gfp.h> #include <linux/ioport.h> #include <linux/mm.h> -#include <linux/smp_lock.h> #include <linux/delay.h> #include <linux/pci.h> diff --git a/drivers/char/n_r3964.c b/drivers/char/n_r3964.c index 65f2d3a96b85..14557a4822c0 100644 --- a/drivers/char/n_r3964.c +++ b/drivers/char/n_r3964.c @@ -1088,13 +1088,13 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file, /* block until there is a message: */ add_wait_queue(&pInfo->read_wait, &wait); repeat: - current->state = TASK_INTERRUPTIBLE; + __set_current_state(TASK_INTERRUPTIBLE); pMsg = remove_msg(pInfo, pClient); if (!pMsg && !signal_pending(current)) { schedule(); goto repeat; } - current->state = TASK_RUNNING; + __set_current_state(TASK_RUNNING); remove_wait_queue(&pInfo->read_wait, &wait); } diff --git a/drivers/char/pcmcia/Kconfig b/drivers/char/pcmcia/Kconfig index 27c1179ee527..f25facd97bb4 100644 --- a/drivers/char/pcmcia/Kconfig +++ b/drivers/char/pcmcia/Kconfig @@ -21,6 +21,7 @@ config SYNCLINK_CS config CARDMAN_4000 tristate "Omnikey Cardman 4000 support" depends on PCMCIA + select BITREVERSE help Enable support for the Omnikey Cardman 4000 PCMCIA Smartcard reader. diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c index e91b43a014b0..fee58e03dbe2 100644 --- a/drivers/char/pcmcia/cm4000_cs.c +++ b/drivers/char/pcmcia/cm4000_cs.c @@ -31,6 +31,7 @@ #include <linux/init.h> #include <linux/fs.h> #include <linux/delay.h> +#include <linux/bitrev.h> #include <asm/uaccess.h> #include <asm/io.h> @@ -194,41 +195,17 @@ static inline unsigned char xinb(unsigned short port) } #endif -#define b_0000 15 -#define b_0001 14 -#define b_0010 13 -#define b_0011 12 -#define b_0100 11 -#define b_0101 10 -#define b_0110 9 -#define b_0111 8 -#define b_1000 7 -#define b_1001 6 -#define b_1010 5 -#define b_1011 4 -#define b_1100 3 -#define b_1101 2 -#define b_1110 1 -#define b_1111 0 - -static unsigned char irtab[16] = { - b_0000, b_1000, b_0100, b_1100, - b_0010, b_1010, b_0110, b_1110, - b_0001, b_1001, b_0101, b_1101, - b_0011, b_1011, b_0111, b_1111 -}; +static inline unsigned char invert_revert(unsigned char ch) +{ + return bitrev8(~ch); +} static void str_invert_revert(unsigned char *b, int len) { int i; for (i = 0; i < len; i++) - b[i] = (irtab[b[i] & 0x0f] << 4) | irtab[b[i] >> 4]; -} - -static unsigned char invert_revert(unsigned char ch) -{ - return (irtab[ch & 0x0f] << 4) | irtab[ch >> 4]; + b[i] = invert_revert(b[i]); } #define ATRLENCK(dev,pos) \ @@ -1114,7 +1091,7 @@ static ssize_t cmm_write(struct file *filp, const char __user *buf, /* * wait for atr to become valid. * note: it is important to lock this code. if we dont, the monitor - * could be run between test_bit and the the call the sleep on the + * could be run between test_bit and the call to sleep on the * atr-queue. if *then* the monitor detects atr valid, it will wake up * any process on the atr-queue, *but* since we have been interrupted, * we do not yet sleep on this queue. this would result in a missed @@ -1881,8 +1858,11 @@ static int cm4000_probe(struct pcmcia_device *link) init_waitqueue_head(&dev->readq); ret = cm4000_config(link, i); - if (ret) + if (ret) { + dev_table[i] = NULL; + kfree(dev); return ret; + } class_device_create(cmm_class, NULL, MKDEV(major, i), NULL, "cmm%d", i); @@ -1907,7 +1887,7 @@ static void cm4000_detach(struct pcmcia_device *link) cm4000_release(link); dev_table[devno] = NULL; - kfree(dev); + kfree(dev); class_device_destroy(cmm_class, MKDEV(major, devno)); @@ -1956,12 +1936,14 @@ static int __init cmm_init(void) if (major < 0) { printk(KERN_WARNING MODULE_NAME ": could not get major number\n"); + class_destroy(cmm_class); return major; } rc = pcmcia_register_driver(&cm4000_driver); if (rc < 0) { unregister_chrdev(major, DEVICE_NAME); + class_destroy(cmm_class); return rc; } diff --git a/drivers/char/pcmcia/cm4040_cs.c b/drivers/char/pcmcia/cm4040_cs.c index f2e4ec4fd407..af88181a17f4 100644 --- a/drivers/char/pcmcia/cm4040_cs.c +++ b/drivers/char/pcmcia/cm4040_cs.c @@ -636,8 +636,11 @@ static int reader_probe(struct pcmcia_device *link) setup_timer(&dev->poll_timer, cm4040_do_poll, 0); ret = reader_config(link, i); - if (ret) + if (ret) { + dev_table[i] = NULL; + kfree(dev); return ret; + } class_device_create(cmx_class, NULL, MKDEV(major, i), NULL, "cmx%d", i); @@ -708,12 +711,14 @@ static int __init cm4040_init(void) if (major < 0) { printk(KERN_WARNING MODULE_NAME ": could not get major number\n"); + class_destroy(cmx_class); return major; } rc = pcmcia_register_driver(&reader_driver); if (rc < 0) { unregister_chrdev(major, DEVICE_NAME); + class_destroy(cmx_class); return rc; } diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c index 4abd1eff61d6..84ac64fc48a1 100644 --- a/drivers/char/ppdev.c +++ b/drivers/char/ppdev.c @@ -66,7 +66,6 @@ #include <linux/poll.h> #include <linux/major.h> #include <linux/ppdev.h> -#include <linux/smp_lock.h> #include <linux/device.h> #include <asm/uaccess.h> @@ -752,7 +751,7 @@ static const struct file_operations pp_fops = { static void pp_attach(struct parport *port) { - device_create(ppdev_class, NULL, MKDEV(PP_MAJOR, port->number), + device_create(ppdev_class, port->dev, MKDEV(PP_MAJOR, port->number), "parport%d", port->number); } diff --git a/drivers/char/riscom8.c b/drivers/char/riscom8.c index 70145254fb9d..3494e3fc44bf 100644 --- a/drivers/char/riscom8.c +++ b/drivers/char/riscom8.c @@ -980,7 +980,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, } schedule(); } - current->state = TASK_RUNNING; + __set_current_state(TASK_RUNNING); remove_wait_queue(&port->open_wait, &wait); if (!tty_hung_up_p(filp)) port->count++; diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c index 76357c855ce3..61a63da420c2 100644 --- a/drivers/char/rocket.c +++ b/drivers/char/rocket.c @@ -65,10 +65,6 @@ /****** Kernel includes ******/ -#ifdef MODVERSIONS -#include <config/modversions.h> -#endif - #include <linux/module.h> #include <linux/errno.h> #include <linux/major.h> @@ -85,6 +81,7 @@ #include <linux/string.h> #include <linux/fcntl.h> #include <linux/ptrace.h> +#include <linux/mutex.h> #include <linux/ioport.h> #include <linux/delay.h> #include <linux/wait.h> @@ -93,7 +90,6 @@ #include <asm/atomic.h> #include <linux/bitops.h> #include <linux/spinlock.h> -#include <asm/semaphore.h> #include <linux/init.h> /****** RocketPort includes ******/ @@ -702,7 +698,7 @@ static void init_r_port(int board, int aiop, int chan, struct pci_dev *pci_dev) } } spin_lock_init(&info->slock); - sema_init(&info->write_sem, 1); + mutex_init(&info->write_mtx); rp_table[line] = info; if (pci_dev) tty_register_device(rocket_driver, line, &pci_dev->dev); @@ -947,7 +943,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, #endif schedule(); /* Don't hold spinlock here, will hang PC */ } - current->state = TASK_RUNNING; + __set_current_state(TASK_RUNNING); remove_wait_queue(&info->open_wait, &wait); spin_lock_irqsave(&info->slock, flags); @@ -1602,7 +1598,7 @@ static void rp_wait_until_sent(struct tty_struct *tty, int timeout) if (signal_pending(current)) break; } - current->state = TASK_RUNNING; + __set_current_state(TASK_RUNNING); #ifdef ROCKET_DEBUG_WAIT_UNTIL_SENT printk(KERN_INFO "txcnt = %d (jiff=%lu)...done\n", txcnt, jiffies); #endif @@ -1661,8 +1657,11 @@ static void rp_put_char(struct tty_struct *tty, unsigned char ch) if (rocket_paranoia_check(info, "rp_put_char")) return; - /* Grab the port write semaphore, locking out other processes that try to write to this port */ - down(&info->write_sem); + /* + * Grab the port write mutex, locking out other processes that try to + * write to this port + */ + mutex_lock(&info->write_mtx); #ifdef ROCKET_DEBUG_WRITE printk(KERN_INFO "rp_put_char %c...", ch); @@ -1684,12 +1683,12 @@ static void rp_put_char(struct tty_struct *tty, unsigned char ch) info->xmit_fifo_room--; } spin_unlock_irqrestore(&info->slock, flags); - up(&info->write_sem); + mutex_unlock(&info->write_mtx); } /* * Exception handler - write routine, called when user app writes to the device. - * A per port write semaphore is used to protect from another process writing to + * A per port write mutex is used to protect from another process writing to * this port at the same time. This other process could be running on the other CPU * or get control of the CPU if the copy_from_user() blocks due to a page fault (swapped out). * Spinlocks protect the info xmit members. @@ -1706,7 +1705,7 @@ static int rp_write(struct tty_struct *tty, if (count <= 0 || rocket_paranoia_check(info, "rp_write")) return 0; - down_interruptible(&info->write_sem); + mutex_lock_interruptible(&info->write_mtx); #ifdef ROCKET_DEBUG_WRITE printk(KERN_INFO "rp_write %d chars...", count); @@ -1777,7 +1776,7 @@ end: wake_up_interruptible(&tty->poll_wait); #endif } - up(&info->write_sem); + mutex_unlock(&info->write_mtx); return retval; } @@ -1852,6 +1851,12 @@ static void rp_flush_buffer(struct tty_struct *tty) #ifdef CONFIG_PCI +static struct pci_device_id __devinitdata rocket_pci_ids[] = { + { PCI_DEVICE(PCI_VENDOR_ID_RP, PCI_ANY_ID) }, + { } +}; +MODULE_DEVICE_TABLE(pci, rocket_pci_ids); + /* * Called when a PCI card is found. Retrieves and stores model information, * init's aiopic and serial port hardware. diff --git a/drivers/char/rocket_int.h b/drivers/char/rocket_int.h index 3a8bcc85bc14..89b4d7b10d12 100644 --- a/drivers/char/rocket_int.h +++ b/drivers/char/rocket_int.h @@ -15,6 +15,8 @@ #define ROCKET_TYPE_MODEMIII 3 #define ROCKET_TYPE_PC104 4 +#include <linux/mutex.h> + #include <asm/io.h> #include <asm/byteorder.h> @@ -1171,7 +1173,7 @@ struct r_port { struct wait_queue *close_wait; #endif spinlock_t slock; - struct semaphore write_sem; + struct mutex write_mtx; }; #define RPORT_MAGIC 0x525001 diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c index c7dac9b13351..20380a2c4dee 100644 --- a/drivers/char/rtc.c +++ b/drivers/char/rtc.c @@ -388,7 +388,7 @@ static ssize_t rtc_read(struct file *file, char __user *buf, if (!retval) retval = count; out: - current->state = TASK_RUNNING; + __set_current_state(TASK_RUNNING); remove_wait_queue(&rtc_wait, &wait); return retval; diff --git a/drivers/char/selection.c b/drivers/char/selection.c index 74cff839c857..a69f094d1ed3 100644 --- a/drivers/char/selection.c +++ b/drivers/char/selection.c @@ -299,7 +299,7 @@ int paste_selection(struct tty_struct *tty) pasted += count; } remove_wait_queue(&vc->paste_wait, &wait); - current->state = TASK_RUNNING; + __set_current_state(TASK_RUNNING); tty_ldisc_deref(ld); return 0; diff --git a/drivers/char/serial167.c b/drivers/char/serial167.c index 5fd314adc1f2..c585b4738f86 100644 --- a/drivers/char/serial167.c +++ b/drivers/char/serial167.c @@ -1892,7 +1892,7 @@ block_til_ready(struct tty_struct *tty, struct file *filp, #endif schedule(); } - current->state = TASK_RUNNING; + __set_current_state(TASK_RUNNING); remove_wait_queue(&info->open_wait, &wait); if (!tty_hung_up_p(filp)) { info->count++; diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c index ce4db6f52362..f02a0795983f 100644 --- a/drivers/char/synclink.c +++ b/drivers/char/synclink.c @@ -4010,8 +4010,13 @@ static int mgsl_alloc_intermediate_txbuffer_memory(struct mgsl_struct *info) for ( i=0; i<info->num_tx_holding_buffers; ++i) { info->tx_holding_buffers[i].buffer = kmalloc(info->max_frame_size, GFP_KERNEL); - if ( info->tx_holding_buffers[i].buffer == NULL ) + if (info->tx_holding_buffers[i].buffer == NULL) { + for (--i; i >= 0; i--) { + kfree(info->tx_holding_buffers[i].buffer); + info->tx_holding_buffers[i].buffer = NULL; + } return -ENOMEM; + } } return 0; diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c index 0a367cd4121f..2a7736b5f2f7 100644 --- a/drivers/char/synclink_gt.c +++ b/drivers/char/synclink_gt.c @@ -3415,6 +3415,9 @@ static void device_init(int adapter_num, struct pci_dev *pdev) } } } + + for (i=0; i < port_count; ++i) + tty_register_device(serial_driver, port_array[i]->line, &(port_array[i]->pdev->dev)); } static int __devinit init_one(struct pci_dev *dev, @@ -3466,6 +3469,8 @@ static void slgt_cleanup(void) printk("unload %s %s\n", driver_name, driver_version); if (serial_driver) { + for (info=slgt_device_list ; info != NULL ; info=info->next_device) + tty_unregister_device(serial_driver, info->line); if ((rc = tty_unregister_driver(serial_driver))) DBGERR(("tty_unregister_driver error=%d\n", rc)); put_tty_driver(serial_driver); @@ -3506,23 +3511,10 @@ static int __init slgt_init(void) printk("%s %s\n", driver_name, driver_version); - slgt_device_count = 0; - if ((rc = pci_register_driver(&pci_driver)) < 0) { - printk("%s pci_register_driver error=%d\n", driver_name, rc); - return rc; - } - pci_registered = 1; - - if (!slgt_device_list) { - printk("%s no devices found\n",driver_name); - pci_unregister_driver(&pci_driver); - return -ENODEV; - } - serial_driver = alloc_tty_driver(MAX_DEVICES); if (!serial_driver) { - rc = -ENOMEM; - goto error; + printk("%s can't allocate tty driver\n", driver_name); + return -ENOMEM; } /* Initialize the tty_driver structure */ @@ -3539,7 +3531,7 @@ static int __init slgt_init(void) B9600 | CS8 | CREAD | HUPCL | CLOCAL; serial_driver->init_termios.c_ispeed = 9600; serial_driver->init_termios.c_ospeed = 9600; - serial_driver->flags = TTY_DRIVER_REAL_RAW; + serial_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; tty_set_operations(serial_driver, &ops); if ((rc = tty_register_driver(serial_driver)) < 0) { DBGERR(("%s can't register serial driver\n", driver_name)); @@ -3552,6 +3544,16 @@ static int __init slgt_init(void) driver_name, driver_version, serial_driver->major); + slgt_device_count = 0; + if ((rc = pci_register_driver(&pci_driver)) < 0) { + printk("%s pci_register_driver error=%d\n", driver_name, rc); + goto error; + } + pci_registered = 1; + + if (!slgt_device_list) + printk("%s no devices found\n",driver_name); + return 0; error: diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c index 1d8c4ae61551..39cc318011ea 100644 --- a/drivers/char/sysrq.c +++ b/drivers/char/sysrq.c @@ -24,7 +24,6 @@ #include <linux/sysrq.h> #include <linux/kbd_kern.h> #include <linux/quotaops.h> -#include <linux/smp_lock.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/suspend.h> diff --git a/drivers/char/tipar.c b/drivers/char/tipar.c index 47fb20f69695..35b40b996534 100644 --- a/drivers/char/tipar.c +++ b/drivers/char/tipar.c @@ -442,7 +442,7 @@ tipar_register(int nr, struct parport *port) } class_device_create(tipar_class, NULL, MKDEV(TIPAR_MAJOR, - TIPAR_MINOR + nr), NULL, "par%d", nr); + TIPAR_MINOR + nr), port->dev, "par%d", nr); /* Display informations */ pr_info("tipar%d: using %s (%s)\n", nr, port->name, (port->irq == diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig index fe00c7dfb649..11089be0691b 100644 --- a/drivers/char/tpm/Kconfig +++ b/drivers/char/tpm/Kconfig @@ -33,7 +33,7 @@ config TCG_NSC tristate "National Semiconductor TPM Interface" depends on TCG_TPM && PNPACPI ---help--- - If you have a TPM security chip from National Semicondutor + If you have a TPM security chip from National Semiconductor say Yes and it will be accessible from within Linux. To compile this driver as a module, choose M here; the module will be called tpm_nsc. diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index e5a254a434f8..9bb542913b86 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c @@ -24,7 +24,9 @@ */ #include <linux/poll.h> +#include <linux/mutex.h> #include <linux/spinlock.h> + #include "tpm.h" enum tpm_const { @@ -328,10 +330,10 @@ static void timeout_work(struct work_struct *work) { struct tpm_chip *chip = container_of(work, struct tpm_chip, work); - down(&chip->buffer_mutex); + mutex_lock(&chip->buffer_mutex); atomic_set(&chip->data_pending, 0); memset(chip->data_buffer, 0, TPM_BUFSIZE); - up(&chip->buffer_mutex); + mutex_unlock(&chip->buffer_mutex); } /* @@ -380,7 +382,7 @@ static ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf, return -E2BIG; } - down(&chip->tpm_mutex); + mutex_lock(&chip->tpm_mutex); if ((rc = chip->vendor.send(chip, (u8 *) buf, count)) < 0) { dev_err(chip->dev, @@ -419,7 +421,7 @@ out_recv: dev_err(chip->dev, "tpm_transmit: tpm_recv: error %zd\n", rc); out: - up(&chip->tpm_mutex); + mutex_unlock(&chip->tpm_mutex); return rc; } @@ -942,12 +944,12 @@ int tpm_release(struct inode *inode, struct file *file) { struct tpm_chip *chip = file->private_data; + flush_scheduled_work(); spin_lock(&driver_lock); file->private_data = NULL; - chip->num_opens--; del_singleshot_timer_sync(&chip->user_read_timer); - flush_scheduled_work(); atomic_set(&chip->data_pending, 0); + chip->num_opens--; put_device(chip->dev); kfree(chip->data_buffer); spin_unlock(&driver_lock); @@ -966,14 +968,14 @@ ssize_t tpm_write(struct file *file, const char __user *buf, while (atomic_read(&chip->data_pending) != 0) msleep(TPM_TIMEOUT); - down(&chip->buffer_mutex); + mutex_lock(&chip->buffer_mutex); if (in_size > TPM_BUFSIZE) in_size = TPM_BUFSIZE; if (copy_from_user (chip->data_buffer, (void __user *) buf, in_size)) { - up(&chip->buffer_mutex); + mutex_unlock(&chip->buffer_mutex); return -EFAULT; } @@ -981,7 +983,7 @@ ssize_t tpm_write(struct file *file, const char __user *buf, out_size = tpm_transmit(chip, chip->data_buffer, TPM_BUFSIZE); atomic_set(&chip->data_pending, out_size); - up(&chip->buffer_mutex); + mutex_unlock(&chip->buffer_mutex); /* Set a timeout by which the reader must come claim the result */ mod_timer(&chip->user_read_timer, jiffies + (60 * HZ)); @@ -1004,10 +1006,10 @@ ssize_t tpm_read(struct file *file, char __user *buf, if (size < ret_size) ret_size = size; - down(&chip->buffer_mutex); + mutex_lock(&chip->buffer_mutex); if (copy_to_user(buf, chip->data_buffer, ret_size)) ret_size = -EFAULT; - up(&chip->buffer_mutex); + mutex_unlock(&chip->buffer_mutex); } return ret_size; @@ -1097,11 +1099,16 @@ struct tpm_chip *tpm_register_hardware(struct device *dev, const struct tpm_vend /* Driver specific per-device data */ chip = kzalloc(sizeof(*chip), GFP_KERNEL); - if (chip == NULL) + devname = kmalloc(DEVNAME_SIZE, GFP_KERNEL); + + if (chip == NULL || devname == NULL) { + kfree(chip); + kfree(devname); return NULL; + } - init_MUTEX(&chip->buffer_mutex); - init_MUTEX(&chip->tpm_mutex); + mutex_init(&chip->buffer_mutex); + mutex_init(&chip->tpm_mutex); INIT_LIST_HEAD(&chip->list); INIT_WORK(&chip->work, timeout_work); @@ -1124,7 +1131,6 @@ struct tpm_chip *tpm_register_hardware(struct device *dev, const struct tpm_vend set_bit(chip->dev_num, dev_mask); - devname = kmalloc(DEVNAME_SIZE, GFP_KERNEL); scnprintf(devname, DEVNAME_SIZE, "%s%d", "tpm", chip->dev_num); chip->vendor.miscdev.name = devname; diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index 9f273f032b0f..b2e2b002a1bb 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h @@ -21,6 +21,7 @@ #include <linux/module.h> #include <linux/delay.h> #include <linux/fs.h> +#include <linux/mutex.h> #include <linux/sched.h> #include <linux/miscdevice.h> #include <linux/platform_device.h> @@ -94,11 +95,11 @@ struct tpm_chip { /* Data passed to and from the tpm via the read/write calls */ u8 *data_buffer; atomic_t data_pending; - struct semaphore buffer_mutex; + struct mutex buffer_mutex; struct timer_list user_read_timer; /* user needs to claim result */ struct work_struct work; - struct semaphore tpm_mutex; /* tpm is processing */ + struct mutex tpm_mutex; /* tpm is processing */ struct tpm_vendor_specific vendor; diff --git a/drivers/char/tpm/tpm_atmel.h b/drivers/char/tpm/tpm_atmel.h index 3c852009196e..c912d8691cbd 100644 --- a/drivers/char/tpm/tpm_atmel.h +++ b/drivers/char/tpm/tpm_atmel.h @@ -47,12 +47,12 @@ static void __iomem * atmel_get_base_addr(unsigned long *base, int *region_size) if (!dn) return NULL; - if (!device_is_compatible(dn, "AT97SC3201")) { + if (!of_device_is_compatible(dn, "AT97SC3201")) { of_node_put(dn); return NULL; } - reg = get_property(dn, "reg", ®len); + reg = of_get_property(dn, "reg", ®len); naddrc = of_n_addr_cells(dn); nsizec = of_n_size_cells(dn); diff --git a/drivers/char/tpm/tpm_infineon.c b/drivers/char/tpm/tpm_infineon.c index 1353b5a6bae8..967002a5a1e5 100644 --- a/drivers/char/tpm/tpm_infineon.c +++ b/drivers/char/tpm/tpm_infineon.c @@ -30,12 +30,60 @@ #define TPM_MAX_TRIES 5000 #define TPM_INFINEON_DEV_VEN_VALUE 0x15D1 -/* These values will be filled after PnP-call */ -static int TPM_INF_DATA; -static int TPM_INF_ADDR; -static int TPM_INF_BASE; -static int TPM_INF_ADDR_LEN; -static int TPM_INF_PORT_LEN; +#define TPM_INF_IO_PORT 0x0 +#define TPM_INF_IO_MEM 0x1 + +#define TPM_INF_ADDR 0x0 +#define TPM_INF_DATA 0x1 + +struct tpm_inf_dev { + int iotype; + + void __iomem *mem_base; /* MMIO ioremap'd addr */ + unsigned long map_base; /* phys MMIO base */ + unsigned long map_size; /* MMIO region size */ + unsigned int index_off; /* index register offset */ + + unsigned int data_regs; /* Data registers */ + unsigned int data_size; + + unsigned int config_port; /* IO Port config index reg */ + unsigned int config_size; +}; + +static struct tpm_inf_dev tpm_dev; + +static inline void tpm_data_out(unsigned char data, unsigned char offset) +{ + if (tpm_dev.iotype == TPM_INF_IO_PORT) + outb(data, tpm_dev.data_regs + offset); + else + writeb(data, tpm_dev.mem_base + tpm_dev.data_regs + offset); +} + +static inline unsigned char tpm_data_in(unsigned char offset) +{ + if (tpm_dev.iotype == TPM_INF_IO_PORT) + return inb(tpm_dev.data_regs + offset); + else + return readb(tpm_dev.mem_base + tpm_dev.data_regs + offset); +} + +static inline void tpm_config_out(unsigned char data, unsigned char offset) +{ + if (tpm_dev.iotype == TPM_INF_IO_PORT) + outb(data, tpm_dev.config_port + offset); + else + writeb(data, tpm_dev.mem_base + tpm_dev.index_off + offset); +} + +static inline unsigned char tpm_config_in(unsigned char offset) +{ + if (tpm_dev.iotype == TPM_INF_IO_PORT) + return inb(tpm_dev.config_port + offset); + else + return readb(tpm_dev.mem_base + tpm_dev.index_off + offset); +} /* TPM header definitions */ enum infineon_tpm_header { @@ -105,7 +153,7 @@ static int empty_fifo(struct tpm_chip *chip, int clear_wrfifo) if (clear_wrfifo) { for (i = 0; i < 4096; i++) { - status = inb(chip->vendor.base + WRFIFO); + status = tpm_data_in(WRFIFO); if (status == 0xff) { if (check == 5) break; @@ -125,8 +173,8 @@ static int empty_fifo(struct tpm_chip *chip, int clear_wrfifo) */ i = 0; do { - status = inb(chip->vendor.base + RDFIFO); - status = inb(chip->vendor.base + STAT); + status = tpm_data_in(RDFIFO); + status = tpm_data_in(STAT); i++; if (i == TPM_MAX_TRIES) return -EIO; @@ -139,7 +187,7 @@ static int wait(struct tpm_chip *chip, int wait_for_bit) int status; int i; for (i = 0; i < TPM_MAX_TRIES; i++) { - status = inb(chip->vendor.base + STAT); + status = tpm_data_in(STAT); /* check the status-register if wait_for_bit is set */ if (status & 1 << wait_for_bit) break; @@ -158,7 +206,7 @@ static int wait(struct tpm_chip *chip, int wait_for_bit) static void wait_and_send(struct tpm_chip *chip, u8 sendbyte) { wait(chip, STAT_XFE); - outb(sendbyte, chip->vendor.base + WRFIFO); + tpm_data_out(sendbyte, WRFIFO); } /* Note: WTX means Waiting-Time-Extension. Whenever the TPM needs more @@ -205,7 +253,7 @@ recv_begin: ret = wait(chip, STAT_RDA); if (ret) return -EIO; - buf[i] = inb(chip->vendor.base + RDFIFO); + buf[i] = tpm_data_in(RDFIFO); } if (buf[0] != TPM_VL_VER) { @@ -220,7 +268,7 @@ recv_begin: for (i = 0; i < size; i++) { wait(chip, STAT_RDA); - buf[i] = inb(chip->vendor.base + RDFIFO); + buf[i] = tpm_data_in(RDFIFO); } if ((size == 0x6D00) && (buf[1] == 0x80)) { @@ -269,7 +317,7 @@ static int tpm_inf_send(struct tpm_chip *chip, u8 * buf, size_t count) u8 count_high, count_low, count_4, count_3, count_2, count_1; /* Disabling Reset, LP and IRQC */ - outb(RESET_LP_IRQC_DISABLE, chip->vendor.base + CMD); + tpm_data_out(RESET_LP_IRQC_DISABLE, CMD); ret = empty_fifo(chip, 1); if (ret) { @@ -320,7 +368,7 @@ static void tpm_inf_cancel(struct tpm_chip *chip) static u8 tpm_inf_status(struct tpm_chip *chip) { - return inb(chip->vendor.base + STAT); + return tpm_data_in(STAT); } static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL); @@ -381,51 +429,88 @@ static int __devinit tpm_inf_pnp_probe(struct pnp_dev *dev, /* read IO-ports through PnP */ if (pnp_port_valid(dev, 0) && pnp_port_valid(dev, 1) && !(pnp_port_flags(dev, 0) & IORESOURCE_DISABLED)) { - TPM_INF_ADDR = pnp_port_start(dev, 0); - TPM_INF_ADDR_LEN = pnp_port_len(dev, 0); - TPM_INF_DATA = (TPM_INF_ADDR + 1); - TPM_INF_BASE = pnp_port_start(dev, 1); - TPM_INF_PORT_LEN = pnp_port_len(dev, 1); - if ((TPM_INF_PORT_LEN < 4) || (TPM_INF_ADDR_LEN < 2)) { + + tpm_dev.iotype = TPM_INF_IO_PORT; + + tpm_dev.config_port = pnp_port_start(dev, 0); + tpm_dev.config_size = pnp_port_len(dev, 0); + tpm_dev.data_regs = pnp_port_start(dev, 1); + tpm_dev.data_size = pnp_port_len(dev, 1); + if ((tpm_dev.data_size < 4) || (tpm_dev.config_size < 2)) { rc = -EINVAL; goto err_last; } dev_info(&dev->dev, "Found %s with ID %s\n", dev->name, dev_id->id); - if (!((TPM_INF_BASE >> 8) & 0xff)) { + if (!((tpm_dev.data_regs >> 8) & 0xff)) { rc = -EINVAL; goto err_last; } /* publish my base address and request region */ - if (request_region - (TPM_INF_BASE, TPM_INF_PORT_LEN, "tpm_infineon0") == NULL) { + if (request_region(tpm_dev.data_regs, tpm_dev.data_size, + "tpm_infineon0") == NULL) { rc = -EINVAL; goto err_last; } - if (request_region - (TPM_INF_ADDR, TPM_INF_ADDR_LEN, "tpm_infineon0") == NULL) { + if (request_region(tpm_dev.config_port, tpm_dev.config_size, + "tpm_infineon0") == NULL) { + release_region(tpm_dev.data_regs, tpm_dev.data_size); rc = -EINVAL; goto err_last; } + } else if (pnp_mem_valid(dev, 0) && + !(pnp_mem_flags(dev, 0) & IORESOURCE_DISABLED)) { + + tpm_dev.iotype = TPM_INF_IO_MEM; + + tpm_dev.map_base = pnp_mem_start(dev, 0); + tpm_dev.map_size = pnp_mem_len(dev, 0); + + dev_info(&dev->dev, "Found %s with ID %s\n", + dev->name, dev_id->id); + + /* publish my base address and request region */ + if (request_mem_region(tpm_dev.map_base, tpm_dev.map_size, + "tpm_infineon0") == NULL) { + rc = -EINVAL; + goto err_last; + } + + tpm_dev.mem_base = ioremap(tpm_dev.map_base, tpm_dev.map_size); + if (tpm_dev.mem_base == NULL) { + release_mem_region(tpm_dev.map_base, tpm_dev.map_size); + rc = -EINVAL; + goto err_last; + } + + /* + * The only known MMIO based Infineon TPM system provides + * a single large mem region with the device config + * registers at the default TPM_ADDR. The data registers + * seem like they could be placed anywhere within the MMIO + * region, but lets just put them at zero offset. + */ + tpm_dev.index_off = TPM_ADDR; + tpm_dev.data_regs = 0x0; } else { rc = -EINVAL; goto err_last; } /* query chip for its vendor, its version number a.s.o. */ - outb(ENABLE_REGISTER_PAIR, TPM_INF_ADDR); - outb(IDVENL, TPM_INF_ADDR); - vendorid[1] = inb(TPM_INF_DATA); - outb(IDVENH, TPM_INF_ADDR); - vendorid[0] = inb(TPM_INF_DATA); - outb(IDPDL, TPM_INF_ADDR); - productid[1] = inb(TPM_INF_DATA); - outb(IDPDH, TPM_INF_ADDR); - productid[0] = inb(TPM_INF_DATA); - outb(CHIP_ID1, TPM_INF_ADDR); - version[1] = inb(TPM_INF_DATA); - outb(CHIP_ID2, TPM_INF_ADDR); - version[0] = inb(TPM_INF_DATA); + tpm_config_out(ENABLE_REGISTER_PAIR, TPM_INF_ADDR); + tpm_config_out(IDVENL, TPM_INF_ADDR); + vendorid[1] = tpm_config_in(TPM_INF_DATA); + tpm_config_out(IDVENH, TPM_INF_ADDR); + vendorid[0] = tpm_config_in(TPM_INF_DATA); + tpm_config_out(IDPDL, TPM_INF_ADDR); + productid[1] = tpm_config_in(TPM_INF_DATA); + tpm_config_out(IDPDH, TPM_INF_ADDR); + productid[0] = tpm_config_in(TPM_INF_DATA); + tpm_config_out(CHIP_ID1, TPM_INF_ADDR); + version[1] = tpm_config_in(TPM_INF_DATA); + tpm_config_out(CHIP_ID2, TPM_INF_ADDR); + version[0] = tpm_config_in(TPM_INF_DATA); switch ((productid[0] << 8) | productid[1]) { case 6: @@ -442,51 +527,54 @@ static int __devinit tpm_inf_pnp_probe(struct pnp_dev *dev, if ((vendorid[0] << 8 | vendorid[1]) == (TPM_INFINEON_DEV_VEN_VALUE)) { /* configure TPM with IO-ports */ - outb(IOLIMH, TPM_INF_ADDR); - outb(((TPM_INF_BASE >> 8) & 0xff), TPM_INF_DATA); - outb(IOLIML, TPM_INF_ADDR); - outb((TPM_INF_BASE & 0xff), TPM_INF_DATA); + tpm_config_out(IOLIMH, TPM_INF_ADDR); + tpm_config_out((tpm_dev.data_regs >> 8) & 0xff, TPM_INF_DATA); + tpm_config_out(IOLIML, TPM_INF_ADDR); + tpm_config_out((tpm_dev.data_regs & 0xff), TPM_INF_DATA); /* control if IO-ports are set correctly */ - outb(IOLIMH, TPM_INF_ADDR); - ioh = inb(TPM_INF_DATA); - outb(IOLIML, TPM_INF_ADDR); - iol = inb(TPM_INF_DATA); + tpm_config_out(IOLIMH, TPM_INF_ADDR); + ioh = tpm_config_in(TPM_INF_DATA); + tpm_config_out(IOLIML, TPM_INF_ADDR); + iol = tpm_config_in(TPM_INF_DATA); - if ((ioh << 8 | iol) != TPM_INF_BASE) { + if ((ioh << 8 | iol) != tpm_dev.data_regs) { dev_err(&dev->dev, - "Could not set IO-ports to 0x%x\n", - TPM_INF_BASE); + "Could not set IO-data registers to 0x%x\n", + tpm_dev.data_regs); rc = -EIO; goto err_release_region; } /* activate register */ - outb(TPM_DAR, TPM_INF_ADDR); - outb(0x01, TPM_INF_DATA); - outb(DISABLE_REGISTER_PAIR, TPM_INF_ADDR); + tpm_config_out(TPM_DAR, TPM_INF_ADDR); + tpm_config_out(0x01, TPM_INF_DATA); + tpm_config_out(DISABLE_REGISTER_PAIR, TPM_INF_ADDR); /* disable RESET, LP and IRQC */ - outb(RESET_LP_IRQC_DISABLE, TPM_INF_BASE + CMD); + tpm_data_out(RESET_LP_IRQC_DISABLE, CMD); /* Finally, we're done, print some infos */ dev_info(&dev->dev, "TPM found: " - "config base 0x%x, " - "io base 0x%x, " + "config base 0x%lx, " + "data base 0x%lx, " "chip version 0x%02x%02x, " "vendor id 0x%x%x (Infineon), " "product id 0x%02x%02x" "%s\n", - TPM_INF_ADDR, - TPM_INF_BASE, + tpm_dev.iotype == TPM_INF_IO_PORT ? + tpm_dev.config_port : + tpm_dev.map_base + tpm_dev.index_off, + tpm_dev.iotype == TPM_INF_IO_PORT ? + tpm_dev.data_regs : + tpm_dev.map_base + tpm_dev.data_regs, version[0], version[1], vendorid[0], vendorid[1], productid[0], productid[1], chipname); - if (!(chip = tpm_register_hardware(&dev->dev, &tpm_inf))) { + if (!(chip = tpm_register_hardware(&dev->dev, &tpm_inf))) goto err_release_region; - } - chip->vendor.base = TPM_INF_BASE; + return 0; } else { rc = -ENODEV; @@ -494,8 +582,13 @@ static int __devinit tpm_inf_pnp_probe(struct pnp_dev *dev, } err_release_region: - release_region(TPM_INF_BASE, TPM_INF_PORT_LEN); - release_region(TPM_INF_ADDR, TPM_INF_ADDR_LEN); + if (tpm_dev.iotype == TPM_INF_IO_PORT) { + release_region(tpm_dev.data_regs, tpm_dev.data_size); + release_region(tpm_dev.config_port, tpm_dev.config_size); + } else { + iounmap(tpm_dev.mem_base); + release_mem_region(tpm_dev.map_base, tpm_dev.map_size); + } err_last: return rc; @@ -506,8 +599,14 @@ static __devexit void tpm_inf_pnp_remove(struct pnp_dev *dev) struct tpm_chip *chip = pnp_get_drvdata(dev); if (chip) { - release_region(TPM_INF_BASE, TPM_INF_PORT_LEN); - release_region(TPM_INF_ADDR, TPM_INF_ADDR_LEN); + if (tpm_dev.iotype == TPM_INF_IO_PORT) { + release_region(tpm_dev.data_regs, tpm_dev.data_size); + release_region(tpm_dev.config_port, + tpm_dev.config_size); + } else { + iounmap(tpm_dev.mem_base); + release_mem_region(tpm_dev.map_base, tpm_dev.map_size); + } tpm_remove_hardware(chip->dev); } } @@ -539,5 +638,5 @@ module_exit(cleanup_inf); MODULE_AUTHOR("Marcel Selhorst <selhorst@crypto.rub.de>"); MODULE_DESCRIPTION("Driver for Infineon TPM SLD 9630 TT 1.1 / SLB 9635 TT 1.2"); -MODULE_VERSION("1.8"); +MODULE_VERSION("1.9"); MODULE_LICENSE("GPL"); diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 389da364e6b6..fc662e4ce58a 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -141,8 +141,6 @@ static DECLARE_MUTEX(allocated_ptys_lock); static int ptmx_open(struct inode *, struct file *); #endif -extern void disable_early_printk(void); - static void initialize_tty_struct(struct tty_struct *tty); static ssize_t tty_read(struct file *, char __user *, size_t, loff_t *); @@ -155,8 +153,8 @@ int tty_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg); static int tty_fasync(int fd, struct file * filp, int on); static void release_tty(struct tty_struct *tty, int idx); -static struct pid *__proc_set_tty(struct task_struct *tsk, - struct tty_struct *tty); +static void __proc_set_tty(struct task_struct *tsk, struct tty_struct *tty); +static void proc_set_tty(struct task_struct *tsk, struct tty_struct *tty); /** * alloc_tty_struct - allocate a tty object @@ -936,13 +934,6 @@ restart: return -EINVAL; /* - * No more input please, we are switching. The new ldisc - * will update this value in the ldisc open function - */ - - tty->receive_room = 0; - - /* * Problem: What do we do if this blocks ? */ @@ -953,6 +944,13 @@ restart: return 0; } + /* + * No more input please, we are switching. The new ldisc + * will update this value in the ldisc open function + */ + + tty->receive_room = 0; + o_ldisc = tty->ldisc; o_tty = tty->link; @@ -1534,10 +1532,9 @@ void disassociate_ctty(int on_exit) } spin_lock_irq(¤t->sighand->siglock); - tty_pgrp = current->signal->tty_old_pgrp; + put_pid(current->signal->tty_old_pgrp); current->signal->tty_old_pgrp = NULL; spin_unlock_irq(¤t->sighand->siglock); - put_pid(tty_pgrp); mutex_lock(&tty_mutex); /* It is possible that do_tty_hangup has free'd this tty */ @@ -1562,13 +1559,25 @@ void disassociate_ctty(int on_exit) unlock_kernel(); } +/** + * + * no_tty - Ensure the current process does not have a controlling tty + */ +void no_tty(void) +{ + struct task_struct *tsk = current; + if (tsk->signal->leader) + disassociate_ctty(0); + proc_clear_tty(tsk); +} + /** - * stop_tty - propogate flow control + * stop_tty - propagate flow control * @tty: tty to stop * * Perform flow control to the driver. For PTY/TTY pairs we - * must also propogate the TIOCKPKT status. May be called + * must also propagate the TIOCKPKT status. May be called * on an already stopped device and will not re-call the driver * method. * @@ -1598,11 +1607,11 @@ void stop_tty(struct tty_struct *tty) EXPORT_SYMBOL(stop_tty); /** - * start_tty - propogate flow control + * start_tty - propagate flow control * @tty: tty to start * * Start a tty that has been stopped if at all possible. Perform - * any neccessary wakeups and propogate the TIOCPKT status. If this + * any neccessary wakeups and propagate the TIOCPKT status. If this * is the tty was previous stopped and is being started then the * driver start method is invoked and the line discipline woken. * @@ -2508,7 +2517,6 @@ static int tty_open(struct inode * inode, struct file * filp) int index; dev_t device = inode->i_rdev; unsigned short saved_flags = filp->f_flags; - struct pid *old_pgrp; nonseekable_open(inode, filp); @@ -2602,17 +2610,15 @@ got_driver: goto retry_open; } - old_pgrp = NULL; mutex_lock(&tty_mutex); spin_lock_irq(¤t->sighand->siglock); if (!noctty && current->signal->leader && !current->signal->tty && tty->session == NULL) - old_pgrp = __proc_set_tty(current, tty); + __proc_set_tty(current, tty); spin_unlock_irq(¤t->sighand->siglock); mutex_unlock(&tty_mutex); - put_pid(old_pgrp); return 0; } @@ -3287,9 +3293,7 @@ int tty_ioctl(struct inode * inode, struct file * file, case TIOCNOTTY: if (current->signal->tty != tty) return -ENOTTY; - if (current->signal->leader) - disassociate_ctty(0); - proc_clear_tty(current); + no_tty(); return 0; case TIOCSCTTY: return tiocsctty(tty, arg); @@ -3766,7 +3770,9 @@ int tty_register_driver(struct tty_driver *driver) if (!driver->put_char) driver->put_char = tty_default_put_char; + mutex_lock(&tty_mutex); list_add(&driver->tty_drivers, &tty_drivers); + mutex_unlock(&tty_mutex); if ( !(driver->flags & TTY_DRIVER_DYNAMIC_DEV) ) { for(i = 0; i < driver->num; i++) @@ -3792,8 +3798,9 @@ int tty_unregister_driver(struct tty_driver *driver) unregister_chrdev_region(MKDEV(driver->major, driver->minor_start), driver->num); - + mutex_lock(&tty_mutex); list_del(&driver->tty_drivers); + mutex_unlock(&tty_mutex); /* * Free the termios and termios_locked structures because @@ -3836,11 +3843,9 @@ void proc_clear_tty(struct task_struct *p) p->signal->tty = NULL; spin_unlock_irq(&p->sighand->siglock); } -EXPORT_SYMBOL(proc_clear_tty); -static struct pid *__proc_set_tty(struct task_struct *tsk, struct tty_struct *tty) +static void __proc_set_tty(struct task_struct *tsk, struct tty_struct *tty) { - struct pid *old_pgrp; if (tty) { /* We should not have a session or pgrp to here but.... */ put_pid(tty->session); @@ -3848,21 +3853,16 @@ static struct pid *__proc_set_tty(struct task_struct *tsk, struct tty_struct *tt tty->session = get_pid(task_session(tsk)); tty->pgrp = get_pid(task_pgrp(tsk)); } - old_pgrp = tsk->signal->tty_old_pgrp; + put_pid(tsk->signal->tty_old_pgrp); tsk->signal->tty = tty; tsk->signal->tty_old_pgrp = NULL; - return old_pgrp; } -void proc_set_tty(struct task_struct *tsk, struct tty_struct *tty) +static void proc_set_tty(struct task_struct *tsk, struct tty_struct *tty) { - struct pid *old_pgrp; - spin_lock_irq(&tsk->sighand->siglock); - old_pgrp = __proc_set_tty(tsk, tty); + __proc_set_tty(tsk, tty); spin_unlock_irq(&tsk->sighand->siglock); - - put_pid(old_pgrp); } struct tty_struct *get_current_tty(void) @@ -3897,9 +3897,6 @@ void __init console_init(void) * set up the console device so that later boot sequences can * inform about problems etc.. */ -#ifdef CONFIG_EARLY_PRINTK - disable_early_printk(); -#endif call = __con_initcall_start; while (call < __con_initcall_end) { (*call)(); diff --git a/drivers/char/vc_screen.c b/drivers/char/vc_screen.c index 791930320a13..83aeedda200c 100644 --- a/drivers/char/vc_screen.c +++ b/drivers/char/vc_screen.c @@ -28,12 +28,13 @@ #include <linux/interrupt.h> #include <linux/mm.h> #include <linux/init.h> +#include <linux/mutex.h> #include <linux/vt_kern.h> #include <linux/selection.h> #include <linux/kbd_kern.h> #include <linux/console.h> -#include <linux/smp_lock.h> #include <linux/device.h> + #include <asm/uaccess.h> #include <asm/byteorder.h> #include <asm/unaligned.h> @@ -70,11 +71,11 @@ static loff_t vcs_lseek(struct file *file, loff_t offset, int orig) { int size; - down(&con_buf_sem); + mutex_lock(&con_buf_mtx); size = vcs_size(file->f_path.dentry->d_inode); switch (orig) { default: - up(&con_buf_sem); + mutex_unlock(&con_buf_mtx); return -EINVAL; case 2: offset += size; @@ -85,11 +86,11 @@ static loff_t vcs_lseek(struct file *file, loff_t offset, int orig) break; } if (offset < 0 || offset > size) { - up(&con_buf_sem); + mutex_unlock(&con_buf_mtx); return -EINVAL; } file->f_pos = offset; - up(&con_buf_sem); + mutex_unlock(&con_buf_mtx); return file->f_pos; } @@ -106,7 +107,7 @@ vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) unsigned short *org = NULL; ssize_t ret; - down(&con_buf_sem); + mutex_lock(&con_buf_mtx); pos = *ppos; @@ -263,7 +264,7 @@ vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) ret = read; unlock_out: release_console_sem(); - up(&con_buf_sem); + mutex_unlock(&con_buf_mtx); return ret; } @@ -280,7 +281,7 @@ vcs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) u16 *org0 = NULL, *org = NULL; size_t ret; - down(&con_buf_sem); + mutex_lock(&con_buf_mtx); pos = *ppos; @@ -450,7 +451,7 @@ vcs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) unlock_out: release_console_sem(); - up(&con_buf_sem); + mutex_unlock(&con_buf_mtx); return ret; } diff --git a/drivers/char/vt.c b/drivers/char/vt.c index 1bbb45b937fd..bbd9fc412877 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c @@ -86,6 +86,7 @@ #include <linux/mm.h> #include <linux/console.h> #include <linux/init.h> +#include <linux/mutex.h> #include <linux/vt_kern.h> #include <linux/selection.h> #include <linux/tiocl.h> @@ -157,6 +158,8 @@ static void blank_screen_t(unsigned long dummy); static void set_palette(struct vc_data *vc); static int printable; /* Is console ready for printing? */ +static int default_utf8; +module_param(default_utf8, int, S_IRUGO | S_IWUSR); /* * ignore_poke: don't unblank the screen when things are typed. This is @@ -348,10 +351,12 @@ void update_region(struct vc_data *vc, unsigned long start, int count) /* Structure of attributes is hardware-dependent */ -static u8 build_attr(struct vc_data *vc, u8 _color, u8 _intensity, u8 _blink, u8 _underline, u8 _reverse) +static u8 build_attr(struct vc_data *vc, u8 _color, u8 _intensity, u8 _blink, + u8 _underline, u8 _reverse, u8 _italic) { if (vc->vc_sw->con_build_attr) - return vc->vc_sw->con_build_attr(vc, _color, _intensity, _blink, _underline, _reverse); + return vc->vc_sw->con_build_attr(vc, _color, _intensity, + _blink, _underline, _reverse, _italic); #ifndef VT_BUF_VRAM_ONLY /* @@ -368,10 +373,13 @@ static u8 build_attr(struct vc_data *vc, u8 _color, u8 _intensity, u8 _blink, u8 u8 a = vc->vc_color; if (!vc->vc_can_do_color) return _intensity | + (_italic ? 2 : 0) | (_underline ? 4 : 0) | (_reverse ? 8 : 0) | (_blink ? 0x80 : 0); - if (_underline) + if (_italic) + a = (a & 0xF0) | vc->vc_itcolor; + else if (_underline) a = (a & 0xf0) | vc->vc_ulcolor; else if (_intensity == 0) a = (a & 0xf0) | vc->vc_ulcolor; @@ -392,8 +400,10 @@ static u8 build_attr(struct vc_data *vc, u8 _color, u8 _intensity, u8 _blink, u8 static void update_attr(struct vc_data *vc) { - vc->vc_attr = build_attr(vc, vc->vc_color, vc->vc_intensity, vc->vc_blink, vc->vc_underline, vc->vc_reverse ^ vc->vc_decscnm); - vc->vc_video_erase_char = (build_attr(vc, vc->vc_color, 1, vc->vc_blink, 0, vc->vc_decscnm) << 8) | ' '; + vc->vc_attr = build_attr(vc, vc->vc_color, vc->vc_intensity, + vc->vc_blink, vc->vc_underline, + vc->vc_reverse ^ vc->vc_decscnm, vc->vc_italic); + vc->vc_video_erase_char = (build_attr(vc, vc->vc_color, 1, vc->vc_blink, 0, vc->vc_decscnm, 0) << 8) | ' '; } /* Note: inverting the screen twice should revert to the original state */ @@ -934,6 +944,10 @@ int default_grn[] = {0x00,0x00,0xaa,0x55,0x00,0x00,0xaa,0xaa, int default_blu[] = {0x00,0x00,0x00,0x00,0xaa,0xaa,0xaa,0xaa, 0x55,0x55,0x55,0x55,0xff,0xff,0xff,0xff}; +module_param_array(default_red, int, NULL, S_IRUGO | S_IWUSR); +module_param_array(default_grn, int, NULL, S_IRUGO | S_IWUSR); +module_param_array(default_blu, int, NULL, S_IRUGO | S_IWUSR); + /* * gotoxy() must verify all boundaries, because the arguments * might also be negative. If the given position is out of @@ -1132,6 +1146,7 @@ static void csi_X(struct vc_data *vc, int vpar) /* erase the following vpar posi static void default_attr(struct vc_data *vc) { vc->vc_intensity = 1; + vc->vc_italic = 0; vc->vc_underline = 0; vc->vc_reverse = 0; vc->vc_blink = 0; @@ -1154,6 +1169,9 @@ static void csi_m(struct vc_data *vc) case 2: vc->vc_intensity = 0; break; + case 3: + vc->vc_italic = 1; + break; case 4: vc->vc_underline = 1; break; @@ -1194,6 +1212,9 @@ static void csi_m(struct vc_data *vc) case 22: vc->vc_intensity = 1; break; + case 23: + vc->vc_italic = 0; + break; case 24: vc->vc_underline = 0; break; @@ -1454,6 +1475,7 @@ static void save_cur(struct vc_data *vc) vc->vc_saved_x = vc->vc_x; vc->vc_saved_y = vc->vc_y; vc->vc_s_intensity = vc->vc_intensity; + vc->vc_s_italic = vc->vc_italic; vc->vc_s_underline = vc->vc_underline; vc->vc_s_blink = vc->vc_blink; vc->vc_s_reverse = vc->vc_reverse; @@ -1468,6 +1490,7 @@ static void restore_cur(struct vc_data *vc) { gotoxy(vc, vc->vc_saved_x, vc->vc_saved_y); vc->vc_intensity = vc->vc_s_intensity; + vc->vc_italic = vc->vc_s_italic; vc->vc_underline = vc->vc_s_underline; vc->vc_blink = vc->vc_s_blink; vc->vc_reverse = vc->vc_s_reverse; @@ -1497,7 +1520,7 @@ static void reset_terminal(struct vc_data *vc, int do_clear) vc->vc_charset = 0; vc->vc_need_wrap = 0; vc->vc_report_mouse = 0; - vc->vc_utf = 0; + vc->vc_utf = default_utf8; vc->vc_utf_count = 0; vc->vc_disp_ctrl = 0; @@ -1930,7 +1953,47 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c) * kernel memory allocation is available. */ char con_buf[CON_BUF_SIZE]; -DECLARE_MUTEX(con_buf_sem); +DEFINE_MUTEX(con_buf_mtx); + +/* is_double_width() is based on the wcwidth() implementation by + * Markus Kuhn -- 2003-05-20 (Unicode 4.0) + * Latest version: http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c + */ +struct interval { + uint32_t first; + uint32_t last; +}; + +static int bisearch(uint32_t ucs, const struct interval *table, int max) +{ + int min = 0; + int mid; + + if (ucs < table[0].first || ucs > table[max].last) + return 0; + while (max >= min) { + mid = (min + max) / 2; + if (ucs > table[mid].last) + min = mid + 1; + else if (ucs < table[mid].first) + max = mid - 1; + else + return 1; + } + return 0; +} + +static int is_double_width(uint32_t ucs) +{ + static const struct interval double_width[] = { + { 0x1100, 0x115F }, { 0x2329, 0x232A }, { 0x2E80, 0x303E }, + { 0x3040, 0xA4CF }, { 0xAC00, 0xD7A3 }, { 0xF900, 0xFAFF }, + { 0xFE30, 0xFE6F }, { 0xFF00, 0xFF60 }, { 0xFFE0, 0xFFE6 }, + { 0x20000, 0x2FFFD }, { 0x30000, 0x3FFFD } + }; + return bisearch(ucs, double_width, + sizeof(double_width) / sizeof(*double_width) - 1); +} /* acquires console_sem */ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int count) @@ -1948,6 +2011,10 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co unsigned int currcons; unsigned long draw_from = 0, draw_to = 0; struct vc_data *vc; + unsigned char vc_attr; + uint8_t rescan; + uint8_t inverse; + uint8_t width; u16 himask, charmask; const unsigned char *orig_buf = NULL; int orig_count; @@ -1983,7 +2050,7 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co /* At this point 'buf' is guaranteed to be a kernel buffer * and therefore no access to userspace (and therefore sleeping) - * will be needed. The con_buf_sem serializes all tty based + * will be needed. The con_buf_mtx serializes all tty based * console rendering and vcs write/read operations. We hold * the console spinlock during the entire write. */ @@ -2010,53 +2077,86 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co buf++; n++; count--; + rescan = 0; + inverse = 0; + width = 1; /* Do no translation at all in control states */ if (vc->vc_state != ESnormal) { tc = c; } else if (vc->vc_utf && !vc->vc_disp_ctrl) { - /* Combine UTF-8 into Unicode */ - /* Malformed sequences as sequences of replacement glyphs */ + /* Combine UTF-8 into Unicode in vc_utf_char. + * vc_utf_count is the number of continuation bytes still + * expected to arrive. + * vc_npar is the number of continuation bytes arrived so + * far + */ rescan_last_byte: - if(c > 0x7f) { + if ((c & 0xc0) == 0x80) { + /* Continuation byte received */ + static const uint32_t utf8_length_changes[] = { 0x0000007f, 0x000007ff, 0x0000ffff, 0x001fffff, 0x03ffffff, 0x7fffffff }; if (vc->vc_utf_count) { - if ((c & 0xc0) == 0x80) { - vc->vc_utf_char = (vc->vc_utf_char << 6) | (c & 0x3f); - if (--vc->vc_utf_count) { - vc->vc_npar++; - continue; - } - tc = c = vc->vc_utf_char; - } else - goto replacement_glyph; - } else { - vc->vc_npar = 0; - if ((c & 0xe0) == 0xc0) { - vc->vc_utf_count = 1; - vc->vc_utf_char = (c & 0x1f); - } else if ((c & 0xf0) == 0xe0) { - vc->vc_utf_count = 2; - vc->vc_utf_char = (c & 0x0f); - } else if ((c & 0xf8) == 0xf0) { - vc->vc_utf_count = 3; - vc->vc_utf_char = (c & 0x07); - } else if ((c & 0xfc) == 0xf8) { - vc->vc_utf_count = 4; - vc->vc_utf_char = (c & 0x03); - } else if ((c & 0xfe) == 0xfc) { - vc->vc_utf_count = 5; - vc->vc_utf_char = (c & 0x01); - } else - goto replacement_glyph; + vc->vc_utf_char = (vc->vc_utf_char << 6) | (c & 0x3f); + vc->vc_npar++; + if (--vc->vc_utf_count) { + /* Still need some bytes */ continue; - } + } + /* Got a whole character */ + c = vc->vc_utf_char; + /* Reject overlong sequences */ + if (c <= utf8_length_changes[vc->vc_npar - 1] || + c > utf8_length_changes[vc->vc_npar]) + c = 0xfffd; + } else { + /* Unexpected continuation byte */ + vc->vc_utf_count = 0; + c = 0xfffd; + } } else { - if (vc->vc_utf_count) - goto replacement_glyph; - tc = c; + /* Single ASCII byte or first byte of a sequence received */ + if (vc->vc_utf_count) { + /* Continuation byte expected */ + rescan = 1; + vc->vc_utf_count = 0; + c = 0xfffd; + } else if (c > 0x7f) { + /* First byte of a multibyte sequence received */ + vc->vc_npar = 0; + if ((c & 0xe0) == 0xc0) { + vc->vc_utf_count = 1; + vc->vc_utf_char = (c & 0x1f); + } else if ((c & 0xf0) == 0xe0) { + vc->vc_utf_count = 2; + vc->vc_utf_char = (c & 0x0f); + } else if ((c & 0xf8) == 0xf0) { + vc->vc_utf_count = 3; + vc->vc_utf_char = (c & 0x07); + } else if ((c & 0xfc) == 0xf8) { + vc->vc_utf_count = 4; + vc->vc_utf_char = (c & 0x03); + } else if ((c & 0xfe) == 0xfc) { + vc->vc_utf_count = 5; + vc->vc_utf_char = (c & 0x01); + } else { + /* 254 and 255 are invalid */ + c = 0xfffd; + } + if (vc->vc_utf_count) { + /* Still need some bytes */ + continue; + } + } + /* Nothing to do if an ASCII byte was received */ } + /* End of UTF-8 decoding. */ + /* c is the received character, or U+FFFD for invalid sequences. */ + /* Replace invalid Unicode code points with U+FFFD too */ + if ((c >= 0xd800 && c <= 0xdfff) || c == 0xfffe || c == 0xffff) + c = 0xfffd; + tc = c; } else { /* no utf or alternate charset mode */ - tc = vc->vc_translate[vc->vc_toggle_meta ? (c | 0x80) : c]; + tc = vc->vc_translate[vc->vc_toggle_meta ? (c | 0x80) : c]; } /* If the original code was a control character we @@ -2076,56 +2176,80 @@ rescan_last_byte: && (c != 128+27); if (vc->vc_state == ESnormal && ok) { + if (vc->vc_utf && !vc->vc_disp_ctrl) { + if (is_double_width(c)) + width = 2; + } /* Now try to find out how to display it */ tc = conv_uni_to_pc(vc, tc); if (tc & ~charmask) { - if ( tc == -4 ) { - /* If we got -4 (not found) then see if we have - defined a replacement character (U+FFFD) */ -replacement_glyph: - tc = conv_uni_to_pc(vc, 0xfffd); - if (!(tc & ~charmask)) - goto display_glyph; - } else if ( tc != -3 ) - continue; /* nothing to display */ - /* no hash table or no replacement -- - * hope for the best */ - if ( c & ~charmask ) - tc = '?'; - else - tc = c; + if (tc == -1 || tc == -2) { + continue; /* nothing to display */ + } + /* Glyph not found */ + if (!(vc->vc_utf && !vc->vc_disp_ctrl) && !(c & ~charmask)) { + /* In legacy mode use the glyph we get by a 1:1 mapping. + This would make absolutely no sense with Unicode in mind. */ + tc = c; + } else { + /* Display U+FFFD. If it's not found, display an inverse question mark. */ + tc = conv_uni_to_pc(vc, 0xfffd); + if (tc < 0) { + inverse = 1; + tc = conv_uni_to_pc(vc, '?'); + if (tc < 0) tc = '?'; + } + } } -display_glyph: - if (vc->vc_need_wrap || vc->vc_decim) - FLUSH - if (vc->vc_need_wrap) { - cr(vc); - lf(vc); - } - if (vc->vc_decim) - insert_char(vc, 1); - scr_writew(himask ? - ((vc->vc_attr << 8) & ~himask) + ((tc & 0x100) ? himask : 0) + (tc & 0xff) : - (vc->vc_attr << 8) + tc, - (u16 *) vc->vc_pos); - if (DO_UPDATE(vc) && draw_x < 0) { - draw_x = vc->vc_x; - draw_from = vc->vc_pos; - } - if (vc->vc_x == vc->vc_cols - 1) { - vc->vc_need_wrap = vc->vc_decawm; - draw_to = vc->vc_pos + 2; + if (!inverse) { + vc_attr = vc->vc_attr; } else { - vc->vc_x++; - draw_to = (vc->vc_pos += 2); + /* invert vc_attr */ + if (!vc->vc_can_do_color) { + vc_attr = (vc->vc_attr) ^ 0x08; + } else if (vc->vc_hi_font_mask == 0x100) { + vc_attr = ((vc->vc_attr) & 0x11) | (((vc->vc_attr) & 0xe0) >> 4) | (((vc->vc_attr) & 0x0e) << 4); + } else { + vc_attr = ((vc->vc_attr) & 0x88) | (((vc->vc_attr) & 0x70) >> 4) | (((vc->vc_attr) & 0x07) << 4); + } } - if (vc->vc_utf_count) { - if (vc->vc_npar) { - vc->vc_npar--; - goto display_glyph; + + while (1) { + if (vc->vc_need_wrap || vc->vc_decim) + FLUSH + if (vc->vc_need_wrap) { + cr(vc); + lf(vc); + } + if (vc->vc_decim) + insert_char(vc, 1); + scr_writew(himask ? + ((vc_attr << 8) & ~himask) + ((tc & 0x100) ? himask : 0) + (tc & 0xff) : + (vc_attr << 8) + tc, + (u16 *) vc->vc_pos); + if (DO_UPDATE(vc) && draw_x < 0) { + draw_x = vc->vc_x; + draw_from = vc->vc_pos; + } + if (vc->vc_x == vc->vc_cols - 1) { + vc->vc_need_wrap = vc->vc_decawm; + draw_to = vc->vc_pos + 2; + } else { + vc->vc_x++; + draw_to = (vc->vc_pos += 2); } - vc->vc_utf_count = 0; + + if (!--width) break; + + tc = conv_uni_to_pc(vc, ' '); /* A space is printed in the second column */ + if (tc < 0) tc = ' '; + } + + if (rescan) { + rescan = 0; + inverse = 0; + width = 1; c = orig; goto rescan_last_byte; } @@ -2581,6 +2705,11 @@ static void con_close(struct tty_struct *tty, struct file *filp) mutex_unlock(&tty_mutex); } +static int default_italic_color = 2; // green (ASCII) +static int default_underline_color = 3; // cyan (ASCII) +module_param_named(italic, default_italic_color, int, S_IRUGO | S_IWUSR); +module_param_named(underline, default_underline_color, int, S_IRUGO | S_IWUSR); + static void vc_init(struct vc_data *vc, unsigned int rows, unsigned int cols, int do_clear) { @@ -2600,7 +2729,8 @@ static void vc_init(struct vc_data *vc, unsigned int rows, vc->vc_palette[k++] = default_blu[j] ; } vc->vc_def_color = 0x07; /* white */ - vc->vc_ulcolor = 0x0f; /* bold white */ + vc->vc_ulcolor = default_underline_color; + vc->vc_itcolor = default_italic_color; vc->vc_halfcolor = 0x08; /* grey */ init_waitqueue_head(&vc->paste_wait); reset_terminal(vc, do_clear); diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c index c9f2dd620e87..c6f6f4209739 100644 --- a/drivers/char/vt_ioctl.c +++ b/drivers/char/vt_ioctl.c @@ -1061,7 +1061,7 @@ int vt_waitactive(int vt) schedule(); } remove_wait_queue(&vt_activate_queue, &wait); - current->state = TASK_RUNNING; + __set_current_state(TASK_RUNNING); return retval; } diff --git a/drivers/char/watchdog/omap_wdt.c b/drivers/char/watchdog/omap_wdt.c index 84074a697dce..b36fa8de2131 100644 --- a/drivers/char/watchdog/omap_wdt.c +++ b/drivers/char/watchdog/omap_wdt.c @@ -34,7 +34,6 @@ #include <linux/miscdevice.h> #include <linux/watchdog.h> #include <linux/reboot.h> -#include <linux/smp_lock.h> #include <linux/init.h> #include <linux/err.h> #include <linux/platform_device.h> |