Merge branch 'tty-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty-2.6

* 'tty-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty-2.6: (26 commits)
  amba pl011: workaround for uart registers lockup
  n_gsm: fix the wrong FCS handling
  pch_uart: add missing comment about OKI ML7223
  pch_uart: Add MSI support
  tty: fix "IRQ45: nobody cared"
  PTI feature to allow user to name and mark masterchannel request.
  0 for o PTI Makefile bug.
  tty: serial: samsung.c remove legacy PM code.
  SERIAL: SC26xx: Fix link error.
  serial: mrst_max3110: initialize waitqueue earlier
  mrst_max3110: Change max missing message priority.
  tty: s5pv210: Add delay loop on fifo reset function for UART
  tty/serial: Fix XSCALE serial ports, e.g. ce4100
  serial: bfin_5xx: fix off-by-one with resource size
  drivers/tty: use printk_ratelimited() instead of printk_ratelimit()
  tty: n_gsm: Added refcount usage to gsm_mux and gsm_dlci structs
  tty: n_gsm: Add raw-ip support
  tty: n_gsm: expose gsmtty device nodes at ldisc open time
  pch_phub: Fix register miss-setting issue
  serial: 8250, increase PASS_LIMIT
  ...
This commit is contained in:
Linus Torvalds 2011-07-25 23:09:27 -07:00
commit d5ef642355
20 changed files with 904 additions and 188 deletions

View File

@ -6,7 +6,7 @@ obj-$(CONFIG_IBM_ASM) += ibmasm/
obj-$(CONFIG_AD525X_DPOT) += ad525x_dpot.o
obj-$(CONFIG_AD525X_DPOT_I2C) += ad525x_dpot-i2c.o
obj-$(CONFIG_AD525X_DPOT_SPI) += ad525x_dpot-spi.o
0bj-$(CONFIG_INTEL_MID_PTI) += pti.o
obj-$(CONFIG_INTEL_MID_PTI) += pti.o
obj-$(CONFIG_ATMEL_PWM) += atmel_pwm.o
obj-$(CONFIG_ATMEL_SSC) += atmel-ssc.o
obj-$(CONFIG_ATMEL_TCLIB) += atmel_tclib.o

View File

@ -735,6 +735,8 @@ static int __devinit pch_phub_probe(struct pci_dev *pdev,
* Device8(GbE)
*/
iowrite32(0x000a0000, chip->pch_phub_base_address + 0x14);
/* set the interrupt delay value */
iowrite32(0x25, chip->pch_phub_base_address + 0x140);
chip->pch_opt_rom_start_address =\
PCH_PHUB_ROM_START_ADDR_ML7223;
chip->pch_mac_start_address = PCH_PHUB_MAC_START_ADDR_ML7223;
@ -752,8 +754,6 @@ static int __devinit pch_phub_probe(struct pci_dev *pdev,
* Device6(SATA 2):f
*/
iowrite32(0x0000ffa0, chip->pch_phub_base_address + 0x14);
/* set the interrupt delay value */
iowrite32(0x25, chip->pch_phub_base_address + 0x140);
chip->pch_opt_rom_start_address =\
PCH_PHUB_ROM_START_ADDR_ML7223;
chip->pch_mac_start_address = PCH_PHUB_MAC_START_ADDR_ML7223;

View File

@ -146,45 +146,54 @@ static void pti_write_to_aperture(struct pti_masterchannel *mc,
/**
* pti_control_frame_built_and_sent()- control frame build and send function.
*
* @mc: The master / channel structure on which the function
* built a control frame.
* @mc: The master / channel structure on which the function
* built a control frame.
* @thread_name: The thread name associated with the master / channel or
* 'NULL' if using the 'current' global variable.
*
* To be able to post process the PTI contents on host side, a control frame
* is added before sending any PTI content. So the host side knows on
* each PTI frame the name of the thread using a dedicated master / channel.
* The thread name is retrieved from the 'current' global variable.
* The thread name is retrieved from 'current' global variable if 'thread_name'
* is 'NULL', else it is retrieved from 'thread_name' parameter.
* This function builds this frame and sends it to a master ID CONTROL_ID.
* The overhead is only 32 bytes since the driver only writes to HW
* in 32 byte chunks.
*/
static void pti_control_frame_built_and_sent(struct pti_masterchannel *mc)
static void pti_control_frame_built_and_sent(struct pti_masterchannel *mc,
const char *thread_name)
{
struct pti_masterchannel mccontrol = {.master = CONTROL_ID,
.channel = 0};
const char *thread_name_p;
const char *control_format = "%3d %3d %s";
u8 control_frame[CONTROL_FRAME_LEN];
/*
* Since we access the comm member in current's task_struct,
* we only need to be as large as what 'comm' in that
* structure is.
*/
char comm[TASK_COMM_LEN];
if (!thread_name) {
/*
* Since we access the comm member in current's task_struct,
* we only need to be as large as what 'comm' in that
* structure is.
*/
char comm[TASK_COMM_LEN];
if (!in_interrupt())
get_task_comm(comm, current);
else
strncpy(comm, "Interrupt", TASK_COMM_LEN);
if (!in_interrupt())
get_task_comm(comm, current);
else
strncpy(comm, "Interrupt", TASK_COMM_LEN);
/* Absolutely ensure our buffer is zero terminated. */
comm[TASK_COMM_LEN-1] = 0;
/* Absolutely ensure our buffer is zero terminated. */
comm[TASK_COMM_LEN-1] = 0;
thread_name_p = comm;
} else {
thread_name_p = thread_name;
}
mccontrol.channel = pti_control_channel;
pti_control_channel = (pti_control_channel + 1) & 0x7f;
snprintf(control_frame, CONTROL_FRAME_LEN, control_format, mc->master,
mc->channel, comm);
mc->channel, thread_name_p);
pti_write_to_aperture(&mccontrol, control_frame, strlen(control_frame));
}
@ -206,18 +215,20 @@ static void pti_write_full_frame_to_aperture(struct pti_masterchannel *mc,
const unsigned char *buf,
int len)
{
pti_control_frame_built_and_sent(mc);
pti_control_frame_built_and_sent(mc, NULL);
pti_write_to_aperture(mc, (u8 *)buf, len);
}
/**
* get_id()- Allocate a master and channel ID.
*
* @id_array: an array of bits representing what channel
* id's are allocated for writing.
* @max_ids: The max amount of available write IDs to use.
* @base_id: The starting SW channel ID, based on the Intel
* PTI arch.
* @id_array: an array of bits representing what channel
* id's are allocated for writing.
* @max_ids: The max amount of available write IDs to use.
* @base_id: The starting SW channel ID, based on the Intel
* PTI arch.
* @thread_name: The thread name associated with the master / channel or
* 'NULL' if using the 'current' global variable.
*
* Returns:
* pti_masterchannel struct with master, channel ID address
@ -227,7 +238,10 @@ static void pti_write_full_frame_to_aperture(struct pti_masterchannel *mc,
* channel id. The bit is one if the id is taken and 0 if free. For
* every master there are 128 channel id's.
*/
static struct pti_masterchannel *get_id(u8 *id_array, int max_ids, int base_id)
static struct pti_masterchannel *get_id(u8 *id_array,
int max_ids,
int base_id,
const char *thread_name)
{
struct pti_masterchannel *mc;
int i, j, mask;
@ -257,7 +271,7 @@ static struct pti_masterchannel *get_id(u8 *id_array, int max_ids, int base_id)
mc->master = base_id;
mc->channel = ((i & 0xf)<<3) + j;
/* write new master Id / channel Id allocation to channel control */
pti_control_frame_built_and_sent(mc);
pti_control_frame_built_and_sent(mc, thread_name);
return mc;
}
@ -273,18 +287,22 @@ static struct pti_masterchannel *get_id(u8 *id_array, int max_ids, int base_id)
* a master, channel ID address
* to write to PTI HW.
*
* @type: 0- request Application master, channel aperture ID write address.
* 1- request OS master, channel aperture ID write
* address.
* 2- request Modem master, channel aperture ID
* write address.
* Other values, error.
* @type: 0- request Application master, channel aperture ID
* write address.
* 1- request OS master, channel aperture ID write
* address.
* 2- request Modem master, channel aperture ID
* write address.
* Other values, error.
* @thread_name: The thread name associated with the master / channel or
* 'NULL' if using the 'current' global variable.
*
* Returns:
* pti_masterchannel struct
* 0 for error
*/
struct pti_masterchannel *pti_request_masterchannel(u8 type)
struct pti_masterchannel *pti_request_masterchannel(u8 type,
const char *thread_name)
{
struct pti_masterchannel *mc;
@ -293,15 +311,18 @@ struct pti_masterchannel *pti_request_masterchannel(u8 type)
switch (type) {
case 0:
mc = get_id(drv_data->ia_app, MAX_APP_IDS, APP_BASE_ID);
mc = get_id(drv_data->ia_app, MAX_APP_IDS,
APP_BASE_ID, thread_name);
break;
case 1:
mc = get_id(drv_data->ia_os, MAX_OS_IDS, OS_BASE_ID);
mc = get_id(drv_data->ia_os, MAX_OS_IDS,
OS_BASE_ID, thread_name);
break;
case 2:
mc = get_id(drv_data->ia_modem, MAX_MODEM_IDS, MODEM_BASE_ID);
mc = get_id(drv_data->ia_modem, MAX_MODEM_IDS,
MODEM_BASE_ID, thread_name);
break;
default:
mc = NULL;
@ -472,9 +493,9 @@ static int pti_tty_install(struct tty_driver *driver, struct tty_struct *tty)
return -ENOMEM;
if (idx == PTITTY_MINOR_START)
pti_tty_data->mc = pti_request_masterchannel(0);
pti_tty_data->mc = pti_request_masterchannel(0, NULL);
else
pti_tty_data->mc = pti_request_masterchannel(2);
pti_tty_data->mc = pti_request_masterchannel(2, NULL);
if (pti_tty_data->mc == NULL) {
kfree(pti_tty_data);
@ -563,7 +584,7 @@ static int pti_char_open(struct inode *inode, struct file *filp)
* before assigning the value to filp->private_data.
* Slightly easier to debug if this driver needs debugging.
*/
mc = pti_request_masterchannel(0);
mc = pti_request_masterchannel(0, NULL);
if (mc == NULL)
return -ENOMEM;
filp->private_data = mc;

View File

@ -2864,24 +2864,6 @@ enum parport_pc_pci_cards {
lava_parallel_dual_b,
boca_ioppar,
plx_9050,
timedia_4078a,
timedia_4079h,
timedia_4085h,
timedia_4088a,
timedia_4089a,
timedia_4095a,
timedia_4096a,
timedia_4078u,
timedia_4079a,
timedia_4085u,
timedia_4079r,
timedia_4079s,
timedia_4079d,
timedia_4079e,
timedia_4079f,
timedia_9079a,
timedia_9079b,
timedia_9079c,
timedia_4006a,
timedia_4014,
timedia_4008a,
@ -2940,24 +2922,6 @@ static struct parport_pc_pci {
/* lava_parallel_dual_b */ { 1, { { 0, -1 }, } },
/* boca_ioppar */ { 1, { { 0, -1 }, } },
/* plx_9050 */ { 2, { { 4, -1 }, { 5, -1 }, } },
/* timedia_4078a */ { 1, { { 2, -1 }, } },
/* timedia_4079h */ { 1, { { 2, 3 }, } },
/* timedia_4085h */ { 2, { { 2, -1 }, { 4, -1 }, } },
/* timedia_4088a */ { 2, { { 2, 3 }, { 4, 5 }, } },
/* timedia_4089a */ { 2, { { 2, 3 }, { 4, 5 }, } },
/* timedia_4095a */ { 2, { { 2, 3 }, { 4, 5 }, } },
/* timedia_4096a */ { 2, { { 2, 3 }, { 4, 5 }, } },
/* timedia_4078u */ { 1, { { 2, -1 }, } },
/* timedia_4079a */ { 1, { { 2, 3 }, } },
/* timedia_4085u */ { 2, { { 2, -1 }, { 4, -1 }, } },
/* timedia_4079r */ { 1, { { 2, 3 }, } },
/* timedia_4079s */ { 1, { { 2, 3 }, } },
/* timedia_4079d */ { 1, { { 2, 3 }, } },
/* timedia_4079e */ { 1, { { 2, 3 }, } },
/* timedia_4079f */ { 1, { { 2, 3 }, } },
/* timedia_9079a */ { 1, { { 2, 3 }, } },
/* timedia_9079b */ { 1, { { 2, 3 }, } },
/* timedia_9079c */ { 1, { { 2, 3 }, } },
/* timedia_4006a */ { 1, { { 0, -1 }, } },
/* timedia_4014 */ { 2, { { 0, -1 }, { 2, -1 }, } },
/* timedia_4008a */ { 1, { { 0, 1 }, } },
@ -3019,24 +2983,6 @@ static const struct pci_device_id parport_pc_pci_tbl[] = {
{ PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
PCI_SUBVENDOR_ID_EXSYS, PCI_SUBDEVICE_ID_EXSYS_4014, 0, 0, plx_9050 },
/* PCI_VENDOR_ID_TIMEDIA/SUNIX has many differing cards ...*/
{ 0x1409, 0x7168, 0x1409, 0x4078, 0, 0, timedia_4078a },
{ 0x1409, 0x7168, 0x1409, 0x4079, 0, 0, timedia_4079h },
{ 0x1409, 0x7168, 0x1409, 0x4085, 0, 0, timedia_4085h },
{ 0x1409, 0x7168, 0x1409, 0x4088, 0, 0, timedia_4088a },
{ 0x1409, 0x7168, 0x1409, 0x4089, 0, 0, timedia_4089a },
{ 0x1409, 0x7168, 0x1409, 0x4095, 0, 0, timedia_4095a },
{ 0x1409, 0x7168, 0x1409, 0x4096, 0, 0, timedia_4096a },
{ 0x1409, 0x7168, 0x1409, 0x5078, 0, 0, timedia_4078u },
{ 0x1409, 0x7168, 0x1409, 0x5079, 0, 0, timedia_4079a },
{ 0x1409, 0x7168, 0x1409, 0x5085, 0, 0, timedia_4085u },
{ 0x1409, 0x7168, 0x1409, 0x6079, 0, 0, timedia_4079r },
{ 0x1409, 0x7168, 0x1409, 0x7079, 0, 0, timedia_4079s },
{ 0x1409, 0x7168, 0x1409, 0x8079, 0, 0, timedia_4079d },
{ 0x1409, 0x7168, 0x1409, 0x9079, 0, 0, timedia_4079e },
{ 0x1409, 0x7168, 0x1409, 0xa079, 0, 0, timedia_4079f },
{ 0x1409, 0x7168, 0x1409, 0xb079, 0, 0, timedia_9079a },
{ 0x1409, 0x7168, 0x1409, 0xc079, 0, 0, timedia_9079b },
{ 0x1409, 0x7168, 0x1409, 0xd079, 0, 0, timedia_9079c },
{ 0x1409, 0x7268, 0x1409, 0x0101, 0, 0, timedia_4006a },
{ 0x1409, 0x7268, 0x1409, 0x0102, 0, 0, timedia_4014 },
{ 0x1409, 0x7268, 0x1409, 0x0103, 0, 0, timedia_4008a },

View File

@ -33,6 +33,9 @@ enum parport_pc_pci_cards {
netmos_9xx5_combo,
netmos_9855,
netmos_9855_2p,
netmos_9900,
netmos_9900_2p,
netmos_99xx_1p,
avlab_1s1p,
avlab_1s2p,
avlab_2s1p,
@ -41,6 +44,24 @@ enum parport_pc_pci_cards {
siig_2p1s_20x,
siig_1s1p_20x,
siig_2s1p_20x,
timedia_4078a,
timedia_4079h,
timedia_4085h,
timedia_4088a,
timedia_4089a,
timedia_4095a,
timedia_4096a,
timedia_4078u,
timedia_4079a,
timedia_4085u,
timedia_4079r,
timedia_4079s,
timedia_4079d,
timedia_4079e,
timedia_4079f,
timedia_9079a,
timedia_9079b,
timedia_9079c,
};
/* each element directly indexed from enum list, above */
@ -72,22 +93,20 @@ static int __devinit netmos_parallel_init(struct pci_dev *dev, struct parport_pc
dev->subsystem_vendor == PCI_VENDOR_ID_IBM &&
dev->subsystem_device == 0x0299)
return -ENODEV;
/*
* Netmos uses the subdevice ID to indicate the number of parallel
* and serial ports. The form is 0x00PS, where <P> is the number of
* parallel ports and <S> is the number of serial ports.
*/
par->numports = (dev->subsystem_device & 0xf0) >> 4;
if (par->numports > ARRAY_SIZE(par->addr))
par->numports = ARRAY_SIZE(par->addr);
/*
* This function is currently only called for cards with up to
* one parallel port.
* Parallel port BAR is either before or after serial ports BARS;
* hence, lo should be either 0 or equal to the number of serial ports.
*/
if (par->addr[0].lo != 0)
par->addr[0].lo = dev->subsystem_device & 0xf;
if (dev->device == PCI_DEVICE_ID_NETMOS_9912) {
par->numports = 1;
} else {
/*
* Netmos uses the subdevice ID to indicate the number of parallel
* and serial ports. The form is 0x00PS, where <P> is the number of
* parallel ports and <S> is the number of serial ports.
*/
par->numports = (dev->subsystem_device & 0xf0) >> 4;
if (par->numports > ARRAY_SIZE(par->addr))
par->numports = ARRAY_SIZE(par->addr);
}
return 0;
}
@ -97,6 +116,9 @@ static struct parport_pc_pci cards[] __devinitdata = {
/* netmos_9xx5_combo */ { 1, { { 2, -1 }, }, netmos_parallel_init },
/* netmos_9855 */ { 1, { { 0, -1 }, }, netmos_parallel_init },
/* netmos_9855_2p */ { 2, { { 0, -1 }, { 2, -1 }, } },
/* netmos_9900 */ {1, { { 3, 4 }, }, netmos_parallel_init },
/* netmos_9900_2p */ {2, { { 0, 1 }, { 3, 4 }, } },
/* netmos_99xx_1p */ {1, { { 0, 1 }, } },
/* avlab_1s1p */ { 1, { { 1, 2}, } },
/* avlab_1s2p */ { 2, { { 1, 2}, { 3, 4 },} },
/* avlab_2s1p */ { 1, { { 2, 3}, } },
@ -105,6 +127,24 @@ static struct parport_pc_pci cards[] __devinitdata = {
/* siig_2p1s_20x */ { 2, { { 1, 2 }, { 3, 4 }, } },
/* siig_1s1p_20x */ { 1, { { 1, 2 }, } },
/* siig_2s1p_20x */ { 1, { { 2, 3 }, } },
/* timedia_4078a */ { 1, { { 2, -1 }, } },
/* timedia_4079h */ { 1, { { 2, 3 }, } },
/* timedia_4085h */ { 2, { { 2, -1 }, { 4, -1 }, } },
/* timedia_4088a */ { 2, { { 2, 3 }, { 4, 5 }, } },
/* timedia_4089a */ { 2, { { 2, 3 }, { 4, 5 }, } },
/* timedia_4095a */ { 2, { { 2, 3 }, { 4, 5 }, } },
/* timedia_4096a */ { 2, { { 2, 3 }, { 4, 5 }, } },
/* timedia_4078u */ { 1, { { 2, -1 }, } },
/* timedia_4079a */ { 1, { { 2, 3 }, } },
/* timedia_4085u */ { 2, { { 2, -1 }, { 4, -1 }, } },
/* timedia_4079r */ { 1, { { 2, 3 }, } },
/* timedia_4079s */ { 1, { { 2, 3 }, } },
/* timedia_4079d */ { 1, { { 2, 3 }, } },
/* timedia_4079e */ { 1, { { 2, 3 }, } },
/* timedia_4079f */ { 1, { { 2, 3 }, } },
/* timedia_9079a */ { 1, { { 2, 3 }, } },
/* timedia_9079b */ { 1, { { 2, 3 }, } },
/* timedia_9079c */ { 1, { { 2, 3 }, } },
};
static struct pci_device_id parport_serial_pci_tbl[] = {
@ -127,6 +167,14 @@ static struct pci_device_id parport_serial_pci_tbl[] = {
0x1000, 0x0022, 0, 0, netmos_9855_2p },
{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9855,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9855 },
{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9900,
0xA000, 0x3011, 0, 0, netmos_9900 },
{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9900,
0xA000, 0x3012, 0, 0, netmos_9900 },
{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9900,
0xA000, 0x3020, 0, 0, netmos_9900_2p },
{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9912,
0xA000, 0x2000, 0, 0, netmos_99xx_1p },
/* PCI_VENDOR_ID_AVLAB/Intek21 has another bunch of cards ...*/
{ PCI_VENDOR_ID_AFAVLAB, 0x2110,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s1p },
@ -176,6 +224,25 @@ static struct pci_device_id parport_serial_pci_tbl[] = {
PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_20x },
{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_850,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_20x },
/* PCI_VENDOR_ID_TIMEDIA/SUNIX has many differing cards ...*/
{ 0x1409, 0x7168, 0x1409, 0x4078, 0, 0, timedia_4078a },
{ 0x1409, 0x7168, 0x1409, 0x4079, 0, 0, timedia_4079h },
{ 0x1409, 0x7168, 0x1409, 0x4085, 0, 0, timedia_4085h },
{ 0x1409, 0x7168, 0x1409, 0x4088, 0, 0, timedia_4088a },
{ 0x1409, 0x7168, 0x1409, 0x4089, 0, 0, timedia_4089a },
{ 0x1409, 0x7168, 0x1409, 0x4095, 0, 0, timedia_4095a },
{ 0x1409, 0x7168, 0x1409, 0x4096, 0, 0, timedia_4096a },
{ 0x1409, 0x7168, 0x1409, 0x5078, 0, 0, timedia_4078u },
{ 0x1409, 0x7168, 0x1409, 0x5079, 0, 0, timedia_4079a },
{ 0x1409, 0x7168, 0x1409, 0x5085, 0, 0, timedia_4085u },
{ 0x1409, 0x7168, 0x1409, 0x6079, 0, 0, timedia_4079r },
{ 0x1409, 0x7168, 0x1409, 0x7079, 0, 0, timedia_4079s },
{ 0x1409, 0x7168, 0x1409, 0x8079, 0, 0, timedia_4079d },
{ 0x1409, 0x7168, 0x1409, 0x9079, 0, 0, timedia_4079e },
{ 0x1409, 0x7168, 0x1409, 0xa079, 0, 0, timedia_4079f },
{ 0x1409, 0x7168, 0x1409, 0xb079, 0, 0, timedia_9079a },
{ 0x1409, 0x7168, 0x1409, 0xc079, 0, 0, timedia_9079b },
{ 0x1409, 0x7168, 0x1409, 0xd079, 0, 0, timedia_9079c },
{ 0, } /* terminate list */
};
@ -219,6 +286,24 @@ static struct pciserial_board pci_parport_serial_boards[] __devinitdata = {
.base_baud = 115200,
.uart_offset = 8,
},
[netmos_9900] = { /* n/t */
.flags = FL_BASE0 | FL_BASE_BARS,
.num_ports = 1,
.base_baud = 115200,
.uart_offset = 8,
},
[netmos_9900_2p] = { /* parallel only */ /* n/t */
.flags = FL_BASE0,
.num_ports = 0,
.base_baud = 115200,
.uart_offset = 8,
},
[netmos_99xx_1p] = { /* parallel only */ /* n/t */
.flags = FL_BASE0,
.num_ports = 0,
.base_baud = 115200,
.uart_offset = 8,
},
[avlab_1s1p] = { /* n/t */
.flags = FL_BASE0 | FL_BASE_BARS,
.num_ports = 1,
@ -267,6 +352,114 @@ static struct pciserial_board pci_parport_serial_boards[] __devinitdata = {
.base_baud = 921600,
.uart_offset = 8,
},
[timedia_4078a] = {
.flags = FL_BASE0|FL_BASE_BARS,
.num_ports = 1,
.base_baud = 921600,
.uart_offset = 8,
},
[timedia_4079h] = {
.flags = FL_BASE0|FL_BASE_BARS,
.num_ports = 1,
.base_baud = 921600,
.uart_offset = 8,
},
[timedia_4085h] = {
.flags = FL_BASE0|FL_BASE_BARS,
.num_ports = 1,
.base_baud = 921600,
.uart_offset = 8,
},
[timedia_4088a] = {
.flags = FL_BASE0|FL_BASE_BARS,
.num_ports = 1,
.base_baud = 921600,
.uart_offset = 8,
},
[timedia_4089a] = {
.flags = FL_BASE0|FL_BASE_BARS,
.num_ports = 1,
.base_baud = 921600,
.uart_offset = 8,
},
[timedia_4095a] = {
.flags = FL_BASE0|FL_BASE_BARS,
.num_ports = 1,
.base_baud = 921600,
.uart_offset = 8,
},
[timedia_4096a] = {
.flags = FL_BASE0|FL_BASE_BARS,
.num_ports = 1,
.base_baud = 921600,
.uart_offset = 8,
},
[timedia_4078u] = {
.flags = FL_BASE0|FL_BASE_BARS,
.num_ports = 1,
.base_baud = 921600,
.uart_offset = 8,
},
[timedia_4079a] = {
.flags = FL_BASE0|FL_BASE_BARS,
.num_ports = 1,
.base_baud = 921600,
.uart_offset = 8,
},
[timedia_4085u] = {
.flags = FL_BASE0|FL_BASE_BARS,
.num_ports = 1,
.base_baud = 921600,
.uart_offset = 8,
},
[timedia_4079r] = {
.flags = FL_BASE0|FL_BASE_BARS,
.num_ports = 1,
.base_baud = 921600,
.uart_offset = 8,
},
[timedia_4079s] = {
.flags = FL_BASE0|FL_BASE_BARS,
.num_ports = 1,
.base_baud = 921600,
.uart_offset = 8,
},
[timedia_4079d] = {
.flags = FL_BASE0|FL_BASE_BARS,
.num_ports = 1,
.base_baud = 921600,
.uart_offset = 8,
},
[timedia_4079e] = {
.flags = FL_BASE0|FL_BASE_BARS,
.num_ports = 1,
.base_baud = 921600,
.uart_offset = 8,
},
[timedia_4079f] = {
.flags = FL_BASE0|FL_BASE_BARS,
.num_ports = 1,
.base_baud = 921600,
.uart_offset = 8,
},
[timedia_9079a] = {
.flags = FL_BASE0|FL_BASE_BARS,
.num_ports = 1,
.base_baud = 921600,
.uart_offset = 8,
},
[timedia_9079b] = {
.flags = FL_BASE0|FL_BASE_BARS,
.num_ports = 1,
.base_baud = 921600,
.uart_offset = 8,
},
[timedia_9079c] = {
.flags = FL_BASE0|FL_BASE_BARS,
.num_ports = 1,
.base_baud = 921600,
.uart_offset = 8,
},
};
struct parport_serial_private {
@ -285,6 +478,10 @@ static int __devinit serial_register (struct pci_dev *dev,
struct serial_private *serial;
board = &pci_parport_serial_boards[id->driver_data];
if (board->num_ports == 0)
return 0;
serial = pciserial_init_ports(dev, board);
if (IS_ERR(serial))

View File

@ -44,6 +44,7 @@
#include <linux/init.h>
#include <linux/bitops.h>
#include <linux/slab.h>
#include <linux/ratelimit.h>
#include <asm/system.h>
#include <asm/io.h>
@ -242,8 +243,8 @@ static void moxa_wait_finish(void __iomem *ofsAddr)
while (readw(ofsAddr + FuncCode) != 0)
if (time_after(jiffies, end))
return;
if (readw(ofsAddr + FuncCode) != 0 && printk_ratelimit())
printk(KERN_WARNING "moxa function expired\n");
if (readw(ofsAddr + FuncCode) != 0)
printk_ratelimited(KERN_WARNING "moxa function expired\n");
}
static void moxafunc(void __iomem *ofsAddr, u16 cmd, u16 arg)

View File

@ -39,6 +39,7 @@
#include <linux/pci.h>
#include <linux/bitops.h>
#include <linux/slab.h>
#include <linux/ratelimit.h>
#include <asm/system.h>
#include <asm/io.h>
@ -1490,8 +1491,7 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp)
switch (cmd) {
case MOXA_GET_MAJOR:
if (printk_ratelimit())
printk(KERN_WARNING "mxser: '%s' uses deprecated ioctl "
printk_ratelimited(KERN_WARNING "mxser: '%s' uses deprecated ioctl "
"%x (GET_MAJOR), fix your userspace\n",
current->comm, cmd);
return put_user(ttymajor, (int __user *)argp);

View File

@ -58,6 +58,10 @@
#include <linux/serial.h>
#include <linux/kfifo.h>
#include <linux/skbuff.h>
#include <net/arp.h>
#include <linux/ip.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/gsmmux.h>
static int debug;
@ -77,8 +81,24 @@ module_param(debug, int, 0600);
* Semi-arbitrary buffer size limits. 0710 is normally run with 32-64 byte
* limits so this is plenty
*/
#define MAX_MRU 512
#define MAX_MTU 512
#define MAX_MRU 1500
#define MAX_MTU 1500
#define GSM_NET_TX_TIMEOUT (HZ*10)
/**
* struct gsm_mux_net - network interface
* @struct gsm_dlci* dlci
* @struct net_device_stats stats;
*
* Created when net interface is initialized.
**/
struct gsm_mux_net {
struct kref ref;
struct gsm_dlci *dlci;
struct net_device_stats stats;
};
#define STATS(net) (((struct gsm_mux_net *)netdev_priv(net))->stats)
/*
* Each block of data we have queued to go out is in the form of
@ -113,6 +133,8 @@ struct gsm_dlci {
#define DLCI_OPENING 1 /* Sending SABM not seen UA */
#define DLCI_OPEN 2 /* SABM/UA complete */
#define DLCI_CLOSING 3 /* Sending DISC not seen UA/DM */
struct kref ref; /* freed from port or mux close */
struct mutex mutex;
/* Link layer */
spinlock_t lock; /* Protects the internal state */
@ -123,6 +145,7 @@ struct gsm_dlci {
struct kfifo *fifo; /* Queue fifo for the DLCI */
struct kfifo _fifo; /* For new fifo API porting only */
int adaption; /* Adaption layer in use */
int prev_adaption;
u32 modem_rx; /* Our incoming virtual modem lines */
u32 modem_tx; /* Our outgoing modem lines */
int dead; /* Refuse re-open */
@ -134,6 +157,8 @@ struct gsm_dlci {
struct sk_buff_head skb_list; /* Queued frames */
/* Data handling callback */
void (*data)(struct gsm_dlci *dlci, u8 *data, int len);
void (*prev_data)(struct gsm_dlci *dlci, u8 *data, int len);
struct net_device *net; /* network interface, if created */
};
/* DLCI 0, 62/63 are special or reseved see gsmtty_open */
@ -169,6 +194,8 @@ struct gsm_control {
struct gsm_mux {
struct tty_struct *tty; /* The tty our ldisc is bound to */
spinlock_t lock;
unsigned int num;
struct kref ref;
/* Events on the GSM channel */
wait_queue_head_t event;
@ -250,6 +277,8 @@ struct gsm_mux {
static struct gsm_mux *gsm_mux[MAX_MUX]; /* GSM muxes */
static spinlock_t gsm_mux_lock;
static struct tty_driver *gsm_tty_driver;
/*
* This section of the driver logic implements the GSM encodings
* both the basic and the 'advanced'. Reliable transport is not
@ -878,8 +907,10 @@ static int gsm_dlci_data_output_framed(struct gsm_mux *gsm,
memcpy(dp, dlci->skb->data, len);
skb_pull(dlci->skb, len);
__gsm_data_queue(dlci, msg);
if (last)
if (last) {
kfree_skb(dlci->skb);
dlci->skb = NULL;
}
return size;
}
@ -912,7 +943,7 @@ static void gsm_dlci_data_sweep(struct gsm_mux *gsm)
i++;
continue;
}
if (dlci->adaption < 3)
if (dlci->adaption < 3 && !dlci->net)
len = gsm_dlci_data_output(gsm, dlci);
else
len = gsm_dlci_data_output_framed(gsm, dlci);
@ -939,9 +970,12 @@ static void gsm_dlci_data_kick(struct gsm_dlci *dlci)
spin_lock_irqsave(&dlci->gsm->tx_lock, flags);
/* If we have nothing running then we need to fire up */
if (dlci->gsm->tx_bytes == 0)
gsm_dlci_data_output(dlci->gsm, dlci);
else if (dlci->gsm->tx_bytes < TX_THRESH_LO)
if (dlci->gsm->tx_bytes == 0) {
if (dlci->net)
gsm_dlci_data_output_framed(dlci->gsm, dlci);
else
gsm_dlci_data_output(dlci->gsm, dlci);
} else if (dlci->gsm->tx_bytes < TX_THRESH_LO)
gsm_dlci_data_sweep(dlci->gsm);
spin_unlock_irqrestore(&dlci->gsm->tx_lock, flags);
}
@ -1588,6 +1622,8 @@ static struct gsm_dlci *gsm_dlci_alloc(struct gsm_mux *gsm, int addr)
if (dlci == NULL)
return NULL;
spin_lock_init(&dlci->lock);
kref_init(&dlci->ref);
mutex_init(&dlci->mutex);
dlci->fifo = &dlci->_fifo;
if (kfifo_alloc(&dlci->_fifo, 4096, GFP_KERNEL) < 0) {
kfree(dlci);
@ -1613,26 +1649,52 @@ static struct gsm_dlci *gsm_dlci_alloc(struct gsm_mux *gsm, int addr)
}
/**
* gsm_dlci_free - release DLCI
* @dlci: DLCI to destroy
* gsm_dlci_free - free DLCI
* @dlci: DLCI to free
*
* Free up a DLCI. Currently to keep the lifetime rules sane we only
* clean up DLCI objects when the MUX closes rather than as the port
* is closed down on both the tty and mux levels.
* Free up a DLCI.
*
* Can sleep.
*/
static void gsm_dlci_free(struct gsm_dlci *dlci)
static void gsm_dlci_free(struct kref *ref)
{
struct gsm_dlci *dlci = container_of(ref, struct gsm_dlci, ref);
del_timer_sync(&dlci->t1);
dlci->gsm->dlci[dlci->addr] = NULL;
kfifo_free(dlci->fifo);
while ((dlci->skb = skb_dequeue(&dlci->skb_list)))
kfree_skb(dlci->skb);
kfree(dlci);
}
static inline void dlci_get(struct gsm_dlci *dlci)
{
kref_get(&dlci->ref);
}
static inline void dlci_put(struct gsm_dlci *dlci)
{
kref_put(&dlci->ref, gsm_dlci_free);
}
/**
* gsm_dlci_release - release DLCI
* @dlci: DLCI to destroy
*
* Release a DLCI. Actual free is deferred until either
* mux is closed or tty is closed - whichever is last.
*
* Can sleep.
*/
static void gsm_dlci_release(struct gsm_dlci *dlci)
{
struct tty_struct *tty = tty_port_tty_get(&dlci->port);
if (tty) {
tty_vhangup(tty);
tty_kref_put(tty);
}
del_timer_sync(&dlci->t1);
dlci->gsm->dlci[dlci->addr] = NULL;
kfifo_free(dlci->fifo);
kfree(dlci);
dlci_put(dlci);
}
/*
@ -1823,10 +1885,6 @@ static void gsm0_receive(struct gsm_mux *gsm, unsigned char c)
break;
case GSM_FCS: /* FCS follows the packet */
gsm->received_fcs = c;
if (c == GSM0_SOF) {
gsm->state = GSM_SEARCH;
break;
}
gsm_queue(gsm);
gsm->state = GSM_SSOF;
break;
@ -1970,7 +2028,7 @@ void gsm_cleanup_mux(struct gsm_mux *gsm)
/* Free up any link layer users */
for (i = 0; i < NUM_DLCI; i++)
if (gsm->dlci[i])
gsm_dlci_free(gsm->dlci[i]);
gsm_dlci_release(gsm->dlci[i]);
/* Now wipe the queues */
for (txq = gsm->tx_head; txq != NULL; txq = gsm->tx_head) {
gsm->tx_head = txq->next;
@ -2010,6 +2068,7 @@ int gsm_activate_mux(struct gsm_mux *gsm)
spin_lock(&gsm_mux_lock);
for (i = 0; i < MAX_MUX; i++) {
if (gsm_mux[i] == NULL) {
gsm->num = i;
gsm_mux[i] = gsm;
break;
}
@ -2030,8 +2089,7 @@ EXPORT_SYMBOL_GPL(gsm_activate_mux);
* gsm_free_mux - free up a mux
* @mux: mux to free
*
* Dispose of allocated resources for a dead mux. No refcounting
* at present so the mux must be truly dead.
* Dispose of allocated resources for a dead mux
*/
void gsm_free_mux(struct gsm_mux *gsm)
{
@ -2041,6 +2099,28 @@ void gsm_free_mux(struct gsm_mux *gsm)
}
EXPORT_SYMBOL_GPL(gsm_free_mux);
/**
* gsm_free_muxr - free up a mux
* @mux: mux to free
*
* Dispose of allocated resources for a dead mux
*/
static void gsm_free_muxr(struct kref *ref)
{
struct gsm_mux *gsm = container_of(ref, struct gsm_mux, ref);
gsm_free_mux(gsm);
}
static inline void mux_get(struct gsm_mux *gsm)
{
kref_get(&gsm->ref);
}
static inline void mux_put(struct gsm_mux *gsm)
{
kref_put(&gsm->ref, gsm_free_muxr);
}
/**
* gsm_alloc_mux - allocate a mux
*
@ -2064,12 +2144,12 @@ struct gsm_mux *gsm_alloc_mux(void)
return NULL;
}
spin_lock_init(&gsm->lock);
kref_init(&gsm->ref);
gsm->t1 = T1;
gsm->t2 = T2;
gsm->n2 = N2;
gsm->ftype = UIH;
gsm->initiator = 0;
gsm->adaption = 1;
gsm->encoding = 1;
gsm->mru = 64; /* Default to encoding 1 so these should be 64 */
@ -2115,13 +2195,20 @@ static int gsmld_output(struct gsm_mux *gsm, u8 *data, int len)
static int gsmld_attach_gsm(struct tty_struct *tty, struct gsm_mux *gsm)
{
int ret;
int ret, i;
int base = gsm->num << 6; /* Base for this MUX */
gsm->tty = tty_kref_get(tty);
gsm->output = gsmld_output;
ret = gsm_activate_mux(gsm);
if (ret != 0)
tty_kref_put(gsm->tty);
else {
/* Don't register device 0 - this is the control channel and not
a usable tty interface */
for (i = 1; i < NUM_DLCI; i++)
tty_register_device(gsm_tty_driver, base + i, NULL);
}
return ret;
}
@ -2136,7 +2223,12 @@ static int gsmld_attach_gsm(struct tty_struct *tty, struct gsm_mux *gsm)
static void gsmld_detach_gsm(struct tty_struct *tty, struct gsm_mux *gsm)
{
int i;
int base = gsm->num << 6; /* Base for this MUX */
WARN_ON(tty != gsm->tty);
for (i = 1; i < NUM_DLCI; i++)
tty_unregister_device(gsm_tty_driver, base + i);
gsm_cleanup_mux(gsm);
tty_kref_put(gsm->tty);
gsm->tty = NULL;
@ -2224,7 +2316,7 @@ static void gsmld_close(struct tty_struct *tty)
gsmld_flush_buffer(tty);
/* Do other clean up here */
gsm_free_mux(gsm);
mux_put(gsm);
}
/**
@ -2476,6 +2568,220 @@ static int gsmld_ioctl(struct tty_struct *tty, struct file *file,
}
}
/*
* Network interface
*
*/
static int gsm_mux_net_open(struct net_device *net)
{
pr_debug("%s called\n", __func__);
netif_start_queue(net);
return 0;
}
static int gsm_mux_net_close(struct net_device *net)
{
netif_stop_queue(net);
return 0;
}
static struct net_device_stats *gsm_mux_net_get_stats(struct net_device *net)
{
return &((struct gsm_mux_net *)netdev_priv(net))->stats;
}
static void dlci_net_free(struct gsm_dlci *dlci)
{
if (!dlci->net) {
WARN_ON(1);
return;
}
dlci->adaption = dlci->prev_adaption;
dlci->data = dlci->prev_data;
free_netdev(dlci->net);
dlci->net = NULL;
}
static void net_free(struct kref *ref)
{
struct gsm_mux_net *mux_net;
struct gsm_dlci *dlci;
mux_net = container_of(ref, struct gsm_mux_net, ref);
dlci = mux_net->dlci;
if (dlci->net) {
unregister_netdev(dlci->net);
dlci_net_free(dlci);
}
}
static inline void muxnet_get(struct gsm_mux_net *mux_net)
{
kref_get(&mux_net->ref);
}
static inline void muxnet_put(struct gsm_mux_net *mux_net)
{
kref_put(&mux_net->ref, net_free);
}
static int gsm_mux_net_start_xmit(struct sk_buff *skb,
struct net_device *net)
{
struct gsm_mux_net *mux_net = (struct gsm_mux_net *)netdev_priv(net);
struct gsm_dlci *dlci = mux_net->dlci;
muxnet_get(mux_net);
skb_queue_head(&dlci->skb_list, skb);
STATS(net).tx_packets++;
STATS(net).tx_bytes += skb->len;
gsm_dlci_data_kick(dlci);
/* And tell the kernel when the last transmit started. */
net->trans_start = jiffies;
muxnet_put(mux_net);
return NETDEV_TX_OK;
}
/* called when a packet did not ack after watchdogtimeout */
static void gsm_mux_net_tx_timeout(struct net_device *net)
{
/* Tell syslog we are hosed. */
dev_dbg(&net->dev, "Tx timed out.\n");
/* Update statistics */
STATS(net).tx_errors++;
}
static void gsm_mux_rx_netchar(struct gsm_dlci *dlci,
unsigned char *in_buf, int size)
{
struct net_device *net = dlci->net;
struct sk_buff *skb;
struct gsm_mux_net *mux_net = (struct gsm_mux_net *)netdev_priv(net);
muxnet_get(mux_net);
/* Allocate an sk_buff */
skb = dev_alloc_skb(size + NET_IP_ALIGN);
if (!skb) {
/* We got no receive buffer. */
STATS(net).rx_dropped++;
muxnet_put(mux_net);
return;
}
skb_reserve(skb, NET_IP_ALIGN);
memcpy(skb_put(skb, size), in_buf, size);
skb->dev = net;
skb->protocol = __constant_htons(ETH_P_IP);
/* Ship it off to the kernel */
netif_rx(skb);
/* update out statistics */
STATS(net).rx_packets++;
STATS(net).rx_bytes += size;
muxnet_put(mux_net);
return;
}
int gsm_change_mtu(struct net_device *net, int new_mtu)
{
struct gsm_mux_net *mux_net = (struct gsm_mux_net *)netdev_priv(net);
if ((new_mtu < 8) || (new_mtu > mux_net->dlci->gsm->mtu))
return -EINVAL;
net->mtu = new_mtu;
return 0;
}
static void gsm_mux_net_init(struct net_device *net)
{
static const struct net_device_ops gsm_netdev_ops = {
.ndo_open = gsm_mux_net_open,
.ndo_stop = gsm_mux_net_close,
.ndo_start_xmit = gsm_mux_net_start_xmit,
.ndo_tx_timeout = gsm_mux_net_tx_timeout,
.ndo_get_stats = gsm_mux_net_get_stats,
.ndo_change_mtu = gsm_change_mtu,
};
net->netdev_ops = &gsm_netdev_ops;
/* fill in the other fields */
net->watchdog_timeo = GSM_NET_TX_TIMEOUT;
net->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST;
net->type = ARPHRD_NONE;
net->tx_queue_len = 10;
}
/* caller holds the dlci mutex */
static void gsm_destroy_network(struct gsm_dlci *dlci)
{
struct gsm_mux_net *mux_net;
pr_debug("destroy network interface");
if (!dlci->net)
return;
mux_net = (struct gsm_mux_net *)netdev_priv(dlci->net);
muxnet_put(mux_net);
}
/* caller holds the dlci mutex */
static int gsm_create_network(struct gsm_dlci *dlci, struct gsm_netconfig *nc)
{
char *netname;
int retval = 0;
struct net_device *net;
struct gsm_mux_net *mux_net;
if (!capable(CAP_NET_ADMIN))
return -EPERM;
/* Already in a non tty mode */
if (dlci->adaption > 2)
return -EBUSY;
if (nc->protocol != htons(ETH_P_IP))
return -EPROTONOSUPPORT;
if (nc->adaption != 3 && nc->adaption != 4)
return -EPROTONOSUPPORT;
pr_debug("create network interface");
netname = "gsm%d";
if (nc->if_name[0] != '\0')
netname = nc->if_name;
net = alloc_netdev(sizeof(struct gsm_mux_net),
netname,
gsm_mux_net_init);
if (!net) {
pr_err("alloc_netdev failed");
return -ENOMEM;
}
net->mtu = dlci->gsm->mtu;
mux_net = (struct gsm_mux_net *)netdev_priv(net);
mux_net->dlci = dlci;
kref_init(&mux_net->ref);
strncpy(nc->if_name, net->name, IFNAMSIZ); /* return net name */
/* reconfigure dlci for network */
dlci->prev_adaption = dlci->adaption;
dlci->prev_data = dlci->data;
dlci->adaption = nc->adaption;
dlci->data = gsm_mux_rx_netchar;
dlci->net = net;
pr_debug("register netdev");
retval = register_netdev(net);
if (retval) {
pr_err("network register fail %d\n", retval);
dlci_net_free(dlci);
return retval;
}
return net->ifindex; /* return network index */
}
/* Line discipline for real tty */
struct tty_ldisc_ops tty_ldisc_packet = {
@ -2579,6 +2885,9 @@ static int gsmtty_open(struct tty_struct *tty, struct file *filp)
port = &dlci->port;
port->count++;
tty->driver_data = dlci;
dlci_get(dlci);
dlci_get(dlci->gsm->dlci[0]);
mux_get(dlci->gsm);
tty_port_tty_set(port, tty);
dlci->modem_rx = 0;
@ -2594,13 +2903,23 @@ static int gsmtty_open(struct tty_struct *tty, struct file *filp)
static void gsmtty_close(struct tty_struct *tty, struct file *filp)
{
struct gsm_dlci *dlci = tty->driver_data;
struct gsm_mux *gsm;
if (dlci == NULL)
return;
mutex_lock(&dlci->mutex);
gsm_destroy_network(dlci);
mutex_unlock(&dlci->mutex);
gsm = dlci->gsm;
if (tty_port_close_start(&dlci->port, tty, filp) == 0)
return;
goto out;
gsm_dlci_begin_close(dlci);
tty_port_close_end(&dlci->port, tty);
tty_port_tty_set(&dlci->port, NULL);
out:
dlci_put(dlci);
dlci_put(gsm->dlci[0]);
mux_put(gsm);
}
static void gsmtty_hangup(struct tty_struct *tty)
@ -2677,7 +2996,32 @@ static int gsmtty_tiocmset(struct tty_struct *tty,
static int gsmtty_ioctl(struct tty_struct *tty,
unsigned int cmd, unsigned long arg)
{
return -ENOIOCTLCMD;
struct gsm_dlci *dlci = tty->driver_data;
struct gsm_netconfig nc;
int index;
switch (cmd) {
case GSMIOC_ENABLE_NET:
if (copy_from_user(&nc, (void __user *)arg, sizeof(nc)))
return -EFAULT;
nc.if_name[IFNAMSIZ-1] = '\0';
/* return net interface index or error code */
mutex_lock(&dlci->mutex);
index = gsm_create_network(dlci, &nc);
mutex_unlock(&dlci->mutex);
if (copy_to_user((void __user *)arg, &nc, sizeof(nc)))
return -EFAULT;
return index;
case GSMIOC_DISABLE_NET:
if (!capable(CAP_NET_ADMIN))
return -EPERM;
mutex_lock(&dlci->mutex);
gsm_destroy_network(dlci);
mutex_unlock(&dlci->mutex);
return 0;
default:
return -ENOIOCTLCMD;
}
}
static void gsmtty_set_termios(struct tty_struct *tty, struct ktermios *old)
@ -2726,7 +3070,6 @@ static int gsmtty_break_ctl(struct tty_struct *tty, int state)
return gsmtty_modem_update(dlci, encode);
}
static struct tty_driver *gsm_tty_driver;
/* Virtual ttys for the demux */
static const struct tty_operations gsmtty_ops = {

View File

@ -185,7 +185,6 @@ static void reset_buffer_flags(struct tty_struct *tty)
tty->canon_head = tty->canon_data = tty->erasing = 0;
memset(&tty->read_flags, 0, sizeof tty->read_flags);
n_tty_set_room(tty);
check_unthrottle(tty);
}
/**
@ -1587,6 +1586,7 @@ static int n_tty_open(struct tty_struct *tty)
return -ENOMEM;
}
reset_buffer_flags(tty);
tty_unthrottle(tty);
tty->column = 0;
n_tty_set_termios(tty, NULL);
tty->minimum_to_wake = 1;

View File

@ -81,7 +81,7 @@ static unsigned int skip_txen_test; /* force skip of txen test at init time */
#define DEBUG_INTR(fmt...) do { } while (0)
#endif
#define PASS_LIMIT 256
#define PASS_LIMIT 512
#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
@ -1107,7 +1107,7 @@ static void autoconfig_16550a(struct uart_8250_port *up)
*/
DEBUG_AUTOCONF("Xscale ");
up->port.type = PORT_XSCALE;
up->capabilities |= UART_CAP_UUE;
up->capabilities |= UART_CAP_UUE | UART_CAP_RTOIE;
return;
}
} else {

View File

@ -39,6 +39,7 @@ struct pci_serial_quirk {
u32 device;
u32 subvendor;
u32 subdevice;
int (*probe)(struct pci_dev *dev);
int (*init)(struct pci_dev *dev);
int (*setup)(struct serial_private *,
const struct pciserial_board *,
@ -56,6 +57,9 @@ struct serial_private {
int line[0];
};
static int pci_default_setup(struct serial_private*,
const struct pciserial_board*, struct uart_port*, int);
static void moan_device(const char *str, struct pci_dev *dev)
{
printk(KERN_WARNING
@ -571,6 +575,28 @@ static const struct timedia_struct {
{ 8, timedia_eight_port }
};
/*
* There are nearly 70 different Timedia/SUNIX PCI serial devices. Instead of
* listing them individually, this driver merely grabs them all with
* PCI_ANY_ID. Some of these devices, however, also feature a parallel port,
* and should be left free to be claimed by parport_serial instead.
*/
static int pci_timedia_probe(struct pci_dev *dev)
{
/*
* Check the third digit of the subdevice ID
* (0,2,3,5,6: serial only -- 7,8,9: serial + parallel)
*/
if ((dev->subsystem_device & 0x00f0) >= 0x70) {
dev_info(&dev->dev,
"ignoring Timedia subdevice %04x for parport_serial\n",
dev->subsystem_device);
return -ENODEV;
}
return 0;
}
static int pci_timedia_init(struct pci_dev *dev)
{
const unsigned short *ids;
@ -752,6 +778,62 @@ pci_ni8430_setup(struct serial_private *priv,
return setup_port(priv, port, bar, offset, board->reg_shift);
}
static int pci_netmos_9900_setup(struct serial_private *priv,
const struct pciserial_board *board,
struct uart_port *port, int idx)
{
unsigned int bar;
if ((priv->dev->subsystem_device & 0xff00) == 0x3000) {
/* netmos apparently orders BARs by datasheet layout, so serial
* ports get BARs 0 and 3 (or 1 and 4 for memmapped)
*/
bar = 3 * idx;
return setup_port(priv, port, bar, 0, board->reg_shift);
} else {
return pci_default_setup(priv, board, port, idx);
}
}
/* the 99xx series comes with a range of device IDs and a variety
* of capabilities:
*
* 9900 has varying capabilities and can cascade to sub-controllers
* (cascading should be purely internal)
* 9904 is hardwired with 4 serial ports
* 9912 and 9922 are hardwired with 2 serial ports
*/
static int pci_netmos_9900_numports(struct pci_dev *dev)
{
unsigned int c = dev->class;
unsigned int pi;
unsigned short sub_serports;
pi = (c & 0xff);
if (pi == 2) {
return 1;
} else if ((pi == 0) &&
(dev->device == PCI_DEVICE_ID_NETMOS_9900)) {
/* two possibilities: 0x30ps encodes number of parallel and
* serial ports, or 0x1000 indicates *something*. This is not
* immediately obvious, since the 2s1p+4s configuration seems
* to offer all functionality on functions 0..2, while still
* advertising the same function 3 as the 4s+2s1p config.
*/
sub_serports = dev->subsystem_device & 0xf;
if (sub_serports > 0) {
return sub_serports;
} else {
printk(KERN_NOTICE "NetMos/Mostech serial driver ignoring port on ambiguous config.\n");
return 0;
}
}
moan_device("unknown NetMos/Mostech program interface", dev);
return 0;
}
static int pci_netmos_init(struct pci_dev *dev)
{
@ -761,12 +843,28 @@ static int pci_netmos_init(struct pci_dev *dev)
if ((dev->device == PCI_DEVICE_ID_NETMOS_9901) ||
(dev->device == PCI_DEVICE_ID_NETMOS_9865))
return 0;
if (dev->subsystem_vendor == PCI_VENDOR_ID_IBM &&
dev->subsystem_device == 0x0299)
return 0;
switch (dev->device) { /* FALLTHROUGH on all */
case PCI_DEVICE_ID_NETMOS_9904:
case PCI_DEVICE_ID_NETMOS_9912:
case PCI_DEVICE_ID_NETMOS_9922:
case PCI_DEVICE_ID_NETMOS_9900:
num_serial = pci_netmos_9900_numports(dev);
break;
default:
if (num_serial == 0 ) {
moan_device("unknown NetMos/Mostech device", dev);
}
}
if (num_serial == 0)
return -ENODEV;
return num_serial;
}
@ -1396,6 +1494,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.device = PCI_DEVICE_ID_TIMEDIA_1889,
.subvendor = PCI_VENDOR_ID_TIMEDIA,
.subdevice = PCI_ANY_ID,
.probe = pci_timedia_probe,
.init = pci_timedia_init,
.setup = pci_timedia_setup,
},
@ -1426,7 +1525,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.init = pci_netmos_init,
.setup = pci_default_setup,
.setup = pci_netmos_9900_setup,
},
/*
* For Oxford Semiconductor Tornado based devices
@ -1703,6 +1802,7 @@ enum pci_board_num_t {
pbn_ADDIDATA_PCIe_8_3906250,
pbn_ce4100_1_115200,
pbn_omegapci,
pbn_NETMOS9900_2s_115200,
};
/*
@ -2404,6 +2504,11 @@ static struct pciserial_board pci_boards[] __devinitdata = {
.base_baud = 115200,
.uart_offset = 0x200,
},
[pbn_NETMOS9900_2s_115200] = {
.flags = FL_BASE0,
.num_ports = 2,
.base_baud = 115200,
},
};
static const struct pci_device_id softmodem_blacklist[] = {
@ -2640,11 +2745,19 @@ EXPORT_SYMBOL_GPL(pciserial_resume_ports);
static int __devinit
pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
{
struct pci_serial_quirk *quirk;
struct serial_private *priv;
const struct pciserial_board *board;
struct pciserial_board tmp;
int rc;
quirk = find_quirk(dev);
if (quirk->probe) {
rc = quirk->probe(dev);
if (rc)
return rc;
}
if (ent->driver_data >= ARRAY_SIZE(pci_boards)) {
printk(KERN_ERR "pci_init_one: invalid driver_data: %ld\n",
ent->driver_data);
@ -2654,6 +2767,7 @@ pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
board = &pci_boards[ent->driver_data];
rc = pci_enable_device(dev);
pci_save_state(dev);
if (rc)
return rc;
@ -3885,6 +3999,27 @@ static struct pci_device_id serial_pci_tbl[] = {
0xA000, 0x1000,
0, 0, pbn_b0_1_115200 },
/* the 9901 is a rebranded 9912 */
{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9912,
0xA000, 0x1000,
0, 0, pbn_b0_1_115200 },
{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9922,
0xA000, 0x1000,
0, 0, pbn_b0_1_115200 },
{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9904,
0xA000, 0x1000,
0, 0, pbn_b0_1_115200 },
{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9900,
0xA000, 0x1000,
0, 0, pbn_b0_1_115200 },
{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9900,
0xA000, 0x3002,
0, 0, pbn_NETMOS9900_2s_115200 },
/*
* Best Connectivity PCI Multi I/O cards
*/
@ -3927,6 +4062,51 @@ static struct pci_device_id serial_pci_tbl[] = {
{ 0, }
};
static pci_ers_result_t serial8250_io_error_detected(struct pci_dev *dev,
pci_channel_state_t state)
{
struct serial_private *priv = pci_get_drvdata(dev);
if (state == pci_channel_io_perm_failure)
return PCI_ERS_RESULT_DISCONNECT;
if (priv)
pciserial_suspend_ports(priv);
pci_disable_device(dev);
return PCI_ERS_RESULT_NEED_RESET;
}
static pci_ers_result_t serial8250_io_slot_reset(struct pci_dev *dev)
{
int rc;
rc = pci_enable_device(dev);
if (rc)
return PCI_ERS_RESULT_DISCONNECT;
pci_restore_state(dev);
pci_save_state(dev);
return PCI_ERS_RESULT_RECOVERED;
}
static void serial8250_io_resume(struct pci_dev *dev)
{
struct serial_private *priv = pci_get_drvdata(dev);
if (priv)
pciserial_resume_ports(priv);
}
static struct pci_error_handlers serial8250_err_handler = {
.error_detected = serial8250_io_error_detected,
.slot_reset = serial8250_io_slot_reset,
.resume = serial8250_io_resume,
};
static struct pci_driver serial_pci_driver = {
.name = "serial",
.probe = pciserial_init_one,
@ -3936,6 +4116,7 @@ static struct pci_driver serial_pci_driver = {
.resume = pciserial_resume_one,
#endif
.id_table = serial_pci_tbl,
.err_handler = &serial8250_err_handler,
};
static int __init serial8250_pci_init(void)

View File

@ -1404,7 +1404,7 @@ config SERIAL_SC26XX
config SERIAL_SC26XX_CONSOLE
bool "Console on SC2681/SC2692 serial port"
depends on SERIAL_SC26XX
depends on SERIAL_SC26XX=y
select SERIAL_CORE_CONSOLE
help
Support for Console on SC2681/SC2692 serial ports.

View File

@ -14,6 +14,7 @@
*along with this program; if not, write to the Free Software
*Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*/
#include <linux/kernel.h>
#include <linux/serial_reg.h>
#include <linux/slab.h>
#include <linux/module.h>
@ -44,6 +45,7 @@ enum {
/* Set the max number of UART port
* Intel EG20T PCH: 4 port
* OKI SEMICONDUCTOR ML7213 IOH: 3 port
* OKI SEMICONDUCTOR ML7223 IOH: 2 port
*/
#define PCH_UART_NR 4
@ -137,8 +139,6 @@ enum {
#define PCH_UART_DLL 0x00
#define PCH_UART_DLM 0x01
#define DIV_ROUND(a, b) (((a) + ((b)/2)) / (b))
#define PCH_UART_IID_RLS (PCH_UART_IIR_REI)
#define PCH_UART_IID_RDR (PCH_UART_IIR_RRI)
#define PCH_UART_IID_RDR_TO (PCH_UART_IIR_RRI | PCH_UART_IIR_TOI)
@ -316,7 +316,7 @@ static int pch_uart_hal_set_line(struct eg20t_port *priv, int baud,
unsigned int dll, dlm, lcr;
int div;
div = DIV_ROUND(priv->base_baud / 16, baud);
div = DIV_ROUND_CLOSEST(priv->base_baud / 16, baud);
if (div < 0 || USHRT_MAX <= div) {
dev_err(priv->port.dev, "Invalid Baud(div=0x%x)\n", div);
return -EINVAL;
@ -1429,6 +1429,8 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev,
goto init_port_hal_free;
}
pci_enable_msi(pdev);
iobase = pci_resource_start(pdev, 0);
mapbase = pci_resource_start(pdev, 1);
priv->mapbase = mapbase;
@ -1485,6 +1487,8 @@ static void pch_uart_pci_remove(struct pci_dev *pdev)
struct eg20t_port *priv;
priv = (struct eg20t_port *)pci_get_drvdata(pdev);
pci_disable_msi(pdev);
pch_uart_exit_port(priv);
pci_disable_device(pdev);
kfree(priv);
@ -1568,6 +1572,7 @@ static int __devinit pch_uart_pci_probe(struct pci_dev *pdev,
return ret;
probe_disable_device:
pci_disable_msi(pdev);
pci_disable_device(pdev);
probe_error:
return ret;

View File

@ -18,6 +18,7 @@
#include <linux/init.h>
#include <linux/serial_core.h>
#include <linux/serial.h>
#include <linux/delay.h>
#include <asm/irq.h>
#include <mach/hardware.h>
@ -83,6 +84,9 @@ static int s5pv210_serial_resetport(struct uart_port *port,
wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH);
wr_regl(port, S3C2410_UFCON, cfg->ufcon);
/* It is need to delay When reset FIFO register */
udelay(1);
return 0;
}

View File

@ -1194,12 +1194,10 @@ int __devexit s3c24xx_serial_remove(struct platform_device *dev)
EXPORT_SYMBOL_GPL(s3c24xx_serial_remove);
/* UART power management code */
#ifdef CONFIG_PM
static int s3c24xx_serial_suspend(struct platform_device *dev, pm_message_t state)
#ifdef CONFIG_PM_SLEEP
static int s3c24xx_serial_suspend(struct device *dev)
{
struct uart_port *port = s3c24xx_dev_to_port(&dev->dev);
struct uart_port *port = s3c24xx_dev_to_port(dev);
if (port)
uart_suspend_port(&s3c24xx_uart_drv, port);
@ -1207,9 +1205,9 @@ static int s3c24xx_serial_suspend(struct platform_device *dev, pm_message_t stat
return 0;
}
static int s3c24xx_serial_resume(struct platform_device *dev)
static int s3c24xx_serial_resume(struct device *dev)
{
struct uart_port *port = s3c24xx_dev_to_port(&dev->dev);
struct uart_port *port = s3c24xx_dev_to_port(dev);
struct s3c24xx_uart_port *ourport = to_ourport(port);
if (port) {
@ -1222,17 +1220,20 @@ static int s3c24xx_serial_resume(struct platform_device *dev)
return 0;
}
#endif
static const struct dev_pm_ops s3c24xx_serial_pm_ops = {
.suspend = s3c24xx_serial_suspend,
.resume = s3c24xx_serial_resume,
};
#else /* !CONFIG_PM_SLEEP */
#define s3c24xx_serial_pm_ops NULL
#endif /* CONFIG_PM_SLEEP */
int s3c24xx_serial_init(struct platform_driver *drv,
struct s3c24xx_uart_info *info)
{
dbg("s3c24xx_serial_init(%p,%p)\n", drv, info);
#ifdef CONFIG_PM
drv->suspend = s3c24xx_serial_suspend;
drv->resume = s3c24xx_serial_resume;
#endif
drv->driver.pm = &s3c24xx_serial_pm_ops;
return platform_driver_register(drv);
}

View File

@ -94,6 +94,7 @@
#include <linux/delay.h>
#include <linux/seq_file.h>
#include <linux/serial.h>
#include <linux/ratelimit.h>
#include <linux/uaccess.h>
#include <asm/system.h>
@ -1420,8 +1421,7 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx,
/* call the tty release_tty routine to clean out this slot */
err_release_tty:
if (printk_ratelimit())
printk(KERN_INFO "tty_init_dev: ldisc open failed, "
printk_ratelimited(KERN_INFO "tty_init_dev: ldisc open failed, "
"clearing slot %d\n", idx);
release_tty(tty, idx);
return ERR_PTR(retval);

View File

@ -21,5 +21,16 @@ struct gsm_config
#define GSMIOC_GETCONF _IOR('G', 0, struct gsm_config)
#define GSMIOC_SETCONF _IOW('G', 1, struct gsm_config)
struct gsm_netconfig {
unsigned int adaption; /* Adaption to use in network mode */
unsigned short protocol;/* Protocol to use - only ETH_P_IP supported */
unsigned short unused2;
char if_name[IFNAMSIZ]; /* interface name format string */
__u8 unused[28]; /* For future use */
};
#define GSMIOC_ENABLE_NET _IOW('G', 2, struct gsm_netconfig)
#define GSMIOC_DISABLE_NET _IO('G', 3)
#endif

View File

@ -2832,7 +2832,11 @@
#define PCI_DEVICE_ID_NETMOS_9845 0x9845
#define PCI_DEVICE_ID_NETMOS_9855 0x9855
#define PCI_DEVICE_ID_NETMOS_9865 0x9865
#define PCI_DEVICE_ID_NETMOS_9900 0x9900
#define PCI_DEVICE_ID_NETMOS_9901 0x9901
#define PCI_DEVICE_ID_NETMOS_9904 0x9904
#define PCI_DEVICE_ID_NETMOS_9912 0x9912
#define PCI_DEVICE_ID_NETMOS_9922 0x9922
#define PCI_VENDOR_ID_3COM_2 0xa727

View File

@ -36,7 +36,8 @@ struct pti_masterchannel {
/* the following functions are defined in misc/pti.c */
void pti_writedata(struct pti_masterchannel *mc, u8 *buf, int count);
struct pti_masterchannel *pti_request_masterchannel(u8 type);
struct pti_masterchannel *pti_request_masterchannel(u8 type,
const char *thread_name);
void pti_release_masterchannel(struct pti_masterchannel *mc);
#endif /*PTI_H_*/

View File

@ -5,24 +5,6 @@
* 'tty.h' defines some structures used by tty_io.c and some defines.
*/
#ifdef __KERNEL__
#include <linux/fs.h>
#include <linux/major.h>
#include <linux/termios.h>
#include <linux/workqueue.h>
#include <linux/tty_driver.h>
#include <linux/tty_ldisc.h>
#include <linux/mutex.h>
#include <asm/system.h>
/*
* (Note: the *_driver.minor_start values 1, 64, 128, 192 are
* hardcoded at present.)
*/
#define NR_UNIX98_PTY_DEFAULT 4096 /* Default maximum for Unix98 ptys */
#define NR_UNIX98_PTY_MAX (1 << MINORBITS) /* Absolute limit */
#define NR_LDISCS 30
/* line disciplines */
@ -53,6 +35,25 @@
#define N_TRACESINK 23 /* Trace data routing for MIPI P1149.7 */
#define N_TRACEROUTER 24 /* Trace data routing for MIPI P1149.7 */
#ifdef __KERNEL__
#include <linux/fs.h>
#include <linux/major.h>
#include <linux/termios.h>
#include <linux/workqueue.h>
#include <linux/tty_driver.h>
#include <linux/tty_ldisc.h>
#include <linux/mutex.h>
#include <asm/system.h>
/*
* (Note: the *_driver.minor_start values 1, 64, 128, 192 are
* hardcoded at present.)
*/
#define NR_UNIX98_PTY_DEFAULT 4096 /* Default maximum for Unix98 ptys */
#define NR_UNIX98_PTY_MAX (1 << MINORBITS) /* Absolute limit */
/*
* This character is the same as _POSIX_VDISABLE: it cannot be used as
* a c_cc[] character, but indicates that a particular special character