All of lore.kernel.org
 help / color / mirror / Atom feed
From: Mark Hounschell <markh@compro.net>
To: Peter Hurley <peter@hurleysoftware.com>
Cc: linux-serial@vger.kernel.org, Mark Hounschell <dmarkh@cfl.rr.com>
Subject: Re: Out of tree GPL serial tty driver help?
Date: Fri, 26 Apr 2013 16:26:29 -0400	[thread overview]
Message-ID: <517AE2F5.4060200@compro.net> (raw)
In-Reply-To: <1367005866.3971.15.camel@thor.lan>

On 04/26/2013 03:51 PM, Peter Hurley wrote:
> On Fri, 2013-04-26 at 14:17 -0400, Mark Hounschell wrote:
>> On 04/26/2013 12:37 PM, Peter Hurley wrote:
>>> These drivers weren't really current at 3.4 though, either. I'm not sure
>>> what else you're going to find that doesn't work.
>>>
>>
>> No, I have kept them current, or I should say functional, to the best of
>> my ability from 2.6 up to and including 3.4.x.
>
> By 'current', I mean 'similar in structure and functionality to in-tree
> drivers'.
>
> The structure of this driver is more akin to a 2.5 driver (back when
> there were separate serial and callout tty drivers).
>
>>   What I have here works
>> with kernels up to 3.4.x. I have not tried anything between 3.4 and 3.8.
>>    As far as building against 3.8, the only issues were the change from
>> *termios to termios and the "structn_tty_data" no longer in an include
>> file so not easily directly accessible.
>
> What is this driver accessing in N_TTY's private data?
>
         /* Decide how much data we can send into the tty layer */
         if(dgdm_rawreadok && tty->real_raw)
                 flip_len = MYFLIPLEN;
         else
                 flip_len = TTY_FLIPBUF_SIZE;
         len = MIN(data_len, flip_len);
         len = MIN(len, (N_TTY_BUF_SIZE - 1) - tty->read_cnt);
         dxb_return_fixed_cost(dxb, channel, 1);
         ld = tty_ldisc_ref(tty);
.
.
.
.
                 /*
                  * In high performance mode, we don't have to update
                  * flag_buf or any of the counts or pointers into flip buf.
                  */
                 if(!dgdm_rawreadok || !tty->real_raw) {
                         if (I_PARMRK(tty) || I_BRKINT(tty) || 
I_INPCK(tty)) {
                                 parity_scan(dc, myflipbuf[boardnum],
                                         myflipflagbuf[boardnum], &len);
                         } else {
                                 memset(myflipflagbuf[boardnum], 
TTY_NORMAL, len);
                         }
                 }
.
.
.
.
                 /*
                  * If we're doing raw reads, jam it right into the
                  * line disc bypassing the flip buffers.
                  * OPT OPP: do this only once per channel instead of
                  * once per dxb message.
                  */
                 if(dgdm_rawreadok && tty->real_raw) {
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)
                         tty->ldisc->ops->receive_buf(tty, 
myflipbuf[boardnum], NULL, len);
#else
                         tty->ldisc.ops->receive_buf(tty, 
myflipbuf[boardnum], NULL, len);
#endif
#else
                         tty->ldisc.receive_buf(tty, 
myflipbuf[boardnum], NULL, len);
#endif
                 } else {
                         len = tty_buffer_request_room(tty, len);
                         tty_insert_flip_string_flags(tty, 
myflipbuf[boardnum],
                                 myflipflagbuf[boardnum], len);

                         /* Tell the tty layer its okay to "eat" the 
data now */
                         tty_flip_buffer_push(tty);
                 }
.
.
.
         /*
          * Just go ahead and try to read some data into the flip buffer.
          * If there isn't any data available, dxb_rxbuf_read will return
          * 0 back to us right away.
          *
          * The dgdm_rawreadok case takes advantage of carnal knowldge that
          * the char_buf and the flag_buf are next to each other and
          * are each of (2 * TTY_FLIPBUF_SIZE) size.
          */

         if(dgdm_rawreadok && tty->real_raw)
                 flip_len = MYFLIPLEN;
         else
                 flip_len = TTY_FLIPBUF_SIZE;

         flip_len = MIN(flip_len, (N_TTY_BUF_SIZE - 1) - tty->read_cnt);

         len = dxb_rxbuf_read(brd->dxb, dc->dxbchan, 
myflipbuf[boardnum], flip_len);


etc...

Looks like for hopes of performance????




>>> For both PCI and PCI-e, these drivers should _at a minimum_ be pci
>>> drivers that register the tty driver at module init and register _only_
>>> the tty devices for that particular PCI device at PCI probe time. Look
>>> at the end of synclink_gt.c for how this is supposed to look.
>>>
>>
>> I'll look at it some more but I have been there.
>
> Specifically, review:
> 	struct pci_driver
> 	device_init()
> 	init_one()
> 	remove_one()
> 	sglt_init()
> 	sglt_exit()
>

Ok, I'll will look more closely at these to try to understand what 
should be done.


Here is the init_module funtion FYI.

GLOBAL int init_module(void)
{
     int rc;

         /* make sure that the globals are init'd before we do anything 
else */
         dgdm_init_globals();

         dgdm_NumBoards = 0;
         dgdm_Major_Serial_Registered = FALSE;
         dgdm_Major_Callout_Registered = FALSE;
         dgdm_Major_TransparentPrint_Registered = FALSE;
         dgdm_Major_Control_Registered = FALSE;
         dgdm_Major_ISDN_Registered = FALSE;

         APR(("%s, Digi International Part Number %s\n", DG_NAME, DG_PART));

         /*
          * Find and configure all the cards
          */

         rc = dgdm_init_pci();

         if (!rc) {
                 /*
                  * At least one card was found, register the devices
                  * with the kernel.
                  */
                 dgdm_proc_register_basic();

                 if (dgdm_tty) {
                         rc = dgdm_tty_init();  // This is the function 
that creates all the device entries
                         if (rc < 0) {
                                 dgdm_tty_uninit();
                                 APR(("Can't init tty devices (%d)\n", rc));
                                 return (rc);
                         }
                         /*
                          * Register FEP related /proc files
                          */
                         dgdm_proc_register_fep();
                 }
                 if (!dgdm_Major_Control_Registered) {
                         /*
                          * Register memory/control/debug/mangement devices
                          */
                         rc = register_chrdev(major + DGDM_CONTROL_MAJOR,
                                              "dxb", &BoardFops);
                         if (rc < 0) {
                                 APR(("Can't register ram device 
(%d)\n", rc));
                                 return (rc);
                         }
                         dgdm_Major_Control_Registered = TRUE;
                 }
                 if (dgdm_isdn && !dgdm_Major_ISDN_Registered) {
                         /*
                          * Register ISDN testing device
                          */
                         rc = register_chrdev(major + DGDM_ISDN_MAJOR,
                                              "dxbisdn", 
&dgdm_BoardIsdnFops);
                         if (rc < 0) {
                                 APR(("Can't register ISDN device 
(%d)\n", rc));
                                 return (rc);
                         }
                         dgdm_Major_ISDN_Registered = TRUE;
                 }
                 if(dgdm_NumBoards > 4) {
                         if (!dgdm_Major_Control2_Registered) {
                                 rc = 
register_chrdev(major+DGDM_CONTROL2_MAJOR,
                                                      "dxb2", &BoardFops);
                                 if (rc < 0) {
                                         APR(("Can't register high ram "
                                              "device (%d)\n", rc));
                                         return (rc);
                                 }
                                 dgdm_Major_Control2_Registered = TRUE;
                         }
                         if (dgdm_isdn && !dgdm_Major_ISDN2_Registered) {
                                 rc = register_chrdev(major + 
DGDM_ISDN2_MAJOR,
                                                      "dxbisdn2", 
&dgdm_BoardIsdnFops);
                                 if (rc < 0) {
                                         APR(("Can't register high ISDN "
                                              "devices (%d)\n", rc));
                                         return (rc);
                                 }
                                 dgdm_Major_ISDN2_Registered = TRUE;
                         }
                 }

                 //       Compro Computer Svcs udev support
                 // Need udev notification of the dgdm_mgmt device creation
                 //
                 // See config/99-dgdm.rules 
"/etc/udev/rules.d/99-dgdm.rules"
                 // and /usr/local/sbin/dgdm
                 //
                 if (alloc_chrdev_region(&dgdm_mgmt_major, 0, 1, 
"dgdm_mgmt") != 0) {
                         printk("DGDM: Unable to get MAJOR/MINOR device 
numbers\n");
                         return -ENODEV;
                 }

                 dgdm_mgmt_device = cdev_alloc();
                 if (dgdm_mgmt_device <= 0) {
                         printk("DGDM: Unable to alloc cdev struct\n");
                         return -ENODEV;
                 }

                 cdev_init(dgdm_mgmt_device, &dgdm_BoardIsdnFops);
                 dgdm_mgmt_device->owner = THIS_MODULE;

                 if (cdev_add(dgdm_mgmt_device, dgdm_mgmt_major, 1) < 0) {
                         printk("DGDM: Error Registering chrdev device\n");
                         return -ENODEV;
                 }

                 dgdm_mgmt_class = class_create(THIS_MODULE, "dgdm_mgmt");
                 if (IS_ERR(dgdm_mgmt_class)) {
                         printk("DGDM: Error creating class\n");
                         return -ENODEV;
                 }

                 device_dgdm_mgmt = device_create(dgdm_mgmt_class, NULL, 
dgdm_mgmt_major, NULL, "dgdm_mgmt");
                 if (IS_ERR(device_dgdm_mgmt)) {
                         printk("DGDM: Error creating device entry\n");
                         return -ENODEV;
                 }
         } else {
                 cleanup_module();
         }

         return (rc);
}


Mark

  reply	other threads:[~2013-04-26 20:26 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-04-24 17:44 Out of tree GPL serial tty driver help? Mark Hounschell
2013-04-25 21:41 ` Peter Hurley
2013-04-26 12:58   ` Mark Hounschell
2013-04-26 13:45     ` Peter Hurley
2013-04-26 14:28       ` Mark Hounschell
2013-04-26 14:35         ` Greg KH
2013-04-26 15:10           ` Mark Hounschell
2013-04-26 15:19             ` Greg KH
2013-04-26 15:39               ` Peter Hurley
2013-04-26 16:03                 ` Greg KH
2013-04-26 17:58                   ` Mark Hounschell
2013-04-26 23:21                     ` Greg KH
2013-04-26 16:37         ` Peter Hurley
2013-04-26 18:17           ` Mark Hounschell
2013-04-26 19:51             ` Peter Hurley
2013-04-26 20:26               ` Mark Hounschell [this message]
2013-04-26 21:49                 ` Peter Hurley

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=517AE2F5.4060200@compro.net \
    --to=markh@compro.net \
    --cc=dmarkh@cfl.rr.com \
    --cc=linux-serial@vger.kernel.org \
    --cc=peter@hurleysoftware.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.