提交 dd025c0c 编写于 作者: J Jiri Slaby 提交者: Linus Torvalds

Char: cyclades, dynamic ports

and save thus approx. 160k of .bss
Signed-off-by: NJiri Slaby <jirislaby@gmail.com>
Signed-off-by: NAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
上级 f2462bfe
...@@ -722,11 +722,6 @@ module_param_array(irq, int, NULL, 0); ...@@ -722,11 +722,6 @@ module_param_array(irq, int, NULL, 0);
*/ */
static struct cyclades_card cy_card[NR_CARDS]; static struct cyclades_card cy_card[NR_CARDS];
/* This is the per-channel data structure containing pointers, flags
and variables for the port. This driver supports a maximum of NR_PORTS.
*/
static struct cyclades_port cy_port[NR_PORTS];
static int cy_next_channel; /* next minor available */ static int cy_next_channel; /* next minor available */
/* /*
...@@ -855,13 +850,6 @@ static inline int serial_paranoia_check(struct cyclades_port *info, ...@@ -855,13 +850,6 @@ static inline int serial_paranoia_check(struct cyclades_port *info,
return 1; return 1;
} }
if ((long)info < (long)(&cy_port[0]) ||
(long)(&cy_port[NR_PORTS]) < (long)info) {
printk(KERN_WARNING "cyc Warning: cyclades_port out of range "
"for (%s) in %s\n", name, routine);
return 1;
}
if (info->magic != CYCLADES_MAGIC) { if (info->magic != CYCLADES_MAGIC) {
printk(KERN_WARNING "cyc Warning: bad magic number for serial " printk(KERN_WARNING "cyc Warning: bad magic number for serial "
"struct (%s) in %s\n", name, routine); "struct (%s) in %s\n", name, routine);
...@@ -1025,7 +1013,7 @@ static void cyy_intr_chip(struct cyclades_card *cinfo, int chip, ...@@ -1025,7 +1013,7 @@ static void cyy_intr_chip(struct cyclades_card *cinfo, int chip,
struct cyclades_port *info; struct cyclades_port *info;
struct tty_struct *tty; struct tty_struct *tty;
int char_count; int char_count;
int i, j, len, mdm_change, mdm_status, outch; int j, len, mdm_change, mdm_status, outch;
int save_xir, channel, save_car; int save_xir, channel, save_car;
char data; char data;
...@@ -1037,8 +1025,7 @@ static void cyy_intr_chip(struct cyclades_card *cinfo, int chip, ...@@ -1037,8 +1025,7 @@ static void cyy_intr_chip(struct cyclades_card *cinfo, int chip,
spin_lock(&cinfo->card_lock); spin_lock(&cinfo->card_lock);
save_xir = (u_char) readb(base_addr + (CyRIR << index)); save_xir = (u_char) readb(base_addr + (CyRIR << index));
channel = (u_short) (save_xir & CyIRChannel); channel = (u_short) (save_xir & CyIRChannel);
i = channel + chip * 4 + cinfo->first_line; info = &cinfo->ports[channel + chip * 4];
info = &cy_port[i];
save_car = readb(base_addr + (CyCAR << index)); save_car = readb(base_addr + (CyCAR << index));
cy_writeb(base_addr + (CyCAR << index), save_xir); cy_writeb(base_addr + (CyCAR << index), save_xir);
...@@ -1202,18 +1189,17 @@ static void cyy_intr_chip(struct cyclades_card *cinfo, int chip, ...@@ -1202,18 +1189,17 @@ static void cyy_intr_chip(struct cyclades_card *cinfo, int chip,
spin_lock(&cinfo->card_lock); spin_lock(&cinfo->card_lock);
save_xir = (u_char) readb(base_addr + (CyTIR << index)); save_xir = (u_char) readb(base_addr + (CyTIR << index));
channel = (u_short) (save_xir & CyIRChannel); channel = (u_short) (save_xir & CyIRChannel);
i = channel + chip * 4 + cinfo->first_line;
save_car = readb(base_addr + (CyCAR << index)); save_car = readb(base_addr + (CyCAR << index));
cy_writeb(base_addr + (CyCAR << index), save_xir); cy_writeb(base_addr + (CyCAR << index), save_xir);
/* validate the port# (as configured and open) */ /* validate the port# (as configured and open) */
if ((i < 0) || (NR_PORTS <= i)) { if (channel + chip * 4 >= cinfo->nports) {
cy_writeb(base_addr + (CySRER << index), cy_writeb(base_addr + (CySRER << index),
readb(base_addr + (CySRER << index)) & readb(base_addr + (CySRER << index)) &
~CyTxRdy); ~CyTxRdy);
goto txend; goto txend;
} }
info = &cy_port[i]; info = &cinfo->ports[channel + chip * 4];
if (info->tty == NULL) { if (info->tty == NULL) {
cy_writeb(base_addr + (CySRER << index), cy_writeb(base_addr + (CySRER << index),
readb(base_addr + (CySRER << index)) & readb(base_addr + (CySRER << index)) &
...@@ -1325,7 +1311,7 @@ static void cyy_intr_chip(struct cyclades_card *cinfo, int chip, ...@@ -1325,7 +1311,7 @@ static void cyy_intr_chip(struct cyclades_card *cinfo, int chip,
spin_lock(&cinfo->card_lock); spin_lock(&cinfo->card_lock);
save_xir = (u_char) readb(base_addr + (CyMIR << index)); save_xir = (u_char) readb(base_addr + (CyMIR << index));
channel = (u_short) (save_xir & CyIRChannel); channel = (u_short) (save_xir & CyIRChannel);
info = &cy_port[channel + chip * 4 + cinfo->first_line]; info = &cinfo->ports[channel + chip * 4];
save_car = readb(base_addr + (CyCAR << index)); save_car = readb(base_addr + (CyCAR << index));
cy_writeb(base_addr + (CyCAR << index), save_xir); cy_writeb(base_addr + (CyCAR << index), save_xir);
...@@ -1726,7 +1712,7 @@ static void cyz_handle_cmd(struct cyclades_card *cinfo) ...@@ -1726,7 +1712,7 @@ static void cyz_handle_cmd(struct cyclades_card *cinfo)
while (cyz_fetch_msg(cinfo, &channel, &cmd, &param) == 1) { while (cyz_fetch_msg(cinfo, &channel, &cmd, &param) == 1) {
special_count = 0; special_count = 0;
delta_count = 0; delta_count = 0;
info = &cy_port[channel + cinfo->first_line]; info = &cinfo->ports[channel];
if ((tty = info->tty) == NULL) if ((tty = info->tty) == NULL)
continue; continue;
...@@ -1896,7 +1882,7 @@ static void cyz_poll(unsigned long arg) ...@@ -1896,7 +1882,7 @@ static void cyz_poll(unsigned long arg)
cyz_handle_cmd(cinfo); cyz_handle_cmd(cinfo);
for (port = 0; port < cinfo->nports; port++) { for (port = 0; port < cinfo->nports; port++) {
info = &cy_port[port + cinfo->first_line]; info = &cinfo->ports[port];
tty = info->tty; tty = info->tty;
ch_ctrl = &(zfw_ctrl->ch_ctrl[port]); ch_ctrl = &(zfw_ctrl->ch_ctrl[port]);
buf_ctrl = &(zfw_ctrl->buf_ctrl[port]); buf_ctrl = &(zfw_ctrl->buf_ctrl[port]);
...@@ -2468,13 +2454,20 @@ block_til_ready(struct tty_struct *tty, struct file *filp, ...@@ -2468,13 +2454,20 @@ block_til_ready(struct tty_struct *tty, struct file *filp,
static int cy_open(struct tty_struct *tty, struct file *filp) static int cy_open(struct tty_struct *tty, struct file *filp)
{ {
struct cyclades_port *info; struct cyclades_port *info;
unsigned int i;
int retval, line; int retval, line;
line = tty->index; line = tty->index;
if ((line < 0) || (NR_PORTS <= line)) { if ((line < 0) || (NR_PORTS <= line)) {
return -ENODEV; return -ENODEV;
} }
info = &cy_port[line]; for (i = 0; i < NR_CARDS; i++)
if (line < cy_card[i].first_line + cy_card[i].nports &&
line >= cy_card[i].first_line)
break;
if (i >= NR_CARDS)
return -ENODEV;
info = &cy_card[i].ports[line - cy_card[i].first_line];
if (info->line < 0) { if (info->line < 0) {
return -ENODEV; return -ENODEV;
} }
...@@ -4437,7 +4430,7 @@ static void cy_hangup(struct tty_struct *tty) ...@@ -4437,7 +4430,7 @@ static void cy_hangup(struct tty_struct *tty)
* --------------------------------------------------------------------- * ---------------------------------------------------------------------
*/ */
static void __devinit cy_init_card(struct cyclades_card *cinfo) static int __devinit cy_init_card(struct cyclades_card *cinfo)
{ {
struct cyclades_port *info; struct cyclades_port *info;
u32 mailbox; u32 mailbox;
...@@ -4459,10 +4452,15 @@ static void __devinit cy_init_card(struct cyclades_card *cinfo) ...@@ -4459,10 +4452,15 @@ static void __devinit cy_init_card(struct cyclades_card *cinfo)
nports = cinfo->nports = CyPORTS_PER_CHIP * cinfo->num_chips; nports = cinfo->nports = CyPORTS_PER_CHIP * cinfo->num_chips;
} }
cinfo->ports = kzalloc(sizeof(*cinfo->ports) * nports, GFP_KERNEL);
if (cinfo->ports == NULL) {
printk(KERN_ERR "Cyclades: cannot allocate ports\n");
return -ENOMEM;
}
for (port = cinfo->first_line; port < cinfo->first_line + nports; for (port = cinfo->first_line; port < cinfo->first_line + nports;
port++) { port++) {
info = &cy_port[port]; info = &cinfo->ports[port - cinfo->first_line];
memset(info, 0, sizeof(*info));
info->magic = CYCLADES_MAGIC; info->magic = CYCLADES_MAGIC;
info->card = cinfo; info->card = cinfo;
info->line = port; info->line = port;
...@@ -4525,6 +4523,7 @@ static void __devinit cy_init_card(struct cyclades_card *cinfo) ...@@ -4525,6 +4523,7 @@ static void __devinit cy_init_card(struct cyclades_card *cinfo)
#endif #endif
} }
#endif #endif
return 0;
} }
/* initialize chips on Cyclom-Y card -- return number of valid /* initialize chips on Cyclom-Y card -- return number of valid
...@@ -5094,13 +5093,11 @@ static void __devexit cy_pci_remove(struct pci_dev *pdev) ...@@ -5094,13 +5093,11 @@ static void __devexit cy_pci_remove(struct pci_dev *pdev)
pci_release_regions(pdev); pci_release_regions(pdev);
cinfo->base_addr = NULL; cinfo->base_addr = NULL;
for (i = cinfo->first_line; i < cinfo->first_line + cinfo->nports; i++){
cy_port[i].line = -1;
cy_port[i].magic = -1;
}
for (i = cinfo->first_line; i < cinfo->first_line + for (i = cinfo->first_line; i < cinfo->first_line +
cinfo->nports; i++) cinfo->nports; i++)
tty_unregister_device(cy_serial_driver, i); tty_unregister_device(cy_serial_driver, i);
cinfo->nports = 0;
kfree(cinfo->ports);
} }
static struct pci_driver cy_pci_driver = { static struct pci_driver cy_pci_driver = {
...@@ -5116,7 +5113,7 @@ cyclades_get_proc_info(char *buf, char **start, off_t offset, int length, ...@@ -5116,7 +5113,7 @@ cyclades_get_proc_info(char *buf, char **start, off_t offset, int length,
int *eof, void *data) int *eof, void *data)
{ {
struct cyclades_port *info; struct cyclades_port *info;
int i; unsigned int i, j;
int len = 0; int len = 0;
off_t begin = 0; off_t begin = 0;
off_t pos = 0; off_t pos = 0;
...@@ -5130,33 +5127,34 @@ cyclades_get_proc_info(char *buf, char **start, off_t offset, int length, ...@@ -5130,33 +5127,34 @@ cyclades_get_proc_info(char *buf, char **start, off_t offset, int length,
len += size; len += size;
/* Output one line for each known port */ /* Output one line for each known port */
for (i = 0; i < NR_PORTS && cy_port[i].line >= 0; i++) { for (i = 0; i < NR_CARDS; i++)
info = &cy_port[i]; for (j = 0; j < cy_card[i].nports; j++) {
info = &cy_card[i].ports[j];
if (info->count)
size = sprintf(buf + len, "%3d %8lu %10lu %8lu %10lu " if (info->count)
"%8lu %9lu %6ld\n", info->line, size = sprintf(buf + len, "%3d %8lu %10lu %8lu "
(cur_jifs - info->idle_stats.in_use) / HZ, "%10lu %8lu %9lu %6ld\n", info->line,
info->idle_stats.xmit_bytes, (cur_jifs - info->idle_stats.in_use) /
(cur_jifs - info->idle_stats.xmit_idle) / HZ, HZ, info->idle_stats.xmit_bytes,
info->idle_stats.recv_bytes, (cur_jifs - info->idle_stats.xmit_idle)/
(cur_jifs - info->idle_stats.recv_idle) / HZ, HZ, info->idle_stats.recv_bytes,
info->idle_stats.overruns, (cur_jifs - info->idle_stats.recv_idle)/
(long)info->tty->ldisc.num); HZ, info->idle_stats.overruns,
else (long)info->tty->ldisc.num);
size = sprintf(buf + len, "%3d %8lu %10lu %8lu %10lu " else
"%8lu %9lu %6ld\n", size = sprintf(buf + len, "%3d %8lu %10lu %8lu "
info->line, 0L, 0L, 0L, 0L, 0L, 0L, 0L); "%10lu %8lu %9lu %6ld\n",
len += size; info->line, 0L, 0L, 0L, 0L, 0L, 0L, 0L);
pos = begin + len; len += size;
pos = begin + len;
if (pos < offset) {
len = 0; if (pos < offset) {
begin = pos; len = 0;
begin = pos;
}
if (pos > offset + length)
goto done;
} }
if (pos > offset + length)
goto done;
}
*eof = 1; *eof = 1;
done: done:
*start = buf + (offset - begin); /* Start of wanted data */ *start = buf + (offset - begin); /* Start of wanted data */
...@@ -5211,7 +5209,7 @@ static const struct tty_operations cy_ops = { ...@@ -5211,7 +5209,7 @@ static const struct tty_operations cy_ops = {
static int __init cy_init(void) static int __init cy_init(void)
{ {
unsigned int i, nboards; unsigned int nboards;
int retval = -ENOMEM; int retval = -ENOMEM;
cy_serial_driver = alloc_tty_driver(NR_PORTS); cy_serial_driver = alloc_tty_driver(NR_PORTS);
...@@ -5242,11 +5240,6 @@ static int __init cy_init(void) ...@@ -5242,11 +5240,6 @@ static int __init cy_init(void)
goto err_frtty; goto err_frtty;
} }
for (i = 0; i < NR_PORTS; i++) {
cy_port[i].line = -1;
cy_port[i].magic = -1;
}
/* the code below is responsible to find the boards. Each different /* the code below is responsible to find the boards. Each different
type of board has its own detection routine. If a board is found, type of board has its own detection routine. If a board is found,
the next cy_card structure available is set by the detection the next cy_card structure available is set by the detection
...@@ -5275,6 +5268,7 @@ static int __init cy_init(void) ...@@ -5275,6 +5268,7 @@ static int __init cy_init(void)
static void __exit cy_cleanup_module(void) static void __exit cy_cleanup_module(void)
{ {
struct cyclades_card *card;
int i, e1; int i, e1;
#ifndef CONFIG_CYZ_INTR #ifndef CONFIG_CYZ_INTR
...@@ -5290,22 +5284,24 @@ static void __exit cy_cleanup_module(void) ...@@ -5290,22 +5284,24 @@ static void __exit cy_cleanup_module(void)
#endif #endif
for (i = 0; i < NR_CARDS; i++) { for (i = 0; i < NR_CARDS; i++) {
if (cy_card[i].base_addr) { card = &cy_card[i];
if (card->base_addr) {
/* clear interrupt */ /* clear interrupt */
cy_writeb(cy_card[i].base_addr + Cy_ClrIntr, 0); cy_writeb(card->base_addr + Cy_ClrIntr, 0);
iounmap(cy_card[i].base_addr); iounmap(card->base_addr);
if (cy_card[i].ctl_addr) if (card->ctl_addr)
iounmap(cy_card[i].ctl_addr); iounmap(card->ctl_addr);
if (cy_card[i].irq if (card->irq
#ifndef CONFIG_CYZ_INTR #ifndef CONFIG_CYZ_INTR
&& !IS_CYC_Z(cy_card[i]) && !IS_CYC_Z(*card)
#endif /* CONFIG_CYZ_INTR */ #endif /* CONFIG_CYZ_INTR */
) )
free_irq(cy_card[i].irq, &cy_card[i]); free_irq(card->irq, card);
for (e1 = cy_card[i].first_line; for (e1 = card->first_line;
e1 < cy_card[i].first_line + e1 < card->first_line +
cy_card[i].nports; e1++) card->nports; e1++)
tty_unregister_device(cy_serial_driver, e1); tty_unregister_device(cy_serial_driver, e1);
kfree(card->ports);
} }
} }
......
...@@ -518,6 +518,7 @@ struct cyclades_card { ...@@ -518,6 +518,7 @@ struct cyclades_card {
int bus_index; /* address shift - 0 for ISA, 1 for PCI */ int bus_index; /* address shift - 0 for ISA, 1 for PCI */
int intr_enabled; /* FW Interrupt flag - 0 disabled, 1 enabled */ int intr_enabled; /* FW Interrupt flag - 0 disabled, 1 enabled */
spinlock_t card_lock; spinlock_t card_lock;
struct cyclades_port *ports;
}; };
/*************************************** /***************************************
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册