diff options
Diffstat (limited to 'drivers/staging/dgap')
-rw-r--r-- | drivers/staging/dgap/dgap.c | 662 | ||||
-rw-r--r-- | drivers/staging/dgap/dgap.h | 2 |
2 files changed, 323 insertions, 341 deletions
diff --git a/drivers/staging/dgap/dgap.c b/drivers/staging/dgap/dgap.c index 170d6f3e4221..06c55cb57090 100644 --- a/drivers/staging/dgap/dgap.c +++ b/drivers/staging/dgap/dgap.c @@ -70,14 +70,14 @@ MODULE_SUPPORTED_DEVICE("dgap"); static int dgap_start(void); static void dgap_init_globals(void); -static int dgap_found_board(struct pci_dev *pdev, int id); +static struct board_t *dgap_found_board(struct pci_dev *pdev, int id, + int boardnum); static void dgap_cleanup_board(struct board_t *brd); static void dgap_poll_handler(ulong dummy); -static int dgap_init_pci(void); static int dgap_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); static void dgap_remove_one(struct pci_dev *dev); -static int dgap_probe1(struct pci_dev *pdev, int card_type); static int dgap_do_remap(struct board_t *brd); +static void dgap_release_remap(struct board_t *brd); static irqreturn_t dgap_intr(int irq, void *voidbrd); static int dgap_tty_open(struct tty_struct *tty, struct file *file); @@ -86,12 +86,12 @@ static int dgap_block_til_ready(struct tty_struct *tty, struct file *file, struct channel_t *ch); static int dgap_tty_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg); -static int dgap_tty_digigeta(struct tty_struct *tty, - struct digi_t __user *retinfo); -static int dgap_tty_digiseta(struct tty_struct *tty, - struct digi_t __user *new_info); +static int dgap_tty_digigeta(struct channel_t *ch, struct digi_t __user *retinfo); +static int dgap_tty_digiseta(struct channel_t *ch, struct board_t *bd, + struct un_t *un, struct digi_t __user *new_info); static int dgap_tty_digigetedelay(struct tty_struct *tty, int __user *retinfo); -static int dgap_tty_digisetedelay(struct tty_struct *tty, int __user *new_info); +static int dgap_tty_digisetedelay(struct channel_t *ch, struct board_t *bd, + struct un_t *un, int __user *new_info); static int dgap_tty_write_room(struct tty_struct *tty); static int dgap_tty_chars_in_buffer(struct tty_struct *tty); static void dgap_tty_start(struct tty_struct *tty); @@ -102,14 +102,14 @@ static void dgap_tty_flush_chars(struct tty_struct *tty); static void dgap_tty_flush_buffer(struct tty_struct *tty); static void dgap_tty_hangup(struct tty_struct *tty); static int dgap_wait_for_drain(struct tty_struct *tty); -static int dgap_set_modem_info(struct tty_struct *tty, unsigned int command, - unsigned int __user *value); +static int dgap_set_modem_info(struct channel_t *ch, struct board_t *bd, struct un_t *un, + unsigned int command, unsigned int __user *value); static int dgap_get_modem_info(struct channel_t *ch, unsigned int __user *value); -static int dgap_tty_digisetcustombaud(struct tty_struct *tty, - int __user *new_info); -static int dgap_tty_digigetcustombaud(struct tty_struct *tty, - int __user *retinfo); +static int dgap_tty_digisetcustombaud(struct channel_t *ch, struct board_t *bd, + struct un_t *un, int __user *new_info); +static int dgap_tty_digigetcustombaud(struct channel_t *ch, struct un_t *un, + int __user *retinfo); static int dgap_tty_tiocmget(struct tty_struct *tty); static int dgap_tty_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear); @@ -123,8 +123,10 @@ static int dgap_tty_put_char(struct tty_struct *tty, unsigned char c); static void dgap_tty_send_xchar(struct tty_struct *tty, char ch); static int dgap_tty_register(struct board_t *brd); +static void dgap_tty_unregister(struct board_t *brd); static int dgap_tty_init(struct board_t *); -static void dgap_tty_uninit(struct board_t *); +static void dgap_tty_free(struct board_t *); +static void dgap_cleanup_tty(struct board_t *); static void dgap_carrier(struct channel_t *ch); static void dgap_input(struct channel_t *ch); @@ -139,7 +141,7 @@ static void dgap_cmdb(struct channel_t *ch, u8 cmd, u8 byte1, u8 byte2, uint ncmds); static void dgap_cmdw(struct channel_t *ch, u8 cmd, u16 word, uint ncmds); static void dgap_wmove(struct channel_t *ch, char *buf, uint cnt); -static int dgap_param(struct tty_struct *tty); +static int dgap_param(struct channel_t *ch, struct board_t *bd, u32 un_type); static void dgap_parity_scan(struct channel_t *ch, unsigned char *cbuf, unsigned char *fbuf, int *len); static uint dgap_get_custom_baud(struct channel_t *ch); @@ -148,9 +150,8 @@ static void dgap_firmware_reset_port(struct channel_t *ch); /* * Function prototypes from dgap_parse.c. */ -static int dgap_gettok(char **in, struct cnode *p); +static int dgap_gettok(char **in); static char *dgap_getword(char **in); -static struct cnode *dgap_newnode(int t); static int dgap_checknode(struct cnode *p); static void dgap_err(char *s); @@ -175,7 +176,7 @@ static void dgap_remove_tty_sysfs(struct device *c); /* * Function prototypes from dgap_parse.h */ -static int dgap_parsefile(char **in, int remove); +static int dgap_parsefile(char **in); static struct cnode *dgap_find_config(int type, int bus, int slot); static uint dgap_config_get_num_prts(struct board_t *bd); static char *dgap_create_config_string(struct board_t *bd, char *string); @@ -188,15 +189,18 @@ static void dgap_do_fep_load(struct board_t *brd, const u8 *ufep, int len); #ifdef DIGI_CONCENTRATORS_SUPPORTED static void dgap_do_conc_load(struct board_t *brd, u8 *uaddr, int len); #endif -static int dgap_after_config_loaded(int board); -static int dgap_finalize_board_init(struct board_t *brd); +static int dgap_alloc_flipbuf(struct board_t *brd); +static void dgap_free_flipbuf(struct board_t *brd); +static int dgap_request_irq(struct board_t *brd); +static void dgap_free_irq(struct board_t *brd); static void dgap_get_vpd(struct board_t *brd); static void dgap_do_reset_board(struct board_t *brd); static int dgap_test_bios(struct board_t *brd); static int dgap_test_fep(struct board_t *brd); static int dgap_tty_register_ports(struct board_t *brd); -static int dgap_firmware_load(struct pci_dev *pdev, int card_type); +static int dgap_firmware_load(struct pci_dev *pdev, int card_type, + struct board_t *brd); static void dgap_cleanup_module(void); @@ -212,9 +216,7 @@ static const struct file_operations dgap_board_fops = { static uint dgap_numboards; static struct board_t *dgap_board[MAXBOARDS]; static ulong dgap_poll_counter; -static char *dgap_config_buf; static int dgap_driver_state = DRIVER_INITIALIZED; -static wait_queue_head_t dgap_dl_wait; static int dgap_poll_tick = 20; /* Poll interval - 20 ms */ static struct class *dgap_class; @@ -474,7 +476,7 @@ static int dgap_init_module(void) if (rc) return rc; - rc = dgap_init_pci(); + rc = pci_register_driver(&dgap_driver); if (rc) goto err_cleanup; @@ -558,17 +560,10 @@ failed_class: return rc; } -/* - * Register pci driver, and return how many boards we have. - */ -static int dgap_init_pci(void) -{ - return pci_register_driver(&dgap_driver); -} - static int dgap_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { int rc; + struct board_t *brd; if (dgap_numboards >= MAXBOARDS) return -EPERM; @@ -577,17 +572,57 @@ static int dgap_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) if (rc) return -EIO; - rc = dgap_probe1(pdev, ent->driver_data); + brd = dgap_found_board(pdev, ent->driver_data, dgap_numboards); + if (IS_ERR(brd)) + return PTR_ERR(brd); + + rc = dgap_firmware_load(pdev, ent->driver_data, brd); if (rc) - return rc; + goto cleanup_brd; - dgap_numboards++; - return dgap_firmware_load(pdev, ent->driver_data); -} + rc = dgap_alloc_flipbuf(brd); + if (rc) + goto cleanup_brd; -static int dgap_probe1(struct pci_dev *pdev, int card_type) -{ - return dgap_found_board(pdev, card_type); + rc = dgap_tty_register(brd); + if (rc) + goto free_flipbuf; + + rc = dgap_request_irq(brd); + if (rc) + goto unregister_tty; + + /* + * Do tty device initialization. + */ + rc = dgap_tty_init(brd); + if (rc < 0) + goto free_irq; + + rc = dgap_tty_register_ports(brd); + if (rc) + goto tty_free; + + brd->state = BOARD_READY; + brd->dpastatus = BD_RUNNING; + + dgap_board[dgap_numboards++] = brd; + + return 0; + +tty_free: + dgap_tty_free(brd); +free_irq: + dgap_free_irq(brd); +unregister_tty: + dgap_tty_unregister(brd); +free_flipbuf: + dgap_free_flipbuf(brd); +cleanup_brd: + dgap_release_remap(brd); + kfree(brd); + + return rc; } static void dgap_remove_one(struct pci_dev *dev) @@ -620,7 +655,7 @@ static void dgap_cleanup_module(void) for (i = 0; i < dgap_numboards; ++i) { dgap_remove_ports_sysfiles(dgap_board[i]); - dgap_tty_uninit(dgap_board[i]); + dgap_cleanup_tty(dgap_board[i]); dgap_cleanup_board(dgap_board[i]); } @@ -640,8 +675,7 @@ static void dgap_cleanup_board(struct board_t *brd) if (!brd || brd->magic != DGAP_BOARD_MAGIC) return; - if (brd->intr_used && brd->irq) - free_irq(brd->irq, brd); + dgap_free_irq(brd); tasklet_kill(&brd->helper_tasklet); @@ -674,23 +708,22 @@ static void dgap_cleanup_board(struct board_t *brd) * * A board has been found, init it. */ -static int dgap_found_board(struct pci_dev *pdev, int id) +static struct board_t *dgap_found_board(struct pci_dev *pdev, int id, + int boardnum) { struct board_t *brd; unsigned int pci_irq; int i; + int ret; /* get the board structure and prep it */ brd = kzalloc(sizeof(struct board_t), GFP_KERNEL); if (!brd) - return -ENOMEM; - - dgap_board[dgap_numboards] = brd; + return ERR_PTR(-ENOMEM); /* store the info for the board we've found */ brd->magic = DGAP_BOARD_MAGIC; - brd->boardnum = dgap_numboards; - brd->firstminor = 0; + brd->boardnum = boardnum; brd->vendor = dgap_pci_tbl[id].vendor; brd->device = dgap_pci_tbl[id].device; brd->pdev = pdev; @@ -734,8 +767,10 @@ static int dgap_found_board(struct pci_dev *pdev, int id) brd->membase_end = pci_resource_end(pdev, 0); } - if (!brd->membase) - return -ENODEV; + if (!brd->membase) { + ret = -ENODEV; + goto free_brd; + } if (brd->membase & 1) brd->membase &= ~3; @@ -776,18 +811,23 @@ static int dgap_found_board(struct pci_dev *pdev, int id) tasklet_init(&brd->helper_tasklet, dgap_poll_tasklet, (unsigned long) brd); - i = dgap_do_remap(brd); - if (i) - brd->state = BOARD_FAILED; + ret = dgap_do_remap(brd); + if (ret) + goto free_brd; pr_info("dgap: board %d: %s (rev %d), irq %ld\n", - dgap_numboards, brd->name, brd->rev, brd->irq); + boardnum, brd->name, brd->rev, brd->irq); - return 0; + return brd; + +free_brd: + kfree(brd); + + return ERR_PTR(ret); } -static int dgap_finalize_board_init(struct board_t *brd) +static int dgap_request_irq(struct board_t *brd) { int rc; @@ -814,17 +854,24 @@ static int dgap_finalize_board_init(struct board_t *brd) return 0; } -static int dgap_firmware_load(struct pci_dev *pdev, int card_type) +static void dgap_free_irq(struct board_t *brd) +{ + if (brd->intr_used && brd->irq) + free_irq(brd->irq, brd); +} + +static int dgap_firmware_load(struct pci_dev *pdev, int card_type, + struct board_t *brd) { - struct board_t *brd = dgap_board[dgap_numboards - 1]; const struct firmware *fw; char *tmp_ptr; int ret; + char *dgap_config_buf; dgap_get_vpd(brd); dgap_do_reset_board(brd); - if ((fw_info[card_type].conf_name) && !dgap_config_buf) { + if (fw_info[card_type].conf_name) { ret = request_firmware(&fw, fw_info[card_type].conf_name, &pdev->dev); if (ret) { @@ -849,16 +896,13 @@ static int dgap_firmware_load(struct pci_dev *pdev, int card_type) */ tmp_ptr = dgap_config_buf; - if (dgap_parsefile(&tmp_ptr, TRUE) != 0) { + if (dgap_parsefile(&tmp_ptr) != 0) { kfree(dgap_config_buf); return -EINVAL; } kfree(dgap_config_buf); } - ret = dgap_after_config_loaded(brd->boardnum); - if (ret) - return ret; /* * Match this board to a config the user created for us. */ @@ -880,14 +924,6 @@ static int dgap_firmware_load(struct pci_dev *pdev, int card_type) return -EINVAL; } - ret = dgap_tty_register(brd); - if (ret) - return ret; - - ret = dgap_finalize_board_init(brd); - if (ret) - return ret; - if (fw_info[card_type].bios_name) { ret = request_firmware(&fw, fw_info[card_type].bios_name, &pdev->dev); @@ -950,21 +986,6 @@ static int dgap_firmware_load(struct pci_dev *pdev, int card_type) release_firmware(fw); } #endif - /* - * Do tty device initialization. - */ - ret = dgap_tty_init(brd); - if (ret < 0) { - dgap_tty_uninit(brd); - return ret; - } - - ret = dgap_tty_register_ports(brd); - if (ret) - return ret; - - brd->state = BOARD_READY; - brd->dpastatus = BD_RUNNING; return 0; } @@ -1004,6 +1025,12 @@ static int dgap_do_remap(struct board_t *brd) return 0; } +static void dgap_release_remap(struct board_t *brd) +{ + release_mem_region(brd->membase, 0x200000); + release_mem_region(brd->membase + PCI_IO_OFFSET, 0x200000); + iounmap(brd->re_map_membase); +} /***************************************************************************** * * Function: @@ -1171,8 +1198,6 @@ static void dgap_init_globals(void) dgap_board[i] = NULL; init_timer(&dgap_poll_timer); - - init_waitqueue_head(&dgap_dl_wait); } /************************************************************************ @@ -1311,6 +1336,14 @@ free_serial_drv: return rc; } +static void dgap_tty_unregister(struct board_t *brd) +{ + tty_unregister_driver(brd->print_driver); + tty_unregister_driver(brd->serial_driver); + put_tty_driver(brd->print_driver); + put_tty_driver(brd->serial_driver); +} + /* * dgap_tty_init() * @@ -1327,9 +1360,7 @@ static int dgap_tty_init(struct board_t *brd) struct channel_t *ch; struct bs_t __iomem *bs; struct cm_t __iomem *cm; - - if (!brd) - return -EIO; + int ret; /* * Initialize board structure elements. @@ -1376,11 +1407,11 @@ static int dgap_tty_init(struct board_t *brd) * when the driver was first loaded. */ for (i = 0; i < brd->nasync; i++) { + brd->channels[i] = + kzalloc(sizeof(struct channel_t), GFP_KERNEL); if (!brd->channels[i]) { - brd->channels[i] = - kzalloc(sizeof(struct channel_t), GFP_KERNEL); - if (!brd->channels[i]) - return -ENOMEM; + ret = -ENOMEM; + goto free_chan; } } @@ -1395,9 +1426,6 @@ static int dgap_tty_init(struct board_t *brd) /* Set up channel variables */ for (i = 0; i < brd->nasync; i++, ch = brd->channels[i], bs++) { - if (!brd->channels[i]) - continue; - spin_lock_init(&ch->ch_lock); /* Store all our magic numbers */ @@ -1480,15 +1508,34 @@ static int dgap_tty_init(struct board_t *brd) } return 0; + +free_chan: + while (--i >= 0) { + kfree(brd->channels[i]); + brd->channels[i] = NULL; + } + return ret; } /* - * dgap_tty_uninit() + * dgap_tty_free() + * + * Free the channles which are allocated in dgap_tty_init(). + */ +static void dgap_tty_free(struct board_t *brd) +{ + int i; + + for (i = 0; i < brd->nasync; i++) + kfree(brd->channels[i]); +} +/* + * dgap_cleanup_tty() * * Uninitialize the TTY portion of this driver. Free all memory and * resources. */ -static void dgap_tty_uninit(struct board_t *brd) +static void dgap_cleanup_tty(struct board_t *brd) { struct device *dev; int i; @@ -1981,7 +2028,7 @@ static int dgap_tty_open(struct tty_struct *tty, struct file *file) /* * Run param in case we changed anything */ - dgap_param(tty); + dgap_param(ch, brd, un->un_type); /* * follow protocol for opening port @@ -2133,10 +2180,7 @@ static int dgap_block_til_ready(struct tty_struct *tty, struct file *file, spin_unlock_irqrestore(&ch->ch_lock, lock_flags); - if (retval) - return retval; - - return 0; + return retval; } /* @@ -2459,22 +2503,9 @@ static int dgap_wait_for_drain(struct tty_struct *tty) * returns the new bytes_available. This only affects printer * output. */ -static int dgap_maxcps_room(struct tty_struct *tty, int bytes_available) +static int dgap_maxcps_room(struct channel_t *ch, struct un_t *un, + int bytes_available) { - struct channel_t *ch; - struct un_t *un; - - if (!tty) - return bytes_available; - - un = tty->driver_data; - if (!un || un->magic != DGAP_UNIT_MAGIC) - return bytes_available; - - ch = un->un_ch; - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return bytes_available; - /* * If its not the Transparent print device, return * the full data amount. @@ -2576,7 +2607,7 @@ static int dgap_tty_write_room(struct tty_struct *tty) ret += ch->ch_tsize; /* Limit printer to maxcps */ - ret = dgap_maxcps_room(tty, ret); + ret = dgap_maxcps_room(ch, un, ret); /* * If we are printer device, leave space for @@ -2681,7 +2712,7 @@ static int dgap_tty_write(struct tty_struct *tty, const unsigned char *buf, * Limit printer output to maxcps overall, with bursts allowed * up to bufsize characters. */ - bufcount = dgap_maxcps_room(tty, bufcount); + bufcount = dgap_maxcps_room(ch, un, bufcount); /* * Take minimum of what the user wants to send, and the @@ -2892,7 +2923,7 @@ static int dgap_tty_tiocmset(struct tty_struct *tty, ch->ch_mval &= ~(D_DTR(ch)); } - dgap_param(tty); + dgap_param(ch, bd, un->un_type); spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); spin_unlock_irqrestore(&bd->bd_lock, lock_flags); @@ -3014,8 +3045,6 @@ static void dgap_tty_send_xchar(struct tty_struct *tty, char c) spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - - return; } /* @@ -3028,9 +3057,6 @@ static int dgap_get_modem_info(struct channel_t *ch, unsigned int __user *value) ulong lock_flags; int rc; - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return -EIO; - spin_lock_irqsave(&ch->ch_lock, lock_flags); mstat = readb(&(ch->ch_bs->m_stat)); @@ -3064,32 +3090,14 @@ static int dgap_get_modem_info(struct channel_t *ch, unsigned int __user *value) * * Set modem signals, called by ld. */ -static int dgap_set_modem_info(struct tty_struct *tty, unsigned int command, - unsigned int __user *value) +static int dgap_set_modem_info(struct channel_t *ch, struct board_t *bd, struct un_t *un, + unsigned int command, unsigned int __user *value) { - struct board_t *bd; - struct channel_t *ch; - struct un_t *un; int ret; unsigned int arg; ulong lock_flags; ulong lock_flags2; - if (!tty || tty->magic != TTY_MAGIC) - return -EIO; - - un = tty->driver_data; - if (!un || un->magic != DGAP_UNIT_MAGIC) - return -EIO; - - ch = un->un_ch; - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return -EIO; - - bd = ch->ch_bd; - if (!bd || bd->magic != DGAP_BOARD_MAGIC) - return -EIO; - ret = get_user(arg, value); if (ret) return ret; @@ -3143,7 +3151,7 @@ static int dgap_set_modem_info(struct tty_struct *tty, unsigned int command, spin_lock_irqsave(&bd->bd_lock, lock_flags); spin_lock_irqsave(&ch->ch_lock, lock_flags2); - dgap_param(tty); + dgap_param(ch, bd, un->un_type); spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); spin_unlock_irqrestore(&bd->bd_lock, lock_flags); @@ -3159,28 +3167,14 @@ static int dgap_set_modem_info(struct tty_struct *tty, unsigned int command, * * */ -static int dgap_tty_digigeta(struct tty_struct *tty, - struct digi_t __user *retinfo) +static int dgap_tty_digigeta(struct channel_t *ch, struct digi_t __user *retinfo) { - struct channel_t *ch; - struct un_t *un; struct digi_t tmp; ulong lock_flags; if (!retinfo) return -EFAULT; - if (!tty || tty->magic != TTY_MAGIC) - return -EFAULT; - - un = tty->driver_data; - if (!un || un->magic != DGAP_UNIT_MAGIC) - return -EFAULT; - - ch = un->un_ch; - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return -EFAULT; - memset(&tmp, 0, sizeof(tmp)); spin_lock_irqsave(&ch->ch_lock, lock_flags); @@ -3201,31 +3195,13 @@ static int dgap_tty_digigeta(struct tty_struct *tty, * * */ -static int dgap_tty_digiseta(struct tty_struct *tty, - struct digi_t __user *new_info) +static int dgap_tty_digiseta(struct channel_t *ch, struct board_t *bd, + struct un_t *un, struct digi_t __user *new_info) { - struct board_t *bd; - struct channel_t *ch; - struct un_t *un; struct digi_t new_digi; ulong lock_flags = 0; unsigned long lock_flags2; - if (!tty || tty->magic != TTY_MAGIC) - return -EFAULT; - - un = tty->driver_data; - if (!un || un->magic != DGAP_UNIT_MAGIC) - return -EFAULT; - - ch = un->un_ch; - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return -EFAULT; - - bd = ch->ch_bd; - if (!bd || bd->magic != DGAP_BOARD_MAGIC) - return -EFAULT; - if (copy_from_user(&new_digi, new_info, sizeof(struct digi_t))) return -EFAULT; @@ -3255,7 +3231,7 @@ static int dgap_tty_digiseta(struct tty_struct *tty, if (ch->ch_digi.digi_offlen > DIGI_PLEN) ch->ch_digi.digi_offlen = DIGI_PLEN; - dgap_param(tty); + dgap_param(ch, bd, un->un_type); spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); spin_unlock_irqrestore(&bd->bd_lock, lock_flags); @@ -3310,30 +3286,13 @@ static int dgap_tty_digigetedelay(struct tty_struct *tty, int __user *retinfo) * Ioctl to set the EDELAY setting * */ -static int dgap_tty_digisetedelay(struct tty_struct *tty, int __user *new_info) +static int dgap_tty_digisetedelay(struct channel_t *ch, struct board_t *bd, + struct un_t *un, int __user *new_info) { - struct board_t *bd; - struct channel_t *ch; - struct un_t *un; int new_digi; ulong lock_flags; ulong lock_flags2; - if (!tty || tty->magic != TTY_MAGIC) - return -EFAULT; - - un = tty->driver_data; - if (!un || un->magic != DGAP_UNIT_MAGIC) - return -EFAULT; - - ch = un->un_ch; - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return -EFAULT; - - bd = ch->ch_bd; - if (!bd || bd->magic != DGAP_BOARD_MAGIC) - return -EFAULT; - if (copy_from_user(&new_digi, new_info, sizeof(int))) return -EFAULT; @@ -3342,7 +3301,7 @@ static int dgap_tty_digisetedelay(struct tty_struct *tty, int __user *new_info) writew((u16) new_digi, &(ch->ch_bs->edelay)); - dgap_param(tty); + dgap_param(ch, bd, un->un_type); spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); spin_unlock_irqrestore(&bd->bd_lock, lock_flags); @@ -3355,28 +3314,15 @@ static int dgap_tty_digisetedelay(struct tty_struct *tty, int __user *new_info) * * Ioctl to get the current custom baud rate setting. */ -static int dgap_tty_digigetcustombaud(struct tty_struct *tty, - int __user *retinfo) +static int dgap_tty_digigetcustombaud(struct channel_t *ch, struct un_t *un, + int __user *retinfo) { - struct channel_t *ch; - struct un_t *un; int tmp; ulong lock_flags; if (!retinfo) return -EFAULT; - if (!tty || tty->magic != TTY_MAGIC) - return -EFAULT; - - un = tty->driver_data; - if (!un || un->magic != DGAP_UNIT_MAGIC) - return -EFAULT; - - ch = un->un_ch; - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return -EFAULT; - memset(&tmp, 0, sizeof(tmp)); spin_lock_irqsave(&ch->ch_lock, lock_flags); @@ -3394,32 +3340,13 @@ static int dgap_tty_digigetcustombaud(struct tty_struct *tty, * * Ioctl to set the custom baud rate setting */ -static int dgap_tty_digisetcustombaud(struct tty_struct *tty, - int __user *new_info) +static int dgap_tty_digisetcustombaud(struct channel_t *ch, struct board_t *bd, + struct un_t *un, int __user *new_info) { - struct board_t *bd; - struct channel_t *ch; - struct un_t *un; uint new_rate; ulong lock_flags; ulong lock_flags2; - if (!tty || tty->magic != TTY_MAGIC) - return -EFAULT; - - un = tty->driver_data; - if (!un || un->magic != DGAP_UNIT_MAGIC) - return -EFAULT; - - ch = un->un_ch; - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return -EFAULT; - - bd = ch->ch_bd; - if (!bd || bd->magic != DGAP_BOARD_MAGIC) - return -EFAULT; - - if (copy_from_user(&new_rate, new_info, sizeof(unsigned int))) return -EFAULT; @@ -3430,7 +3357,7 @@ static int dgap_tty_digisetcustombaud(struct tty_struct *tty, ch->ch_custom_speed = new_rate; - dgap_param(tty); + dgap_param(ch, bd, un->un_type); spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); spin_unlock_irqrestore(&bd->bd_lock, lock_flags); @@ -3477,7 +3404,7 @@ static void dgap_tty_set_termios(struct tty_struct *tty, ch->ch_stopc = tty->termios.c_cc[VSTOP]; dgap_carrier(ch); - dgap_param(tty); + dgap_param(ch, bd, un->un_type); spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); spin_unlock_irqrestore(&bd->bd_lock, lock_flags); @@ -3884,7 +3811,7 @@ static int dgap_tty_ioctl(struct tty_struct *tty, unsigned int cmd, spin_lock_irqsave(&ch->ch_lock, lock_flags2); tty->termios.c_cflag = ((tty->termios.c_cflag & ~CLOCAL) | (arg ? CLOCAL : 0)); - dgap_param(tty); + dgap_param(ch, bd, un->un_type); spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); spin_unlock_irqrestore(&bd->bd_lock, lock_flags); @@ -3900,7 +3827,7 @@ static int dgap_tty_ioctl(struct tty_struct *tty, unsigned int cmd, case TIOCMSET: spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - return dgap_set_modem_info(tty, cmd, uarg); + return dgap_set_modem_info(ch, bd, un, cmd, uarg); /* * Here are any additional ioctl's that we want to implement @@ -4048,7 +3975,7 @@ static int dgap_tty_ioctl(struct tty_struct *tty, unsigned int cmd, /* get information for ditty */ spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - return dgap_tty_digigeta(tty, uarg); + return dgap_tty_digigeta(ch, uarg); case DIGI_SETAW: case DIGI_SETAF: @@ -4070,7 +3997,7 @@ static int dgap_tty_ioctl(struct tty_struct *tty, unsigned int cmd, case DIGI_SETA: spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - return dgap_tty_digiseta(tty, uarg); + return dgap_tty_digiseta(ch, bd, un, uarg); case DIGI_GEDELAY: spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); @@ -4080,21 +4007,21 @@ static int dgap_tty_ioctl(struct tty_struct *tty, unsigned int cmd, case DIGI_SEDELAY: spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - return dgap_tty_digisetedelay(tty, uarg); + return dgap_tty_digisetedelay(ch, bd, un, uarg); case DIGI_GETCUSTOMBAUD: spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - return dgap_tty_digigetcustombaud(tty, uarg); + return dgap_tty_digigetcustombaud(ch, un, uarg); case DIGI_SETCUSTOMBAUD: spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); spin_unlock_irqrestore(&bd->bd_lock, lock_flags); - return dgap_tty_digisetcustombaud(tty, uarg); + return dgap_tty_digisetcustombaud(ch, bd, un, uarg); case DIGI_RESET_PORT: dgap_firmware_reset_port(ch); - dgap_param(tty); + dgap_param(ch, bd, un->un_type); spin_unlock_irqrestore(&ch->ch_lock, lock_flags2); spin_unlock_irqrestore(&bd->bd_lock, lock_flags); return 0; @@ -4107,29 +4034,30 @@ static int dgap_tty_ioctl(struct tty_struct *tty, unsigned int cmd, } } -static int dgap_after_config_loaded(int board) +static int dgap_alloc_flipbuf(struct board_t *brd) { /* - * Initialize KME waitqueues... - */ - init_waitqueue_head(&(dgap_board[board]->kme_wait)); - - /* * allocate flip buffer for board. */ - dgap_board[board]->flipbuf = kmalloc(MYFLIPLEN, GFP_KERNEL); - if (!dgap_board[board]->flipbuf) + brd->flipbuf = kmalloc(MYFLIPLEN, GFP_KERNEL); + if (!brd->flipbuf) return -ENOMEM; - dgap_board[board]->flipflagbuf = kmalloc(MYFLIPLEN, GFP_KERNEL); - if (!dgap_board[board]->flipflagbuf) { - kfree(dgap_board[board]->flipbuf); + brd->flipflagbuf = kmalloc(MYFLIPLEN, GFP_KERNEL); + if (!brd->flipflagbuf) { + kfree(brd->flipbuf); return -ENOMEM; } return 0; } +static void dgap_free_flipbuf(struct board_t *brd) +{ + kfree(brd->flipbuf); + kfree(brd->flipflagbuf); +} + /* * Create pr and tty device entries */ @@ -4137,6 +4065,7 @@ static int dgap_tty_register_ports(struct board_t *brd) { struct channel_t *ch; int i; + int ret; brd->serial_ports = kcalloc(brd->nasync, sizeof(*brd->serial_ports), GFP_KERNEL); @@ -4146,8 +4075,8 @@ static int dgap_tty_register_ports(struct board_t *brd) brd->printer_ports = kcalloc(brd->nasync, sizeof(*brd->printer_ports), GFP_KERNEL); if (!brd->printer_ports) { - kfree(brd->serial_ports); - return -ENOMEM; + ret = -ENOMEM; + goto free_serial_ports; } for (i = 0; i < brd->nasync; i++) { @@ -4161,15 +4090,25 @@ static int dgap_tty_register_ports(struct board_t *brd) struct device *classp; classp = tty_port_register_device(&brd->serial_ports[i], - brd->serial_driver, - brd->firstminor + i, NULL); + brd->serial_driver, + i, NULL); + + if (IS_ERR(classp)) { + ret = PTR_ERR(classp); + goto unregister_ttys; + } dgap_create_tty_sysfs(&ch->ch_tun, classp); ch->ch_tun.un_sysfs = classp; classp = tty_port_register_device(&brd->printer_ports[i], - brd->print_driver, - brd->firstminor + i, NULL); + brd->print_driver, + i, NULL); + + if (IS_ERR(classp)) { + ret = PTR_ERR(classp); + goto unregister_ttys; + } dgap_create_tty_sysfs(&ch->ch_pun, classp); ch->ch_pun.un_sysfs = classp; @@ -4177,6 +4116,35 @@ static int dgap_tty_register_ports(struct board_t *brd) dgap_create_ports_sysfiles(brd); return 0; + +unregister_ttys: + while (i >= 0) { + ch = brd->channels[i]; + if (ch->ch_tun.un_sysfs) { + dgap_remove_tty_sysfs(ch->ch_tun.un_sysfs); + tty_unregister_device(brd->serial_driver, i); + } + + if (ch->ch_pun.un_sysfs) { + dgap_remove_tty_sysfs(ch->ch_pun.un_sysfs); + tty_unregister_device(brd->print_driver, i); + } + i--; + } + + for (i = 0; i < brd->nasync; i++) { + tty_port_destroy(&brd->serial_ports[i]); + tty_port_destroy(&brd->printer_ports[i]); + } + + kfree(brd->printer_ports); + brd->printer_ports = NULL; + +free_serial_ports: + kfree(brd->serial_ports); + brd->serial_ports = NULL; + + return ret; } /* @@ -4995,40 +4963,14 @@ static void dgap_firmware_reset_port(struct channel_t *ch) * struct tty_struct * - TTY for port. * *=======================================================================*/ -static int dgap_param(struct tty_struct *tty) +static int dgap_param(struct channel_t *ch, struct board_t *bd, u32 un_type) { - struct ktermios *ts; - struct board_t *bd; - struct channel_t *ch; - struct bs_t __iomem *bs; - struct un_t *un; u16 head; u16 cflag; u16 iflag; u8 mval; u8 hflow; - if (!tty || tty->magic != TTY_MAGIC) - return -EIO; - - un = (struct un_t *) tty->driver_data; - if (!un || un->magic != DGAP_UNIT_MAGIC) - return -EIO; - - ch = un->un_ch; - if (!ch || ch->magic != DGAP_CHANNEL_MAGIC) - return -EIO; - - bd = ch->ch_bd; - if (!bd || bd->magic != DGAP_BOARD_MAGIC) - return -EIO; - - bs = ch->ch_bs; - if (!bs) - return -EIO; - - ts = &tty->termios; - /* * If baud rate is zero, flush queues, and set mval to drop DTR. */ @@ -5108,7 +5050,7 @@ static int dgap_param(struct tty_struct *tty) * terminal unit is NOT open */ if (!(ch->ch_tun.un_flags & UN_ISOPEN) && - (un->un_type == DGAP_PRINT)) + un_type == DGAP_PRINT) baud = C_BAUD(ch->ch_pun.un_tty) & 0xff; else baud = C_BAUD(ch->ch_tun.un_tty) & 0xff; @@ -5281,6 +5223,7 @@ static int dgap_param(struct tty_struct *tty) */ if (bd->bd_flags & BD_FEP5PLUS) { u16 hflow2 = 0; + if (ch->ch_digi.digi_flags & DIGI_RTS_TOGGLE) hflow2 |= (D_RTS(ch)); if (ch->ch_digi.digi_flags & DIGI_DTR_TOGGLE) @@ -5305,7 +5248,7 @@ static int dgap_param(struct tty_struct *tty) /* * Read modem signals, and then call carrier function. */ - ch->ch_mistat = readb(&(bs->m_stat)); + ch->ch_mistat = readb(&(ch->ch_bs->m_stat)); dgap_carrier(ch); /* @@ -5690,6 +5633,7 @@ static int dgap_create_driver_sysfiles(struct pci_driver *dgap_driver) static void dgap_remove_driver_sysfiles(struct pci_driver *dgap_driver) { struct device_driver *driverfs = &dgap_driver->driver; + driver_remove_file(driverfs, &driver_attr_version); driver_remove_file(driverfs, &driver_attr_boards); driver_remove_file(driverfs, &driver_attr_maxboards); @@ -6283,6 +6227,7 @@ static ssize_t dgap_tty_name_show(struct device *d, if (cptr->type == TNODE && found == TRUE) { char *ptr1; + if (strstr(cptr->u.ttyname, "tty")) { ptr1 = cptr->u.ttyname; ptr1 += 3; @@ -6381,7 +6326,7 @@ static void dgap_remove_tty_sysfs(struct device *c) /* * Parse a configuration file read into memory as a string. */ -static int dgap_parsefile(char **in, int remove) +static int dgap_parsefile(char **in) { struct cnode *p, *brd, *line, *conc; int rc; @@ -6396,7 +6341,7 @@ static int dgap_parsefile(char **in, int remove) p = p->next; /* file must start with a BEGIN */ - while ((rc = dgap_gettok(in, p)) != BEGIN) { + while ((rc = dgap_gettok(in)) != BEGIN) { if (rc == 0) { dgap_err("unexpected EOF"); return -1; @@ -6404,17 +6349,13 @@ static int dgap_parsefile(char **in, int remove) } for (; ;) { - rc = dgap_gettok(in, p); + rc = dgap_gettok(in); if (rc == 0) { dgap_err("unexpected EOF"); return -1; } switch (rc) { - case 0: - dgap_err("unexpected end of file"); - return -1; - case BEGIN: /* should only be 1 begin */ dgap_err("unexpected config_begin\n"); return -1; @@ -6425,13 +6366,15 @@ static int dgap_parsefile(char **in, int remove) case BOARD: /* board info */ if (dgap_checknode(p)) return -1; - p->next = dgap_newnode(BNODE); + + p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL); if (!p->next) { dgap_err("out of memory"); return -1; } p = p->next; + p->type = BNODE; p->u.board.status = kstrdup("No", GFP_KERNEL); line = conc = NULL; brd = p; @@ -6716,12 +6659,16 @@ static int dgap_parsefile(char **in, int remove) case TTYN: /* tty name prefix */ if (dgap_checknode(p)) return -1; - p->next = dgap_newnode(TNODE); + + p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL); if (!p->next) { dgap_err("out of memory"); return -1; } + p = p->next; + p->type = TNODE; + s = dgap_getword(in); if (!s) { dgap_err("unexpeced end of file"); @@ -6737,12 +6684,16 @@ static int dgap_parsefile(char **in, int remove) case CU: /* cu name prefix */ if (dgap_checknode(p)) return -1; - p->next = dgap_newnode(CUNODE); + + p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL); if (!p->next) { dgap_err("out of memory"); return -1; } + p = p->next; + p->type = CUNODE; + s = dgap_getword(in); if (!s) { dgap_err("unexpeced end of file"); @@ -6767,12 +6718,15 @@ static int dgap_parsefile(char **in, int remove) dgap_err("line not vaild for PC/em"); return -1; } - p->next = dgap_newnode(LNODE); + + p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL); if (!p->next) { dgap_err("out of memory"); return -1; } + p = p->next; + p->type = LNODE; conc = NULL; line = p; linecnt++; @@ -6785,13 +6739,17 @@ static int dgap_parsefile(char **in, int remove) dgap_err("must specify line info before concentrator"); return -1; } - p->next = dgap_newnode(CNODE); + + p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL); if (!p->next) { dgap_err("out of memory"); return -1; } + p = p->next; + p->type = CNODE; conc = p; + if (linecnt) brd->u.board.conc2++; else @@ -6834,12 +6792,15 @@ static int dgap_parsefile(char **in, int remove) return -1; } } - p->next = dgap_newnode(MNODE); + + p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL); if (!p->next) { dgap_err("out of memory"); return -1; } p = p->next; + p->type = MNODE; + if (linecnt) brd->u.board.module2++; else @@ -6920,12 +6881,16 @@ static int dgap_parsefile(char **in, int remove) case PRINT: /* transparent print name prefix */ if (dgap_checknode(p)) return -1; - p->next = dgap_newnode(PNODE); + + p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL); if (!p->next) { dgap_err("out of memory"); return -1; } + p = p->next; + p->type = PNODE; + s = dgap_getword(in); if (!s) { dgap_err("unexpeced end of file"); @@ -6941,12 +6906,16 @@ static int dgap_parsefile(char **in, int remove) case CMAJOR: /* major number */ if (dgap_checknode(p)) return -1; - p->next = dgap_newnode(JNODE); + + p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL); if (!p->next) { dgap_err("out of memory"); return -1; } + p = p->next; + p->type = JNODE; + s = dgap_getword(in); if (!s) { dgap_err("unexpected end of file"); @@ -6961,12 +6930,16 @@ static int dgap_parsefile(char **in, int remove) case ALTPIN: /* altpin setting */ if (dgap_checknode(p)) return -1; - p->next = dgap_newnode(ANODE); + + p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL); if (!p->next) { dgap_err("out of memory"); return -1; } + p = p->next; + p->type = ANODE; + s = dgap_getword(in); if (!s) { dgap_err("unexpected end of file"); @@ -6981,12 +6954,14 @@ static int dgap_parsefile(char **in, int remove) case USEINTR: /* enable interrupt setting */ if (dgap_checknode(p)) return -1; - p->next = dgap_newnode(INTRNODE); + + p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL); if (!p->next) { dgap_err("out of memory"); return -1; } p = p->next; + p->type = INTRNODE; s = dgap_getword(in); if (!s) { dgap_err("unexpected end of file"); @@ -7001,12 +6976,16 @@ static int dgap_parsefile(char **in, int remove) case TTSIZ: /* size of tty structure */ if (dgap_checknode(p)) return -1; - p->next = dgap_newnode(TSNODE); + + p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL); if (!p->next) { dgap_err("out of memory"); return -1; } + p = p->next; + p->type = TSNODE; + s = dgap_getword(in); if (!s) { dgap_err("unexpected end of file"); @@ -7021,12 +7000,16 @@ static int dgap_parsefile(char **in, int remove) case CHSIZ: /* channel structure size */ if (dgap_checknode(p)) return -1; - p->next = dgap_newnode(CSNODE); + + p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL); if (!p->next) { dgap_err("out of memory"); return -1; } + p = p->next; + p->type = CSNODE; + s = dgap_getword(in); if (!s) { dgap_err("unexpected end of file"); @@ -7041,12 +7024,16 @@ static int dgap_parsefile(char **in, int remove) case BSSIZ: /* board structure size */ if (dgap_checknode(p)) return -1; - p->next = dgap_newnode(BSNODE); + + p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL); if (!p->next) { dgap_err("out of memory"); return -1; } + p = p->next; + p->type = BSNODE; + s = dgap_getword(in); if (!s) { dgap_err("unexpected end of file"); @@ -7061,12 +7048,16 @@ static int dgap_parsefile(char **in, int remove) case UNTSIZ: /* sched structure size */ if (dgap_checknode(p)) return -1; - p->next = dgap_newnode(USNODE); + + p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL); if (!p->next) { dgap_err("out of memory"); return -1; } + p = p->next; + p->type = USNODE; + s = dgap_getword(in); if (!s) { dgap_err("unexpected end of file"); @@ -7081,12 +7072,16 @@ static int dgap_parsefile(char **in, int remove) case F2SIZ: /* f2200 structure size */ if (dgap_checknode(p)) return -1; - p->next = dgap_newnode(FSNODE); + + p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL); if (!p->next) { dgap_err("out of memory"); return -1; } + p = p->next; + p->type = FSNODE; + s = dgap_getword(in); if (!s) { dgap_err("unexpected end of file"); @@ -7101,12 +7096,16 @@ static int dgap_parsefile(char **in, int remove) case VPSIZ: /* vpix structure size */ if (dgap_checknode(p)) return -1; - p->next = dgap_newnode(VSNODE); + + p->next = kzalloc(sizeof(struct cnode), GFP_KERNEL); if (!p->next) { dgap_err("out of memory"); return -1; } + p = p->next; + p->type = VSNODE; + s = dgap_getword(in); if (!s) { dgap_err("unexpected end of file"); @@ -7158,12 +7157,12 @@ static char *dgap_sindex(char *string, char *group) /* * Get a token from the input file; return 0 if end of file is reached */ -static int dgap_gettok(char **in, struct cnode *p) +static int dgap_gettok(char **in) { char *w; struct toklist *t; - if (strstr(dgap_cword, "boar")) { + if (strstr(dgap_cword, "board")) { w = dgap_getword(in); snprintf(dgap_cword, MAXCWORD, "%s", w); for (t = dgap_tlist; t->token != 0; t++) { @@ -7223,21 +7222,6 @@ static void dgap_err(char *s) } /* - * allocate a new configuration node of type t - */ -static struct cnode *dgap_newnode(int t) -{ - struct cnode *n; - - n = kmalloc(sizeof(struct cnode), GFP_KERNEL); - if (n) { - memset((char *)n, 0, sizeof(struct cnode)); - n->type = t; - } - return n; -} - -/* * dgap_checknode: see if all the necessary info has been supplied for a node * before creating the next node. */ diff --git a/drivers/staging/dgap/dgap.h b/drivers/staging/dgap/dgap.h index 03c020e35f88..9728d59c94d1 100644 --- a/drivers/staging/dgap/dgap.h +++ b/drivers/staging/dgap/dgap.h @@ -529,7 +529,6 @@ struct macounter { struct board_t { int magic; /* Board Magic number. */ int boardnum; /* Board number: 0-3 */ - int firstminor; /* First minor, e.g. 0, 30, 60 */ int type; /* Type of board */ char *name; /* Product Name */ @@ -604,7 +603,6 @@ struct board_t { /* by DPA */ u16 dpastatus; /* The board "status", as defined */ /* by DPA */ - wait_queue_head_t kme_wait; /* Needed for DPA support */ u32 conc_dl_status; /* Status of any pending conc */ /* download */ |