add nozomi driver
[openwrt.git] / package / nozomi / patches / 002-nozomi_vf_01.patch
1 --- nozomi/nozomi.c.orig        2006-04-16 12:15:42.000000000 +0100
2 +++ nozomi/nozomi.c     2006-04-19 18:27:29.000000000 +0100
3 @@ -7,6 +7,9 @@
4   *
5   * Maintained by: Paul Hardwick, p.hardwick@option.com
6   *
7 + * Patches:
8 + *          Locking code changes for Vodafone, Andrew Bird & Phil Sanderson
9 + *
10   * Source has been ported from an implementation made by Filip Aben, f.aben@option.com
11   *
12   * --------------------------------------------------------------------------
13 @@ -61,6 +64,7 @@
14  #include <linux/interrupt.h>
15  #include <linux/kmod.h>
16  #include <linux/proc_fs.h>
17 +#include <linux/init.h>
18  #include <asm/uaccess.h>
19  
20  
21 @@ -133,23 +137,23 @@
22  /* TODO: rewrite to optimize macros... */
23  #define SET_FCR(value__) \
24    do {  \
25 -       writew((value__), (void*) (dc->REG_FCR )); \
26 +       writew((value__), (dc->REG_FCR )); \
27  } while(0)
28  
29  #define SET_IER(value__, mask__) \
30    do {  \
31         dc->ier_last_written = (dc->ier_last_written & ~mask__) | (value__ & mask__ );\
32 -    writew( dc->ier_last_written, (void*) (dc->REG_IER));\
33 +    writew( dc->ier_last_written, (dc->REG_IER));\
34  } while(0)
35  
36  #define GET_IER(read_val__) \
37    do {  \
38 -       (read_val__) = readw((void*) (dc->REG_IER));\
39 +       (read_val__) = readw((dc->REG_IER));\
40  } while(0)
41  
42  #define GET_IIR(read_val__) \
43    do {  \
44 -       (read_val__) = readw((void*) (dc->REG_IIR));\
45 +       (read_val__) = readw( (dc->REG_IIR));\
46  } while(0)
47  
48  #define GET_MEM(value__, addr__, length__) \
49 @@ -265,7 +268,7 @@
50  /* There are two types of nozomi cards, one with 2048 memory and with 8192 memory */
51  typedef enum {
52         F32_2 = 2048, /* Has 512 bytes downlink and uplink * 2             -> 2048 */
53 -       F32_8 = 9192, /* Has 3072 bytes downlink and 1024 bytes uplink * 2 -> 8192 */
54 +       F32_8 = 8192, /* Has 3072 bytes downlink and 1024 bytes uplink * 2 -> 8192 */
55  } card_type_t;
56  
57  /* Two different toggle channels exist */
58 @@ -438,12 +441,12 @@
59         u32                                  base_addr;
60         u8                                   closing;
61  
62 -       /* Register addresses */
63 -       u32                                  REG_IIR;
64 -       u32                                  REG_FCR;
65 -       u32                                  REG_IER;
66 +   /* Pointers to registers ( register is tagged volatile, not pointer ) */
67 +       volatile u16 * REG_IIR;
68 +       volatile u16 * REG_FCR;
69 +       volatile u16 * REG_IER;
70  
71 -       volatile u16             ier_last_written;
72 +       u16              ier_last_written;
73         card_type_t          card_type;
74         config_table_t       config_table; /* Configuration table */
75         struct pci_dev      *pdev;
76 @@ -490,7 +493,7 @@
77  
78  /* Used to store interrupt variables */
79  typedef struct {
80 -       volatile u16 read_iir; /* Holds current interrupt tokens */
81 +       u16 read_iir; /* Holds current interrupt tokens */
82  } irq_t;
83  
84  MODULE_DEVICE_TABLE(pci, nozomi_pci_tbl);
85 @@ -1345,9 +1348,9 @@
86         u32 offset = dc->base_addr + dc->card_type/2;
87         int i;
88  
89 -       dc->REG_FCR = offset + R_FCR;
90 -       dc->REG_IIR = offset + R_IIR;
91 -       dc->REG_IER = offset + R_IER;
92 +       dc->REG_FCR = (u16 *) (offset + R_FCR);
93 +       dc->REG_IIR = (u16 *) (offset + R_IIR);
94 +       dc->REG_IER = (u16 *) (offset + R_IER);
95         dc->ier_last_written = 0;
96         dc->closing = 0;
97  
98 @@ -1366,13 +1369,16 @@
99  static void tty_flip_queue_function(void *tmp_dc) {
100         dc_t *dc = (dc_t*) tmp_dc;
101         int i;
102 +   u32 flags;
103  
104         /* Enable interrupt for that port */
105         for(i=0;i<MAX_PORT;i++) {
106                 if (dc->port[i].tty_dont_flip) {
107                         D6("Enable for port: %d", i);
108                         dc->port[i].tty_dont_flip = 0;
109 +         spin_lock_irqsave(&dc->spin_mutex, flags);
110                         enable_transmit_dl(dc->port[i].tty_index, dc);
111 +         spin_unlock_irqrestore(&dc->spin_mutex, flags);
112                 }
113         }
114  }
115 @@ -1555,7 +1561,11 @@
116  
117  static void tty_do_close(dc_t *dc, port_t *port) {
118  
119 -       down(&port->tty_sem);
120 +       u32      flags;
121 +
122 +       if(down_interruptible(&port->tty_sem)){
123 +      return;
124 +   }
125  
126         if ( !port->tty_open_count ) {
127                 goto exit;
128 @@ -1569,7 +1579,9 @@
129  
130         if ( port->tty_open_count == 0) {
131          D1("close: %d", port->token_dl );
132 +      spin_lock_irqsave(&dc->spin_mutex, flags);
133                 SET_IER( 0,  port->token_dl );
134 +      spin_unlock_irqrestore(&dc->spin_mutex, flags);
135         }
136  
137  exit:
138 @@ -1679,8 +1691,11 @@
139         s32 index = get_index(tty);
140         port_t *port = get_port_by_tty(tty);
141         dc_t *dc = get_dc_by_tty(tty);
142 +       u32      flags;
143  
144 -       down(&port->tty_sem);
145 +   if(down_interruptible(&port->tty_sem)){
146 +      return -ERESTARTSYS;
147 +   }
148  
149         tty->low_latency  = 1;
150         tty->driver_data  = port;
151 @@ -1698,7 +1713,9 @@
152         if ( port->tty_open_count == 1) {
153                 port->rx_data = port->tx_data = 0;
154          D1("open: %d", port->token_dl );
155 +      spin_lock_irqsave(&dc->spin_mutex, flags);
156                 SET_IER( port->token_dl,  port->token_dl );
157 +      spin_unlock_irqrestore(&dc->spin_mutex, flags);
158         }
159  
160         up(&port->tty_sem);
161 @@ -1722,6 +1739,7 @@
162         int                  rval = -EINVAL;
163         dc_t                *dc = get_dc_by_tty(tty);
164         port_t              *port = (port_t *) tty->driver_data;
165 +       u32      flags;
166  
167         /* D1( "WRITEx: %d, index = %d", count, index); */
168  
169 @@ -1729,7 +1747,10 @@
170                 return -ENODEV;
171         }
172  
173 -       down(&port->tty_sem);
174 +   if(down_trylock(&port->tty_sem) ) { // must test lock as tty layer wraps calls to this function with BKL
175 +      ERR("Would have deadlocked - return ERESTARTSYS");
176 +      return -ERESTARTSYS;
177 +   }
178  
179         if (! port->tty_open_count) {
180          D1( " ");
181 @@ -1752,6 +1773,7 @@
182                 goto exit;
183         }
184  
185 +   spin_lock_irqsave(&dc->spin_mutex, flags);
186         // CTS is only valid on the modem channel
187         if ( port == &(dc->port[PORT_MDM]) ) {
188                 if ( port->ctrl_dl.CTS ) {
189 @@ -1763,6 +1785,7 @@
190         } else {
191                 enable_transmit_ul(port->tty_index, dc );
192         }
193 +   spin_unlock_irqrestore(&dc->spin_mutex, flags);
194  
195  exit:
196         up(&port->tty_sem);
197 @@ -1782,7 +1805,9 @@
198          return 0;
199         }
200  
201 -       down(&port->tty_sem);
202 +   if(down_interruptible(&port->tty_sem)){
203 +      return 0;
204 +   }
205  
206         if (! port->tty_open_count) {
207                 goto exit;
208 @@ -1969,6 +1994,8 @@
209  
210  static int ntty_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg) {
211         port_t *port = (port_t *) tty->driver_data;
212 +       dc_t    *dc = get_dc_by_tty(tty);
213 +       u32      flags;
214         int mask;
215         int rval = -ENOIOCTLCMD;
216  
217 @@ -1991,7 +2018,9 @@
218                 rval =  ntty_ioctl_tiocgicount(tty, file, cmd, arg);
219                 break;
220         case TIOCMGET:
221 +      spin_lock_irqsave(&dc->spin_mutex, flags);
222                 rval = ntty_tiocmget(tty, file);
223 +      spin_unlock_irqrestore(&dc->spin_mutex, flags);
224                 break;
225         case TIOCMSET:
226                 rval = ntty_tiocmset(tty, file, arg);
227 @@ -2000,20 +2029,24 @@
228                 if (get_user(mask, (unsigned long *) arg))
229                         return -EFAULT;
230  
231 +      spin_lock_irqsave(&dc->spin_mutex, flags);
232                 if (mask & TIOCM_RTS)
233                         set_rts(port->tty_index, 0);
234                 if (mask & TIOCM_DTR)
235                         set_dtr(port->tty_index, 0);
236 +      spin_unlock_irqrestore(&dc->spin_mutex, flags);
237                 rval = 0;
238                 break;
239         case TIOCMBIS:
240                 if (get_user(mask, (unsigned long *) arg))
241                         return -EFAULT;
242  
243 +      spin_lock_irqsave(&dc->spin_mutex, flags);
244                 if (mask & TIOCM_RTS)
245                         set_rts(port->tty_index, 1);
246                 if (mask & TIOCM_DTR)
247                         set_dtr(port->tty_index, 1);
248 +      spin_unlock_irqrestore(&dc->spin_mutex, flags);
249                 rval = 0;
250                 break;
251         case TCFLSH: