tty/serial fixes for 3.10-rc2
Here are some tty / serial driver fixes for 3.10-rc2.
Nothing huge, although the rocket driver fix looks large, it's just
moving the code around to fix the reported build issues in it. Other
than that, this has the fix for the of-reported lockdep warning from the
vt layer, as well as some other needed bugfixes.
All of these have been in linux-next for a while.
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.19 (GNU/Linux)
iEYEABECAAYFAlGePq4ACgkQMUfUDdst+ylQEgCeIW1+VA7qMg2ByD1ewxIv1trn
p1cAnjvLF0yIM2IqknCh6NmlnBqF/2Oo
=1rWD
-----END PGP SIGNATURE-----
Merge tag 'tty-3.10-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty
Pull tty/serial fixes from Greg Kroah-Hartman:
"Here are some tty / serial driver fixes for 3.10-rc2.
Nothing huge, although the rocket driver fix looks large, it's just
moving the code around to fix the reported build issues in it. Other
than that, this has the fix for the of-reported lockdep warning from
the vt layer, as well as some other needed bugfixes.
All of these have been in linux-next for a while"
* tag 'tty-3.10-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty:
tty: mxser: Fix build warning introduced by dfc7b837c7
(Re: linux-next: build warning after merge of the tty.current tree)
tty: mxser: fix usage of opmode_ioaddr
serial: 8250_dw: add ACPI ID for Intel BayTrail
TTY: Fix tty miss restart after we turn off flow-control
tty/vt: Fix vc_deallocate() lock order
TTY: ehv_bytechan: add missing platform_driver_unregister() when module exit
TTY: rocket, fix more no-PCI warnings
serial: mcf: missing uart_unregister_driver() on error in mcf_init()
tty: serial: mpc5xxx: fix error handing in mpc52xx_uart_init()
serial: samsung: add missing platform_driver_unregister() when module exit
serial: pl011: protect attribute read from NULL platform data struct
tty: nwpserial: Pass correct pointer to free_irq()
serial: 8250_dw: Add valid clk pointer check
This commit is contained in:
commit
d979556257
|
@ -859,6 +859,7 @@ error:
|
|||
*/
|
||||
static void __exit ehv_bc_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&ehv_bc_tty_driver);
|
||||
tty_unregister_driver(ehv_bc_driver);
|
||||
put_tty_driver(ehv_bc_driver);
|
||||
kfree(bcs);
|
||||
|
|
|
@ -1618,8 +1618,12 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp)
|
|||
if (ip->type == PORT_16550A)
|
||||
me->fifo[p] = 1;
|
||||
|
||||
opmode = inb(ip->opmode_ioaddr)>>((p % 4) * 2);
|
||||
opmode &= OP_MODE_MASK;
|
||||
if (ip->board->chip_flag == MOXA_MUST_MU860_HWID) {
|
||||
opmode = inb(ip->opmode_ioaddr)>>((p % 4) * 2);
|
||||
opmode &= OP_MODE_MASK;
|
||||
} else {
|
||||
opmode = RS232_MODE;
|
||||
}
|
||||
me->iftype[p] = opmode;
|
||||
mutex_unlock(&port->mutex);
|
||||
}
|
||||
|
@ -1676,6 +1680,9 @@ static int mxser_ioctl(struct tty_struct *tty,
|
|||
int shiftbit;
|
||||
unsigned char val, mask;
|
||||
|
||||
if (info->board->chip_flag != MOXA_MUST_MU860_HWID)
|
||||
return -EFAULT;
|
||||
|
||||
p = tty->index % 4;
|
||||
if (cmd == MOXA_SET_OP_MODE) {
|
||||
if (get_user(opmode, (int __user *) argp))
|
||||
|
|
|
@ -1573,6 +1573,14 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old)
|
|||
ldata->real_raw = 0;
|
||||
}
|
||||
n_tty_set_room(tty);
|
||||
/*
|
||||
* Fix tty hang when I_IXON(tty) is cleared, but the tty
|
||||
* been stopped by STOP_CHAR(tty) before it.
|
||||
*/
|
||||
if (!I_IXON(tty) && old && (old->c_iflag & IXON) && !tty->flow_stopped) {
|
||||
start_tty(tty);
|
||||
}
|
||||
|
||||
/* The termios change make the tty ready for I/O */
|
||||
wake_up_interruptible(&tty->write_wait);
|
||||
wake_up_interruptible(&tty->read_wait);
|
||||
|
|
|
@ -150,12 +150,14 @@ static Word_t aiop_intr_bits[AIOP_CTL_SIZE] = {
|
|||
AIOP_INTR_BIT_3
|
||||
};
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
static Word_t upci_aiop_intr_bits[AIOP_CTL_SIZE] = {
|
||||
UPCI_AIOP_INTR_BIT_0,
|
||||
UPCI_AIOP_INTR_BIT_1,
|
||||
UPCI_AIOP_INTR_BIT_2,
|
||||
UPCI_AIOP_INTR_BIT_3
|
||||
};
|
||||
#endif
|
||||
|
||||
static Byte_t RData[RDATASIZE] = {
|
||||
0x00, 0x09, 0xf6, 0x82,
|
||||
|
@ -227,7 +229,6 @@ static unsigned long nextLineNumber;
|
|||
static int __init init_ISA(int i);
|
||||
static void rp_wait_until_sent(struct tty_struct *tty, int timeout);
|
||||
static void rp_flush_buffer(struct tty_struct *tty);
|
||||
static void rmSpeakerReset(CONTROLLER_T * CtlP, unsigned long model);
|
||||
static unsigned char GetLineNumber(int ctrl, int aiop, int ch);
|
||||
static unsigned char SetLineNumber(int ctrl, int aiop, int ch);
|
||||
static void rp_start(struct tty_struct *tty);
|
||||
|
@ -241,11 +242,6 @@ static void sDisInterrupts(CHANNEL_T * ChP, Word_t Flags);
|
|||
static void sModemReset(CONTROLLER_T * CtlP, int chan, int on);
|
||||
static void sPCIModemReset(CONTROLLER_T * CtlP, int chan, int on);
|
||||
static int sWriteTxPrioByte(CHANNEL_T * ChP, Byte_t Data);
|
||||
static int sPCIInitController(CONTROLLER_T * CtlP, int CtlNum,
|
||||
ByteIO_t * AiopIOList, int AiopIOListSize,
|
||||
WordIO_t ConfigIO, int IRQNum, Byte_t Frequency,
|
||||
int PeriodicOnly, int altChanRingIndicator,
|
||||
int UPCIRingInd);
|
||||
static int sInitController(CONTROLLER_T * CtlP, int CtlNum, ByteIO_t MudbacIO,
|
||||
ByteIO_t * AiopIOList, int AiopIOListSize,
|
||||
int IRQNum, Byte_t Frequency, int PeriodicOnly);
|
||||
|
@ -1775,6 +1771,145 @@ static DEFINE_PCI_DEVICE_TABLE(rocket_pci_ids) = {
|
|||
};
|
||||
MODULE_DEVICE_TABLE(pci, rocket_pci_ids);
|
||||
|
||||
/* Resets the speaker controller on RocketModem II and III devices */
|
||||
static void rmSpeakerReset(CONTROLLER_T * CtlP, unsigned long model)
|
||||
{
|
||||
ByteIO_t addr;
|
||||
|
||||
/* RocketModem II speaker control is at the 8th port location of offset 0x40 */
|
||||
if ((model == MODEL_RP4M) || (model == MODEL_RP6M)) {
|
||||
addr = CtlP->AiopIO[0] + 0x4F;
|
||||
sOutB(addr, 0);
|
||||
}
|
||||
|
||||
/* RocketModem III speaker control is at the 1st port location of offset 0x80 */
|
||||
if ((model == MODEL_UPCI_RM3_8PORT)
|
||||
|| (model == MODEL_UPCI_RM3_4PORT)) {
|
||||
addr = CtlP->AiopIO[0] + 0x88;
|
||||
sOutB(addr, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
Function: sPCIInitController
|
||||
Purpose: Initialization of controller global registers and controller
|
||||
structure.
|
||||
Call: sPCIInitController(CtlP,CtlNum,AiopIOList,AiopIOListSize,
|
||||
IRQNum,Frequency,PeriodicOnly)
|
||||
CONTROLLER_T *CtlP; Ptr to controller structure
|
||||
int CtlNum; Controller number
|
||||
ByteIO_t *AiopIOList; List of I/O addresses for each AIOP.
|
||||
This list must be in the order the AIOPs will be found on the
|
||||
controller. Once an AIOP in the list is not found, it is
|
||||
assumed that there are no more AIOPs on the controller.
|
||||
int AiopIOListSize; Number of addresses in AiopIOList
|
||||
int IRQNum; Interrupt Request number. Can be any of the following:
|
||||
0: Disable global interrupts
|
||||
3: IRQ 3
|
||||
4: IRQ 4
|
||||
5: IRQ 5
|
||||
9: IRQ 9
|
||||
10: IRQ 10
|
||||
11: IRQ 11
|
||||
12: IRQ 12
|
||||
15: IRQ 15
|
||||
Byte_t Frequency: A flag identifying the frequency
|
||||
of the periodic interrupt, can be any one of the following:
|
||||
FREQ_DIS - periodic interrupt disabled
|
||||
FREQ_137HZ - 137 Hertz
|
||||
FREQ_69HZ - 69 Hertz
|
||||
FREQ_34HZ - 34 Hertz
|
||||
FREQ_17HZ - 17 Hertz
|
||||
FREQ_9HZ - 9 Hertz
|
||||
FREQ_4HZ - 4 Hertz
|
||||
If IRQNum is set to 0 the Frequency parameter is
|
||||
overidden, it is forced to a value of FREQ_DIS.
|
||||
int PeriodicOnly: 1 if all interrupts except the periodic
|
||||
interrupt are to be blocked.
|
||||
0 is both the periodic interrupt and
|
||||
other channel interrupts are allowed.
|
||||
If IRQNum is set to 0 the PeriodicOnly parameter is
|
||||
overidden, it is forced to a value of 0.
|
||||
Return: int: Number of AIOPs on the controller, or CTLID_NULL if controller
|
||||
initialization failed.
|
||||
|
||||
Comments:
|
||||
If periodic interrupts are to be disabled but AIOP interrupts
|
||||
are allowed, set Frequency to FREQ_DIS and PeriodicOnly to 0.
|
||||
|
||||
If interrupts are to be completely disabled set IRQNum to 0.
|
||||
|
||||
Setting Frequency to FREQ_DIS and PeriodicOnly to 1 is an
|
||||
invalid combination.
|
||||
|
||||
This function performs initialization of global interrupt modes,
|
||||
but it does not actually enable global interrupts. To enable
|
||||
and disable global interrupts use functions sEnGlobalInt() and
|
||||
sDisGlobalInt(). Enabling of global interrupts is normally not
|
||||
done until all other initializations are complete.
|
||||
|
||||
Even if interrupts are globally enabled, they must also be
|
||||
individually enabled for each channel that is to generate
|
||||
interrupts.
|
||||
|
||||
Warnings: No range checking on any of the parameters is done.
|
||||
|
||||
No context switches are allowed while executing this function.
|
||||
|
||||
After this function all AIOPs on the controller are disabled,
|
||||
they can be enabled with sEnAiop().
|
||||
*/
|
||||
static int sPCIInitController(CONTROLLER_T * CtlP, int CtlNum,
|
||||
ByteIO_t * AiopIOList, int AiopIOListSize,
|
||||
WordIO_t ConfigIO, int IRQNum, Byte_t Frequency,
|
||||
int PeriodicOnly, int altChanRingIndicator,
|
||||
int UPCIRingInd)
|
||||
{
|
||||
int i;
|
||||
ByteIO_t io;
|
||||
|
||||
CtlP->AltChanRingIndicator = altChanRingIndicator;
|
||||
CtlP->UPCIRingInd = UPCIRingInd;
|
||||
CtlP->CtlNum = CtlNum;
|
||||
CtlP->CtlID = CTLID_0001; /* controller release 1 */
|
||||
CtlP->BusType = isPCI; /* controller release 1 */
|
||||
|
||||
if (ConfigIO) {
|
||||
CtlP->isUPCI = 1;
|
||||
CtlP->PCIIO = ConfigIO + _PCI_9030_INT_CTRL;
|
||||
CtlP->PCIIO2 = ConfigIO + _PCI_9030_GPIO_CTRL;
|
||||
CtlP->AiopIntrBits = upci_aiop_intr_bits;
|
||||
} else {
|
||||
CtlP->isUPCI = 0;
|
||||
CtlP->PCIIO =
|
||||
(WordIO_t) ((ByteIO_t) AiopIOList[0] + _PCI_INT_FUNC);
|
||||
CtlP->AiopIntrBits = aiop_intr_bits;
|
||||
}
|
||||
|
||||
sPCIControllerEOI(CtlP); /* clear EOI if warm init */
|
||||
/* Init AIOPs */
|
||||
CtlP->NumAiop = 0;
|
||||
for (i = 0; i < AiopIOListSize; i++) {
|
||||
io = AiopIOList[i];
|
||||
CtlP->AiopIO[i] = (WordIO_t) io;
|
||||
CtlP->AiopIntChanIO[i] = io + _INT_CHAN;
|
||||
|
||||
CtlP->AiopID[i] = sReadAiopID(io); /* read AIOP ID */
|
||||
if (CtlP->AiopID[i] == AIOPID_NULL) /* if AIOP does not exist */
|
||||
break; /* done looking for AIOPs */
|
||||
|
||||
CtlP->AiopNumChan[i] = sReadAiopNumChan((WordIO_t) io); /* num channels in AIOP */
|
||||
sOutW((WordIO_t) io + _INDX_ADDR, _CLK_PRE); /* clock prescaler */
|
||||
sOutB(io + _INDX_DATA, sClockPrescale);
|
||||
CtlP->NumAiop++; /* bump count of AIOPs */
|
||||
}
|
||||
|
||||
if (CtlP->NumAiop == 0)
|
||||
return (-1);
|
||||
else
|
||||
return (CtlP->NumAiop);
|
||||
}
|
||||
|
||||
/*
|
||||
* Called when a PCI card is found. Retrieves and stores model information,
|
||||
* init's aiopic and serial port hardware.
|
||||
|
@ -2519,147 +2654,6 @@ static int sInitController(CONTROLLER_T * CtlP, int CtlNum, ByteIO_t MudbacIO,
|
|||
return (CtlP->NumAiop);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
/***************************************************************************
|
||||
Function: sPCIInitController
|
||||
Purpose: Initialization of controller global registers and controller
|
||||
structure.
|
||||
Call: sPCIInitController(CtlP,CtlNum,AiopIOList,AiopIOListSize,
|
||||
IRQNum,Frequency,PeriodicOnly)
|
||||
CONTROLLER_T *CtlP; Ptr to controller structure
|
||||
int CtlNum; Controller number
|
||||
ByteIO_t *AiopIOList; List of I/O addresses for each AIOP.
|
||||
This list must be in the order the AIOPs will be found on the
|
||||
controller. Once an AIOP in the list is not found, it is
|
||||
assumed that there are no more AIOPs on the controller.
|
||||
int AiopIOListSize; Number of addresses in AiopIOList
|
||||
int IRQNum; Interrupt Request number. Can be any of the following:
|
||||
0: Disable global interrupts
|
||||
3: IRQ 3
|
||||
4: IRQ 4
|
||||
5: IRQ 5
|
||||
9: IRQ 9
|
||||
10: IRQ 10
|
||||
11: IRQ 11
|
||||
12: IRQ 12
|
||||
15: IRQ 15
|
||||
Byte_t Frequency: A flag identifying the frequency
|
||||
of the periodic interrupt, can be any one of the following:
|
||||
FREQ_DIS - periodic interrupt disabled
|
||||
FREQ_137HZ - 137 Hertz
|
||||
FREQ_69HZ - 69 Hertz
|
||||
FREQ_34HZ - 34 Hertz
|
||||
FREQ_17HZ - 17 Hertz
|
||||
FREQ_9HZ - 9 Hertz
|
||||
FREQ_4HZ - 4 Hertz
|
||||
If IRQNum is set to 0 the Frequency parameter is
|
||||
overidden, it is forced to a value of FREQ_DIS.
|
||||
int PeriodicOnly: 1 if all interrupts except the periodic
|
||||
interrupt are to be blocked.
|
||||
0 is both the periodic interrupt and
|
||||
other channel interrupts are allowed.
|
||||
If IRQNum is set to 0 the PeriodicOnly parameter is
|
||||
overidden, it is forced to a value of 0.
|
||||
Return: int: Number of AIOPs on the controller, or CTLID_NULL if controller
|
||||
initialization failed.
|
||||
|
||||
Comments:
|
||||
If periodic interrupts are to be disabled but AIOP interrupts
|
||||
are allowed, set Frequency to FREQ_DIS and PeriodicOnly to 0.
|
||||
|
||||
If interrupts are to be completely disabled set IRQNum to 0.
|
||||
|
||||
Setting Frequency to FREQ_DIS and PeriodicOnly to 1 is an
|
||||
invalid combination.
|
||||
|
||||
This function performs initialization of global interrupt modes,
|
||||
but it does not actually enable global interrupts. To enable
|
||||
and disable global interrupts use functions sEnGlobalInt() and
|
||||
sDisGlobalInt(). Enabling of global interrupts is normally not
|
||||
done until all other initializations are complete.
|
||||
|
||||
Even if interrupts are globally enabled, they must also be
|
||||
individually enabled for each channel that is to generate
|
||||
interrupts.
|
||||
|
||||
Warnings: No range checking on any of the parameters is done.
|
||||
|
||||
No context switches are allowed while executing this function.
|
||||
|
||||
After this function all AIOPs on the controller are disabled,
|
||||
they can be enabled with sEnAiop().
|
||||
*/
|
||||
static int sPCIInitController(CONTROLLER_T * CtlP, int CtlNum,
|
||||
ByteIO_t * AiopIOList, int AiopIOListSize,
|
||||
WordIO_t ConfigIO, int IRQNum, Byte_t Frequency,
|
||||
int PeriodicOnly, int altChanRingIndicator,
|
||||
int UPCIRingInd)
|
||||
{
|
||||
int i;
|
||||
ByteIO_t io;
|
||||
|
||||
CtlP->AltChanRingIndicator = altChanRingIndicator;
|
||||
CtlP->UPCIRingInd = UPCIRingInd;
|
||||
CtlP->CtlNum = CtlNum;
|
||||
CtlP->CtlID = CTLID_0001; /* controller release 1 */
|
||||
CtlP->BusType = isPCI; /* controller release 1 */
|
||||
|
||||
if (ConfigIO) {
|
||||
CtlP->isUPCI = 1;
|
||||
CtlP->PCIIO = ConfigIO + _PCI_9030_INT_CTRL;
|
||||
CtlP->PCIIO2 = ConfigIO + _PCI_9030_GPIO_CTRL;
|
||||
CtlP->AiopIntrBits = upci_aiop_intr_bits;
|
||||
} else {
|
||||
CtlP->isUPCI = 0;
|
||||
CtlP->PCIIO =
|
||||
(WordIO_t) ((ByteIO_t) AiopIOList[0] + _PCI_INT_FUNC);
|
||||
CtlP->AiopIntrBits = aiop_intr_bits;
|
||||
}
|
||||
|
||||
sPCIControllerEOI(CtlP); /* clear EOI if warm init */
|
||||
/* Init AIOPs */
|
||||
CtlP->NumAiop = 0;
|
||||
for (i = 0; i < AiopIOListSize; i++) {
|
||||
io = AiopIOList[i];
|
||||
CtlP->AiopIO[i] = (WordIO_t) io;
|
||||
CtlP->AiopIntChanIO[i] = io + _INT_CHAN;
|
||||
|
||||
CtlP->AiopID[i] = sReadAiopID(io); /* read AIOP ID */
|
||||
if (CtlP->AiopID[i] == AIOPID_NULL) /* if AIOP does not exist */
|
||||
break; /* done looking for AIOPs */
|
||||
|
||||
CtlP->AiopNumChan[i] = sReadAiopNumChan((WordIO_t) io); /* num channels in AIOP */
|
||||
sOutW((WordIO_t) io + _INDX_ADDR, _CLK_PRE); /* clock prescaler */
|
||||
sOutB(io + _INDX_DATA, sClockPrescale);
|
||||
CtlP->NumAiop++; /* bump count of AIOPs */
|
||||
}
|
||||
|
||||
if (CtlP->NumAiop == 0)
|
||||
return (-1);
|
||||
else
|
||||
return (CtlP->NumAiop);
|
||||
}
|
||||
|
||||
/* Resets the speaker controller on RocketModem II and III devices */
|
||||
static void rmSpeakerReset(CONTROLLER_T * CtlP, unsigned long model)
|
||||
{
|
||||
ByteIO_t addr;
|
||||
|
||||
/* RocketModem II speaker control is at the 8th port location of offset 0x40 */
|
||||
if ((model == MODEL_RP4M) || (model == MODEL_RP6M)) {
|
||||
addr = CtlP->AiopIO[0] + 0x4F;
|
||||
sOutB(addr, 0);
|
||||
}
|
||||
|
||||
/* RocketModem III speaker control is at the 1st port location of offset 0x80 */
|
||||
if ((model == MODEL_UPCI_RM3_8PORT)
|
||||
|| (model == MODEL_UPCI_RM3_4PORT)) {
|
||||
addr = CtlP->AiopIO[0] + 0x88;
|
||||
sOutB(addr, 0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/***************************************************************************
|
||||
Function: sReadAiopID
|
||||
Purpose: Read the AIOP idenfication number directly from an AIOP.
|
||||
|
|
|
@ -338,7 +338,8 @@ static int dw8250_runtime_suspend(struct device *dev)
|
|||
{
|
||||
struct dw8250_data *data = dev_get_drvdata(dev);
|
||||
|
||||
clk_disable_unprepare(data->clk);
|
||||
if (!IS_ERR(data->clk))
|
||||
clk_disable_unprepare(data->clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -347,7 +348,8 @@ static int dw8250_runtime_resume(struct device *dev)
|
|||
{
|
||||
struct dw8250_data *data = dev_get_drvdata(dev);
|
||||
|
||||
clk_prepare_enable(data->clk);
|
||||
if (!IS_ERR(data->clk))
|
||||
clk_prepare_enable(data->clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -367,6 +369,7 @@ MODULE_DEVICE_TABLE(of, dw8250_of_match);
|
|||
static const struct acpi_device_id dw8250_acpi_match[] = {
|
||||
{ "INT33C4", 0 },
|
||||
{ "INT33C5", 0 },
|
||||
{ "80860F0A", 0 },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(acpi, dw8250_acpi_match);
|
||||
|
|
|
@ -332,7 +332,7 @@ static void pl011_dma_probe_initcall(struct device *dev, struct uart_amba_port *
|
|||
dmaengine_slave_config(chan, &rx_conf);
|
||||
uap->dmarx.chan = chan;
|
||||
|
||||
if (plat->dma_rx_poll_enable) {
|
||||
if (plat && plat->dma_rx_poll_enable) {
|
||||
/* Set poll rate if specified. */
|
||||
if (plat->dma_rx_poll_rate) {
|
||||
uap->dmarx.auto_poll_rate = false;
|
||||
|
|
|
@ -707,8 +707,10 @@ static int __init mcf_init(void)
|
|||
if (rc)
|
||||
return rc;
|
||||
rc = platform_driver_register(&mcf_platform_driver);
|
||||
if (rc)
|
||||
if (rc) {
|
||||
uart_unregister_driver(&mcf_driver);
|
||||
return rc;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -1497,18 +1497,23 @@ mpc52xx_uart_init(void)
|
|||
if (psc_ops && psc_ops->fifoc_init) {
|
||||
ret = psc_ops->fifoc_init();
|
||||
if (ret)
|
||||
return ret;
|
||||
goto err_init;
|
||||
}
|
||||
|
||||
ret = platform_driver_register(&mpc52xx_uart_of_driver);
|
||||
if (ret) {
|
||||
printk(KERN_ERR "%s: platform_driver_register failed (%i)\n",
|
||||
__FILE__, ret);
|
||||
uart_unregister_driver(&mpc52xx_uart_driver);
|
||||
return ret;
|
||||
goto err_reg;
|
||||
}
|
||||
|
||||
return 0;
|
||||
err_reg:
|
||||
if (psc_ops && psc_ops->fifoc_uninit)
|
||||
psc_ops->fifoc_uninit();
|
||||
err_init:
|
||||
uart_unregister_driver(&mpc52xx_uart_driver);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit
|
||||
|
|
|
@ -199,7 +199,7 @@ static void nwpserial_shutdown(struct uart_port *port)
|
|||
dcr_write(up->dcr_host, UART_IER, up->ier);
|
||||
|
||||
/* free irq */
|
||||
free_irq(up->port.irq, port);
|
||||
free_irq(up->port.irq, up);
|
||||
}
|
||||
|
||||
static int nwpserial_verify_port(struct uart_port *port,
|
||||
|
|
|
@ -1803,6 +1803,7 @@ static int __init s3c24xx_serial_modinit(void)
|
|||
|
||||
static void __exit s3c24xx_serial_modexit(void)
|
||||
{
|
||||
platform_driver_unregister(&samsung_serial_driver);
|
||||
uart_unregister_driver(&s3c24xx_uart_drv);
|
||||
}
|
||||
|
||||
|
|
|
@ -779,7 +779,6 @@ int vc_allocate(unsigned int currcons) /* return 0 on success */
|
|||
con_set_default_unimap(vc);
|
||||
vc->vc_screenbuf = kmalloc(vc->vc_screenbuf_size, GFP_KERNEL);
|
||||
if (!vc->vc_screenbuf) {
|
||||
tty_port_destroy(&vc->port);
|
||||
kfree(vc);
|
||||
vc_cons[currcons].d = NULL;
|
||||
return -ENOMEM;
|
||||
|
@ -986,26 +985,25 @@ static int vt_resize(struct tty_struct *tty, struct winsize *ws)
|
|||
return ret;
|
||||
}
|
||||
|
||||
void vc_deallocate(unsigned int currcons)
|
||||
struct vc_data *vc_deallocate(unsigned int currcons)
|
||||
{
|
||||
struct vc_data *vc = NULL;
|
||||
|
||||
WARN_CONSOLE_UNLOCKED();
|
||||
|
||||
if (vc_cons_allocated(currcons)) {
|
||||
struct vc_data *vc = vc_cons[currcons].d;
|
||||
struct vt_notifier_param param = { .vc = vc };
|
||||
struct vt_notifier_param param;
|
||||
|
||||
param.vc = vc = vc_cons[currcons].d;
|
||||
atomic_notifier_call_chain(&vt_notifier_list, VT_DEALLOCATE, ¶m);
|
||||
vcs_remove_sysfs(currcons);
|
||||
vc->vc_sw->con_deinit(vc);
|
||||
put_pid(vc->vt_pid);
|
||||
module_put(vc->vc_sw->owner);
|
||||
kfree(vc->vc_screenbuf);
|
||||
if (currcons >= MIN_NR_CONSOLES) {
|
||||
tty_port_destroy(&vc->port);
|
||||
kfree(vc);
|
||||
}
|
||||
vc_cons[currcons].d = NULL;
|
||||
}
|
||||
return vc;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -283,6 +283,51 @@ do_unimap_ioctl(int cmd, struct unimapdesc __user *user_ud, int perm, struct vc_
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* deallocate a single console, if possible (leave 0) */
|
||||
static int vt_disallocate(unsigned int vc_num)
|
||||
{
|
||||
struct vc_data *vc = NULL;
|
||||
int ret = 0;
|
||||
|
||||
if (!vc_num)
|
||||
return 0;
|
||||
|
||||
console_lock();
|
||||
if (VT_BUSY(vc_num))
|
||||
ret = -EBUSY;
|
||||
else
|
||||
vc = vc_deallocate(vc_num);
|
||||
console_unlock();
|
||||
|
||||
if (vc && vc_num >= MIN_NR_CONSOLES) {
|
||||
tty_port_destroy(&vc->port);
|
||||
kfree(vc);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* deallocate all unused consoles, but leave 0 */
|
||||
static void vt_disallocate_all(void)
|
||||
{
|
||||
struct vc_data *vc[MAX_NR_CONSOLES];
|
||||
int i;
|
||||
|
||||
console_lock();
|
||||
for (i = 1; i < MAX_NR_CONSOLES; i++)
|
||||
if (!VT_BUSY(i))
|
||||
vc[i] = vc_deallocate(i);
|
||||
else
|
||||
vc[i] = NULL;
|
||||
console_unlock();
|
||||
|
||||
for (i = 1; i < MAX_NR_CONSOLES; i++) {
|
||||
if (vc[i] && i >= MIN_NR_CONSOLES) {
|
||||
tty_port_destroy(&vc[i]->port);
|
||||
kfree(vc[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
@ -769,24 +814,10 @@ int vt_ioctl(struct tty_struct *tty,
|
|||
ret = -ENXIO;
|
||||
break;
|
||||
}
|
||||
if (arg == 0) {
|
||||
/* deallocate all unused consoles, but leave 0 */
|
||||
console_lock();
|
||||
for (i=1; i<MAX_NR_CONSOLES; i++)
|
||||
if (! VT_BUSY(i))
|
||||
vc_deallocate(i);
|
||||
console_unlock();
|
||||
} else {
|
||||
/* deallocate a single console, if possible */
|
||||
arg--;
|
||||
if (VT_BUSY(arg))
|
||||
ret = -EBUSY;
|
||||
else if (arg) { /* leave 0 */
|
||||
console_lock();
|
||||
vc_deallocate(arg);
|
||||
console_unlock();
|
||||
}
|
||||
}
|
||||
if (arg == 0)
|
||||
vt_disallocate_all();
|
||||
else
|
||||
ret = vt_disallocate(--arg);
|
||||
break;
|
||||
|
||||
case VT_RESIZE:
|
||||
|
|
|
@ -36,7 +36,7 @@ extern int fg_console, last_console, want_console;
|
|||
int vc_allocate(unsigned int console);
|
||||
int vc_cons_allocated(unsigned int console);
|
||||
int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines);
|
||||
void vc_deallocate(unsigned int console);
|
||||
struct vc_data *vc_deallocate(unsigned int console);
|
||||
void reset_palette(struct vc_data *vc);
|
||||
void do_blank_screen(int entering_gfx);
|
||||
void do_unblank_screen(int leaving_gfx);
|
||||
|
|
Loading…
Reference in a new issue