Merge branch 'tty-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty-2.6
Linus Torvalds [Tue, 26 Jul 2011 06:09:27 +0000 (23:09 -0700)]
* '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
  ...

20 files changed:
drivers/misc/Makefile
drivers/misc/pch_phub.c
drivers/misc/pti.c
drivers/parport/parport_pc.c
drivers/parport/parport_serial.c
drivers/tty/moxa.c
drivers/tty/mxser.c
drivers/tty/n_gsm.c
drivers/tty/n_tty.c
drivers/tty/serial/8250.c
drivers/tty/serial/8250_pci.c
drivers/tty/serial/Kconfig
drivers/tty/serial/pch_uart.c
drivers/tty/serial/s5pv210.c
drivers/tty/serial/samsung.c
drivers/tty/tty_io.c
include/linux/gsmmux.h
include/linux/pci_ids.h
include/linux/pti.h
include/linux/tty.h

index 3328215..8f3efb6 100644 (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
index 01eb67b..0fd7e77 100644 (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;
index e5f295a..8653bd0 100644 (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;
index f330338..d1cdb94 100644 (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 },
index f01e264..e9c3227 100644 (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))
index ba679ce..d15a071 100644 (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)
index d188f37..7fc8c02 100644 (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);
index 19b4ae0..8a50e4e 100644 (file)
 #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
+ *     gsm_dlci_free           -       free DLCI
+ *     @dlci: DLCI to free
+ *
+ *     Free up a DLCI.
+ *
+ *     Can sleep.
+ */
+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
  *
- *     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.
+ *     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_free(struct gsm_dlci *dlci)
+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)
 {
@@ -2042,6 +2100,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
  *
  *     Creates a new mux ready for activation.
@@ -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 = {
index c3954fb..39d6ab6 100644 (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;
index b4129f5..f2dfec8 100644 (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 {
index cf35e0d..6b887d9 100644 (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)
index 8f41e11..cb40b82 100644 (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.
index 4652109..846dfcd 100644 (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;
index 8dd160c..8b0b888 100644 (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;
 }
 
index 7ead421..afc6294 100644 (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);
 }
index 6556f74..150e4f7 100644 (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 @@ err_module_put:
 
        /* 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);
index 378de41..c25e947 100644 (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
index 74173c5..b00c4ec 100644 (file)
 #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
 
index 81af667..b3ea01a 100644 (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_*/
index d6f0529..44bc0c5 100644 (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 */
 #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