staging: dgap: re-arrange functions for removing forward declarations.
PATCH 1/1 staging: dgap: re-arrange functions for removing forward declarations.
Re-arrange the functions for removing forward declarations.
---
This patch has too many changes for re-arranging the functions. So I wonder that I should break this up into smaller patches.
drivers/staging/dgap/dgap.c | 7462 +++++++++++++++++++++---------------------- 1 files changed, 3669 insertions(+), 3793 deletions(-)
drivers/staging/dgap/dgap.c +3669 -3793
@@ -65,145 +65,6 @@#include "dgap.h" -MODULE_LICENSE ("GPL" ); -MODULE_AUTHOR ("Digi International, http://www.digi.com" ); -MODULE_DESCRIPTION ("Driver for the Digi International EPCA PCI based product line" ); -MODULE_SUPPORTED_DEVICE ("dgap" ); - -static int dgap_start (void ); -static void dgap_stop (void ); -static void dgap_init_globals (void ); -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_one (struct pci_dev *pdev,const struct pci_device_id *ent); -static void dgap_remove_one (struct pci_dev *dev); -static int dgap_remap (struct board_t *brd); -static void dgap_unmap (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); -static void dgap_tty_close (struct tty_struct *tty,struct file *file); -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 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 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); -static void dgap_tty_stop (struct tty_struct *tty); -static void dgap_tty_throttle (struct tty_struct *tty); -static void dgap_tty_unthrottle (struct tty_struct *tty); -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 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 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); -static int dgap_tty_send_break (struct tty_struct *tty,int msec); -static void dgap_tty_wait_until_sent (struct tty_struct *tty,int timeout); -static int dgap_tty_write (struct tty_struct *tty,const unsigned char *buf, -int count); -static void dgap_tty_set_termios (struct tty_struct *tty, -struct ktermios *old_termios); -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_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); - -/* -* Our function prototypes from dgap_fep5 -*/ -static void dgap_cmdw_ext (struct channel_t *ch,u16 cmd,u16 word,uint ncmds); -static int dgap_event (struct board_t *bd); - -static void dgap_poll_tasklet (unsigned long data); -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 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); -static void dgap_firmware_reset_port (struct channel_t *ch); - -/* -* Function prototypes from dgap_parse.c. -*/ -static int dgap_gettok (char **in); -static char *dgap_getword (char **in); -static int dgap_checknode (struct cnode *p); - -/* -* Function prototypes from dgap_sysfs.h -*/ -static void dgap_create_ports_sysfiles (struct board_t *bd); -static void dgap_remove_ports_sysfiles (struct board_t *bd); - -static int dgap_create_driver_sysfiles (struct pci_driver *); -static void dgap_remove_driver_sysfiles (struct pci_driver *); - -static void dgap_create_tty_sysfs (struct un_t *un,struct device *c); -static void dgap_remove_tty_sysfs (struct device *c); - -/* -* Function prototypes from dgap_parse.h -*/ -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); -static uint dgap_config_get_useintr (struct board_t *bd); -static uint dgap_config_get_altpin (struct board_t *bd); - -static void dgap_do_bios_load (struct board_t *brd,const u8 *ubios,int len); -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_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, -struct board_t *brd); -static void dgap_cleanup_nodes (void ); - -static void dgap_cleanup_module (void ); - -module_exit (dgap_cleanup_module); -/* * File operations permitted on Control/Management major. */
@@ -298,13 +159,6 @@ static struct board_id dgap_ids[] = { {0,} /* 0 terminated list. */ }; -static struct pci_driver dgap_driver = { - .name ="dgap" , - .probe = dgap_init_one, - .id_table = dgap_pci_tbl, - .remove = dgap_remove_one, -}; -struct firmware_info {u8 *conf_name;/* dgap.conf */ u8 *bios_name;/* BIOS filename */
@@ -367,29 +221,6 @@ static struct ktermios dgap_default_termios = { .c_line = 0, }; -static const struct tty_operations dgap_tty_ops = { - .open = dgap_tty_open, - .close = dgap_tty_close, - .write = dgap_tty_write, - .write_room = dgap_tty_write_room, - .flush_buffer = dgap_tty_flush_buffer, - .chars_in_buffer = dgap_tty_chars_in_buffer, - .flush_chars = dgap_tty_flush_chars, - .ioctl = dgap_tty_ioctl, - .set_termios = dgap_tty_set_termios, - .stop = dgap_tty_stop, - .start = dgap_tty_start, - .throttle = dgap_tty_throttle, - .unthrottle = dgap_tty_unthrottle, - .hangup = dgap_tty_hangup, - .put_char = dgap_tty_put_char, - .tiocmget = dgap_tty_tiocmget, - .tiocmset = dgap_tty_tiocmset, - .break_ctl = dgap_tty_send_break, - .wait_until_sent = dgap_tty_wait_until_sent, - .send_xchar = dgap_tty_send_xchar -}; -/* * Our needed internal static variables from dgap_parse.c */
@@ -457,1089 +288,1226 @@ static struct toklist dgap_tlist[] = { { 0, NULL } }; -/************************************************************************ -* -* Driver load/unload functions -* -************************************************************************/ /* -* init_module() -* -* Module load. This is where it all starts. +* dgap_sindex: much like index(), but it looks for a match of any character in +* the group, and returns that position. If the first character is a ^, then +* this will match the first occurrence not in that group. */ -static int dgap_init_module (void ) +static char *dgap_sindex (char *string,char *group) { -int rc; - -pr_info ("%s, Digi International Part Number %s\n" ,DG_NAME ,DG_PART ); - - rc =dgap_start (); -if (rc) -return rc; - - rc =pci_register_driver (&dgap_driver); -if (rc) - goto err_stop; - - rc =dgap_create_driver_sysfiles (&dgap_driver); -if (rc) - goto err_unregister; - - dgap_driver_state =DRIVER_READY ; +char *ptr; -return 0 ; +if (!string || !group) +return (char *)NULL ; -err_unregister: -pci_unregister_driver (&dgap_driver); -err_stop: -dgap_stop (); +if (*group =='^' ) { + group++; +for (; *string; string++) { +for (ptr = group; *ptr; ptr++) { +if (*ptr == *string) +break ; + } +if (*ptr =='\0' ) +return string; + } + }else { +for (; *string; string++) { +for (ptr = group; *ptr; ptr++) { +if (*ptr == *string) +return string; + } + } + } -return rc; +return (char *)NULL ; } -module_init (dgap_init_module);/* -* Start of driver. +* get a word from the input stream, also keep track of current line number. +* words are separated by whitespace. */ -static int dgap_start (void ) +static char *dgap_getword (char **in) { -int rc; -unsigned long flags; -struct device *device; - -/* -* make sure that the globals are -* init'd before we do anything else -*/ -dgap_init_globals (); - - dgap_numboards =0 ; +char *ret_ptr = *in; -pr_info ("For the tools package please visit http://www.digi.com\n" ); +char *ptr =dgap_sindex (*in," \t\n" ); -/* -* Register our base character device into the kernel. -*/ +/* If no word found, return null */ +if (!ptr) +return NULL ; -/* -* Register management/dpa devices -*/ - rc =register_chrdev (DIGI_DGAP_MAJOR ,"dgap" , &dgap_board_fops); -if (rc <0 ) -return rc; +/* Mark new location for our buffer */ + *ptr ='\0' ; + *in = ptr +1 ; - dgap_class =class_create (THIS_MODULE ,"dgap_mgmt" ); -if (IS_ERR (dgap_class)) { - rc =PTR_ERR (dgap_class); - goto failed_class; +/* Eat any extra spaces/tabs/newlines that might be present */ +while (*in && **in && ((**in ==' ' ) || + (**in =='\t' ) || + (**in =='\n' ))) { + **in ='\0' ; + *in = *in +1 ; } - device =device_create (dgap_class,NULL , -MKDEV (DIGI_DGAP_MAJOR ,0 ), -NULL ,"dgap_mgmt" ); -if (IS_ERR (device)) { - rc =PTR_ERR (device); - goto failed_device; - } +return ret_ptr; +} -/* Start the poller */ -spin_lock_irqsave (&dgap_poll_lock, flags); -init_timer (&dgap_poll_timer); - dgap_poll_timer.function = dgap_poll_handler; - dgap_poll_timer.data =0 ; - dgap_poll_time = jiffies +dgap_jiffies_from_ms (dgap_poll_tick); - dgap_poll_timer.expires = dgap_poll_time; -spin_unlock_irqrestore (&dgap_poll_lock, flags); -add_timer (&dgap_poll_timer); +/* +* Get a token from the input file; return 0 if end of file is reached +*/ +static int dgap_gettok (char **in) +{ +char *w; +struct toklist *t; -return rc; +if (strstr (dgap_cword,"board" )) { + w =dgap_getword (in); +snprintf (dgap_cword,MAXCWORD ,"%s" , w); +for (t = dgap_brdtype; t->token !=0 ; t++) { +if (!strcmp (w, t->string)) +return t->token; + } + }else { +while ((w =dgap_getword (in))) { +snprintf (dgap_cword,MAXCWORD ,"%s" , w); +for (t = dgap_tlist; t->token !=0 ; t++) { +if (!strcmp (w, t->string)) +return t->token; + } + } + } -failed_device: -class_destroy (dgap_class); -failed_class: -unregister_chrdev (DIGI_DGAP_MAJOR ,"dgap" ); -return rc; +return 0 ; } -static void dgap_stop (void ) +/* +* dgap_checknode: see if all the necessary info has been supplied for a node +* before creating the next node. +*/ +static int dgap_checknode (struct cnode *p) { -unsigned long lock_flags; - -spin_lock_irqsave (&dgap_poll_lock, lock_flags); - dgap_poll_stop =1 ; -spin_unlock_irqrestore (&dgap_poll_lock, lock_flags); +switch (p->type) { +case LNODE : +if (p->u.line.v_speed ==0 ) { +pr_err ("line speed not specified" ); +return 1 ; + } +return 0 ; -del_timer_sync (&dgap_poll_timer); +case CNODE : +if (p->u.conc.v_speed ==0 ) { +pr_err ("concentrator line speed not specified" ); +return 1 ; + } +if (p->u.conc.v_nport ==0 ) { +pr_err ("number of ports on concentrator not specified" ); +return 1 ; + } +if (p->u.conc.v_id ==0 ) { +pr_err ("concentrator id letter not specified" ); +return 1 ; + } +return 0 ; -device_destroy (dgap_class,MKDEV (DIGI_DGAP_MAJOR ,0 )); -class_destroy (dgap_class); -unregister_chrdev (DIGI_DGAP_MAJOR ,"dgap" ); +case MNODE : +if (p->u.module.v_nport ==0 ) { +pr_err ("number of ports on EBI module not specified" ); +return 1 ; + } +if (p->u.module.v_id ==0 ) { +pr_err ("EBI module id letter not specified" ); +return 1 ; + } +return 0 ; + } +return 0 ; } -static int dgap_init_one (struct pci_dev *pdev,const struct pci_device_id *ent) +/* +* Given a board pointer, returns whether we should use interrupts or not. +*/ +static uint dgap_config_get_useintr (struct board_t *bd) { -int rc; -struct board_t *brd; - -if (dgap_numboards >=MAXBOARDS ) -return -EPERM ; - - rc =pci_enable_device (pdev); -if (rc) -return -EIO ; - - 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) - goto cleanup_brd; - - rc =dgap_alloc_flipbuf (brd); -if (rc) - goto cleanup_brd; - - 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; +struct cnode *p; - brd->state =BOARD_READY ; - brd->dpastatus =BD_RUNNING ; +if (!bd) +return 0 ; - dgap_board[dgap_numboards++] = brd; +for (p = bd->bd_config; p; p = p->next) { +if (p->type ==INTRNODE ) { +/* +* check for pcxr types. +*/ +return p->u.useintr; + } + } +/* If not found, then don't turn on interrupts. */ 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_cleanup_nodes (); -dgap_unmap (brd); -kfree (brd); - -return rc; -} - -static void dgap_remove_one (struct pci_dev *dev) -{ -/* Do Nothing */ }/* -* dgap_cleanup_module() -* -* Module unload. This is where it all ends. +* Given a board pointer, returns whether we turn on altpin or not. */ -static void dgap_cleanup_module (void ) +static uint dgap_config_get_altpin (struct board_t *bd) { -int i; -ulong lock_flags; - -spin_lock_irqsave (&dgap_poll_lock, lock_flags); - dgap_poll_stop =1 ; -spin_unlock_irqrestore (&dgap_poll_lock, lock_flags); - -/* Turn off poller right away. */ -del_timer_sync (&dgap_poll_timer); - -dgap_remove_driver_sysfiles (&dgap_driver); +struct cnode *p; -device_destroy (dgap_class,MKDEV (DIGI_DGAP_MAJOR ,0 )); -class_destroy (dgap_class); -unregister_chrdev (DIGI_DGAP_MAJOR ,"dgap" ); +if (!bd) +return 0 ; -for (i =0 ; i < dgap_numboards; ++i) { -dgap_remove_ports_sysfiles (dgap_board[i]); -dgap_cleanup_tty (dgap_board[i]); -dgap_cleanup_board (dgap_board[i]); +for (p = bd->bd_config; p; p = p->next) { +if (p->type ==ANODE ) { +/* +* check for pcxr types. +*/ +return p->u.altpin; + } } -dgap_cleanup_nodes (); - -if (dgap_numboards) -pci_unregister_driver (&dgap_driver); +/* If not found, then don't turn on interrupts. */ +return 0 ; }/* -* dgap_cleanup_board() -* -* Free all the memory associated with a board +* Given a specific type of board, if found, detached link and +* returns the first occurrence in the list. */ -static void dgap_cleanup_board (struct board_t *brd) +static struct cnode *dgap_find_config (int type,int bus,int slot) { -int i; +struct cnode *p, *prev, *prev2, *found; -if (!brd || brd->magic !=DGAP_BOARD_MAGIC ) -return ; + p = &dgap_head; -dgap_free_irq (brd); +while (p->next) { + prev = p; + p = p->next; -tasklet_kill (&brd->helper_tasklet); +if (p->type !=BNODE ) +continue ; -dgap_unmap (brd); +if (p->u.board.type != type) +continue ; -/* Free all allocated channels structs */ -for (i =0 ; i <MAXPORTS ; i++) -kfree (brd->channels[i]); +if (p->u.board.v_pcibus && + p->u.board.pcibus != bus) +continue ; -kfree (brd->flipbuf); -kfree (brd->flipflagbuf); +if (p->u.board.v_pcislot && + p->u.board.pcislot != slot) +continue ; - dgap_board[brd->boardnum] =NULL ; + found = p; +/* +* Keep walking thru the list till we +* find the next board. +*/ +while (p->next) { + prev2 = p; + p = p->next; -kfree (brd); +if (p->type !=BNODE ) +continue ; + +/* +* Mark the end of our 1 board +* chain of configs. +*/ + prev2->next =NULL ; + +/* +* Link the "next" board to the +* previous board, effectively +* "unlinking" our board from +* the main config. +*/ + prev->next = p; + +return found; + } +/* +* It must be the last board in the list. +*/ + prev->next =NULL ; +return found; + } +return NULL ; }/* -* dgap_found_board() -* -* A board has been found, init it. +* Given a board pointer, walks the config link, counting up +* all ports user specified should be on the board. +* (This does NOT mean they are all actually present right now tho) */ -static struct board_t *dgap_found_board (struct pci_dev *pdev,int id, -int boardnum) +static uint dgap_config_get_num_prts (struct board_t *bd) { -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 ERR_PTR (-ENOMEM ); - -/* store the info for the board we've found */ - brd->magic =DGAP_BOARD_MAGIC ; - brd->boardnum = boardnum; - brd->vendor = dgap_pci_tbl[id].vendor; - brd->device = dgap_pci_tbl[id].device; - brd->pdev = pdev; - brd->pci_bus = pdev->bus->number; - brd->pci_slot =PCI_SLOT (pdev->devfn); - brd->name = dgap_ids[id].name; - brd->maxports = dgap_ids[id].maxports; - brd->type = dgap_ids[id].config_type; - brd->dpatype = dgap_ids[id].dpatype; - brd->dpastatus =BD_NOFEP ; -init_waitqueue_head (&brd->state_wait); +int count =0 ; +struct cnode *p; -spin_lock_init (&brd->bd_lock); +if (!bd) +return 0 ; - brd->inhibit_poller = FALSE; - brd->wait_for_bios =0 ; - brd->wait_for_fep =0 ; +for (p = bd->bd_config; p; p = p->next) { -for (i =0 ; i <MAXPORTS ; i++) - brd->channels[i] =NULL ; +switch (p->type) { +case BNODE : +/* +* check for pcxr types. +*/ +if (p->u.board.type >EPCFE ) + count += p->u.board.nport; +break ; +case CNODE : + count += p->u.conc.nport; +break ; +case MNODE : + count += p->u.module.nport; +break ; + } + } +return count; +} -/* store which card & revision we have */ -pci_read_config_word (pdev,PCI_SUBSYSTEM_VENDOR_ID , &brd->subvendor); -pci_read_config_word (pdev,PCI_SUBSYSTEM_ID , &brd->subdevice); -pci_read_config_byte (pdev,PCI_REVISION_ID , &brd->rev); +static char *dgap_create_config_string (struct board_t *bd,char *string) +{ +char *ptr = string; +struct cnode *p; +struct cnode *q; +int speed; - pci_irq = pdev->irq; - brd->irq = pci_irq; +if (!bd) { + *ptr =0xff ; +return string; + } -/* get the PCI Base Address Registers */ +for (p = bd->bd_config; p; p = p->next) { -/* Xr Jupiter and EPC use BAR 2 */ -if (brd->device ==PCI_DEV_XRJ_DID || brd->device ==PCI_DEV_EPCJ_DID ) { - brd->membase =pci_resource_start (pdev,2 ); - brd->membase_end =pci_resource_end (pdev,2 ); - } -/* Everyone else uses BAR 0 */ -else { - brd->membase =pci_resource_start (pdev,0 ); - brd->membase_end =pci_resource_end (pdev,0 ); - } +switch (p->type) { +case LNODE : + *ptr ='\0' ; + ptr++; + *ptr = p->u.line.speed; + ptr++; +break ; +case CNODE : +/* +* Because the EPC/con concentrators can have EM modules +* hanging off of them, we have to walk ahead in the +* list and keep adding the number of ports on each EM +* to the config. UGH! +*/ + speed = p->u.conc.speed; + q = p->next; +if (q && (q->type ==MNODE )) { + *ptr = (p->u.conc.nport +0x80 ); + ptr++; + p = q; +while (q->next && (q->next->type) ==MNODE ) { + *ptr = (q->u.module.nport +0x80 ); + ptr++; + p = q; + q = q->next; + } + *ptr = q->u.module.nport; + ptr++; + }else { + *ptr = p->u.conc.nport; + ptr++; + } -if (!brd->membase) { - ret = -ENODEV ; - goto free_brd; + *ptr = speed; + ptr++; +break ; + } } -if (brd->membase &1 ) - brd->membase &= ~3 ; -else - brd->membase &= ~15 ; - -/* -* On the PCI boards, there is no IO space allocated -* The I/O registers will be in the first 3 bytes of the -* upper 2MB of the 4MB memory space. The board memory -* will be mapped into the low 2MB of the 4MB memory space -*/ - brd->port = brd->membase +PCI_IO_OFFSET ; - brd->port_end = brd->port +PCI_IO_SIZE ; + *ptr =0xff ; +return string; +} -/* -* Special initialization for non-PLX boards -*/ -if (brd->device !=PCI_DEV_XRJ_DID && brd->device !=PCI_DEV_EPCJ_DID ) { -unsigned short cmd; +/* +* Parse a configuration file read into memory as a string. +*/ +static int dgap_parsefile (char **in) +{ +struct cnode *p, *brd, *line, *conc; +int rc; +char *s; +int linecnt =0 ; -pci_write_config_byte (pdev,0x40 ,0 ); -pci_write_config_byte (pdev,0x46 ,0 ); + p = &dgap_head; + brd = line = conc =NULL ; -/* Limit burst length to 2 doubleword transactions */ -pci_write_config_byte (pdev,0x42 ,1 ); +/* perhaps we are adding to an existing list? */ +while (p->next) + p = p->next; -/* -* Enable IO and mem if not already done. -* This was needed for support on Itanium. -*/ -pci_read_config_word (pdev,PCI_COMMAND , &cmd); - cmd |= (PCI_COMMAND_IO |PCI_COMMAND_MEMORY ); -pci_write_config_word (pdev,PCI_COMMAND , cmd); +/* file must start with a BEGIN */ +while ((rc =dgap_gettok (in)) !=BEGIN ) { +if (rc ==0 ) { +pr_err ("unexpected EOF" ); +return -1 ; + } } -/* init our poll helper tasklet */ -tasklet_init (&brd->helper_tasklet, dgap_poll_tasklet, - (unsigned long ) brd); +for (; ;) { +int board_type =0 ; +int conc_type =0 ; +int module_type =0 ; - ret =dgap_remap (brd); -if (ret) - goto free_brd; + rc =dgap_gettok (in); +if (rc ==0 ) { +pr_err ("unexpected EOF" ); +return -1 ; + } -pr_info ("dgap: board %d: %s (rev %d), irq %ld\n" , - boardnum, brd->name, brd->rev, brd->irq); +switch (rc) { +case BEGIN :/* should only be 1 begin */ +pr_err ("unexpected config_begin\n" ); +return -1 ; -return brd; +case END : +return 0 ; -free_brd: -kfree (brd); +case BOARD :/* board info */ +if (dgap_checknode (p)) +return -1 ; -return ERR_PTR (ret); -} + p->next =kzalloc (sizeof (struct cnode ),GFP_KERNEL ); +if (!p->next) +return -1 ; + p = p->next; -static int dgap_request_irq (struct board_t *brd) -{ -int rc; + p->type =BNODE ; + p->u.board.status =kstrdup ("No" ,GFP_KERNEL ); + line = conc =NULL ; + brd = p; + linecnt =-1 ; -if (!brd || brd->magic !=DGAP_BOARD_MAGIC ) -return -ENODEV ; + board_type =dgap_gettok (in); +if (board_type ==0 ) { +pr_err ("board !!type not specified" ); +return -1 ; + } -/* -* Set up our interrupt handler if we are set to do interrupts. -*/ -if (dgap_config_get_useintr (brd) && brd->irq) { + p->u.board.type = board_type; - rc =request_irq (brd->irq, dgap_intr,IRQF_SHARED ,"DGAP" , brd); +break ; -if (!rc) - brd->intr_used =1 ; - } -return 0 ; -} +case IO :/* i/o port */ +if (p->type !=BNODE ) { +pr_err ("IO port only vaild for boards" ); +return -1 ; + } + s =dgap_getword (in); +if (!s) { +pr_err ("unexpected end of file" ); +return -1 ; + } + p->u.board.portstr =kstrdup (s,GFP_KERNEL ); +if (kstrtol (s,0 , &p->u.board.port)) { +pr_err ("bad number for IO port" ); +return -1 ; + } + p->u.board.v_port =1 ; +break ; -static void dgap_free_irq (struct board_t *brd) -{ -if (brd->intr_used && brd->irq) -free_irq (brd->irq, brd); -} +case MEM :/* memory address */ +if (p->type !=BNODE ) { +pr_err ("memory address only vaild for boards" ); +return -1 ; + } + s =dgap_getword (in); +if (!s) { +pr_err ("unexpected end of file" ); +return -1 ; + } + p->u.board.addrstr =kstrdup (s,GFP_KERNEL ); +if (kstrtoul (s,0 , &p->u.board.addr)) { +pr_err ("bad number for memory address" ); +return -1 ; + } + p->u.board.v_addr =1 ; +break ; -static int dgap_firmware_load (struct pci_dev *pdev,int card_type, -struct board_t *brd) -{ -const struct firmware *fw; -char *tmp_ptr; -int ret; -char *dgap_config_buf; +case PCIINFO :/* pci information */ +if (p->type !=BNODE ) { +pr_err ("memory address only vaild for boards" ); +return -1 ; + } + s =dgap_getword (in); +if (!s) { +pr_err ("unexpected end of file" ); +return -1 ; + } + p->u.board.pcibusstr =kstrdup (s,GFP_KERNEL ); +if (kstrtoul (s,0 , &p->u.board.pcibus)) { +pr_err ("bad number for pci bus" ); +return -1 ; + } + p->u.board.v_pcibus =1 ; + s =dgap_getword (in); +if (!s) { +pr_err ("unexpected end of file" ); +return -1 ; + } + p->u.board.pcislotstr =kstrdup (s,GFP_KERNEL ); +if (kstrtoul (s,0 , &p->u.board.pcislot)) { +pr_err ("bad number for pci slot" ); +return -1 ; + } + p->u.board.v_pcislot =1 ; +break ; -dgap_get_vpd (brd); -dgap_do_reset_board (brd); +case METHOD : +if (p->type !=BNODE ) { +pr_err ("install method only vaild for boards" ); +return -1 ; + } + s =dgap_getword (in); +if (!s) { +pr_err ("unexpected end of file" ); +return -1 ; + } + p->u.board.method =kstrdup (s,GFP_KERNEL ); + p->u.board.v_method =1 ; +break ; -if (fw_info[card_type].conf_name) { - ret =request_firmware (&fw, fw_info[card_type].conf_name, - &pdev->dev); -if (ret) { -dev_err (&pdev->dev,"config file %s not found\n" , - fw_info[card_type].conf_name); -return ret; - } +case STATUS : +if (p->type !=BNODE ) { +pr_err ("config status only vaild for boards" ); +return -1 ; + } + s =dgap_getword (in); +if (!s) { +pr_err ("unexpected end of file" ); +return -1 ; + } + p->u.board.status =kstrdup (s,GFP_KERNEL ); +break ; - dgap_config_buf =kzalloc (fw->size +1 ,GFP_KERNEL ); -if (!dgap_config_buf) { -release_firmware (fw); -return -ENOMEM ; - } +case NPORTS :/* number of ports */ +if (p->type ==BNODE ) { + s =dgap_getword (in); +if (!s) { +pr_err ("unexpected end of file" ); +return -1 ; + } +if (kstrtol (s,0 , &p->u.board.nport)) { +pr_err ("bad number for number of ports" ); +return -1 ; + } + p->u.board.v_nport =1 ; + }else if (p->type ==CNODE ) { + s =dgap_getword (in); +if (!s) { +pr_err ("unexpected end of file" ); +return -1 ; + } +if (kstrtol (s,0 , &p->u.conc.nport)) { +pr_err ("bad number for number of ports" ); +return -1 ; + } + p->u.conc.v_nport =1 ; + }else if (p->type ==MNODE ) { + s =dgap_getword (in); +if (!s) { +pr_err ("unexpected end of file" ); +return -1 ; + } +if (kstrtol (s,0 , &p->u.module.nport)) { +pr_err ("bad number for number of ports" ); +return -1 ; + } + p->u.module.v_nport =1 ; + }else { +pr_err ("nports only valid for concentrators or modules" ); +return -1 ; + } +break ; -memcpy (dgap_config_buf, fw->data, fw->size); -release_firmware (fw); +case ID :/* letter ID used in tty name */ + s =dgap_getword (in); +if (!s) { +pr_err ("unexpected end of file" ); +return -1 ; + } -/* -* preserve dgap_config_buf -* as dgap_parsefile would -* otherwise alter it. -*/ - tmp_ptr = dgap_config_buf; + p->u.board.status =kstrdup (s,GFP_KERNEL ); -if (dgap_parsefile (&tmp_ptr) !=0 ) { -kfree (dgap_config_buf); -return -EINVAL ; - } -kfree (dgap_config_buf); - } +if (p->type ==CNODE ) { + p->u.conc.id =kstrdup (s,GFP_KERNEL ); + p->u.conc.v_id =1 ; + }else if (p->type ==MNODE ) { + p->u.module.id =kstrdup (s,GFP_KERNEL ); + p->u.module.v_id =1 ; + }else { +pr_err ("id only valid for concentrators or modules" ); +return -1 ; + } +break ; -/* -* Match this board to a config the user created for us. -*/ - brd->bd_config = -dgap_find_config (brd->type, brd->pci_bus, brd->pci_slot); +case STARTO :/* start offset of ID */ +if (p->type ==BNODE ) { + s =dgap_getword (in); +if (!s) { +pr_err ("unexpected end of file" ); +return -1 ; + } +if (kstrtol (s,0 , &p->u.board.start)) { +pr_err ("bad number for start of tty count" ); +return -1 ; + } + p->u.board.v_start =1 ; + }else if (p->type ==CNODE ) { + s =dgap_getword (in); +if (!s) { +pr_err ("unexpected end of file" ); +return -1 ; + } +if (kstrtol (s,0 , &p->u.conc.start)) { +pr_err ("bad number for start of tty count" ); +return -1 ; + } + p->u.conc.v_start =1 ; + }else if (p->type ==MNODE ) { + s =dgap_getword (in); +if (!s) { +pr_err ("unexpected end of file" ); +return -1 ; + } +if (kstrtol (s,0 , &p->u.module.start)) { +pr_err ("bad number for start of tty count" ); +return -1 ; + } + p->u.module.v_start =1 ; + }else { +pr_err ("start only valid for concentrators or modules" ); +return -1 ; + } +break ; -/* -* Because the 4 port Xr products share the same PCI ID -* as the 8 port Xr products, if we receive a NULL config -* back, and this is a PAPORT8 board, retry with a -* PAPORT4 attempt as well. -*/ -if (brd->type ==PAPORT8 && !brd->bd_config) - brd->bd_config = -dgap_find_config (PAPORT4 , brd->pci_bus, brd->pci_slot); +case TTYN :/* tty name prefix */ +if (dgap_checknode (p)) +return -1 ; -if (!brd->bd_config) { -dev_err (&pdev->dev,"No valid configuration found\n" ); -return -EINVAL ; - } + p->next =kzalloc (sizeof (struct cnode ),GFP_KERNEL ); +if (!p->next) +return -1 ; -if (fw_info[card_type].bios_name) { - ret =request_firmware (&fw, fw_info[card_type].bios_name, - &pdev->dev); -if (ret) { -dev_err (&pdev->dev,"bios file %s not found\n" , - fw_info[card_type].bios_name); -return ret; - } -dgap_do_bios_load (brd, fw->data, fw->size); -release_firmware (fw); + p = p->next; + p->type =TNODE ; -/* Wait for BIOS to test board... */ - ret =dgap_test_bios (brd); -if (ret) -return ret; - } + s =dgap_getword (in); +if (!s) { +pr_err ("unexpeced end of file" ); +return -1 ; + } + p->u.ttyname =kstrdup (s,GFP_KERNEL ); +if (!p->u.ttyname) +return -1 ; -if (fw_info[card_type].fep_name) { - ret =request_firmware (&fw, fw_info[card_type].fep_name, - &pdev->dev); -if (ret) { -dev_err (&pdev->dev,"dgap: fep file %s not found\n" , - fw_info[card_type].fep_name); -return ret; - } -dgap_do_fep_load (brd, fw->data, fw->size); -release_firmware (fw); +break ; -/* Wait for FEP to load on board... */ - ret =dgap_test_fep (brd); -if (ret) -return ret; - } +case CU :/* cu name prefix */ +if (dgap_checknode (p)) +return -1 ; -#ifdef DIGI_CONCENTRATORS_SUPPORTED -/* -* If this is a CX or EPCX, we need to see if the firmware -* is requesting a concentrator image from us. -*/ -if ((bd->type ==PCX ) || (bd->type ==PEPC )) { - chk_addr = (u16 *) (vaddr +DOWNREQ ); -/* Nonzero if FEP is requesting concentrator image. */ - check =readw (chk_addr); - vaddr = brd->re_map_membase; - } + p->next =kzalloc (sizeof (struct cnode ),GFP_KERNEL ); +if (!p->next) +return -1 ; -if (fw_info[card_type].con_name && check && vaddr) { - ret =request_firmware (&fw, fw_info[card_type].con_name, - &pdev->dev); -if (ret) { -dev_err (&pdev->dev,"conc file %s not found\n" , - fw_info[card_type].con_name); -return ret; - } -/* Put concentrator firmware loading code here */ - offset =readw ((u16 *) (vaddr +DOWNREQ )); -memcpy_toio (offset, fw->data, fw->size); + p = p->next; + p->type =CUNODE ; - dgap_do_conc_load(brd, (char *)fw->data, fw->size) -release_firmware (fw); - } -#endif + s =dgap_getword (in); +if (!s) { +pr_err ("unexpeced end of file" ); +return -1 ; + } + p->u.cuname =kstrdup (s,GFP_KERNEL ); +if (!p->u.cuname) +return -1 ; -return 0 ; -} +break ; -/* -* Remap PCI memory. -*/ -static int dgap_remap (struct board_t *brd) -{ -if (!brd || brd->magic !=DGAP_BOARD_MAGIC ) -return -EIO ; +case LINE :/* line information */ +if (dgap_checknode (p)) +return -1 ; +if (!brd) { +pr_err ("must specify board before line info" ); +return -1 ; + } +switch (brd->u.board.type) { +case PPCM : +pr_err ("line not vaild for PC/em" ); +return -1 ; + } -if (!request_mem_region (brd->membase,0x200000 ,"dgap" )) -return -ENOMEM ; + p->next =kzalloc (sizeof (struct cnode ),GFP_KERNEL ); +if (!p->next) +return -1 ; -if (!request_mem_region (brd->membase +PCI_IO_OFFSET ,0x200000 , -"dgap" )) { -release_mem_region (brd->membase,0x200000 ); -return -ENOMEM ; - } + p = p->next; + p->type =LNODE ; + conc =NULL ; + line = p; + linecnt++; +break ; - brd->re_map_membase =ioremap (brd->membase,0x200000 ); -if (!brd->re_map_membase) { -release_mem_region (brd->membase,0x200000 ); -release_mem_region (brd->membase +PCI_IO_OFFSET ,0x200000 ); -return -ENOMEM ; - } +case CONC :/* concentrator information */ +if (dgap_checknode (p)) +return -1 ; +if (!line) { +pr_err ("must specify line info before concentrator" ); +return -1 ; + } - brd->re_map_port =ioremap ((brd->membase +PCI_IO_OFFSET ),0x200000 ); -if (!brd->re_map_port) { -release_mem_region (brd->membase,0x200000 ); -release_mem_region (brd->membase +PCI_IO_OFFSET ,0x200000 ); -iounmap (brd->re_map_membase); -return -ENOMEM ; - } + p->next =kzalloc (sizeof (struct cnode ),GFP_KERNEL ); +if (!p->next) +return -1 ; -return 0 ; -} + p = p->next; + p->type =CNODE ; + conc = p; -static void dgap_unmap (struct board_t *brd) -{ -iounmap (brd->re_map_port); -iounmap (brd->re_map_membase); -release_mem_region (brd->membase +PCI_IO_OFFSET ,0x200000 ); -release_mem_region (brd->membase,0x200000 ); -} -/***************************************************************************** -* -* Function: -* -* dgap_poll_handler -* -* Author: -* -* Scott H Kilau -* -* Parameters: -* -* dummy -- ignored -* -* Return Values: -* -* none -* -* Description: -* -* As each timer expires, it determines (a) whether the "transmit" -* waiter needs to be woken up, and (b) whether the poller needs to -* be rescheduled. -* -******************************************************************************/ +if (linecnt) + brd->u.board.conc2++; +else + brd->u.board.conc1++; -static void dgap_poll_handler (ulong dummy) -{ -int i; -struct board_t *brd; -unsigned long lock_flags; -ulong new_time; + conc_type =dgap_gettok (in); +if (conc_type ==0 || conc_type !=CX || + conc_type !=EPC ) { +pr_err ("failed to set a type of concentratros" ); +return -1 ; + } - dgap_poll_counter++; + p->u.conc.type = conc_type; -/* -* Do not start the board state machine until -* driver tells us its up and running, and has -* everything it needs. -*/ -if (dgap_driver_state !=DRIVER_READY ) - goto schedule_poller; +break ; -/* -* If we have just 1 board, or the system is not SMP, -* then use the typical old style poller. -* Otherwise, use our new tasklet based poller, which should -* speed things up for multiple boards. -*/ -if ((dgap_numboards ==1 ) || (num_online_cpus () <=1 )) { -for (i =0 ; i < dgap_numboards; i++) { +case MOD :/* EBI module */ +if (dgap_checknode (p)) +return -1 ; +if (!brd) { +pr_err ("must specify board info before EBI modules" ); +return -1 ; + } +switch (brd->u.board.type) { +case PPCM : + linecnt =0 ; +break ; +default : +if (!conc) { +pr_err ("must specify concentrator info before EBI module" ); +return -1 ; + } + } - brd = dgap_board[i]; + p->next =kzalloc (sizeof (struct cnode ),GFP_KERNEL ); +if (!p->next) +return -1 ; -if (brd->state ==BOARD_FAILED ) -continue ; -if (!brd->intr_running) -/* Call the real board poller directly */ -dgap_poll_tasklet ((unsigned long ) brd); - } - }else { -/* -* Go thru each board, kicking off a -* tasklet for each if needed -*/ -for (i =0 ; i < dgap_numboards; i++) { - brd = dgap_board[i]; + p = p->next; + p->type =MNODE ; -/* -* Attempt to grab the board lock. -* -* If we can't get it, no big deal, the next poll -* will get it. Basically, I just really don't want -* to spin in here, because I want to kick off my -* tasklets as fast as I can, and then get out the -* poller. -*/ -if (!spin_trylock (&brd->bd_lock)) -continue ; +if (linecnt) + brd->u.board.module2++; +else + brd->u.board.module1++; -/* -* If board is in a failed state, don't bother -* scheduling a tasklet -*/ -if (brd->state ==BOARD_FAILED ) { -spin_unlock (&brd->bd_lock); -continue ; + module_type =dgap_gettok (in); +if (module_type ==0 || module_type !=PORTS || + module_type !=MODEM ) { +pr_err ("failed to set a type of module" ); +return -1 ; } -/* Schedule a poll helper task */ -if (!brd->intr_running) -tasklet_schedule (&brd->helper_tasklet); - -/* -* Can't do DGAP_UNLOCK here, as we don't have -* lock_flags because we did a trylock above. -*/ -spin_unlock (&brd->bd_lock); - } - } + p->u.module.type = module_type; -schedule_poller: +break ; -/* -* Schedule ourself back at the nominal wakeup interval. -*/ -spin_lock_irqsave (&dgap_poll_lock, lock_flags); - dgap_poll_time +=dgap_jiffies_from_ms (dgap_poll_tick); +case CABLE : +if (p->type ==LNODE ) { + s =dgap_getword (in); +if (!s) { +pr_err ("unexpected end of file" ); +return -1 ; + } + p->u.line.cable =kstrdup (s,GFP_KERNEL ); + p->u.line.v_cable =1 ; + } +break ; - new_time = dgap_poll_time - jiffies; +case SPEED :/* sync line speed indication */ +if (p->type ==LNODE ) { + s =dgap_getword (in); +if (!s) { +pr_err ("unexpected end of file" ); +return -1 ; + } +if (kstrtol (s,0 , &p->u.line.speed)) { +pr_err ("bad number for line speed" ); +return -1 ; + } + p->u.line.v_speed =1 ; + }else if (p->type ==CNODE ) { + s =dgap_getword (in); +if (!s) { +pr_err ("unexpected end of file" ); +return -1 ; + } +if (kstrtol (s,0 , &p->u.conc.speed)) { +pr_err ("bad number for line speed" ); +return -1 ; + } + p->u.conc.v_speed =1 ; + }else { +pr_err ("speed valid only for lines or concentrators." ); +return -1 ; + } +break ; -if ((ulong ) new_time >=2 * dgap_poll_tick) { - dgap_poll_time = - jiffies +dgap_jiffies_from_ms (dgap_poll_tick); - } +case CONNECT : +if (p->type ==CNODE ) { + s =dgap_getword (in); +if (!s) { +pr_err ("unexpected end of file" ); +return -1 ; + } + p->u.conc.connect =kstrdup (s,GFP_KERNEL ); + p->u.conc.v_connect =1 ; + } +break ; +case /* transparent print name prefix */ +if (dgap_checknode (p)) +return -1 ; - dgap_poll_timer.function = dgap_poll_handler; - dgap_poll_timer.data =0 ; - dgap_poll_timer.expires = dgap_poll_time; -spin_unlock_irqrestore (&dgap_poll_lock, lock_flags); + p->next =kzalloc (sizeof (struct cnode ),GFP_KERNEL ); +if (!p->next) +return -1 ; -if (!dgap_poll_stop) -add_timer (&dgap_poll_timer); -} + p = p->next; + p->type =PNODE ; -/* -* dgap_intr() -* -* Driver interrupt handler. -*/ -static irqreturn_t dgap_intr (int irq,void *voidbrd) -{ -struct board_t *brd = (struct board_t *) voidbrd; + s =dgap_getword (in); +if (!s) { +pr_err ("unexpeced end of file" ); +return -1 ; + } + p->u.printname =kstrdup (s,GFP_KERNEL ); +if (!p->u.printname) +return -1 ; -if (!brd) -return IRQ_NONE ; +break ; -/* -* Check to make sure its for us. -*/ -if (brd->magic !=DGAP_BOARD_MAGIC ) -return IRQ_NONE ; +case CMAJOR :/* major number */ +if (dgap_checknode (p)) +return -1 ; - brd->intr_count++; + p->next =kzalloc (sizeof (struct cnode ),GFP_KERNEL ); +if (!p->next) +return -1 ; -/* -* Schedule tasklet to run at a better time. -*/ -tasklet_schedule (&brd->helper_tasklet); -return IRQ_HANDLED ; -} + p = p->next; + p->type =JNODE ; -/* -* dgap_init_globals() -* -* This is where we initialize the globals from the static insmod -* configuration variables. These are declared near the head of -* this file. -*/ -static void dgap_init_globals (void ) -{ -int i; + s =dgap_getword (in); +if (!s) { +pr_err ("unexpected end of file" ); +return -1 ; + } +if (kstrtol (s,0 , &p->u.majornumber)) { +pr_err ("bad number for major number" ); +return -1 ; + } +break ; -for (i =0 ; i <MAXBOARDS ; i++) - dgap_board[i] =NULL ; +case ALTPIN :/* altpin setting */ +if (dgap_checknode (p)) +return -1 ; -init_timer (&dgap_poll_timer); -} + p->next =kzalloc (sizeof (struct cnode ),GFP_KERNEL ); +if (!p->next) +return -1 ; -/************************************************************************ -* -* TTY Initialization/Cleanup Functions -* -************************************************************************/ + p = p->next; + p->type =ANODE ; -/* -* dgap_tty_register() -* -* Init the tty subsystem for this board. -*/ -static int dgap_tty_register (struct board_t *brd) -{ -int rc; + s =dgap_getword (in); +if (!s) { +pr_err ("unexpected end of file" ); +return -1 ; + } +if (kstrtol (s,0 , &p->u.altpin)) { +pr_err ("bad number for altpin" ); +return -1 ; + } +break ; - brd->serial_driver =tty_alloc_driver (MAXPORTS ,0 ); -if (IS_ERR (brd->serial_driver)) -return PTR_ERR (brd->serial_driver); +case USEINTR :/* enable interrupt setting */ +if (dgap_checknode (p)) +return -1 ; -snprintf (brd->serial_name,MAXTTYNAMELEN ,"tty_dgap_%d_" , - brd->boardnum); - brd->serial_driver->name = brd->serial_name; - brd->serial_driver->name_base =0 ; - brd->serial_driver->major =0 ; - brd->serial_driver->minor_start =0 ; - brd->serial_driver->type =TTY_DRIVER_TYPE_SERIAL ; - brd->serial_driver->subtype =SERIAL_TYPE_NORMAL ; - brd->serial_driver->init_termios = dgap_default_termios; - brd->serial_driver->driver_name =DRVSTR ; - brd->serial_driver->flags = (TTY_DRIVER_REAL_RAW | -TTY_DRIVER_DYNAMIC_DEV | -TTY_DRIVER_HARDWARE_BREAK ); + p->next =kzalloc (sizeof (struct cnode ),GFP_KERNEL ); +if (!p->next) +return -1 ; -/* The kernel wants space to store pointers to tty_structs */ - brd->serial_driver->ttys = -kzalloc (MAXPORTS *sizeof (struct tty_struct *),GFP_KERNEL ); -if (!brd->serial_driver->ttys) { - rc = -ENOMEM ; - goto free_serial_drv; - } + p = p->next; + p->type =INTRNODE ; + s =dgap_getword (in); +if (!s) { +pr_err ("unexpected end of file" ); +return -1 ; + } +if (kstrtol (s,0 , &p->u.useintr)) { +pr_err ("bad number for useintr" ); +return -1 ; + } +break ; -/* -* Entry points for driver. Called by the kernel from -* tty_io.c and n_tty.c. -*/ -tty_set_operations (brd->serial_driver, &dgap_tty_ops); +case TTSIZ :/* size of tty structure */ +if (dgap_checknode (p)) +return -1 ; -/* -* If we're doing transparent print, we have to do all of the above -* again, separately so we don't get the LD confused about what major -* we are when we get into the dgap_tty_open() routine. -*/ - brd->print_driver =tty_alloc_driver (MAXPORTS ,0 ); -if (IS_ERR (brd->print_driver)) { - rc =PTR_ERR (brd->print_driver); - goto free_serial_drv; - } + p->next =kzalloc (sizeof (struct cnode ),GFP_KERNEL ); +if (!p->next) +return -1 ; -snprintf (brd->print_name,MAXTTYNAMELEN ,"pr_dgap_%d_" , - brd->boardnum); - brd->print_driver->name = brd->print_name; - brd->print_driver->name_base =0 ; - brd->print_driver->major =0 ; - brd->print_driver->minor_start =0 ; - brd->print_driver->type =TTY_DRIVER_TYPE_SERIAL ; - brd->print_driver->subtype =SERIAL_TYPE_NORMAL ; - brd->print_driver->init_termios = dgap_default_termios; - brd->print_driver->driver_name =DRVSTR ; - brd->print_driver->flags = (TTY_DRIVER_REAL_RAW | -TTY_DRIVER_DYNAMIC_DEV | -TTY_DRIVER_HARDWARE_BREAK ); + p = p->next; + p->type =TSNODE ; -/* The kernel wants space to store pointers to tty_structs */ - brd->print_driver->ttys = -kzalloc (MAXPORTS *sizeof (struct tty_struct *),GFP_KERNEL ); -if (!brd->print_driver->ttys) { - rc = -ENOMEM ; - goto free_print_drv; - } + s =dgap_getword (in); +if (!s) { +pr_err ("unexpected end of file" ); +return -1 ; + } +if (kstrtol (s,0 , &p->u.ttysize)) { +pr_err ("bad number for ttysize" ); +return -1 ; + } +break ; -/* -* Entry points for driver. Called by the kernel from -* tty_io.c and n_tty.c. -*/ -tty_set_operations (brd->print_driver, &dgap_tty_ops); +case CHSIZ :/* channel structure size */ +if (dgap_checknode (p)) +return -1 ; -/* Register tty devices */ - rc =tty_register_driver (brd->serial_driver); -if (rc <0 ) - goto free_print_drv; + p->next =kzalloc (sizeof (struct cnode ),GFP_KERNEL ); +if (!p->next) +return -1 ; -/* Register Transparent Print devices */ - rc =tty_register_driver (brd->print_driver); -if (rc <0 ) - goto unregister_serial_drv; + p = p->next; + p->type =CSNODE ; - dgap_boards_by_major[brd->serial_driver->major] = brd; - brd->dgap_serial_major = brd->serial_driver->major; + s =dgap_getword (in); +if (!s) { +pr_err ("unexpected end of file" ); +return -1 ; + } +if (kstrtol (s,0 , &p->u.chsize)) { +pr_err ("bad number for chsize" ); +return -1 ; + } +break ; - dgap_boards_by_major[brd->print_driver->major] = brd; - brd->dgap_transparent_print_major = brd->print_driver->major; +case BSSIZ :/* board structure size */ +if (dgap_checknode (p)) +return -1 ; -return 0 ; + p->next =kzalloc (sizeof (struct cnode ),GFP_KERNEL ); +if (!p->next) +return -1 ; -unregister_serial_drv: -tty_unregister_driver (brd->serial_driver); -free_print_drv: -put_tty_driver (brd->print_driver); -free_serial_drv: -put_tty_driver (brd->serial_driver); + p = p->next; + p->type =BSNODE ; -return rc; -} + s =dgap_getword (in); +if (!s) { +pr_err ("unexpected end of file" ); +return -1 ; + } +if (kstrtol (s,0 , &p->u.bssize)) { +pr_err ("bad number for bssize" ); +return -1 ; + } +break ; -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); -} +case UNTSIZ :/* sched structure size */ +if (dgap_checknode (p)) +return -1 ; -/* -* dgap_tty_init() -* -* Init the tty subsystem. Called once per board after board has been -* downloaded and init'ed. -*/ -static int dgap_tty_init (struct board_t *brd) -{ -int i; -int tlw; -uint true_count; -u8 __iomem *vaddr; -u8 modem; -struct channel_t *ch; -struct bs_t __iomem *bs; -struct cm_t __iomem *cm; -int ret; + p->next =kzalloc (sizeof (struct cnode ),GFP_KERNEL ); +if (!p->next) +return -1 ; -/* -* Initialize board structure elements. -*/ + p = p->next; + p->type =USNODE ; - vaddr = brd->re_map_membase; - true_count =readw ((vaddr +NCHAN )); + s =dgap_getword (in); +if (!s) { +pr_err ("unexpected end of file" ); +return -1 ; + } +if (kstrtol (s,0 , &p->u.unsize)) { +pr_err ("bad number for schedsize" ); +return -1 ; + } +break ; - brd->nasync =dgap_config_get_num_prts (brd); +case F2SIZ :/* f2200 structure size */ +if (dgap_checknode (p)) +return -1 ; -if (!brd->nasync) - brd->nasync = brd->maxports; + p->next =kzalloc (sizeof (struct cnode ),GFP_KERNEL ); +if (!p->next) +return -1 ; -if (brd->nasync > brd->maxports) - brd->nasync = brd->maxports; + p = p->next; + p->type =FSNODE ; -if (true_count != brd->nasync) { -dev_warn (&brd->pdev->dev, -"%s configured for %d ports, has %d ports.\n" , - brd->name, brd->nasync, true_count); + s =dgap_getword (in); +if (!s) { +pr_err ("unexpected end of file" ); +return -1 ; + } +if (kstrtol (s,0 , &p->u.f2size)) { +pr_err ("bad number for f2200size" ); +return -1 ; + } +break ; -if ((brd->type ==PPCM ) && - (true_count ==64 || true_count ==0 )) { -dev_warn (&brd->pdev->dev, -"Please make SURE the EBI cable running from the card\n" ); -dev_warn (&brd->pdev->dev, -"to each EM module is plugged into EBI IN!\n" ); - } +case VPSIZ :/* vpix structure size */ +if (dgap_checknode (p)) +return -1 ; - brd->nasync = true_count; + p->next =kzalloc (sizeof (struct cnode ),GFP_KERNEL ); +if (!p->next) +return -1 ; -/* If no ports, don't bother going any further */ -if (!brd->nasync) { - brd->state =BOARD_FAILED ; - brd->dpastatus =BD_NOFEP ; -return -EIO ; - } - } + p = p->next; + p->type =VSNODE ; -/* -* Allocate channel memory that might not have been allocated -* 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]) { - ret = -ENOMEM ; - goto free_chan; + s =dgap_getword (in); +if (!s) { +pr_err ("unexpected end of file" ); +return -1 ; + } +if (kstrtol (s,0 , &p->u.vpixsize)) { +pr_err ("bad number for vpixsize" ); +return -1 ; + } +break ; } } +} - ch = brd->channels[0 ]; - vaddr = brd->re_map_membase; +static void dgap_cleanup_nodes (void ) +{ +struct cnode *p; - bs = (struct bs_t __iomem *) ((ulong ) vaddr +CHANBUF ); - cm = (struct cm_t __iomem *) ((ulong ) vaddr +CMDBUF ); + p = &dgap_head; - brd->bd_bs = bs; +while (p) { +struct cnode *tmp = p->next; -/* Set up channel variables */ -for (i =0 ; i < brd->nasync; i++, ch = brd->channels[i], bs++) { +if (p->type ==NULLNODE ) { + p = tmp; +continue ; + } -spin_lock_init (&ch->ch_lock); +switch (p->type) { +case BNODE : +kfree (p->u.board.portstr); +kfree (p->u.board.addrstr); +kfree (p->u.board.pcibusstr); +kfree (p->u.board.pcislotstr); +kfree (p->u.board.method); +break ; +case CNODE : +kfree (p->u.conc.id); +kfree (p->u.conc.connect); +break ; +case MNODE : +kfree (p->u.module.id); +break ; +case TNODE : +kfree (p->u.ttyname); +break ; +case CUNODE : +kfree (p->u.cuname); +break ; +case LNODE : +kfree (p->u.line.cable); +break ; +case PNODE : +kfree (p->u.printname); +break ; + } -/* Store all our magic numbers */ - ch->magic =DGAP_CHANNEL_MAGIC ; - ch->ch_tun.magic =DGAP_UNIT_MAGIC ; - ch->ch_tun.un_type =DGAP_SERIAL ; - ch->ch_tun.un_ch = ch; - ch->ch_tun.un_dev = i; +kfree (p->u.board.status); +kfree (p); + p = tmp; + } +} - ch->ch_pun.magic =DGAP_UNIT_MAGIC ; - ch->ch_pun.un_type =DGAP_PRINT ; - ch->ch_pun.un_ch = ch; - ch->ch_pun.un_dev = i; +/* +* Retrives the current custom baud rate from FEP memory, +* and returns it back to the user. +* Returns 0 on error. +*/ +static uint dgap_get_custom_baud (struct channel_t *ch) +{ +u8 __iomem *vaddr; +ulong offset; +uint value; - ch->ch_vaddr = vaddr; - ch->ch_bs = bs; - ch->ch_cm = cm; - ch->ch_bd = brd; - ch->ch_portnum = i; - ch->ch_digi = dgap_digi_init; +if (!ch || ch->magic !=DGAP_CHANNEL_MAGIC ) +return 0 ; -/* -* Set up digi dsr and dcd bits based on altpin flag. -*/ -if (dgap_config_get_altpin (brd)) { - ch->ch_dsr =DM_CD ; - ch->ch_cd =DM_DSR ; - ch->ch_digi.digi_flags |=DIGI_ALTPIN ; - }else { - ch->ch_cd =DM_CD ; - ch->ch_dsr =DM_DSR ; - } +if (!ch->ch_bd || ch->ch_bd->magic !=DGAP_BOARD_MAGIC ) +return 0 ; - ch->ch_taddr = vaddr + (ioread16 (&(ch->ch_bs->tx_seg)) <<4 ); - ch->ch_raddr = vaddr + (ioread16 (&(ch->ch_bs->rx_seg)) <<4 ); - ch->ch_tx_win =0 ; - ch->ch_rx_win =0 ; - ch->ch_tsize =readw (&(ch->ch_bs->tx_max)) +1 ; - ch->ch_rsize =readw (&(ch->ch_bs->rx_max)) +1 ; - ch->ch_tstart =0 ; - ch->ch_rstart =0 ; +if (!(ch->ch_bd->bd_flags &BD_FEP5PLUS )) +return 0 ; -/* -* Set queue water marks, interrupt mask, -* and general tty parameters. -*/ - tlw = ch->ch_tsize >=2000 ? ((ch->ch_tsize *5 ) /8 ) : - ch->ch_tsize /2 ; - ch->ch_tlw = tlw; + vaddr = ch->ch_bd->re_map_membase; -dgap_cmdw (ch,STLOW , tlw,0 ); +if (!vaddr) +return 0 ; -dgap_cmdw (ch,SRLOW , ch->ch_rsize /2 ,0 ); +/* +* Go get from fep mem, what the fep +* believes the custom baud rate is. +*/ + offset = (ioread16 (vaddr +ECS_SEG ) <<4 ) + (ch->ch_portnum *0x28 ) + +LINE_SPEED ; -dgap_cmdw (ch,SRHIGH ,7 * ch->ch_rsize /8 ,0 ); + value =readw (vaddr + offset); +return value; +} - ch->ch_mistat =readb (&(ch->ch_bs->m_stat)); +/* +* Remap PCI memory. +*/ +static int dgap_remap (struct board_t *brd) +{ +if (!brd || brd->magic !=DGAP_BOARD_MAGIC ) +return -EIO ; -init_waitqueue_head (&ch->ch_flags_wait); -init_waitqueue_head (&ch->ch_tun.un_flags_wait); -init_waitqueue_head (&ch->ch_pun.un_flags_wait); +if (!request_mem_region (brd->membase,0x200000 ,"dgap" )) +return -ENOMEM ; -/* Turn on all modem interrupts for now */ - modem = (DM_CD |DM_DSR |DM_CTS |DM_RI ); -writeb (modem, &(ch->ch_bs->m_int)); +if (!request_mem_region (brd->membase +PCI_IO_OFFSET ,0x200000 , +"dgap" )) { +release_mem_region (brd->membase,0x200000 ); +return -ENOMEM ; + } -/* -* Set edelay to 0 if interrupts are turned on, -* otherwise set edelay to the usual 100. -*/ -if (brd->intr_used) -writew (0 , &(ch->ch_bs->edelay)); -else -writew (100 , &(ch->ch_bs->edelay)); + brd->re_map_membase =ioremap (brd->membase,0x200000 ); +if (!brd->re_map_membase) { +release_mem_region (brd->membase,0x200000 ); +release_mem_region (brd->membase +PCI_IO_OFFSET ,0x200000 ); +return -ENOMEM ; + } -writeb (1 , &(ch->ch_bs->idata)); + brd->re_map_port =ioremap ((brd->membase +PCI_IO_OFFSET ),0x200000 ); +if (!brd->re_map_port) { +release_mem_region (brd->membase,0x200000 ); +release_mem_region (brd->membase +PCI_IO_OFFSET ,0x200000 ); +iounmap (brd->re_map_membase); +return -ENOMEM ; }return 0 ; - -free_chan: -while (--i >=0 ) { -kfree (brd->channels[i]); - brd->channels[i] =NULL ; - } -return ret; } -/* -* dgap_tty_free() -* -* Free the channles which are allocated in dgap_tty_init(). -*/ -static void dgap_tty_free (struct board_t *brd) +static void dgap_unmap (struct board_t *brd) { -int i; - -for (i =0 ; i < brd->nasync; i++) -kfree (brd->channels[i]); +iounmap (brd->re_map_port); +iounmap (brd->re_map_membase); +release_mem_region (brd->membase +PCI_IO_OFFSET ,0x200000 ); +release_mem_region (brd->membase,0x200000 ); } +/* -* dgap_cleanup_tty() +* dgap_parity_scan() * -* Uninitialize the TTY portion of this driver. Free all memory and -* resources. +* Convert the FEP5 way of reporting parity errors and breaks into +* the Linux line discipline way. */ -static void dgap_cleanup_tty (struct board_t *brd) +static void dgap_parity_scan (struct channel_t *ch,unsigned char *cbuf, +unsigned char *fbuf,int *len) { -struct device *dev; -int i; +int l = *len; +int count =0 ; +unsigned char *in, *cout, *fout; +unsigned char c; - dgap_boards_by_major[brd->serial_driver->major] =NULL ; - brd->dgap_serial_major =0 ; -for (i =0 ; i < brd->nasync; i++) { -tty_port_destroy (&brd->serial_ports[i]); - dev = brd->channels[i]->ch_tun.un_sysfs; -dgap_remove_tty_sysfs (dev); -tty_unregister_device (brd->serial_driver, i); - } -tty_unregister_driver (brd->serial_driver); -put_tty_driver (brd->serial_driver); -kfree (brd->serial_ports); + in = cbuf; + cout = cbuf; + fout = fbuf; - dgap_boards_by_major[brd->print_driver->major] =NULL ; - brd->dgap_transparent_print_major =0 ; -for (i =0 ; i < brd->nasync; i++) { -tty_port_destroy (&brd->printer_ports[i]); - dev = brd->channels[i]->ch_pun.un_sysfs; -dgap_remove_tty_sysfs (dev); -tty_unregister_device (brd->print_driver, i); +if (!ch || ch->magic !=DGAP_CHANNEL_MAGIC ) +return ; + +while (l--) { + c = *in++; +switch (ch->pscan_state) { +default : +/* reset to sanity and fall through */ + ch->pscan_state =0 ; + +case 0 : +/* No FF seen yet */ +if (c == (unsigned char )'\377' ) +/* delete this character from stream */ + ch->pscan_state =1 ; +else { + *cout++ = c; + *fout++ =TTY_NORMAL ; + count +=1 ; + } +break ; + +case 1 : +/* first FF seen */ +if (c == (unsigned char )'\377' ) { +/* doubled ff, transform to single ff */ + *cout++ = c; + *fout++ =TTY_NORMAL ; + count +=1 ; + ch->pscan_state =0 ; + }else { +/* save value examination in next state */ + ch->pscan_savechar = c; + ch->pscan_state =2 ; + } +break ; + +case 2 : +/* third character of ff sequence */ + + *cout++ = c; + +if (ch->pscan_savechar ==0x0 ) { + +if (c ==0x0 ) { + ch->ch_err_break++; + *fout++ =TTY_BREAK ; + }else { + ch->ch_err_parity++; + *fout++ =TTY_PARITY ; + } + } + + count +=1 ; + ch->pscan_state =0 ; + } } -tty_unregister_driver (brd->print_driver); -put_tty_driver (brd->print_driver); -kfree (brd->printer_ports); + *len = count; }/*=======================================================================
@@ -1750,6 +1718,33 @@ static void dgap_input(struct channel_t *ch) } +static void dgap_write_wakeup (struct board_t *bd,struct channel_t *ch, +struct un_t *un,u32 mask, +unsigned long *irq_flags1, +unsigned long *irq_flags2) +{ +if (!(un->un_flags & mask)) +return ; + + un->un_flags &= ~mask; + +if (!(un->un_flags &UN_ISOPEN )) +return ; + +if ((un->un_tty->flags & (1 <<TTY_DO_WRITE_WAKEUP )) && + un->un_tty->ldisc->ops->write_wakeup) { +spin_unlock_irqrestore (&ch->ch_lock, *irq_flags2); +spin_unlock_irqrestore (&bd->bd_lock, *irq_flags1); + + (un->un_tty->ldisc->ops->write_wakeup)(un->un_tty); + +spin_lock_irqsave (&bd->bd_lock, *irq_flags1); +spin_lock_irqsave (&ch->ch_lock, *irq_flags2); + } +wake_up_interruptible (&un->un_tty->write_wait); +wake_up_interruptible (&un->un_flags_wait); +} +/************************************************************************ * Determines when CARRIER changes state and takes appropriate * action.
@@ -1864,163 +1859,1207 @@ static void dgap_carrier(struct channel_t *ch) ch->ch_flags &= ~CH_CD ; } -/************************************************************************ +/*======================================================================= * -* TTY Entry points and helper functions +* dgap_event - FEP to host event processing routine. * -************************************************************************/ - -/* -* dgap_tty_open() +* bd - Board of current event. * -*/ -static int dgap_tty_open (struct tty_struct *tty,struct file *file) +*=======================================================================*/ +static int dgap_event (struct board_t *bd) { -struct board_t *brd;struct channel_t *ch; -struct un_t *un; -struct bs_t __iomem *bs; -uint major; -uint minor; -int rc;ulong lock_flags;ulong lock_flags2; -u16 head; +struct bs_t __iomem *bs; +u8 __iomem *event; +u8 __iomem *vaddr; +struct ev_t __iomem *eaddr; +uint head; +uint tail; +int port; +int reason; +int modem; +int b1; - major =MAJOR (tty_devnum (tty)); - minor =MINOR (tty_devnum (tty)); +if (!bd || bd->magic !=DGAP_BOARD_MAGIC ) +return -EIO ; -if (major >255 ) +spin_lock_irqsave (&bd->bd_lock, lock_flags); + + vaddr = bd->re_map_membase; + +if (!vaddr) { +spin_unlock_irqrestore (&bd->bd_lock, lock_flags);return -EIO ; + } -/* Get board pointer from our array of majors we have allocated */ - brd = dgap_boards_by_major[major]; -if (!brd) + eaddr = (struct ev_t __iomem *) (vaddr +EVBUF ); + +/* Get our head and tail */ + head =readw (&(eaddr->ev_head)); + tail =readw (&(eaddr->ev_tail)); + +/* +* Forget it if pointers out of range. +*/ + +if (head >=EVMAX -EVSTART || tail >=EVMAX -EVSTART || + (head | tail) &03 ) { +/* Let go of board lock */ +spin_unlock_irqrestore (&bd->bd_lock, lock_flags);return -EIO ; + }/* -* If board is not yet up to a state of READY, go to -* sleep waiting for it to happen or they cancel the open. +* Loop to process all the events in the buffer. */ - rc =wait_event_interruptible (brd->state_wait, - (brd->state &BOARD_READY )); +while (tail != head) { -if (rc) -return rc; +/* +* Get interrupt information. +*/ -spin_lock_irqsave (&brd->bd_lock, lock_flags); + event = bd->re_map_membase + tail +EVSTART ; -/* The wait above should guarantee this cannot happen */ -if (brd->state !=BOARD_READY ) { -spin_unlock_irqrestore (&brd->bd_lock, lock_flags); -return -EIO ; + port =ioread8 (event); + reason =ioread8 (event +1 ); + modem =ioread8 (event +2 ); + b1 =ioread8 (event +3 ); + +/* +* Make sure the interrupt is valid. +*/ +if (port >= bd->nasync) + goto next; + +if (!(reason & (IFMODEM |IFBREAK |IFTLW |IFTEM |IFDATA ))) + goto next; + + ch = bd->channels[port]; + +if (!ch || ch->magic !=DGAP_CHANNEL_MAGIC ) + goto next; + +/* +* If we have made it here, the event was valid. +* Lock down the channel. +*/ +spin_lock_irqsave (&ch->ch_lock, lock_flags2); + + bs = ch->ch_bs; + +if (!bs) { +spin_unlock_irqrestore (&ch->ch_lock, lock_flags2); + goto next; + } + +/* +* Process received data. +*/ +if (reason &IFDATA ) { + +/* +* ALL LOCKS *MUST* BE DROPPED BEFORE CALLING INPUT! +* input could send some data to ld, which in turn +* could do a callback to one of our other functions. +*/ +spin_unlock_irqrestore (&ch->ch_lock, lock_flags2); +spin_unlock_irqrestore (&bd->bd_lock, lock_flags); + +dgap_input (ch); + +spin_lock_irqsave (&bd->bd_lock, lock_flags); +spin_lock_irqsave (&ch->ch_lock, lock_flags2); + +if (ch->ch_flags &CH_RACTIVE ) + ch->ch_flags |=CH_RENABLE ; +else +writeb (1 , &(bs->idata)); + +if (ch->ch_flags &CH_RWAIT ) { + ch->ch_flags &= ~CH_RWAIT ; + +wake_up_interruptible + (&ch->ch_tun.un_flags_wait); + } + } + +/* +* Process Modem change signals. +*/ +if (reason &IFMODEM ) { + ch->ch_mistat = modem; +dgap_carrier (ch); + } + +/* +* Process break. +*/ +if (reason &IFBREAK ) { + +if (ch->ch_tun.un_tty) { +/* A break has been indicated */ + ch->ch_err_break++; +tty_buffer_request_room + (ch->ch_tun.un_tty->port,1 ); +tty_insert_flip_char (ch->ch_tun.un_tty->port, +0 ,TTY_BREAK ); +tty_flip_buffer_push (ch->ch_tun.un_tty->port); + } + } + +/* +* Process Transmit low. +*/ +if (reason &IFTLW ) { +dgap_write_wakeup (bd, ch, &ch->ch_tun,UN_LOW , + &lock_flags, &lock_flags2); +dgap_write_wakeup (bd, ch, &ch->ch_pun,UN_LOW , + &lock_flags, &lock_flags2); +if (ch->ch_flags &CH_WLOW ) { + ch->ch_flags &= ~CH_WLOW ; +wake_up_interruptible (&ch->ch_flags_wait); + } + } + +/* +* Process Transmit empty. +*/ +if (reason &IFTEM ) { +dgap_write_wakeup (bd, ch, &ch->ch_tun,UN_EMPTY , + &lock_flags, &lock_flags2); +dgap_write_wakeup (bd, ch, &ch->ch_pun,UN_EMPTY , + &lock_flags, &lock_flags2); +if (ch->ch_flags &CH_WEMPTY ) { + ch->ch_flags &= ~CH_WEMPTY ; +wake_up_interruptible (&ch->ch_flags_wait); + } + } + +spin_unlock_irqrestore (&ch->ch_lock, lock_flags2); + +next: + tail = (tail +4 ) & (EVMAX -EVSTART -4 ); } -/* If opened device is greater than our number of ports, bail. */ -if (MINOR (tty_devnum (tty)) > brd->nasync) { -spin_unlock_irqrestore (&brd->bd_lock, lock_flags); -return -EIO ; +writew (tail, &(eaddr->ev_tail)); +spin_unlock_irqrestore (&bd->bd_lock, lock_flags); + +return 0 ; +} + +/* +* Our board poller function. +*/ +static void dgap_poll_tasklet (unsigned long data) +{ +struct board_t *bd = (struct board_t *) data; +ulong lock_flags; +char __iomem *vaddr; +u16 head, tail; + +if (!bd || (bd->magic !=DGAP_BOARD_MAGIC )) +return ; + +if (bd->inhibit_poller) +return ; + +spin_lock_irqsave (&bd->bd_lock, lock_flags); + + vaddr = bd->re_map_membase; + +/* +* If board is ready, parse deeper to see if there is anything to do. +*/ +if (bd->state ==BOARD_READY ) { + +struct ev_t __iomem *eaddr; + +if (!bd->re_map_membase) { +spin_unlock_irqrestore (&bd->bd_lock, lock_flags); +return ; + } +if (!bd->re_map_port) { +spin_unlock_irqrestore (&bd->bd_lock, lock_flags); +return ; + } + +if (!bd->nasync) + goto out; + + eaddr = (struct ev_t __iomem *) (vaddr +EVBUF ); + +/* Get our head and tail */ + head =readw (&(eaddr->ev_head)); + tail =readw (&(eaddr->ev_tail)); + +/* +* If there is an event pending. Go service it. +*/ +if (head != tail) { +spin_unlock_irqrestore (&bd->bd_lock, lock_flags); +dgap_event (bd); +spin_lock_irqsave (&bd->bd_lock, lock_flags); + } + +out: +/* +* If board is doing interrupts, ACK the interrupt. +*/ +if (bd && bd->intr_running) +readb (bd->re_map_port +2 ); + +spin_unlock_irqrestore (&bd->bd_lock, lock_flags); +return ; } - ch = brd->channels[minor]; -if (!ch) { -spin_unlock_irqrestore (&brd->bd_lock, lock_flags); -return -EIO ; +spin_unlock_irqrestore (&bd->bd_lock, lock_flags); +} + +/* +* dgap_found_board() +* +* A board has been found, init it. +*/ +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 ERR_PTR (-ENOMEM ); + +/* store the info for the board we've found */ + brd->magic =DGAP_BOARD_MAGIC ; + brd->boardnum = boardnum; + brd->vendor = dgap_pci_tbl[id].vendor; + brd->device = dgap_pci_tbl[id].device; + brd->pdev = pdev; + brd->pci_bus = pdev->bus->number; + brd->pci_slot =PCI_SLOT (pdev->devfn); + brd->name = dgap_ids[id].name; + brd->maxports = dgap_ids[id].maxports; + brd->type = dgap_ids[id].config_type; + brd->dpatype = dgap_ids[id].dpatype; + brd->dpastatus =BD_NOFEP ; +init_waitqueue_head (&brd->state_wait); + +spin_lock_init (&brd->bd_lock); + + brd->inhibit_poller = FALSE; + brd->wait_for_bios =0 ; + brd->wait_for_fep =0 ; + +for (i =0 ; i <MAXPORTS ; i++) + brd->channels[i] =NULL ; + +/* store which card & revision we have */ +pci_read_config_word (pdev,PCI_SUBSYSTEM_VENDOR_ID , &brd->subvendor); +pci_read_config_word (pdev,PCI_SUBSYSTEM_ID , &brd->subdevice); +pci_read_config_byte (pdev,PCI_REVISION_ID , &brd->rev); + + pci_irq = pdev->irq; + brd->irq = pci_irq; + +/* get the PCI Base Address Registers */ + +/* Xr Jupiter and EPC use BAR 2 */ +if (brd->device ==PCI_DEV_XRJ_DID || brd->device ==PCI_DEV_EPCJ_DID ) { + brd->membase =pci_resource_start (pdev,2 ); + brd->membase_end =pci_resource_end (pdev,2 ); + } +/* Everyone else uses BAR 0 */ +else { + brd->membase =pci_resource_start (pdev,0 ); + brd->membase_end =pci_resource_end (pdev,0 ); } -/* Grab channel lock */ -spin_lock_irqsave (&ch->ch_lock, lock_flags2); +if (!brd->membase) { + ret = -ENODEV ; + goto free_brd; + } -/* Figure out our type */ -if (major == brd->dgap_serial_major) { - un = &brd->channels[minor]->ch_tun; - un->un_type =DGAP_SERIAL ; - }else if (major == brd->dgap_transparent_print_major) { - un = &brd->channels[minor]->ch_pun; - un->un_type =DGAP_PRINT ; +if (brd->membase &1 ) + brd->membase &= ~3 ; +else + brd->membase &= ~15 ; + +/* +* On the PCI boards, there is no IO space allocated +* The I/O registers will be in the first 3 bytes of the +* upper 2MB of the 4MB memory space. The board memory +* will be mapped into the low 2MB of the 4MB memory space +*/ + brd->port = brd->membase +PCI_IO_OFFSET ; + brd->port_end = brd->port +PCI_IO_SIZE ; + +/* +* Special initialization for non-PLX boards +*/ +if (brd->device !=PCI_DEV_XRJ_DID && brd->device !=PCI_DEV_EPCJ_DID ) { +unsigned short cmd; + +pci_write_config_byte (pdev,0x40 ,0 ); +pci_write_config_byte (pdev,0x46 ,0 ); + +/* Limit burst length to 2 doubleword transactions */ +pci_write_config_byte (pdev,0x42 ,1 ); + +/* +* Enable IO and mem if not already done. +* This was needed for support on Itanium. +*/ +pci_read_config_word (pdev,PCI_COMMAND , &cmd); + cmd |= (PCI_COMMAND_IO |PCI_COMMAND_MEMORY ); +pci_write_config_word (pdev,PCI_COMMAND , cmd); + } + +/* init our poll helper tasklet */ +tasklet_init (&brd->helper_tasklet, dgap_poll_tasklet, + (unsigned long ) brd); + + ret =dgap_remap (brd); +if (ret) + goto free_brd; + +pr_info ("dgap: board %d: %s (rev %d), irq %ld\n" , + boardnum, brd->name, brd->rev, brd->irq); + +return brd; + +free_brd: +kfree (brd); + +return ERR_PTR (ret); +} + +/* +* dgap_intr() +* +* Driver interrupt handler. +*/ +static irqreturn_t dgap_intr (int irq,void *voidbrd) +{ +struct board_t *brd = (struct board_t *) voidbrd; + +if (!brd) +return IRQ_NONE ; + +/* +* Check to make sure its for us. +*/ +if (brd->magic !=DGAP_BOARD_MAGIC ) +return IRQ_NONE ; + + brd->intr_count++; + +/* +* Schedule tasklet to run at a better time. +*/ +tasklet_schedule (&brd->helper_tasklet); +return IRQ_HANDLED ; +} + +/***************************************************************************** +* +* Function: +* +* dgap_poll_handler +* +* Author: +* +* Scott H Kilau +* +* Parameters: +* +* dummy -- ignored +* +* Return Values: +* +* none +* +* Description: +* +* As each timer expires, it determines (a) whether the "transmit" +* waiter needs to be woken up, and (b) whether the poller needs to +* be rescheduled. +* +******************************************************************************/ + +static void dgap_poll_handler (ulong dummy) +{ +int i; +struct board_t *brd; +unsigned long lock_flags; +ulong new_time; + + dgap_poll_counter++; + +/* +* Do not start the board state machine until +* driver tells us its up and running, and has +* everything it needs. +*/ +if (dgap_driver_state !=DRIVER_READY ) + goto schedule_poller; + +/* +* If we have just 1 board, or the system is not SMP, +* then use the typical old style poller. +* Otherwise, use our new tasklet based poller, which should +* speed things up for multiple boards. +*/ +if ((dgap_numboards ==1 ) || (num_online_cpus () <=1 )) { +for (i =0 ; i < dgap_numboards; i++) { + + brd = dgap_board[i]; + +if (brd->state ==BOARD_FAILED ) +continue ; +if (!brd->intr_running) +/* Call the real board poller directly */ +dgap_poll_tasklet ((unsigned long ) brd); + } }else { -spin_unlock_irqrestore (&ch->ch_lock, lock_flags2); -spin_unlock_irqrestore (&brd->bd_lock, lock_flags); -return -EIO ; +/* +* Go thru each board, kicking off a +* tasklet for each if needed +*/ +for (i =0 ; i < dgap_numboards; i++) { + brd = dgap_board[i]; + +/* +* Attempt to grab the board lock. +* +* If we can't get it, no big deal, the next poll +* will get it. Basically, I just really don't want +* to spin in here, because I want to kick off my +* tasklets as fast as I can, and then get out the +* poller. +*/ +if (!spin_trylock (&brd->bd_lock)) +continue ; + +/* +* If board is in a failed state, don't bother +* scheduling a tasklet +*/ +if (brd->state ==BOARD_FAILED ) { +spin_unlock (&brd->bd_lock); +continue ; + } + +/* Schedule a poll helper task */ +if (!brd->intr_running) +tasklet_schedule (&brd->helper_tasklet); + +/* +* Can't do DGAP_UNLOCK here, as we don't have +* lock_flags because we did a trylock above. +*/ +spin_unlock (&brd->bd_lock); + } } -/* Store our unit into driver_data, so we always have it available. */ - tty->driver_data = un; +schedule_poller:/* -* Error if channel info pointer is NULL. +* Schedule ourself back at the nominal wakeup interval. */ - bs = ch->ch_bs; -if (!bs) { -spin_unlock_irqrestore (&ch->ch_lock, lock_flags2); -spin_unlock_irqrestore (&brd->bd_lock, lock_flags); -return -EIO ; +spin_lock_irqsave (&dgap_poll_lock, lock_flags); + dgap_poll_time +=dgap_jiffies_from_ms (dgap_poll_tick); + + new_time = dgap_poll_time - jiffies; + +if ((ulong ) new_time >=2 * dgap_poll_tick) { + dgap_poll_time = + jiffies +dgap_jiffies_from_ms (dgap_poll_tick); } + dgap_poll_timer.function = dgap_poll_handler; + dgap_poll_timer.data =0 ; + dgap_poll_timer.expires = dgap_poll_time; +spin_unlock_irqrestore (&dgap_poll_lock, lock_flags); + +if (!dgap_poll_stop) +add_timer (&dgap_poll_timer); +} + +/*======================================================================= +* +* dgap_cmdb - Sends a 2 byte command to the FEP. +* +* ch - Pointer to channel structure. +* cmd - Command to be sent. +* byte1 - Integer containing first byte to be sent. +* byte2 - Integer containing second byte to be sent. +* ncmds - Wait until ncmds or fewer cmds are left +* in the cmd buffer before returning. +* +*=======================================================================*/ +static void dgap_cmdb (struct channel_t *ch,u8 cmd,u8 byte1, +u8 byte2,uint ncmds) +{ +char __iomem *vaddr; +struct __iomem cm_t *cm_addr; +uint count; +uint n; +u16 head; +u16 tail; + +if (!ch || ch->magic !=DGAP_CHANNEL_MAGIC ) +return ; +/* -* Initialize tty's +* Check if board is still alive. */ -if (!(un->un_flags &UN_ISOPEN )) { -/* Store important variables. */ - un->un_tty = tty; +if (ch->ch_bd->state ==BOARD_FAILED ) +return ; -/* Maybe do something here to the TTY struct as well? */ +/* +* Make sure the pointers are in range before +* writing to the FEP memory. +*/ + vaddr = ch->ch_bd->re_map_membase; + +if (!vaddr) +return ; + + cm_addr = (struct cm_t __iomem *) (vaddr +CMDBUF ); + head =readw (&(cm_addr->cm_head)); + +/* +* Forget it if pointers out of range. +*/ +if (head >= (CMDMAX -CMDSTART ) || (head &03 )) { + ch->ch_bd->state =BOARD_FAILED ; +return ; }/* -* Initialize if neither terminal or printer is open. +* Put the data in the circular command buffer. */ -if (!((ch->ch_tun.un_flags | ch->ch_pun.un_flags) &UN_ISOPEN )) { +writeb (cmd, (vaddr + head +CMDSTART +0 )); +writeb ((u8 ) ch->ch_portnum, (vaddr + head +CMDSTART +1 )); +writeb (byte1, (vaddr + head +CMDSTART +2 )); +writeb (byte2, (vaddr + head +CMDSTART +3 )); - ch->ch_mforce =0 ; - ch->ch_mval =0 ; + head = (head +4 ) & (CMDMAX -CMDSTART -4 ); + +writew (head, &(cm_addr->cm_head)); + +/* +* Wait if necessary before updating the head +* pointer to limit the number of outstanding +* commands to the FEP. If the time spent waiting +* is outlandish, declare the FEP dead. +*/
Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
Signature · 1 line
1.7.1
Part of the diff is not shown here. View the raw message.
Greg KH
maintainerQuoted 6 lines · Daeseok Youn
Re-arrange the functions for removing forward declarations.
Signed-off-by Daeseok Youn <[email protected]>---
This patch has too many changes for re-arranging the functions. So I wonder that I should break this up into smaller patches.
Are the .o files identical before and after this patch? If so, it's fine.
thanks,
greg k-h
Hi,
2014-10-13 12:25 GMT+09:00 Greg KH <[email protected]>:
Quoted 10 lines · Daeseok Youn
Quoted 6 lines
Re-arrange the functions for removing forward declarations.
Signed-off-by Daeseok Youn <[email protected]>---
This patch has too many changes for re-arranging the functions. So I wonder that I should break this up into smaller patches.Are the .o files identical before and after this patch? If so, it's fine.
Ok. I will check for that.
Thanks.
regards,
Daeseok Youn.
Quoted 4 lines
thanks,
greg k-h
Quoted 6 lines · DaeSeok Youn
Hi,
2014-10-13 12:25 GMT+09:00 Greg KH <[email protected]>:
Quoted 3 lines · Daeseok Youn
Quoted 2 lines
Re-arrange the functions for removing forward declarations.
Quoted 8 lines
Quoted 7 lines
Quoted 4 lines
Signed-off-by Daeseok Youn <[email protected]>---
This patch has too many changes for re-arranging the functions. So I wonder that I should break this up into smaller patches.Are the .o files identical before and after this patch? If so, it's fine.
Ok. I will check for that.
The .o files shouldn't be identical after function reordering.
Hi,
2014-10-13 23:56 GMT+09:00 Joe Perches <[email protected]>:
Quoted 12 lines · DaeSeok Youn
Quoted 11 lines
Hi,
2014-10-13 12:25 GMT+09:00 Greg KH <[email protected]>:
Quoted 8 lines · Daeseok Youn
Quoted 6 lines
Re-arrange the functions for removing forward declarations.
Signed-off-by Daeseok Youn <[email protected]>---
This patch has too many changes for re-arranging the functions. So I wonder that I should break this up into smaller patches.
Quoted 6 lines
Quoted 3 lines
Quoted 2 lines
Are the .o files identical before and after this patch? If so, it's fine.
Ok. I will check for that.
The .o files shouldn't be identical after function reordering.
Is it possible to sort "objdump -d" output by function name? I'm not sure but it can be checked after sorting.
I think greg want to know missing functions in this patch because this has many changes.
thanks.
regards,
Daeseok Youn.
Greg KH
maintainerQuoted 12 lines · Joe Perches
Quoted 11 lines · DaeSeok Youn
Hi,
2014-10-13 12:25 GMT+09:00 Greg KH <[email protected]>:
Quoted 8 lines · Daeseok Youn
Quoted 6 lines
Re-arrange the functions for removing forward declarations.
Signed-off-by Daeseok Youn <[email protected]>---
This patch has too many changes for re-arranging the functions. So I wonder that I should break this up into smaller patches.
Quoted 5 lines
Quoted 3 lines
Quoted 2 lines
Are the .o files identical before and after this patch? If so, it's fine.
Ok. I will check for that.
The .o files shouldn't be identical after function reordering.
Hm, they might be the same size, but I can see how on some architectures (like ppc) how that would not be the case, you are right.
Isn't there an "objdiff" program or something like that which might help in validating that nothing "changed" in the source for type of patch that just moves functions around in a file.
thanks,
greg k-h
Quoted 5 lines · Greg KH
Quoted 4 lines · Joe Perches
Quoted 3 lines · DaeSeok Youn
2014-10-13 12:25 GMT+09:00 Greg KH <[email protected]>:
Quoted 2 lines · Daeseok Youn
Quoted 1 line
Re-arrange the functions for removing forward declarations.
[]
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 4 lines
Quoted 2 lines
This patch has too many changes for re-arranging the functions. So I wonder that I should break this up into smaller patches.
Are the .o files identical before and after this patch? If so, it's fine.
Ok. I will check for that.
Quoted 8 lines
Quoted 1 line
The .o files shouldn't be identical after function reordering.
Hm, they might be the same size, but I can see how on some architectures (like ppc) how that would not be the case, you are right.
Isn't there an "objdiff" program or something like that which might help in validating that nothing "changed" in the source for type of patch that just moves functions around in a file.
There is a scripts/objdiff, but that is basically for whitespace only changes.
I don't know of a way to compare objects when functions are rearranged in the source file.
Anyone else?
Hi,
2014-10-14 11:19 GMT+09:00 Joe Perches <[email protected]>:
Quoted 21 lines · Greg KH
Quoted 5 lines · Joe Perches
Quoted 4 lines · DaeSeok Youn
Quoted 3 lines
2014-10-13 12:25 GMT+09:00 Greg KH <[email protected]>:
Quoted 2 lines · Daeseok Youn
Quoted 1 line
Re-arrange the functions for removing forward declarations.
[]
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 4 lines
Quoted 2 lines
This patch has too many changes for re-arranging the functions. So I wonder that I should break this up into smaller patches.
Are the .o files identical before and after this patch? If so, it's fine.
Ok. I will check for that.
Quoted 8 lines
Quoted 1 line
The .o files shouldn't be identical after function reordering.
Hm, they might be the same size, but I can see how on some architectures (like ppc) how that would not be the case, you are right.
Isn't there an "objdiff" program or something like that which might help in validating that nothing "changed" in the source for type of patch that just moves functions around in a file.
Quoted 8 lines
There is a
scripts/objdiff, but that is basically for whitespace only changes.I don't know of a way to compare objects when functions are rearranged in the source file.
Anyone else?
I was just trying to sort "objdump -d" output by function name with someone's python script.
The script was on github. url : https://gist.github.com/fritschy/1183292
And I got two results, one is before applying this patch, another is after doing that.
These are possible to compare but it has difference of base address...
I'm not sure what should I do for applying this patch. :-( If anyone knows how to compare, let me know.
Thanks.
Regards,
Daeseok Youn.
Quoted 4 lines · Joe Perches
I don't know of a way to compare objects when functions are rearranged in the source file.
Anyone else?
I have a perl script that I use to review function movement. It barfed on the DaeSeok's original patch so I re-wrote it, but it's still not great.
Anyway, attached.
regards,
dan carpenter
#!/usr/bin/perl
use strict;
use File::Temp qw/ tempdir /;
use File::Path qw/ rmtree /;
use File::Compare;
sub filter($) {
my $_ = shift();
# remove the first char
s/^[ +-]//;
return $_;
}sub break_out_blocks($)
{
my $dir = shift();
my $block_nr = 0;
open FILE, "<", "$dir/full";
open OUT, ">", "$dir/$block_nr";
while (<FILE>) {
if ($block_nr && $_ =~ /^}/) {
print OUT $_;
close(OUT);
$block_nr++;
open OUT, ">", "$dir/$block_nr";
next;
}
if ($_ =~ /^{/ || ($_ =~ /^[a-zA-Z]/ && $_ =~ / {$/)) {
close(OUT);
$block_nr++;
open OUT, ">", "$dir/$block_nr";
}
print OUT $_;
}
close(OUT);
}sub files_same($$)
{
my $one = shift();
my $two = shift();
my $size_one = (stat($one))[7];
my $size_two = (stat($two))[7];
if ($size_one != $size_two) {
return 0;
}
return compare($one, $two) == 0;
}sub is_block($)
{
my $file = shift();
open LINE, "<", "$file";
my $line = <LINE>;
if ($line =~ /^{/ || ($line =~ /^[a-zA-Z]/ && $line =~ / {$/)) {
return 1;
}
return 0;
}sub replace_exact_blocks($$) {
my $olddir = shift();
my $newdir = shift();
my $i = -1;
while (1) {
$i++;
if (! -e "$olddir/$i") {
last;
}
if (!is_block("$olddir/$i")) {
next;
}
my $j = -1;
while (1) {
$j++;
if (! -e "$newdir/$j") {
last;
}
if (files_same("$olddir/$i", "$newdir/$j")) {
open OUT, ">", "$olddir/$i";
print OUT "- MOVED {$i}\n";
close OUT;
open OUT, ">", "$newdir/$j";
print OUT "+ MOVED {$j}\n";
close OUT;
last;
}
}
}
}sub merge_blocks($) {
my $dir = shift();
open MERGED, ">", "$dir/merged";
my $i = -1;
while (1) {
$i++;
if (! -e "$dir/$i") {
last;
}
open FILE, "<", "$dir/$i";
while (<FILE>) {
print MERGED $_;
}
close(FILE);
}
close(MERGED);
}sub show_diff($$) {
my $olddir = shift();
my $newdir = shift();
open diff, "diff -uw $olddir/merged $newdir/merged |";
while (<diff>) {
print $_;
}
}my $output;
my $inside = 0;
my $olddir = tempdir();
my $newdir = tempdir();
open oldfh, ">", "$olddir/full";
open newfh, ">", "$newdir/full";
#recreate an old file and a new file
while (<>) {
if ($_ =~ /^(---|\+\+\+)/) {
next;
}
if ($_ =~ /^@/) {
$inside = 1;
}
if ($inside && !(($_ =~ /^[- @+]/) || ($_ =~ /^$/))) {
$inside = 0;
}
if (!$inside) {
next;
}
$output = filter($_);
if ($_ =~ /^-/) {
print oldfh $output;
next;
}
if ($_ =~ /^\+/) {
print newfh $output;
next;
}
print oldfh $output;
print newfh $output;}
close(oldfh);
close(newfh);
break_out_blocks($olddir);break_out_blocks($newdir);
replace_exact_blocks($olddir, $newdir);
merge_blocks($olddir);merge_blocks($newdir);
show_diff($olddir, $newdir);
#print "old = $olddir/ new = $newdir/\n";
rmtree($olddir);
rmtree($newdir);
A message that is not in the archive (sent off-list or not yet received): [email protected]
Quoted 19 lines · Greg KH
Quoted 12 lines · Joe Perches
Quoted 11 lines · DaeSeok Youn
Hi,
2014-10-13 12:25 GMT+09:00 Greg KH <[email protected]>:
Quoted 8 lines · Daeseok Youn
Quoted 6 lines
Re-arrange the functions for removing forward declarations.
Signed-off-by Daeseok Youn <[email protected]>---
This patch has too many changes for re-arranging the functions. So I wonder that I should break this up into smaller patches.Quoted 5 lines
Quoted 3 lines
Quoted 2 lines
Are the .o files identical before and after this patch? If so, it's fine.
Ok. I will check for that.
The .o files shouldn't be identical after function reordering.
Quoted 9 lines
Hm, they might be the same size, but I can see how on some architectures (like ppc) how that would not be the case, you are right.
Isn't there an "objdiff" program or something like that which might help in validating that nothing "changed" in the source for type of patch that just moves functions around in a file.
thanks,
Greg,
Would just testing the thing be of any help?
Regards
Mark
A message that is not in the archive (sent off-list or not yet received): [email protected]
Mark Hounschell
Tested-byQuoted 30 lines · Mark Hounschell
Quoted 19 lines · Greg KH
Quoted 12 lines · Joe Perches
Quoted 11 lines · DaeSeok Youn
Hi,
2014-10-13 12:25 GMT+09:00 Greg KH <[email protected]>:
Quoted 8 lines · Daeseok Youn
Quoted 6 lines
Re-arrange the functions for removing forward declarations.
Signed-off-by Daeseok Youn <[email protected]>---
This patch has too many changes for re-arranging the functions. So I wonder that I should break this up into smaller patches.Quoted 5 lines
Quoted 3 lines
Quoted 2 lines
Are the .o files identical before and after this patch? If so, it's fine.
Ok. I will check for that.
The .o files shouldn't be identical after function reordering.
Quoted 9 lines
Hm, they might be the same size, but I can see how on some architectures (like ppc) how that would not be the case, you are right.
Isn't there an "objdiff" program or something like that which might help in validating that nothing "changed" in the source for type of patch that just moves functions around in a file.
thanks,
Quoted 6 lines
Greg,
Would just testing the thing be of any help?
Regards
Mark
I don't know what is going on with this patch, but for what it's worth, I have applied this patch and my testing still shows everything OK.
Regards
Mark