mirror of https://gitee.com/openkylin/linux.git
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:
commit
d5ef642355
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 },
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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_*/
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue