Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d9795562 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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 dfc7b837 (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
parents 388c2896 e037f95f
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -859,6 +859,7 @@ static int __init ehv_bc_init(void)
 */
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);
+9 −2
Original line number Diff line number Diff line
@@ -1618,8 +1618,12 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp)
				if (ip->type == PORT_16550A)
					me->fifo[p] = 1;

				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))
+8 −0
Original line number Diff line number Diff line
@@ -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);
+141 −147
Original line number Diff line number Diff line
@@ -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.
+5 −2
Original line number Diff line number Diff line
@@ -338,6 +338,7 @@ static int dw8250_runtime_suspend(struct device *dev)
{
	struct dw8250_data *data = dev_get_drvdata(dev);

	if (!IS_ERR(data->clk))
		clk_disable_unprepare(data->clk);

	return 0;
@@ -347,6 +348,7 @@ static int dw8250_runtime_resume(struct device *dev)
{
	struct dw8250_data *data = dev_get_drvdata(dev);

	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);
Loading