Commit 963118ee authored by Jiri Slaby's avatar Jiri Slaby Committed by Linus Torvalds

tty: cyclades, fix nports handling

Set up ports right after FW load so that we won't allocate maximal
(64) ports when we use few.

Also remove reading of nports in irq context, since we know it from
initialisation now.

This also fixes a tty ports unregistration on some fail paths and for
Ze which registered 64 and unregistered real port count.
Signed-off-by: default avatarJiri Slaby <jirislaby@gmail.com>
Signed-off-by: default avatarAlan Cox <alan@linux.intel.com>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 08a951e1
...@@ -604,7 +604,6 @@ ...@@ -604,7 +604,6 @@
#define NR_PORTS 256 #define NR_PORTS 256
#define ZE_V1_NPORTS 64
#define ZO_V1 0 #define ZO_V1 0
#define ZO_V2 1 #define ZO_V2 1
#define ZE_V1 2 #define ZE_V1 2
...@@ -1777,7 +1776,6 @@ static void cyz_poll(unsigned long arg) ...@@ -1777,7 +1776,6 @@ static void cyz_poll(unsigned long arg)
struct tty_struct *tty; struct tty_struct *tty;
struct FIRM_ID __iomem *firm_id; struct FIRM_ID __iomem *firm_id;
struct ZFW_CTRL __iomem *zfw_ctrl; struct ZFW_CTRL __iomem *zfw_ctrl;
struct BOARD_CTRL __iomem *board_ctrl;
struct BUF_CTRL __iomem *buf_ctrl; struct BUF_CTRL __iomem *buf_ctrl;
unsigned long expires = jiffies + HZ; unsigned long expires = jiffies + HZ;
unsigned int port, card; unsigned int port, card;
...@@ -1793,11 +1791,9 @@ static void cyz_poll(unsigned long arg) ...@@ -1793,11 +1791,9 @@ static void cyz_poll(unsigned long arg)
firm_id = cinfo->base_addr + ID_ADDRESS; firm_id = cinfo->base_addr + ID_ADDRESS;
zfw_ctrl = cinfo->base_addr + zfw_ctrl = cinfo->base_addr +
(readl(&firm_id->zfwctrl_addr) & 0xfffff); (readl(&firm_id->zfwctrl_addr) & 0xfffff);
board_ctrl = &(zfw_ctrl->board_ctrl);
/* Skip first polling cycle to avoid racing conditions with the FW */ /* Skip first polling cycle to avoid racing conditions with the FW */
if (!cinfo->intr_enabled) { if (!cinfo->intr_enabled) {
cinfo->nports = (int)readl(&board_ctrl->n_channel);
cinfo->intr_enabled = 1; cinfo->intr_enabled = 1;
continue; continue;
} }
...@@ -2413,16 +2409,8 @@ static int cy_open(struct tty_struct *tty, struct file *filp) ...@@ -2413,16 +2409,8 @@ static int cy_open(struct tty_struct *tty, struct file *filp)
interrupts should be enabled as soon as the first open interrupts should be enabled as soon as the first open
happens to one of its ports. */ happens to one of its ports. */
if (!cinfo->intr_enabled) { if (!cinfo->intr_enabled) {
struct ZFW_CTRL __iomem *zfw_ctrl;
struct BOARD_CTRL __iomem *board_ctrl;
u16 intr; u16 intr;
zfw_ctrl = cinfo->base_addr +
(readl(&firm_id->zfwctrl_addr) &
0xfffff);
board_ctrl = &zfw_ctrl->board_ctrl;
/* Enable interrupts on the PLX chip */ /* Enable interrupts on the PLX chip */
intr = readw(&cinfo->ctl_addr.p9060-> intr = readw(&cinfo->ctl_addr.p9060->
intr_ctrl_stat) | 0x0900; intr_ctrl_stat) | 0x0900;
...@@ -2435,8 +2423,6 @@ static int cy_open(struct tty_struct *tty, struct file *filp) ...@@ -2435,8 +2423,6 @@ static int cy_open(struct tty_struct *tty, struct file *filp)
printk(KERN_ERR "cyc:IRQ enable retval " printk(KERN_ERR "cyc:IRQ enable retval "
"was %x\n", retval); "was %x\n", retval);
} }
cinfo->nports =
(int)readl(&board_ctrl->n_channel);
cinfo->intr_enabled = 1; cinfo->intr_enabled = 1;
} }
} }
...@@ -4340,30 +4326,20 @@ static void cy_hangup(struct tty_struct *tty) ...@@ -4340,30 +4326,20 @@ static void cy_hangup(struct tty_struct *tty)
static int __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;
unsigned int nports, port; unsigned int port;
unsigned short chip_number; unsigned short chip_number;
int uninitialized_var(index);
spin_lock_init(&cinfo->card_lock); spin_lock_init(&cinfo->card_lock);
cinfo->intr_enabled = 0;
if (cy_is_Z(cinfo)) { /* Cyclades-Z */ cinfo->ports = kcalloc(cinfo->nports, sizeof(*cinfo->ports),
nports = (cinfo->hw_ver == ZE_V1) ? ZE_V1_NPORTS : 8; GFP_KERNEL);
cinfo->intr_enabled = 0;
cinfo->nports = 0; /* Will be correctly set later, after
Z FW is loaded */
} else {
index = cinfo->bus_index;
nports = cinfo->nports = CyPORTS_PER_CHIP * cinfo->num_chips;
}
cinfo->ports = kzalloc(sizeof(*cinfo->ports) * nports, GFP_KERNEL);
if (cinfo->ports == NULL) { if (cinfo->ports == NULL) {
printk(KERN_ERR "Cyclades: cannot allocate ports\n"); printk(KERN_ERR "Cyclades: cannot allocate ports\n");
cinfo->nports = 0;
return -ENOMEM; return -ENOMEM;
} }
for (port = cinfo->first_line; port < cinfo->first_line + nports; for (port = cinfo->first_line; port < cinfo->first_line + cinfo->nports;
port++) { port++) {
info = &cinfo->ports[port - cinfo->first_line]; info = &cinfo->ports[port - cinfo->first_line];
tty_port_init(&info->port); tty_port_init(&info->port);
...@@ -4388,6 +4364,7 @@ static int __devinit cy_init_card(struct cyclades_card *cinfo) ...@@ -4388,6 +4364,7 @@ static int __devinit cy_init_card(struct cyclades_card *cinfo)
cyz_rx_restart, (unsigned long)info); cyz_rx_restart, (unsigned long)info);
#endif #endif
} else { } else {
int index = cinfo->bus_index;
info->type = PORT_CIRRUS; info->type = PORT_CIRRUS;
info->xmit_fifo_size = CyMAX_CHAR_FIFO; info->xmit_fifo_size = CyMAX_CHAR_FIFO;
info->cor1 = CyPARITY_NONE | Cy_1_STOP | Cy_8_BITS; info->cor1 = CyPARITY_NONE | Cy_1_STOP | Cy_8_BITS;
...@@ -4615,7 +4592,8 @@ static int __init cy_detect_isa(void) ...@@ -4615,7 +4592,8 @@ static int __init cy_detect_isa(void)
cy_card[j].irq = (int)cy_isa_irq; cy_card[j].irq = (int)cy_isa_irq;
cy_card[j].bus_index = 0; cy_card[j].bus_index = 0;
cy_card[j].first_line = cy_next_channel; cy_card[j].first_line = cy_next_channel;
cy_card[j].num_chips = cy_isa_nchan / 4; cy_card[j].num_chips = cy_isa_nchan / CyPORTS_PER_CHIP;
cy_card[j].nports = cy_isa_nchan;
if (cy_init_card(&cy_card[j])) { if (cy_init_card(&cy_card[j])) {
cy_card[j].base_addr = NULL; cy_card[j].base_addr = NULL;
free_irq(cy_isa_irq, &cy_card[j]); free_irq(cy_isa_irq, &cy_card[j]);
...@@ -4771,7 +4749,7 @@ static int __devinit cyz_load_fw(struct pci_dev *pdev, void __iomem *base_addr, ...@@ -4771,7 +4749,7 @@ static int __devinit cyz_load_fw(struct pci_dev *pdev, void __iomem *base_addr,
struct CUSTOM_REG __iomem *cust = base_addr; struct CUSTOM_REG __iomem *cust = base_addr;
struct ZFW_CTRL __iomem *pt_zfwctrl; struct ZFW_CTRL __iomem *pt_zfwctrl;
void __iomem *tmp; void __iomem *tmp;
u32 mailbox, status; u32 mailbox, status, nchan;
unsigned int i; unsigned int i;
int retval; int retval;
...@@ -4892,11 +4870,11 @@ static int __devinit cyz_load_fw(struct pci_dev *pdev, void __iomem *base_addr, ...@@ -4892,11 +4870,11 @@ static int __devinit cyz_load_fw(struct pci_dev *pdev, void __iomem *base_addr,
base_addr + ID_ADDRESS, readl(&fid->zfwctrl_addr), base_addr + ID_ADDRESS, readl(&fid->zfwctrl_addr),
base_addr + readl(&fid->zfwctrl_addr)); base_addr + readl(&fid->zfwctrl_addr));
nchan = readl(&pt_zfwctrl->board_ctrl.n_channel);
dev_info(&pdev->dev, "Cyclades-Z FW loaded: version = %x, ports = %u\n", dev_info(&pdev->dev, "Cyclades-Z FW loaded: version = %x, ports = %u\n",
readl(&pt_zfwctrl->board_ctrl.fw_version), readl(&pt_zfwctrl->board_ctrl.fw_version), nchan);
readl(&pt_zfwctrl->board_ctrl.n_channel));
if (readl(&pt_zfwctrl->board_ctrl.n_channel) == 0) { if (nchan == 0) {
dev_warn(&pdev->dev, "no Cyclades-Z ports were found. Please " dev_warn(&pdev->dev, "no Cyclades-Z ports were found. Please "
"check the connection between the Z host card and the " "check the connection between the Z host card and the "
"serial expanders.\n"); "serial expanders.\n");
...@@ -4922,7 +4900,7 @@ static int __devinit cyz_load_fw(struct pci_dev *pdev, void __iomem *base_addr, ...@@ -4922,7 +4900,7 @@ static int __devinit cyz_load_fw(struct pci_dev *pdev, void __iomem *base_addr,
cy_writel(&ctl_addr->intr_ctrl_stat, readl(&ctl_addr->intr_ctrl_stat) | cy_writel(&ctl_addr->intr_ctrl_stat, readl(&ctl_addr->intr_ctrl_stat) |
0x00030800UL); 0x00030800UL);
return 0; return nchan;
err_rel: err_rel:
release_firmware(fw); release_firmware(fw);
err: err:
...@@ -5027,12 +5005,8 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev, ...@@ -5027,12 +5005,8 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev,
if (mailbox == ZE_V1) { if (mailbox == ZE_V1) {
card_name = "Cyclades-Ze"; card_name = "Cyclades-Ze";
nchan = ZE_V1_NPORTS;
} else { } else {
card_name = "Cyclades-8Zo"; card_name = "Cyclades-8Zo";
nchan = 8;
#ifdef CY_PCI_DEBUG #ifdef CY_PCI_DEBUG
if (mailbox == ZO_V1) { if (mailbox == ZO_V1) {
cy_writel(&ctl_addr->loc_addr_base, WIN_CREG); cy_writel(&ctl_addr->loc_addr_base, WIN_CREG);
...@@ -5057,8 +5031,9 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev, ...@@ -5057,8 +5031,9 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev,
} }
retval = cyz_load_fw(pdev, addr2, addr0, irq); retval = cyz_load_fw(pdev, addr2, addr0, irq);
if (retval) if (retval <= 0)
goto err_unmap; goto err_unmap;
nchan = retval;
} }
if ((cy_next_channel + nchan) > NR_PORTS) { if ((cy_next_channel + nchan) > NR_PORTS) {
...@@ -5088,7 +5063,7 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev, ...@@ -5088,7 +5063,7 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev,
dev_err(&pdev->dev, "could not allocate IRQ\n"); dev_err(&pdev->dev, "could not allocate IRQ\n");
goto err_unmap; goto err_unmap;
} }
cy_card[card_no].num_chips = nchan / 4; cy_card[card_no].num_chips = nchan / CyPORTS_PER_CHIP;
} else { } else {
cy_card[card_no].hw_ver = mailbox; cy_card[card_no].hw_ver = mailbox;
cy_card[card_no].num_chips = (unsigned int)-1; cy_card[card_no].num_chips = (unsigned int)-1;
...@@ -5112,6 +5087,7 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev, ...@@ -5112,6 +5087,7 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev,
cy_card[card_no].irq = irq; cy_card[card_no].irq = irq;
cy_card[card_no].bus_index = 1; cy_card[card_no].bus_index = 1;
cy_card[card_no].first_line = cy_next_channel; cy_card[card_no].first_line = cy_next_channel;
cy_card[card_no].nports = nchan;
retval = cy_init_card(&cy_card[card_no]); retval = cy_init_card(&cy_card[card_no]);
if (retval) if (retval)
goto err_null; goto err_null;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment