diff options
Diffstat (limited to 'drivers')
97 files changed, 3248 insertions, 3606 deletions
diff --git a/drivers/atm/Kconfig b/drivers/atm/Kconfig index 5b4fab24155f..bb4ae6281491 100644 --- a/drivers/atm/Kconfig +++ b/drivers/atm/Kconfig | |||
@@ -142,7 +142,7 @@ config ATM_ENI_BURST_RX_2W | |||
142 | 142 | ||
143 | config ATM_FIRESTREAM | 143 | config ATM_FIRESTREAM |
144 | tristate "Fujitsu FireStream (FS50/FS155) " | 144 | tristate "Fujitsu FireStream (FS50/FS155) " |
145 | depends on PCI | 145 | depends on PCI && VIRT_TO_BUS |
146 | help | 146 | help |
147 | Driver for the Fujitsu FireStream 155 (MB86697) and | 147 | Driver for the Fujitsu FireStream 155 (MB86697) and |
148 | FireStream 50 (MB86695) ATM PCI chips. | 148 | FireStream 50 (MB86695) ATM PCI chips. |
@@ -152,7 +152,7 @@ config ATM_FIRESTREAM | |||
152 | 152 | ||
153 | config ATM_ZATM | 153 | config ATM_ZATM |
154 | tristate "ZeitNet ZN1221/ZN1225" | 154 | tristate "ZeitNet ZN1221/ZN1225" |
155 | depends on PCI | 155 | depends on PCI && VIRT_TO_BUS |
156 | help | 156 | help |
157 | Driver for the ZeitNet ZN1221 (MMF) and ZN1225 (UTP-5) 155 Mbps ATM | 157 | Driver for the ZeitNet ZN1221 (MMF) and ZN1225 (UTP-5) 155 Mbps ATM |
158 | adapters. | 158 | adapters. |
@@ -240,7 +240,7 @@ config ATM_IDT77252_USE_SUNI | |||
240 | 240 | ||
241 | config ATM_AMBASSADOR | 241 | config ATM_AMBASSADOR |
242 | tristate "Madge Ambassador (Collage PCI 155 Server)" | 242 | tristate "Madge Ambassador (Collage PCI 155 Server)" |
243 | depends on PCI | 243 | depends on PCI && VIRT_TO_BUS |
244 | select BITREVERSE | 244 | select BITREVERSE |
245 | help | 245 | help |
246 | This is a driver for ATMizer based ATM card produced by Madge | 246 | This is a driver for ATMizer based ATM card produced by Madge |
@@ -265,7 +265,7 @@ config ATM_AMBASSADOR_DEBUG | |||
265 | 265 | ||
266 | config ATM_HORIZON | 266 | config ATM_HORIZON |
267 | tristate "Madge Horizon [Ultra] (Collage PCI 25 and Collage PCI 155 Client)" | 267 | tristate "Madge Horizon [Ultra] (Collage PCI 25 and Collage PCI 155 Client)" |
268 | depends on PCI | 268 | depends on PCI && VIRT_TO_BUS |
269 | help | 269 | help |
270 | This is a driver for the Horizon chipset ATM adapter cards once | 270 | This is a driver for the Horizon chipset ATM adapter cards once |
271 | produced by Madge Networks Ltd. Say Y (or M to compile as a module | 271 | produced by Madge Networks Ltd. Say Y (or M to compile as a module |
diff --git a/drivers/auxdisplay/Kconfig b/drivers/auxdisplay/Kconfig index ea4fe3e48f33..de2fcce10ba5 100644 --- a/drivers/auxdisplay/Kconfig +++ b/drivers/auxdisplay/Kconfig | |||
@@ -5,8 +5,11 @@ | |||
5 | # Auxiliary display drivers configuration. | 5 | # Auxiliary display drivers configuration. |
6 | # | 6 | # |
7 | 7 | ||
8 | menu "Auxiliary Display support" | 8 | menuconfig AUXDISPLAY |
9 | depends on PARPORT | 9 | depends on PARPORT |
10 | bool "Auxiliary Display support" | ||
11 | |||
12 | if AUXDISPLAY && PARPORT | ||
10 | 13 | ||
11 | config KS0108 | 14 | config KS0108 |
12 | tristate "KS0108 LCD Controller" | 15 | tristate "KS0108 LCD Controller" |
@@ -111,4 +114,5 @@ config CFAG12864B_RATE | |||
111 | 114 | ||
112 | If you compile this as a module, you can still override this | 115 | If you compile this as a module, you can still override this |
113 | value using the module parameters. | 116 | value using the module parameters. |
114 | endmenu | 117 | |
118 | endif # AUXDISPLAY | ||
diff --git a/drivers/base/dmapool.c b/drivers/base/dmapool.c index 91970e9bb05e..7647abfe1890 100644 --- a/drivers/base/dmapool.c +++ b/drivers/base/dmapool.c | |||
@@ -127,7 +127,7 @@ dma_pool_create (const char *name, struct device *dev, | |||
127 | } else if (allocation < size) | 127 | } else if (allocation < size) |
128 | return NULL; | 128 | return NULL; |
129 | 129 | ||
130 | if (!(retval = kmalloc (sizeof *retval, GFP_KERNEL))) | 130 | if (!(retval = kmalloc_node (sizeof *retval, GFP_KERNEL, dev_to_node(dev)))) |
131 | return retval; | 131 | return retval; |
132 | 132 | ||
133 | strlcpy (retval->name, name, sizeof retval->name); | 133 | strlcpy (retval->name, name, sizeof retval->name); |
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index 6e23af1ecbdb..c5a61571a076 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig | |||
@@ -59,17 +59,6 @@ config AMIGA_Z2RAM | |||
59 | To compile this driver as a module, choose M here: the | 59 | To compile this driver as a module, choose M here: the |
60 | module will be called z2ram. | 60 | module will be called z2ram. |
61 | 61 | ||
62 | config ATARI_SLM | ||
63 | tristate "Atari SLM laser printer support" | ||
64 | depends on ATARI | ||
65 | help | ||
66 | If you have an Atari SLM laser printer, say Y to include support for | ||
67 | it in the kernel. Otherwise, say N. This driver is also available as | ||
68 | a module ( = code which can be inserted in and removed from the | ||
69 | running kernel whenever you want). The module will be called | ||
70 | acsi_slm. Be warned: the driver needs much ST-RAM and can cause | ||
71 | problems due to that fact! | ||
72 | |||
73 | config BLK_DEV_XD | 62 | config BLK_DEV_XD |
74 | tristate "XT hard disk support" | 63 | tristate "XT hard disk support" |
75 | depends on ISA && ISA_DMA_API | 64 | depends on ISA && ISA_DMA_API |
@@ -113,7 +102,7 @@ source "drivers/block/paride/Kconfig" | |||
113 | 102 | ||
114 | config BLK_CPQ_DA | 103 | config BLK_CPQ_DA |
115 | tristate "Compaq SMART2 support" | 104 | tristate "Compaq SMART2 support" |
116 | depends on PCI | 105 | depends on PCI && VIRT_TO_BUS |
117 | help | 106 | help |
118 | This is the driver for Compaq Smart Array controllers. Everyone | 107 | This is the driver for Compaq Smart Array controllers. Everyone |
119 | using these boards should say Y here. See the file | 108 | using these boards should say Y here. See the file |
@@ -423,6 +412,13 @@ config ATA_OVER_ETH | |||
423 | This driver provides Support for ATA over Ethernet block | 412 | This driver provides Support for ATA over Ethernet block |
424 | devices like the Coraid EtherDrive (R) Storage Blade. | 413 | devices like the Coraid EtherDrive (R) Storage Blade. |
425 | 414 | ||
415 | config SUNVDC | ||
416 | tristate "Sun Virtual Disk Client support" | ||
417 | depends on SUN_LDOMS | ||
418 | help | ||
419 | Support for virtual disk devices as a client under Sun | ||
420 | Logical Domains. | ||
421 | |||
426 | source "drivers/s390/block/Kconfig" | 422 | source "drivers/s390/block/Kconfig" |
427 | 423 | ||
428 | endif # BLK_DEV | 424 | endif # BLK_DEV |
diff --git a/drivers/block/Makefile b/drivers/block/Makefile index e5f98acc5d52..7926be8c9fb7 100644 --- a/drivers/block/Makefile +++ b/drivers/block/Makefile | |||
@@ -9,7 +9,6 @@ obj-$(CONFIG_MAC_FLOPPY) += swim3.o | |||
9 | obj-$(CONFIG_BLK_DEV_FD) += floppy.o | 9 | obj-$(CONFIG_BLK_DEV_FD) += floppy.o |
10 | obj-$(CONFIG_AMIGA_FLOPPY) += amiflop.o | 10 | obj-$(CONFIG_AMIGA_FLOPPY) += amiflop.o |
11 | obj-$(CONFIG_ATARI_FLOPPY) += ataflop.o | 11 | obj-$(CONFIG_ATARI_FLOPPY) += ataflop.o |
12 | obj-$(CONFIG_ATARI_SLM) += acsi_slm.o | ||
13 | obj-$(CONFIG_AMIGA_Z2RAM) += z2ram.o | 12 | obj-$(CONFIG_AMIGA_Z2RAM) += z2ram.o |
14 | obj-$(CONFIG_BLK_DEV_RAM) += rd.o | 13 | obj-$(CONFIG_BLK_DEV_RAM) += rd.o |
15 | obj-$(CONFIG_BLK_DEV_LOOP) += loop.o | 14 | obj-$(CONFIG_BLK_DEV_LOOP) += loop.o |
@@ -19,6 +18,7 @@ obj-$(CONFIG_BLK_CPQ_DA) += cpqarray.o | |||
19 | obj-$(CONFIG_BLK_CPQ_CISS_DA) += cciss.o | 18 | obj-$(CONFIG_BLK_CPQ_CISS_DA) += cciss.o |
20 | obj-$(CONFIG_BLK_DEV_DAC960) += DAC960.o | 19 | obj-$(CONFIG_BLK_DEV_DAC960) += DAC960.o |
21 | obj-$(CONFIG_CDROM_PKTCDVD) += pktcdvd.o | 20 | obj-$(CONFIG_CDROM_PKTCDVD) += pktcdvd.o |
21 | obj-$(CONFIG_SUNVDC) += sunvdc.o | ||
22 | 22 | ||
23 | obj-$(CONFIG_BLK_DEV_UMEM) += umem.o | 23 | obj-$(CONFIG_BLK_DEV_UMEM) += umem.o |
24 | obj-$(CONFIG_BLK_DEV_NBD) += nbd.o | 24 | obj-$(CONFIG_BLK_DEV_NBD) += nbd.o |
diff --git a/drivers/block/acsi_slm.c b/drivers/block/acsi_slm.c deleted file mode 100644 index 1d9d9b4f48cc..000000000000 --- a/drivers/block/acsi_slm.c +++ /dev/null | |||
@@ -1,1032 +0,0 @@ | |||
1 | /* | ||
2 | * acsi_slm.c -- Device driver for the Atari SLM laser printer | ||
3 | * | ||
4 | * Copyright 1995 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> | ||
5 | * | ||
6 | * This file is subject to the terms and conditions of the GNU General Public | ||
7 | * License. See the file COPYING in the main directory of this archive for | ||
8 | * more details. | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | /* | ||
13 | |||
14 | Notes: | ||
15 | |||
16 | The major number for SLM printers is 28 (like ACSI), but as a character | ||
17 | device, not block device. The minor number is the number of the printer (if | ||
18 | you have more than one SLM; currently max. 2 (#define-constant) SLMs are | ||
19 | supported). The device can be opened for reading and writing. If reading it, | ||
20 | you get some status infos (MODE SENSE data). Writing mode is used for the data | ||
21 | to be printed. Some ioctls allow to get the printer status and to tune printer | ||
22 | modes and some internal variables. | ||
23 | |||
24 | A special problem of the SLM driver is the timing and thus the buffering of | ||
25 | the print data. The problem is that all the data for one page must be present | ||
26 | in memory when printing starts, else --when swapping occurs-- the timing could | ||
27 | not be guaranteed. There are several ways to assure this: | ||
28 | |||
29 | 1) Reserve a buffer of 1196k (maximum page size) statically by | ||
30 | atari_stram_alloc(). The data are collected there until they're complete, | ||
31 | and then printing starts. Since the buffer is reserved, no further | ||
32 | considerations about memory and swapping are needed. So this is the | ||
33 | simplest method, but it needs a lot of memory for just the SLM. | ||
34 | |||
35 | An striking advantage of this method is (supposed the SLM_CONT_CNT_REPROG | ||
36 | method works, see there), that there are no timing problems with the DMA | ||
37 | anymore. | ||
38 | |||
39 | 2) The other method would be to reserve the buffer dynamically each time | ||
40 | printing is required. I could think of looking at mem_map where the | ||
41 | largest unallocted ST-RAM area is, taking the area, and then extending it | ||
42 | by swapping out the neighbored pages, until the needed size is reached. | ||
43 | This requires some mm hacking, but seems possible. The only obstacle could | ||
44 | be pages that cannot be swapped out (reserved pages)... | ||
45 | |||
46 | 3) Another possibility would be to leave the real data in user space and to | ||
47 | work with two dribble buffers of about 32k in the driver: While the one | ||
48 | buffer is DMAed to the SLM, the other can be filled with new data. But | ||
49 | to keep the timing, that requires that the user data remain in memory and | ||
50 | are not swapped out. Requires mm hacking, too, but maybe not so bad as | ||
51 | method 2). | ||
52 | |||
53 | */ | ||
54 | |||
55 | #include <linux/module.h> | ||
56 | |||
57 | #include <linux/errno.h> | ||
58 | #include <linux/sched.h> | ||
59 | #include <linux/timer.h> | ||
60 | #include <linux/fs.h> | ||
61 | #include <linux/major.h> | ||
62 | #include <linux/kernel.h> | ||
63 | #include <linux/delay.h> | ||
64 | #include <linux/interrupt.h> | ||
65 | #include <linux/time.h> | ||
66 | #include <linux/mm.h> | ||
67 | #include <linux/slab.h> | ||
68 | |||
69 | #include <asm/pgtable.h> | ||
70 | #include <asm/system.h> | ||
71 | #include <asm/uaccess.h> | ||
72 | #include <asm/atarihw.h> | ||
73 | #include <asm/atariints.h> | ||
74 | #include <asm/atari_acsi.h> | ||
75 | #include <asm/atari_stdma.h> | ||
76 | #include <asm/atari_stram.h> | ||
77 | #include <asm/atari_SLM.h> | ||
78 | |||
79 | |||
80 | #undef DEBUG | ||
81 | |||
82 | /* Define this if the page data are continuous in physical memory. That | ||
83 | * requires less reprogramming of the ST-DMA */ | ||
84 | #define SLM_CONTINUOUS_DMA | ||
85 | |||
86 | /* Use continuous reprogramming of the ST-DMA counter register. This is | ||
87 | * --strictly speaking-- not allowed, Atari recommends not to look at the | ||
88 | * counter register while a DMA is going on. But I don't know if that applies | ||
89 | * only for reading the register, or also writing to it. Writing only works | ||
90 | * fine for me... The advantage is that the timing becomes absolutely | ||
91 | * uncritical: Just update each, say 200ms, the counter reg to its maximum, | ||
92 | * and the DMA will work until the status byte interrupt occurs. | ||
93 | */ | ||
94 | #define SLM_CONT_CNT_REPROG | ||
95 | |||
96 | #define CMDSET_TARG_LUN(cmd,targ,lun) \ | ||
97 | do { \ | ||
98 | cmd[0] = (cmd[0] & ~0xe0) | (targ)<<5; \ | ||
99 | cmd[1] = (cmd[1] & ~0xe0) | (lun)<<5; \ | ||
100 | } while(0) | ||
101 | |||
102 | #define START_TIMER(to) mod_timer(&slm_timer, jiffies + (to)) | ||
103 | #define STOP_TIMER() del_timer(&slm_timer) | ||
104 | |||
105 | |||
106 | static char slmreqsense_cmd[6] = { 0x03, 0, 0, 0, 0, 0 }; | ||
107 | static char slmprint_cmd[6] = { 0x0a, 0, 0, 0, 0, 0 }; | ||
108 | static char slminquiry_cmd[6] = { 0x12, 0, 0, 0, 0, 0x80 }; | ||
109 | static char slmmsense_cmd[6] = { 0x1a, 0, 0, 0, 255, 0 }; | ||
110 | #if 0 | ||
111 | static char slmmselect_cmd[6] = { 0x15, 0, 0, 0, 0, 0 }; | ||
112 | #endif | ||
113 | |||
114 | |||
115 | #define MAX_SLM 2 | ||
116 | |||
117 | static struct slm { | ||
118 | unsigned target; /* target number */ | ||
119 | unsigned lun; /* LUN in target controller */ | ||
120 | atomic_t wr_ok; /* set to 0 if output part busy */ | ||
121 | atomic_t rd_ok; /* set to 0 if status part busy */ | ||
122 | } slm_info[MAX_SLM]; | ||
123 | |||
124 | int N_SLM_Printers = 0; | ||
125 | |||
126 | /* printer buffer */ | ||
127 | static unsigned char *SLMBuffer; /* start of buffer */ | ||
128 | static unsigned char *BufferP; /* current position in buffer */ | ||
129 | static int BufferSize; /* length of buffer for page size */ | ||
130 | |||
131 | typedef enum { IDLE, FILLING, PRINTING } SLMSTATE; | ||
132 | static SLMSTATE SLMState; | ||
133 | static int SLMBufOwner; /* SLM# currently using the buffer */ | ||
134 | |||
135 | /* DMA variables */ | ||
136 | #ifndef SLM_CONT_CNT_REPROG | ||
137 | static unsigned long SLMCurAddr; /* current base addr of DMA chunk */ | ||
138 | static unsigned long SLMEndAddr; /* expected end addr */ | ||
139 | static unsigned long SLMSliceSize; /* size of one DMA chunk */ | ||
140 | #endif | ||
141 | static int SLMError; | ||
142 | |||
143 | /* wait queues */ | ||
144 | static DECLARE_WAIT_QUEUE_HEAD(slm_wait); /* waiting for buffer */ | ||
145 | static DECLARE_WAIT_QUEUE_HEAD(print_wait); /* waiting for printing finished */ | ||
146 | |||
147 | /* status codes */ | ||
148 | #define SLMSTAT_OK 0x00 | ||
149 | #define SLMSTAT_ORNERY 0x02 | ||
150 | #define SLMSTAT_TONER 0x03 | ||
151 | #define SLMSTAT_WARMUP 0x04 | ||
152 | #define SLMSTAT_PAPER 0x05 | ||
153 | #define SLMSTAT_DRUM 0x06 | ||
154 | #define SLMSTAT_INJAM 0x07 | ||
155 | #define SLMSTAT_THRJAM 0x08 | ||
156 | #define SLMSTAT_OUTJAM 0x09 | ||
157 | #define SLMSTAT_COVER 0x0a | ||
158 | #define SLMSTAT_FUSER 0x0b | ||
159 | #define SLMSTAT_IMAGER 0x0c | ||
160 | #define SLMSTAT_MOTOR 0x0d | ||
161 | #define SLMSTAT_VIDEO 0x0e | ||
162 | #define SLMSTAT_SYSTO 0x10 | ||
163 | #define SLMSTAT_OPCODE 0x12 | ||
164 | #define SLMSTAT_DEVNUM 0x15 | ||
165 | #define SLMSTAT_PARAM 0x1a | ||
166 | #define SLMSTAT_ACSITO 0x1b /* driver defined */ | ||
167 | #define SLMSTAT_NOTALL 0x1c /* driver defined */ | ||
168 | |||
169 | static char *SLMErrors[] = { | ||
170 | /* 0x00 */ "OK and ready", | ||
171 | /* 0x01 */ NULL, | ||
172 | /* 0x02 */ "ornery printer", | ||
173 | /* 0x03 */ "toner empty", | ||
174 | /* 0x04 */ "warming up", | ||
175 | /* 0x05 */ "paper empty", | ||
176 | /* 0x06 */ "drum empty", | ||
177 | /* 0x07 */ "input jam", | ||
178 | /* 0x08 */ "through jam", | ||
179 | /* 0x09 */ "output jam", | ||
180 | /* 0x0a */ "cover open", | ||
181 | /* 0x0b */ "fuser malfunction", | ||
182 | /* 0x0c */ "imager malfunction", | ||
183 | /* 0x0d */ "motor malfunction", | ||
184 | /* 0x0e */ "video malfunction", | ||
185 | /* 0x0f */ NULL, | ||
186 | /* 0x10 */ "printer system timeout", | ||
187 | /* 0x11 */ NULL, | ||
188 | /* 0x12 */ "invalid operation code", | ||
189 | /* 0x13 */ NULL, | ||
190 | /* 0x14 */ NULL, | ||
191 | /* 0x15 */ "invalid device number", | ||
192 | /* 0x16 */ NULL, | ||
193 | /* 0x17 */ NULL, | ||
194 | /* 0x18 */ NULL, | ||
195 | /* 0x19 */ NULL, | ||
196 | /* 0x1a */ "invalid parameter list", | ||
197 | /* 0x1b */ "ACSI timeout", | ||
198 | /* 0x1c */ "not all printed" | ||
199 | }; | ||
200 | |||
201 | #define N_ERRORS (sizeof(SLMErrors)/sizeof(*SLMErrors)) | ||
202 | |||
203 | /* real (driver caused) error? */ | ||
204 | #define IS_REAL_ERROR(x) (x > 0x10) | ||
205 | |||
206 | |||
207 | static struct { | ||
208 | char *name; | ||
209 | int w, h; | ||
210 | } StdPageSize[] = { | ||
211 | { "Letter", 2400, 3180 }, | ||
212 | { "Legal", 2400, 4080 }, | ||
213 | { "A4", 2336, 3386 }, | ||
214 | { "B5", 2016, 2914 } | ||
215 | }; | ||
216 | |||
217 | #define N_STD_SIZES (sizeof(StdPageSize)/sizeof(*StdPageSize)) | ||
218 | |||
219 | #define SLM_BUFFER_SIZE (2336*3386/8) /* A4 for now */ | ||
220 | #define SLM_DMA_AMOUNT 255 /* #sectors to program the DMA for */ | ||
221 | |||
222 | #ifdef SLM_CONTINUOUS_DMA | ||
223 | # define SLM_DMA_INT_OFFSET 0 /* DMA goes until seccnt 0, no offs */ | ||
224 | # define SLM_DMA_END_OFFSET 32 /* 32 Byte ST-DMA FIFO */ | ||
225 | # define SLM_SLICE_SIZE(w) (255*512) | ||
226 | #else | ||
227 | # define SLM_DMA_INT_OFFSET 32 /* 32 Byte ST-DMA FIFO */ | ||
228 | # define SLM_DMA_END_OFFSET 32 /* 32 Byte ST-DMA FIFO */ | ||
229 | # define SLM_SLICE_SIZE(w) ((254*512)/(w/8)*(w/8)) | ||
230 | #endif | ||
231 | |||
232 | /* calculate the number of jiffies to wait for 'n' bytes */ | ||
233 | #ifdef SLM_CONT_CNT_REPROG | ||
234 | #define DMA_TIME_FOR(n) 50 | ||
235 | #define DMA_STARTUP_TIME 0 | ||
236 | #else | ||
237 | #define DMA_TIME_FOR(n) (n/1400-1) | ||
238 | #define DMA_STARTUP_TIME 650 | ||
239 | #endif | ||
240 | |||
241 | /***************************** Prototypes *****************************/ | ||
242 | |||
243 | static char *slm_errstr( int stat ); | ||
244 | static int slm_getstats( char *buffer, int device ); | ||
245 | static ssize_t slm_read( struct file* file, char *buf, size_t count, loff_t | ||
246 | *ppos ); | ||
247 | static void start_print( int device ); | ||
248 | static irqreturn_t slm_interrupt(int irc, void *data); | ||
249 | static void slm_test_ready( unsigned long dummy ); | ||
250 | static void set_dma_addr( unsigned long paddr ); | ||
251 | static unsigned long get_dma_addr( void ); | ||
252 | static ssize_t slm_write( struct file *file, const char *buf, size_t count, | ||
253 | loff_t *ppos ); | ||
254 | static int slm_ioctl( struct inode *inode, struct file *file, unsigned int | ||
255 | cmd, unsigned long arg ); | ||
256 | static int slm_open( struct inode *inode, struct file *file ); | ||
257 | static int slm_release( struct inode *inode, struct file *file ); | ||
258 | static int slm_req_sense( int device ); | ||
259 | static int slm_mode_sense( int device, char *buffer, int abs_flag ); | ||
260 | #if 0 | ||
261 | static int slm_mode_select( int device, char *buffer, int len, int | ||
262 | default_flag ); | ||
263 | #endif | ||
264 | static int slm_get_pagesize( int device, int *w, int *h ); | ||
265 | |||
266 | /************************* End of Prototypes **************************/ | ||
267 | |||
268 | |||
269 | static DEFINE_TIMER(slm_timer, slm_test_ready, 0, 0); | ||
270 | |||
271 | static const struct file_operations slm_fops = { | ||
272 | .owner = THIS_MODULE, | ||
273 | .read = slm_read, | ||
274 | .write = slm_write, | ||
275 | .ioctl = slm_ioctl, | ||
276 | .open = slm_open, | ||
277 | .release = slm_release, | ||
278 | }; | ||
279 | |||
280 | |||
281 | /* ---------------------------------------------------------------------- */ | ||
282 | /* Status Functions */ | ||
283 | |||
284 | |||
285 | static char *slm_errstr( int stat ) | ||
286 | |||
287 | { char *p; | ||
288 | static char str[22]; | ||
289 | |||
290 | stat &= 0x1f; | ||
291 | if (stat >= 0 && stat < N_ERRORS && (p = SLMErrors[stat])) | ||
292 | return( p ); | ||
293 | sprintf( str, "unknown status 0x%02x", stat ); | ||
294 | return( str ); | ||
295 | } | ||
296 | |||
297 | |||
298 | static int slm_getstats( char *buffer, int device ) | ||
299 | |||
300 | { int len = 0, stat, i, w, h; | ||
301 | unsigned char buf[256]; | ||
302 | |||
303 | stat = slm_mode_sense( device, buf, 0 ); | ||
304 | if (IS_REAL_ERROR(stat)) | ||
305 | return( -EIO ); | ||
306 | |||
307 | #define SHORTDATA(i) ((buf[i] << 8) | buf[i+1]) | ||
308 | #define BOOLDATA(i,mask) ((buf[i] & mask) ? "on" : "off") | ||
309 | |||
310 | w = SHORTDATA( 3 ); | ||
311 | h = SHORTDATA( 1 ); | ||
312 | |||
313 | len += sprintf( buffer+len, "Status\t\t%s\n", | ||
314 | slm_errstr( stat ) ); | ||
315 | len += sprintf( buffer+len, "Page Size\t%dx%d", | ||
316 | w, h ); | ||
317 | |||
318 | for( i = 0; i < N_STD_SIZES; ++i ) { | ||
319 | if (w == StdPageSize[i].w && h == StdPageSize[i].h) | ||
320 | break; | ||
321 | } | ||
322 | if (i < N_STD_SIZES) | ||
323 | len += sprintf( buffer+len, " (%s)", StdPageSize[i].name ); | ||
324 | buffer[len++] = '\n'; | ||
325 | |||
326 | len += sprintf( buffer+len, "Top/Left Margin\t%d/%d\n", | ||
327 | SHORTDATA( 5 ), SHORTDATA( 7 ) ); | ||
328 | len += sprintf( buffer+len, "Manual Feed\t%s\n", | ||
329 | BOOLDATA( 9, 0x01 ) ); | ||
330 | len += sprintf( buffer+len, "Input Select\t%d\n", | ||
331 | (buf[9] >> 1) & 7 ); | ||
332 | len += sprintf( buffer+len, "Auto Select\t%s\n", | ||
333 | BOOLDATA( 9, 0x10 ) ); | ||
334 | len += sprintf( buffer+len, "Prefeed Paper\t%s\n", | ||
335 | BOOLDATA( 9, 0x20 ) ); | ||
336 | len += sprintf( buffer+len, "Thick Pixels\t%s\n", | ||
337 | BOOLDATA( 9, 0x40 ) ); | ||
338 | len += sprintf( buffer+len, "H/V Resol.\t%d/%d dpi\n", | ||
339 | SHORTDATA( 12 ), SHORTDATA( 10 ) ); | ||
340 | len += sprintf( buffer+len, "System Timeout\t%d\n", | ||
341 | buf[14] ); | ||
342 | len += sprintf( buffer+len, "Scan Time\t%d\n", | ||
343 | SHORTDATA( 15 ) ); | ||
344 | len += sprintf( buffer+len, "Page Count\t%d\n", | ||
345 | SHORTDATA( 17 ) ); | ||
346 | len += sprintf( buffer+len, "In/Out Cap.\t%d/%d\n", | ||
347 | SHORTDATA( 19 ), SHORTDATA( 21 ) ); | ||
348 | len += sprintf( buffer+len, "Stagger Output\t%s\n", | ||
349 | BOOLDATA( 23, 0x01 ) ); | ||
350 | len += sprintf( buffer+len, "Output Select\t%d\n", | ||
351 | (buf[23] >> 1) & 7 ); | ||
352 | len += sprintf( buffer+len, "Duplex Print\t%s\n", | ||
353 | BOOLDATA( 23, 0x10 ) ); | ||
354 | len += sprintf( buffer+len, "Color Sep.\t%s\n", | ||
355 | BOOLDATA( 23, 0x20 ) ); | ||
356 | |||
357 | return( len ); | ||
358 | } | ||
359 | |||
360 | |||
361 | static ssize_t slm_read( struct file *file, char *buf, size_t count, | ||
362 | loff_t *ppos ) | ||
363 | |||
364 | { | ||
365 | struct inode *node = file->f_path.dentry->d_inode; | ||
366 | unsigned long page; | ||
367 | int length; | ||
368 | int end; | ||
369 | |||
370 | if (!(page = __get_free_page( GFP_KERNEL ))) | ||
371 | return( -ENOMEM ); | ||
372 | |||
373 | length = slm_getstats( (char *)page, iminor(node) ); | ||
374 | if (length < 0) { | ||
375 | count = length; | ||
376 | goto out; | ||
377 | } | ||
378 | if (file->f_pos >= length) { | ||
379 | count = 0; | ||
380 | goto out; | ||
381 | } | ||
382 | if (count + file->f_pos > length) | ||
383 | count = length - file->f_pos; | ||
384 | end = count + file->f_pos; | ||
385 | if (copy_to_user(buf, (char *)page + file->f_pos, count)) { | ||
386 | count = -EFAULT; | ||
387 | goto out; | ||
388 | } | ||
389 | file->f_pos = end; | ||
390 | out: free_page( page ); | ||
391 | return( count ); | ||
392 | } | ||
393 | |||
394 | |||
395 | /* ---------------------------------------------------------------------- */ | ||
396 | /* Printing */ | ||
397 | |||
398 | |||
399 | static void start_print( int device ) | ||
400 | |||
401 | { struct slm *sip = &slm_info[device]; | ||
402 | unsigned char *cmd; | ||
403 | unsigned long paddr; | ||
404 | int i; | ||
405 | |||
406 | stdma_lock( slm_interrupt, NULL ); | ||
407 | |||
408 | CMDSET_TARG_LUN( slmprint_cmd, sip->target, sip->lun ); | ||
409 | cmd = slmprint_cmd; | ||
410 | paddr = virt_to_phys( SLMBuffer ); | ||
411 | dma_cache_maintenance( paddr, virt_to_phys(BufferP)-paddr, 1 ); | ||
412 | DISABLE_IRQ(); | ||
413 | |||
414 | /* Low on A1 */ | ||
415 | dma_wd.dma_mode_status = 0x88; | ||
416 | MFPDELAY(); | ||
417 | |||
418 | /* send the command bytes except the last */ | ||
419 | for( i = 0; i < 5; ++i ) { | ||
420 | DMA_LONG_WRITE( *cmd++, 0x8a ); | ||
421 | udelay(20); | ||
422 | if (!acsi_wait_for_IRQ( HZ/2 )) { | ||
423 | SLMError = 1; | ||
424 | return; /* timeout */ | ||
425 | } | ||
426 | } | ||
427 | /* last command byte */ | ||
428 | DMA_LONG_WRITE( *cmd++, 0x82 ); | ||
429 | MFPDELAY(); | ||
430 | /* set DMA address */ | ||
431 | set_dma_addr( paddr ); | ||
432 | /* program DMA for write and select sector counter reg */ | ||
433 | dma_wd.dma_mode_status = 0x192; | ||
434 | MFPDELAY(); | ||
435 | /* program for 255*512 bytes and start DMA */ | ||
436 | DMA_LONG_WRITE( SLM_DMA_AMOUNT, 0x112 ); | ||
437 | |||
438 | #ifndef SLM_CONT_CNT_REPROG | ||
439 | SLMCurAddr = paddr; | ||
440 | SLMEndAddr = paddr + SLMSliceSize + SLM_DMA_INT_OFFSET; | ||
441 | #endif | ||
442 | START_TIMER( DMA_STARTUP_TIME + DMA_TIME_FOR( SLMSliceSize )); | ||
443 | #if !defined(SLM_CONT_CNT_REPROG) && defined(DEBUG) | ||
444 | printk( "SLM: CurAddr=%#lx EndAddr=%#lx timer=%ld\n", | ||
445 | SLMCurAddr, SLMEndAddr, DMA_TIME_FOR( SLMSliceSize ) ); | ||
446 | #endif | ||
447 | |||
448 | ENABLE_IRQ(); | ||
449 | } | ||
450 | |||
451 | |||
452 | /* Only called when an error happened or at the end of a page */ | ||
453 | |||
454 | static irqreturn_t slm_interrupt(int irc, void *data) | ||
455 | |||
456 | { unsigned long addr; | ||
457 | int stat; | ||
458 | |||
459 | STOP_TIMER(); | ||
460 | addr = get_dma_addr(); | ||
461 | stat = acsi_getstatus(); | ||
462 | SLMError = (stat < 0) ? SLMSTAT_ACSITO : | ||
463 | (addr < virt_to_phys(BufferP)) ? SLMSTAT_NOTALL : | ||
464 | stat; | ||
465 | |||
466 | dma_wd.dma_mode_status = 0x80; | ||
467 | MFPDELAY(); | ||
468 | #ifdef DEBUG | ||
469 | printk( "SLM: interrupt, addr=%#lx, error=%d\n", addr, SLMError ); | ||
470 | #endif | ||
471 | |||
472 | wake_up( &print_wait ); | ||
473 | stdma_release(); | ||
474 | ENABLE_IRQ(); | ||
475 | return IRQ_HANDLED; | ||
476 | } | ||
477 | |||
478 | |||
479 | static void slm_test_ready( unsigned long dummy ) | ||
480 | |||
481 | { | ||
482 | #ifdef SLM_CONT_CNT_REPROG | ||
483 | /* program for 255*512 bytes again */ | ||
484 | dma_wd.fdc_acces_seccount = SLM_DMA_AMOUNT; | ||
485 | START_TIMER( DMA_TIME_FOR(0) ); | ||
486 | #ifdef DEBUG | ||
487 | printk( "SLM: reprogramming timer for %d jiffies, addr=%#lx\n", | ||
488 | DMA_TIME_FOR(0), get_dma_addr() ); | ||
489 | #endif | ||
490 | |||
491 | #else /* !SLM_CONT_CNT_REPROG */ | ||
492 | |||
493 | unsigned long flags, addr; | ||
494 | int d, ti; | ||
495 | #ifdef DEBUG | ||
496 | struct timeval start_tm, end_tm; | ||
497 | int did_wait = 0; | ||
498 | #endif | ||
499 | |||
500 | local_irq_save(flags); | ||
501 | |||
502 | addr = get_dma_addr(); | ||
503 | if ((d = SLMEndAddr - addr) > 0) { | ||
504 | local_irq_restore(flags); | ||
505 | |||
506 | /* slice not yet finished, decide whether to start another timer or to | ||
507 | * busy-wait */ | ||
508 | ti = DMA_TIME_FOR( d ); | ||
509 | if (ti > 0) { | ||
510 | #ifdef DEBUG | ||
511 | printk( "SLM: reprogramming timer for %d jiffies, rest %d bytes\n", | ||
512 | ti, d ); | ||
513 | #endif | ||
514 | START_TIMER( ti ); | ||
515 | return; | ||
516 | } | ||
517 | /* wait for desired end address to be reached */ | ||
518 | #ifdef DEBUG | ||
519 | do_gettimeofday( &start_tm ); | ||
520 | did_wait = 1; | ||
521 | #endif | ||
522 | local_irq_disable(); | ||
523 | while( get_dma_addr() < SLMEndAddr ) | ||
524 | barrier(); | ||
525 | } | ||
526 | |||
527 | /* slice finished, start next one */ | ||
528 | SLMCurAddr += SLMSliceSize; | ||
529 | |||
530 | #ifdef SLM_CONTINUOUS_DMA | ||
531 | /* program for 255*512 bytes again */ | ||
532 | dma_wd.fdc_acces_seccount = SLM_DMA_AMOUNT; | ||
533 | #else | ||
534 | /* set DMA address; | ||
535 | * add 2 bytes for the ones in the SLM controller FIFO! */ | ||
536 | set_dma_addr( SLMCurAddr + 2 ); | ||
537 | /* toggle DMA to write and select sector counter reg */ | ||
538 | dma_wd.dma_mode_status = 0x92; | ||
539 | MFPDELAY(); | ||
540 | dma_wd.dma_mode_status = 0x192; | ||
541 | MFPDELAY(); | ||
542 | /* program for 255*512 bytes and start DMA */ | ||
543 | DMA_LONG_WRITE( SLM_DMA_AMOUNT, 0x112 ); | ||
544 | #endif | ||
545 | |||
546 | local_irq_restore(flags); | ||
547 | |||
548 | #ifdef DEBUG | ||
549 | if (did_wait) { | ||
550 | int ms; | ||
551 | do_gettimeofday( &end_tm ); | ||
552 | ms = (end_tm.tv_sec*1000000+end_tm.tv_usec) - | ||
553 | (start_tm.tv_sec*1000000+start_tm.tv_usec); | ||
554 | printk( "SLM: did %ld.%ld ms busy waiting for %d bytes\n", | ||
555 | ms/1000, ms%1000, d ); | ||
556 | } | ||
557 | else | ||
558 | printk( "SLM: didn't wait (!)\n" ); | ||
559 | #endif | ||
560 | |||
561 | if ((unsigned char *)PTOV( SLMCurAddr + SLMSliceSize ) >= BufferP) { | ||
562 | /* will be last slice, no timer necessary */ | ||
563 | #ifdef DEBUG | ||
564 | printk( "SLM: CurAddr=%#lx EndAddr=%#lx last slice -> no timer\n", | ||
565 | SLMCurAddr, SLMEndAddr ); | ||
566 | #endif | ||
567 | } | ||
568 | else { | ||
569 | /* not last slice */ | ||
570 | SLMEndAddr = SLMCurAddr + SLMSliceSize + SLM_DMA_INT_OFFSET; | ||
571 | START_TIMER( DMA_TIME_FOR( SLMSliceSize )); | ||
572 | #ifdef DEBUG | ||
573 | printk( "SLM: CurAddr=%#lx EndAddr=%#lx timer=%ld\n", | ||
574 | SLMCurAddr, SLMEndAddr, DMA_TIME_FOR( SLMSliceSize ) ); | ||
575 | #endif | ||
576 | } | ||
577 | #endif /* SLM_CONT_CNT_REPROG */ | ||
578 | } | ||
579 | |||
580 | |||
581 | static void set_dma_addr( unsigned long paddr ) | ||
582 | |||
583 | { unsigned long flags; | ||
584 | |||
585 | local_irq_save(flags); | ||
586 | dma_wd.dma_lo = (unsigned char)paddr; | ||
587 | paddr >>= 8; | ||
588 | MFPDELAY(); | ||
589 | dma_wd.dma_md = (unsigned char)paddr; | ||
590 | paddr >>= 8; | ||
591 | MFPDELAY(); | ||
592 | if (ATARIHW_PRESENT( EXTD_DMA )) | ||
593 | st_dma_ext_dmahi = (unsigned short)paddr; | ||
594 | else | ||
595 | dma_wd.dma_hi = (unsigned char)paddr; | ||
596 | MFPDELAY(); | ||
597 | local_irq_restore(flags); | ||
598 | } | ||
599 | |||
600 | |||
601 | static unsigned long get_dma_addr( void ) | ||
602 | |||
603 | { unsigned long addr; | ||
604 | |||
605 | addr = dma_wd.dma_lo & 0xff; | ||
606 | MFPDELAY(); | ||
607 | addr |= (dma_wd.dma_md & 0xff) << 8; | ||
608 | MFPDELAY(); | ||
609 | addr |= (dma_wd.dma_hi & 0xff) << 16; | ||
610 | MFPDELAY(); | ||
611 | |||
612 | return( addr ); | ||
613 | } | ||
614 | |||
615 | |||
616 | static ssize_t slm_write( struct file *file, const char *buf, size_t count, | ||
617 | loff_t *ppos ) | ||
618 | |||
619 | { | ||
620 | struct inode *node = file->f_path.dentry->d_inode; | ||
621 | int device = iminor(node); | ||
622 | int n, filled, w, h; | ||
623 | |||
624 | while( SLMState == PRINTING || | ||
625 | (SLMState == FILLING && SLMBufOwner != device) ) { | ||
626 | interruptible_sleep_on( &slm_wait ); | ||
627 | if (signal_pending(current)) | ||
628 | return( -ERESTARTSYS ); | ||
629 | } | ||
630 | if (SLMState == IDLE) { | ||
631 | /* first data of page: get current page size */ | ||
632 | if (slm_get_pagesize( device, &w, &h )) | ||
633 | return( -EIO ); | ||
634 | BufferSize = w*h/8; | ||
635 | if (BufferSize > SLM_BUFFER_SIZE) | ||
636 | return( -ENOMEM ); | ||
637 | |||
638 | SLMState = FILLING; | ||
639 | SLMBufOwner = device; | ||
640 | } | ||
641 | |||
642 | n = count; | ||
643 | filled = BufferP - SLMBuffer; | ||
644 | if (filled + n > BufferSize) | ||
645 | n = BufferSize - filled; | ||
646 | |||
647 | if (copy_from_user(BufferP, buf, n)) | ||
648 | return -EFAULT; | ||
649 | BufferP += n; | ||
650 | filled += n; | ||
651 | |||
652 | if (filled == BufferSize) { | ||
653 | /* Check the paper size again! The user may have switched it in the | ||
654 | * time between starting the data and finishing them. Would end up in | ||
655 | * a trashy page... */ | ||
656 | if (slm_get_pagesize( device, &w, &h )) | ||
657 | return( -EIO ); | ||
658 | if (BufferSize != w*h/8) { | ||
659 | printk( KERN_NOTICE "slm%d: page size changed while printing\n", | ||
660 | device ); | ||
661 | return( -EAGAIN ); | ||
662 | } | ||
663 | |||
664 | SLMState = PRINTING; | ||
665 | /* choose a slice size that is a multiple of the line size */ | ||
666 | #ifndef SLM_CONT_CNT_REPROG | ||
667 | SLMSliceSize = SLM_SLICE_SIZE(w); | ||
668 | #endif | ||
669 | |||
670 | start_print( device ); | ||
671 | sleep_on( &print_wait ); | ||
672 | if (SLMError && IS_REAL_ERROR(SLMError)) { | ||
673 | printk( KERN_ERR "slm%d: %s\n", device, slm_errstr(SLMError) ); | ||
674 | n = -EIO; | ||
675 | } | ||
676 | |||
677 | SLMState = IDLE; | ||
678 | BufferP = SLMBuffer; | ||
679 | wake_up_interruptible( &slm_wait ); | ||
680 | } | ||
681 | |||
682 | return( n ); | ||
683 | } | ||
684 | |||
685 | |||
686 | /* ---------------------------------------------------------------------- */ | ||
687 | /* ioctl Functions */ | ||
688 | |||
689 | |||
690 | static int slm_ioctl( struct inode *inode, struct file *file, | ||
691 | unsigned int cmd, unsigned long arg ) | ||
692 | |||
693 | { int device = iminor(inode), err; | ||
694 | |||
695 | /* I can think of setting: | ||
696 | * - manual feed | ||
697 | * - paper format | ||
698 | * - copy count | ||
699 | * - ... | ||
700 | * but haven't implemented that yet :-) | ||
701 | * BTW, has anybody better docs about the MODE SENSE/MODE SELECT data? | ||
702 | */ | ||
703 | switch( cmd ) { | ||
704 | |||
705 | case SLMIORESET: /* reset buffer, i.e. empty the buffer */ | ||
706 | if (!(file->f_mode & 2)) | ||
707 | return( -EINVAL ); | ||
708 | if (SLMState == PRINTING) | ||
709 | return( -EBUSY ); | ||
710 | SLMState = IDLE; | ||
711 | BufferP = SLMBuffer; | ||
712 | wake_up_interruptible( &slm_wait ); | ||
713 | return( 0 ); | ||
714 | |||
715 | case SLMIOGSTAT: { /* get status */ | ||
716 | int stat; | ||
717 | char *str; | ||
718 | |||
719 | stat = slm_req_sense( device ); | ||
720 | if (arg) { | ||
721 | str = slm_errstr( stat ); | ||
722 | if (put_user(stat, | ||
723 | (long *)&((struct SLM_status *)arg)->stat)) | ||
724 | return -EFAULT; | ||
725 | if (copy_to_user( ((struct SLM_status *)arg)->str, str, | ||
726 | strlen(str) + 1)) | ||
727 | return -EFAULT; | ||
728 | } | ||
729 | return( stat ); | ||
730 | } | ||
731 | |||
732 | case SLMIOGPSIZE: { /* get paper size */ | ||
733 | int w, h; | ||
734 | |||
735 | if ((err = slm_get_pagesize( device, &w, &h ))) return( err ); | ||
736 | |||
737 | if (put_user(w, (long *)&((struct SLM_paper_size *)arg)->width)) | ||
738 | return -EFAULT; | ||
739 | if (put_user(h, (long *)&((struct SLM_paper_size *)arg)->height)) | ||
740 | return -EFAULT; | ||
741 | return( 0 ); | ||
742 | } | ||
743 | |||
744 | case SLMIOGMFEED: /* get manual feed */ | ||
745 | return( -EINVAL ); | ||
746 | |||
747 | case SLMIOSPSIZE: /* set paper size */ | ||
748 | return( -EINVAL ); | ||
749 | |||
750 | case SLMIOSMFEED: /* set manual feed */ | ||
751 | return( -EINVAL ); | ||
752 | |||
753 | } | ||
754 | return( -EINVAL ); | ||
755 | } | ||
756 | |||
757 | |||
758 | /* ---------------------------------------------------------------------- */ | ||
759 | /* Opening and Closing */ | ||
760 | |||
761 | |||
762 | static int slm_open( struct inode *inode, struct file *file ) | ||
763 | |||
764 | { int device; | ||
765 | struct slm *sip; | ||
766 | |||
767 | device = iminor(inode); | ||
768 | if (device >= N_SLM_Printers) | ||
769 | return( -ENXIO ); | ||
770 | sip = &slm_info[device]; | ||
771 | |||
772 | if (file->f_mode & 2) { | ||
773 | /* open for writing is exclusive */ | ||
774 | if ( !atomic_dec_and_test(&sip->wr_ok) ) { | ||
775 | atomic_inc(&sip->wr_ok); | ||
776 | return( -EBUSY ); | ||
777 | } | ||
778 | } | ||
779 | if (file->f_mode & 1) { | ||
780 | /* open for reading is exclusive */ | ||
781 | if ( !atomic_dec_and_test(&sip->rd_ok) ) { | ||
782 | atomic_inc(&sip->rd_ok); | ||
783 | return( -EBUSY ); | ||
784 | } | ||
785 | } | ||
786 | |||
787 | return( 0 ); | ||
788 | } | ||
789 | |||
790 | |||
791 | static int slm_release( struct inode *inode, struct file *file ) | ||
792 | |||
793 | { int device; | ||
794 | struct slm *sip; | ||
795 | |||
796 | device = iminor(inode); | ||
797 | sip = &slm_info[device]; | ||
798 | |||
799 | if (file->f_mode & 2) | ||
800 | atomic_inc( &sip->wr_ok ); | ||
801 | if (file->f_mode & 1) | ||
802 | atomic_inc( &sip->rd_ok ); | ||
803 | |||
804 | return( 0 ); | ||
805 | } | ||
806 | |||
807 | |||
808 | /* ---------------------------------------------------------------------- */ | ||
809 | /* ACSI Primitives for the SLM */ | ||
810 | |||
811 | |||
812 | static int slm_req_sense( int device ) | ||
813 | |||
814 | { int stat, rv; | ||
815 | struct slm *sip = &slm_info[device]; | ||
816 | |||
817 | stdma_lock( NULL, NULL ); | ||
818 | |||
819 | CMDSET_TARG_LUN( slmreqsense_cmd, sip->target, sip->lun ); | ||
820 | if (!acsicmd_nodma( slmreqsense_cmd, 0 ) || | ||
821 | (stat = acsi_getstatus()) < 0) | ||
822 | rv = SLMSTAT_ACSITO; | ||
823 | else | ||
824 | rv = stat & 0x1f; | ||
825 | |||
826 | ENABLE_IRQ(); | ||
827 | stdma_release(); | ||
828 | return( rv ); | ||
829 | } | ||
830 | |||
831 | |||
832 | static int slm_mode_sense( int device, char *buffer, int abs_flag ) | ||
833 | |||
834 | { unsigned char stat, len; | ||
835 | int rv = 0; | ||
836 | struct slm *sip = &slm_info[device]; | ||
837 | |||
838 | stdma_lock( NULL, NULL ); | ||
839 | |||
840 | CMDSET_TARG_LUN( slmmsense_cmd, sip->target, sip->lun ); | ||
841 | slmmsense_cmd[5] = abs_flag ? 0x80 : 0; | ||
842 | if (!acsicmd_nodma( slmmsense_cmd, 0 )) { | ||
843 | rv = SLMSTAT_ACSITO; | ||
844 | goto the_end; | ||
845 | } | ||
846 | |||
847 | if (!acsi_extstatus( &stat, 1 )) { | ||
848 | acsi_end_extstatus(); | ||
849 | rv = SLMSTAT_ACSITO; | ||
850 | goto the_end; | ||
851 | } | ||
852 | |||
853 | if (!acsi_extstatus( &len, 1 )) { | ||
854 | acsi_end_extstatus(); | ||
855 | rv = SLMSTAT_ACSITO; | ||
856 | goto the_end; | ||
857 | } | ||
858 | buffer[0] = len; | ||
859 | if (!acsi_extstatus( buffer+1, len )) { | ||
860 | acsi_end_extstatus(); | ||
861 | rv = SLMSTAT_ACSITO; | ||
862 | goto the_end; | ||
863 | } | ||
864 | |||
865 | acsi_end_extstatus(); | ||
866 | rv = stat & 0x1f; | ||
867 | |||
868 | the_end: | ||
869 | ENABLE_IRQ(); | ||
870 | stdma_release(); | ||
871 | return( rv ); | ||
872 | } | ||
873 | |||
874 | |||
875 | #if 0 | ||
876 | /* currently unused */ | ||
877 | static int slm_mode_select( int device, char *buffer, int len, | ||
878 | int default_flag ) | ||
879 | |||
880 | { int stat, rv; | ||
881 | struct slm *sip = &slm_info[device]; | ||
882 | |||
883 | stdma_lock( NULL, NULL ); | ||
884 | |||
885 | CMDSET_TARG_LUN( slmmselect_cmd, sip->target, sip->lun ); | ||
886 | slmmselect_cmd[5] = default_flag ? 0x80 : 0; | ||
887 | if (!acsicmd_nodma( slmmselect_cmd, 0 )) { | ||
888 | rv = SLMSTAT_ACSITO; | ||
889 | goto the_end; | ||
890 | } | ||
891 | |||
892 | if (!default_flag) { | ||
893 | unsigned char c = len; | ||
894 | if (!acsi_extcmd( &c, 1 )) { | ||
895 | rv = SLMSTAT_ACSITO; | ||
896 | goto the_end; | ||
897 | } | ||
898 | if (!acsi_extcmd( buffer, len )) { | ||
899 | rv = SLMSTAT_ACSITO; | ||
900 | goto the_end; | ||
901 | } | ||
902 | } | ||
903 | |||
904 | stat = acsi_getstatus(); | ||
905 | rv = (stat < 0 ? SLMSTAT_ACSITO : stat); | ||
906 | |||
907 | the_end: | ||
908 | ENABLE_IRQ(); | ||
909 | stdma_release(); | ||
910 | return( rv ); | ||
911 | } | ||
912 | #endif | ||
913 | |||
914 | |||
915 | static int slm_get_pagesize( int device, int *w, int *h ) | ||
916 | |||
917 | { char buf[256]; | ||
918 | int stat; | ||
919 | |||
920 | stat = slm_mode_sense( device, buf, 0 ); | ||
921 | ENABLE_IRQ(); | ||
922 | stdma_release(); | ||
923 | |||
924 | if (stat != SLMSTAT_OK) | ||
925 | return( -EIO ); | ||
926 | |||
927 | *w = (buf[3] << 8) | buf[4]; | ||
928 | *h = (buf[1] << 8) | buf[2]; | ||
929 | return( 0 ); | ||
930 | } | ||
931 | |||
932 | |||
933 | /* ---------------------------------------------------------------------- */ | ||
934 | /* Initialization */ | ||
935 | |||
936 | |||
937 | int attach_slm( int target, int lun ) | ||
938 | |||
939 | { static int did_register; | ||
940 | int len; | ||
941 | |||
942 | if (N_SLM_Printers >= MAX_SLM) { | ||
943 | printk( KERN_WARNING "Too much SLMs\n" ); | ||
944 | return( 0 ); | ||
945 | } | ||
946 | |||
947 | /* do an INQUIRY */ | ||
948 | udelay(100); | ||
949 | CMDSET_TARG_LUN( slminquiry_cmd, target, lun ); | ||
950 | if (!acsicmd_nodma( slminquiry_cmd, 0 )) { | ||
951 | inq_timeout: | ||
952 | printk( KERN_ERR "SLM inquiry command timed out.\n" ); | ||
953 | inq_fail: | ||
954 | acsi_end_extstatus(); | ||
955 | return( 0 ); | ||
956 | } | ||
957 | /* read status and header of return data */ | ||
958 | if (!acsi_extstatus( SLMBuffer, 6 )) | ||
959 | goto inq_timeout; | ||
960 | |||
961 | if (SLMBuffer[1] != 2) { /* device type == printer? */ | ||
962 | printk( KERN_ERR "SLM inquiry returned device type != printer\n" ); | ||
963 | goto inq_fail; | ||
964 | } | ||
965 | len = SLMBuffer[5]; | ||
966 | |||
967 | /* read id string */ | ||
968 | if (!acsi_extstatus( SLMBuffer, len )) | ||
969 | goto inq_timeout; | ||
970 | acsi_end_extstatus(); | ||
971 | SLMBuffer[len] = 0; | ||
972 | |||
973 | if (!did_register) { | ||
974 | did_register = 1; | ||
975 | } | ||
976 | |||
977 | slm_info[N_SLM_Printers].target = target; | ||
978 | slm_info[N_SLM_Printers].lun = lun; | ||
979 | atomic_set(&slm_info[N_SLM_Printers].wr_ok, 1 ); | ||
980 | atomic_set(&slm_info[N_SLM_Printers].rd_ok, 1 ); | ||
981 | |||
982 | printk( KERN_INFO " Printer: %s\n", SLMBuffer ); | ||
983 | printk( KERN_INFO "Detected slm%d at id %d lun %d\n", | ||
984 | N_SLM_Printers, target, lun ); | ||
985 | N_SLM_Printers++; | ||
986 | return( 1 ); | ||
987 | } | ||
988 | |||
989 | int slm_init( void ) | ||
990 | |||
991 | { | ||
992 | int i; | ||
993 | if (register_chrdev( ACSI_MAJOR, "slm", &slm_fops )) { | ||
994 | printk( KERN_ERR "Unable to get major %d for ACSI SLM\n", ACSI_MAJOR ); | ||
995 | return -EBUSY; | ||
996 | } | ||
997 | |||
998 | if (!(SLMBuffer = atari_stram_alloc( SLM_BUFFER_SIZE, "SLM" ))) { | ||
999 | printk( KERN_ERR "Unable to get SLM ST-Ram buffer.\n" ); | ||
1000 | unregister_chrdev( ACSI_MAJOR, "slm" ); | ||
1001 | return -ENOMEM; | ||
1002 | } | ||
1003 | BufferP = SLMBuffer; | ||
1004 | SLMState = IDLE; | ||
1005 | |||
1006 | return 0; | ||
1007 | } | ||
1008 | |||
1009 | #ifdef MODULE | ||
1010 | |||
1011 | /* from acsi.c */ | ||
1012 | void acsi_attach_SLMs( int (*attach_func)( int, int ) ); | ||
1013 | |||
1014 | int init_module(void) | ||
1015 | { | ||
1016 | int err; | ||
1017 | |||
1018 | if ((err = slm_init())) | ||
1019 | return( err ); | ||
1020 | /* This calls attach_slm() for every target/lun where acsi.c detected a | ||
1021 | * printer */ | ||
1022 | acsi_attach_SLMs( attach_slm ); | ||
1023 | return( 0 ); | ||
1024 | } | ||
1025 | |||
1026 | void cleanup_module(void) | ||
1027 | { | ||
1028 | if (unregister_chrdev( ACSI_MAJOR, "slm" ) != 0) | ||
1029 | printk( KERN_ERR "acsi_slm: cleanup_module failed\n"); | ||
1030 | atari_stram_free( SLMBuffer ); | ||
1031 | } | ||
1032 | #endif | ||
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index c575fb1d585f..c12951024090 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c | |||
@@ -122,17 +122,12 @@ static int sock_xmit(struct socket *sock, int send, void *buf, int size, | |||
122 | int result; | 122 | int result; |
123 | struct msghdr msg; | 123 | struct msghdr msg; |
124 | struct kvec iov; | 124 | struct kvec iov; |
125 | unsigned long flags; | 125 | sigset_t blocked, oldset; |
126 | sigset_t oldset; | ||
127 | 126 | ||
128 | /* Allow interception of SIGKILL only | 127 | /* Allow interception of SIGKILL only |
129 | * Don't allow other signals to interrupt the transmission */ | 128 | * Don't allow other signals to interrupt the transmission */ |
130 | spin_lock_irqsave(¤t->sighand->siglock, flags); | 129 | siginitsetinv(&blocked, sigmask(SIGKILL)); |
131 | oldset = current->blocked; | 130 | sigprocmask(SIG_SETMASK, &blocked, &oldset); |
132 | sigfillset(¤t->blocked); | ||
133 | sigdelsetmask(¤t->blocked, sigmask(SIGKILL)); | ||
134 | recalc_sigpending(); | ||
135 | spin_unlock_irqrestore(¤t->sighand->siglock, flags); | ||
136 | 131 | ||
137 | do { | 132 | do { |
138 | sock->sk->sk_allocation = GFP_NOIO; | 133 | sock->sk->sk_allocation = GFP_NOIO; |
@@ -151,11 +146,9 @@ static int sock_xmit(struct socket *sock, int send, void *buf, int size, | |||
151 | 146 | ||
152 | if (signal_pending(current)) { | 147 | if (signal_pending(current)) { |
153 | siginfo_t info; | 148 | siginfo_t info; |
154 | spin_lock_irqsave(¤t->sighand->siglock, flags); | ||
155 | printk(KERN_WARNING "nbd (pid %d: %s) got signal %d\n", | 149 | printk(KERN_WARNING "nbd (pid %d: %s) got signal %d\n", |
156 | current->pid, current->comm, | 150 | current->pid, current->comm, |
157 | dequeue_signal(current, ¤t->blocked, &info)); | 151 | dequeue_signal_lock(current, ¤t->blocked, &info)); |
158 | spin_unlock_irqrestore(¤t->sighand->siglock, flags); | ||
159 | result = -EINTR; | 152 | result = -EINTR; |
160 | break; | 153 | break; |
161 | } | 154 | } |
@@ -169,10 +162,7 @@ static int sock_xmit(struct socket *sock, int send, void *buf, int size, | |||
169 | buf += result; | 162 | buf += result; |
170 | } while (size > 0); | 163 | } while (size > 0); |
171 | 164 | ||
172 | spin_lock_irqsave(¤t->sighand->siglock, flags); | 165 | sigprocmask(SIG_SETMASK, &oldset, NULL); |
173 | current->blocked = oldset; | ||
174 | recalc_sigpending(); | ||
175 | spin_unlock_irqrestore(¤t->sighand->siglock, flags); | ||
176 | 166 | ||
177 | return result; | 167 | return result; |
178 | } | 168 | } |
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index ce64e86d6ffb..7c294a40002e 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c | |||
@@ -1652,9 +1652,6 @@ static int kcdrwd(void *foobar) | |||
1652 | } | 1652 | } |
1653 | } | 1653 | } |
1654 | 1654 | ||
1655 | if (signal_pending(current)) { | ||
1656 | flush_signals(current); | ||
1657 | } | ||
1658 | if (kthread_should_stop()) | 1655 | if (kthread_should_stop()) |
1659 | break; | 1656 | break; |
1660 | } | 1657 | } |
diff --git a/drivers/block/sunvdc.c b/drivers/block/sunvdc.c new file mode 100644 index 000000000000..0f5e3caf85d7 --- /dev/null +++ b/drivers/block/sunvdc.c | |||
@@ -0,0 +1,972 @@ | |||
1 | /* sunvdc.c: Sun LDOM Virtual Disk Client. | ||
2 | * | ||
3 | * Copyright (C) 2007 David S. Miller <davem@davemloft.net> | ||
4 | */ | ||
5 | |||
6 | #include <linux/module.h> | ||
7 | #include <linux/kernel.h> | ||
8 | #include <linux/types.h> | ||
9 | #include <linux/blkdev.h> | ||
10 | #include <linux/hdreg.h> | ||
11 | #include <linux/genhd.h> | ||
12 | #include <linux/slab.h> | ||
13 | #include <linux/spinlock.h> | ||
14 | #include <linux/completion.h> | ||
15 | #include <linux/delay.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/list.h> | ||
18 | |||
19 | #include <asm/vio.h> | ||
20 | #include <asm/ldc.h> | ||
21 | |||
22 | #define DRV_MODULE_NAME "sunvdc" | ||
23 | #define PFX DRV_MODULE_NAME ": " | ||
24 | #define DRV_MODULE_VERSION "1.0" | ||
25 | #define DRV_MODULE_RELDATE "June 25, 2007" | ||
26 | |||
27 | static char version[] __devinitdata = | ||
28 | DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; | ||
29 | MODULE_AUTHOR("David S. Miller (davem@davemloft.net)"); | ||
30 | MODULE_DESCRIPTION("Sun LDOM virtual disk client driver"); | ||
31 | MODULE_LICENSE("GPL"); | ||
32 | MODULE_VERSION(DRV_MODULE_VERSION); | ||
33 | |||
34 | #define VDC_TX_RING_SIZE 256 | ||
35 | |||
36 | #define WAITING_FOR_LINK_UP 0x01 | ||
37 | #define WAITING_FOR_TX_SPACE 0x02 | ||
38 | #define WAITING_FOR_GEN_CMD 0x04 | ||
39 | #define WAITING_FOR_ANY -1 | ||
40 | |||
41 | struct vdc_req_entry { | ||
42 | struct request *req; | ||
43 | }; | ||
44 | |||
45 | struct vdc_port { | ||
46 | struct vio_driver_state vio; | ||
47 | |||
48 | struct vdc *vp; | ||
49 | |||
50 | struct gendisk *disk; | ||
51 | |||
52 | struct vdc_completion *cmp; | ||
53 | |||
54 | u64 req_id; | ||
55 | u64 seq; | ||
56 | struct vdc_req_entry rq_arr[VDC_TX_RING_SIZE]; | ||
57 | |||
58 | unsigned long ring_cookies; | ||
59 | |||
60 | u64 max_xfer_size; | ||
61 | u32 vdisk_block_size; | ||
62 | |||
63 | /* The server fills these in for us in the disk attribute | ||
64 | * ACK packet. | ||
65 | */ | ||
66 | u64 operations; | ||
67 | u32 vdisk_size; | ||
68 | u8 vdisk_type; | ||
69 | u8 dev_no; | ||
70 | |||
71 | char disk_name[32]; | ||
72 | |||
73 | struct vio_disk_geom geom; | ||
74 | struct vio_disk_vtoc label; | ||
75 | |||
76 | struct list_head list; | ||
77 | }; | ||
78 | |||
79 | static inline struct vdc_port *to_vdc_port(struct vio_driver_state *vio) | ||
80 | { | ||
81 | return container_of(vio, struct vdc_port, vio); | ||
82 | } | ||
83 | |||
84 | struct vdc { | ||
85 | /* Protects prot_list. */ | ||
86 | spinlock_t lock; | ||
87 | |||
88 | struct vio_dev *dev; | ||
89 | |||
90 | struct list_head port_list; | ||
91 | }; | ||
92 | |||
93 | /* Ordered from largest major to lowest */ | ||
94 | static struct vio_version vdc_versions[] = { | ||
95 | { .major = 1, .minor = 0 }, | ||
96 | }; | ||
97 | |||
98 | #define VDCBLK_NAME "vdisk" | ||
99 | static int vdc_major; | ||
100 | #define PARTITION_SHIFT 3 | ||
101 | |||
102 | static inline u32 vdc_tx_dring_avail(struct vio_dring_state *dr) | ||
103 | { | ||
104 | return vio_dring_avail(dr, VDC_TX_RING_SIZE); | ||
105 | } | ||
106 | |||
107 | static int vdc_getgeo(struct block_device *bdev, struct hd_geometry *geo) | ||
108 | { | ||
109 | struct gendisk *disk = bdev->bd_disk; | ||
110 | struct vdc_port *port = disk->private_data; | ||
111 | |||
112 | geo->heads = (u8) port->geom.num_hd; | ||
113 | geo->sectors = (u8) port->geom.num_sec; | ||
114 | geo->cylinders = port->geom.num_cyl; | ||
115 | |||
116 | return 0; | ||
117 | } | ||
118 | |||
119 | static struct block_device_operations vdc_fops = { | ||
120 | .owner = THIS_MODULE, | ||
121 | .getgeo = vdc_getgeo, | ||
122 | }; | ||
123 | |||
124 | static void vdc_finish(struct vio_driver_state *vio, int err, int waiting_for) | ||
125 | { | ||
126 | if (vio->cmp && | ||
127 | (waiting_for == -1 || | ||
128 | vio->cmp->waiting_for == waiting_for)) { | ||
129 | vio->cmp->err = err; | ||
130 | complete(&vio->cmp->com); | ||
131 | vio->cmp = NULL; | ||
132 | } | ||
133 | } | ||
134 | |||
135 | static void vdc_handshake_complete(struct vio_driver_state *vio) | ||
136 | { | ||
137 | vdc_finish(vio, 0, WAITING_FOR_LINK_UP); | ||
138 | } | ||
139 | |||
140 | static int vdc_handle_unknown(struct vdc_port *port, void *arg) | ||
141 | { | ||
142 | struct vio_msg_tag *pkt = arg; | ||
143 | |||
144 | printk(KERN_ERR PFX "Received unknown msg [%02x:%02x:%04x:%08x]\n", | ||
145 | pkt->type, pkt->stype, pkt->stype_env, pkt->sid); | ||
146 | printk(KERN_ERR PFX "Resetting connection.\n"); | ||
147 | |||
148 | ldc_disconnect(port->vio.lp); | ||
149 | |||
150 | return -ECONNRESET; | ||
151 | } | ||
152 | |||
153 | static int vdc_send_attr(struct vio_driver_state *vio) | ||
154 | { | ||
155 | struct vdc_port *port = to_vdc_port(vio); | ||
156 | struct vio_disk_attr_info pkt; | ||
157 | |||
158 | memset(&pkt, 0, sizeof(pkt)); | ||
159 | |||
160 | pkt.tag.type = VIO_TYPE_CTRL; | ||
161 | pkt.tag.stype = VIO_SUBTYPE_INFO; | ||
162 | pkt.tag.stype_env = VIO_ATTR_INFO; | ||
163 | pkt.tag.sid = vio_send_sid(vio); | ||
164 | |||
165 | pkt.xfer_mode = VIO_DRING_MODE; | ||
166 | pkt.vdisk_block_size = port->vdisk_block_size; | ||
167 | pkt.max_xfer_size = port->max_xfer_size; | ||
168 | |||
169 | viodbg(HS, "SEND ATTR xfer_mode[0x%x] blksz[%u] max_xfer[%lu]\n", | ||
170 | pkt.xfer_mode, pkt.vdisk_block_size, pkt.max_xfer_size); | ||
171 | |||
172 | return vio_ldc_send(&port->vio, &pkt, sizeof(pkt)); | ||
173 | } | ||
174 | |||
175 | static int vdc_handle_attr(struct vio_driver_state *vio, void *arg) | ||
176 | { | ||
177 | struct vdc_port *port = to_vdc_port(vio); | ||
178 | struct vio_disk_attr_info *pkt = arg; | ||
179 | |||
180 | viodbg(HS, "GOT ATTR stype[0x%x] ops[%lx] disk_size[%lu] disk_type[%x] " | ||
181 | "xfer_mode[0x%x] blksz[%u] max_xfer[%lu]\n", | ||
182 | pkt->tag.stype, pkt->operations, | ||
183 | pkt->vdisk_size, pkt->vdisk_type, | ||
184 | pkt->xfer_mode, pkt->vdisk_block_size, | ||
185 | pkt->max_xfer_size); | ||
186 | |||
187 | if (pkt->tag.stype == VIO_SUBTYPE_ACK) { | ||
188 | switch (pkt->vdisk_type) { | ||
189 | case VD_DISK_TYPE_DISK: | ||
190 | case VD_DISK_TYPE_SLICE: | ||
191 | break; | ||
192 | |||
193 | default: | ||
194 | printk(KERN_ERR PFX "%s: Bogus vdisk_type 0x%x\n", | ||
195 | vio->name, pkt->vdisk_type); | ||
196 | return -ECONNRESET; | ||
197 | } | ||
198 | |||
199 | if (pkt->vdisk_block_size > port->vdisk_block_size) { | ||
200 | printk(KERN_ERR PFX "%s: BLOCK size increased " | ||
201 | "%u --> %u\n", | ||
202 | vio->name, | ||
203 | port->vdisk_block_size, pkt->vdisk_block_size); | ||
204 | return -ECONNRESET; | ||
205 | } | ||
206 | |||
207 | port->operations = pkt->operations; | ||
208 | port->vdisk_size = pkt->vdisk_size; | ||
209 | port->vdisk_type = pkt->vdisk_type; | ||
210 | if (pkt->max_xfer_size < port->max_xfer_size) | ||
211 | port->max_xfer_size = pkt->max_xfer_size; | ||
212 | port->vdisk_block_size = pkt->vdisk_block_size; | ||
213 | return 0; | ||
214 | } else { | ||
215 | printk(KERN_ERR PFX "%s: Attribute NACK\n", vio->name); | ||
216 | |||
217 | return -ECONNRESET; | ||
218 | } | ||
219 | } | ||
220 | |||
221 | static void vdc_end_special(struct vdc_port *port, struct vio_disk_desc *desc) | ||
222 | { | ||
223 | int err = desc->status; | ||
224 | |||
225 | vdc_finish(&port->vio, -err, WAITING_FOR_GEN_CMD); | ||
226 | } | ||
227 | |||
228 | static void vdc_end_request(struct request *req, int uptodate, int num_sectors) | ||
229 | { | ||
230 | if (end_that_request_first(req, uptodate, num_sectors)) | ||
231 | return; | ||
232 | add_disk_randomness(req->rq_disk); | ||
233 | end_that_request_last(req, uptodate); | ||
234 | } | ||
235 | |||
236 | static void vdc_end_one(struct vdc_port *port, struct vio_dring_state *dr, | ||
237 | unsigned int index) | ||
238 | { | ||
239 | struct vio_disk_desc *desc = vio_dring_entry(dr, index); | ||
240 | struct vdc_req_entry *rqe = &port->rq_arr[index]; | ||
241 | struct request *req; | ||
242 | |||
243 | if (unlikely(desc->hdr.state != VIO_DESC_DONE)) | ||
244 | return; | ||
245 | |||
246 | ldc_unmap(port->vio.lp, desc->cookies, desc->ncookies); | ||
247 | desc->hdr.state = VIO_DESC_FREE; | ||
248 | dr->cons = (index + 1) & (VDC_TX_RING_SIZE - 1); | ||
249 | |||
250 | req = rqe->req; | ||
251 | if (req == NULL) { | ||
252 | vdc_end_special(port, desc); | ||
253 | return; | ||
254 | } | ||
255 | |||
256 | rqe->req = NULL; | ||
257 | |||
258 | vdc_end_request(req, !desc->status, desc->size >> 9); | ||
259 | |||
260 | if (blk_queue_stopped(port->disk->queue)) | ||
261 | blk_start_queue(port->disk->queue); | ||
262 | } | ||
263 | |||
264 | static int vdc_ack(struct vdc_port *port, void *msgbuf) | ||
265 | { | ||
266 | struct vio_dring_state *dr = &port->vio.drings[VIO_DRIVER_TX_RING]; | ||
267 | struct vio_dring_data *pkt = msgbuf; | ||
268 | |||
269 | if (unlikely(pkt->dring_ident != dr->ident || | ||
270 | pkt->start_idx != pkt->end_idx || | ||
271 | pkt->start_idx >= VDC_TX_RING_SIZE)) | ||
272 | return 0; | ||
273 | |||
274 | vdc_end_one(port, dr, pkt->start_idx); | ||
275 | |||
276 | return 0; | ||
277 | } | ||
278 | |||
279 | static int vdc_nack(struct vdc_port *port, void *msgbuf) | ||
280 | { | ||
281 | /* XXX Implement me XXX */ | ||
282 | return 0; | ||
283 | } | ||
284 | |||
285 | static void vdc_event(void *arg, int event) | ||
286 | { | ||
287 | struct vdc_port *port = arg; | ||
288 | struct vio_driver_state *vio = &port->vio; | ||
289 | unsigned long flags; | ||
290 | int err; | ||
291 | |||
292 | spin_lock_irqsave(&vio->lock, flags); | ||
293 | |||
294 | if (unlikely(event == LDC_EVENT_RESET || | ||
295 | event == LDC_EVENT_UP)) { | ||
296 | vio_link_state_change(vio, event); | ||
297 | spin_unlock_irqrestore(&vio->lock, flags); | ||
298 | return; | ||
299 | } | ||
300 | |||
301 | if (unlikely(event != LDC_EVENT_DATA_READY)) { | ||
302 | printk(KERN_WARNING PFX "Unexpected LDC event %d\n", event); | ||
303 | spin_unlock_irqrestore(&vio->lock, flags); | ||
304 | return; | ||
305 | } | ||
306 | |||
307 | err = 0; | ||
308 | while (1) { | ||
309 | union { | ||
310 | struct vio_msg_tag tag; | ||
311 | u64 raw[8]; | ||
312 | } msgbuf; | ||
313 | |||
314 | err = ldc_read(vio->lp, &msgbuf, sizeof(msgbuf)); | ||
315 | if (unlikely(err < 0)) { | ||
316 | if (err == -ECONNRESET) | ||
317 | vio_conn_reset(vio); | ||
318 | break; | ||
319 | } | ||
320 | if (err == 0) | ||
321 | break; | ||
322 | viodbg(DATA, "TAG [%02x:%02x:%04x:%08x]\n", | ||
323 | msgbuf.tag.type, | ||
324 | msgbuf.tag.stype, | ||
325 | msgbuf.tag.stype_env, | ||
326 | msgbuf.tag.sid); | ||
327 | err = vio_validate_sid(vio, &msgbuf.tag); | ||
328 | if (err < 0) | ||
329 | break; | ||
330 | |||
331 | if (likely(msgbuf.tag.type == VIO_TYPE_DATA)) { | ||
332 | if (msgbuf.tag.stype == VIO_SUBTYPE_ACK) | ||
333 | err = vdc_ack(port, &msgbuf); | ||
334 | else if (msgbuf.tag.stype == VIO_SUBTYPE_NACK) | ||
335 | err = vdc_nack(port, &msgbuf); | ||
336 | else | ||
337 | err = vdc_handle_unknown(port, &msgbuf); | ||
338 | } else if (msgbuf.tag.type == VIO_TYPE_CTRL) { | ||
339 | err = vio_control_pkt_engine(vio, &msgbuf); | ||
340 | } else { | ||
341 | err = vdc_handle_unknown(port, &msgbuf); | ||
342 | } | ||
343 | if (err < 0) | ||
344 | break; | ||
345 | } | ||
346 | if (err < 0) | ||
347 | vdc_finish(&port->vio, err, WAITING_FOR_ANY); | ||
348 | spin_unlock_irqrestore(&vio->lock, flags); | ||
349 | } | ||
350 | |||
351 | static int __vdc_tx_trigger(struct vdc_port *port) | ||
352 | { | ||
353 | struct vio_dring_state *dr = &port->vio.drings[VIO_DRIVER_TX_RING]; | ||
354 | struct vio_dring_data hdr = { | ||
355 | .tag = { | ||
356 | .type = VIO_TYPE_DATA, | ||
357 | .stype = VIO_SUBTYPE_INFO, | ||
358 | .stype_env = VIO_DRING_DATA, | ||
359 | .sid = vio_send_sid(&port->vio), | ||
360 | }, | ||
361 | .dring_ident = dr->ident, | ||
362 | .start_idx = dr->prod, | ||
363 | .end_idx = dr->prod, | ||
364 | }; | ||
365 | int err, delay; | ||
366 | |||
367 | hdr.seq = dr->snd_nxt; | ||
368 | delay = 1; | ||
369 | do { | ||
370 | err = vio_ldc_send(&port->vio, &hdr, sizeof(hdr)); | ||
371 | if (err > 0) { | ||
372 | dr->snd_nxt++; | ||
373 | break; | ||
374 | } | ||
375 | udelay(delay); | ||
376 | if ((delay <<= 1) > 128) | ||
377 | delay = 128; | ||
378 | } while (err == -EAGAIN); | ||
379 | |||
380 | return err; | ||
381 | } | ||
382 | |||
383 | static int __send_request(struct request *req) | ||
384 | { | ||
385 | struct vdc_port *port = req->rq_disk->private_data; | ||
386 | struct vio_dring_state *dr = &port->vio.drings[VIO_DRIVER_TX_RING]; | ||
387 | struct scatterlist sg[port->ring_cookies]; | ||
388 | struct vdc_req_entry *rqe; | ||
389 | struct vio_disk_desc *desc; | ||
390 | unsigned int map_perm; | ||
391 | int nsg, err, i; | ||
392 | u64 len; | ||
393 | u8 op; | ||
394 | |||
395 | map_perm = LDC_MAP_SHADOW | LDC_MAP_DIRECT | LDC_MAP_IO; | ||
396 | |||
397 | if (rq_data_dir(req) == READ) { | ||
398 | map_perm |= LDC_MAP_W; | ||
399 | op = VD_OP_BREAD; | ||
400 | } else { | ||
401 | map_perm |= LDC_MAP_R; | ||
402 | op = VD_OP_BWRITE; | ||
403 | } | ||
404 | |||
405 | nsg = blk_rq_map_sg(req->q, req, sg); | ||
406 | |||
407 | len = 0; | ||
408 | for (i = 0; i < nsg; i++) | ||
409 | len += sg[i].length; | ||
410 | |||
411 | if (unlikely(vdc_tx_dring_avail(dr) < 1)) { | ||
412 | blk_stop_queue(port->disk->queue); | ||
413 | err = -ENOMEM; | ||
414 | goto out; | ||
415 | } | ||
416 | |||
417 | desc = vio_dring_cur(dr); | ||
418 | |||
419 | err = ldc_map_sg(port->vio.lp, sg, nsg, | ||
420 | desc->cookies, port->ring_cookies, | ||
421 | map_perm); | ||
422 | if (err < 0) { | ||
423 | printk(KERN_ERR PFX "ldc_map_sg() failure, err=%d.\n", err); | ||
424 | return err; | ||
425 | } | ||
426 | |||
427 | rqe = &port->rq_arr[dr->prod]; | ||
428 | rqe->req = req; | ||
429 | |||
430 | desc->hdr.ack = VIO_ACK_ENABLE; | ||
431 | desc->req_id = port->req_id; | ||
432 | desc->operation = op; | ||
433 | if (port->vdisk_type == VD_DISK_TYPE_DISK) { | ||
434 | desc->slice = 2; | ||
435 | } else { | ||
436 | desc->slice = 0; | ||
437 | } | ||
438 | desc->status = ~0; | ||
439 | desc->offset = (req->sector << 9) / port->vdisk_block_size; | ||
440 | desc->size = len; | ||
441 | desc->ncookies = err; | ||
442 | |||
443 | /* This has to be a non-SMP write barrier because we are writing | ||
444 | * to memory which is shared with the peer LDOM. | ||
445 | */ | ||
446 | wmb(); | ||
447 | desc->hdr.state = VIO_DESC_READY; | ||
448 | |||
449 | err = __vdc_tx_trigger(port); | ||
450 | if (err < 0) { | ||
451 | printk(KERN_ERR PFX "vdc_tx_trigger() failure, err=%d\n", err); | ||
452 | } else { | ||
453 | port->req_id++; | ||
454 | dr->prod = (dr->prod + 1) & (VDC_TX_RING_SIZE - 1); | ||
455 | } | ||
456 | out: | ||
457 | |||
458 | return err; | ||
459 | } | ||
460 | |||
461 | static void do_vdc_request(request_queue_t *q) | ||
462 | { | ||
463 | while (1) { | ||
464 | struct request *req = elv_next_request(q); | ||
465 | |||
466 | if (!req) | ||
467 | break; | ||
468 | |||
469 | blkdev_dequeue_request(req); | ||
470 | if (__send_request(req) < 0) | ||
471 | vdc_end_request(req, 0, req->hard_nr_sectors); | ||
472 | } | ||
473 | } | ||
474 | |||
475 | static int generic_request(struct vdc_port *port, u8 op, void *buf, int len) | ||
476 | { | ||
477 | struct vio_dring_state *dr; | ||
478 | struct vio_completion comp; | ||
479 | struct vio_disk_desc *desc; | ||
480 | unsigned int map_perm; | ||
481 | unsigned long flags; | ||
482 | int op_len, err; | ||
483 | void *req_buf; | ||
484 | |||
485 | if (!(((u64)1 << ((u64)op - 1)) & port->operations)) | ||
486 | return -EOPNOTSUPP; | ||
487 | |||
488 | switch (op) { | ||
489 | case VD_OP_BREAD: | ||
490 | case VD_OP_BWRITE: | ||
491 | default: | ||
492 | return -EINVAL; | ||
493 | |||
494 | case VD_OP_FLUSH: | ||
495 | op_len = 0; | ||
496 | map_perm = 0; | ||
497 | break; | ||
498 | |||
499 | case VD_OP_GET_WCE: | ||
500 | op_len = sizeof(u32); | ||
501 | map_perm = LDC_MAP_W; | ||
502 | break; | ||
503 | |||
504 | case VD_OP_SET_WCE: | ||
505 | op_len = sizeof(u32); | ||
506 | map_perm = LDC_MAP_R; | ||
507 | break; | ||
508 | |||
509 | case VD_OP_GET_VTOC: | ||
510 | op_len = sizeof(struct vio_disk_vtoc); | ||
511 | map_perm = LDC_MAP_W; | ||
512 | break; | ||
513 | |||
514 | case VD_OP_SET_VTOC: | ||
515 | op_len = sizeof(struct vio_disk_vtoc); | ||
516 | map_perm = LDC_MAP_R; | ||
517 | break; | ||
518 | |||
519 | case VD_OP_GET_DISKGEOM: | ||
520 | op_len = sizeof(struct vio_disk_geom); | ||
521 | map_perm = LDC_MAP_W; | ||
522 | break; | ||
523 | |||
524 | case VD_OP_SET_DISKGEOM: | ||
525 | op_len = sizeof(struct vio_disk_geom); | ||
526 | map_perm = LDC_MAP_R; | ||
527 | break; | ||
528 | |||
529 | case VD_OP_SCSICMD: | ||
530 | op_len = 16; | ||
531 | map_perm = LDC_MAP_RW; | ||
532 | break; | ||
533 | |||
534 | case VD_OP_GET_DEVID: | ||
535 | op_len = sizeof(struct vio_disk_devid); | ||
536 | map_perm = LDC_MAP_W; | ||
537 | break; | ||
538 | |||
539 | case VD_OP_GET_EFI: | ||
540 | case VD_OP_SET_EFI: | ||
541 | return -EOPNOTSUPP; | ||
542 | break; | ||
543 | }; | ||
544 | |||
545 | map_perm |= LDC_MAP_SHADOW | LDC_MAP_DIRECT | LDC_MAP_IO; | ||
546 | |||
547 | op_len = (op_len + 7) & ~7; | ||
548 | req_buf = kzalloc(op_len, GFP_KERNEL); | ||
549 | if (!req_buf) | ||
550 | return -ENOMEM; | ||
551 | |||
552 | if (len > op_len) | ||
553 | len = op_len; | ||
554 | |||
555 | if (map_perm & LDC_MAP_R) | ||
556 | memcpy(req_buf, buf, len); | ||
557 | |||
558 | spin_lock_irqsave(&port->vio.lock, flags); | ||
559 | |||
560 | dr = &port->vio.drings[VIO_DRIVER_TX_RING]; | ||
561 | |||
562 | /* XXX If we want to use this code generically we have to | ||
563 | * XXX handle TX ring exhaustion etc. | ||
564 | */ | ||
565 | desc = vio_dring_cur(dr); | ||
566 | |||
567 | err = ldc_map_single(port->vio.lp, req_buf, op_len, | ||
568 | desc->cookies, port->ring_cookies, | ||
569 | map_perm); | ||
570 | if (err < 0) { | ||
571 | spin_unlock_irqrestore(&port->vio.lock, flags); | ||
572 | kfree(req_buf); | ||
573 | return err; | ||
574 | } | ||
575 | |||
576 | init_completion(&comp.com); | ||
577 | comp.waiting_for = WAITING_FOR_GEN_CMD; | ||
578 | port->vio.cmp = ∁ | ||
579 | |||
580 | desc->hdr.ack = VIO_ACK_ENABLE; | ||
581 | desc->req_id = port->req_id; | ||
582 | desc->operation = op; | ||
583 | desc->slice = 0; | ||
584 | desc->status = ~0; | ||
585 | desc->offset = 0; | ||
586 | desc->size = op_len; | ||
587 | desc->ncookies = err; | ||
588 | |||
589 | /* This has to be a non-SMP write barrier because we are writing | ||
590 | * to memory which is shared with the peer LDOM. | ||
591 | */ | ||
592 | wmb(); | ||
593 | desc->hdr.state = VIO_DESC_READY; | ||
594 | |||
595 | err = __vdc_tx_trigger(port); | ||
596 | if (err >= 0) { | ||
597 | port->req_id++; | ||
598 | dr->prod = (dr->prod + 1) & (VDC_TX_RING_SIZE - 1); | ||
599 | spin_unlock_irqrestore(&port->vio.lock, flags); | ||
600 | |||
601 | wait_for_completion(&comp.com); | ||
602 | err = comp.err; | ||
603 | } else { | ||
604 | port->vio.cmp = NULL; | ||
605 | spin_unlock_irqrestore(&port->vio.lock, flags); | ||
606 | } | ||
607 | |||
608 | if (map_perm & LDC_MAP_W) | ||
609 | memcpy(buf, req_buf, len); | ||
610 | |||
611 | kfree(req_buf); | ||
612 | |||
613 | return err; | ||
614 | } | ||
615 | |||
616 | static int __devinit vdc_alloc_tx_ring(struct vdc_port *port) | ||
617 | { | ||
618 | struct vio_dring_state *dr = &port->vio.drings[VIO_DRIVER_TX_RING]; | ||
619 | unsigned long len, entry_size; | ||
620 | int ncookies; | ||
621 | void *dring; | ||
622 | |||
623 | entry_size = sizeof(struct vio_disk_desc) + | ||
624 | (sizeof(struct ldc_trans_cookie) * port->ring_cookies); | ||
625 | len = (VDC_TX_RING_SIZE * entry_size); | ||
626 | |||
627 | ncookies = VIO_MAX_RING_COOKIES; | ||
628 | dring = ldc_alloc_exp_dring(port->vio.lp, len, | ||
629 | dr->cookies, &ncookies, | ||
630 | (LDC_MAP_SHADOW | | ||
631 | LDC_MAP_DIRECT | | ||
632 | LDC_MAP_RW)); | ||
633 | if (IS_ERR(dring)) | ||
634 | return PTR_ERR(dring); | ||
635 | |||
636 | dr->base = dring; | ||
637 | dr->entry_size = entry_size; | ||
638 | dr->num_entries = VDC_TX_RING_SIZE; | ||
639 | dr->prod = dr->cons = 0; | ||
640 | dr->pending = VDC_TX_RING_SIZE; | ||
641 | dr->ncookies = ncookies; | ||
642 | |||
643 | return 0; | ||
644 | } | ||
645 | |||
646 | static void vdc_free_tx_ring(struct vdc_port *port) | ||
647 | { | ||
648 | struct vio_dring_state *dr = &port->vio.drings[VIO_DRIVER_TX_RING]; | ||
649 | |||
650 | if (dr->base) { | ||
651 | ldc_free_exp_dring(port->vio.lp, dr->base, | ||
652 | (dr->entry_size * dr->num_entries), | ||
653 | dr->cookies, dr->ncookies); | ||
654 | dr->base = NULL; | ||
655 | dr->entry_size = 0; | ||
656 | dr->num_entries = 0; | ||
657 | dr->pending = 0; | ||
658 | dr->ncookies = 0; | ||
659 | } | ||
660 | } | ||
661 | |||
662 | static int probe_disk(struct vdc_port *port) | ||
663 | { | ||
664 | struct vio_completion comp; | ||
665 | struct request_queue *q; | ||
666 | struct gendisk *g; | ||
667 | int err; | ||
668 | |||
669 | init_completion(&comp.com); | ||
670 | comp.err = 0; | ||
671 | comp.waiting_for = WAITING_FOR_LINK_UP; | ||
672 | port->vio.cmp = ∁ | ||
673 | |||
674 | vio_port_up(&port->vio); | ||
675 | |||
676 | wait_for_completion(&comp.com); | ||
677 | if (comp.err) | ||
678 | return comp.err; | ||
679 | |||
680 | err = generic_request(port, VD_OP_GET_VTOC, | ||
681 | &port->label, sizeof(port->label)); | ||
682 | if (err < 0) { | ||
683 | printk(KERN_ERR PFX "VD_OP_GET_VTOC returns error %d\n", err); | ||
684 | return err; | ||
685 | } | ||
686 | |||
687 | err = generic_request(port, VD_OP_GET_DISKGEOM, | ||
688 | &port->geom, sizeof(port->geom)); | ||
689 | if (err < 0) { | ||
690 | printk(KERN_ERR PFX "VD_OP_GET_DISKGEOM returns " | ||
691 | "error %d\n", err); | ||
692 | return err; | ||
693 | } | ||
694 | |||
695 | port->vdisk_size = ((u64)port->geom.num_cyl * | ||
696 | (u64)port->geom.num_hd * | ||
697 | (u64)port->geom.num_sec); | ||
698 | |||
699 | q = blk_init_queue(do_vdc_request, &port->vio.lock); | ||
700 | if (!q) { | ||
701 | printk(KERN_ERR PFX "%s: Could not allocate queue.\n", | ||
702 | port->vio.name); | ||
703 | return -ENOMEM; | ||
704 | } | ||
705 | g = alloc_disk(1 << PARTITION_SHIFT); | ||
706 | if (!g) { | ||
707 | printk(KERN_ERR PFX "%s: Could not allocate gendisk.\n", | ||
708 | port->vio.name); | ||
709 | blk_cleanup_queue(q); | ||
710 | return -ENOMEM; | ||
711 | } | ||
712 | |||
713 | port->disk = g; | ||
714 | |||
715 | blk_queue_max_hw_segments(q, port->ring_cookies); | ||
716 | blk_queue_max_phys_segments(q, port->ring_cookies); | ||
717 | blk_queue_max_sectors(q, port->max_xfer_size); | ||
718 | g->major = vdc_major; | ||
719 | g->first_minor = port->dev_no << PARTITION_SHIFT; | ||
720 | strcpy(g->disk_name, port->disk_name); | ||
721 | |||
722 | g->fops = &vdc_fops; | ||
723 | g->queue = q; | ||
724 | g->private_data = port; | ||
725 | g->driverfs_dev = &port->vio.vdev->dev; | ||
726 | |||
727 | set_capacity(g, port->vdisk_size); | ||
728 | |||
729 | printk(KERN_INFO PFX "%s: %u sectors (%u MB)\n", | ||
730 | g->disk_name, | ||
731 | port->vdisk_size, (port->vdisk_size >> (20 - 9))); | ||
732 | |||
733 | add_disk(g); | ||
734 | |||
735 | return 0; | ||
736 | } | ||
737 | |||
738 | static struct ldc_channel_config vdc_ldc_cfg = { | ||
739 | .event = vdc_event, | ||
740 | .mtu = 64, | ||
741 | .mode = LDC_MODE_UNRELIABLE, | ||
742 | }; | ||
743 | |||
744 | static struct vio_driver_ops vdc_vio_ops = { | ||
745 | .send_attr = vdc_send_attr, | ||
746 | .handle_attr = vdc_handle_attr, | ||
747 | .handshake_complete = vdc_handshake_complete, | ||
748 | }; | ||
749 | |||
750 | static int __devinit vdc_port_probe(struct vio_dev *vdev, | ||
751 | const struct vio_device_id *id) | ||
752 | { | ||
753 | struct mdesc_handle *hp; | ||
754 | struct vdc_port *port; | ||
755 | unsigned long flags; | ||
756 | struct vdc *vp; | ||
757 | const u64 *port_id; | ||
758 | int err; | ||
759 | |||
760 | vp = dev_get_drvdata(vdev->dev.parent); | ||
761 | if (!vp) { | ||
762 | printk(KERN_ERR PFX "Cannot find port parent vdc.\n"); | ||
763 | return -ENODEV; | ||
764 | } | ||
765 | |||
766 | hp = mdesc_grab(); | ||
767 | |||
768 | port_id = mdesc_get_property(hp, vdev->mp, "id", NULL); | ||
769 | err = -ENODEV; | ||
770 | if (!port_id) { | ||
771 | printk(KERN_ERR PFX "Port lacks id property.\n"); | ||
772 | goto err_out_release_mdesc; | ||
773 | } | ||
774 | if ((*port_id << PARTITION_SHIFT) & ~(u64)MINORMASK) { | ||
775 | printk(KERN_ERR PFX "Port id [%lu] too large.\n", *port_id); | ||
776 | goto err_out_release_mdesc; | ||
777 | } | ||
778 | |||
779 | port = kzalloc(sizeof(*port), GFP_KERNEL); | ||
780 | err = -ENOMEM; | ||
781 | if (!port) { | ||
782 | printk(KERN_ERR PFX "Cannot allocate vdc_port.\n"); | ||
783 | goto err_out_release_mdesc; | ||
784 | } | ||
785 | |||
786 | port->vp = vp; | ||
787 | port->dev_no = *port_id; | ||
788 | |||
789 | if (port->dev_no >= 26) | ||
790 | snprintf(port->disk_name, sizeof(port->disk_name), | ||
791 | VDCBLK_NAME "%c%c", | ||
792 | 'a' + (port->dev_no / 26) - 1, | ||
793 | 'a' + (port->dev_no % 26)); | ||
794 | else | ||
795 | snprintf(port->disk_name, sizeof(port->disk_name), | ||
796 | VDCBLK_NAME "%c", 'a' + (port->dev_no % 26)); | ||
797 | |||
798 | err = vio_driver_init(&port->vio, vdev, VDEV_DISK, | ||
799 | vdc_versions, ARRAY_SIZE(vdc_versions), | ||
800 | &vdc_vio_ops, port->disk_name); | ||
801 | if (err) | ||
802 | goto err_out_free_port; | ||
803 | |||
804 | port->vdisk_block_size = 512; | ||
805 | port->max_xfer_size = ((128 * 1024) / port->vdisk_block_size); | ||
806 | port->ring_cookies = ((port->max_xfer_size * | ||
807 | port->vdisk_block_size) / PAGE_SIZE) + 2; | ||
808 | |||
809 | err = vio_ldc_alloc(&port->vio, &vdc_ldc_cfg, port); | ||
810 | if (err) | ||
811 | goto err_out_free_port; | ||
812 | |||
813 | err = vdc_alloc_tx_ring(port); | ||
814 | if (err) | ||
815 | goto err_out_free_ldc; | ||
816 | |||
817 | err = probe_disk(port); | ||
818 | if (err) | ||
819 | goto err_out_free_tx_ring; | ||
820 | |||
821 | INIT_LIST_HEAD(&port->list); | ||
822 | |||
823 | spin_lock_irqsave(&vp->lock, flags); | ||
824 | list_add(&port->list, &vp->port_list); | ||
825 | spin_unlock_irqrestore(&vp->lock, flags); | ||
826 | |||
827 | dev_set_drvdata(&vdev->dev, port); | ||
828 | |||
829 | mdesc_release(hp); | ||
830 | |||
831 | return 0; | ||
832 | |||
833 | err_out_free_tx_ring: | ||
834 | vdc_free_tx_ring(port); | ||
835 | |||
836 | err_out_free_ldc: | ||
837 | vio_ldc_free(&port->vio); | ||
838 | |||
839 | err_out_free_port: | ||
840 | kfree(port); | ||
841 | |||
842 | err_out_release_mdesc: | ||
843 | mdesc_release(hp); | ||
844 | return err; | ||
845 | } | ||
846 | |||
847 | static int vdc_port_remove(struct vio_dev *vdev) | ||
848 | { | ||
849 | struct vdc_port *port = dev_get_drvdata(&vdev->dev); | ||
850 | |||
851 | if (port) { | ||
852 | del_timer_sync(&port->vio.timer); | ||
853 | |||
854 | vdc_free_tx_ring(port); | ||
855 | vio_ldc_free(&port->vio); | ||
856 | |||
857 | dev_set_drvdata(&vdev->dev, NULL); | ||
858 | |||
859 | kfree(port); | ||
860 | } | ||
861 | return 0; | ||
862 | } | ||
863 | |||
864 | static struct vio_device_id vdc_port_match[] = { | ||
865 | { | ||
866 | .type = "vdc-port", | ||
867 | }, | ||
868 | {}, | ||
869 | }; | ||
870 | MODULE_DEVICE_TABLE(vio, vdc_match); | ||
871 | |||
872 | static struct vio_driver vdc_port_driver = { | ||
873 | .id_table = vdc_port_match, | ||
874 | .probe = vdc_port_probe, | ||
875 | .remove = vdc_port_remove, | ||
876 | .driver = { | ||
877 | .name = "vdc_port", | ||
878 | .owner = THIS_MODULE, | ||
879 | } | ||
880 | }; | ||
881 | |||
882 | static int __devinit vdc_probe(struct vio_dev *vdev, | ||
883 | const struct vio_device_id *id) | ||
884 | { | ||
885 | static int vdc_version_printed; | ||
886 | struct vdc *vp; | ||
887 | |||
888 | if (vdc_version_printed++ == 0) | ||
889 | printk(KERN_INFO "%s", version); | ||
890 | |||
891 | vp = kzalloc(sizeof(struct vdc), GFP_KERNEL); | ||
892 | if (!vp) | ||
893 | return -ENOMEM; | ||
894 | |||
895 | spin_lock_init(&vp->lock); | ||
896 | vp->dev = vdev; | ||
897 | INIT_LIST_HEAD(&vp->port_list); | ||
898 | |||
899 | dev_set_drvdata(&vdev->dev, vp); | ||
900 | |||
901 | return 0; | ||
902 | } | ||
903 | |||
904 | static int vdc_remove(struct vio_dev *vdev) | ||
905 | { | ||
906 | |||
907 | struct vdc *vp = dev_get_drvdata(&vdev->dev); | ||
908 | |||
909 | if (vp) { | ||
910 | kfree(vp); | ||
911 | dev_set_drvdata(&vdev->dev, NULL); | ||
912 | } | ||
913 | return 0; | ||
914 | } | ||
915 | |||
916 | static struct vio_device_id vdc_match[] = { | ||
917 | { | ||
918 | .type = "block", | ||
919 | }, | ||
920 | {}, | ||
921 | }; | ||
922 | MODULE_DEVICE_TABLE(vio, vdc_match); | ||
923 | |||
924 | static struct vio_driver vdc_driver = { | ||
925 | .id_table = vdc_match, | ||
926 | .probe = vdc_probe, | ||
927 | .remove = vdc_remove, | ||
928 | .driver = { | ||
929 | .name = "vdc", | ||
930 | .owner = THIS_MODULE, | ||
931 | } | ||
932 | }; | ||
933 | |||
934 | static int __init vdc_init(void) | ||
935 | { | ||
936 | int err; | ||
937 | |||
938 | err = register_blkdev(0, VDCBLK_NAME); | ||
939 | if (err < 0) | ||
940 | goto out_err; | ||
941 | |||
942 | vdc_major = err; | ||
943 | err = vio_register_driver(&vdc_driver); | ||
944 | if (err) | ||
945 | goto out_unregister_blkdev; | ||
946 | |||
947 | err = vio_register_driver(&vdc_port_driver); | ||
948 | if (err) | ||
949 | goto out_unregister_vdc; | ||
950 | |||
951 | return 0; | ||
952 | |||
953 | out_unregister_vdc: | ||
954 | vio_unregister_driver(&vdc_driver); | ||
955 | |||
956 | out_unregister_blkdev: | ||
957 | unregister_blkdev(vdc_major, VDCBLK_NAME); | ||
958 | vdc_major = 0; | ||
959 | |||
960 | out_err: | ||
961 | return err; | ||
962 | } | ||
963 | |||
964 | static void __exit vdc_exit(void) | ||
965 | { | ||
966 | vio_unregister_driver(&vdc_port_driver); | ||
967 | vio_unregister_driver(&vdc_driver); | ||
968 | unregister_blkdev(vdc_major, VDCBLK_NAME); | ||
969 | } | ||
970 | |||
971 | module_init(vdc_init); | ||
972 | module_exit(vdc_exit); | ||
diff --git a/drivers/block/umem.c b/drivers/block/umem.c index 6f5d6203d725..dec74bd23496 100644 --- a/drivers/block/umem.c +++ b/drivers/block/umem.c | |||
@@ -105,12 +105,6 @@ struct cardinfo { | |||
105 | unsigned long csr_base; | 105 | unsigned long csr_base; |
106 | unsigned char __iomem *csr_remap; | 106 | unsigned char __iomem *csr_remap; |
107 | unsigned long csr_len; | 107 | unsigned long csr_len; |
108 | #ifdef CONFIG_MM_MAP_MEMORY | ||
109 | unsigned long mem_base; | ||
110 | unsigned char __iomem *mem_remap; | ||
111 | unsigned long mem_len; | ||
112 | #endif | ||
113 | |||
114 | unsigned int win_size; /* PCI window size */ | 108 | unsigned int win_size; /* PCI window size */ |
115 | unsigned int mm_size; /* size in kbytes */ | 109 | unsigned int mm_size; /* size in kbytes */ |
116 | 110 | ||
@@ -872,10 +866,6 @@ static int __devinit mm_pci_probe(struct pci_dev *dev, const struct pci_device_i | |||
872 | 866 | ||
873 | card->csr_base = pci_resource_start(dev, 0); | 867 | card->csr_base = pci_resource_start(dev, 0); |
874 | card->csr_len = pci_resource_len(dev, 0); | 868 | card->csr_len = pci_resource_len(dev, 0); |
875 | #ifdef CONFIG_MM_MAP_MEMORY | ||
876 | card->mem_base = pci_resource_start(dev, 1); | ||
877 | card->mem_len = pci_resource_len(dev, 1); | ||
878 | #endif | ||
879 | 869 | ||
880 | printk(KERN_INFO "Micro Memory(tm) controller #%d found at %02x:%02x (PCI Mem Module (Battery Backup))\n", | 870 | printk(KERN_INFO "Micro Memory(tm) controller #%d found at %02x:%02x (PCI Mem Module (Battery Backup))\n", |
881 | card->card_number, dev->bus->number, dev->devfn); | 871 | card->card_number, dev->bus->number, dev->devfn); |
@@ -903,27 +893,6 @@ static int __devinit mm_pci_probe(struct pci_dev *dev, const struct pci_device_i | |||
903 | printk(KERN_INFO "MM%d: CSR 0x%08lx -> 0x%p (0x%lx)\n", card->card_number, | 893 | printk(KERN_INFO "MM%d: CSR 0x%08lx -> 0x%p (0x%lx)\n", card->card_number, |
904 | card->csr_base, card->csr_remap, card->csr_len); | 894 | card->csr_base, card->csr_remap, card->csr_len); |
905 | 895 | ||
906 | #ifdef CONFIG_MM_MAP_MEMORY | ||
907 | if (!request_mem_region(card->mem_base, card->mem_len, "Micro Memory")) { | ||
908 | printk(KERN_ERR "MM%d: Unable to request memory region\n", card->card_number); | ||
909 | ret = -ENOMEM; | ||
910 | |||
911 | goto failed_req_mem; | ||
912 | } | ||
913 | |||
914 | if (!(card->mem_remap = ioremap(card->mem_base, cards->mem_len))) { | ||
915 | printk(KERN_ERR "MM%d: Unable to remap memory region\n", card->card_number); | ||
916 | ret = -ENOMEM; | ||
917 | |||
918 | goto failed_remap_mem; | ||
919 | } | ||
920 | |||
921 | printk(KERN_INFO "MM%d: MEM 0x%8lx -> 0x%8lx (0x%lx)\n", card->card_number, | ||
922 | card->mem_base, card->mem_remap, card->mem_len); | ||
923 | #else | ||
924 | printk(KERN_INFO "MM%d: MEM area not remapped (CONFIG_MM_MAP_MEMORY not set)\n", | ||
925 | card->card_number); | ||
926 | #endif | ||
927 | switch(card->dev->device) { | 896 | switch(card->dev->device) { |
928 | case 0x5415: | 897 | case 0x5415: |
929 | card->flags |= UM_FLAG_NO_BYTE_STATUS | UM_FLAG_NO_BATTREG; | 898 | card->flags |= UM_FLAG_NO_BYTE_STATUS | UM_FLAG_NO_BATTREG; |
@@ -1091,12 +1060,6 @@ static int __devinit mm_pci_probe(struct pci_dev *dev, const struct pci_device_i | |||
1091 | card->mm_pages[1].desc, | 1060 | card->mm_pages[1].desc, |
1092 | card->mm_pages[1].page_dma); | 1061 | card->mm_pages[1].page_dma); |
1093 | failed_magic: | 1062 | failed_magic: |
1094 | #ifdef CONFIG_MM_MAP_MEMORY | ||
1095 | iounmap(card->mem_remap); | ||
1096 | failed_remap_mem: | ||
1097 | release_mem_region(card->mem_base, card->mem_len); | ||
1098 | failed_req_mem: | ||
1099 | #endif | ||
1100 | iounmap(card->csr_remap); | 1063 | iounmap(card->csr_remap); |
1101 | failed_remap_csr: | 1064 | failed_remap_csr: |
1102 | release_mem_region(card->csr_base, card->csr_len); | 1065 | release_mem_region(card->csr_base, card->csr_len); |
@@ -1116,10 +1079,6 @@ static void mm_pci_remove(struct pci_dev *dev) | |||
1116 | tasklet_kill(&card->tasklet); | 1079 | tasklet_kill(&card->tasklet); |
1117 | iounmap(card->csr_remap); | 1080 | iounmap(card->csr_remap); |
1118 | release_mem_region(card->csr_base, card->csr_len); | 1081 | release_mem_region(card->csr_base, card->csr_len); |
1119 | #ifdef CONFIG_MM_MAP_MEMORY | ||
1120 | iounmap(card->mem_remap); | ||
1121 | release_mem_region(card->mem_base, card->mem_len); | ||
1122 | #endif | ||
1123 | free_irq(card->irq, card); | 1082 | free_irq(card->irq, card); |
1124 | 1083 | ||
1125 | if (card->mm_pages[0].desc) | 1084 | if (card->mm_pages[0].desc) |
@@ -1133,23 +1092,18 @@ static void mm_pci_remove(struct pci_dev *dev) | |||
1133 | blk_cleanup_queue(card->queue); | 1092 | blk_cleanup_queue(card->queue); |
1134 | } | 1093 | } |
1135 | 1094 | ||
1136 | static const struct pci_device_id mm_pci_ids[] = { { | 1095 | static const struct pci_device_id mm_pci_ids[] = { |
1137 | .vendor = PCI_VENDOR_ID_MICRO_MEMORY, | 1096 | {PCI_DEVICE(PCI_VENDOR_ID_MICRO_MEMORY,PCI_DEVICE_ID_MICRO_MEMORY_5415CN)}, |
1138 | .device = PCI_DEVICE_ID_MICRO_MEMORY_5415CN, | 1097 | {PCI_DEVICE(PCI_VENDOR_ID_MICRO_MEMORY,PCI_DEVICE_ID_MICRO_MEMORY_5425CN)}, |
1139 | }, { | 1098 | {PCI_DEVICE(PCI_VENDOR_ID_MICRO_MEMORY,PCI_DEVICE_ID_MICRO_MEMORY_6155)}, |
1140 | .vendor = PCI_VENDOR_ID_MICRO_MEMORY, | 1099 | { |
1141 | .device = PCI_DEVICE_ID_MICRO_MEMORY_5425CN, | ||
1142 | }, { | ||
1143 | .vendor = PCI_VENDOR_ID_MICRO_MEMORY, | ||
1144 | .device = PCI_DEVICE_ID_MICRO_MEMORY_6155, | ||
1145 | }, { | ||
1146 | .vendor = 0x8086, | 1100 | .vendor = 0x8086, |
1147 | .device = 0xB555, | 1101 | .device = 0xB555, |
1148 | .subvendor= 0x1332, | 1102 | .subvendor= 0x1332, |
1149 | .subdevice= 0x5460, | 1103 | .subdevice= 0x5460, |
1150 | .class = 0x050000, | 1104 | .class = 0x050000, |
1151 | .class_mask= 0, | 1105 | .class_mask= 0, |
1152 | }, { /* end: all zeroes */ } | 1106 | }, { /* end: all zeroes */ } |
1153 | }; | 1107 | }; |
1154 | 1108 | ||
1155 | MODULE_DEVICE_TABLE(pci, mm_pci_ids); | 1109 | MODULE_DEVICE_TABLE(pci, mm_pci_ids); |
diff --git a/drivers/block/z2ram.c b/drivers/block/z2ram.c index 7cc2685ca84a..2abf94cc3137 100644 --- a/drivers/block/z2ram.c +++ b/drivers/block/z2ram.c | |||
@@ -44,9 +44,6 @@ | |||
44 | extern int m68k_realnum_memory; | 44 | extern int m68k_realnum_memory; |
45 | extern struct mem_info m68k_memory[NUM_MEMINFO]; | 45 | extern struct mem_info m68k_memory[NUM_MEMINFO]; |
46 | 46 | ||
47 | #define TRUE (1) | ||
48 | #define FALSE (0) | ||
49 | |||
50 | #define Z2MINOR_COMBINED (0) | 47 | #define Z2MINOR_COMBINED (0) |
51 | #define Z2MINOR_Z2ONLY (1) | 48 | #define Z2MINOR_Z2ONLY (1) |
52 | #define Z2MINOR_CHIPONLY (2) | 49 | #define Z2MINOR_CHIPONLY (2) |
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index f6648682b43a..ec9dc3d53f18 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig | |||
@@ -979,15 +979,14 @@ config GPIO_VR41XX | |||
979 | depends on CPU_VR41XX | 979 | depends on CPU_VR41XX |
980 | 980 | ||
981 | config RAW_DRIVER | 981 | config RAW_DRIVER |
982 | tristate "RAW driver (/dev/raw/rawN) (OBSOLETE)" | 982 | tristate "RAW driver (/dev/raw/rawN)" |
983 | depends on BLOCK | 983 | depends on BLOCK |
984 | help | 984 | help |
985 | The raw driver permits block devices to be bound to /dev/raw/rawN. | 985 | The raw driver permits block devices to be bound to /dev/raw/rawN. |
986 | Once bound, I/O against /dev/raw/rawN uses efficient zero-copy I/O. | 986 | Once bound, I/O against /dev/raw/rawN uses efficient zero-copy I/O. |
987 | See the raw(8) manpage for more details. | 987 | See the raw(8) manpage for more details. |
988 | 988 | ||
989 | The raw driver is deprecated and will be removed soon. | 989 | Applications should preferably open the device (eg /dev/hda1) |
990 | Applications should simply open the device (eg /dev/hda1) | ||
991 | with the O_DIRECT flag. | 990 | with the O_DIRECT flag. |
992 | 991 | ||
993 | config MAX_RAW_DEVS | 992 | config MAX_RAW_DEVS |
diff --git a/drivers/char/Makefile b/drivers/char/Makefile index 2f56ecc035aa..f2996a95eb07 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile | |||
@@ -15,6 +15,7 @@ obj-y += misc.o | |||
15 | obj-$(CONFIG_VT) += vt_ioctl.o vc_screen.o consolemap.o \ | 15 | obj-$(CONFIG_VT) += vt_ioctl.o vc_screen.o consolemap.o \ |
16 | consolemap_deftbl.o selection.o keyboard.o | 16 | consolemap_deftbl.o selection.o keyboard.o |
17 | obj-$(CONFIG_HW_CONSOLE) += vt.o defkeymap.o | 17 | obj-$(CONFIG_HW_CONSOLE) += vt.o defkeymap.o |
18 | obj-$(CONFIG_AUDIT) += tty_audit.o | ||
18 | obj-$(CONFIG_MAGIC_SYSRQ) += sysrq.o | 19 | obj-$(CONFIG_MAGIC_SYSRQ) += sysrq.o |
19 | obj-$(CONFIG_ESPSERIAL) += esp.o | 20 | obj-$(CONFIG_ESPSERIAL) += esp.o |
20 | obj-$(CONFIG_MVME147_SCC) += generic_serial.o vme_scc.o | 21 | obj-$(CONFIG_MVME147_SCC) += generic_serial.o vme_scc.o |
diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c index 4eaceabd8cea..7b02bf1289a2 100644 --- a/drivers/char/amiserial.c +++ b/drivers/char/amiserial.c | |||
@@ -738,6 +738,7 @@ static void change_speed(struct async_struct *info, | |||
738 | } | 738 | } |
739 | /* If the quotient is zero refuse the change */ | 739 | /* If the quotient is zero refuse the change */ |
740 | if (!quot && old_termios) { | 740 | if (!quot && old_termios) { |
741 | /* FIXME: Will need updating for new tty in the end */ | ||
741 | info->tty->termios->c_cflag &= ~CBAUD; | 742 | info->tty->termios->c_cflag &= ~CBAUD; |
742 | info->tty->termios->c_cflag |= (old_termios->c_cflag & CBAUD); | 743 | info->tty->termios->c_cflag |= (old_termios->c_cflag & CBAUD); |
743 | baud = tty_get_baud_rate(info->tty); | 744 | baud = tty_get_baud_rate(info->tty); |
@@ -783,7 +784,6 @@ static void change_speed(struct async_struct *info, | |||
783 | /* | 784 | /* |
784 | * Set up parity check flag | 785 | * Set up parity check flag |
785 | */ | 786 | */ |
786 | #define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK)) | ||
787 | 787 | ||
788 | info->read_status_mask = UART_LSR_OE | UART_LSR_DR; | 788 | info->read_status_mask = UART_LSR_OE | UART_LSR_DR; |
789 | if (I_INPCK(info->tty)) | 789 | if (I_INPCK(info->tty)) |
@@ -1367,11 +1367,6 @@ static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) | |||
1367 | unsigned long flags; | 1367 | unsigned long flags; |
1368 | unsigned int cflag = tty->termios->c_cflag; | 1368 | unsigned int cflag = tty->termios->c_cflag; |
1369 | 1369 | ||
1370 | if ( (cflag == old_termios->c_cflag) | ||
1371 | && ( RELEVANT_IFLAG(tty->termios->c_iflag) | ||
1372 | == RELEVANT_IFLAG(old_termios->c_iflag))) | ||
1373 | return; | ||
1374 | |||
1375 | change_speed(info, old_termios); | 1370 | change_speed(info, old_termios); |
1376 | 1371 | ||
1377 | /* Handle transition to B0 status */ | 1372 | /* Handle transition to B0 status */ |
diff --git a/drivers/char/consolemap.c b/drivers/char/consolemap.c index fd40b959afdd..4b3916f54909 100644 --- a/drivers/char/consolemap.c +++ b/drivers/char/consolemap.c | |||
@@ -177,6 +177,7 @@ struct uni_pagedir { | |||
177 | unsigned long refcount; | 177 | unsigned long refcount; |
178 | unsigned long sum; | 178 | unsigned long sum; |
179 | unsigned char *inverse_translations[4]; | 179 | unsigned char *inverse_translations[4]; |
180 | u16 *inverse_trans_unicode; | ||
180 | int readonly; | 181 | int readonly; |
181 | }; | 182 | }; |
182 | 183 | ||
@@ -207,6 +208,41 @@ static void set_inverse_transl(struct vc_data *conp, struct uni_pagedir *p, int | |||
207 | } | 208 | } |
208 | } | 209 | } |
209 | 210 | ||
211 | static void set_inverse_trans_unicode(struct vc_data *conp, | ||
212 | struct uni_pagedir *p) | ||
213 | { | ||
214 | int i, j, k, glyph; | ||
215 | u16 **p1, *p2; | ||
216 | u16 *q; | ||
217 | |||
218 | if (!p) return; | ||
219 | q = p->inverse_trans_unicode; | ||
220 | if (!q) { | ||
221 | q = p->inverse_trans_unicode = | ||
222 | kmalloc(MAX_GLYPH * sizeof(u16), GFP_KERNEL); | ||
223 | if (!q) | ||
224 | return; | ||
225 | } | ||
226 | memset(q, 0, MAX_GLYPH * sizeof(u16)); | ||
227 | |||
228 | for (i = 0; i < 32; i++) { | ||
229 | p1 = p->uni_pgdir[i]; | ||
230 | if (!p1) | ||
231 | continue; | ||
232 | for (j = 0; j < 32; j++) { | ||
233 | p2 = p1[j]; | ||
234 | if (!p2) | ||
235 | continue; | ||
236 | for (k = 0; k < 64; k++) { | ||
237 | glyph = p2[k]; | ||
238 | if (glyph >= 0 && glyph < MAX_GLYPH | ||
239 | && q[glyph] < 32) | ||
240 | q[glyph] = (i << 11) + (j << 6) + k; | ||
241 | } | ||
242 | } | ||
243 | } | ||
244 | } | ||
245 | |||
210 | unsigned short *set_translate(int m, struct vc_data *vc) | 246 | unsigned short *set_translate(int m, struct vc_data *vc) |
211 | { | 247 | { |
212 | inv_translate[vc->vc_num] = m; | 248 | inv_translate[vc->vc_num] = m; |
@@ -217,19 +253,29 @@ unsigned short *set_translate(int m, struct vc_data *vc) | |||
217 | * Inverse translation is impossible for several reasons: | 253 | * Inverse translation is impossible for several reasons: |
218 | * 1. The font<->character maps are not 1-1. | 254 | * 1. The font<->character maps are not 1-1. |
219 | * 2. The text may have been written while a different translation map | 255 | * 2. The text may have been written while a different translation map |
220 | * was active, or using Unicode. | 256 | * was active. |
221 | * Still, it is now possible to a certain extent to cut and paste non-ASCII. | 257 | * Still, it is now possible to a certain extent to cut and paste non-ASCII. |
222 | */ | 258 | */ |
223 | unsigned char inverse_translate(struct vc_data *conp, int glyph) | 259 | u16 inverse_translate(struct vc_data *conp, int glyph, int use_unicode) |
224 | { | 260 | { |
225 | struct uni_pagedir *p; | 261 | struct uni_pagedir *p; |
262 | int m; | ||
226 | if (glyph < 0 || glyph >= MAX_GLYPH) | 263 | if (glyph < 0 || glyph >= MAX_GLYPH) |
227 | return 0; | 264 | return 0; |
228 | else if (!(p = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc) || | 265 | else if (!(p = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc)) |
229 | !p->inverse_translations[inv_translate[conp->vc_num]]) | ||
230 | return glyph; | 266 | return glyph; |
231 | else | 267 | else if (use_unicode) { |
232 | return p->inverse_translations[inv_translate[conp->vc_num]][glyph]; | 268 | if (!p->inverse_trans_unicode) |
269 | return glyph; | ||
270 | else | ||
271 | return p->inverse_trans_unicode[glyph]; | ||
272 | } else { | ||
273 | m = inv_translate[conp->vc_num]; | ||
274 | if (!p->inverse_translations[m]) | ||
275 | return glyph; | ||
276 | else | ||
277 | return p->inverse_translations[m][glyph]; | ||
278 | } | ||
233 | } | 279 | } |
234 | 280 | ||
235 | static void update_user_maps(void) | 281 | static void update_user_maps(void) |
@@ -243,6 +289,7 @@ static void update_user_maps(void) | |||
243 | p = (struct uni_pagedir *)*vc_cons[i].d->vc_uni_pagedir_loc; | 289 | p = (struct uni_pagedir *)*vc_cons[i].d->vc_uni_pagedir_loc; |
244 | if (p && p != q) { | 290 | if (p && p != q) { |
245 | set_inverse_transl(vc_cons[i].d, p, USER_MAP); | 291 | set_inverse_transl(vc_cons[i].d, p, USER_MAP); |
292 | set_inverse_trans_unicode(vc_cons[i].d, p); | ||
246 | q = p; | 293 | q = p; |
247 | } | 294 | } |
248 | } | 295 | } |
@@ -353,6 +400,10 @@ static void con_release_unimap(struct uni_pagedir *p) | |||
353 | kfree(p->inverse_translations[i]); | 400 | kfree(p->inverse_translations[i]); |
354 | p->inverse_translations[i] = NULL; | 401 | p->inverse_translations[i] = NULL; |
355 | } | 402 | } |
403 | if (p->inverse_trans_unicode) { | ||
404 | kfree(p->inverse_trans_unicode); | ||
405 | p->inverse_trans_unicode = NULL; | ||
406 | } | ||
356 | } | 407 | } |
357 | 408 | ||
358 | void con_free_unimap(struct vc_data *vc) | 409 | void con_free_unimap(struct vc_data *vc) |
@@ -511,6 +562,7 @@ int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list) | |||
511 | 562 | ||
512 | for (i = 0; i <= 3; i++) | 563 | for (i = 0; i <= 3; i++) |
513 | set_inverse_transl(vc, p, i); /* Update all inverse translations */ | 564 | set_inverse_transl(vc, p, i); /* Update all inverse translations */ |
565 | set_inverse_trans_unicode(vc, p); | ||
514 | 566 | ||
515 | return err; | 567 | return err; |
516 | } | 568 | } |
@@ -561,6 +613,7 @@ int con_set_default_unimap(struct vc_data *vc) | |||
561 | 613 | ||
562 | for (i = 0; i <= 3; i++) | 614 | for (i = 0; i <= 3; i++) |
563 | set_inverse_transl(vc, p, i); /* Update all inverse translations */ | 615 | set_inverse_transl(vc, p, i); /* Update all inverse translations */ |
616 | set_inverse_trans_unicode(vc, p); | ||
564 | dflt = p; | 617 | dflt = p; |
565 | return err; | 618 | return err; |
566 | } | 619 | } |
@@ -617,6 +670,19 @@ void con_protect_unimap(struct vc_data *vc, int rdonly) | |||
617 | p->readonly = rdonly; | 670 | p->readonly = rdonly; |
618 | } | 671 | } |
619 | 672 | ||
673 | /* may be called during an interrupt */ | ||
674 | u32 conv_8bit_to_uni(unsigned char c) | ||
675 | { | ||
676 | /* | ||
677 | * Always use USER_MAP. This function is used by the keyboard, | ||
678 | * which shouldn't be affected by G0/G1 switching, etc. | ||
679 | * If the user map still contains default values, i.e. the | ||
680 | * direct-to-font mapping, then assume user is using Latin1. | ||
681 | */ | ||
682 | unsigned short uni = translations[USER_MAP][c]; | ||
683 | return uni == (0xf000 | c) ? c : uni; | ||
684 | } | ||
685 | |||
620 | int | 686 | int |
621 | conv_uni_to_pc(struct vc_data *conp, long ucs) | 687 | conv_uni_to_pc(struct vc_data *conp, long ucs) |
622 | { | 688 | { |
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c index ca376b92162c..e04005b5f8a6 100644 --- a/drivers/char/cyclades.c +++ b/drivers/char/cyclades.c | |||
@@ -4127,10 +4127,6 @@ static void cy_set_termios(struct tty_struct *tty, struct ktermios *old_termios) | |||
4127 | printk(KERN_DEBUG "cyc:cy_set_termios ttyC%d\n", info->line); | 4127 | printk(KERN_DEBUG "cyc:cy_set_termios ttyC%d\n", info->line); |
4128 | #endif | 4128 | #endif |
4129 | 4129 | ||
4130 | if (tty->termios->c_cflag == old_termios->c_cflag && | ||
4131 | (tty->termios->c_iflag & (IXON | IXANY)) == | ||
4132 | (old_termios->c_iflag & (IXON | IXANY))) | ||
4133 | return; | ||
4134 | set_line_char(info); | 4130 | set_line_char(info); |
4135 | 4131 | ||
4136 | if ((old_termios->c_cflag & CRTSCTS) && | 4132 | if ((old_termios->c_cflag & CRTSCTS) && |
diff --git a/drivers/char/esp.c b/drivers/char/esp.c index d1bfbaa2aa02..74cd5118af57 100644 --- a/drivers/char/esp.c +++ b/drivers/char/esp.c | |||
@@ -1121,8 +1121,6 @@ static void change_speed(struct esp_struct *info) | |||
1121 | /* | 1121 | /* |
1122 | * Set up parity check flag | 1122 | * Set up parity check flag |
1123 | */ | 1123 | */ |
1124 | #define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK)) | ||
1125 | |||
1126 | info->read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR; | 1124 | info->read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR; |
1127 | if (I_INPCK(info->tty)) | 1125 | if (I_INPCK(info->tty)) |
1128 | info->read_status_mask |= UART_LSR_FE | UART_LSR_PE; | 1126 | info->read_status_mask |= UART_LSR_FE | UART_LSR_PE; |
@@ -1920,11 +1918,6 @@ static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) | |||
1920 | struct esp_struct *info = (struct esp_struct *)tty->driver_data; | 1918 | struct esp_struct *info = (struct esp_struct *)tty->driver_data; |
1921 | unsigned long flags; | 1919 | unsigned long flags; |
1922 | 1920 | ||
1923 | if ( (tty->termios->c_cflag == old_termios->c_cflag) | ||
1924 | && ( RELEVANT_IFLAG(tty->termios->c_iflag) | ||
1925 | == RELEVANT_IFLAG(old_termios->c_iflag))) | ||
1926 | return; | ||
1927 | |||
1928 | change_speed(info); | 1921 | change_speed(info); |
1929 | 1922 | ||
1930 | spin_lock_irqsave(&info->lock, flags); | 1923 | spin_lock_irqsave(&info->lock, flags); |
diff --git a/drivers/char/generic_serial.c b/drivers/char/generic_serial.c index 8ea02755b1c9..8facf3e25c49 100644 --- a/drivers/char/generic_serial.c +++ b/drivers/char/generic_serial.c | |||
@@ -43,16 +43,6 @@ static int gs_debug; | |||
43 | 43 | ||
44 | #define func_enter() gs_dprintk (GS_DEBUG_FLOW, "gs: enter %s\n", __FUNCTION__) | 44 | #define func_enter() gs_dprintk (GS_DEBUG_FLOW, "gs: enter %s\n", __FUNCTION__) |
45 | #define func_exit() gs_dprintk (GS_DEBUG_FLOW, "gs: exit %s\n", __FUNCTION__) | 45 | #define func_exit() gs_dprintk (GS_DEBUG_FLOW, "gs: exit %s\n", __FUNCTION__) |
46 | #define NEW_WRITE_LOCKING 1 | ||
47 | #if NEW_WRITE_LOCKING | ||
48 | #define DECL /* Nothing */ | ||
49 | #define LOCKIT mutex_lock(& port->port_write_mutex); | ||
50 | #define RELEASEIT mutex_unlock(&port->port_write_mutex); | ||
51 | #else | ||
52 | #define DECL unsigned long flags; | ||
53 | #define LOCKIT save_flags (flags);cli () | ||
54 | #define RELEASEIT restore_flags (flags) | ||
55 | #endif | ||
56 | 46 | ||
57 | #define RS_EVENT_WRITE_WAKEUP 1 | 47 | #define RS_EVENT_WRITE_WAKEUP 1 |
58 | 48 | ||
@@ -62,7 +52,6 @@ module_param(gs_debug, int, 0644); | |||
62 | void gs_put_char(struct tty_struct * tty, unsigned char ch) | 52 | void gs_put_char(struct tty_struct * tty, unsigned char ch) |
63 | { | 53 | { |
64 | struct gs_port *port; | 54 | struct gs_port *port; |
65 | DECL | ||
66 | 55 | ||
67 | func_enter (); | 56 | func_enter (); |
68 | 57 | ||
@@ -75,11 +64,11 @@ void gs_put_char(struct tty_struct * tty, unsigned char ch) | |||
75 | if (! (port->flags & ASYNC_INITIALIZED)) return; | 64 | if (! (port->flags & ASYNC_INITIALIZED)) return; |
76 | 65 | ||
77 | /* Take a lock on the serial tranmit buffer! */ | 66 | /* Take a lock on the serial tranmit buffer! */ |
78 | LOCKIT; | 67 | mutex_lock(& port->port_write_mutex); |
79 | 68 | ||
80 | if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1) { | 69 | if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1) { |
81 | /* Sorry, buffer is full, drop character. Update statistics???? -- REW */ | 70 | /* Sorry, buffer is full, drop character. Update statistics???? -- REW */ |
82 | RELEASEIT; | 71 | mutex_unlock(&port->port_write_mutex); |
83 | return; | 72 | return; |
84 | } | 73 | } |
85 | 74 | ||
@@ -87,13 +76,11 @@ void gs_put_char(struct tty_struct * tty, unsigned char ch) | |||
87 | port->xmit_head &= SERIAL_XMIT_SIZE - 1; | 76 | port->xmit_head &= SERIAL_XMIT_SIZE - 1; |
88 | port->xmit_cnt++; /* Characters in buffer */ | 77 | port->xmit_cnt++; /* Characters in buffer */ |
89 | 78 | ||
90 | RELEASEIT; | 79 | mutex_unlock(&port->port_write_mutex); |
91 | func_exit (); | 80 | func_exit (); |
92 | } | 81 | } |
93 | 82 | ||
94 | 83 | ||
95 | #ifdef NEW_WRITE_LOCKING | ||
96 | |||
97 | /* | 84 | /* |
98 | > Problems to take into account are: | 85 | > Problems to take into account are: |
99 | > -1- Interrupts that empty part of the buffer. | 86 | > -1- Interrupts that empty part of the buffer. |
@@ -166,90 +153,6 @@ int gs_write(struct tty_struct * tty, | |||
166 | func_exit (); | 153 | func_exit (); |
167 | return total; | 154 | return total; |
168 | } | 155 | } |
169 | #else | ||
170 | /* | ||
171 | > Problems to take into account are: | ||
172 | > -1- Interrupts that empty part of the buffer. | ||
173 | > -2- page faults on the access to userspace. | ||
174 | > -3- Other processes that are also trying to do a "write". | ||
175 | */ | ||
176 | |||
177 | int gs_write(struct tty_struct * tty, | ||
178 | const unsigned char *buf, int count) | ||
179 | { | ||
180 | struct gs_port *port; | ||
181 | int c, total = 0; | ||
182 | int t; | ||
183 | unsigned long flags; | ||
184 | |||
185 | func_enter (); | ||
186 | |||
187 | /* The standard serial driver returns 0 in this case. | ||
188 | That sounds to me as "No error, I just didn't get to writing any | ||
189 | bytes. Feel free to try again." | ||
190 | The "official" way to write n bytes from buf is: | ||
191 | |||
192 | for (nwritten = 0;nwritten < n;nwritten += rv) { | ||
193 | rv = write (fd, buf+nwritten, n-nwritten); | ||
194 | if (rv < 0) break; // Error: bail out. // | ||
195 | } | ||
196 | |||
197 | which will loop endlessly in this case. The manual page for write | ||
198 | agrees with me. In practise almost everybody writes | ||
199 | "write (fd, buf,n);" but some people might have had to deal with | ||
200 | incomplete writes in the past and correctly implemented it by now... | ||
201 | */ | ||
202 | |||
203 | if (!tty) return -EIO; | ||
204 | |||
205 | port = tty->driver_data; | ||
206 | if (!port || !port->xmit_buf) | ||
207 | return -EIO; | ||
208 | |||
209 | local_save_flags(flags); | ||
210 | while (1) { | ||
211 | cli(); | ||
212 | c = count; | ||
213 | |||
214 | /* This is safe because we "OWN" the "head". Noone else can | ||
215 | change the "head": we own the port_write_mutex. */ | ||
216 | /* Don't overrun the end of the buffer */ | ||
217 | t = SERIAL_XMIT_SIZE - port->xmit_head; | ||
218 | if (t < c) c = t; | ||
219 | |||
220 | /* This is safe because the xmit_cnt can only decrease. This | ||
221 | would increase "t", so we might copy too little chars. */ | ||
222 | /* Don't copy past the "head" of the buffer */ | ||
223 | t = SERIAL_XMIT_SIZE - 1 - port->xmit_cnt; | ||
224 | if (t < c) c = t; | ||
225 | |||
226 | /* Can't copy more? break out! */ | ||
227 | if (c <= 0) { | ||
228 | local_restore_flags(flags); | ||
229 | break; | ||
230 | } | ||
231 | memcpy(port->xmit_buf + port->xmit_head, buf, c); | ||
232 | port->xmit_head = ((port->xmit_head + c) & | ||
233 | (SERIAL_XMIT_SIZE-1)); | ||
234 | port->xmit_cnt += c; | ||
235 | local_restore_flags(flags); | ||
236 | buf += c; | ||
237 | count -= c; | ||
238 | total += c; | ||
239 | } | ||
240 | |||
241 | if (port->xmit_cnt && | ||
242 | !tty->stopped && | ||
243 | !tty->hw_stopped && | ||
244 | !(port->flags & GS_TX_INTEN)) { | ||
245 | port->flags |= GS_TX_INTEN; | ||
246 | port->rd->enable_tx_interrupts (port); | ||
247 | } | ||
248 | func_exit (); | ||
249 | return total; | ||
250 | } | ||
251 | |||
252 | #endif | ||
253 | 156 | ||
254 | 157 | ||
255 | 158 | ||
@@ -737,23 +640,6 @@ void gs_set_termios (struct tty_struct * tty, | |||
737 | gs_dprintk (GS_DEBUG_TERMIOS, "termios structure (%p):\n", tiosp); | 640 | gs_dprintk (GS_DEBUG_TERMIOS, "termios structure (%p):\n", tiosp); |
738 | } | 641 | } |
739 | 642 | ||
740 | /* This is an optimization that is only allowed for dumb cards */ | ||
741 | /* Smart cards require knowledge of iflags and oflags too: that | ||
742 | might change hardware cooking mode.... */ | ||
743 | if (old_termios) { | ||
744 | if( (tiosp->c_iflag == old_termios->c_iflag) | ||
745 | && (tiosp->c_oflag == old_termios->c_oflag) | ||
746 | && (tiosp->c_cflag == old_termios->c_cflag) | ||
747 | && (tiosp->c_lflag == old_termios->c_lflag) | ||
748 | && (tiosp->c_line == old_termios->c_line) | ||
749 | && (memcmp(tiosp->c_cc, old_termios->c_cc, NCC) == 0)) { | ||
750 | gs_dprintk(GS_DEBUG_TERMIOS, "gs_set_termios: optimized away\n"); | ||
751 | return /* 0 */; | ||
752 | } | ||
753 | } else | ||
754 | gs_dprintk(GS_DEBUG_TERMIOS, "gs_set_termios: no old_termios: " | ||
755 | "no optimization\n"); | ||
756 | |||
757 | if(old_termios && (gs_debug & GS_DEBUG_TERMIOS)) { | 643 | if(old_termios && (gs_debug & GS_DEBUG_TERMIOS)) { |
758 | if(tiosp->c_iflag != old_termios->c_iflag) printk("c_iflag changed\n"); | 644 | if(tiosp->c_iflag != old_termios->c_iflag) printk("c_iflag changed\n"); |
759 | if(tiosp->c_oflag != old_termios->c_oflag) printk("c_oflag changed\n"); | 645 | if(tiosp->c_oflag != old_termios->c_oflag) printk("c_oflag changed\n"); |
diff --git a/drivers/char/genrtc.c b/drivers/char/genrtc.c index 9e1fc02967ff..69f0a2993af0 100644 --- a/drivers/char/genrtc.c +++ b/drivers/char/genrtc.c | |||
@@ -173,7 +173,6 @@ static void gen_rtc_interrupt(unsigned long arg) | |||
173 | static ssize_t gen_rtc_read(struct file *file, char __user *buf, | 173 | static ssize_t gen_rtc_read(struct file *file, char __user *buf, |
174 | size_t count, loff_t *ppos) | 174 | size_t count, loff_t *ppos) |
175 | { | 175 | { |
176 | DECLARE_WAITQUEUE(wait, current); | ||
177 | unsigned long data; | 176 | unsigned long data; |
178 | ssize_t retval; | 177 | ssize_t retval; |
179 | 178 | ||
@@ -183,18 +182,10 @@ static ssize_t gen_rtc_read(struct file *file, char __user *buf, | |||
183 | if (file->f_flags & O_NONBLOCK && !gen_rtc_irq_data) | 182 | if (file->f_flags & O_NONBLOCK && !gen_rtc_irq_data) |
184 | return -EAGAIN; | 183 | return -EAGAIN; |
185 | 184 | ||
186 | add_wait_queue(&gen_rtc_wait, &wait); | 185 | retval = wait_event_interruptible(gen_rtc_wait, |
187 | retval = -ERESTARTSYS; | 186 | (data = xchg(&gen_rtc_irq_data, 0))); |
188 | 187 | if (retval) | |
189 | while (1) { | 188 | goto out; |
190 | set_current_state(TASK_INTERRUPTIBLE); | ||
191 | data = xchg(&gen_rtc_irq_data, 0); | ||
192 | if (data) | ||
193 | break; | ||
194 | if (signal_pending(current)) | ||
195 | goto out; | ||
196 | schedule(); | ||
197 | } | ||
198 | 189 | ||
199 | /* first test allows optimizer to nuke this case for 32-bit machines */ | 190 | /* first test allows optimizer to nuke this case for 32-bit machines */ |
200 | if (sizeof (int) != sizeof (long) && count == sizeof (unsigned int)) { | 191 | if (sizeof (int) != sizeof (long) && count == sizeof (unsigned int)) { |
@@ -206,10 +197,7 @@ static ssize_t gen_rtc_read(struct file *file, char __user *buf, | |||
206 | retval = put_user(data, (unsigned long __user *)buf) ?: | 197 | retval = put_user(data, (unsigned long __user *)buf) ?: |
207 | sizeof(unsigned long); | 198 | sizeof(unsigned long); |
208 | } | 199 | } |
209 | out: | 200 | out: |
210 | __set_current_state(TASK_RUNNING); | ||
211 | remove_wait_queue(&gen_rtc_wait, &wait); | ||
212 | |||
213 | return retval; | 201 | return retval; |
214 | } | 202 | } |
215 | 203 | ||
diff --git a/drivers/char/hw_random/intel-rng.c b/drivers/char/hw_random/intel-rng.c index 4ae9811d1a6c..753f46052b87 100644 --- a/drivers/char/hw_random/intel-rng.c +++ b/drivers/char/hw_random/intel-rng.c | |||
@@ -296,12 +296,10 @@ static int __init intel_init_hw_struct(struct intel_rng_hw *intel_rng_hw, | |||
296 | (BIOS_CNTL_LOCK_ENABLE_MASK|BIOS_CNTL_WRITE_ENABLE_MASK)) | 296 | (BIOS_CNTL_LOCK_ENABLE_MASK|BIOS_CNTL_WRITE_ENABLE_MASK)) |
297 | == BIOS_CNTL_LOCK_ENABLE_MASK) { | 297 | == BIOS_CNTL_LOCK_ENABLE_MASK) { |
298 | static __initdata /*const*/ char warning[] = | 298 | static __initdata /*const*/ char warning[] = |
299 | KERN_WARNING PFX "Firmware space is locked read-only. " | 299 | KERN_WARNING PFX "Firmware space is locked read-only. If you can't or\n" |
300 | KERN_WARNING PFX "If you can't or\n don't want to " | 300 | KERN_WARNING PFX "don't want to disable this in firmware setup, and if\n" |
301 | KERN_WARNING PFX "disable this in firmware setup, and " | 301 | KERN_WARNING PFX "you are certain that your system has a functional\n" |
302 | KERN_WARNING PFX "if\n you are certain that your " | 302 | KERN_WARNING PFX "RNG, try using the 'no_fwh_detect' option.\n"; |
303 | KERN_WARNING PFX "system has a functional\n RNG, try" | ||
304 | KERN_WARNING PFX "using the 'no_fwh_detect' option.\n"; | ||
305 | 303 | ||
306 | if (no_fwh_detect) | 304 | if (no_fwh_detect) |
307 | return -ENODEV; | 305 | return -ENODEV; |
diff --git a/drivers/char/ip2/i2ellis.c b/drivers/char/ip2/i2ellis.c index dd761a1e4f08..61ef013b8445 100644 --- a/drivers/char/ip2/i2ellis.c +++ b/drivers/char/ip2/i2ellis.c | |||
@@ -43,8 +43,6 @@ static void iiEnableMailIrqIIEX(i2eBordStrPtr); | |||
43 | static void iiWriteMaskII(i2eBordStrPtr, unsigned char); | 43 | static void iiWriteMaskII(i2eBordStrPtr, unsigned char); |
44 | static void iiWriteMaskIIEX(i2eBordStrPtr, unsigned char); | 44 | static void iiWriteMaskIIEX(i2eBordStrPtr, unsigned char); |
45 | 45 | ||
46 | static void ii2DelayTimer(unsigned int); | ||
47 | static void ii2DelayWakeup(unsigned long id); | ||
48 | static void ii2Nop(void); | 46 | static void ii2Nop(void); |
49 | 47 | ||
50 | //*************** | 48 | //*************** |
@@ -55,8 +53,6 @@ static int ii2Safe; // Safe I/O address for delay routine | |||
55 | 53 | ||
56 | static int iiDelayed; // Set when the iiResetDelay function is | 54 | static int iiDelayed; // Set when the iiResetDelay function is |
57 | // called. Cleared when ANY board is reset. | 55 | // called. Cleared when ANY board is reset. |
58 | static struct timer_list * pDelayTimer; // Used by iiDelayTimer | ||
59 | static wait_queue_head_t pDelayWait; // Used by iiDelayTimer | ||
60 | static rwlock_t Dl_spinlock; | 56 | static rwlock_t Dl_spinlock; |
61 | 57 | ||
62 | //******** | 58 | //******** |
@@ -86,9 +82,6 @@ static rwlock_t Dl_spinlock; | |||
86 | static void | 82 | static void |
87 | iiEllisInit(void) | 83 | iiEllisInit(void) |
88 | { | 84 | { |
89 | pDelayTimer = kmalloc ( sizeof (struct timer_list), GFP_KERNEL ); | ||
90 | init_timer(pDelayTimer); | ||
91 | init_waitqueue_head(&pDelayWait); | ||
92 | LOCK_INIT(&Dl_spinlock); | 85 | LOCK_INIT(&Dl_spinlock); |
93 | } | 86 | } |
94 | 87 | ||
@@ -106,7 +99,6 @@ iiEllisInit(void) | |||
106 | static void | 99 | static void |
107 | iiEllisCleanup(void) | 100 | iiEllisCleanup(void) |
108 | { | 101 | { |
109 | kfree(pDelayTimer); | ||
110 | } | 102 | } |
111 | 103 | ||
112 | //****************************************************************************** | 104 | //****************************************************************************** |
@@ -560,19 +552,6 @@ iiInitialize(i2eBordStrPtr pB) | |||
560 | COMPLETE(pB, I2EE_GOOD); | 552 | COMPLETE(pB, I2EE_GOOD); |
561 | } | 553 | } |
562 | 554 | ||
563 | //======================================================= | ||
564 | // Delay Routines | ||
565 | // | ||
566 | // iiDelayIO | ||
567 | // iiNop | ||
568 | //======================================================= | ||
569 | |||
570 | static void | ||
571 | ii2DelayWakeup(unsigned long id) | ||
572 | { | ||
573 | wake_up_interruptible ( &pDelayWait ); | ||
574 | } | ||
575 | |||
576 | //****************************************************************************** | 555 | //****************************************************************************** |
577 | // Function: ii2DelayTimer(mseconds) | 556 | // Function: ii2DelayTimer(mseconds) |
578 | // Parameters: mseconds - number of milliseconds to delay | 557 | // Parameters: mseconds - number of milliseconds to delay |
@@ -594,28 +573,7 @@ ii2DelayWakeup(unsigned long id) | |||
594 | static void | 573 | static void |
595 | ii2DelayTimer(unsigned int mseconds) | 574 | ii2DelayTimer(unsigned int mseconds) |
596 | { | 575 | { |
597 | wait_queue_t wait; | 576 | msleep_interruptible(mseconds); |
598 | |||
599 | init_waitqueue_entry(&wait, current); | ||
600 | |||
601 | init_timer ( pDelayTimer ); | ||
602 | |||
603 | add_wait_queue(&pDelayWait, &wait); | ||
604 | |||
605 | set_current_state( TASK_INTERRUPTIBLE ); | ||
606 | |||
607 | pDelayTimer->expires = jiffies + ( mseconds + 9 ) / 10; | ||
608 | pDelayTimer->function = ii2DelayWakeup; | ||
609 | pDelayTimer->data = 0; | ||
610 | |||
611 | add_timer ( pDelayTimer ); | ||
612 | |||
613 | schedule(); | ||
614 | |||
615 | set_current_state( TASK_RUNNING ); | ||
616 | remove_wait_queue(&pDelayWait, &wait); | ||
617 | |||
618 | del_timer ( pDelayTimer ); | ||
619 | } | 577 | } |
620 | 578 | ||
621 | #if 0 | 579 | #if 0 |
diff --git a/drivers/char/ipmi/Kconfig b/drivers/char/ipmi/Kconfig index b894f67fdf14..0baa8fab4ea7 100644 --- a/drivers/char/ipmi/Kconfig +++ b/drivers/char/ipmi/Kconfig | |||
@@ -2,11 +2,9 @@ | |||
2 | # IPMI device configuration | 2 | # IPMI device configuration |
3 | # | 3 | # |
4 | 4 | ||
5 | menu "IPMI" | 5 | menuconfig IPMI_HANDLER |
6 | depends on HAS_IOMEM | ||
7 | |||
8 | config IPMI_HANDLER | ||
9 | tristate 'IPMI top-level message handler' | 6 | tristate 'IPMI top-level message handler' |
7 | depends on HAS_IOMEM | ||
10 | help | 8 | help |
11 | This enables the central IPMI message handler, required for IPMI | 9 | This enables the central IPMI message handler, required for IPMI |
12 | to work. | 10 | to work. |
@@ -18,9 +16,10 @@ config IPMI_HANDLER | |||
18 | 16 | ||
19 | If unsure, say N. | 17 | If unsure, say N. |
20 | 18 | ||
19 | if IPMI_HANDLER | ||
20 | |||
21 | config IPMI_PANIC_EVENT | 21 | config IPMI_PANIC_EVENT |
22 | bool 'Generate a panic event to all BMCs on a panic' | 22 | bool 'Generate a panic event to all BMCs on a panic' |
23 | depends on IPMI_HANDLER | ||
24 | help | 23 | help |
25 | When a panic occurs, this will cause the IPMI message handler to | 24 | When a panic occurs, this will cause the IPMI message handler to |
26 | generate an IPMI event describing the panic to each interface | 25 | generate an IPMI event describing the panic to each interface |
@@ -40,14 +39,12 @@ config IPMI_PANIC_STRING | |||
40 | 39 | ||
41 | config IPMI_DEVICE_INTERFACE | 40 | config IPMI_DEVICE_INTERFACE |
42 | tristate 'Device interface for IPMI' | 41 | tristate 'Device interface for IPMI' |
43 | depends on IPMI_HANDLER | ||
44 | help | 42 | help |
45 | This provides an IOCTL interface to the IPMI message handler so | 43 | This provides an IOCTL interface to the IPMI message handler so |
46 | userland processes may use IPMI. It supports poll() and select(). | 44 | userland processes may use IPMI. It supports poll() and select(). |
47 | 45 | ||
48 | config IPMI_SI | 46 | config IPMI_SI |
49 | tristate 'IPMI System Interface handler' | 47 | tristate 'IPMI System Interface handler' |
50 | depends on IPMI_HANDLER | ||
51 | help | 48 | help |
52 | Provides a driver for System Interfaces (KCS, SMIC, BT). | 49 | Provides a driver for System Interfaces (KCS, SMIC, BT). |
53 | Currently, only KCS and SMIC are supported. If | 50 | Currently, only KCS and SMIC are supported. If |
@@ -55,15 +52,13 @@ config IPMI_SI | |||
55 | 52 | ||
56 | config IPMI_WATCHDOG | 53 | config IPMI_WATCHDOG |
57 | tristate 'IPMI Watchdog Timer' | 54 | tristate 'IPMI Watchdog Timer' |
58 | depends on IPMI_HANDLER | ||
59 | help | 55 | help |
60 | This enables the IPMI watchdog timer. | 56 | This enables the IPMI watchdog timer. |
61 | 57 | ||
62 | config IPMI_POWEROFF | 58 | config IPMI_POWEROFF |
63 | tristate 'IPMI Poweroff' | 59 | tristate 'IPMI Poweroff' |
64 | depends on IPMI_HANDLER | ||
65 | help | 60 | help |
66 | This enables a function to power off the system with IPMI if | 61 | This enables a function to power off the system with IPMI if |
67 | the IPMI management controller is capable of this. | 62 | the IPMI management controller is capable of this. |
68 | 63 | ||
69 | endmenu | 64 | endif # IPMI_HANDLER |
diff --git a/drivers/char/ipmi/ipmi_poweroff.c b/drivers/char/ipmi/ipmi_poweroff.c index e02893b7b300..b86186de7f07 100644 --- a/drivers/char/ipmi/ipmi_poweroff.c +++ b/drivers/char/ipmi/ipmi_poweroff.c | |||
@@ -679,7 +679,7 @@ static int ipmi_poweroff_init (void) | |||
679 | { | 679 | { |
680 | int rv; | 680 | int rv; |
681 | 681 | ||
682 | printk ("Copyright (C) 2004 MontaVista Software -" | 682 | printk (KERN_INFO "Copyright (C) 2004 MontaVista Software -" |
683 | " IPMI Powerdown via sys_reboot.\n"); | 683 | " IPMI Powerdown via sys_reboot.\n"); |
684 | 684 | ||
685 | if (poweroff_powercycle) | 685 | if (poweroff_powercycle) |
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 78e1b962fe35..4edfdda0cf99 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c | |||
@@ -2857,7 +2857,7 @@ static int try_smi_init(struct smi_info *new_smi) | |||
2857 | 2857 | ||
2858 | mutex_unlock(&smi_infos_lock); | 2858 | mutex_unlock(&smi_infos_lock); |
2859 | 2859 | ||
2860 | printk(" IPMI %s interface initialized\n",si_to_str[new_smi->si_type]); | 2860 | printk(KERN_INFO "IPMI %s interface initialized\n",si_to_str[new_smi->si_type]); |
2861 | 2861 | ||
2862 | return 0; | 2862 | return 0; |
2863 | 2863 | ||
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c index 7b279d1de4a2..809409922996 100644 --- a/drivers/char/istallion.c +++ b/drivers/char/istallion.c | |||
@@ -1753,9 +1753,6 @@ static void stli_settermios(struct tty_struct *tty, struct ktermios *old) | |||
1753 | return; | 1753 | return; |
1754 | 1754 | ||
1755 | tiosp = tty->termios; | 1755 | tiosp = tty->termios; |
1756 | if ((tiosp->c_cflag == old->c_cflag) && | ||
1757 | (tiosp->c_iflag == old->c_iflag)) | ||
1758 | return; | ||
1759 | 1756 | ||
1760 | stli_mkasyport(portp, &aport, tiosp); | 1757 | stli_mkasyport(portp, &aport, tiosp); |
1761 | stli_cmdwait(brdp, portp, A_SETPORT, &aport, sizeof(asyport_t), 0); | 1758 | stli_cmdwait(brdp, portp, A_SETPORT, &aport, sizeof(asyport_t), 0); |
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c index 90965b4def5c..2ce0af1bd588 100644 --- a/drivers/char/keyboard.c +++ b/drivers/char/keyboard.c | |||
@@ -24,6 +24,7 @@ | |||
24 | * 21-08-02: Converted to input API, major cleanup. (Vojtech Pavlik) | 24 | * 21-08-02: Converted to input API, major cleanup. (Vojtech Pavlik) |
25 | */ | 25 | */ |
26 | 26 | ||
27 | #include <linux/consolemap.h> | ||
27 | #include <linux/module.h> | 28 | #include <linux/module.h> |
28 | #include <linux/sched.h> | 29 | #include <linux/sched.h> |
29 | #include <linux/tty.h> | 30 | #include <linux/tty.h> |
@@ -308,10 +309,9 @@ static void applkey(struct vc_data *vc, int key, char mode) | |||
308 | * Many other routines do put_queue, but I think either | 309 | * Many other routines do put_queue, but I think either |
309 | * they produce ASCII, or they produce some user-assigned | 310 | * they produce ASCII, or they produce some user-assigned |
310 | * string, and in both cases we might assume that it is | 311 | * string, and in both cases we might assume that it is |
311 | * in utf-8 already. UTF-8 is defined for words of up to 31 bits, | 312 | * in utf-8 already. |
312 | * but we need only 16 bits here | ||
313 | */ | 313 | */ |
314 | static void to_utf8(struct vc_data *vc, ushort c) | 314 | static void to_utf8(struct vc_data *vc, uint c) |
315 | { | 315 | { |
316 | if (c < 0x80) | 316 | if (c < 0x80) |
317 | /* 0******* */ | 317 | /* 0******* */ |
@@ -320,11 +320,21 @@ static void to_utf8(struct vc_data *vc, ushort c) | |||
320 | /* 110***** 10****** */ | 320 | /* 110***** 10****** */ |
321 | put_queue(vc, 0xc0 | (c >> 6)); | 321 | put_queue(vc, 0xc0 | (c >> 6)); |
322 | put_queue(vc, 0x80 | (c & 0x3f)); | 322 | put_queue(vc, 0x80 | (c & 0x3f)); |
323 | } else { | 323 | } else if (c < 0x10000) { |
324 | if (c >= 0xD800 && c < 0xE000) | ||
325 | return; | ||
326 | if (c == 0xFFFF) | ||
327 | return; | ||
324 | /* 1110**** 10****** 10****** */ | 328 | /* 1110**** 10****** 10****** */ |
325 | put_queue(vc, 0xe0 | (c >> 12)); | 329 | put_queue(vc, 0xe0 | (c >> 12)); |
326 | put_queue(vc, 0x80 | ((c >> 6) & 0x3f)); | 330 | put_queue(vc, 0x80 | ((c >> 6) & 0x3f)); |
327 | put_queue(vc, 0x80 | (c & 0x3f)); | 331 | put_queue(vc, 0x80 | (c & 0x3f)); |
332 | } else if (c < 0x110000) { | ||
333 | /* 11110*** 10****** 10****** 10****** */ | ||
334 | put_queue(vc, 0xf0 | (c >> 18)); | ||
335 | put_queue(vc, 0x80 | ((c >> 12) & 0x3f)); | ||
336 | put_queue(vc, 0x80 | ((c >> 6) & 0x3f)); | ||
337 | put_queue(vc, 0x80 | (c & 0x3f)); | ||
328 | } | 338 | } |
329 | } | 339 | } |
330 | 340 | ||
@@ -393,7 +403,7 @@ static unsigned int handle_diacr(struct vc_data *vc, unsigned int ch) | |||
393 | return d; | 403 | return d; |
394 | 404 | ||
395 | if (kbd->kbdmode == VC_UNICODE) | 405 | if (kbd->kbdmode == VC_UNICODE) |
396 | to_utf8(vc, d); | 406 | to_utf8(vc, conv_8bit_to_uni(d)); |
397 | else if (d < 0x100) | 407 | else if (d < 0x100) |
398 | put_queue(vc, d); | 408 | put_queue(vc, d); |
399 | 409 | ||
@@ -407,7 +417,7 @@ static void fn_enter(struct vc_data *vc) | |||
407 | { | 417 | { |
408 | if (diacr) { | 418 | if (diacr) { |
409 | if (kbd->kbdmode == VC_UNICODE) | 419 | if (kbd->kbdmode == VC_UNICODE) |
410 | to_utf8(vc, diacr); | 420 | to_utf8(vc, conv_8bit_to_uni(diacr)); |
411 | else if (diacr < 0x100) | 421 | else if (diacr < 0x100) |
412 | put_queue(vc, diacr); | 422 | put_queue(vc, diacr); |
413 | diacr = 0; | 423 | diacr = 0; |
@@ -617,7 +627,7 @@ static void k_unicode(struct vc_data *vc, unsigned int value, char up_flag) | |||
617 | return; | 627 | return; |
618 | } | 628 | } |
619 | if (kbd->kbdmode == VC_UNICODE) | 629 | if (kbd->kbdmode == VC_UNICODE) |
620 | to_utf8(vc, value); | 630 | to_utf8(vc, conv_8bit_to_uni(value)); |
621 | else if (value < 0x100) | 631 | else if (value < 0x100) |
622 | put_queue(vc, value); | 632 | put_queue(vc, value); |
623 | } | 633 | } |
@@ -775,7 +785,7 @@ static void k_shift(struct vc_data *vc, unsigned char value, char up_flag) | |||
775 | /* kludge */ | 785 | /* kludge */ |
776 | if (up_flag && shift_state != old_state && npadch != -1) { | 786 | if (up_flag && shift_state != old_state && npadch != -1) { |
777 | if (kbd->kbdmode == VC_UNICODE) | 787 | if (kbd->kbdmode == VC_UNICODE) |
778 | to_utf8(vc, npadch & 0xffff); | 788 | to_utf8(vc, npadch); |
779 | else | 789 | else |
780 | put_queue(vc, npadch & 0xff); | 790 | put_queue(vc, npadch & 0xff); |
781 | npadch = -1; | 791 | npadch = -1; |
diff --git a/drivers/char/misc.c b/drivers/char/misc.c index 4e6fb9651a16..71c8cd7fa15f 100644 --- a/drivers/char/misc.c +++ b/drivers/char/misc.c | |||
@@ -67,25 +67,13 @@ extern int pmu_device_init(void); | |||
67 | #ifdef CONFIG_PROC_FS | 67 | #ifdef CONFIG_PROC_FS |
68 | static void *misc_seq_start(struct seq_file *seq, loff_t *pos) | 68 | static void *misc_seq_start(struct seq_file *seq, loff_t *pos) |
69 | { | 69 | { |
70 | struct miscdevice *p; | ||
71 | loff_t off = 0; | ||
72 | |||
73 | mutex_lock(&misc_mtx); | 70 | mutex_lock(&misc_mtx); |
74 | list_for_each_entry(p, &misc_list, list) { | 71 | return seq_list_start(&misc_list, *pos); |
75 | if (*pos == off++) | ||
76 | return p; | ||
77 | } | ||
78 | return NULL; | ||
79 | } | 72 | } |
80 | 73 | ||
81 | static void *misc_seq_next(struct seq_file *seq, void *v, loff_t *pos) | 74 | static void *misc_seq_next(struct seq_file *seq, void *v, loff_t *pos) |
82 | { | 75 | { |
83 | struct list_head *n = ((struct miscdevice *)v)->list.next; | 76 | return seq_list_next(v, &misc_list, pos); |
84 | |||
85 | ++*pos; | ||
86 | |||
87 | return (n != &misc_list) ? list_entry(n, struct miscdevice, list) | ||
88 | : NULL; | ||
89 | } | 77 | } |
90 | 78 | ||
91 | static void misc_seq_stop(struct seq_file *seq, void *v) | 79 | static void misc_seq_stop(struct seq_file *seq, void *v) |
@@ -95,7 +83,7 @@ static void misc_seq_stop(struct seq_file *seq, void *v) | |||
95 | 83 | ||
96 | static int misc_seq_show(struct seq_file *seq, void *v) | 84 | static int misc_seq_show(struct seq_file *seq, void *v) |
97 | { | 85 | { |
98 | const struct miscdevice *p = v; | 86 | const struct miscdevice *p = list_entry(v, struct miscdevice, list); |
99 | 87 | ||
100 | seq_printf(seq, "%3i %s\n", p->minor, p->name ? p->name : ""); | 88 | seq_printf(seq, "%3i %s\n", p->minor, p->name ? p->name : ""); |
101 | return 0; | 89 | return 0; |
diff --git a/drivers/char/mspec.c b/drivers/char/mspec.c index 7ac30612068b..c716ef0dd370 100644 --- a/drivers/char/mspec.c +++ b/drivers/char/mspec.c | |||
@@ -265,7 +265,7 @@ mspec_mmap(struct file *file, struct vm_area_struct *vma, int type) | |||
265 | vdata->refcnt = ATOMIC_INIT(1); | 265 | vdata->refcnt = ATOMIC_INIT(1); |
266 | vma->vm_private_data = vdata; | 266 | vma->vm_private_data = vdata; |
267 | 267 | ||
268 | vma->vm_flags |= (VM_IO | VM_LOCKED | VM_RESERVED | VM_PFNMAP); | 268 | vma->vm_flags |= (VM_IO | VM_RESERVED | VM_PFNMAP); |
269 | if (vdata->type == MSPEC_FETCHOP || vdata->type == MSPEC_UNCACHED) | 269 | if (vdata->type == MSPEC_FETCHOP || vdata->type == MSPEC_UNCACHED) |
270 | vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); | 270 | vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); |
271 | vma->vm_ops = &mspec_vm_ops; | 271 | vma->vm_ops = &mspec_vm_ops; |
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c index 5953a45d7e96..2aee3fef0416 100644 --- a/drivers/char/mxser.c +++ b/drivers/char/mxser.c | |||
@@ -90,8 +90,6 @@ | |||
90 | #define UART_MCR_AFE 0x20 | 90 | #define UART_MCR_AFE 0x20 |
91 | #define UART_LSR_SPECIAL 0x1E | 91 | #define UART_LSR_SPECIAL 0x1E |
92 | 92 | ||
93 | #define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK|\ | ||
94 | IXON|IXOFF)) | ||
95 | 93 | ||
96 | #define IRQ_T(info) ((info->flags & ASYNC_SHARE_IRQ) ? IRQF_SHARED : IRQF_DISABLED) | 94 | #define IRQ_T(info) ((info->flags & ASYNC_SHARE_IRQ) ? IRQF_SHARED : IRQF_DISABLED) |
97 | 95 | ||
@@ -1729,16 +1727,12 @@ static void mxser_set_termios(struct tty_struct *tty, struct ktermios *old_termi | |||
1729 | struct mxser_struct *info = tty->driver_data; | 1727 | struct mxser_struct *info = tty->driver_data; |
1730 | unsigned long flags; | 1728 | unsigned long flags; |
1731 | 1729 | ||
1732 | if ((tty->termios->c_cflag != old_termios->c_cflag) || | 1730 | mxser_change_speed(info, old_termios); |
1733 | (RELEVANT_IFLAG(tty->termios->c_iflag) != RELEVANT_IFLAG(old_termios->c_iflag))) { | ||
1734 | 1731 | ||
1735 | mxser_change_speed(info, old_termios); | 1732 | if ((old_termios->c_cflag & CRTSCTS) && |
1736 | 1733 | !(tty->termios->c_cflag & CRTSCTS)) { | |
1737 | if ((old_termios->c_cflag & CRTSCTS) && | 1734 | tty->hw_stopped = 0; |
1738 | !(tty->termios->c_cflag & CRTSCTS)) { | 1735 | mxser_start(tty); |
1739 | tty->hw_stopped = 0; | ||
1740 | mxser_start(tty); | ||
1741 | } | ||
1742 | } | 1736 | } |
1743 | 1737 | ||
1744 | /* Handle sw stopped */ | 1738 | /* Handle sw stopped */ |
diff --git a/drivers/char/mxser_new.c b/drivers/char/mxser_new.c index 6cde448cd5b2..6a563932ba19 100644 --- a/drivers/char/mxser_new.c +++ b/drivers/char/mxser_new.c | |||
@@ -72,8 +72,6 @@ | |||
72 | #define UART_MCR_AFE 0x20 | 72 | #define UART_MCR_AFE 0x20 |
73 | #define UART_LSR_SPECIAL 0x1E | 73 | #define UART_LSR_SPECIAL 0x1E |
74 | 74 | ||
75 | #define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK|\ | ||
76 | IXON|IXOFF)) | ||
77 | 75 | ||
78 | #define C168_ASIC_ID 1 | 76 | #define C168_ASIC_ID 1 |
79 | #define C104_ASIC_ID 2 | 77 | #define C104_ASIC_ID 2 |
@@ -1560,7 +1558,7 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp) | |||
1560 | return -EFAULT; | 1558 | return -EFAULT; |
1561 | return 0; | 1559 | return 0; |
1562 | case MOXA_ASPP_MON_EXT: { | 1560 | case MOXA_ASPP_MON_EXT: { |
1563 | int status, p, shiftbit; | 1561 | int p, shiftbit; |
1564 | unsigned long opmode; | 1562 | unsigned long opmode; |
1565 | unsigned cflag, iflag; | 1563 | unsigned cflag, iflag; |
1566 | 1564 | ||
@@ -1990,18 +1988,14 @@ static void mxser_set_termios(struct tty_struct *tty, struct ktermios *old_termi | |||
1990 | struct mxser_port *info = tty->driver_data; | 1988 | struct mxser_port *info = tty->driver_data; |
1991 | unsigned long flags; | 1989 | unsigned long flags; |
1992 | 1990 | ||
1993 | if ((tty->termios->c_cflag != old_termios->c_cflag) || | 1991 | spin_lock_irqsave(&info->slock, flags); |
1994 | (RELEVANT_IFLAG(tty->termios->c_iflag) != RELEVANT_IFLAG(old_termios->c_iflag))) { | 1992 | mxser_change_speed(info, old_termios); |
1995 | 1993 | spin_unlock_irqrestore(&info->slock, flags); | |
1996 | spin_lock_irqsave(&info->slock, flags); | ||
1997 | mxser_change_speed(info, old_termios); | ||
1998 | spin_unlock_irqrestore(&info->slock, flags); | ||
1999 | 1994 | ||
2000 | if ((old_termios->c_cflag & CRTSCTS) && | 1995 | if ((old_termios->c_cflag & CRTSCTS) && |
2001 | !(tty->termios->c_cflag & CRTSCTS)) { | 1996 | !(tty->termios->c_cflag & CRTSCTS)) { |
2002 | tty->hw_stopped = 0; | 1997 | tty->hw_stopped = 0; |
2003 | mxser_start(tty); | 1998 | mxser_start(tty); |
2004 | } | ||
2005 | } | 1999 | } |
2006 | 2000 | ||
2007 | /* Handle sw stopped */ | 2001 | /* Handle sw stopped */ |
diff --git a/drivers/char/n_hdlc.c b/drivers/char/n_hdlc.c index 337a87f86a3b..e8332f305d72 100644 --- a/drivers/char/n_hdlc.c +++ b/drivers/char/n_hdlc.c | |||
@@ -400,7 +400,12 @@ static void n_hdlc_send_frames(struct n_hdlc *n_hdlc, struct tty_struct *tty) | |||
400 | /* Send the next block of data to device */ | 400 | /* Send the next block of data to device */ |
401 | tty->flags |= (1 << TTY_DO_WRITE_WAKEUP); | 401 | tty->flags |= (1 << TTY_DO_WRITE_WAKEUP); |
402 | actual = tty->driver->write(tty, tbuf->buf, tbuf->count); | 402 | actual = tty->driver->write(tty, tbuf->buf, tbuf->count); |
403 | 403 | ||
404 | /* rollback was possible and has been done */ | ||
405 | if (actual == -ERESTARTSYS) { | ||
406 | n_hdlc->tbuf = tbuf; | ||
407 | break; | ||
408 | } | ||
404 | /* if transmit error, throw frame away by */ | 409 | /* if transmit error, throw frame away by */ |
405 | /* pretending it was accepted by driver */ | 410 | /* pretending it was accepted by driver */ |
406 | if (actual < 0) | 411 | if (actual < 0) |
@@ -780,13 +785,14 @@ static unsigned int n_hdlc_tty_poll(struct tty_struct *tty, struct file *filp, | |||
780 | poll_wait(filp, &tty->write_wait, wait); | 785 | poll_wait(filp, &tty->write_wait, wait); |
781 | 786 | ||
782 | /* set bits for operations that won't block */ | 787 | /* set bits for operations that won't block */ |
783 | if(n_hdlc->rx_buf_list.head) | 788 | if (n_hdlc->rx_buf_list.head) |
784 | mask |= POLLIN | POLLRDNORM; /* readable */ | 789 | mask |= POLLIN | POLLRDNORM; /* readable */ |
785 | if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) | 790 | if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) |
786 | mask |= POLLHUP; | 791 | mask |= POLLHUP; |
787 | if(tty_hung_up_p(filp)) | 792 | if (tty_hung_up_p(filp)) |
788 | mask |= POLLHUP; | 793 | mask |= POLLHUP; |
789 | if(n_hdlc->tx_free_buf_list.head) | 794 | if (!tty_is_writelocked(tty) && |
795 | n_hdlc->tx_free_buf_list.head) | ||
790 | mask |= POLLOUT | POLLWRNORM; /* writable */ | 796 | mask |= POLLOUT | POLLWRNORM; /* writable */ |
791 | } | 797 | } |
792 | return mask; | 798 | return mask; |
@@ -861,7 +867,7 @@ static void n_hdlc_buf_put(struct n_hdlc_buf_list *list, | |||
861 | spin_lock_irqsave(&list->spinlock,flags); | 867 | spin_lock_irqsave(&list->spinlock,flags); |
862 | 868 | ||
863 | buf->link=NULL; | 869 | buf->link=NULL; |
864 | if(list->tail) | 870 | if (list->tail) |
865 | list->tail->link = buf; | 871 | list->tail->link = buf; |
866 | else | 872 | else |
867 | list->head = buf; | 873 | list->head = buf; |
diff --git a/drivers/char/n_r3964.c b/drivers/char/n_r3964.c index 14557a4822c0..6b918b80f73e 100644 --- a/drivers/char/n_r3964.c +++ b/drivers/char/n_r3964.c | |||
@@ -1071,8 +1071,6 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file, | |||
1071 | struct r3964_client_info *pClient; | 1071 | struct r3964_client_info *pClient; |
1072 | struct r3964_message *pMsg; | 1072 | struct r3964_message *pMsg; |
1073 | struct r3964_client_message theMsg; | 1073 | struct r3964_client_message theMsg; |
1074 | DECLARE_WAITQUEUE(wait, current); | ||
1075 | |||
1076 | int count; | 1074 | int count; |
1077 | 1075 | ||
1078 | TRACE_L("read()"); | 1076 | TRACE_L("read()"); |
@@ -1086,16 +1084,8 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file, | |||
1086 | return -EAGAIN; | 1084 | return -EAGAIN; |
1087 | } | 1085 | } |
1088 | /* block until there is a message: */ | 1086 | /* block until there is a message: */ |
1089 | add_wait_queue(&pInfo->read_wait, &wait); | 1087 | wait_event_interruptible(pInfo->read_wait, |
1090 | repeat: | 1088 | (pMsg = remove_msg(pInfo, pClient))); |
1091 | __set_current_state(TASK_INTERRUPTIBLE); | ||
1092 | pMsg = remove_msg(pInfo, pClient); | ||
1093 | if (!pMsg && !signal_pending(current)) { | ||
1094 | schedule(); | ||
1095 | goto repeat; | ||
1096 | } | ||
1097 | __set_current_state(TASK_RUNNING); | ||
1098 | remove_wait_queue(&pInfo->read_wait, &wait); | ||
1099 | } | 1089 | } |
1100 | 1090 | ||
1101 | /* If we still haven't got a message, we must have been signalled */ | 1091 | /* If we still haven't got a message, we must have been signalled */ |
diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c index 154f42203b05..038056911934 100644 --- a/drivers/char/n_tty.c +++ b/drivers/char/n_tty.c | |||
@@ -45,6 +45,8 @@ | |||
45 | #include <linux/slab.h> | 45 | #include <linux/slab.h> |
46 | #include <linux/poll.h> | 46 | #include <linux/poll.h> |
47 | #include <linux/bitops.h> | 47 | #include <linux/bitops.h> |
48 | #include <linux/audit.h> | ||
49 | #include <linux/file.h> | ||
48 | 50 | ||
49 | #include <asm/uaccess.h> | 51 | #include <asm/uaccess.h> |
50 | #include <asm/system.h> | 52 | #include <asm/system.h> |
@@ -78,6 +80,13 @@ static inline void free_buf(unsigned char *buf) | |||
78 | free_page((unsigned long) buf); | 80 | free_page((unsigned long) buf); |
79 | } | 81 | } |
80 | 82 | ||
83 | static inline int tty_put_user(struct tty_struct *tty, unsigned char x, | ||
84 | unsigned char __user *ptr) | ||
85 | { | ||
86 | tty_audit_add_data(tty, &x, 1); | ||
87 | return put_user(x, ptr); | ||
88 | } | ||
89 | |||
81 | /** | 90 | /** |
82 | * n_tty_set__room - receive space | 91 | * n_tty_set__room - receive space |
83 | * @tty: terminal | 92 | * @tty: terminal |
@@ -1153,6 +1162,7 @@ static int copy_from_read_buf(struct tty_struct *tty, | |||
1153 | if (n) { | 1162 | if (n) { |
1154 | retval = copy_to_user(*b, &tty->read_buf[tty->read_tail], n); | 1163 | retval = copy_to_user(*b, &tty->read_buf[tty->read_tail], n); |
1155 | n -= retval; | 1164 | n -= retval; |
1165 | tty_audit_add_data(tty, &tty->read_buf[tty->read_tail], n); | ||
1156 | spin_lock_irqsave(&tty->read_lock, flags); | 1166 | spin_lock_irqsave(&tty->read_lock, flags); |
1157 | tty->read_tail = (tty->read_tail + n) & (N_TTY_BUF_SIZE-1); | 1167 | tty->read_tail = (tty->read_tail + n) & (N_TTY_BUF_SIZE-1); |
1158 | tty->read_cnt -= n; | 1168 | tty->read_cnt -= n; |
@@ -1279,7 +1289,7 @@ do_it_again: | |||
1279 | break; | 1289 | break; |
1280 | cs = tty->link->ctrl_status; | 1290 | cs = tty->link->ctrl_status; |
1281 | tty->link->ctrl_status = 0; | 1291 | tty->link->ctrl_status = 0; |
1282 | if (put_user(cs, b++)) { | 1292 | if (tty_put_user(tty, cs, b++)) { |
1283 | retval = -EFAULT; | 1293 | retval = -EFAULT; |
1284 | b--; | 1294 | b--; |
1285 | break; | 1295 | break; |
@@ -1321,7 +1331,7 @@ do_it_again: | |||
1321 | 1331 | ||
1322 | /* Deal with packet mode. */ | 1332 | /* Deal with packet mode. */ |
1323 | if (tty->packet && b == buf) { | 1333 | if (tty->packet && b == buf) { |
1324 | if (put_user(TIOCPKT_DATA, b++)) { | 1334 | if (tty_put_user(tty, TIOCPKT_DATA, b++)) { |
1325 | retval = -EFAULT; | 1335 | retval = -EFAULT; |
1326 | b--; | 1336 | b--; |
1327 | break; | 1337 | break; |
@@ -1352,15 +1362,17 @@ do_it_again: | |||
1352 | spin_unlock_irqrestore(&tty->read_lock, flags); | 1362 | spin_unlock_irqrestore(&tty->read_lock, flags); |
1353 | 1363 | ||
1354 | if (!eol || (c != __DISABLED_CHAR)) { | 1364 | if (!eol || (c != __DISABLED_CHAR)) { |
1355 | if (put_user(c, b++)) { | 1365 | if (tty_put_user(tty, c, b++)) { |
1356 | retval = -EFAULT; | 1366 | retval = -EFAULT; |
1357 | b--; | 1367 | b--; |
1358 | break; | 1368 | break; |
1359 | } | 1369 | } |
1360 | nr--; | 1370 | nr--; |
1361 | } | 1371 | } |
1362 | if (eol) | 1372 | if (eol) { |
1373 | tty_audit_push(tty); | ||
1363 | break; | 1374 | break; |
1375 | } | ||
1364 | } | 1376 | } |
1365 | if (retval) | 1377 | if (retval) |
1366 | break; | 1378 | break; |
@@ -1538,7 +1550,8 @@ static unsigned int normal_poll(struct tty_struct * tty, struct file * file, pol | |||
1538 | else | 1550 | else |
1539 | tty->minimum_to_wake = 1; | 1551 | tty->minimum_to_wake = 1; |
1540 | } | 1552 | } |
1541 | if (tty->driver->chars_in_buffer(tty) < WAKEUP_CHARS && | 1553 | if (!tty_is_writelocked(tty) && |
1554 | tty->driver->chars_in_buffer(tty) < WAKEUP_CHARS && | ||
1542 | tty->driver->write_room(tty) > 0) | 1555 | tty->driver->write_room(tty) > 0) |
1543 | mask |= POLLOUT | POLLWRNORM; | 1556 | mask |= POLLOUT | POLLWRNORM; |
1544 | return mask; | 1557 | return mask; |
diff --git a/drivers/char/nvram.c b/drivers/char/nvram.c index 204deaa0de80..98dec380af49 100644 --- a/drivers/char/nvram.c +++ b/drivers/char/nvram.c | |||
@@ -42,19 +42,12 @@ | |||
42 | 42 | ||
43 | #define PC 1 | 43 | #define PC 1 |
44 | #define ATARI 2 | 44 | #define ATARI 2 |
45 | #define COBALT 3 | ||
46 | 45 | ||
47 | /* select machine configuration */ | 46 | /* select machine configuration */ |
48 | #if defined(CONFIG_ATARI) | 47 | #if defined(CONFIG_ATARI) |
49 | # define MACH ATARI | 48 | # define MACH ATARI |
50 | #elif defined(__i386__) || defined(__x86_64__) || defined(__arm__) /* and others?? */ | 49 | #elif defined(__i386__) || defined(__x86_64__) || defined(__arm__) /* and others?? */ |
51 | #define MACH PC | 50 | # define MACH PC |
52 | # if defined(CONFIG_COBALT) | ||
53 | # include <linux/cobalt-nvram.h> | ||
54 | # define MACH COBALT | ||
55 | # else | ||
56 | # define MACH PC | ||
57 | # endif | ||
58 | #else | 51 | #else |
59 | # error Cannot build nvram driver for this machine configuration. | 52 | # error Cannot build nvram driver for this machine configuration. |
60 | #endif | 53 | #endif |
@@ -76,18 +69,6 @@ | |||
76 | 69 | ||
77 | #endif | 70 | #endif |
78 | 71 | ||
79 | #if MACH == COBALT | ||
80 | |||
81 | #define CHECK_DRIVER_INIT() 1 | ||
82 | |||
83 | #define NVRAM_BYTES (128-NVRAM_FIRST_BYTE) | ||
84 | |||
85 | #define mach_check_checksum cobalt_check_checksum | ||
86 | #define mach_set_checksum cobalt_set_checksum | ||
87 | #define mach_proc_infos cobalt_proc_infos | ||
88 | |||
89 | #endif | ||
90 | |||
91 | #if MACH == ATARI | 72 | #if MACH == ATARI |
92 | 73 | ||
93 | /* Special parameters for RTC in Atari machines */ | 74 | /* Special parameters for RTC in Atari machines */ |
@@ -604,177 +585,6 @@ pc_proc_infos(unsigned char *nvram, char *buffer, int *len, | |||
604 | 585 | ||
605 | #endif /* MACH == PC */ | 586 | #endif /* MACH == PC */ |
606 | 587 | ||
607 | #if MACH == COBALT | ||
608 | |||
609 | /* the cobalt CMOS has a wider range of its checksum */ | ||
610 | static int cobalt_check_checksum(void) | ||
611 | { | ||
612 | int i; | ||
613 | unsigned short sum = 0; | ||
614 | unsigned short expect; | ||
615 | |||
616 | for (i = COBT_CMOS_CKS_START; i <= COBT_CMOS_CKS_END; ++i) { | ||
617 | if ((i == COBT_CMOS_CHECKSUM) || (i == (COBT_CMOS_CHECKSUM+1))) | ||
618 | continue; | ||
619 | |||
620 | sum += __nvram_read_byte(i); | ||
621 | } | ||
622 | expect = __nvram_read_byte(COBT_CMOS_CHECKSUM) << 8 | | ||
623 | __nvram_read_byte(COBT_CMOS_CHECKSUM+1); | ||
624 | return ((sum & 0xffff) == expect); | ||
625 | } | ||
626 | |||
627 | static void cobalt_set_checksum(void) | ||
628 | { | ||
629 | int i; | ||
630 | unsigned short sum = 0; | ||
631 | |||
632 | for (i = COBT_CMOS_CKS_START; i <= COBT_CMOS_CKS_END; ++i) { | ||
633 | if ((i == COBT_CMOS_CHECKSUM) || (i == (COBT_CMOS_CHECKSUM+1))) | ||
634 | continue; | ||
635 | |||
636 | sum += __nvram_read_byte(i); | ||
637 | } | ||
638 | |||
639 | __nvram_write_byte(sum >> 8, COBT_CMOS_CHECKSUM); | ||
640 | __nvram_write_byte(sum & 0xff, COBT_CMOS_CHECKSUM+1); | ||
641 | } | ||
642 | |||
643 | #ifdef CONFIG_PROC_FS | ||
644 | |||
645 | static int cobalt_proc_infos(unsigned char *nvram, char *buffer, int *len, | ||
646 | off_t *begin, off_t offset, int size) | ||
647 | { | ||
648 | int i; | ||
649 | unsigned int checksum; | ||
650 | unsigned int flags; | ||
651 | char sernum[14]; | ||
652 | char *key = "cNoEbTaWlOtR!"; | ||
653 | unsigned char bto_csum; | ||
654 | |||
655 | spin_lock_irq(&rtc_lock); | ||
656 | checksum = __nvram_check_checksum(); | ||
657 | spin_unlock_irq(&rtc_lock); | ||
658 | |||
659 | PRINT_PROC("Checksum status: %svalid\n", checksum ? "" : "not "); | ||
660 | |||
661 | flags = nvram[COBT_CMOS_FLAG_BYTE_0] << 8 | ||
662 | | nvram[COBT_CMOS_FLAG_BYTE_1]; | ||
663 | |||
664 | PRINT_PROC("Console: %s\n", | ||
665 | flags & COBT_CMOS_CONSOLE_FLAG ? "on": "off"); | ||
666 | |||
667 | PRINT_PROC("Firmware Debug Messages: %s\n", | ||
668 | flags & COBT_CMOS_DEBUG_FLAG ? "on": "off"); | ||
669 | |||
670 | PRINT_PROC("Auto Prompt: %s\n", | ||
671 | flags & COBT_CMOS_AUTO_PROMPT_FLAG ? "on": "off"); | ||
672 | |||
673 | PRINT_PROC("Shutdown Status: %s\n", | ||
674 | flags & COBT_CMOS_CLEAN_BOOT_FLAG ? "clean": "dirty"); | ||
675 | |||
676 | PRINT_PROC("Hardware Probe: %s\n", | ||
677 | flags & COBT_CMOS_HW_NOPROBE_FLAG ? "partial": "full"); | ||
678 | |||
679 | PRINT_PROC("System Fault: %sdetected\n", | ||
680 | flags & COBT_CMOS_SYSFAULT_FLAG ? "": "not "); | ||
681 | |||
682 | PRINT_PROC("Panic on OOPS: %s\n", | ||
683 | flags & COBT_CMOS_OOPSPANIC_FLAG ? "yes": "no"); | ||
684 | |||
685 | PRINT_PROC("Delayed Cache Initialization: %s\n", | ||
686 | flags & COBT_CMOS_DELAY_CACHE_FLAG ? "yes": "no"); | ||
687 | |||
688 | PRINT_PROC("Show Logo at Boot: %s\n", | ||
689 | flags & COBT_CMOS_NOLOGO_FLAG ? "no": "yes"); | ||
690 | |||
691 | PRINT_PROC("Boot Method: "); | ||
692 | switch (nvram[COBT_CMOS_BOOT_METHOD]) { | ||
693 | case COBT_CMOS_BOOT_METHOD_DISK: | ||
694 | PRINT_PROC("disk\n"); | ||
695 | break; | ||
696 | |||
697 | case COBT_CMOS_BOOT_METHOD_ROM: | ||
698 | PRINT_PROC("rom\n"); | ||
699 | break; | ||
700 | |||
701 | case COBT_CMOS_BOOT_METHOD_NET: | ||
702 | PRINT_PROC("net\n"); | ||
703 | break; | ||
704 | |||
705 | default: | ||
706 | PRINT_PROC("unknown\n"); | ||
707 | break; | ||
708 | } | ||
709 | |||
710 | PRINT_PROC("Primary Boot Device: %d:%d\n", | ||
711 | nvram[COBT_CMOS_BOOT_DEV0_MAJ], | ||
712 | nvram[COBT_CMOS_BOOT_DEV0_MIN] ); | ||
713 | PRINT_PROC("Secondary Boot Device: %d:%d\n", | ||
714 | nvram[COBT_CMOS_BOOT_DEV1_MAJ], | ||
715 | nvram[COBT_CMOS_BOOT_DEV1_MIN] ); | ||
716 | PRINT_PROC("Tertiary Boot Device: %d:%d\n", | ||
717 | nvram[COBT_CMOS_BOOT_DEV2_MAJ], | ||
718 | nvram[COBT_CMOS_BOOT_DEV2_MIN] ); | ||
719 | |||
720 | PRINT_PROC("Uptime: %d\n", | ||
721 | nvram[COBT_CMOS_UPTIME_0] << 24 | | ||
722 | nvram[COBT_CMOS_UPTIME_1] << 16 | | ||
723 | nvram[COBT_CMOS_UPTIME_2] << 8 | | ||
724 | nvram[COBT_CMOS_UPTIME_3]); | ||
725 | |||
726 | PRINT_PROC("Boot Count: %d\n", | ||
727 | nvram[COBT_CMOS_BOOTCOUNT_0] << 24 | | ||
728 | nvram[COBT_CMOS_BOOTCOUNT_1] << 16 | | ||
729 | nvram[COBT_CMOS_BOOTCOUNT_2] << 8 | | ||
730 | nvram[COBT_CMOS_BOOTCOUNT_3]); | ||
731 | |||
732 | /* 13 bytes of serial num */ | ||
733 | for (i=0 ; i<13 ; i++) { | ||
734 | sernum[i] = nvram[COBT_CMOS_SYS_SERNUM_0 + i]; | ||
735 | } | ||
736 | sernum[13] = '\0'; | ||
737 | |||
738 | checksum = 0; | ||
739 | for (i=0 ; i<13 ; i++) { | ||
740 | checksum += sernum[i] ^ key[i]; | ||
741 | } | ||
742 | checksum = ((checksum & 0x7f) ^ (0xd6)) & 0xff; | ||
743 | |||
744 | PRINT_PROC("Serial Number: %s", sernum); | ||
745 | if (checksum != nvram[COBT_CMOS_SYS_SERNUM_CSUM]) { | ||
746 | PRINT_PROC(" (invalid checksum)"); | ||
747 | } | ||
748 | PRINT_PROC("\n"); | ||
749 | |||
750 | PRINT_PROC("Rom Revison: %d.%d.%d\n", nvram[COBT_CMOS_ROM_REV_MAJ], | ||
751 | nvram[COBT_CMOS_ROM_REV_MIN], nvram[COBT_CMOS_ROM_REV_REV]); | ||
752 | |||
753 | PRINT_PROC("BTO Server: %d.%d.%d.%d", nvram[COBT_CMOS_BTO_IP_0], | ||
754 | nvram[COBT_CMOS_BTO_IP_1], nvram[COBT_CMOS_BTO_IP_2], | ||
755 | nvram[COBT_CMOS_BTO_IP_3]); | ||
756 | bto_csum = nvram[COBT_CMOS_BTO_IP_0] + nvram[COBT_CMOS_BTO_IP_1] | ||
757 | + nvram[COBT_CMOS_BTO_IP_2] + nvram[COBT_CMOS_BTO_IP_3]; | ||
758 | if (bto_csum != nvram[COBT_CMOS_BTO_IP_CSUM]) { | ||
759 | PRINT_PROC(" (invalid checksum)"); | ||
760 | } | ||
761 | PRINT_PROC("\n"); | ||
762 | |||
763 | if (flags & COBT_CMOS_VERSION_FLAG | ||
764 | && nvram[COBT_CMOS_VERSION] >= COBT_CMOS_VER_BTOCODE) { | ||
765 | PRINT_PROC("BTO Code: 0x%x\n", | ||
766 | nvram[COBT_CMOS_BTO_CODE_0] << 24 | | ||
767 | nvram[COBT_CMOS_BTO_CODE_1] << 16 | | ||
768 | nvram[COBT_CMOS_BTO_CODE_2] << 8 | | ||
769 | nvram[COBT_CMOS_BTO_CODE_3]); | ||
770 | } | ||
771 | |||
772 | return 1; | ||
773 | } | ||
774 | #endif /* CONFIG_PROC_FS */ | ||
775 | |||
776 | #endif /* MACH == COBALT */ | ||
777 | |||
778 | #if MACH == ATARI | 588 | #if MACH == ATARI |
779 | 589 | ||
780 | static int | 590 | static int |
diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c index a3fd7e7ba5a9..0270080ff0c0 100644 --- a/drivers/char/rocket.c +++ b/drivers/char/rocket.c | |||
@@ -1702,7 +1702,8 @@ static int rp_write(struct tty_struct *tty, | |||
1702 | if (count <= 0 || rocket_paranoia_check(info, "rp_write")) | 1702 | if (count <= 0 || rocket_paranoia_check(info, "rp_write")) |
1703 | return 0; | 1703 | return 0; |
1704 | 1704 | ||
1705 | mutex_lock_interruptible(&info->write_mtx); | 1705 | if (mutex_lock_interruptible(&info->write_mtx)) |
1706 | return -ERESTARTSYS; | ||
1706 | 1707 | ||
1707 | #ifdef ROCKET_DEBUG_WRITE | 1708 | #ifdef ROCKET_DEBUG_WRITE |
1708 | printk(KERN_INFO "rp_write %d chars...", count); | 1709 | printk(KERN_INFO "rp_write %d chars...", count); |
diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c index 20380a2c4dee..22cf7aa56cc4 100644 --- a/drivers/char/rtc.c +++ b/drivers/char/rtc.c | |||
@@ -1159,7 +1159,8 @@ static void rtc_dropped_irq(unsigned long data) | |||
1159 | 1159 | ||
1160 | spin_unlock_irq(&rtc_lock); | 1160 | spin_unlock_irq(&rtc_lock); |
1161 | 1161 | ||
1162 | printk(KERN_WARNING "rtc: lost some interrupts at %ldHz.\n", freq); | 1162 | if (printk_ratelimit()) |
1163 | printk(KERN_WARNING "rtc: lost some interrupts at %ldHz.\n", freq); | ||
1163 | 1164 | ||
1164 | /* Now we have new data */ | 1165 | /* Now we have new data */ |
1165 | wake_up_interruptible(&rtc_wait); | 1166 | wake_up_interruptible(&rtc_wait); |
diff --git a/drivers/char/selection.c b/drivers/char/selection.c index a69f094d1ed3..d63f5ccc29e6 100644 --- a/drivers/char/selection.c +++ b/drivers/char/selection.c | |||
@@ -20,6 +20,7 @@ | |||
20 | 20 | ||
21 | #include <asm/uaccess.h> | 21 | #include <asm/uaccess.h> |
22 | 22 | ||
23 | #include <linux/kbd_kern.h> | ||
23 | #include <linux/vt_kern.h> | 24 | #include <linux/vt_kern.h> |
24 | #include <linux/consolemap.h> | 25 | #include <linux/consolemap.h> |
25 | #include <linux/selection.h> | 26 | #include <linux/selection.h> |
@@ -34,6 +35,7 @@ extern void poke_blanked_console(void); | |||
34 | /* Variables for selection control. */ | 35 | /* Variables for selection control. */ |
35 | /* Use a dynamic buffer, instead of static (Dec 1994) */ | 36 | /* Use a dynamic buffer, instead of static (Dec 1994) */ |
36 | struct vc_data *sel_cons; /* must not be deallocated */ | 37 | struct vc_data *sel_cons; /* must not be deallocated */ |
38 | static int use_unicode; | ||
37 | static volatile int sel_start = -1; /* cleared by clear_selection */ | 39 | static volatile int sel_start = -1; /* cleared by clear_selection */ |
38 | static int sel_end; | 40 | static int sel_end; |
39 | static int sel_buffer_lth; | 41 | static int sel_buffer_lth; |
@@ -54,10 +56,11 @@ static inline void highlight_pointer(const int where) | |||
54 | complement_pos(sel_cons, where); | 56 | complement_pos(sel_cons, where); |
55 | } | 57 | } |
56 | 58 | ||
57 | static unsigned char | 59 | static u16 |
58 | sel_pos(int n) | 60 | sel_pos(int n) |
59 | { | 61 | { |
60 | return inverse_translate(sel_cons, screen_glyph(sel_cons, n)); | 62 | return inverse_translate(sel_cons, screen_glyph(sel_cons, n), |
63 | use_unicode); | ||
61 | } | 64 | } |
62 | 65 | ||
63 | /* remove the current selection highlight, if any, | 66 | /* remove the current selection highlight, if any, |
@@ -86,8 +89,8 @@ static u32 inwordLut[8]={ | |||
86 | 0xFF7FFFFF /* latin-1 accented letters, not division sign */ | 89 | 0xFF7FFFFF /* latin-1 accented letters, not division sign */ |
87 | }; | 90 | }; |
88 | 91 | ||
89 | static inline int inword(const unsigned char c) { | 92 | static inline int inword(const u16 c) { |
90 | return ( inwordLut[c>>5] >> (c & 0x1F) ) & 1; | 93 | return c > 0xff || (( inwordLut[c>>5] >> (c & 0x1F) ) & 1); |
91 | } | 94 | } |
92 | 95 | ||
93 | /* set inwordLut contents. Invoked by ioctl(). */ | 96 | /* set inwordLut contents. Invoked by ioctl(). */ |
@@ -108,13 +111,36 @@ static inline unsigned short limit(const unsigned short v, const unsigned short | |||
108 | return (v > u) ? u : v; | 111 | return (v > u) ? u : v; |
109 | } | 112 | } |
110 | 113 | ||
114 | /* stores the char in UTF8 and returns the number of bytes used (1-3) */ | ||
115 | static int store_utf8(u16 c, char *p) | ||
116 | { | ||
117 | if (c < 0x80) { | ||
118 | /* 0******* */ | ||
119 | p[0] = c; | ||
120 | return 1; | ||
121 | } else if (c < 0x800) { | ||
122 | /* 110***** 10****** */ | ||
123 | p[0] = 0xc0 | (c >> 6); | ||
124 | p[1] = 0x80 | (c & 0x3f); | ||
125 | return 2; | ||
126 | } else { | ||
127 | /* 1110**** 10****** 10****** */ | ||
128 | p[0] = 0xe0 | (c >> 12); | ||
129 | p[1] = 0x80 | ((c >> 6) & 0x3f); | ||
130 | p[2] = 0x80 | (c & 0x3f); | ||
131 | return 3; | ||
132 | } | ||
133 | } | ||
134 | |||
111 | /* set the current selection. Invoked by ioctl() or by kernel code. */ | 135 | /* set the current selection. Invoked by ioctl() or by kernel code. */ |
112 | int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *tty) | 136 | int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *tty) |
113 | { | 137 | { |
114 | struct vc_data *vc = vc_cons[fg_console].d; | 138 | struct vc_data *vc = vc_cons[fg_console].d; |
115 | int sel_mode, new_sel_start, new_sel_end, spc; | 139 | int sel_mode, new_sel_start, new_sel_end, spc; |
116 | char *bp, *obp; | 140 | char *bp, *obp; |
117 | int i, ps, pe; | 141 | int i, ps, pe, multiplier; |
142 | u16 c; | ||
143 | struct kbd_struct *kbd = kbd_table + fg_console; | ||
118 | 144 | ||
119 | poke_blanked_console(); | 145 | poke_blanked_console(); |
120 | 146 | ||
@@ -158,6 +184,7 @@ int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *t | |||
158 | clear_selection(); | 184 | clear_selection(); |
159 | sel_cons = vc_cons[fg_console].d; | 185 | sel_cons = vc_cons[fg_console].d; |
160 | } | 186 | } |
187 | use_unicode = kbd && kbd->kbdmode == VC_UNICODE; | ||
161 | 188 | ||
162 | switch (sel_mode) | 189 | switch (sel_mode) |
163 | { | 190 | { |
@@ -240,7 +267,8 @@ int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *t | |||
240 | sel_end = new_sel_end; | 267 | sel_end = new_sel_end; |
241 | 268 | ||
242 | /* Allocate a new buffer before freeing the old one ... */ | 269 | /* Allocate a new buffer before freeing the old one ... */ |
243 | bp = kmalloc((sel_end-sel_start)/2+1, GFP_KERNEL); | 270 | multiplier = use_unicode ? 3 : 1; /* chars can take up to 3 bytes */ |
271 | bp = kmalloc((sel_end-sel_start)/2*multiplier+1, GFP_KERNEL); | ||
244 | if (!bp) { | 272 | if (!bp) { |
245 | printk(KERN_WARNING "selection: kmalloc() failed\n"); | 273 | printk(KERN_WARNING "selection: kmalloc() failed\n"); |
246 | clear_selection(); | 274 | clear_selection(); |
@@ -251,8 +279,12 @@ int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *t | |||
251 | 279 | ||
252 | obp = bp; | 280 | obp = bp; |
253 | for (i = sel_start; i <= sel_end; i += 2) { | 281 | for (i = sel_start; i <= sel_end; i += 2) { |
254 | *bp = sel_pos(i); | 282 | c = sel_pos(i); |
255 | if (!isspace(*bp++)) | 283 | if (use_unicode) |
284 | bp += store_utf8(c, bp); | ||
285 | else | ||
286 | *bp++ = c; | ||
287 | if (!isspace(c)) | ||
256 | obp = bp; | 288 | obp = bp; |
257 | if (! ((i + 2) % vc->vc_size_row)) { | 289 | if (! ((i + 2) % vc->vc_size_row)) { |
258 | /* strip trailing blanks from line and add newline, | 290 | /* strip trailing blanks from line and add newline, |
diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c index 3ef593a9015f..73037a4d3c50 100644 --- a/drivers/char/sonypi.c +++ b/drivers/char/sonypi.c | |||
@@ -885,53 +885,6 @@ found: | |||
885 | return IRQ_HANDLED; | 885 | return IRQ_HANDLED; |
886 | } | 886 | } |
887 | 887 | ||
888 | /* External camera command (exported to the motion eye v4l driver) */ | ||
889 | int sonypi_camera_command(int command, u8 value) | ||
890 | { | ||
891 | if (!camera) | ||
892 | return -EIO; | ||
893 | |||
894 | mutex_lock(&sonypi_device.lock); | ||
895 | |||
896 | switch (command) { | ||
897 | case SONYPI_COMMAND_SETCAMERA: | ||
898 | if (value) | ||
899 | sonypi_camera_on(); | ||
900 | else | ||
901 | sonypi_camera_off(); | ||
902 | break; | ||
903 | case SONYPI_COMMAND_SETCAMERABRIGHTNESS: | ||
904 | sonypi_set(SONYPI_CAMERA_BRIGHTNESS, value); | ||
905 | break; | ||
906 | case SONYPI_COMMAND_SETCAMERACONTRAST: | ||
907 | sonypi_set(SONYPI_CAMERA_CONTRAST, value); | ||
908 | break; | ||
909 | case SONYPI_COMMAND_SETCAMERAHUE: | ||
910 | sonypi_set(SONYPI_CAMERA_HUE, value); | ||
911 | break; | ||
912 | case SONYPI_COMMAND_SETCAMERACOLOR: | ||
913 | sonypi_set(SONYPI_CAMERA_COLOR, value); | ||
914 | break; | ||
915 | case SONYPI_COMMAND_SETCAMERASHARPNESS: | ||
916 | sonypi_set(SONYPI_CAMERA_SHARPNESS, value); | ||
917 | break; | ||
918 | case SONYPI_COMMAND_SETCAMERAPICTURE: | ||
919 | sonypi_set(SONYPI_CAMERA_PICTURE, value); | ||
920 | break; | ||
921 | case SONYPI_COMMAND_SETCAMERAAGC: | ||
922 | sonypi_set(SONYPI_CAMERA_AGC, value); | ||
923 | break; | ||
924 | default: | ||
925 | printk(KERN_ERR "sonypi: sonypi_camera_command invalid: %d\n", | ||
926 | command); | ||
927 | break; | ||
928 | } | ||
929 | mutex_unlock(&sonypi_device.lock); | ||
930 | return 0; | ||
931 | } | ||
932 | |||
933 | EXPORT_SYMBOL(sonypi_camera_command); | ||
934 | |||
935 | static int sonypi_misc_fasync(int fd, struct file *filp, int on) | 888 | static int sonypi_misc_fasync(int fd, struct file *filp, int on) |
936 | { | 889 | { |
937 | int retval; | 890 | int retval; |
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c index f02a0795983f..f53e51ddb9d7 100644 --- a/drivers/char/synclink.c +++ b/drivers/char/synclink.c | |||
@@ -160,8 +160,6 @@ typedef struct _DMABUFFERENTRY | |||
160 | 160 | ||
161 | #define IO_PIN_SHUTDOWN_LIMIT 100 | 161 | #define IO_PIN_SHUTDOWN_LIMIT 100 |
162 | 162 | ||
163 | #define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK)) | ||
164 | |||
165 | struct _input_signal_events { | 163 | struct _input_signal_events { |
166 | int ri_up; | 164 | int ri_up; |
167 | int ri_down; | 165 | int ri_down; |
@@ -3064,12 +3062,6 @@ static void mgsl_set_termios(struct tty_struct *tty, struct ktermios *old_termio | |||
3064 | printk("%s(%d):mgsl_set_termios %s\n", __FILE__,__LINE__, | 3062 | printk("%s(%d):mgsl_set_termios %s\n", __FILE__,__LINE__, |
3065 | tty->driver->name ); | 3063 | tty->driver->name ); |
3066 | 3064 | ||
3067 | /* just return if nothing has changed */ | ||
3068 | if ((tty->termios->c_cflag == old_termios->c_cflag) | ||
3069 | && (RELEVANT_IFLAG(tty->termios->c_iflag) | ||
3070 | == RELEVANT_IFLAG(old_termios->c_iflag))) | ||
3071 | return; | ||
3072 | |||
3073 | mgsl_change_params(info); | 3065 | mgsl_change_params(info); |
3074 | 3066 | ||
3075 | /* Handle transition to B0 status */ | 3067 | /* Handle transition to B0 status */ |
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c index 02b49bc00028..428b514201f4 100644 --- a/drivers/char/synclink_gt.c +++ b/drivers/char/synclink_gt.c | |||
@@ -144,8 +144,6 @@ MODULE_PARM_DESC(dosyncppp, "Enable synchronous net device, 0=disable 1=enable") | |||
144 | /* | 144 | /* |
145 | * tty support and callbacks | 145 | * tty support and callbacks |
146 | */ | 146 | */ |
147 | #define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK)) | ||
148 | |||
149 | static struct tty_driver *serial_driver; | 147 | static struct tty_driver *serial_driver; |
150 | 148 | ||
151 | static int open(struct tty_struct *tty, struct file * filp); | 149 | static int open(struct tty_struct *tty, struct file * filp); |
@@ -823,12 +821,6 @@ static void set_termios(struct tty_struct *tty, struct ktermios *old_termios) | |||
823 | 821 | ||
824 | DBGINFO(("%s set_termios\n", tty->driver->name)); | 822 | DBGINFO(("%s set_termios\n", tty->driver->name)); |
825 | 823 | ||
826 | /* just return if nothing has changed */ | ||
827 | if ((tty->termios->c_cflag == old_termios->c_cflag) | ||
828 | && (RELEVANT_IFLAG(tty->termios->c_iflag) | ||
829 | == RELEVANT_IFLAG(old_termios->c_iflag))) | ||
830 | return; | ||
831 | |||
832 | change_params(info); | 824 | change_params(info); |
833 | 825 | ||
834 | /* Handle transition to B0 status */ | 826 | /* Handle transition to B0 status */ |
diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c index ef93d055bdd7..a65407b32079 100644 --- a/drivers/char/synclinkmp.c +++ b/drivers/char/synclinkmp.c | |||
@@ -135,8 +135,6 @@ typedef struct _SCADESC_EX | |||
135 | 135 | ||
136 | #define IO_PIN_SHUTDOWN_LIMIT 100 | 136 | #define IO_PIN_SHUTDOWN_LIMIT 100 |
137 | 137 | ||
138 | #define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK)) | ||
139 | |||
140 | struct _input_signal_events { | 138 | struct _input_signal_events { |
141 | int ri_up; | 139 | int ri_up; |
142 | int ri_down; | 140 | int ri_down; |
@@ -927,12 +925,6 @@ static void set_termios(struct tty_struct *tty, struct ktermios *old_termios) | |||
927 | printk("%s(%d):%s set_termios()\n", __FILE__,__LINE__, | 925 | printk("%s(%d):%s set_termios()\n", __FILE__,__LINE__, |
928 | tty->driver->name ); | 926 | tty->driver->name ); |
929 | 927 | ||
930 | /* just return if nothing has changed */ | ||
931 | if ((tty->termios->c_cflag == old_termios->c_cflag) | ||
932 | && (RELEVANT_IFLAG(tty->termios->c_iflag) | ||
933 | == RELEVANT_IFLAG(old_termios->c_iflag))) | ||
934 | return; | ||
935 | |||
936 | change_params(info); | 928 | change_params(info); |
937 | 929 | ||
938 | /* Handle transition to B0 status */ | 930 | /* Handle transition to B0 status */ |
diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig index dc4e1ff7f56f..8f3f7620f95a 100644 --- a/drivers/char/tpm/Kconfig +++ b/drivers/char/tpm/Kconfig | |||
@@ -2,11 +2,9 @@ | |||
2 | # TPM device configuration | 2 | # TPM device configuration |
3 | # | 3 | # |
4 | 4 | ||
5 | menu "TPM devices" | 5 | menuconfig TCG_TPM |
6 | depends on HAS_IOMEM | ||
7 | |||
8 | config TCG_TPM | ||
9 | tristate "TPM Hardware Support" | 6 | tristate "TPM Hardware Support" |
7 | depends on HAS_IOMEM | ||
10 | depends on EXPERIMENTAL | 8 | depends on EXPERIMENTAL |
11 | ---help--- | 9 | ---help--- |
12 | If you have a TPM security chip in your system, which | 10 | If you have a TPM security chip in your system, which |
@@ -21,9 +19,11 @@ config TCG_TPM | |||
21 | Note: For more TPM drivers enable CONFIG_PNP, CONFIG_ACPI | 19 | Note: For more TPM drivers enable CONFIG_PNP, CONFIG_ACPI |
22 | and CONFIG_PNPACPI. | 20 | and CONFIG_PNPACPI. |
23 | 21 | ||
22 | if TCG_TPM | ||
23 | |||
24 | config TCG_TIS | 24 | config TCG_TIS |
25 | tristate "TPM Interface Specification 1.2 Interface" | 25 | tristate "TPM Interface Specification 1.2 Interface" |
26 | depends on TCG_TPM && PNPACPI | 26 | depends on PNPACPI |
27 | ---help--- | 27 | ---help--- |
28 | If you have a TPM security chip that is compliant with the | 28 | If you have a TPM security chip that is compliant with the |
29 | TCG TIS 1.2 TPM specification say Yes and it will be accessible | 29 | TCG TIS 1.2 TPM specification say Yes and it will be accessible |
@@ -32,7 +32,7 @@ config TCG_TIS | |||
32 | 32 | ||
33 | config TCG_NSC | 33 | config TCG_NSC |
34 | tristate "National Semiconductor TPM Interface" | 34 | tristate "National Semiconductor TPM Interface" |
35 | depends on TCG_TPM && PNPACPI | 35 | depends on PNPACPI |
36 | ---help--- | 36 | ---help--- |
37 | If you have a TPM security chip from National Semiconductor | 37 | If you have a TPM security chip from National Semiconductor |
38 | say Yes and it will be accessible from within Linux. To | 38 | say Yes and it will be accessible from within Linux. To |
@@ -41,7 +41,6 @@ config TCG_NSC | |||
41 | 41 | ||
42 | config TCG_ATMEL | 42 | config TCG_ATMEL |
43 | tristate "Atmel TPM Interface" | 43 | tristate "Atmel TPM Interface" |
44 | depends on TCG_TPM | ||
45 | ---help--- | 44 | ---help--- |
46 | If you have a TPM security chip from Atmel say Yes and it | 45 | If you have a TPM security chip from Atmel say Yes and it |
47 | will be accessible from within Linux. To compile this driver | 46 | will be accessible from within Linux. To compile this driver |
@@ -49,7 +48,7 @@ config TCG_ATMEL | |||
49 | 48 | ||
50 | config TCG_INFINEON | 49 | config TCG_INFINEON |
51 | tristate "Infineon Technologies TPM Interface" | 50 | tristate "Infineon Technologies TPM Interface" |
52 | depends on TCG_TPM && PNPACPI | 51 | depends on PNPACPI |
53 | ---help--- | 52 | ---help--- |
54 | If you have a TPM security chip from Infineon Technologies | 53 | If you have a TPM security chip from Infineon Technologies |
55 | (either SLD 9630 TT 1.1 or SLB 9635 TT 1.2) say Yes and it | 54 | (either SLD 9630 TT 1.1 or SLB 9635 TT 1.2) say Yes and it |
@@ -59,5 +58,4 @@ config TCG_INFINEON | |||
59 | Further information on this driver and the supported hardware | 58 | Further information on this driver and the supported hardware |
60 | can be found at http://www.prosec.rub.de/tpm | 59 | can be found at http://www.prosec.rub.de/tpm |
61 | 60 | ||
62 | endmenu | 61 | endif # TCG_TPM |
63 | |||
diff --git a/drivers/char/tty_audit.c b/drivers/char/tty_audit.c new file mode 100644 index 000000000000..d222012c1b0c --- /dev/null +++ b/drivers/char/tty_audit.c | |||
@@ -0,0 +1,345 @@ | |||
1 | /* | ||
2 | * Creating audit events from TTY input. | ||
3 | * | ||
4 | * Copyright (C) 2007 Red Hat, Inc. All rights reserved. This copyrighted | ||
5 | * material is made available to anyone wishing to use, modify, copy, or | ||
6 | * redistribute it subject to the terms and conditions of the GNU General | ||
7 | * Public License v.2. | ||
8 | * | ||
9 | * Authors: Miloslav Trmac <mitr@redhat.com> | ||
10 | */ | ||
11 | |||
12 | #include <linux/audit.h> | ||
13 | #include <linux/file.h> | ||
14 | #include <linux/tty.h> | ||
15 | |||
16 | struct tty_audit_buf { | ||
17 | atomic_t count; | ||
18 | struct mutex mutex; /* Protects all data below */ | ||
19 | int major, minor; /* The TTY which the data is from */ | ||
20 | unsigned icanon:1; | ||
21 | size_t valid; | ||
22 | unsigned char *data; /* Allocated size N_TTY_BUF_SIZE */ | ||
23 | }; | ||
24 | |||
25 | static struct tty_audit_buf *tty_audit_buf_alloc(int major, int minor, | ||
26 | int icanon) | ||
27 | { | ||
28 | struct tty_audit_buf *buf; | ||
29 | |||
30 | buf = kmalloc(sizeof (*buf), GFP_KERNEL); | ||
31 | if (!buf) | ||
32 | goto err; | ||
33 | if (PAGE_SIZE != N_TTY_BUF_SIZE) | ||
34 | buf->data = kmalloc(N_TTY_BUF_SIZE, GFP_KERNEL); | ||
35 | else | ||
36 | buf->data = (unsigned char *)__get_free_page(GFP_KERNEL); | ||
37 | if (!buf->data) | ||
38 | goto err_buf; | ||
39 | atomic_set(&buf->count, 1); | ||
40 | mutex_init(&buf->mutex); | ||
41 | buf->major = major; | ||
42 | buf->minor = minor; | ||
43 | buf->icanon = icanon; | ||
44 | buf->valid = 0; | ||
45 | return buf; | ||
46 | |||
47 | err_buf: | ||
48 | kfree(buf); | ||
49 | err: | ||
50 | return NULL; | ||
51 | } | ||
52 | |||
53 | static void tty_audit_buf_free(struct tty_audit_buf *buf) | ||
54 | { | ||
55 | WARN_ON(buf->valid != 0); | ||
56 | if (PAGE_SIZE != N_TTY_BUF_SIZE) | ||
57 | kfree(buf->data); | ||
58 | else | ||
59 | free_page((unsigned long)buf->data); | ||
60 | kfree(buf); | ||
61 | } | ||
62 | |||
63 | static void tty_audit_buf_put(struct tty_audit_buf *buf) | ||
64 | { | ||
65 | if (atomic_dec_and_test(&buf->count)) | ||
66 | tty_audit_buf_free(buf); | ||
67 | } | ||
68 | |||
69 | /** | ||
70 | * tty_audit_buf_push - Push buffered data out | ||
71 | * | ||
72 | * Generate an audit message from the contents of @buf, which is owned by | ||
73 | * @tsk with @loginuid. @buf->mutex must be locked. | ||
74 | */ | ||
75 | static void tty_audit_buf_push(struct task_struct *tsk, uid_t loginuid, | ||
76 | struct tty_audit_buf *buf) | ||
77 | { | ||
78 | struct audit_buffer *ab; | ||
79 | |||
80 | if (buf->valid == 0) | ||
81 | return; | ||
82 | if (audit_enabled == 0) | ||
83 | return; | ||
84 | ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_TTY); | ||
85 | if (ab) { | ||
86 | char name[sizeof(tsk->comm)]; | ||
87 | |||
88 | audit_log_format(ab, "tty pid=%u uid=%u auid=%u major=%d " | ||
89 | "minor=%d comm=", tsk->pid, tsk->uid, | ||
90 | loginuid, buf->major, buf->minor); | ||
91 | get_task_comm(name, tsk); | ||
92 | audit_log_untrustedstring(ab, name); | ||
93 | audit_log_format(ab, " data="); | ||
94 | audit_log_n_untrustedstring(ab, buf->valid, buf->data); | ||
95 | audit_log_end(ab); | ||
96 | } | ||
97 | buf->valid = 0; | ||
98 | } | ||
99 | |||
100 | /** | ||
101 | * tty_audit_buf_push_current - Push buffered data out | ||
102 | * | ||
103 | * Generate an audit message from the contents of @buf, which is owned by | ||
104 | * the current task. @buf->mutex must be locked. | ||
105 | */ | ||
106 | static void tty_audit_buf_push_current(struct tty_audit_buf *buf) | ||
107 | { | ||
108 | tty_audit_buf_push(current, audit_get_loginuid(current->audit_context), | ||
109 | buf); | ||
110 | } | ||
111 | |||
112 | /** | ||
113 | * tty_audit_exit - Handle a task exit | ||
114 | * | ||
115 | * Make sure all buffered data is written out and deallocate the buffer. | ||
116 | * Only needs to be called if current->signal->tty_audit_buf != %NULL. | ||
117 | */ | ||
118 | void tty_audit_exit(void) | ||
119 | { | ||
120 | struct tty_audit_buf *buf; | ||
121 | |||
122 | spin_lock_irq(¤t->sighand->siglock); | ||
123 | buf = current->signal->tty_audit_buf; | ||
124 | current->signal->tty_audit_buf = NULL; | ||
125 | spin_unlock_irq(¤t->sighand->siglock); | ||
126 | if (!buf) | ||
127 | return; | ||
128 | |||
129 | mutex_lock(&buf->mutex); | ||
130 | tty_audit_buf_push_current(buf); | ||
131 | mutex_unlock(&buf->mutex); | ||
132 | |||
133 | tty_audit_buf_put(buf); | ||
134 | } | ||
135 | |||
136 | /** | ||
137 | * tty_audit_fork - Copy TTY audit state for a new task | ||
138 | * | ||
139 | * Set up TTY audit state in @sig from current. @sig needs no locking. | ||
140 | */ | ||
141 | void tty_audit_fork(struct signal_struct *sig) | ||
142 | { | ||
143 | spin_lock_irq(¤t->sighand->siglock); | ||
144 | sig->audit_tty = current->signal->audit_tty; | ||
145 | spin_unlock_irq(¤t->sighand->siglock); | ||
146 | sig->tty_audit_buf = NULL; | ||
147 | } | ||
148 | |||
149 | /** | ||
150 | * tty_audit_push_task - Flush task's pending audit data | ||
151 | */ | ||
152 | void tty_audit_push_task(struct task_struct *tsk, uid_t loginuid) | ||
153 | { | ||
154 | struct tty_audit_buf *buf; | ||
155 | |||
156 | spin_lock_irq(&tsk->sighand->siglock); | ||
157 | buf = tsk->signal->tty_audit_buf; | ||
158 | if (buf) | ||
159 | atomic_inc(&buf->count); | ||
160 | spin_unlock_irq(&tsk->sighand->siglock); | ||
161 | if (!buf) | ||
162 | return; | ||
163 | |||
164 | mutex_lock(&buf->mutex); | ||
165 | tty_audit_buf_push(tsk, loginuid, buf); | ||
166 | mutex_unlock(&buf->mutex); | ||
167 | |||
168 | tty_audit_buf_put(buf); | ||
169 | } | ||
170 | |||
171 | /** | ||
172 | * tty_audit_buf_get - Get an audit buffer. | ||
173 | * | ||
174 | * Get an audit buffer for @tty, allocate it if necessary. Return %NULL | ||
175 | * if TTY auditing is disabled or out of memory. Otherwise, return a new | ||
176 | * reference to the buffer. | ||
177 | */ | ||
178 | static struct tty_audit_buf *tty_audit_buf_get(struct tty_struct *tty) | ||
179 | { | ||
180 | struct tty_audit_buf *buf, *buf2; | ||
181 | |||
182 | buf = NULL; | ||
183 | buf2 = NULL; | ||
184 | spin_lock_irq(¤t->sighand->siglock); | ||
185 | if (likely(!current->signal->audit_tty)) | ||
186 | goto out; | ||
187 | buf = current->signal->tty_audit_buf; | ||
188 | if (buf) { | ||
189 | atomic_inc(&buf->count); | ||
190 | goto out; | ||
191 | } | ||
192 | spin_unlock_irq(¤t->sighand->siglock); | ||
193 | |||
194 | buf2 = tty_audit_buf_alloc(tty->driver->major, | ||
195 | tty->driver->minor_start + tty->index, | ||
196 | tty->icanon); | ||
197 | if (buf2 == NULL) { | ||
198 | audit_log_lost("out of memory in TTY auditing"); | ||
199 | return NULL; | ||
200 | } | ||
201 | |||
202 | spin_lock_irq(¤t->sighand->siglock); | ||
203 | if (!current->signal->audit_tty) | ||
204 | goto out; | ||
205 | buf = current->signal->tty_audit_buf; | ||
206 | if (!buf) { | ||
207 | current->signal->tty_audit_buf = buf2; | ||
208 | buf = buf2; | ||
209 | buf2 = NULL; | ||
210 | } | ||
211 | atomic_inc(&buf->count); | ||
212 | /* Fall through */ | ||
213 | out: | ||
214 | spin_unlock_irq(¤t->sighand->siglock); | ||
215 | if (buf2) | ||
216 | tty_audit_buf_free(buf2); | ||
217 | return buf; | ||
218 | } | ||
219 | |||
220 | /** | ||
221 | * tty_audit_add_data - Add data for TTY auditing. | ||
222 | * | ||
223 | * Audit @data of @size from @tty, if necessary. | ||
224 | */ | ||
225 | void tty_audit_add_data(struct tty_struct *tty, unsigned char *data, | ||
226 | size_t size) | ||
227 | { | ||
228 | struct tty_audit_buf *buf; | ||
229 | int major, minor; | ||
230 | |||
231 | if (unlikely(size == 0)) | ||
232 | return; | ||
233 | |||
234 | buf = tty_audit_buf_get(tty); | ||
235 | if (!buf) | ||
236 | return; | ||
237 | |||
238 | mutex_lock(&buf->mutex); | ||
239 | major = tty->driver->major; | ||
240 | minor = tty->driver->minor_start + tty->index; | ||
241 | if (buf->major != major || buf->minor != minor | ||
242 | || buf->icanon != tty->icanon) { | ||
243 | tty_audit_buf_push_current(buf); | ||
244 | buf->major = major; | ||
245 | buf->minor = minor; | ||
246 | buf->icanon = tty->icanon; | ||
247 | } | ||
248 | do { | ||
249 | size_t run; | ||
250 | |||
251 | run = N_TTY_BUF_SIZE - buf->valid; | ||
252 | if (run > size) | ||
253 | run = size; | ||
254 | memcpy(buf->data + buf->valid, data, run); | ||
255 | buf->valid += run; | ||
256 | data += run; | ||
257 | size -= run; | ||
258 | if (buf->valid == N_TTY_BUF_SIZE) | ||
259 | tty_audit_buf_push_current(buf); | ||
260 | } while (size != 0); | ||
261 | mutex_unlock(&buf->mutex); | ||
262 | tty_audit_buf_put(buf); | ||
263 | } | ||
264 | |||
265 | /** | ||
266 | * tty_audit_push - Push buffered data out | ||
267 | * | ||
268 | * Make sure no audit data is pending for @tty on the current process. | ||
269 | */ | ||
270 | void tty_audit_push(struct tty_struct *tty) | ||
271 | { | ||
272 | struct tty_audit_buf *buf; | ||
273 | |||
274 | spin_lock_irq(¤t->sighand->siglock); | ||
275 | if (likely(!current->signal->audit_tty)) { | ||
276 | spin_unlock_irq(¤t->sighand->siglock); | ||
277 | return; | ||
278 | } | ||
279 | buf = current->signal->tty_audit_buf; | ||
280 | if (buf) | ||
281 | atomic_inc(&buf->count); | ||
282 | spin_unlock_irq(¤t->sighand->siglock); | ||
283 | |||
284 | if (buf) { | ||
285 | int major, minor; | ||
286 | |||
287 | major = tty->driver->major; | ||
288 | minor = tty->driver->minor_start + tty->index; | ||
289 | mutex_lock(&buf->mutex); | ||
290 | if (buf->major == major && buf->minor == minor) | ||
291 | tty_audit_buf_push_current(buf); | ||
292 | mutex_unlock(&buf->mutex); | ||
293 | tty_audit_buf_put(buf); | ||
294 | } | ||
295 | } | ||
296 | |||
297 | /** | ||
298 | * tty_audit_opening - A TTY is being opened. | ||
299 | * | ||
300 | * As a special hack, tasks that close all their TTYs and open new ones | ||
301 | * are assumed to be system daemons (e.g. getty) and auditing is | ||
302 | * automatically disabled for them. | ||
303 | */ | ||
304 | void tty_audit_opening(void) | ||
305 | { | ||
306 | int disable; | ||
307 | |||
308 | disable = 1; | ||
309 | spin_lock_irq(¤t->sighand->siglock); | ||
310 | if (current->signal->audit_tty == 0) | ||
311 | disable = 0; | ||
312 | spin_unlock_irq(¤t->sighand->siglock); | ||
313 | if (!disable) | ||
314 | return; | ||
315 | |||
316 | task_lock(current); | ||
317 | if (current->files) { | ||
318 | struct fdtable *fdt; | ||
319 | unsigned i; | ||
320 | |||
321 | /* | ||
322 | * We don't take a ref to the file, so we must hold ->file_lock | ||
323 | * instead. | ||
324 | */ | ||
325 | spin_lock(¤t->files->file_lock); | ||
326 | fdt = files_fdtable(current->files); | ||
327 | for (i = 0; i < fdt->max_fds; i++) { | ||
328 | struct file *filp; | ||
329 | |||
330 | filp = fcheck_files(current->files, i); | ||
331 | if (filp && is_tty(filp)) { | ||
332 | disable = 0; | ||
333 | break; | ||
334 | } | ||
335 | } | ||
336 | spin_unlock(¤t->files->file_lock); | ||
337 | } | ||
338 | task_unlock(current); | ||
339 | if (!disable) | ||
340 | return; | ||
341 | |||
342 | spin_lock_irq(¤t->sighand->siglock); | ||
343 | current->signal->audit_tty = 0; | ||
344 | spin_unlock_irq(¤t->sighand->siglock); | ||
345 | } | ||
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index a96f26a63fa2..de37ebc3a4cf 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c | |||
@@ -1503,6 +1503,15 @@ int tty_hung_up_p(struct file * filp) | |||
1503 | 1503 | ||
1504 | EXPORT_SYMBOL(tty_hung_up_p); | 1504 | EXPORT_SYMBOL(tty_hung_up_p); |
1505 | 1505 | ||
1506 | /** | ||
1507 | * is_tty - checker whether file is a TTY | ||
1508 | */ | ||
1509 | int is_tty(struct file *filp) | ||
1510 | { | ||
1511 | return filp->f_op->read == tty_read | ||
1512 | || filp->f_op->read == hung_up_tty_read; | ||
1513 | } | ||
1514 | |||
1506 | static void session_clear_tty(struct pid *session) | 1515 | static void session_clear_tty(struct pid *session) |
1507 | { | 1516 | { |
1508 | struct task_struct *p; | 1517 | struct task_struct *p; |
@@ -1726,6 +1735,23 @@ static ssize_t tty_read(struct file * file, char __user * buf, size_t count, | |||
1726 | return i; | 1735 | return i; |
1727 | } | 1736 | } |
1728 | 1737 | ||
1738 | void tty_write_unlock(struct tty_struct *tty) | ||
1739 | { | ||
1740 | mutex_unlock(&tty->atomic_write_lock); | ||
1741 | wake_up_interruptible(&tty->write_wait); | ||
1742 | } | ||
1743 | |||
1744 | int tty_write_lock(struct tty_struct *tty, int ndelay) | ||
1745 | { | ||
1746 | if (!mutex_trylock(&tty->atomic_write_lock)) { | ||
1747 | if (ndelay) | ||
1748 | return -EAGAIN; | ||
1749 | if (mutex_lock_interruptible(&tty->atomic_write_lock)) | ||
1750 | return -ERESTARTSYS; | ||
1751 | } | ||
1752 | return 0; | ||
1753 | } | ||
1754 | |||
1729 | /* | 1755 | /* |
1730 | * Split writes up in sane blocksizes to avoid | 1756 | * Split writes up in sane blocksizes to avoid |
1731 | * denial-of-service type attacks | 1757 | * denial-of-service type attacks |
@@ -1737,13 +1763,12 @@ static inline ssize_t do_tty_write( | |||
1737 | const char __user *buf, | 1763 | const char __user *buf, |
1738 | size_t count) | 1764 | size_t count) |
1739 | { | 1765 | { |
1740 | ssize_t ret = 0, written = 0; | 1766 | ssize_t ret, written = 0; |
1741 | unsigned int chunk; | 1767 | unsigned int chunk; |
1742 | 1768 | ||
1743 | /* FIXME: O_NDELAY ... */ | 1769 | ret = tty_write_lock(tty, file->f_flags & O_NDELAY); |
1744 | if (mutex_lock_interruptible(&tty->atomic_write_lock)) { | 1770 | if (ret < 0) |
1745 | return -ERESTARTSYS; | 1771 | return ret; |
1746 | } | ||
1747 | 1772 | ||
1748 | /* | 1773 | /* |
1749 | * We chunk up writes into a temporary buffer. This | 1774 | * We chunk up writes into a temporary buffer. This |
@@ -1776,8 +1801,8 @@ static inline ssize_t do_tty_write( | |||
1776 | 1801 | ||
1777 | buf = kmalloc(chunk, GFP_KERNEL); | 1802 | buf = kmalloc(chunk, GFP_KERNEL); |
1778 | if (!buf) { | 1803 | if (!buf) { |
1779 | mutex_unlock(&tty->atomic_write_lock); | 1804 | ret = -ENOMEM; |
1780 | return -ENOMEM; | 1805 | goto out; |
1781 | } | 1806 | } |
1782 | kfree(tty->write_buf); | 1807 | kfree(tty->write_buf); |
1783 | tty->write_cnt = chunk; | 1808 | tty->write_cnt = chunk; |
@@ -1812,7 +1837,8 @@ static inline ssize_t do_tty_write( | |||
1812 | inode->i_mtime = current_fs_time(inode->i_sb); | 1837 | inode->i_mtime = current_fs_time(inode->i_sb); |
1813 | ret = written; | 1838 | ret = written; |
1814 | } | 1839 | } |
1815 | mutex_unlock(&tty->atomic_write_lock); | 1840 | out: |
1841 | tty_write_unlock(tty); | ||
1816 | return ret; | 1842 | return ret; |
1817 | } | 1843 | } |
1818 | 1844 | ||
@@ -2016,11 +2042,9 @@ static int init_dev(struct tty_driver *driver, int idx, | |||
2016 | } | 2042 | } |
2017 | 2043 | ||
2018 | if (!*ltp_loc) { | 2044 | if (!*ltp_loc) { |
2019 | ltp = (struct ktermios *) kmalloc(sizeof(struct ktermios), | 2045 | ltp = kzalloc(sizeof(struct ktermios), GFP_KERNEL); |
2020 | GFP_KERNEL); | ||
2021 | if (!ltp) | 2046 | if (!ltp) |
2022 | goto free_mem_out; | 2047 | goto free_mem_out; |
2023 | memset(ltp, 0, sizeof(struct ktermios)); | ||
2024 | } | 2048 | } |
2025 | 2049 | ||
2026 | if (driver->type == TTY_DRIVER_TYPE_PTY) { | 2050 | if (driver->type == TTY_DRIVER_TYPE_PTY) { |
@@ -2049,11 +2073,9 @@ static int init_dev(struct tty_driver *driver, int idx, | |||
2049 | } | 2073 | } |
2050 | 2074 | ||
2051 | if (!*o_ltp_loc) { | 2075 | if (!*o_ltp_loc) { |
2052 | o_ltp = (struct ktermios *) | 2076 | o_ltp = kzalloc(sizeof(struct ktermios), GFP_KERNEL); |
2053 | kmalloc(sizeof(struct ktermios), GFP_KERNEL); | ||
2054 | if (!o_ltp) | 2077 | if (!o_ltp) |
2055 | goto free_mem_out; | 2078 | goto free_mem_out; |
2056 | memset(o_ltp, 0, sizeof(struct ktermios)); | ||
2057 | } | 2079 | } |
2058 | 2080 | ||
2059 | /* | 2081 | /* |
@@ -2660,6 +2682,7 @@ got_driver: | |||
2660 | __proc_set_tty(current, tty); | 2682 | __proc_set_tty(current, tty); |
2661 | spin_unlock_irq(¤t->sighand->siglock); | 2683 | spin_unlock_irq(¤t->sighand->siglock); |
2662 | mutex_unlock(&tty_mutex); | 2684 | mutex_unlock(&tty_mutex); |
2685 | tty_audit_opening(); | ||
2663 | return 0; | 2686 | return 0; |
2664 | } | 2687 | } |
2665 | 2688 | ||
@@ -2722,8 +2745,10 @@ static int ptmx_open(struct inode * inode, struct file * filp) | |||
2722 | 2745 | ||
2723 | check_tty_count(tty, "tty_open"); | 2746 | check_tty_count(tty, "tty_open"); |
2724 | retval = ptm_driver->open(tty, filp); | 2747 | retval = ptm_driver->open(tty, filp); |
2725 | if (!retval) | 2748 | if (!retval) { |
2749 | tty_audit_opening(); | ||
2726 | return 0; | 2750 | return 0; |
2751 | } | ||
2727 | out1: | 2752 | out1: |
2728 | release_dev(filp); | 2753 | release_dev(filp); |
2729 | return retval; | 2754 | return retval; |
@@ -3163,14 +3188,13 @@ static int tiocsetd(struct tty_struct *tty, int __user *p) | |||
3163 | 3188 | ||
3164 | static int send_break(struct tty_struct *tty, unsigned int duration) | 3189 | static int send_break(struct tty_struct *tty, unsigned int duration) |
3165 | { | 3190 | { |
3166 | if (mutex_lock_interruptible(&tty->atomic_write_lock)) | 3191 | if (tty_write_lock(tty, 0) < 0) |
3167 | return -EINTR; | 3192 | return -EINTR; |
3168 | tty->driver->break_ctl(tty, -1); | 3193 | tty->driver->break_ctl(tty, -1); |
3169 | if (!signal_pending(current)) { | 3194 | if (!signal_pending(current)) |
3170 | msleep_interruptible(duration); | 3195 | msleep_interruptible(duration); |
3171 | } | ||
3172 | tty->driver->break_ctl(tty, 0); | 3196 | tty->driver->break_ctl(tty, 0); |
3173 | mutex_unlock(&tty->atomic_write_lock); | 3197 | tty_write_unlock(tty); |
3174 | if (signal_pending(current)) | 3198 | if (signal_pending(current)) |
3175 | return -EINTR; | 3199 | return -EINTR; |
3176 | return 0; | 3200 | return 0; |
@@ -3739,9 +3763,8 @@ struct tty_driver *alloc_tty_driver(int lines) | |||
3739 | { | 3763 | { |
3740 | struct tty_driver *driver; | 3764 | struct tty_driver *driver; |
3741 | 3765 | ||
3742 | driver = kmalloc(sizeof(struct tty_driver), GFP_KERNEL); | 3766 | driver = kzalloc(sizeof(struct tty_driver), GFP_KERNEL); |
3743 | if (driver) { | 3767 | if (driver) { |
3744 | memset(driver, 0, sizeof(struct tty_driver)); | ||
3745 | driver->magic = TTY_DRIVER_MAGIC; | 3768 | driver->magic = TTY_DRIVER_MAGIC; |
3746 | driver->num = lines; | 3769 | driver->num = lines; |
3747 | /* later we'll move allocation of tables here */ | 3770 | /* later we'll move allocation of tables here */ |
diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c index fd471cb3338f..3423e9ee6481 100644 --- a/drivers/char/tty_ioctl.c +++ b/drivers/char/tty_ioctl.c | |||
@@ -52,8 +52,6 @@ | |||
52 | 52 | ||
53 | void tty_wait_until_sent(struct tty_struct * tty, long timeout) | 53 | void tty_wait_until_sent(struct tty_struct * tty, long timeout) |
54 | { | 54 | { |
55 | DECLARE_WAITQUEUE(wait, current); | ||
56 | |||
57 | #ifdef TTY_DEBUG_WAIT_UNTIL_SENT | 55 | #ifdef TTY_DEBUG_WAIT_UNTIL_SENT |
58 | char buf[64]; | 56 | char buf[64]; |
59 | 57 | ||
@@ -61,26 +59,13 @@ void tty_wait_until_sent(struct tty_struct * tty, long timeout) | |||
61 | #endif | 59 | #endif |
62 | if (!tty->driver->chars_in_buffer) | 60 | if (!tty->driver->chars_in_buffer) |
63 | return; | 61 | return; |
64 | add_wait_queue(&tty->write_wait, &wait); | ||
65 | if (!timeout) | 62 | if (!timeout) |
66 | timeout = MAX_SCHEDULE_TIMEOUT; | 63 | timeout = MAX_SCHEDULE_TIMEOUT; |
67 | do { | 64 | if (wait_event_interruptible_timeout(tty->write_wait, |
68 | #ifdef TTY_DEBUG_WAIT_UNTIL_SENT | 65 | !tty->driver->chars_in_buffer(tty), timeout)) |
69 | printk(KERN_DEBUG "waiting %s...(%d)\n", tty_name(tty, buf), | 66 | return; |
70 | tty->driver->chars_in_buffer(tty)); | ||
71 | #endif | ||
72 | set_current_state(TASK_INTERRUPTIBLE); | ||
73 | if (signal_pending(current)) | ||
74 | goto stop_waiting; | ||
75 | if (!tty->driver->chars_in_buffer(tty)) | ||
76 | break; | ||
77 | timeout = schedule_timeout(timeout); | ||
78 | } while (timeout); | ||
79 | if (tty->driver->wait_until_sent) | 67 | if (tty->driver->wait_until_sent) |
80 | tty->driver->wait_until_sent(tty, timeout); | 68 | tty->driver->wait_until_sent(tty, timeout); |
81 | stop_waiting: | ||
82 | set_current_state(TASK_RUNNING); | ||
83 | remove_wait_queue(&tty->write_wait, &wait); | ||
84 | } | 69 | } |
85 | 70 | ||
86 | EXPORT_SYMBOL(tty_wait_until_sent); | 71 | EXPORT_SYMBOL(tty_wait_until_sent); |
@@ -276,13 +261,12 @@ void tty_termios_encode_baud_rate(struct ktermios *termios, speed_t ibaud, speed | |||
276 | termios->c_cflag |= (baud_bits[i] << IBSHIFT); | 261 | termios->c_cflag |= (baud_bits[i] << IBSHIFT); |
277 | ifound = i; | 262 | ifound = i; |
278 | } | 263 | } |
279 | } | 264 | } while (++i < n_baud_table); |
280 | while(++i < n_baud_table); | ||
281 | if (ofound == -1) | 265 | if (ofound == -1) |
282 | termios->c_cflag |= BOTHER; | 266 | termios->c_cflag |= BOTHER; |
283 | /* Set exact input bits only if the input and output differ or the | 267 | /* Set exact input bits only if the input and output differ or the |
284 | user already did */ | 268 | user already did */ |
285 | if (ifound == -1 && (ibaud != obaud || ibinput)) | 269 | if (ifound == -1 && (ibaud != obaud || ibinput)) |
286 | termios->c_cflag |= (BOTHER << IBSHIFT); | 270 | termios->c_cflag |= (BOTHER << IBSHIFT); |
287 | } | 271 | } |
288 | 272 | ||
@@ -575,7 +559,7 @@ static int set_sgttyb(struct tty_struct * tty, struct sgttyb __user * sgttyb) | |||
575 | return -EFAULT; | 559 | return -EFAULT; |
576 | 560 | ||
577 | mutex_lock(&tty->termios_mutex); | 561 | mutex_lock(&tty->termios_mutex); |
578 | termios = *tty->termios; | 562 | termios = *tty->termios; |
579 | termios.c_cc[VERASE] = tmp.sg_erase; | 563 | termios.c_cc[VERASE] = tmp.sg_erase; |
580 | termios.c_cc[VKILL] = tmp.sg_kill; | 564 | termios.c_cc[VKILL] = tmp.sg_kill; |
581 | set_sgflags(&termios, tmp.sg_flags); | 565 | set_sgflags(&termios, tmp.sg_flags); |
@@ -667,7 +651,7 @@ static int send_prio_char(struct tty_struct *tty, char ch) | |||
667 | return 0; | 651 | return 0; |
668 | } | 652 | } |
669 | 653 | ||
670 | if (mutex_lock_interruptible(&tty->atomic_write_lock)) | 654 | if (tty_write_lock(tty, 0) < 0) |
671 | return -ERESTARTSYS; | 655 | return -ERESTARTSYS; |
672 | 656 | ||
673 | if (was_stopped) | 657 | if (was_stopped) |
@@ -675,7 +659,7 @@ static int send_prio_char(struct tty_struct *tty, char ch) | |||
675 | tty->driver->write(tty, &ch, 1); | 659 | tty->driver->write(tty, &ch, 1); |
676 | if (was_stopped) | 660 | if (was_stopped) |
677 | stop_tty(tty); | 661 | stop_tty(tty); |
678 | mutex_unlock(&tty->atomic_write_lock); | 662 | tty_write_unlock(tty); |
679 | return 0; | 663 | return 0; |
680 | } | 664 | } |
681 | 665 | ||
diff --git a/drivers/connector/Kconfig b/drivers/connector/Kconfig index e0bdc0db9640..100bfd422066 100644 --- a/drivers/connector/Kconfig +++ b/drivers/connector/Kconfig | |||
@@ -1,6 +1,5 @@ | |||
1 | menu "Connector - unified userspace <-> kernelspace linker" | ||
2 | 1 | ||
3 | config CONNECTOR | 2 | menuconfig CONNECTOR |
4 | tristate "Connector - unified userspace <-> kernelspace linker" | 3 | tristate "Connector - unified userspace <-> kernelspace linker" |
5 | depends on NET | 4 | depends on NET |
6 | ---help--- | 5 | ---help--- |
@@ -10,6 +9,8 @@ config CONNECTOR | |||
10 | Connector support can also be built as a module. If so, the module | 9 | Connector support can also be built as a module. If so, the module |
11 | will be called cn.ko. | 10 | will be called cn.ko. |
12 | 11 | ||
12 | if CONNECTOR | ||
13 | |||
13 | config PROC_EVENTS | 14 | config PROC_EVENTS |
14 | boolean "Report process events to userspace" | 15 | boolean "Report process events to userspace" |
15 | depends on CONNECTOR=y | 16 | depends on CONNECTOR=y |
@@ -18,4 +19,4 @@ config PROC_EVENTS | |||
18 | Provide a connector that reports process events to userspace. Send | 19 | Provide a connector that reports process events to userspace. Send |
19 | events such as fork, exec, id change (uid, gid, suid, etc), and exit. | 20 | events such as fork, exec, id change (uid, gid, suid, etc), and exit. |
20 | 21 | ||
21 | endmenu | 22 | endif # CONNECTOR |
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index bb90cbd7ca51..84ebfcc1ffb4 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig | |||
@@ -1,4 +1,9 @@ | |||
1 | menu "Hardware crypto devices" | 1 | |
2 | menuconfig CRYPTO_HW | ||
3 | bool "Hardware crypto devices" | ||
4 | default y | ||
5 | |||
6 | if CRYPTO_HW | ||
2 | 7 | ||
3 | config CRYPTO_DEV_PADLOCK | 8 | config CRYPTO_DEV_PADLOCK |
4 | tristate "Support for VIA PadLock ACE" | 9 | tristate "Support for VIA PadLock ACE" |
@@ -78,4 +83,4 @@ config ZCRYPT_MONOLITHIC | |||
78 | that contains all parts of the crypto device driver (ap bus, | 83 | that contains all parts of the crypto device driver (ap bus, |
79 | request router and all the card drivers). | 84 | request router and all the card drivers). |
80 | 85 | ||
81 | endmenu | 86 | endif # CRYPTO_HW |
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index b31756d59978..8f670dae53bb 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig | |||
@@ -3,7 +3,7 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | menu "DMA Engine support" | 5 | menu "DMA Engine support" |
6 | depends on !S390 | 6 | depends on HAS_DMA |
7 | 7 | ||
8 | config DMA_ENGINE | 8 | config DMA_ENGINE |
9 | bool "Support for DMA engines" | 9 | bool "Support for DMA engines" |
diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig index 807c402df049..debf1d8e8b41 100644 --- a/drivers/edac/Kconfig +++ b/drivers/edac/Kconfig | |||
@@ -6,11 +6,9 @@ | |||
6 | # $Id: Kconfig,v 1.4.2.7 2005/07/08 22:05:38 dsp_llnl Exp $ | 6 | # $Id: Kconfig,v 1.4.2.7 2005/07/08 22:05:38 dsp_llnl Exp $ |
7 | # | 7 | # |
8 | 8 | ||
9 | menu 'EDAC - error detection and reporting (RAS) (EXPERIMENTAL)' | 9 | menuconfig EDAC |
10 | tristate "EDAC - error detection and reporting (EXPERIMENTAL)" | ||
10 | depends on HAS_IOMEM | 11 | depends on HAS_IOMEM |
11 | |||
12 | config EDAC | ||
13 | tristate "EDAC core system error reporting (EXPERIMENTAL)" | ||
14 | depends on X86 && EXPERIMENTAL | 12 | depends on X86 && EXPERIMENTAL |
15 | help | 13 | help |
16 | EDAC is designed to report errors in the core system. | 14 | EDAC is designed to report errors in the core system. |
@@ -30,13 +28,12 @@ config EDAC | |||
30 | There is also a mailing list for the EDAC project, which can | 28 | There is also a mailing list for the EDAC project, which can |
31 | be found via the sourceforge page. | 29 | be found via the sourceforge page. |
32 | 30 | ||
31 | if EDAC | ||
33 | 32 | ||
34 | comment "Reporting subsystems" | 33 | comment "Reporting subsystems" |
35 | depends on EDAC | ||
36 | 34 | ||
37 | config EDAC_DEBUG | 35 | config EDAC_DEBUG |
38 | bool "Debugging" | 36 | bool "Debugging" |
39 | depends on EDAC | ||
40 | help | 37 | help |
41 | This turns on debugging information for the entire EDAC | 38 | This turns on debugging information for the entire EDAC |
42 | sub-system. You can insert module with "debug_level=x", current | 39 | sub-system. You can insert module with "debug_level=x", current |
@@ -45,7 +42,6 @@ config EDAC_DEBUG | |||
45 | 42 | ||
46 | config EDAC_MM_EDAC | 43 | config EDAC_MM_EDAC |
47 | tristate "Main Memory EDAC (Error Detection And Correction) reporting" | 44 | tristate "Main Memory EDAC (Error Detection And Correction) reporting" |
48 | depends on EDAC | ||
49 | default y | 45 | default y |
50 | help | 46 | help |
51 | Some systems are able to detect and correct errors in main | 47 | Some systems are able to detect and correct errors in main |
@@ -100,15 +96,13 @@ config EDAC_R82600 | |||
100 | 96 | ||
101 | choice | 97 | choice |
102 | prompt "Error detecting method" | 98 | prompt "Error detecting method" |
103 | depends on EDAC | ||
104 | default EDAC_POLL | 99 | default EDAC_POLL |
105 | 100 | ||
106 | config EDAC_POLL | 101 | config EDAC_POLL |
107 | bool "Poll for errors" | 102 | bool "Poll for errors" |
108 | depends on EDAC | ||
109 | help | 103 | help |
110 | Poll the chipset periodically to detect errors. | 104 | Poll the chipset periodically to detect errors. |
111 | 105 | ||
112 | endchoice | 106 | endchoice |
113 | 107 | ||
114 | endmenu | 108 | endif # EDAC |
diff --git a/drivers/firmware/edd.c b/drivers/firmware/edd.c index 15232271d848..0fb730ee1da8 100644 --- a/drivers/firmware/edd.c +++ b/drivers/firmware/edd.c | |||
@@ -669,7 +669,7 @@ edd_get_pci_dev(struct edd_device *edev) | |||
669 | struct edd_info *info = edd_dev_get_info(edev); | 669 | struct edd_info *info = edd_dev_get_info(edev); |
670 | 670 | ||
671 | if (edd_dev_is_type(edev, "PCI")) { | 671 | if (edd_dev_is_type(edev, "PCI")) { |
672 | return pci_find_slot(info->params.interface_path.pci.bus, | 672 | return pci_get_bus_and_slot(info->params.interface_path.pci.bus, |
673 | PCI_DEVFN(info->params.interface_path.pci.slot, | 673 | PCI_DEVFN(info->params.interface_path.pci.slot, |
674 | info->params.interface_path.pci. | 674 | info->params.interface_path.pci. |
675 | function)); | 675 | function)); |
@@ -682,9 +682,12 @@ edd_create_symlink_to_pcidev(struct edd_device *edev) | |||
682 | { | 682 | { |
683 | 683 | ||
684 | struct pci_dev *pci_dev = edd_get_pci_dev(edev); | 684 | struct pci_dev *pci_dev = edd_get_pci_dev(edev); |
685 | int ret; | ||
685 | if (!pci_dev) | 686 | if (!pci_dev) |
686 | return 1; | 687 | return 1; |
687 | return sysfs_create_link(&edev->kobj,&pci_dev->dev.kobj,"pci_dev"); | 688 | ret = sysfs_create_link(&edev->kobj,&pci_dev->dev.kobj,"pci_dev"); |
689 | pci_dev_put(pci_dev); | ||
690 | return ret; | ||
688 | } | 691 | } |
689 | 692 | ||
690 | static inline void | 693 | static inline void |
diff --git a/drivers/firmware/pcdp.c b/drivers/firmware/pcdp.c index 2b4b76e8bd72..58e9f8e457f8 100644 --- a/drivers/firmware/pcdp.c +++ b/drivers/firmware/pcdp.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/console.h> | 15 | #include <linux/console.h> |
16 | #include <linux/efi.h> | 16 | #include <linux/efi.h> |
17 | #include <linux/serial.h> | 17 | #include <linux/serial.h> |
18 | #include <linux/serial_8250.h> | ||
18 | #include <asm/vga.h> | 19 | #include <asm/vga.h> |
19 | #include "pcdp.h" | 20 | #include "pcdp.h" |
20 | 21 | ||
@@ -27,7 +28,7 @@ setup_serial_console(struct pcdp_uart *uart) | |||
27 | char parity; | 28 | char parity; |
28 | 29 | ||
29 | mmio = (uart->addr.space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY); | 30 | mmio = (uart->addr.space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY); |
30 | p += sprintf(p, "console=uart,%s,0x%lx", | 31 | p += sprintf(p, "uart8250,%s,0x%lx", |
31 | mmio ? "mmio" : "io", uart->addr.address); | 32 | mmio ? "mmio" : "io", uart->addr.address); |
32 | if (uart->baud) { | 33 | if (uart->baud) { |
33 | p += sprintf(p, ",%lu", uart->baud); | 34 | p += sprintf(p, ",%lu", uart->baud); |
@@ -41,7 +42,8 @@ setup_serial_console(struct pcdp_uart *uart) | |||
41 | } | 42 | } |
42 | } | 43 | } |
43 | 44 | ||
44 | return early_serial_console_init(options); | 45 | add_preferred_console("uart", 8250, &options[9]); |
46 | return setup_early_serial8250_console(options); | ||
45 | #else | 47 | #else |
46 | return -ENODEV; | 48 | return -ENODEV; |
47 | #endif | 49 | #endif |
diff --git a/drivers/macintosh/adb.c b/drivers/macintosh/adb.c index adfea3c7c62a..bc77c5e2ca9f 100644 --- a/drivers/macintosh/adb.c +++ b/drivers/macintosh/adb.c | |||
@@ -248,21 +248,15 @@ static int adb_scan_bus(void) | |||
248 | static int | 248 | static int |
249 | adb_probe_task(void *x) | 249 | adb_probe_task(void *x) |
250 | { | 250 | { |
251 | sigset_t blocked; | ||
252 | |||
253 | strcpy(current->comm, "kadbprobe"); | 251 | strcpy(current->comm, "kadbprobe"); |
254 | 252 | ||
255 | sigfillset(&blocked); | ||
256 | sigprocmask(SIG_BLOCK, &blocked, NULL); | ||
257 | flush_signals(current); | ||
258 | |||
259 | printk(KERN_INFO "adb: starting probe task...\n"); | 253 | printk(KERN_INFO "adb: starting probe task...\n"); |
260 | do_adb_reset_bus(); | 254 | do_adb_reset_bus(); |
261 | printk(KERN_INFO "adb: finished probe task...\n"); | 255 | printk(KERN_INFO "adb: finished probe task...\n"); |
262 | 256 | ||
263 | adb_probe_task_pid = 0; | 257 | adb_probe_task_pid = 0; |
264 | up(&adb_probe_mutex); | 258 | up(&adb_probe_mutex); |
265 | 259 | ||
266 | return 0; | 260 | return 0; |
267 | } | 261 | } |
268 | 262 | ||
diff --git a/drivers/message/i2o/Kconfig b/drivers/message/i2o/Kconfig index f4ac21e5771e..5afa0e393ecf 100644 --- a/drivers/message/i2o/Kconfig +++ b/drivers/message/i2o/Kconfig | |||
@@ -1,9 +1,6 @@ | |||
1 | 1 | ||
2 | menu "I2O device support" | 2 | menuconfig I2O |
3 | depends on PCI | 3 | tristate "I2O device support" |
4 | |||
5 | config I2O | ||
6 | tristate "I2O support" | ||
7 | depends on PCI | 4 | depends on PCI |
8 | ---help--- | 5 | ---help--- |
9 | The Intelligent Input/Output (I2O) architecture allows hardware | 6 | The Intelligent Input/Output (I2O) architecture allows hardware |
@@ -25,9 +22,10 @@ config I2O | |||
25 | 22 | ||
26 | If unsure, say N. | 23 | If unsure, say N. |
27 | 24 | ||
25 | if I2O | ||
26 | |||
28 | config I2O_LCT_NOTIFY_ON_CHANGES | 27 | config I2O_LCT_NOTIFY_ON_CHANGES |
29 | bool "Enable LCT notification" | 28 | bool "Enable LCT notification" |
30 | depends on I2O | ||
31 | default y | 29 | default y |
32 | ---help--- | 30 | ---help--- |
33 | Only say N here if you have a I2O controller from SUN. The SUN | 31 | Only say N here if you have a I2O controller from SUN. The SUN |
@@ -39,7 +37,6 @@ config I2O_LCT_NOTIFY_ON_CHANGES | |||
39 | 37 | ||
40 | config I2O_EXT_ADAPTEC | 38 | config I2O_EXT_ADAPTEC |
41 | bool "Enable Adaptec extensions" | 39 | bool "Enable Adaptec extensions" |
42 | depends on I2O | ||
43 | default y | 40 | default y |
44 | ---help--- | 41 | ---help--- |
45 | Say Y for support of raidutils for Adaptec I2O controllers. You also | 42 | Say Y for support of raidutils for Adaptec I2O controllers. You also |
@@ -57,7 +54,7 @@ config I2O_EXT_ADAPTEC_DMA64 | |||
57 | 54 | ||
58 | config I2O_CONFIG | 55 | config I2O_CONFIG |
59 | tristate "I2O Configuration support" | 56 | tristate "I2O Configuration support" |
60 | depends on I2O | 57 | depends on VIRT_TO_BUS |
61 | ---help--- | 58 | ---help--- |
62 | Say Y for support of the configuration interface for the I2O adapters. | 59 | Say Y for support of the configuration interface for the I2O adapters. |
63 | If you have a RAID controller from Adaptec and you want to use the | 60 | If you have a RAID controller from Adaptec and you want to use the |
@@ -78,7 +75,6 @@ config I2O_CONFIG_OLD_IOCTL | |||
78 | 75 | ||
79 | config I2O_BUS | 76 | config I2O_BUS |
80 | tristate "I2O Bus Adapter OSM" | 77 | tristate "I2O Bus Adapter OSM" |
81 | depends on I2O | ||
82 | ---help--- | 78 | ---help--- |
83 | Include support for the I2O Bus Adapter OSM. The Bus Adapter OSM | 79 | Include support for the I2O Bus Adapter OSM. The Bus Adapter OSM |
84 | provides access to the busses on the I2O controller. The main purpose | 80 | provides access to the busses on the I2O controller. The main purpose |
@@ -89,7 +85,7 @@ config I2O_BUS | |||
89 | 85 | ||
90 | config I2O_BLOCK | 86 | config I2O_BLOCK |
91 | tristate "I2O Block OSM" | 87 | tristate "I2O Block OSM" |
92 | depends on I2O && BLOCK | 88 | depends on BLOCK |
93 | ---help--- | 89 | ---help--- |
94 | Include support for the I2O Block OSM. The Block OSM presents disk | 90 | Include support for the I2O Block OSM. The Block OSM presents disk |
95 | and other structured block devices to the operating system. If you | 91 | and other structured block devices to the operating system. If you |
@@ -102,7 +98,7 @@ config I2O_BLOCK | |||
102 | 98 | ||
103 | config I2O_SCSI | 99 | config I2O_SCSI |
104 | tristate "I2O SCSI OSM" | 100 | tristate "I2O SCSI OSM" |
105 | depends on I2O && SCSI | 101 | depends on SCSI |
106 | ---help--- | 102 | ---help--- |
107 | Allows direct SCSI access to SCSI devices on a SCSI or FibreChannel | 103 | Allows direct SCSI access to SCSI devices on a SCSI or FibreChannel |
108 | I2O controller. You can use both the SCSI and Block OSM together if | 104 | I2O controller. You can use both the SCSI and Block OSM together if |
@@ -114,7 +110,6 @@ config I2O_SCSI | |||
114 | 110 | ||
115 | config I2O_PROC | 111 | config I2O_PROC |
116 | tristate "I2O /proc support" | 112 | tristate "I2O /proc support" |
117 | depends on I2O | ||
118 | ---help--- | 113 | ---help--- |
119 | If you say Y here and to "/proc file system support", you will be | 114 | If you say Y here and to "/proc file system support", you will be |
120 | able to read I2O related information from the virtual directory | 115 | able to read I2O related information from the virtual directory |
@@ -123,5 +118,4 @@ config I2O_PROC | |||
123 | To compile this support as a module, choose M here: the | 118 | To compile this support as a module, choose M here: the |
124 | module will be called i2o_proc. | 119 | module will be called i2o_proc. |
125 | 120 | ||
126 | endmenu | 121 | endif # I2O |
127 | |||
diff --git a/drivers/message/i2o/device.c b/drivers/message/i2o/device.c index 611adc3c0f74..489d7c5c4965 100644 --- a/drivers/message/i2o/device.c +++ b/drivers/message/i2o/device.c | |||
@@ -62,7 +62,7 @@ int i2o_device_claim(struct i2o_device *dev) | |||
62 | { | 62 | { |
63 | int rc = 0; | 63 | int rc = 0; |
64 | 64 | ||
65 | down(&dev->lock); | 65 | mutex_lock(&dev->lock); |
66 | 66 | ||
67 | rc = i2o_device_issue_claim(dev, I2O_CMD_UTIL_CLAIM, I2O_CLAIM_PRIMARY); | 67 | rc = i2o_device_issue_claim(dev, I2O_CMD_UTIL_CLAIM, I2O_CLAIM_PRIMARY); |
68 | if (!rc) | 68 | if (!rc) |
@@ -72,7 +72,7 @@ int i2o_device_claim(struct i2o_device *dev) | |||
72 | pr_debug("i2o: claim of device %d failed %d\n", | 72 | pr_debug("i2o: claim of device %d failed %d\n", |
73 | dev->lct_data.tid, rc); | 73 | dev->lct_data.tid, rc); |
74 | 74 | ||
75 | up(&dev->lock); | 75 | mutex_unlock(&dev->lock); |
76 | 76 | ||
77 | return rc; | 77 | return rc; |
78 | } | 78 | } |
@@ -96,7 +96,7 @@ int i2o_device_claim_release(struct i2o_device *dev) | |||
96 | int tries; | 96 | int tries; |
97 | int rc = 0; | 97 | int rc = 0; |
98 | 98 | ||
99 | down(&dev->lock); | 99 | mutex_lock(&dev->lock); |
100 | 100 | ||
101 | /* | 101 | /* |
102 | * If the controller takes a nonblocking approach to | 102 | * If the controller takes a nonblocking approach to |
@@ -118,7 +118,7 @@ int i2o_device_claim_release(struct i2o_device *dev) | |||
118 | pr_debug("i2o: claim release of device %d failed %d\n", | 118 | pr_debug("i2o: claim release of device %d failed %d\n", |
119 | dev->lct_data.tid, rc); | 119 | dev->lct_data.tid, rc); |
120 | 120 | ||
121 | up(&dev->lock); | 121 | mutex_unlock(&dev->lock); |
122 | 122 | ||
123 | return rc; | 123 | return rc; |
124 | } | 124 | } |
@@ -198,7 +198,7 @@ static struct i2o_device *i2o_device_alloc(void) | |||
198 | return ERR_PTR(-ENOMEM); | 198 | return ERR_PTR(-ENOMEM); |
199 | 199 | ||
200 | INIT_LIST_HEAD(&dev->list); | 200 | INIT_LIST_HEAD(&dev->list); |
201 | init_MUTEX(&dev->lock); | 201 | mutex_init(&dev->lock); |
202 | 202 | ||
203 | dev->device.bus = &i2o_bus_type; | 203 | dev->device.bus = &i2o_bus_type; |
204 | dev->device.release = &i2o_device_release; | 204 | dev->device.release = &i2o_device_release; |
@@ -326,7 +326,7 @@ int i2o_device_parse_lct(struct i2o_controller *c) | |||
326 | u16 table_size; | 326 | u16 table_size; |
327 | u32 buf; | 327 | u32 buf; |
328 | 328 | ||
329 | down(&c->lct_lock); | 329 | mutex_lock(&c->lct_lock); |
330 | 330 | ||
331 | kfree(c->lct); | 331 | kfree(c->lct); |
332 | 332 | ||
@@ -335,7 +335,7 @@ int i2o_device_parse_lct(struct i2o_controller *c) | |||
335 | 335 | ||
336 | lct = c->lct = kmalloc(table_size * 4, GFP_KERNEL); | 336 | lct = c->lct = kmalloc(table_size * 4, GFP_KERNEL); |
337 | if (!lct) { | 337 | if (!lct) { |
338 | up(&c->lct_lock); | 338 | mutex_unlock(&c->lct_lock); |
339 | return -ENOMEM; | 339 | return -ENOMEM; |
340 | } | 340 | } |
341 | 341 | ||
@@ -408,7 +408,7 @@ int i2o_device_parse_lct(struct i2o_controller *c) | |||
408 | i2o_device_remove(dev); | 408 | i2o_device_remove(dev); |
409 | } | 409 | } |
410 | 410 | ||
411 | up(&c->lct_lock); | 411 | mutex_unlock(&c->lct_lock); |
412 | 412 | ||
413 | return 0; | 413 | return 0; |
414 | } | 414 | } |
diff --git a/drivers/message/i2o/exec-osm.c b/drivers/message/i2o/exec-osm.c index 5278aad92bc4..c13b9321e7ab 100644 --- a/drivers/message/i2o/exec-osm.c +++ b/drivers/message/i2o/exec-osm.c | |||
@@ -537,7 +537,7 @@ static int i2o_exec_lct_notify(struct i2o_controller *c, u32 change_ind) | |||
537 | struct device *dev; | 537 | struct device *dev; |
538 | struct i2o_message *msg; | 538 | struct i2o_message *msg; |
539 | 539 | ||
540 | down(&c->lct_lock); | 540 | mutex_lock(&c->lct_lock); |
541 | 541 | ||
542 | dev = &c->pdev->dev; | 542 | dev = &c->pdev->dev; |
543 | 543 | ||
@@ -561,7 +561,7 @@ static int i2o_exec_lct_notify(struct i2o_controller *c, u32 change_ind) | |||
561 | 561 | ||
562 | i2o_msg_post(c, msg); | 562 | i2o_msg_post(c, msg); |
563 | 563 | ||
564 | up(&c->lct_lock); | 564 | mutex_unlock(&c->lct_lock); |
565 | 565 | ||
566 | return 0; | 566 | return 0; |
567 | }; | 567 | }; |
diff --git a/drivers/message/i2o/iop.c b/drivers/message/i2o/iop.c index 3305c12372a2..a1ec16a075c6 100644 --- a/drivers/message/i2o/iop.c +++ b/drivers/message/i2o/iop.c | |||
@@ -1067,7 +1067,7 @@ struct i2o_controller *i2o_iop_alloc(void) | |||
1067 | 1067 | ||
1068 | INIT_LIST_HEAD(&c->devices); | 1068 | INIT_LIST_HEAD(&c->devices); |
1069 | spin_lock_init(&c->lock); | 1069 | spin_lock_init(&c->lock); |
1070 | init_MUTEX(&c->lct_lock); | 1070 | mutex_init(&c->lct_lock); |
1071 | 1071 | ||
1072 | device_initialize(&c->device); | 1072 | device_initialize(&c->device); |
1073 | 1073 | ||
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index bd601efa7bd1..a92b8728b90c 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig | |||
@@ -2,7 +2,11 @@ | |||
2 | # Misc strange devices | 2 | # Misc strange devices |
3 | # | 3 | # |
4 | 4 | ||
5 | menu "Misc devices" | 5 | menuconfig MISC_DEVICES |
6 | bool "Misc devices" | ||
7 | default y | ||
8 | |||
9 | if MISC_DEVICES | ||
6 | 10 | ||
7 | config IBM_ASM | 11 | config IBM_ASM |
8 | tristate "Device driver for IBM RSA service processor" | 12 | tristate "Device driver for IBM RSA service processor" |
@@ -192,4 +196,4 @@ config THINKPAD_ACPI_BAY | |||
192 | 196 | ||
193 | If you are not sure, say Y here. | 197 | If you are not sure, say Y here. |
194 | 198 | ||
195 | endmenu | 199 | endif # MISC_DEVICES |
diff --git a/drivers/misc/sony-laptop.c b/drivers/misc/sony-laptop.c index 8ee0321ef1c8..9623eaf4f89f 100644 --- a/drivers/misc/sony-laptop.c +++ b/drivers/misc/sony-laptop.c | |||
@@ -1917,7 +1917,8 @@ end: | |||
1917 | */ | 1917 | */ |
1918 | static int sony_pic_disable(struct acpi_device *device) | 1918 | static int sony_pic_disable(struct acpi_device *device) |
1919 | { | 1919 | { |
1920 | if (ACPI_FAILURE(acpi_evaluate_object(device->handle, "_DIS", 0, NULL))) | 1920 | if (ACPI_FAILURE(acpi_evaluate_object(device->handle, |
1921 | "_DIS", NULL, NULL))) | ||
1921 | return -ENXIO; | 1922 | return -ENXIO; |
1922 | 1923 | ||
1923 | dprintk("Device disabled\n"); | 1924 | dprintk("Device disabled\n"); |
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index d17d64eb7065..713ab05a87c0 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig | |||
@@ -405,22 +405,6 @@ config ATARILANCE | |||
405 | on the AMD Lance chipset: RieblCard (with or without battery), or | 405 | on the AMD Lance chipset: RieblCard (with or without battery), or |
406 | PAMCard VME (also the version by Rhotron, with different addresses). | 406 | PAMCard VME (also the version by Rhotron, with different addresses). |
407 | 407 | ||
408 | config ATARI_BIONET | ||
409 | tristate "BioNet-100 support" | ||
410 | depends on ATARI && ATARI_ACSI && BROKEN | ||
411 | help | ||
412 | Say Y to include support for BioData's BioNet-100 Ethernet adapter | ||
413 | for the ACSI port. The driver works (has to work...) with a polled | ||
414 | I/O scheme, so it's rather slow :-( | ||
415 | |||
416 | config ATARI_PAMSNET | ||
417 | tristate "PAMsNet support" | ||
418 | depends on ATARI && ATARI_ACSI && BROKEN | ||
419 | help | ||
420 | Say Y to include support for the PAMsNet Ethernet adapter for the | ||
421 | ACSI port ("ACSI node"). The driver works (has to work...) with a | ||
422 | polled I/O scheme, so it's rather slow :-( | ||
423 | |||
424 | config SUN3LANCE | 408 | config SUN3LANCE |
425 | tristate "Sun3/Sun3x on-board LANCE support" | 409 | tristate "Sun3/Sun3x on-board LANCE support" |
426 | depends on SUN3 || SUN3X | 410 | depends on SUN3 || SUN3X |
@@ -604,6 +588,12 @@ config CASSINI | |||
604 | Support for the Sun Cassini chip, aka Sun GigaSwift Ethernet. See also | 588 | Support for the Sun Cassini chip, aka Sun GigaSwift Ethernet. See also |
605 | <http://www.sun.com/products-n-solutions/hardware/docs/pdf/817-4341-10.pdf> | 589 | <http://www.sun.com/products-n-solutions/hardware/docs/pdf/817-4341-10.pdf> |
606 | 590 | ||
591 | config SUNVNET | ||
592 | tristate "Sun Virtual Network support" | ||
593 | depends on SUN_LDOMS | ||
594 | help | ||
595 | Support for virtual network devices under Sun Logical Domains. | ||
596 | |||
607 | config NET_VENDOR_3COM | 597 | config NET_VENDOR_3COM |
608 | bool "3COM cards" | 598 | bool "3COM cards" |
609 | depends on ISA || EISA || MCA || PCI | 599 | depends on ISA || EISA || MCA || PCI |
diff --git a/drivers/net/Makefile b/drivers/net/Makefile index c26b8674213c..eb4167622a6a 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile | |||
@@ -34,6 +34,7 @@ obj-$(CONFIG_SUNBMAC) += sunbmac.o | |||
34 | obj-$(CONFIG_MYRI_SBUS) += myri_sbus.o | 34 | obj-$(CONFIG_MYRI_SBUS) += myri_sbus.o |
35 | obj-$(CONFIG_SUNGEM) += sungem.o sungem_phy.o | 35 | obj-$(CONFIG_SUNGEM) += sungem.o sungem_phy.o |
36 | obj-$(CONFIG_CASSINI) += cassini.o | 36 | obj-$(CONFIG_CASSINI) += cassini.o |
37 | obj-$(CONFIG_SUNVNET) += sunvnet.o | ||
37 | 38 | ||
38 | obj-$(CONFIG_MACE) += mace.o | 39 | obj-$(CONFIG_MACE) += mace.o |
39 | obj-$(CONFIG_BMAC) += bmac.o | 40 | obj-$(CONFIG_BMAC) += bmac.o |
@@ -180,8 +181,6 @@ obj-$(CONFIG_MIPS_SIM_NET) += mipsnet.o | |||
180 | obj-$(CONFIG_SGI_IOC3_ETH) += ioc3-eth.o | 181 | obj-$(CONFIG_SGI_IOC3_ETH) += ioc3-eth.o |
181 | obj-$(CONFIG_DECLANCE) += declance.o | 182 | obj-$(CONFIG_DECLANCE) += declance.o |
182 | obj-$(CONFIG_ATARILANCE) += atarilance.o | 183 | obj-$(CONFIG_ATARILANCE) += atarilance.o |
183 | obj-$(CONFIG_ATARI_BIONET) += atari_bionet.o | ||
184 | obj-$(CONFIG_ATARI_PAMSNET) += atari_pamsnet.o | ||
185 | obj-$(CONFIG_A2065) += a2065.o | 184 | obj-$(CONFIG_A2065) += a2065.o |
186 | obj-$(CONFIG_HYDRA) += hydra.o | 185 | obj-$(CONFIG_HYDRA) += hydra.o |
187 | obj-$(CONFIG_ARIADNE) += ariadne.o | 186 | obj-$(CONFIG_ARIADNE) += ariadne.o |
diff --git a/drivers/net/Space.c b/drivers/net/Space.c index 1c3e293fbaf7..3b79c6cf21a3 100644 --- a/drivers/net/Space.c +++ b/drivers/net/Space.c | |||
@@ -75,8 +75,6 @@ extern struct net_device *atarilance_probe(int unit); | |||
75 | extern struct net_device *sun3lance_probe(int unit); | 75 | extern struct net_device *sun3lance_probe(int unit); |
76 | extern struct net_device *sun3_82586_probe(int unit); | 76 | extern struct net_device *sun3_82586_probe(int unit); |
77 | extern struct net_device *apne_probe(int unit); | 77 | extern struct net_device *apne_probe(int unit); |
78 | extern struct net_device *bionet_probe(int unit); | ||
79 | extern struct net_device *pamsnet_probe(int unit); | ||
80 | extern struct net_device *cs89x0_probe(int unit); | 78 | extern struct net_device *cs89x0_probe(int unit); |
81 | extern struct net_device *hplance_probe(int unit); | 79 | extern struct net_device *hplance_probe(int unit); |
82 | extern struct net_device *bagetlance_probe(int unit); | 80 | extern struct net_device *bagetlance_probe(int unit); |
@@ -264,12 +262,6 @@ static struct devprobe2 m68k_probes[] __initdata = { | |||
264 | #ifdef CONFIG_APNE /* A1200 PCMCIA NE2000 */ | 262 | #ifdef CONFIG_APNE /* A1200 PCMCIA NE2000 */ |
265 | {apne_probe, 0}, | 263 | {apne_probe, 0}, |
266 | #endif | 264 | #endif |
267 | #ifdef CONFIG_ATARI_BIONET /* Atari Bionet Ethernet board */ | ||
268 | {bionet_probe, 0}, | ||
269 | #endif | ||
270 | #ifdef CONFIG_ATARI_PAMSNET /* Atari PAMsNet Ethernet board */ | ||
271 | {pamsnet_probe, 0}, | ||
272 | #endif | ||
273 | #ifdef CONFIG_MVME147_NET /* MVME147 internal Ethernet */ | 265 | #ifdef CONFIG_MVME147_NET /* MVME147 internal Ethernet */ |
274 | {mvme147lance_probe, 0}, | 266 | {mvme147lance_probe, 0}, |
275 | #endif | 267 | #endif |
diff --git a/drivers/net/atari_bionet.c b/drivers/net/atari_bionet.c deleted file mode 100644 index 3d87bd2b4194..000000000000 --- a/drivers/net/atari_bionet.c +++ /dev/null | |||
@@ -1,675 +0,0 @@ | |||
1 | /* bionet.c BioNet-100 device driver for linux68k. | ||
2 | * | ||
3 | * Version: @(#)bionet.c 1.0 02/06/96 | ||
4 | * | ||
5 | * Author: Hartmut Laue <laue@ifk-mp.uni-kiel.de> | ||
6 | * and Torsten Narjes <narjes@ifk-mp.uni-kiel.de> | ||
7 | * | ||
8 | * Little adaptions for integration into pl7 by Roman Hodek | ||
9 | * | ||
10 | * Some changes in bionet_poll_rx by Karl-Heinz Lohner | ||
11 | * | ||
12 | What is it ? | ||
13 | ------------ | ||
14 | This driver controls the BIONET-100 LAN-Adapter which connects | ||
15 | an ATARI ST/TT via the ACSI-port to an Ethernet-based network. | ||
16 | |||
17 | This version can be compiled as a loadable module (See the | ||
18 | compile command at the bottom of this file). | ||
19 | At load time, you can optionally set the debugging level and the | ||
20 | fastest response time on the command line of 'insmod'. | ||
21 | |||
22 | 'bionet_debug' | ||
23 | controls the amount of diagnostic messages: | ||
24 | 0 : no messages | ||
25 | >0 : see code for meaning of printed messages | ||
26 | |||
27 | 'bionet_min_poll_time' (always >=1) | ||
28 | gives the time (in jiffies) between polls. Low values | ||
29 | increase the system load (beware!) | ||
30 | |||
31 | When loaded, a net device with the name 'bio0' becomes available, | ||
32 | which can be controlled with the usual 'ifconfig' command. | ||
33 | |||
34 | It is possible to compile this driver into the kernel like other | ||
35 | (net) drivers. For this purpose, some source files (e.g. config-files | ||
36 | makefiles, Space.c) must be changed accordingly. (You may refer to | ||
37 | other drivers how to do it.) In this case, the device will be detected | ||
38 | at boot time and (probably) appear as 'eth0'. | ||
39 | |||
40 | This code is based on several sources: | ||
41 | - The driver code for a parallel port ethernet adapter by | ||
42 | Donald Becker (see file 'atp.c' from the PC linux distribution) | ||
43 | - The ACSI code by Roman Hodek for the ATARI-ACSI harddisk support | ||
44 | and DMA handling. | ||
45 | - Very limited information about moving packets in and out of the | ||
46 | BIONET-adapter from the TCP package for TOS by BioData GmbH. | ||
47 | |||
48 | Theory of Operation | ||
49 | ------------------- | ||
50 | Because the ATARI DMA port is usually shared between several | ||
51 | devices (eg. harddisk, floppy) we cannot block the ACSI bus | ||
52 | while waiting for interrupts. Therefore we use a polling mechanism | ||
53 | to fetch packets from the adapter. For the same reason, we send | ||
54 | packets without checking that the previous packet has been sent to | ||
55 | the LAN. We rely on the higher levels of the networking code to detect | ||
56 | missing packets and resend them. | ||
57 | |||
58 | Before we access the ATARI DMA controller, we check if another | ||
59 | process is using the DMA. If not, we lock the DMA, perform one or | ||
60 | more packet transfers and unlock the DMA before returning. | ||
61 | We do not use 'stdma_lock' unconditionally because it is unclear | ||
62 | if the networking code can be set to sleep, which will happen if | ||
63 | another (possibly slow) device is using the DMA controller. | ||
64 | |||
65 | The polling is done via timer interrupts which periodically | ||
66 | 'simulate' an interrupt from the Ethernet adapter. The time (in jiffies) | ||
67 | between polls varies depending on an estimate of the net activity. | ||
68 | The allowed range is given by the variable 'bionet_min_poll_time' | ||
69 | for the lower (fastest) limit and the constant 'MAX_POLL_TIME' | ||
70 | for the higher (slowest) limit. | ||
71 | |||
72 | Whenever a packet arrives, we switch to fastest response by setting | ||
73 | the polling time to its lowest limit. If the following poll fails, | ||
74 | because no packets have arrived, we increase the time for the next | ||
75 | poll. When the net activity is low, the polling time effectively | ||
76 | stays at its maximum value, resulting in the lowest load for the | ||
77 | machine. | ||
78 | */ | ||
79 | |||
80 | #define MAX_POLL_TIME 10 | ||
81 | |||
82 | static char version[] = | ||
83 | "bionet.c:v1.0 06-feb-96 (c) Hartmut Laue.\n"; | ||
84 | |||
85 | #include <linux/module.h> | ||
86 | |||
87 | #include <linux/errno.h> | ||
88 | #include <linux/kernel.h> | ||
89 | #include <linux/jiffies.h> | ||
90 | #include <linux/types.h> | ||
91 | #include <linux/fcntl.h> | ||
92 | #include <linux/interrupt.h> | ||
93 | #include <linux/ioport.h> | ||
94 | #include <linux/in.h> | ||
95 | #include <linux/slab.h> | ||
96 | #include <linux/string.h> | ||
97 | #include <linux/delay.h> | ||
98 | #include <linux/timer.h> | ||
99 | #include <linux/init.h> | ||
100 | #include <linux/bitops.h> | ||
101 | |||
102 | #include <linux/netdevice.h> | ||
103 | #include <linux/etherdevice.h> | ||
104 | #include <linux/skbuff.h> | ||
105 | |||
106 | #include <asm/setup.h> | ||
107 | #include <asm/pgtable.h> | ||
108 | #include <asm/system.h> | ||
109 | #include <asm/io.h> | ||
110 | #include <asm/dma.h> | ||
111 | #include <asm/atarihw.h> | ||
112 | #include <asm/atariints.h> | ||
113 | #include <asm/atari_acsi.h> | ||
114 | #include <asm/atari_stdma.h> | ||
115 | |||
116 | |||
117 | /* use 0 for production, 1 for verification, >2 for debug | ||
118 | */ | ||
119 | #ifndef NET_DEBUG | ||
120 | #define NET_DEBUG 0 | ||
121 | #endif | ||
122 | /* | ||
123 | * Global variable 'bionet_debug'. Can be set at load time by 'insmod' | ||
124 | */ | ||
125 | unsigned int bionet_debug = NET_DEBUG; | ||
126 | module_param(bionet_debug, int, 0); | ||
127 | MODULE_PARM_DESC(bionet_debug, "bionet debug level (0-2)"); | ||
128 | MODULE_LICENSE("GPL"); | ||
129 | |||
130 | static unsigned int bionet_min_poll_time = 2; | ||
131 | |||
132 | |||
133 | /* Information that need to be kept for each board. | ||
134 | */ | ||
135 | struct net_local { | ||
136 | struct net_device_stats stats; | ||
137 | long open_time; /* for debugging */ | ||
138 | int poll_time; /* polling time varies with net load */ | ||
139 | }; | ||
140 | |||
141 | static struct nic_pkt_s { /* packet format */ | ||
142 | unsigned char status; | ||
143 | unsigned char dummy; | ||
144 | unsigned char l_lo, l_hi; | ||
145 | unsigned char buffer[3000]; | ||
146 | } *nic_packet; | ||
147 | unsigned char *phys_nic_packet; | ||
148 | |||
149 | /* Index to functions, as function prototypes. | ||
150 | */ | ||
151 | static int bionet_open(struct net_device *dev); | ||
152 | static int bionet_send_packet(struct sk_buff *skb, struct net_device *dev); | ||
153 | static void bionet_poll_rx(struct net_device *); | ||
154 | static int bionet_close(struct net_device *dev); | ||
155 | static struct net_device_stats *net_get_stats(struct net_device *dev); | ||
156 | static void bionet_tick(unsigned long); | ||
157 | |||
158 | static DEFINE_TIMER(bionet_timer, bionet_tick, 0, 0); | ||
159 | |||
160 | #define STRAM_ADDR(a) (((a) & 0xff000000) == 0) | ||
161 | |||
162 | /* The following routines access the ethernet board connected to the | ||
163 | * ACSI port via the st_dma chip. | ||
164 | */ | ||
165 | #define NODE_ADR 0x60 | ||
166 | |||
167 | #define C_READ 8 | ||
168 | #define C_WRITE 0x0a | ||
169 | #define C_GETEA 0x0f | ||
170 | #define C_SETCR 0x0e | ||
171 | |||
172 | static int | ||
173 | sendcmd(unsigned int a0, unsigned int mod, unsigned int cmd) { | ||
174 | unsigned int c; | ||
175 | |||
176 | dma_wd.dma_mode_status = (mod | ((a0) ? 2 : 0) | 0x88); | ||
177 | dma_wd.fdc_acces_seccount = cmd; | ||
178 | dma_wd.dma_mode_status = (mod | 0x8a); | ||
179 | |||
180 | if( !acsi_wait_for_IRQ(HZ/2) ) /* wait for cmd ack */ | ||
181 | return -1; /* timeout */ | ||
182 | |||
183 | c = dma_wd.fdc_acces_seccount; | ||
184 | return (c & 0xff); | ||
185 | } | ||
186 | |||
187 | |||
188 | static void | ||
189 | set_status(int cr) { | ||
190 | sendcmd(0,0x100,NODE_ADR | C_SETCR); /* CMD: SET CR */ | ||
191 | sendcmd(1,0x100,cr); | ||
192 | |||
193 | dma_wd.dma_mode_status = 0x80; | ||
194 | } | ||
195 | |||
196 | static int | ||
197 | get_status(unsigned char *adr) { | ||
198 | int i,c; | ||
199 | |||
200 | DISABLE_IRQ(); | ||
201 | c = sendcmd(0,0x00,NODE_ADR | C_GETEA); /* CMD: GET ETH ADR*/ | ||
202 | if( c < 0 ) goto gsend; | ||
203 | |||
204 | /* now read status bytes */ | ||
205 | |||
206 | for (i=0; i<6; i++) { | ||
207 | dma_wd.fdc_acces_seccount = 0; /* request next byte */ | ||
208 | |||
209 | if( !acsi_wait_for_IRQ(HZ/2) ) { /* wait for cmd ack */ | ||
210 | c = -1; | ||
211 | goto gsend; /* timeout */ | ||
212 | } | ||
213 | c = dma_wd.fdc_acces_seccount; | ||
214 | *adr++ = (unsigned char)c; | ||
215 | } | ||
216 | c = 1; | ||
217 | gsend: | ||
218 | dma_wd.dma_mode_status = 0x80; | ||
219 | return c; | ||
220 | } | ||
221 | |||
222 | static irqreturn_t | ||
223 | bionet_intr(int irq, void *data) { | ||
224 | return IRQ_HANDLED; | ||
225 | } | ||
226 | |||
227 | |||
228 | static int | ||
229 | get_frame(unsigned long paddr, int odd) { | ||
230 | int c; | ||
231 | unsigned long flags; | ||
232 | |||
233 | DISABLE_IRQ(); | ||
234 | local_irq_save(flags); | ||
235 | |||
236 | dma_wd.dma_mode_status = 0x9a; | ||
237 | dma_wd.dma_mode_status = 0x19a; | ||
238 | dma_wd.dma_mode_status = 0x9a; | ||
239 | dma_wd.fdc_acces_seccount = 0x04; /* sector count (was 5) */ | ||
240 | dma_wd.dma_lo = (unsigned char)paddr; | ||
241 | paddr >>= 8; | ||
242 | dma_wd.dma_md = (unsigned char)paddr; | ||
243 | paddr >>= 8; | ||
244 | dma_wd.dma_hi = (unsigned char)paddr; | ||
245 | local_irq_restore(flags); | ||
246 | |||
247 | c = sendcmd(0,0x00,NODE_ADR | C_READ); /* CMD: READ */ | ||
248 | if( c < 128 ) goto rend; | ||
249 | |||
250 | /* now read block */ | ||
251 | |||
252 | c = sendcmd(1,0x00,odd); /* odd flag for address shift */ | ||
253 | dma_wd.dma_mode_status = 0x0a; | ||
254 | |||
255 | if( !acsi_wait_for_IRQ(100) ) { /* wait for DMA to complete */ | ||
256 | c = -1; | ||
257 | goto rend; | ||
258 | } | ||
259 | dma_wd.dma_mode_status = 0x8a; | ||
260 | dma_wd.dma_mode_status = 0x18a; | ||
261 | dma_wd.dma_mode_status = 0x8a; | ||
262 | c = dma_wd.fdc_acces_seccount; | ||
263 | |||
264 | dma_wd.dma_mode_status = 0x88; | ||
265 | c = dma_wd.fdc_acces_seccount; | ||
266 | c = 1; | ||
267 | |||
268 | rend: | ||
269 | dma_wd.dma_mode_status = 0x80; | ||
270 | udelay(40); | ||
271 | acsi_wait_for_noIRQ(20); | ||
272 | return c; | ||
273 | } | ||
274 | |||
275 | |||
276 | static int | ||
277 | hardware_send_packet(unsigned long paddr, int cnt) { | ||
278 | unsigned int c; | ||
279 | unsigned long flags; | ||
280 | |||
281 | DISABLE_IRQ(); | ||
282 | local_irq_save(flags); | ||
283 | |||
284 | dma_wd.dma_mode_status = 0x19a; | ||
285 | dma_wd.dma_mode_status = 0x9a; | ||
286 | dma_wd.dma_mode_status = 0x19a; | ||
287 | dma_wd.dma_lo = (unsigned char)paddr; | ||
288 | paddr >>= 8; | ||
289 | dma_wd.dma_md = (unsigned char)paddr; | ||
290 | paddr >>= 8; | ||
291 | dma_wd.dma_hi = (unsigned char)paddr; | ||
292 | |||
293 | dma_wd.fdc_acces_seccount = 0x4; /* sector count */ | ||
294 | local_irq_restore(flags); | ||
295 | |||
296 | c = sendcmd(0,0x100,NODE_ADR | C_WRITE); /* CMD: WRITE */ | ||
297 | c = sendcmd(1,0x100,cnt&0xff); | ||
298 | c = sendcmd(1,0x100,cnt>>8); | ||
299 | |||
300 | /* now write block */ | ||
301 | |||
302 | dma_wd.dma_mode_status = 0x10a; /* DMA enable */ | ||
303 | if( !acsi_wait_for_IRQ(100) ) /* wait for DMA to complete */ | ||
304 | goto end; | ||
305 | |||
306 | dma_wd.dma_mode_status = 0x19a; /* DMA disable ! */ | ||
307 | c = dma_wd.fdc_acces_seccount; | ||
308 | |||
309 | end: | ||
310 | c = sendcmd(1,0x100,0); | ||
311 | c = sendcmd(1,0x100,0); | ||
312 | |||
313 | dma_wd.dma_mode_status = 0x180; | ||
314 | udelay(40); | ||
315 | acsi_wait_for_noIRQ(20); | ||
316 | return( c & 0x02); | ||
317 | } | ||
318 | |||
319 | |||
320 | /* Check for a network adaptor of this type, and return '0' if one exists. | ||
321 | */ | ||
322 | struct net_device * __init bionet_probe(int unit) | ||
323 | { | ||
324 | struct net_device *dev; | ||
325 | unsigned char station_addr[6]; | ||
326 | static unsigned version_printed; | ||
327 | static int no_more_found; /* avoid "Probing for..." printed 4 times */ | ||
328 | int i; | ||
329 | int err; | ||
330 | |||
331 | if (!MACH_IS_ATARI || no_more_found) | ||
332 | return ERR_PTR(-ENODEV); | ||
333 | |||
334 | dev = alloc_etherdev(sizeof(struct net_local)); | ||
335 | if (!dev) | ||
336 | return ERR_PTR(-ENOMEM); | ||
337 | if (unit >= 0) { | ||
338 | sprintf(dev->name, "eth%d", unit); | ||
339 | netdev_boot_setup_check(dev); | ||
340 | } | ||
341 | SET_MODULE_OWNER(dev); | ||
342 | |||
343 | printk("Probing for BioNet 100 Adapter...\n"); | ||
344 | |||
345 | stdma_lock(bionet_intr, NULL); | ||
346 | i = get_status(station_addr); /* Read the station address PROM. */ | ||
347 | ENABLE_IRQ(); | ||
348 | stdma_release(); | ||
349 | |||
350 | /* Check the first three octets of the S.A. for the manufactor's code. | ||
351 | */ | ||
352 | |||
353 | if( i < 0 | ||
354 | || station_addr[0] != 'B' | ||
355 | || station_addr[1] != 'I' | ||
356 | || station_addr[2] != 'O' ) { | ||
357 | no_more_found = 1; | ||
358 | printk( "No BioNet 100 found.\n" ); | ||
359 | free_netdev(dev); | ||
360 | return ERR_PTR(-ENODEV); | ||
361 | } | ||
362 | |||
363 | if (bionet_debug > 0 && version_printed++ == 0) | ||
364 | printk(version); | ||
365 | |||
366 | printk("%s: %s found, eth-addr: %02x-%02x-%02x:%02x-%02x-%02x.\n", | ||
367 | dev->name, "BioNet 100", | ||
368 | station_addr[0], station_addr[1], station_addr[2], | ||
369 | station_addr[3], station_addr[4], station_addr[5]); | ||
370 | |||
371 | /* Initialize the device structure. */ | ||
372 | |||
373 | nic_packet = (struct nic_pkt_s *)acsi_buffer; | ||
374 | phys_nic_packet = (unsigned char *)phys_acsi_buffer; | ||
375 | if (bionet_debug > 0) { | ||
376 | printk("nic_packet at 0x%p, phys at 0x%p\n", | ||
377 | nic_packet, phys_nic_packet ); | ||
378 | } | ||
379 | |||
380 | dev->open = bionet_open; | ||
381 | dev->stop = bionet_close; | ||
382 | dev->hard_start_xmit = bionet_send_packet; | ||
383 | dev->get_stats = net_get_stats; | ||
384 | |||
385 | /* Fill in the fields of the device structure with ethernet-generic | ||
386 | * values. This should be in a common file instead of per-driver. | ||
387 | */ | ||
388 | |||
389 | for (i = 0; i < ETH_ALEN; i++) { | ||
390 | #if 0 | ||
391 | dev->broadcast[i] = 0xff; | ||
392 | #endif | ||
393 | dev->dev_addr[i] = station_addr[i]; | ||
394 | } | ||
395 | err = register_netdev(dev); | ||
396 | if (!err) | ||
397 | return dev; | ||
398 | free_netdev(dev); | ||
399 | return ERR_PTR(err); | ||
400 | } | ||
401 | |||
402 | /* Open/initialize the board. This is called (in the current kernel) | ||
403 | sometime after booting when the 'ifconfig' program is run. | ||
404 | |||
405 | This routine should set everything up anew at each open, even | ||
406 | registers that "should" only need to be set once at boot, so that | ||
407 | there is non-reboot way to recover if something goes wrong. | ||
408 | */ | ||
409 | static int | ||
410 | bionet_open(struct net_device *dev) { | ||
411 | struct net_local *lp = netdev_priv(dev); | ||
412 | |||
413 | if (bionet_debug > 0) | ||
414 | printk("bionet_open\n"); | ||
415 | stdma_lock(bionet_intr, NULL); | ||
416 | |||
417 | /* Reset the hardware here. | ||
418 | */ | ||
419 | set_status(4); | ||
420 | lp->open_time = 0; /*jiffies*/ | ||
421 | lp->poll_time = MAX_POLL_TIME; | ||
422 | |||
423 | dev->tbusy = 0; | ||
424 | dev->interrupt = 0; | ||
425 | dev->start = 1; | ||
426 | |||
427 | stdma_release(); | ||
428 | bionet_timer.data = (long)dev; | ||
429 | bionet_timer.expires = jiffies + lp->poll_time; | ||
430 | add_timer(&bionet_timer); | ||
431 | return 0; | ||
432 | } | ||
433 | |||
434 | static int | ||
435 | bionet_send_packet(struct sk_buff *skb, struct net_device *dev) { | ||
436 | struct net_local *lp = netdev_priv(dev); | ||
437 | unsigned long flags; | ||
438 | |||
439 | /* Block a timer-based transmit from overlapping. This could better be | ||
440 | * done with atomic_swap(1, dev->tbusy), but set_bit() works as well. | ||
441 | */ | ||
442 | local_irq_save(flags); | ||
443 | |||
444 | if (stdma_islocked()) { | ||
445 | local_irq_restore(flags); | ||
446 | lp->stats.tx_errors++; | ||
447 | } | ||
448 | else { | ||
449 | int length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; | ||
450 | unsigned long buf = virt_to_phys(skb->data); | ||
451 | int stat; | ||
452 | |||
453 | stdma_lock(bionet_intr, NULL); | ||
454 | local_irq_restore(flags); | ||
455 | if( !STRAM_ADDR(buf+length-1) ) { | ||
456 | skb_copy_from_linear_data(skb, nic_packet->buffer, | ||
457 | length); | ||
458 | buf = (unsigned long)&((struct nic_pkt_s *)phys_nic_packet)->buffer; | ||
459 | } | ||
460 | |||
461 | if (bionet_debug >1) { | ||
462 | u_char *data = nic_packet->buffer, *p; | ||
463 | int i; | ||
464 | |||
465 | printk( "%s: TX pkt type 0x%4x from ", dev->name, | ||
466 | ((u_short *)data)[6]); | ||
467 | |||
468 | for( p = &data[6], i = 0; i < 6; i++ ) | ||
469 | printk("%02x%s", *p++,i != 5 ? ":" : "" ); | ||
470 | printk(" to "); | ||
471 | |||
472 | for( p = data, i = 0; i < 6; i++ ) | ||
473 | printk("%02x%s", *p++,i != 5 ? ":" : "" "\n" ); | ||
474 | |||
475 | printk( "%s: ", dev->name ); | ||
476 | printk(" data %02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x" | ||
477 | " %02x%02x%02x%02x len %d\n", | ||
478 | data[12], data[13], data[14], data[15], data[16], data[17], data[18], data[19], | ||
479 | data[20], data[21], data[22], data[23], data[24], data[25], data[26], data[27], | ||
480 | data[28], data[29], data[30], data[31], data[32], data[33], | ||
481 | length ); | ||
482 | } | ||
483 | dma_cache_maintenance(buf, length, 1); | ||
484 | |||
485 | stat = hardware_send_packet(buf, length); | ||
486 | ENABLE_IRQ(); | ||
487 | stdma_release(); | ||
488 | |||
489 | dev->trans_start = jiffies; | ||
490 | dev->tbusy = 0; | ||
491 | lp->stats.tx_packets++; | ||
492 | lp->stats.tx_bytes+=length; | ||
493 | } | ||
494 | dev_kfree_skb(skb); | ||
495 | |||
496 | return 0; | ||
497 | } | ||
498 | |||
499 | /* We have a good packet(s), get it/them out of the buffers. | ||
500 | */ | ||
501 | static void | ||
502 | bionet_poll_rx(struct net_device *dev) { | ||
503 | struct net_local *lp = netdev_priv(dev); | ||
504 | int boguscount = 10; | ||
505 | int pkt_len, status; | ||
506 | unsigned long flags; | ||
507 | |||
508 | local_irq_save(flags); | ||
509 | /* ++roman: Take care at locking the ST-DMA... This must be done with ints | ||
510 | * off, since otherwise an int could slip in between the question and the | ||
511 | * locking itself, and then we'd go to sleep... And locking itself is | ||
512 | * necessary to keep the floppy_change timer from working with ST-DMA | ||
513 | * registers. */ | ||
514 | if (stdma_islocked()) { | ||
515 | local_irq_restore(flags); | ||
516 | return; | ||
517 | } | ||
518 | stdma_lock(bionet_intr, NULL); | ||
519 | DISABLE_IRQ(); | ||
520 | local_irq_restore(flags); | ||
521 | |||
522 | if( lp->poll_time < MAX_POLL_TIME ) lp->poll_time++; | ||
523 | |||
524 | while(boguscount--) { | ||
525 | status = get_frame((unsigned long)phys_nic_packet, 0); | ||
526 | |||
527 | if( status == 0 ) break; | ||
528 | |||
529 | /* Good packet... */ | ||
530 | |||
531 | dma_cache_maintenance((unsigned long)phys_nic_packet, 1520, 0); | ||
532 | |||
533 | pkt_len = (nic_packet->l_hi << 8) | nic_packet->l_lo; | ||
534 | |||
535 | lp->poll_time = bionet_min_poll_time; /* fast poll */ | ||
536 | if( pkt_len >= 60 && pkt_len <= 1520 ) { | ||
537 | /* ^^^^ war 1514 KHL */ | ||
538 | /* Malloc up new buffer. | ||
539 | */ | ||
540 | struct sk_buff *skb = dev_alloc_skb( pkt_len + 2 ); | ||
541 | if (skb == NULL) { | ||
542 | printk("%s: Memory squeeze, dropping packet.\n", | ||
543 | dev->name); | ||
544 | lp->stats.rx_dropped++; | ||
545 | break; | ||
546 | } | ||
547 | |||
548 | skb_reserve( skb, 2 ); /* 16 Byte align */ | ||
549 | skb_put( skb, pkt_len ); /* make room */ | ||
550 | |||
551 | /* 'skb->data' points to the start of sk_buff data area. | ||
552 | */ | ||
553 | skb_copy_to_linear_data(skb, nic_packet->buffer, | ||
554 | pkt_len); | ||
555 | skb->protocol = eth_type_trans( skb, dev ); | ||
556 | netif_rx(skb); | ||
557 | dev->last_rx = jiffies; | ||
558 | lp->stats.rx_packets++; | ||
559 | lp->stats.rx_bytes+=pkt_len; | ||
560 | |||
561 | /* If any worth-while packets have been received, dev_rint() | ||
562 | has done a mark_bh(INET_BH) for us and will work on them | ||
563 | when we get to the bottom-half routine. | ||
564 | */ | ||
565 | |||
566 | if (bionet_debug >1) { | ||
567 | u_char *data = nic_packet->buffer, *p; | ||
568 | int i; | ||
569 | |||
570 | printk( "%s: RX pkt type 0x%4x from ", dev->name, | ||
571 | ((u_short *)data)[6]); | ||
572 | |||
573 | |||
574 | for( p = &data[6], i = 0; i < 6; i++ ) | ||
575 | printk("%02x%s", *p++,i != 5 ? ":" : "" ); | ||
576 | printk(" to "); | ||
577 | for( p = data, i = 0; i < 6; i++ ) | ||
578 | printk("%02x%s", *p++,i != 5 ? ":" : "" "\n" ); | ||
579 | |||
580 | printk( "%s: ", dev->name ); | ||
581 | printk(" data %02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x" | ||
582 | " %02x%02x%02x%02x len %d\n", | ||
583 | data[12], data[13], data[14], data[15], data[16], data[17], data[18], data[19], | ||
584 | data[20], data[21], data[22], data[23], data[24], data[25], data[26], data[27], | ||
585 | data[28], data[29], data[30], data[31], data[32], data[33], | ||
586 | pkt_len ); | ||
587 | } | ||
588 | } | ||
589 | else { | ||
590 | printk(" Packet has wrong length: %04d bytes\n", pkt_len); | ||
591 | lp->stats.rx_errors++; | ||
592 | } | ||
593 | } | ||
594 | stdma_release(); | ||
595 | ENABLE_IRQ(); | ||
596 | return; | ||
597 | } | ||
598 | |||
599 | /* bionet_tick: called by bionet_timer. Reads packets from the adapter, | ||
600 | * passes them to the higher layers and restarts the timer. | ||
601 | */ | ||
602 | static void | ||
603 | bionet_tick(unsigned long data) { | ||
604 | struct net_device *dev = (struct net_device *)data; | ||
605 | struct net_local *lp = netdev_priv(dev); | ||
606 | |||
607 | if( bionet_debug > 0 && (lp->open_time++ & 7) == 8 ) | ||
608 | printk("bionet_tick: %ld\n", lp->open_time); | ||
609 | |||
610 | if( !stdma_islocked() ) bionet_poll_rx(dev); | ||
611 | |||
612 | bionet_timer.expires = jiffies + lp->poll_time; | ||
613 | add_timer(&bionet_timer); | ||
614 | } | ||
615 | |||
616 | /* The inverse routine to bionet_open(). | ||
617 | */ | ||
618 | static int | ||
619 | bionet_close(struct net_device *dev) { | ||
620 | struct net_local *lp = netdev_priv(dev); | ||
621 | |||
622 | if (bionet_debug > 0) | ||
623 | printk("bionet_close, open_time=%ld\n", lp->open_time); | ||
624 | del_timer(&bionet_timer); | ||
625 | stdma_lock(bionet_intr, NULL); | ||
626 | |||
627 | set_status(0); | ||
628 | lp->open_time = 0; | ||
629 | |||
630 | dev->tbusy = 1; | ||
631 | dev->start = 0; | ||
632 | |||
633 | stdma_release(); | ||
634 | return 0; | ||
635 | } | ||
636 | |||
637 | /* Get the current statistics. | ||
638 | This may be called with the card open or closed. | ||
639 | */ | ||
640 | static struct net_device_stats *net_get_stats(struct net_device *dev) | ||
641 | { | ||
642 | struct net_local *lp = netdev_priv(dev); | ||
643 | return &lp->stats; | ||
644 | } | ||
645 | |||
646 | |||
647 | #ifdef MODULE | ||
648 | |||
649 | static struct net_device *bio_dev; | ||
650 | |||
651 | int init_module(void) | ||
652 | { | ||
653 | bio_dev = bionet_probe(-1); | ||
654 | if (IS_ERR(bio_dev)) | ||
655 | return PTR_ERR(bio_dev); | ||
656 | return 0; | ||
657 | } | ||
658 | |||
659 | void cleanup_module(void) | ||
660 | { | ||
661 | unregister_netdev(bio_dev); | ||
662 | free_netdev(bio_dev); | ||
663 | } | ||
664 | |||
665 | #endif /* MODULE */ | ||
666 | |||
667 | /* Local variables: | ||
668 | * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/include | ||
669 | -b m68k-linuxaout -Wall -Wstrict-prototypes -O2 | ||
670 | -fomit-frame-pointer -pipe -DMODULE -I../../net/inet -c bionet.c" | ||
671 | * version-control: t | ||
672 | * kept-new-versions: 5 | ||
673 | * tab-width: 8 | ||
674 | * End: | ||
675 | */ | ||
diff --git a/drivers/net/atari_pamsnet.c b/drivers/net/atari_pamsnet.c deleted file mode 100644 index f7356374a2e7..000000000000 --- a/drivers/net/atari_pamsnet.c +++ /dev/null | |||
@@ -1,878 +0,0 @@ | |||
1 | /* atari_pamsnet.c PAMsNet device driver for linux68k. | ||
2 | * | ||
3 | * Version: @(#)PAMsNet.c 0.2ß 03/31/96 | ||
4 | * | ||
5 | * Author: Torsten Lang <Torsten.Lang@ap.physik.uni-giessen.de> | ||
6 | * <Torsten.Lang@jung.de> | ||
7 | * | ||
8 | * This driver is based on my driver PAMSDMA.c for MiNT-Net and | ||
9 | * on the driver bionet.c written by | ||
10 | * Hartmut Laue <laue@ifk-mp.uni-kiel.de> | ||
11 | * and Torsten Narjes <narjes@ifk-mp.uni-kiel.de> | ||
12 | * | ||
13 | * Little adaptions for integration into pl7 by Roman Hodek | ||
14 | * | ||
15 | What is it ? | ||
16 | ------------ | ||
17 | This driver controls the PAMsNet LAN-Adapter which connects | ||
18 | an ATARI ST/TT via the ACSI-port to an Ethernet-based network. | ||
19 | |||
20 | This version can be compiled as a loadable module (See the | ||
21 | compile command at the bottom of this file). | ||
22 | At load time, you can optionally set the debugging level and the | ||
23 | fastest response time on the command line of 'insmod'. | ||
24 | |||
25 | 'pamsnet_debug' | ||
26 | controls the amount of diagnostic messages: | ||
27 | 0 : no messages | ||
28 | >0 : see code for meaning of printed messages | ||
29 | |||
30 | 'pamsnet_min_poll_time' (always >=1) | ||
31 | gives the time (in jiffies) between polls. Low values | ||
32 | increase the system load (beware!) | ||
33 | |||
34 | When loaded, a net device with the name 'eth?' becomes available, | ||
35 | which can be controlled with the usual 'ifconfig' command. | ||
36 | |||
37 | It is possible to compile this driver into the kernel like other | ||
38 | (net) drivers. For this purpose, some source files (e.g. config-files | ||
39 | makefiles, Space.c) must be changed accordingly. (You may refer to | ||
40 | other drivers how to do it.) In this case, the device will be detected | ||
41 | at boot time and (probably) appear as 'eth0'. | ||
42 | |||
43 | Theory of Operation | ||
44 | ------------------- | ||
45 | Because the ATARI DMA port is usually shared between several | ||
46 | devices (eg. harddisk, floppy) we cannot block the ACSI bus | ||
47 | while waiting for interrupts. Therefore we use a polling mechanism | ||
48 | to fetch packets from the adapter. For the same reason, we send | ||
49 | packets without checking that the previous packet has been sent to | ||
50 | the LAN. We rely on the higher levels of the networking code to detect | ||
51 | missing packets and resend them. | ||
52 | |||
53 | Before we access the ATARI DMA controller, we check if another | ||
54 | process is using the DMA. If not, we lock the DMA, perform one or | ||
55 | more packet transfers and unlock the DMA before returning. | ||
56 | We do not use 'stdma_lock' unconditionally because it is unclear | ||
57 | if the networking code can be set to sleep, which will happen if | ||
58 | another (possibly slow) device is using the DMA controller. | ||
59 | |||
60 | The polling is done via timer interrupts which periodically | ||
61 | 'simulate' an interrupt from the Ethernet adapter. The time (in jiffies) | ||
62 | between polls varies depending on an estimate of the net activity. | ||
63 | The allowed range is given by the variable 'bionet_min_poll_time' | ||
64 | for the lower (fastest) limit and the constant 'MAX_POLL_TIME' | ||
65 | for the higher (slowest) limit. | ||
66 | |||
67 | Whenever a packet arrives, we switch to fastest response by setting | ||
68 | the polling time to its lowest limit. If the following poll fails, | ||
69 | because no packets have arrived, we increase the time for the next | ||
70 | poll. When the net activity is low, the polling time effectively | ||
71 | stays at its maximum value, resulting in the lowest load for the | ||
72 | machine. | ||
73 | */ | ||
74 | |||
75 | #define MAX_POLL_TIME 10 | ||
76 | |||
77 | static char *version = | ||
78 | "pamsnet.c:v0.2beta 30-mar-96 (c) Torsten Lang.\n"; | ||
79 | |||
80 | #include <linux/module.h> | ||
81 | |||
82 | #include <linux/kernel.h> | ||
83 | #include <linux/jiffies.h> | ||
84 | #include <linux/types.h> | ||
85 | #include <linux/fcntl.h> | ||
86 | #include <linux/interrupt.h> | ||
87 | #include <linux/ioport.h> | ||
88 | #include <linux/in.h> | ||
89 | #include <linux/slab.h> | ||
90 | #include <linux/string.h> | ||
91 | #include <linux/bitops.h> | ||
92 | #include <asm/system.h> | ||
93 | #include <asm/pgtable.h> | ||
94 | #include <asm/io.h> | ||
95 | #include <asm/dma.h> | ||
96 | #include <linux/errno.h> | ||
97 | #include <asm/atarihw.h> | ||
98 | #include <asm/atariints.h> | ||
99 | #include <asm/atari_stdma.h> | ||
100 | #include <asm/atari_acsi.h> | ||
101 | |||
102 | #include <linux/delay.h> | ||
103 | #include <linux/timer.h> | ||
104 | #include <linux/init.h> | ||
105 | |||
106 | #include <linux/netdevice.h> | ||
107 | #include <linux/etherdevice.h> | ||
108 | #include <linux/skbuff.h> | ||
109 | |||
110 | #undef READ | ||
111 | #undef WRITE | ||
112 | |||
113 | /* use 0 for production, 1 for verification, >2 for debug | ||
114 | */ | ||
115 | #ifndef NET_DEBUG | ||
116 | #define NET_DEBUG 0 | ||
117 | #endif | ||
118 | /* | ||
119 | * Global variable 'pamsnet_debug'. Can be set at load time by 'insmod' | ||
120 | */ | ||
121 | unsigned int pamsnet_debug = NET_DEBUG; | ||
122 | module_param(pamsnet_debug, int, 0); | ||
123 | MODULE_PARM_DESC(pamsnet_debug, "pamsnet debug enable (0-1)"); | ||
124 | MODULE_LICENSE("GPL"); | ||
125 | |||
126 | static unsigned int pamsnet_min_poll_time = 2; | ||
127 | |||
128 | |||
129 | /* Information that need to be kept for each board. | ||
130 | */ | ||
131 | struct net_local { | ||
132 | struct net_device_stats stats; | ||
133 | long open_time; /* for debugging */ | ||
134 | int poll_time; /* polling time varies with net load */ | ||
135 | }; | ||
136 | |||
137 | static struct nic_pkt_s { /* packet format */ | ||
138 | unsigned char buffer[2048]; | ||
139 | } *nic_packet = 0; | ||
140 | unsigned char *phys_nic_packet; | ||
141 | |||
142 | typedef unsigned char HADDR[6]; /* 6-byte hardware address of lance */ | ||
143 | |||
144 | /* Index to functions, as function prototypes. | ||
145 | */ | ||
146 | static void start (int target); | ||
147 | static int stop (int target); | ||
148 | static int testpkt (int target); | ||
149 | static int sendpkt (int target, unsigned char *buffer, int length); | ||
150 | static int receivepkt (int target, unsigned char *buffer); | ||
151 | static int inquiry (int target, unsigned char *buffer); | ||
152 | static HADDR *read_hw_addr(int target, unsigned char *buffer); | ||
153 | static void setup_dma (void *address, unsigned rw_flag, int num_blocks); | ||
154 | static int send_first (int target, unsigned char byte); | ||
155 | static int send_1_5 (int lun, unsigned char *command, int dma); | ||
156 | static int get_status (void); | ||
157 | static int calc_received (void *start_address); | ||
158 | |||
159 | static int pamsnet_open(struct net_device *dev); | ||
160 | static int pamsnet_send_packet(struct sk_buff *skb, struct net_device *dev); | ||
161 | static void pamsnet_poll_rx(struct net_device *); | ||
162 | static int pamsnet_close(struct net_device *dev); | ||
163 | static struct net_device_stats *net_get_stats(struct net_device *dev); | ||
164 | static void pamsnet_tick(unsigned long); | ||
165 | |||
166 | static irqreturn_t pamsnet_intr(int irq, void *data); | ||
167 | |||
168 | static DEFINE_TIMER(pamsnet_timer, pamsnet_tick, 0, 0); | ||
169 | |||
170 | #define STRAM_ADDR(a) (((a) & 0xff000000) == 0) | ||
171 | |||
172 | typedef struct | ||
173 | { | ||
174 | unsigned char reserved1[0x38]; | ||
175 | HADDR hwaddr; | ||
176 | unsigned char reserved2[0x1c2]; | ||
177 | } DMAHWADDR; | ||
178 | |||
179 | /* | ||
180 | * Definitions of commands understood by the PAMs DMA adaptor. | ||
181 | * | ||
182 | * In general the DMA adaptor uses LUN 0, 5, 6 and 7 on one ID changeable | ||
183 | * by the PAM's Net software. | ||
184 | * | ||
185 | * LUN 0 works as a harddisk. You can boot the PAM's Net driver there. | ||
186 | * LUN 5 works as a harddisk and lets you access the RAM and some I/O HW | ||
187 | * area. In sector 0, bytes 0x38-0x3d you find the ethernet HW address | ||
188 | * of the adaptor. | ||
189 | * LUN 6 works as a harddisk and lets you access the firmware ROM. | ||
190 | * LUN 7 lets you send and receive packets. | ||
191 | * | ||
192 | * Some commands like the INQUIRY command work identical on all used LUNs. | ||
193 | * | ||
194 | * UNKNOWN1 seems to read some data. | ||
195 | * Command length is 6 bytes. | ||
196 | * UNKNOWN2 seems to read some data (command byte 1 must be !=0). The | ||
197 | * following bytes seem to be something like an allocation length. | ||
198 | * Command length is 6 bytes. | ||
199 | * READPKT reads a packet received by the DMA adaptor. | ||
200 | * Command length is 6 bytes. | ||
201 | * WRITEPKT sends a packet transferred by the following DMA phase. The length | ||
202 | * of the packet is transferred in command bytes 3 and 4. | ||
203 | * The adaptor automatically replaces the src hw address in an ethernet | ||
204 | * packet by its own hw address. | ||
205 | * Command length is 6 bytes. | ||
206 | * INQUIRY has the same function as the INQUIRY command supported by harddisks | ||
207 | * and other SCSI devices. It lets you detect which device you found | ||
208 | * at a given address. | ||
209 | * Command length is 6 bytes. | ||
210 | * START initializes the DMA adaptor. After this command it is able to send | ||
211 | * and receive packets. There is no status byte returned! | ||
212 | * Command length is 1 byte. | ||
213 | * NUMPKTS gives back the number of received packets waiting in the queue in | ||
214 | * the status byte. | ||
215 | * Command length is 1 byte. | ||
216 | * UNKNOWN3 | ||
217 | * UNKNOWN4 Function of these three commands is unknown. | ||
218 | * UNKNOWN5 The command length of these three commands is 1 byte. | ||
219 | * DESELECT immediately deselects the DMA adaptor. May important with interrupt | ||
220 | * driven operation. | ||
221 | * Command length is 1 byte. | ||
222 | * STOP resets the DMA adaptor. After this command packets can no longer | ||
223 | * be received or transferred. | ||
224 | * Command length is 6 byte. | ||
225 | */ | ||
226 | |||
227 | enum {UNKNOWN1=3, READPKT=8, UNKNOWN2, WRITEPKT=10, INQUIRY=18, START, | ||
228 | NUMPKTS=22, UNKNOWN3, UNKNOWN4, UNKNOWN5, DESELECT, STOP}; | ||
229 | |||
230 | #define READSECTOR READPKT | ||
231 | #define WRITESECTOR WRITEPKT | ||
232 | |||
233 | u_char *inquire8="MV PAM's NET/GK"; | ||
234 | |||
235 | #define DMALOW dma_wd.dma_lo | ||
236 | #define DMAMID dma_wd.dma_md | ||
237 | #define DMAHIGH dma_wd.dma_hi | ||
238 | #define DACCESS dma_wd.fdc_acces_seccount | ||
239 | |||
240 | #define MFP_GPIP mfp.par_dt_reg | ||
241 | |||
242 | /* Some useful functions */ | ||
243 | |||
244 | #define INT (!(MFP_GPIP & 0x20)) | ||
245 | #define DELAY ({MFP_GPIP; MFP_GPIP; MFP_GPIP;}) | ||
246 | #define WRITEMODE(value) \ | ||
247 | ({ u_short dummy = value; \ | ||
248 | __asm__ volatile("movew %0, 0xFFFF8606" : : "d"(dummy)); \ | ||
249 | DELAY; \ | ||
250 | }) | ||
251 | #define WRITEBOTH(value1, value2) \ | ||
252 | ({ u_long dummy = (u_long)(value1)<<16 | (u_short)(value2); \ | ||
253 | __asm__ volatile("movel %0, 0xFFFF8604" : : "d"(dummy)); \ | ||
254 | DELAY; \ | ||
255 | }) | ||
256 | |||
257 | /* Definitions for DMODE */ | ||
258 | |||
259 | #define READ 0x000 | ||
260 | #define WRITE 0x100 | ||
261 | |||
262 | #define DMA_FDC 0x080 | ||
263 | #define DMA_ACSI 0x000 | ||
264 | |||
265 | #define DMA_DISABLE 0x040 | ||
266 | |||
267 | #define SEC_COUNT 0x010 | ||
268 | #define DMA_WINDOW 0x000 | ||
269 | |||
270 | #define REG_ACSI 0x008 | ||
271 | #define REG_FDC 0x000 | ||
272 | |||
273 | #define A1 0x002 | ||
274 | |||
275 | /* Timeout constants */ | ||
276 | |||
277 | #define TIMEOUTCMD HZ/2 /* ca. 500ms */ | ||
278 | #define TIMEOUTDMA HZ /* ca. 1s */ | ||
279 | #define COMMAND_DELAY 500 /* ca. 0.5ms */ | ||
280 | |||
281 | unsigned rw; | ||
282 | int lance_target = -1; | ||
283 | int if_up = 0; | ||
284 | |||
285 | /* The following routines access the ethernet board connected to the | ||
286 | * ACSI port via the st_dma chip. | ||
287 | */ | ||
288 | |||
289 | /* The following lowlevel routines work on physical addresses only and assume | ||
290 | * that eventually needed buffers are | ||
291 | * - completely located in ST RAM | ||
292 | * - are contigous in the physical address space | ||
293 | */ | ||
294 | |||
295 | /* Setup the DMA counter */ | ||
296 | |||
297 | static void | ||
298 | setup_dma (void *address, unsigned rw_flag, int num_blocks) | ||
299 | { | ||
300 | WRITEMODE((unsigned) rw_flag | DMA_FDC | SEC_COUNT | REG_ACSI | | ||
301 | A1); | ||
302 | WRITEMODE((unsigned)(rw_flag ^ WRITE) | DMA_FDC | SEC_COUNT | REG_ACSI | | ||
303 | A1); | ||
304 | WRITEMODE((unsigned) rw_flag | DMA_FDC | SEC_COUNT | REG_ACSI | | ||
305 | A1); | ||
306 | DMALOW = (unsigned char)((unsigned long)address & 0xFF); | ||
307 | DMAMID = (unsigned char)(((unsigned long)address >> 8) & 0xFF); | ||
308 | DMAHIGH = (unsigned char)(((unsigned long)address >> 16) & 0xFF); | ||
309 | WRITEBOTH((unsigned)num_blocks & 0xFF, | ||
310 | rw_flag | DMA_FDC | DMA_WINDOW | REG_ACSI | A1); | ||
311 | rw = rw_flag; | ||
312 | } | ||
313 | |||
314 | /* Send the first byte of an command block */ | ||
315 | |||
316 | static int | ||
317 | send_first (int target, unsigned char byte) | ||
318 | { | ||
319 | rw = READ; | ||
320 | acsi_delay_end(COMMAND_DELAY); | ||
321 | /* | ||
322 | * wake up ACSI | ||
323 | */ | ||
324 | WRITEMODE(DMA_FDC | DMA_WINDOW | REG_ACSI); | ||
325 | /* | ||
326 | * write command byte | ||
327 | */ | ||
328 | WRITEBOTH((target << 5) | (byte & 0x1F), DMA_FDC | | ||
329 | DMA_WINDOW | REG_ACSI | A1); | ||
330 | return (!acsi_wait_for_IRQ(TIMEOUTCMD)); | ||
331 | } | ||
332 | |||
333 | /* Send the rest of an command block */ | ||
334 | |||
335 | static int | ||
336 | send_1_5 (int lun, unsigned char *command, int dma) | ||
337 | { | ||
338 | int i, j; | ||
339 | |||
340 | for (i=0; i<5; i++) { | ||
341 | WRITEBOTH((!i ? (((lun & 0x7) << 5) | (command[i] & 0x1F)) | ||
342 | : command[i]), | ||
343 | rw | REG_ACSI | DMA_WINDOW | | ||
344 | ((i < 4) ? DMA_FDC | ||
345 | : (dma ? DMA_ACSI | ||
346 | : DMA_FDC)) | A1); | ||
347 | if (i < 4 && (j = !acsi_wait_for_IRQ(TIMEOUTCMD))) | ||
348 | return (j); | ||
349 | } | ||
350 | return (0); | ||
351 | } | ||
352 | |||
353 | /* Read a status byte */ | ||
354 | |||
355 | static int | ||
356 | get_status (void) | ||
357 | { | ||
358 | WRITEMODE(DMA_FDC | DMA_WINDOW | REG_ACSI | A1); | ||
359 | acsi_delay_start(); | ||
360 | return ((int)(DACCESS & 0xFF)); | ||
361 | } | ||
362 | |||
363 | /* Calculate the number of received bytes */ | ||
364 | |||
365 | static int | ||
366 | calc_received (void *start_address) | ||
367 | { | ||
368 | return (int)( | ||
369 | (((unsigned long)DMAHIGH << 16) | ((unsigned)DMAMID << 8) | DMALOW) | ||
370 | - (unsigned long)start_address); | ||
371 | } | ||
372 | |||
373 | /* The following midlevel routines still work on physical addresses ... */ | ||
374 | |||
375 | /* start() starts the PAM's DMA adaptor */ | ||
376 | |||
377 | static void | ||
378 | start (int target) | ||
379 | { | ||
380 | send_first(target, START); | ||
381 | } | ||
382 | |||
383 | /* stop() stops the PAM's DMA adaptor and returns a value of zero in case of success */ | ||
384 | |||
385 | static int | ||
386 | stop (int target) | ||
387 | { | ||
388 | int ret = -1; | ||
389 | unsigned char cmd_buffer[5]; | ||
390 | |||
391 | if (send_first(target, STOP)) | ||
392 | goto bad; | ||
393 | cmd_buffer[0] = cmd_buffer[1] = cmd_buffer[2] = | ||
394 | cmd_buffer[3] = cmd_buffer[4] = 0; | ||
395 | if (send_1_5(7, cmd_buffer, 0) || | ||
396 | !acsi_wait_for_IRQ(TIMEOUTDMA) || | ||
397 | get_status()) | ||
398 | goto bad; | ||
399 | ret = 0; | ||
400 | bad: | ||
401 | return (ret); | ||
402 | } | ||
403 | |||
404 | /* testpkt() returns the number of received packets waiting in the queue */ | ||
405 | |||
406 | static int | ||
407 | testpkt(int target) | ||
408 | { | ||
409 | int ret = -1; | ||
410 | |||
411 | if (send_first(target, NUMPKTS)) | ||
412 | goto bad; | ||
413 | ret = get_status(); | ||
414 | bad: | ||
415 | return (ret); | ||
416 | } | ||
417 | |||
418 | /* inquiry() returns 0 when PAM's DMA found, -1 when timeout, -2 otherwise */ | ||
419 | /* Please note: The buffer is for internal use only but must be defined! */ | ||
420 | |||
421 | static int | ||
422 | inquiry (int target, unsigned char *buffer) | ||
423 | { | ||
424 | int ret = -1; | ||
425 | unsigned char *vbuffer = phys_to_virt((unsigned long)buffer); | ||
426 | unsigned char cmd_buffer[5]; | ||
427 | |||
428 | if (send_first(target, INQUIRY)) | ||
429 | goto bad; | ||
430 | setup_dma(buffer, READ, 1); | ||
431 | vbuffer[8] = vbuffer[27] = 0; /* Avoid confusion with previous read data */ | ||
432 | cmd_buffer[0] = cmd_buffer[1] = cmd_buffer[2] = cmd_buffer[4] = 0; | ||
433 | cmd_buffer[3] = 48; | ||
434 | if (send_1_5(5, cmd_buffer, 1) || | ||
435 | !acsi_wait_for_IRQ(TIMEOUTDMA) || | ||
436 | get_status() || | ||
437 | (calc_received(buffer) < 32)) | ||
438 | goto bad; | ||
439 | dma_cache_maintenance((unsigned long)(buffer+8), 20, 0); | ||
440 | if (memcmp(inquire8, vbuffer+8, 20)) | ||
441 | goto bad; | ||
442 | ret = 0; | ||
443 | bad: | ||
444 | if (!!NET_DEBUG) { | ||
445 | vbuffer[8+20]=0; | ||
446 | printk("inquiry of target %d: %s\n", target, vbuffer+8); | ||
447 | } | ||
448 | return (ret); | ||
449 | } | ||
450 | |||
451 | /* | ||
452 | * read_hw_addr() reads the sector containing the hwaddr and returns | ||
453 | * a pointer to it (virtual address!) or 0 in case of an error | ||
454 | */ | ||
455 | |||
456 | static HADDR | ||
457 | *read_hw_addr(int target, unsigned char *buffer) | ||
458 | { | ||
459 | HADDR *ret = 0; | ||
460 | unsigned char cmd_buffer[5]; | ||
461 | |||
462 | if (send_first(target, READSECTOR)) | ||
463 | goto bad; | ||
464 | setup_dma(buffer, READ, 1); | ||
465 | cmd_buffer[0] = cmd_buffer[1] = cmd_buffer[2] = cmd_buffer[4] = 0; | ||
466 | cmd_buffer[3] = 1; | ||
467 | if (send_1_5(5, cmd_buffer, 1) || | ||
468 | !acsi_wait_for_IRQ(TIMEOUTDMA) || | ||
469 | get_status()) | ||
470 | goto bad; | ||
471 | ret = phys_to_virt((unsigned long)&(((DMAHWADDR *)buffer)->hwaddr)); | ||
472 | dma_cache_maintenance((unsigned long)buffer, 512, 0); | ||
473 | bad: | ||
474 | return (ret); | ||
475 | } | ||
476 | |||
477 | static irqreturn_t | ||
478 | pamsnet_intr(int irq, void *data) | ||
479 | { | ||
480 | return IRQ_HANDLED; | ||
481 | } | ||
482 | |||
483 | /* receivepkt() loads a packet to a given buffer and returns its length */ | ||
484 | |||
485 | static int | ||
486 | receivepkt (int target, unsigned char *buffer) | ||
487 | { | ||
488 | int ret = -1; | ||
489 | unsigned char cmd_buffer[5]; | ||
490 | |||
491 | if (send_first(target, READPKT)) | ||
492 | goto bad; | ||
493 | setup_dma(buffer, READ, 3); | ||
494 | cmd_buffer[0] = cmd_buffer[1] = cmd_buffer[2] = cmd_buffer[4] = 0; | ||
495 | cmd_buffer[3] = 3; | ||
496 | if (send_1_5(7, cmd_buffer, 1) || | ||
497 | !acsi_wait_for_IRQ(TIMEOUTDMA) || | ||
498 | get_status()) | ||
499 | goto bad; | ||
500 | ret = calc_received(buffer); | ||
501 | bad: | ||
502 | return (ret); | ||
503 | } | ||
504 | |||
505 | /* sendpkt() sends a packet and returns a value of zero when the packet was sent | ||
506 | successfully */ | ||
507 | |||
508 | static int | ||
509 | sendpkt (int target, unsigned char *buffer, int length) | ||
510 | { | ||
511 | int ret = -1; | ||
512 | unsigned char cmd_buffer[5]; | ||
513 | |||
514 | if (send_first(target, WRITEPKT)) | ||
515 | goto bad; | ||
516 | setup_dma(buffer, WRITE, 3); | ||
517 | cmd_buffer[0] = cmd_buffer[1] = cmd_buffer[4] = 0; | ||
518 | cmd_buffer[2] = length >> 8; | ||
519 | cmd_buffer[3] = length & 0xFF; | ||
520 | if (send_1_5(7, cmd_buffer, 1) || | ||
521 | !acsi_wait_for_IRQ(TIMEOUTDMA) || | ||
522 | get_status()) | ||
523 | goto bad; | ||
524 | ret = 0; | ||
525 | bad: | ||
526 | return (ret); | ||
527 | } | ||
528 | |||
529 | /* The following higher level routines work on virtual addresses and convert them to | ||
530 | * physical addresses when passed to the lowlevel routines. It's up to the higher level | ||
531 | * routines to copy data from Alternate RAM to ST RAM if neccesary! | ||
532 | */ | ||
533 | |||
534 | /* Check for a network adaptor of this type, and return '0' if one exists. | ||
535 | */ | ||
536 | |||
537 | struct net_device * __init pamsnet_probe (int unit) | ||
538 | { | ||
539 | struct net_device *dev; | ||
540 | int i; | ||
541 | HADDR *hwaddr; | ||
542 | int err; | ||
543 | |||
544 | unsigned char station_addr[6]; | ||
545 | static unsigned version_printed; | ||
546 | /* avoid "Probing for..." printed 4 times - the driver is supporting only one adapter now! */ | ||
547 | static int no_more_found; | ||
548 | |||
549 | if (no_more_found) | ||
550 | return ERR_PTR(-ENODEV); | ||
551 | no_more_found = 1; | ||
552 | |||
553 | dev = alloc_etherdev(sizeof(struct net_local)); | ||
554 | if (!dev) | ||
555 | return ERR_PTR(-ENOMEM); | ||
556 | if (unit >= 0) { | ||
557 | sprintf(dev->name, "eth%d", unit); | ||
558 | netdev_boot_setup_check(dev); | ||
559 | } | ||
560 | SET_MODULE_OWNER(dev); | ||
561 | |||
562 | printk("Probing for PAM's Net/GK Adapter...\n"); | ||
563 | |||
564 | /* Allocate the DMA buffer here since we need it for probing! */ | ||
565 | |||
566 | nic_packet = (struct nic_pkt_s *)acsi_buffer; | ||
567 | phys_nic_packet = (unsigned char *)phys_acsi_buffer; | ||
568 | if (pamsnet_debug > 0) { | ||
569 | printk("nic_packet at 0x%p, phys at 0x%p\n", | ||
570 | nic_packet, phys_nic_packet ); | ||
571 | } | ||
572 | |||
573 | stdma_lock(pamsnet_intr, NULL); | ||
574 | DISABLE_IRQ(); | ||
575 | |||
576 | for (i=0; i<8; i++) { | ||
577 | /* Do two inquiries to cover cases with strange equipment on previous ID */ | ||
578 | /* blocking the ACSI bus (like the SLMC804 laser printer controller... */ | ||
579 | inquiry(i, phys_nic_packet); | ||
580 | if (!inquiry(i, phys_nic_packet)) { | ||
581 | lance_target = i; | ||
582 | break; | ||
583 | } | ||
584 | } | ||
585 | |||
586 | if (!!NET_DEBUG) | ||
587 | printk("ID: %d\n",i); | ||
588 | |||
589 | if (lance_target >= 0) { | ||
590 | if (!(hwaddr = read_hw_addr(lance_target, phys_nic_packet))) | ||
591 | lance_target = -1; | ||
592 | else | ||
593 | memcpy (station_addr, hwaddr, ETH_ALEN); | ||
594 | } | ||
595 | |||
596 | ENABLE_IRQ(); | ||
597 | stdma_release(); | ||
598 | |||
599 | if (lance_target < 0) { | ||
600 | printk("No PAM's Net/GK found.\n"); | ||
601 | free_netdev(dev); | ||
602 | return ERR_PTR(-ENODEV); | ||
603 | } | ||
604 | |||
605 | if (pamsnet_debug > 0 && version_printed++ == 0) | ||
606 | printk(version); | ||
607 | |||
608 | printk("%s: %s found on target %01d, eth-addr: %02x:%02x:%02x:%02x:%02x:%02x.\n", | ||
609 | dev->name, "PAM's Net/GK", lance_target, | ||
610 | station_addr[0], station_addr[1], station_addr[2], | ||
611 | station_addr[3], station_addr[4], station_addr[5]); | ||
612 | |||
613 | /* Initialize the device structure. */ | ||
614 | dev->open = pamsnet_open; | ||
615 | dev->stop = pamsnet_close; | ||
616 | dev->hard_start_xmit = pamsnet_send_packet; | ||
617 | dev->get_stats = net_get_stats; | ||
618 | |||
619 | /* Fill in the fields of the device structure with ethernet-generic | ||
620 | * values. This should be in a common file instead of per-driver. | ||
621 | */ | ||
622 | |||
623 | for (i = 0; i < ETH_ALEN; i++) { | ||
624 | #if 0 | ||
625 | dev->broadcast[i] = 0xff; | ||
626 | #endif | ||
627 | dev->dev_addr[i] = station_addr[i]; | ||
628 | } | ||
629 | err = register_netdev(dev); | ||
630 | if (!err) | ||
631 | return dev; | ||
632 | |||
633 | free_netdev(dev); | ||
634 | return ERR_PTR(err); | ||
635 | } | ||
636 | |||
637 | /* Open/initialize the board. This is called (in the current kernel) | ||
638 | sometime after booting when the 'ifconfig' program is run. | ||
639 | |||
640 | This routine should set everything up anew at each open, even | ||
641 | registers that "should" only need to be set once at boot, so that | ||
642 | there is non-reboot way to recover if something goes wrong. | ||
643 | */ | ||
644 | static int | ||
645 | pamsnet_open(struct net_device *dev) | ||
646 | { | ||
647 | struct net_local *lp = netdev_priv(dev); | ||
648 | |||
649 | if (pamsnet_debug > 0) | ||
650 | printk("pamsnet_open\n"); | ||
651 | stdma_lock(pamsnet_intr, NULL); | ||
652 | DISABLE_IRQ(); | ||
653 | |||
654 | /* Reset the hardware here. | ||
655 | */ | ||
656 | if (!if_up) | ||
657 | start(lance_target); | ||
658 | if_up = 1; | ||
659 | lp->open_time = 0; /*jiffies*/ | ||
660 | lp->poll_time = MAX_POLL_TIME; | ||
661 | |||
662 | dev->tbusy = 0; | ||
663 | dev->interrupt = 0; | ||
664 | dev->start = 1; | ||
665 | |||
666 | ENABLE_IRQ(); | ||
667 | stdma_release(); | ||
668 | pamsnet_timer.data = (long)dev; | ||
669 | pamsnet_timer.expires = jiffies + lp->poll_time; | ||
670 | add_timer(&pamsnet_timer); | ||
671 | return 0; | ||
672 | } | ||
673 | |||
674 | static int | ||
675 | pamsnet_send_packet(struct sk_buff *skb, struct net_device *dev) | ||
676 | { | ||
677 | struct net_local *lp = netdev_priv(dev); | ||
678 | unsigned long flags; | ||
679 | |||
680 | /* Block a timer-based transmit from overlapping. This could better be | ||
681 | * done with atomic_swap(1, dev->tbusy), but set_bit() works as well. | ||
682 | */ | ||
683 | local_irq_save(flags); | ||
684 | |||
685 | if (stdma_islocked()) { | ||
686 | local_irq_restore(flags); | ||
687 | lp->stats.tx_errors++; | ||
688 | } | ||
689 | else { | ||
690 | int length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; | ||
691 | unsigned long buf = virt_to_phys(skb->data); | ||
692 | int stat; | ||
693 | |||
694 | stdma_lock(pamsnet_intr, NULL); | ||
695 | DISABLE_IRQ(); | ||
696 | |||
697 | local_irq_restore(flags); | ||
698 | if( !STRAM_ADDR(buf+length-1) ) { | ||
699 | skb_copy_from_linear_data(skb, nic_packet->buffer, | ||
700 | length); | ||
701 | buf = (unsigned long)phys_nic_packet; | ||
702 | } | ||
703 | |||
704 | dma_cache_maintenance(buf, length, 1); | ||
705 | |||
706 | stat = sendpkt(lance_target, (unsigned char *)buf, length); | ||
707 | ENABLE_IRQ(); | ||
708 | stdma_release(); | ||
709 | |||
710 | dev->trans_start = jiffies; | ||
711 | dev->tbusy = 0; | ||
712 | lp->stats.tx_packets++; | ||
713 | lp->stats.tx_bytes+=length; | ||
714 | } | ||
715 | dev_kfree_skb(skb); | ||
716 | |||
717 | return 0; | ||
718 | } | ||
719 | |||
720 | /* We have a good packet(s), get it/them out of the buffers. | ||
721 | */ | ||
722 | static void | ||
723 | pamsnet_poll_rx(struct net_device *dev) | ||
724 | { | ||
725 | struct net_local *lp = netdev_priv(dev); | ||
726 | int boguscount; | ||
727 | int pkt_len; | ||
728 | struct sk_buff *skb; | ||
729 | unsigned long flags; | ||
730 | |||
731 | local_irq_save(flags); | ||
732 | /* ++roman: Take care at locking the ST-DMA... This must be done with ints | ||
733 | * off, since otherwise an int could slip in between the question and the | ||
734 | * locking itself, and then we'd go to sleep... And locking itself is | ||
735 | * necessary to keep the floppy_change timer from working with ST-DMA | ||
736 | * registers. */ | ||
737 | if (stdma_islocked()) { | ||
738 | local_irq_restore(flags); | ||
739 | return; | ||
740 | } | ||
741 | stdma_lock(pamsnet_intr, NULL); | ||
742 | DISABLE_IRQ(); | ||
743 | local_irq_restore(flags); | ||
744 | |||
745 | boguscount = testpkt(lance_target); | ||
746 | if( lp->poll_time < MAX_POLL_TIME ) lp->poll_time++; | ||
747 | |||
748 | while(boguscount--) { | ||
749 | pkt_len = receivepkt(lance_target, phys_nic_packet); | ||
750 | |||
751 | if( pkt_len < 60 ) break; | ||
752 | |||
753 | /* Good packet... */ | ||
754 | |||
755 | dma_cache_maintenance((unsigned long)phys_nic_packet, pkt_len, 0); | ||
756 | |||
757 | lp->poll_time = pamsnet_min_poll_time; /* fast poll */ | ||
758 | if( pkt_len >= 60 && pkt_len <= 2048 ) { | ||
759 | if (pkt_len > 1514) | ||
760 | pkt_len = 1514; | ||
761 | |||
762 | /* Malloc up new buffer. | ||
763 | */ | ||
764 | skb = alloc_skb(pkt_len, GFP_ATOMIC); | ||
765 | if (skb == NULL) { | ||
766 | printk("%s: Memory squeeze, dropping packet.\n", | ||
767 | dev->name); | ||
768 | lp->stats.rx_dropped++; | ||
769 | break; | ||
770 | } | ||
771 | skb->len = pkt_len; | ||
772 | skb->dev = dev; | ||
773 | |||
774 | /* 'skb->data' points to the start of sk_buff data area. | ||
775 | */ | ||
776 | skb_copy_to_linear_data(skb, nic_packet->buffer, | ||
777 | pkt_len); | ||
778 | netif_rx(skb); | ||
779 | dev->last_rx = jiffies; | ||
780 | lp->stats.rx_packets++; | ||
781 | lp->stats.rx_bytes+=pkt_len; | ||
782 | } | ||
783 | } | ||
784 | |||
785 | /* If any worth-while packets have been received, dev_rint() | ||
786 | has done a mark_bh(INET_BH) for us and will work on them | ||
787 | when we get to the bottom-half routine. | ||
788 | */ | ||
789 | |||
790 | ENABLE_IRQ(); | ||
791 | stdma_release(); | ||
792 | return; | ||
793 | } | ||
794 | |||
795 | /* pamsnet_tick: called by pamsnet_timer. Reads packets from the adapter, | ||
796 | * passes them to the higher layers and restarts the timer. | ||
797 | */ | ||
798 | static void | ||
799 | pamsnet_tick(unsigned long data) | ||
800 | { | ||
801 | struct net_device *dev = (struct net_device *)data; | ||
802 | struct net_local *lp = netdev_priv(dev); | ||
803 | |||
804 | if( pamsnet_debug > 0 && (lp->open_time++ & 7) == 8 ) | ||
805 | printk("pamsnet_tick: %ld\n", lp->open_time); | ||
806 | |||
807 | pamsnet_poll_rx(dev); | ||
808 | |||
809 | pamsnet_timer.expires = jiffies + lp->poll_time; | ||
810 | add_timer(&pamsnet_timer); | ||
811 | } | ||
812 | |||
813 | /* The inverse routine to pamsnet_open(). | ||
814 | */ | ||
815 | static int | ||
816 | pamsnet_close(struct net_device *dev) | ||
817 | { | ||
818 | struct net_local *lp = netdev_priv(dev); | ||
819 | |||
820 | if (pamsnet_debug > 0) | ||
821 | printk("pamsnet_close, open_time=%ld\n", lp->open_time); | ||
822 | del_timer(&pamsnet_timer); | ||
823 | stdma_lock(pamsnet_intr, NULL); | ||
824 | DISABLE_IRQ(); | ||
825 | |||
826 | if (if_up) | ||
827 | stop(lance_target); | ||
828 | if_up = 0; | ||
829 | |||
830 | lp->open_time = 0; | ||
831 | |||
832 | dev->tbusy = 1; | ||
833 | dev->start = 0; | ||
834 | |||
835 | ENABLE_IRQ(); | ||
836 | stdma_release(); | ||
837 | return 0; | ||
838 | } | ||
839 | |||
840 | /* Get the current statistics. | ||
841 | This may be called with the card open or closed. | ||
842 | */ | ||
843 | static struct net_device_stats *net_get_stats(struct net_device *dev) | ||
844 | { | ||
845 | struct net_local *lp = netdev_priv(dev); | ||
846 | return &lp->stats; | ||
847 | } | ||
848 | |||
849 | |||
850 | #ifdef MODULE | ||
851 | |||
852 | static struct net_device *pam_dev; | ||
853 | |||
854 | int init_module(void) | ||
855 | { | ||
856 | pam_dev = pamsnet_probe(-1); | ||
857 | if (IS_ERR(pam_dev)) | ||
858 | return PTR_ERR(pam_dev); | ||
859 | return 0; | ||
860 | } | ||
861 | |||
862 | void cleanup_module(void) | ||
863 | { | ||
864 | unregister_netdev(pam_dev); | ||
865 | free_netdev(pam_dev); | ||
866 | } | ||
867 | |||
868 | #endif /* MODULE */ | ||
869 | |||
870 | /* Local variables: | ||
871 | * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/include | ||
872 | -b m68k-linuxaout -Wall -Wstrict-prototypes -O2 | ||
873 | -fomit-frame-pointer -pipe -DMODULE -I../../net/inet -c atari_pamsnet.c" | ||
874 | * version-control: t | ||
875 | * kept-new-versions: 5 | ||
876 | * tab-width: 8 | ||
877 | * End: | ||
878 | */ | ||
diff --git a/drivers/net/sunvnet.c b/drivers/net/sunvnet.c new file mode 100644 index 000000000000..8a667c13faef --- /dev/null +++ b/drivers/net/sunvnet.c | |||
@@ -0,0 +1,1164 @@ | |||
1 | /* sunvnet.c: Sun LDOM Virtual Network Driver. | ||
2 | * | ||
3 | * Copyright (C) 2007 David S. Miller <davem@davemloft.net> | ||
4 | */ | ||
5 | |||
6 | #include <linux/module.h> | ||
7 | #include <linux/kernel.h> | ||
8 | #include <linux/types.h> | ||
9 | #include <linux/slab.h> | ||
10 | #include <linux/delay.h> | ||
11 | #include <linux/init.h> | ||
12 | #include <linux/netdevice.h> | ||
13 | #include <linux/ethtool.h> | ||
14 | #include <linux/etherdevice.h> | ||
15 | |||
16 | #include <asm/vio.h> | ||
17 | #include <asm/ldc.h> | ||
18 | |||
19 | #include "sunvnet.h" | ||
20 | |||
21 | #define DRV_MODULE_NAME "sunvnet" | ||
22 | #define PFX DRV_MODULE_NAME ": " | ||
23 | #define DRV_MODULE_VERSION "1.0" | ||
24 | #define DRV_MODULE_RELDATE "June 25, 2007" | ||
25 | |||
26 | static char version[] __devinitdata = | ||
27 | DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; | ||
28 | MODULE_AUTHOR("David S. Miller (davem@davemloft.net)"); | ||
29 | MODULE_DESCRIPTION("Sun LDOM virtual network driver"); | ||
30 | MODULE_LICENSE("GPL"); | ||
31 | MODULE_VERSION(DRV_MODULE_VERSION); | ||
32 | |||
33 | /* Ordered from largest major to lowest */ | ||
34 | static struct vio_version vnet_versions[] = { | ||
35 | { .major = 1, .minor = 0 }, | ||
36 | }; | ||
37 | |||
38 | static inline u32 vnet_tx_dring_avail(struct vio_dring_state *dr) | ||
39 | { | ||
40 | return vio_dring_avail(dr, VNET_TX_RING_SIZE); | ||
41 | } | ||
42 | |||
43 | static int vnet_handle_unknown(struct vnet_port *port, void *arg) | ||
44 | { | ||
45 | struct vio_msg_tag *pkt = arg; | ||
46 | |||
47 | printk(KERN_ERR PFX "Received unknown msg [%02x:%02x:%04x:%08x]\n", | ||
48 | pkt->type, pkt->stype, pkt->stype_env, pkt->sid); | ||
49 | printk(KERN_ERR PFX "Resetting connection.\n"); | ||
50 | |||
51 | ldc_disconnect(port->vio.lp); | ||
52 | |||
53 | return -ECONNRESET; | ||
54 | } | ||
55 | |||
56 | static int vnet_send_attr(struct vio_driver_state *vio) | ||
57 | { | ||
58 | struct vnet_port *port = to_vnet_port(vio); | ||
59 | struct net_device *dev = port->vp->dev; | ||
60 | struct vio_net_attr_info pkt; | ||
61 | int i; | ||
62 | |||
63 | memset(&pkt, 0, sizeof(pkt)); | ||
64 | pkt.tag.type = VIO_TYPE_CTRL; | ||
65 | pkt.tag.stype = VIO_SUBTYPE_INFO; | ||
66 | pkt.tag.stype_env = VIO_ATTR_INFO; | ||
67 | pkt.tag.sid = vio_send_sid(vio); | ||
68 | pkt.xfer_mode = VIO_DRING_MODE; | ||
69 | pkt.addr_type = VNET_ADDR_ETHERMAC; | ||
70 | pkt.ack_freq = 0; | ||
71 | for (i = 0; i < 6; i++) | ||
72 | pkt.addr |= (u64)dev->dev_addr[i] << ((5 - i) * 8); | ||
73 | pkt.mtu = ETH_FRAME_LEN; | ||
74 | |||
75 | viodbg(HS, "SEND NET ATTR xmode[0x%x] atype[0x%x] addr[%llx] " | ||
76 | "ackfreq[%u] mtu[%llu]\n", | ||
77 | pkt.xfer_mode, pkt.addr_type, | ||
78 | (unsigned long long) pkt.addr, | ||
79 | pkt.ack_freq, | ||
80 | (unsigned long long) pkt.mtu); | ||
81 | |||
82 | return vio_ldc_send(vio, &pkt, sizeof(pkt)); | ||
83 | } | ||
84 | |||
85 | static int handle_attr_info(struct vio_driver_state *vio, | ||
86 | struct vio_net_attr_info *pkt) | ||
87 | { | ||
88 | viodbg(HS, "GOT NET ATTR INFO xmode[0x%x] atype[0x%x] addr[%llx] " | ||
89 | "ackfreq[%u] mtu[%llu]\n", | ||
90 | pkt->xfer_mode, pkt->addr_type, | ||
91 | (unsigned long long) pkt->addr, | ||
92 | pkt->ack_freq, | ||
93 | (unsigned long long) pkt->mtu); | ||
94 | |||
95 | pkt->tag.sid = vio_send_sid(vio); | ||
96 | |||
97 | if (pkt->xfer_mode != VIO_DRING_MODE || | ||
98 | pkt->addr_type != VNET_ADDR_ETHERMAC || | ||
99 | pkt->mtu != ETH_FRAME_LEN) { | ||
100 | viodbg(HS, "SEND NET ATTR NACK\n"); | ||
101 | |||
102 | pkt->tag.stype = VIO_SUBTYPE_NACK; | ||
103 | |||
104 | (void) vio_ldc_send(vio, pkt, sizeof(*pkt)); | ||
105 | |||
106 | return -ECONNRESET; | ||
107 | } else { | ||
108 | viodbg(HS, "SEND NET ATTR ACK\n"); | ||
109 | |||
110 | pkt->tag.stype = VIO_SUBTYPE_ACK; | ||
111 | |||
112 | return vio_ldc_send(vio, pkt, sizeof(*pkt)); | ||
113 | } | ||
114 | |||
115 | } | ||
116 | |||
117 | static int handle_attr_ack(struct vio_driver_state *vio, | ||
118 | struct vio_net_attr_info *pkt) | ||
119 | { | ||
120 | viodbg(HS, "GOT NET ATTR ACK\n"); | ||
121 | |||
122 | return 0; | ||
123 | } | ||
124 | |||
125 | static int handle_attr_nack(struct vio_driver_state *vio, | ||
126 | struct vio_net_attr_info *pkt) | ||
127 | { | ||
128 | viodbg(HS, "GOT NET ATTR NACK\n"); | ||
129 | |||
130 | return -ECONNRESET; | ||
131 | } | ||
132 | |||
133 | static int vnet_handle_attr(struct vio_driver_state *vio, void *arg) | ||
134 | { | ||
135 | struct vio_net_attr_info *pkt = arg; | ||
136 | |||
137 | switch (pkt->tag.stype) { | ||
138 | case VIO_SUBTYPE_INFO: | ||
139 | return handle_attr_info(vio, pkt); | ||
140 | |||
141 | case VIO_SUBTYPE_ACK: | ||
142 | return handle_attr_ack(vio, pkt); | ||
143 | |||
144 | case VIO_SUBTYPE_NACK: | ||
145 | return handle_attr_nack(vio, pkt); | ||
146 | |||
147 | default: | ||
148 | return -ECONNRESET; | ||
149 | } | ||
150 | } | ||
151 | |||
152 | static void vnet_handshake_complete(struct vio_driver_state *vio) | ||
153 | { | ||
154 | struct vio_dring_state *dr; | ||
155 | |||
156 | dr = &vio->drings[VIO_DRIVER_RX_RING]; | ||
157 | dr->snd_nxt = dr->rcv_nxt = 1; | ||
158 | |||
159 | dr = &vio->drings[VIO_DRIVER_TX_RING]; | ||
160 | dr->snd_nxt = dr->rcv_nxt = 1; | ||
161 | } | ||
162 | |||
163 | /* The hypervisor interface that implements copying to/from imported | ||
164 | * memory from another domain requires that copies are done to 8-byte | ||
165 | * aligned buffers, and that the lengths of such copies are also 8-byte | ||
166 | * multiples. | ||
167 | * | ||
168 | * So we align skb->data to an 8-byte multiple and pad-out the data | ||
169 | * area so we can round the copy length up to the next multiple of | ||
170 | * 8 for the copy. | ||
171 | * | ||
172 | * The transmitter puts the actual start of the packet 6 bytes into | ||
173 | * the buffer it sends over, so that the IP headers after the ethernet | ||
174 | * header are aligned properly. These 6 bytes are not in the descriptor | ||
175 | * length, they are simply implied. This offset is represented using | ||
176 | * the VNET_PACKET_SKIP macro. | ||
177 | */ | ||
178 | static struct sk_buff *alloc_and_align_skb(struct net_device *dev, | ||
179 | unsigned int len) | ||
180 | { | ||
181 | struct sk_buff *skb = netdev_alloc_skb(dev, len+VNET_PACKET_SKIP+8+8); | ||
182 | unsigned long addr, off; | ||
183 | |||
184 | if (unlikely(!skb)) | ||
185 | return NULL; | ||
186 | |||
187 | addr = (unsigned long) skb->data; | ||
188 | off = ((addr + 7UL) & ~7UL) - addr; | ||
189 | if (off) | ||
190 | skb_reserve(skb, off); | ||
191 | |||
192 | return skb; | ||
193 | } | ||
194 | |||
195 | static int vnet_rx_one(struct vnet_port *port, unsigned int len, | ||
196 | struct ldc_trans_cookie *cookies, int ncookies) | ||
197 | { | ||
198 | struct net_device *dev = port->vp->dev; | ||
199 | unsigned int copy_len; | ||
200 | struct sk_buff *skb; | ||
201 | int err; | ||
202 | |||
203 | err = -EMSGSIZE; | ||
204 | if (unlikely(len < ETH_ZLEN || len > ETH_FRAME_LEN)) { | ||
205 | dev->stats.rx_length_errors++; | ||
206 | goto out_dropped; | ||
207 | } | ||
208 | |||
209 | skb = alloc_and_align_skb(dev, len); | ||
210 | err = -ENOMEM; | ||
211 | if (unlikely(!skb)) { | ||
212 | dev->stats.rx_missed_errors++; | ||
213 | goto out_dropped; | ||
214 | } | ||
215 | |||
216 | copy_len = (len + VNET_PACKET_SKIP + 7U) & ~7U; | ||
217 | skb_put(skb, copy_len); | ||
218 | err = ldc_copy(port->vio.lp, LDC_COPY_IN, | ||
219 | skb->data, copy_len, 0, | ||
220 | cookies, ncookies); | ||
221 | if (unlikely(err < 0)) { | ||
222 | dev->stats.rx_frame_errors++; | ||
223 | goto out_free_skb; | ||
224 | } | ||
225 | |||
226 | skb_pull(skb, VNET_PACKET_SKIP); | ||
227 | skb_trim(skb, len); | ||
228 | skb->protocol = eth_type_trans(skb, dev); | ||
229 | |||
230 | dev->stats.rx_packets++; | ||
231 | dev->stats.rx_bytes += len; | ||
232 | |||
233 | netif_rx(skb); | ||
234 | |||
235 | return 0; | ||
236 | |||
237 | out_free_skb: | ||
238 | kfree_skb(skb); | ||
239 | |||
240 | out_dropped: | ||
241 | dev->stats.rx_dropped++; | ||
242 | return err; | ||
243 | } | ||
244 | |||
245 | static int vnet_send_ack(struct vnet_port *port, struct vio_dring_state *dr, | ||
246 | u32 start, u32 end, u8 vio_dring_state) | ||
247 | { | ||
248 | struct vio_dring_data hdr = { | ||
249 | .tag = { | ||
250 | .type = VIO_TYPE_DATA, | ||
251 | .stype = VIO_SUBTYPE_ACK, | ||
252 | .stype_env = VIO_DRING_DATA, | ||
253 | .sid = vio_send_sid(&port->vio), | ||
254 | }, | ||
255 | .dring_ident = dr->ident, | ||
256 | .start_idx = start, | ||
257 | .end_idx = end, | ||
258 | .state = vio_dring_state, | ||
259 | }; | ||
260 | int err, delay; | ||
261 | |||
262 | hdr.seq = dr->snd_nxt; | ||
263 | delay = 1; | ||
264 | do { | ||
265 | err = vio_ldc_send(&port->vio, &hdr, sizeof(hdr)); | ||
266 | if (err > 0) { | ||
267 | dr->snd_nxt++; | ||
268 | break; | ||
269 | } | ||
270 | udelay(delay); | ||
271 | if ((delay <<= 1) > 128) | ||
272 | delay = 128; | ||
273 | } while (err == -EAGAIN); | ||
274 | |||
275 | return err; | ||
276 | } | ||
277 | |||
278 | static u32 next_idx(u32 idx, struct vio_dring_state *dr) | ||
279 | { | ||
280 | if (++idx == dr->num_entries) | ||
281 | idx = 0; | ||
282 | return idx; | ||
283 | } | ||
284 | |||
285 | static u32 prev_idx(u32 idx, struct vio_dring_state *dr) | ||
286 | { | ||
287 | if (idx == 0) | ||
288 | idx = dr->num_entries - 1; | ||
289 | else | ||
290 | idx--; | ||
291 | |||
292 | return idx; | ||
293 | } | ||
294 | |||
295 | static struct vio_net_desc *get_rx_desc(struct vnet_port *port, | ||
296 | struct vio_dring_state *dr, | ||
297 | u32 index) | ||
298 | { | ||
299 | struct vio_net_desc *desc = port->vio.desc_buf; | ||
300 | int err; | ||
301 | |||
302 | err = ldc_get_dring_entry(port->vio.lp, desc, dr->entry_size, | ||
303 | (index * dr->entry_size), | ||
304 | dr->cookies, dr->ncookies); | ||
305 | if (err < 0) | ||
306 | return ERR_PTR(err); | ||
307 | |||
308 | return desc; | ||
309 | } | ||
310 | |||
311 | static int put_rx_desc(struct vnet_port *port, | ||
312 | struct vio_dring_state *dr, | ||
313 | struct vio_net_desc *desc, | ||
314 | u32 index) | ||
315 | { | ||
316 | int err; | ||
317 | |||
318 | err = ldc_put_dring_entry(port->vio.lp, desc, dr->entry_size, | ||
319 | (index * dr->entry_size), | ||
320 | dr->cookies, dr->ncookies); | ||
321 | if (err < 0) | ||
322 | return err; | ||
323 | |||
324 | return 0; | ||
325 | } | ||
326 | |||
327 | static int vnet_walk_rx_one(struct vnet_port *port, | ||
328 | struct vio_dring_state *dr, | ||
329 | u32 index, int *needs_ack) | ||
330 | { | ||
331 | struct vio_net_desc *desc = get_rx_desc(port, dr, index); | ||
332 | struct vio_driver_state *vio = &port->vio; | ||
333 | int err; | ||
334 | |||
335 | if (IS_ERR(desc)) | ||
336 | return PTR_ERR(desc); | ||
337 | |||
338 | viodbg(DATA, "vio_walk_rx_one desc[%02x:%02x:%08x:%08x:%lx:%lx]\n", | ||
339 | desc->hdr.state, desc->hdr.ack, | ||
340 | desc->size, desc->ncookies, | ||
341 | desc->cookies[0].cookie_addr, | ||
342 | desc->cookies[0].cookie_size); | ||
343 | |||
344 | if (desc->hdr.state != VIO_DESC_READY) | ||
345 | return 1; | ||
346 | err = vnet_rx_one(port, desc->size, desc->cookies, desc->ncookies); | ||
347 | if (err == -ECONNRESET) | ||
348 | return err; | ||
349 | desc->hdr.state = VIO_DESC_DONE; | ||
350 | err = put_rx_desc(port, dr, desc, index); | ||
351 | if (err < 0) | ||
352 | return err; | ||
353 | *needs_ack = desc->hdr.ack; | ||
354 | return 0; | ||
355 | } | ||
356 | |||
357 | static int vnet_walk_rx(struct vnet_port *port, struct vio_dring_state *dr, | ||
358 | u32 start, u32 end) | ||
359 | { | ||
360 | struct vio_driver_state *vio = &port->vio; | ||
361 | int ack_start = -1, ack_end = -1; | ||
362 | |||
363 | end = (end == (u32) -1) ? prev_idx(start, dr) : next_idx(end, dr); | ||
364 | |||
365 | viodbg(DATA, "vnet_walk_rx start[%08x] end[%08x]\n", start, end); | ||
366 | |||
367 | while (start != end) { | ||
368 | int ack = 0, err = vnet_walk_rx_one(port, dr, start, &ack); | ||
369 | if (err == -ECONNRESET) | ||
370 | return err; | ||
371 | if (err != 0) | ||
372 | break; | ||
373 | if (ack_start == -1) | ||
374 | ack_start = start; | ||
375 | ack_end = start; | ||
376 | start = next_idx(start, dr); | ||
377 | if (ack && start != end) { | ||
378 | err = vnet_send_ack(port, dr, ack_start, ack_end, | ||
379 | VIO_DRING_ACTIVE); | ||
380 | if (err == -ECONNRESET) | ||
381 | return err; | ||
382 | ack_start = -1; | ||
383 | } | ||
384 | } | ||
385 | if (unlikely(ack_start == -1)) | ||
386 | ack_start = ack_end = prev_idx(start, dr); | ||
387 | return vnet_send_ack(port, dr, ack_start, ack_end, VIO_DRING_STOPPED); | ||
388 | } | ||
389 | |||
390 | static int vnet_rx(struct vnet_port *port, void *msgbuf) | ||
391 | { | ||
392 | struct vio_dring_data *pkt = msgbuf; | ||
393 | struct vio_dring_state *dr = &port->vio.drings[VIO_DRIVER_RX_RING]; | ||
394 | struct vio_driver_state *vio = &port->vio; | ||
395 | |||
396 | viodbg(DATA, "vnet_rx stype_env[%04x] seq[%016lx] rcv_nxt[%016lx]\n", | ||
397 | pkt->tag.stype_env, pkt->seq, dr->rcv_nxt); | ||
398 | |||
399 | if (unlikely(pkt->tag.stype_env != VIO_DRING_DATA)) | ||
400 | return 0; | ||
401 | if (unlikely(pkt->seq != dr->rcv_nxt)) { | ||
402 | printk(KERN_ERR PFX "RX out of sequence seq[0x%lx] " | ||
403 | "rcv_nxt[0x%lx]\n", pkt->seq, dr->rcv_nxt); | ||
404 | return 0; | ||
405 | } | ||
406 | |||
407 | dr->rcv_nxt++; | ||
408 | |||
409 | /* XXX Validate pkt->start_idx and pkt->end_idx XXX */ | ||
410 | |||
411 | return vnet_walk_rx(port, dr, pkt->start_idx, pkt->end_idx); | ||
412 | } | ||
413 | |||
414 | static int idx_is_pending(struct vio_dring_state *dr, u32 end) | ||
415 | { | ||
416 | u32 idx = dr->cons; | ||
417 | int found = 0; | ||
418 | |||
419 | while (idx != dr->prod) { | ||
420 | if (idx == end) { | ||
421 | found = 1; | ||
422 | break; | ||
423 | } | ||
424 | idx = next_idx(idx, dr); | ||
425 | } | ||
426 | return found; | ||
427 | } | ||
428 | |||
429 | static int vnet_ack(struct vnet_port *port, void *msgbuf) | ||
430 | { | ||
431 | struct vio_dring_state *dr = &port->vio.drings[VIO_DRIVER_TX_RING]; | ||
432 | struct vio_dring_data *pkt = msgbuf; | ||
433 | struct net_device *dev; | ||
434 | struct vnet *vp; | ||
435 | u32 end; | ||
436 | |||
437 | if (unlikely(pkt->tag.stype_env != VIO_DRING_DATA)) | ||
438 | return 0; | ||
439 | |||
440 | end = pkt->end_idx; | ||
441 | if (unlikely(!idx_is_pending(dr, end))) | ||
442 | return 0; | ||
443 | |||
444 | dr->cons = next_idx(end, dr); | ||
445 | |||
446 | vp = port->vp; | ||
447 | dev = vp->dev; | ||
448 | if (unlikely(netif_queue_stopped(dev) && | ||
449 | vnet_tx_dring_avail(dr) >= VNET_TX_WAKEUP_THRESH(dr))) | ||
450 | return 1; | ||
451 | |||
452 | return 0; | ||
453 | } | ||
454 | |||
455 | static int vnet_nack(struct vnet_port *port, void *msgbuf) | ||
456 | { | ||
457 | /* XXX just reset or similar XXX */ | ||
458 | return 0; | ||
459 | } | ||
460 | |||
461 | static void maybe_tx_wakeup(struct vnet *vp) | ||
462 | { | ||
463 | struct net_device *dev = vp->dev; | ||
464 | |||
465 | netif_tx_lock(dev); | ||
466 | if (likely(netif_queue_stopped(dev))) { | ||
467 | struct vnet_port *port; | ||
468 | int wake = 1; | ||
469 | |||
470 | list_for_each_entry(port, &vp->port_list, list) { | ||
471 | struct vio_dring_state *dr; | ||
472 | |||
473 | dr = &port->vio.drings[VIO_DRIVER_TX_RING]; | ||
474 | if (vnet_tx_dring_avail(dr) < | ||
475 | VNET_TX_WAKEUP_THRESH(dr)) { | ||
476 | wake = 0; | ||
477 | break; | ||
478 | } | ||
479 | } | ||
480 | if (wake) | ||
481 | netif_wake_queue(dev); | ||
482 | } | ||
483 | netif_tx_unlock(dev); | ||
484 | } | ||
485 | |||
486 | static void vnet_event(void *arg, int event) | ||
487 | { | ||
488 | struct vnet_port *port = arg; | ||
489 | struct vio_driver_state *vio = &port->vio; | ||
490 | unsigned long flags; | ||
491 | int tx_wakeup, err; | ||
492 | |||
493 | spin_lock_irqsave(&vio->lock, flags); | ||
494 | |||
495 | if (unlikely(event == LDC_EVENT_RESET || | ||
496 | event == LDC_EVENT_UP)) { | ||
497 | vio_link_state_change(vio, event); | ||
498 | spin_unlock_irqrestore(&vio->lock, flags); | ||
499 | |||
500 | return; | ||
501 | } | ||
502 | |||
503 | if (unlikely(event != LDC_EVENT_DATA_READY)) { | ||
504 | printk(KERN_WARNING PFX "Unexpected LDC event %d\n", event); | ||
505 | spin_unlock_irqrestore(&vio->lock, flags); | ||
506 | return; | ||
507 | } | ||
508 | |||
509 | tx_wakeup = err = 0; | ||
510 | while (1) { | ||
511 | union { | ||
512 | struct vio_msg_tag tag; | ||
513 | u64 raw[8]; | ||
514 | } msgbuf; | ||
515 | |||
516 | err = ldc_read(vio->lp, &msgbuf, sizeof(msgbuf)); | ||
517 | if (unlikely(err < 0)) { | ||
518 | if (err == -ECONNRESET) | ||
519 | vio_conn_reset(vio); | ||
520 | break; | ||
521 | } | ||
522 | if (err == 0) | ||
523 | break; | ||
524 | viodbg(DATA, "TAG [%02x:%02x:%04x:%08x]\n", | ||
525 | msgbuf.tag.type, | ||
526 | msgbuf.tag.stype, | ||
527 | msgbuf.tag.stype_env, | ||
528 | msgbuf.tag.sid); | ||
529 | err = vio_validate_sid(vio, &msgbuf.tag); | ||
530 | if (err < 0) | ||
531 | break; | ||
532 | |||
533 | if (likely(msgbuf.tag.type == VIO_TYPE_DATA)) { | ||
534 | if (msgbuf.tag.stype == VIO_SUBTYPE_INFO) { | ||
535 | err = vnet_rx(port, &msgbuf); | ||
536 | } else if (msgbuf.tag.stype == VIO_SUBTYPE_ACK) { | ||
537 | err = vnet_ack(port, &msgbuf); | ||
538 | if (err > 0) | ||
539 | tx_wakeup |= err; | ||
540 | } else if (msgbuf.tag.stype == VIO_SUBTYPE_NACK) { | ||
541 | err = vnet_nack(port, &msgbuf); | ||
542 | } | ||
543 | } else if (msgbuf.tag.type == VIO_TYPE_CTRL) { | ||
544 | err = vio_control_pkt_engine(vio, &msgbuf); | ||
545 | if (err) | ||
546 | break; | ||
547 | } else { | ||
548 | err = vnet_handle_unknown(port, &msgbuf); | ||
549 | } | ||
550 | if (err == -ECONNRESET) | ||
551 | break; | ||
552 | } | ||
553 | spin_unlock(&vio->lock); | ||
554 | if (unlikely(tx_wakeup && err != -ECONNRESET)) | ||
555 | maybe_tx_wakeup(port->vp); | ||
556 | local_irq_restore(flags); | ||
557 | } | ||
558 | |||
559 | static int __vnet_tx_trigger(struct vnet_port *port) | ||
560 | { | ||
561 | struct vio_dring_state *dr = &port->vio.drings[VIO_DRIVER_TX_RING]; | ||
562 | struct vio_dring_data hdr = { | ||
563 | .tag = { | ||
564 | .type = VIO_TYPE_DATA, | ||
565 | .stype = VIO_SUBTYPE_INFO, | ||
566 | .stype_env = VIO_DRING_DATA, | ||
567 | .sid = vio_send_sid(&port->vio), | ||
568 | }, | ||
569 | .dring_ident = dr->ident, | ||
570 | .start_idx = dr->prod, | ||
571 | .end_idx = (u32) -1, | ||
572 | }; | ||
573 | int err, delay; | ||
574 | |||
575 | hdr.seq = dr->snd_nxt; | ||
576 | delay = 1; | ||
577 | do { | ||
578 | err = vio_ldc_send(&port->vio, &hdr, sizeof(hdr)); | ||
579 | if (err > 0) { | ||
580 | dr->snd_nxt++; | ||
581 | break; | ||
582 | } | ||
583 | udelay(delay); | ||
584 | if ((delay <<= 1) > 128) | ||
585 | delay = 128; | ||
586 | } while (err == -EAGAIN); | ||
587 | |||
588 | return err; | ||
589 | } | ||
590 | |||
591 | struct vnet_port *__tx_port_find(struct vnet *vp, struct sk_buff *skb) | ||
592 | { | ||
593 | unsigned int hash = vnet_hashfn(skb->data); | ||
594 | struct hlist_head *hp = &vp->port_hash[hash]; | ||
595 | struct hlist_node *n; | ||
596 | struct vnet_port *port; | ||
597 | |||
598 | hlist_for_each_entry(port, n, hp, hash) { | ||
599 | if (!compare_ether_addr(port->raddr, skb->data)) | ||
600 | return port; | ||
601 | } | ||
602 | port = NULL; | ||
603 | if (!list_empty(&vp->port_list)) | ||
604 | port = list_entry(vp->port_list.next, struct vnet_port, list); | ||
605 | |||
606 | return port; | ||
607 | } | ||
608 | |||
609 | struct vnet_port *tx_port_find(struct vnet *vp, struct sk_buff *skb) | ||
610 | { | ||
611 | struct vnet_port *ret; | ||
612 | unsigned long flags; | ||
613 | |||
614 | spin_lock_irqsave(&vp->lock, flags); | ||
615 | ret = __tx_port_find(vp, skb); | ||
616 | spin_unlock_irqrestore(&vp->lock, flags); | ||
617 | |||
618 | return ret; | ||
619 | } | ||
620 | |||
621 | static int vnet_start_xmit(struct sk_buff *skb, struct net_device *dev) | ||
622 | { | ||
623 | struct vnet *vp = netdev_priv(dev); | ||
624 | struct vnet_port *port = tx_port_find(vp, skb); | ||
625 | struct vio_dring_state *dr; | ||
626 | struct vio_net_desc *d; | ||
627 | unsigned long flags; | ||
628 | unsigned int len; | ||
629 | void *tx_buf; | ||
630 | int i, err; | ||
631 | |||
632 | if (unlikely(!port)) | ||
633 | goto out_dropped; | ||
634 | |||
635 | spin_lock_irqsave(&port->vio.lock, flags); | ||
636 | |||
637 | dr = &port->vio.drings[VIO_DRIVER_TX_RING]; | ||
638 | if (unlikely(vnet_tx_dring_avail(dr) < 2)) { | ||
639 | if (!netif_queue_stopped(dev)) { | ||
640 | netif_stop_queue(dev); | ||
641 | |||
642 | /* This is a hard error, log it. */ | ||
643 | printk(KERN_ERR PFX "%s: BUG! Tx Ring full when " | ||
644 | "queue awake!\n", dev->name); | ||
645 | dev->stats.tx_errors++; | ||
646 | } | ||
647 | spin_unlock_irqrestore(&port->vio.lock, flags); | ||
648 | return NETDEV_TX_BUSY; | ||
649 | } | ||
650 | |||
651 | d = vio_dring_cur(dr); | ||
652 | |||
653 | tx_buf = port->tx_bufs[dr->prod].buf; | ||
654 | skb_copy_from_linear_data(skb, tx_buf + VNET_PACKET_SKIP, skb->len); | ||
655 | |||
656 | len = skb->len; | ||
657 | if (len < ETH_ZLEN) { | ||
658 | len = ETH_ZLEN; | ||
659 | memset(tx_buf+VNET_PACKET_SKIP+skb->len, 0, len - skb->len); | ||
660 | } | ||
661 | |||
662 | d->hdr.ack = VIO_ACK_ENABLE; | ||
663 | d->size = len; | ||
664 | d->ncookies = port->tx_bufs[dr->prod].ncookies; | ||
665 | for (i = 0; i < d->ncookies; i++) | ||
666 | d->cookies[i] = port->tx_bufs[dr->prod].cookies[i]; | ||
667 | |||
668 | /* This has to be a non-SMP write barrier because we are writing | ||
669 | * to memory which is shared with the peer LDOM. | ||
670 | */ | ||
671 | wmb(); | ||
672 | |||
673 | d->hdr.state = VIO_DESC_READY; | ||
674 | |||
675 | err = __vnet_tx_trigger(port); | ||
676 | if (unlikely(err < 0)) { | ||
677 | printk(KERN_INFO PFX "%s: TX trigger error %d\n", | ||
678 | dev->name, err); | ||
679 | d->hdr.state = VIO_DESC_FREE; | ||
680 | dev->stats.tx_carrier_errors++; | ||
681 | goto out_dropped_unlock; | ||
682 | } | ||
683 | |||
684 | dev->stats.tx_packets++; | ||
685 | dev->stats.tx_bytes += skb->len; | ||
686 | |||
687 | dr->prod = (dr->prod + 1) & (VNET_TX_RING_SIZE - 1); | ||
688 | if (unlikely(vnet_tx_dring_avail(dr) < 2)) { | ||
689 | netif_stop_queue(dev); | ||
690 | if (vnet_tx_dring_avail(dr) > VNET_TX_WAKEUP_THRESH(dr)) | ||
691 | netif_wake_queue(dev); | ||
692 | } | ||
693 | |||
694 | spin_unlock_irqrestore(&port->vio.lock, flags); | ||
695 | |||
696 | dev_kfree_skb(skb); | ||
697 | |||
698 | dev->trans_start = jiffies; | ||
699 | return NETDEV_TX_OK; | ||
700 | |||
701 | out_dropped_unlock: | ||
702 | spin_unlock_irqrestore(&port->vio.lock, flags); | ||
703 | |||
704 | out_dropped: | ||
705 | dev_kfree_skb(skb); | ||
706 | dev->stats.tx_dropped++; | ||
707 | return NETDEV_TX_OK; | ||
708 | } | ||
709 | |||
710 | static void vnet_tx_timeout(struct net_device *dev) | ||
711 | { | ||
712 | /* XXX Implement me XXX */ | ||
713 | } | ||
714 | |||
715 | static int vnet_open(struct net_device *dev) | ||
716 | { | ||
717 | netif_carrier_on(dev); | ||
718 | netif_start_queue(dev); | ||
719 | |||
720 | return 0; | ||
721 | } | ||
722 | |||
723 | static int vnet_close(struct net_device *dev) | ||
724 | { | ||
725 | netif_stop_queue(dev); | ||
726 | netif_carrier_off(dev); | ||
727 | |||
728 | return 0; | ||
729 | } | ||
730 | |||
731 | static void vnet_set_rx_mode(struct net_device *dev) | ||
732 | { | ||
733 | /* XXX Implement multicast support XXX */ | ||
734 | } | ||
735 | |||
736 | static int vnet_change_mtu(struct net_device *dev, int new_mtu) | ||
737 | { | ||
738 | if (new_mtu != ETH_DATA_LEN) | ||
739 | return -EINVAL; | ||
740 | |||
741 | dev->mtu = new_mtu; | ||
742 | return 0; | ||
743 | } | ||
744 | |||
745 | static int vnet_set_mac_addr(struct net_device *dev, void *p) | ||
746 | { | ||
747 | return -EINVAL; | ||
748 | } | ||
749 | |||
750 | static void vnet_get_drvinfo(struct net_device *dev, | ||
751 | struct ethtool_drvinfo *info) | ||
752 | { | ||
753 | strcpy(info->driver, DRV_MODULE_NAME); | ||
754 | strcpy(info->version, DRV_MODULE_VERSION); | ||
755 | } | ||
756 | |||
757 | static u32 vnet_get_msglevel(struct net_device *dev) | ||
758 | { | ||
759 | struct vnet *vp = netdev_priv(dev); | ||
760 | return vp->msg_enable; | ||
761 | } | ||
762 | |||
763 | static void vnet_set_msglevel(struct net_device *dev, u32 value) | ||
764 | { | ||
765 | struct vnet *vp = netdev_priv(dev); | ||
766 | vp->msg_enable = value; | ||
767 | } | ||
768 | |||
769 | static const struct ethtool_ops vnet_ethtool_ops = { | ||
770 | .get_drvinfo = vnet_get_drvinfo, | ||
771 | .get_msglevel = vnet_get_msglevel, | ||
772 | .set_msglevel = vnet_set_msglevel, | ||
773 | .get_link = ethtool_op_get_link, | ||
774 | .get_perm_addr = ethtool_op_get_perm_addr, | ||
775 | }; | ||
776 | |||
777 | static void vnet_port_free_tx_bufs(struct vnet_port *port) | ||
778 | { | ||
779 | struct vio_dring_state *dr; | ||
780 | int i; | ||
781 | |||
782 | dr = &port->vio.drings[VIO_DRIVER_TX_RING]; | ||
783 | if (dr->base) { | ||
784 | ldc_free_exp_dring(port->vio.lp, dr->base, | ||
785 | (dr->entry_size * dr->num_entries), | ||
786 | dr->cookies, dr->ncookies); | ||
787 | dr->base = NULL; | ||
788 | dr->entry_size = 0; | ||
789 | dr->num_entries = 0; | ||
790 | dr->pending = 0; | ||
791 | dr->ncookies = 0; | ||
792 | } | ||
793 | |||
794 | for (i = 0; i < VNET_TX_RING_SIZE; i++) { | ||
795 | void *buf = port->tx_bufs[i].buf; | ||
796 | |||
797 | if (!buf) | ||
798 | continue; | ||
799 | |||
800 | ldc_unmap(port->vio.lp, | ||
801 | port->tx_bufs[i].cookies, | ||
802 | port->tx_bufs[i].ncookies); | ||
803 | |||
804 | kfree(buf); | ||
805 | port->tx_bufs[i].buf = NULL; | ||
806 | } | ||
807 | } | ||
808 | |||
809 | static int __devinit vnet_port_alloc_tx_bufs(struct vnet_port *port) | ||
810 | { | ||
811 | struct vio_dring_state *dr; | ||
812 | unsigned long len; | ||
813 | int i, err, ncookies; | ||
814 | void *dring; | ||
815 | |||
816 | for (i = 0; i < VNET_TX_RING_SIZE; i++) { | ||
817 | void *buf = kzalloc(ETH_FRAME_LEN + 8, GFP_KERNEL); | ||
818 | int map_len = (ETH_FRAME_LEN + 7) & ~7; | ||
819 | |||
820 | err = -ENOMEM; | ||
821 | if (!buf) { | ||
822 | printk(KERN_ERR "TX buffer allocation failure\n"); | ||
823 | goto err_out; | ||
824 | } | ||
825 | err = -EFAULT; | ||
826 | if ((unsigned long)buf & (8UL - 1)) { | ||
827 | printk(KERN_ERR "TX buffer misaligned\n"); | ||
828 | kfree(buf); | ||
829 | goto err_out; | ||
830 | } | ||
831 | |||
832 | err = ldc_map_single(port->vio.lp, buf, map_len, | ||
833 | port->tx_bufs[i].cookies, 2, | ||
834 | (LDC_MAP_SHADOW | | ||
835 | LDC_MAP_DIRECT | | ||
836 | LDC_MAP_RW)); | ||
837 | if (err < 0) { | ||
838 | kfree(buf); | ||
839 | goto err_out; | ||
840 | } | ||
841 | port->tx_bufs[i].buf = buf; | ||
842 | port->tx_bufs[i].ncookies = err; | ||
843 | } | ||
844 | |||
845 | dr = &port->vio.drings[VIO_DRIVER_TX_RING]; | ||
846 | |||
847 | len = (VNET_TX_RING_SIZE * | ||
848 | (sizeof(struct vio_net_desc) + | ||
849 | (sizeof(struct ldc_trans_cookie) * 2))); | ||
850 | |||
851 | ncookies = VIO_MAX_RING_COOKIES; | ||
852 | dring = ldc_alloc_exp_dring(port->vio.lp, len, | ||
853 | dr->cookies, &ncookies, | ||
854 | (LDC_MAP_SHADOW | | ||
855 | LDC_MAP_DIRECT | | ||
856 | LDC_MAP_RW)); | ||
857 | if (IS_ERR(dring)) { | ||
858 | err = PTR_ERR(dring); | ||
859 | goto err_out; | ||
860 | } | ||
861 | |||
862 | dr->base = dring; | ||
863 | dr->entry_size = (sizeof(struct vio_net_desc) + | ||
864 | (sizeof(struct ldc_trans_cookie) * 2)); | ||
865 | dr->num_entries = VNET_TX_RING_SIZE; | ||
866 | dr->prod = dr->cons = 0; | ||
867 | dr->pending = VNET_TX_RING_SIZE; | ||
868 | dr->ncookies = ncookies; | ||
869 | |||
870 | return 0; | ||
871 | |||
872 | err_out: | ||
873 | vnet_port_free_tx_bufs(port); | ||
874 | |||
875 | return err; | ||
876 | } | ||
877 | |||
878 | static struct ldc_channel_config vnet_ldc_cfg = { | ||
879 | .event = vnet_event, | ||
880 | .mtu = 64, | ||
881 | .mode = LDC_MODE_UNRELIABLE, | ||
882 | }; | ||
883 | |||
884 | static struct vio_driver_ops vnet_vio_ops = { | ||
885 | .send_attr = vnet_send_attr, | ||
886 | .handle_attr = vnet_handle_attr, | ||
887 | .handshake_complete = vnet_handshake_complete, | ||
888 | }; | ||
889 | |||
890 | const char *remote_macaddr_prop = "remote-mac-address"; | ||
891 | |||
892 | static int __devinit vnet_port_probe(struct vio_dev *vdev, | ||
893 | const struct vio_device_id *id) | ||
894 | { | ||
895 | struct mdesc_handle *hp; | ||
896 | struct vnet_port *port; | ||
897 | unsigned long flags; | ||
898 | struct vnet *vp; | ||
899 | const u64 *rmac; | ||
900 | int len, i, err, switch_port; | ||
901 | |||
902 | vp = dev_get_drvdata(vdev->dev.parent); | ||
903 | if (!vp) { | ||
904 | printk(KERN_ERR PFX "Cannot find port parent vnet.\n"); | ||
905 | return -ENODEV; | ||
906 | } | ||
907 | |||
908 | hp = mdesc_grab(); | ||
909 | |||
910 | rmac = mdesc_get_property(hp, vdev->mp, remote_macaddr_prop, &len); | ||
911 | err = -ENODEV; | ||
912 | if (!rmac) { | ||
913 | printk(KERN_ERR PFX "Port lacks %s property.\n", | ||
914 | remote_macaddr_prop); | ||
915 | goto err_out_put_mdesc; | ||
916 | } | ||
917 | |||
918 | port = kzalloc(sizeof(*port), GFP_KERNEL); | ||
919 | err = -ENOMEM; | ||
920 | if (!port) { | ||
921 | printk(KERN_ERR PFX "Cannot allocate vnet_port.\n"); | ||
922 | goto err_out_put_mdesc; | ||
923 | } | ||
924 | |||
925 | for (i = 0; i < ETH_ALEN; i++) | ||
926 | port->raddr[i] = (*rmac >> (5 - i) * 8) & 0xff; | ||
927 | |||
928 | port->vp = vp; | ||
929 | |||
930 | err = vio_driver_init(&port->vio, vdev, VDEV_NETWORK, | ||
931 | vnet_versions, ARRAY_SIZE(vnet_versions), | ||
932 | &vnet_vio_ops, vp->dev->name); | ||
933 | if (err) | ||
934 | goto err_out_free_port; | ||
935 | |||
936 | err = vio_ldc_alloc(&port->vio, &vnet_ldc_cfg, port); | ||
937 | if (err) | ||
938 | goto err_out_free_port; | ||
939 | |||
940 | err = vnet_port_alloc_tx_bufs(port); | ||
941 | if (err) | ||
942 | goto err_out_free_ldc; | ||
943 | |||
944 | INIT_HLIST_NODE(&port->hash); | ||
945 | INIT_LIST_HEAD(&port->list); | ||
946 | |||
947 | switch_port = 0; | ||
948 | if (mdesc_get_property(hp, vdev->mp, "switch-port", NULL) != NULL) | ||
949 | switch_port = 1; | ||
950 | |||
951 | spin_lock_irqsave(&vp->lock, flags); | ||
952 | if (switch_port) | ||
953 | list_add(&port->list, &vp->port_list); | ||
954 | else | ||
955 | list_add_tail(&port->list, &vp->port_list); | ||
956 | hlist_add_head(&port->hash, &vp->port_hash[vnet_hashfn(port->raddr)]); | ||
957 | spin_unlock_irqrestore(&vp->lock, flags); | ||
958 | |||
959 | dev_set_drvdata(&vdev->dev, port); | ||
960 | |||
961 | printk(KERN_INFO "%s: PORT ( remote-mac ", vp->dev->name); | ||
962 | for (i = 0; i < 6; i++) | ||
963 | printk("%2.2x%c", port->raddr[i], i == 5 ? ' ' : ':'); | ||
964 | if (switch_port) | ||
965 | printk("switch-port "); | ||
966 | printk(")\n"); | ||
967 | |||
968 | vio_port_up(&port->vio); | ||
969 | |||
970 | mdesc_release(hp); | ||
971 | |||
972 | return 0; | ||
973 | |||
974 | err_out_free_ldc: | ||
975 | vio_ldc_free(&port->vio); | ||
976 | |||
977 | err_out_free_port: | ||
978 | kfree(port); | ||
979 | |||
980 | err_out_put_mdesc: | ||
981 | mdesc_release(hp); | ||
982 | return err; | ||
983 | } | ||
984 | |||
985 | static int vnet_port_remove(struct vio_dev *vdev) | ||
986 | { | ||
987 | struct vnet_port *port = dev_get_drvdata(&vdev->dev); | ||
988 | |||
989 | if (port) { | ||
990 | struct vnet *vp = port->vp; | ||
991 | unsigned long flags; | ||
992 | |||
993 | del_timer_sync(&port->vio.timer); | ||
994 | |||
995 | spin_lock_irqsave(&vp->lock, flags); | ||
996 | list_del(&port->list); | ||
997 | hlist_del(&port->hash); | ||
998 | spin_unlock_irqrestore(&vp->lock, flags); | ||
999 | |||
1000 | vnet_port_free_tx_bufs(port); | ||
1001 | vio_ldc_free(&port->vio); | ||
1002 | |||
1003 | dev_set_drvdata(&vdev->dev, NULL); | ||
1004 | |||
1005 | kfree(port); | ||
1006 | } | ||
1007 | return 0; | ||
1008 | } | ||
1009 | |||
1010 | static struct vio_device_id vnet_port_match[] = { | ||
1011 | { | ||
1012 | .type = "vnet-port", | ||
1013 | }, | ||
1014 | {}, | ||
1015 | }; | ||
1016 | MODULE_DEVICE_TABLE(vio, vnet_match); | ||
1017 | |||
1018 | static struct vio_driver vnet_port_driver = { | ||
1019 | .id_table = vnet_port_match, | ||
1020 | .probe = vnet_port_probe, | ||
1021 | .remove = vnet_port_remove, | ||
1022 | .driver = { | ||
1023 | .name = "vnet_port", | ||
1024 | .owner = THIS_MODULE, | ||
1025 | } | ||
1026 | }; | ||
1027 | |||
1028 | const char *local_mac_prop = "local-mac-address"; | ||
1029 | |||
1030 | static int __devinit vnet_probe(struct vio_dev *vdev, | ||
1031 | const struct vio_device_id *id) | ||
1032 | { | ||
1033 | static int vnet_version_printed; | ||
1034 | struct mdesc_handle *hp; | ||
1035 | struct net_device *dev; | ||
1036 | struct vnet *vp; | ||
1037 | const u64 *mac; | ||
1038 | int err, i, len; | ||
1039 | |||
1040 | if (vnet_version_printed++ == 0) | ||
1041 | printk(KERN_INFO "%s", version); | ||
1042 | |||
1043 | hp = mdesc_grab(); | ||
1044 | |||
1045 | mac = mdesc_get_property(hp, vdev->mp, local_mac_prop, &len); | ||
1046 | if (!mac) { | ||
1047 | printk(KERN_ERR PFX "vnet lacks %s property.\n", | ||
1048 | local_mac_prop); | ||
1049 | err = -ENODEV; | ||
1050 | goto err_out; | ||
1051 | } | ||
1052 | |||
1053 | dev = alloc_etherdev(sizeof(*vp)); | ||
1054 | if (!dev) { | ||
1055 | printk(KERN_ERR PFX "Etherdev alloc failed, aborting.\n"); | ||
1056 | err = -ENOMEM; | ||
1057 | goto err_out; | ||
1058 | } | ||
1059 | |||
1060 | for (i = 0; i < ETH_ALEN; i++) | ||
1061 | dev->dev_addr[i] = (*mac >> (5 - i) * 8) & 0xff; | ||
1062 | |||
1063 | memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); | ||
1064 | |||
1065 | SET_NETDEV_DEV(dev, &vdev->dev); | ||
1066 | |||
1067 | vp = netdev_priv(dev); | ||
1068 | |||
1069 | spin_lock_init(&vp->lock); | ||
1070 | vp->dev = dev; | ||
1071 | vp->vdev = vdev; | ||
1072 | |||
1073 | INIT_LIST_HEAD(&vp->port_list); | ||
1074 | for (i = 0; i < VNET_PORT_HASH_SIZE; i++) | ||
1075 | INIT_HLIST_HEAD(&vp->port_hash[i]); | ||
1076 | |||
1077 | dev->open = vnet_open; | ||
1078 | dev->stop = vnet_close; | ||
1079 | dev->set_multicast_list = vnet_set_rx_mode; | ||
1080 | dev->set_mac_address = vnet_set_mac_addr; | ||
1081 | dev->tx_timeout = vnet_tx_timeout; | ||
1082 | dev->ethtool_ops = &vnet_ethtool_ops; | ||
1083 | dev->watchdog_timeo = VNET_TX_TIMEOUT; | ||
1084 | dev->change_mtu = vnet_change_mtu; | ||
1085 | dev->hard_start_xmit = vnet_start_xmit; | ||
1086 | |||
1087 | err = register_netdev(dev); | ||
1088 | if (err) { | ||
1089 | printk(KERN_ERR PFX "Cannot register net device, " | ||
1090 | "aborting.\n"); | ||
1091 | goto err_out_free_dev; | ||
1092 | } | ||
1093 | |||
1094 | printk(KERN_INFO "%s: Sun LDOM vnet ", dev->name); | ||
1095 | |||
1096 | for (i = 0; i < 6; i++) | ||
1097 | printk("%2.2x%c", dev->dev_addr[i], i == 5 ? '\n' : ':'); | ||
1098 | |||
1099 | dev_set_drvdata(&vdev->dev, vp); | ||
1100 | |||
1101 | mdesc_release(hp); | ||
1102 | |||
1103 | return 0; | ||
1104 | |||
1105 | err_out_free_dev: | ||
1106 | free_netdev(dev); | ||
1107 | |||
1108 | err_out: | ||
1109 | mdesc_release(hp); | ||
1110 | return err; | ||
1111 | } | ||
1112 | |||
1113 | static int vnet_remove(struct vio_dev *vdev) | ||
1114 | { | ||
1115 | |||
1116 | struct vnet *vp = dev_get_drvdata(&vdev->dev); | ||
1117 | |||
1118 | if (vp) { | ||
1119 | /* XXX unregister port, or at least check XXX */ | ||
1120 | unregister_netdevice(vp->dev); | ||
1121 | dev_set_drvdata(&vdev->dev, NULL); | ||
1122 | } | ||
1123 | return 0; | ||
1124 | } | ||
1125 | |||
1126 | static struct vio_device_id vnet_match[] = { | ||
1127 | { | ||
1128 | .type = "network", | ||
1129 | }, | ||
1130 | {}, | ||
1131 | }; | ||
1132 | MODULE_DEVICE_TABLE(vio, vnet_match); | ||
1133 | |||
1134 | static struct vio_driver vnet_driver = { | ||
1135 | .id_table = vnet_match, | ||
1136 | .probe = vnet_probe, | ||
1137 | .remove = vnet_remove, | ||
1138 | .driver = { | ||
1139 | .name = "vnet", | ||
1140 | .owner = THIS_MODULE, | ||
1141 | } | ||
1142 | }; | ||
1143 | |||
1144 | static int __init vnet_init(void) | ||
1145 | { | ||
1146 | int err = vio_register_driver(&vnet_driver); | ||
1147 | |||
1148 | if (!err) { | ||
1149 | err = vio_register_driver(&vnet_port_driver); | ||
1150 | if (err) | ||
1151 | vio_unregister_driver(&vnet_driver); | ||
1152 | } | ||
1153 | |||
1154 | return err; | ||
1155 | } | ||
1156 | |||
1157 | static void __exit vnet_exit(void) | ||
1158 | { | ||
1159 | vio_unregister_driver(&vnet_port_driver); | ||
1160 | vio_unregister_driver(&vnet_driver); | ||
1161 | } | ||
1162 | |||
1163 | module_init(vnet_init); | ||
1164 | module_exit(vnet_exit); | ||
diff --git a/drivers/net/sunvnet.h b/drivers/net/sunvnet.h new file mode 100644 index 000000000000..1c887302d46d --- /dev/null +++ b/drivers/net/sunvnet.h | |||
@@ -0,0 +1,70 @@ | |||
1 | #ifndef _SUNVNET_H | ||
2 | #define _SUNVNET_H | ||
3 | |||
4 | #define DESC_NCOOKIES(entry_size) \ | ||
5 | ((entry_size) - sizeof(struct vio_net_desc)) | ||
6 | |||
7 | /* length of time before we decide the hardware is borked, | ||
8 | * and dev->tx_timeout() should be called to fix the problem | ||
9 | */ | ||
10 | #define VNET_TX_TIMEOUT (5 * HZ) | ||
11 | |||
12 | #define VNET_TX_RING_SIZE 512 | ||
13 | #define VNET_TX_WAKEUP_THRESH(dr) ((dr)->pending / 4) | ||
14 | |||
15 | /* VNET packets are sent in buffers with the first 6 bytes skipped | ||
16 | * so that after the ethernet header the IPv4/IPv6 headers are aligned | ||
17 | * properly. | ||
18 | */ | ||
19 | #define VNET_PACKET_SKIP 6 | ||
20 | |||
21 | struct vnet_tx_entry { | ||
22 | void *buf; | ||
23 | unsigned int ncookies; | ||
24 | struct ldc_trans_cookie cookies[2]; | ||
25 | }; | ||
26 | |||
27 | struct vnet; | ||
28 | struct vnet_port { | ||
29 | struct vio_driver_state vio; | ||
30 | |||
31 | struct hlist_node hash; | ||
32 | u8 raddr[ETH_ALEN]; | ||
33 | |||
34 | struct vnet *vp; | ||
35 | |||
36 | struct vnet_tx_entry tx_bufs[VNET_TX_RING_SIZE]; | ||
37 | |||
38 | struct list_head list; | ||
39 | }; | ||
40 | |||
41 | static inline struct vnet_port *to_vnet_port(struct vio_driver_state *vio) | ||
42 | { | ||
43 | return container_of(vio, struct vnet_port, vio); | ||
44 | } | ||
45 | |||
46 | #define VNET_PORT_HASH_SIZE 16 | ||
47 | #define VNET_PORT_HASH_MASK (VNET_PORT_HASH_SIZE - 1) | ||
48 | |||
49 | static inline unsigned int vnet_hashfn(u8 *mac) | ||
50 | { | ||
51 | unsigned int val = mac[4] ^ mac[5]; | ||
52 | |||
53 | return val & (VNET_PORT_HASH_MASK); | ||
54 | } | ||
55 | |||
56 | struct vnet { | ||
57 | /* Protects port_list and port_hash. */ | ||
58 | spinlock_t lock; | ||
59 | |||
60 | struct net_device *dev; | ||
61 | |||
62 | u32 msg_enable; | ||
63 | struct vio_dev *vdev; | ||
64 | |||
65 | struct list_head port_list; | ||
66 | |||
67 | struct hlist_head port_hash[VNET_PORT_HASH_SIZE]; | ||
68 | }; | ||
69 | |||
70 | #endif /* _SUNVNET_H */ | ||
diff --git a/drivers/net/wan/Kconfig b/drivers/net/wan/Kconfig index 4fc8681bc110..a3df09ee729f 100644 --- a/drivers/net/wan/Kconfig +++ b/drivers/net/wan/Kconfig | |||
@@ -61,7 +61,7 @@ config COSA | |||
61 | # | 61 | # |
62 | config LANMEDIA | 62 | config LANMEDIA |
63 | tristate "LanMedia Corp. SSI/V.35, T1/E1, HSSI, T3 boards" | 63 | tristate "LanMedia Corp. SSI/V.35, T1/E1, HSSI, T3 boards" |
64 | depends on PCI | 64 | depends on PCI && VIRT_TO_BUS |
65 | ---help--- | 65 | ---help--- |
66 | Driver for the following Lan Media family of serial boards: | 66 | Driver for the following Lan Media family of serial boards: |
67 | 67 | ||
diff --git a/drivers/parport/Kconfig b/drivers/parport/Kconfig index f46c69e4ed82..09c93ff932b1 100644 --- a/drivers/parport/Kconfig +++ b/drivers/parport/Kconfig | |||
@@ -5,11 +5,9 @@ | |||
5 | # Parport configuration. | 5 | # Parport configuration. |
6 | # | 6 | # |
7 | 7 | ||
8 | menu "Parallel port support" | 8 | menuconfig PARPORT |
9 | depends on HAS_IOMEM | ||
10 | |||
11 | config PARPORT | ||
12 | tristate "Parallel port support" | 9 | tristate "Parallel port support" |
10 | depends on HAS_IOMEM | ||
13 | ---help--- | 11 | ---help--- |
14 | If you want to use devices connected to your machine's parallel port | 12 | If you want to use devices connected to your machine's parallel port |
15 | (the connector at the computer with 25 holes), e.g. printer, ZIP | 13 | (the connector at the computer with 25 holes), e.g. printer, ZIP |
@@ -33,9 +31,11 @@ config PARPORT | |||
33 | 31 | ||
34 | If unsure, say Y. | 32 | If unsure, say Y. |
35 | 33 | ||
34 | if PARPORT | ||
35 | |||
36 | config PARPORT_PC | 36 | config PARPORT_PC |
37 | tristate "PC-style hardware" | 37 | tristate "PC-style hardware" |
38 | depends on PARPORT && (!SPARC64 || PCI) && !SPARC32 && !M32R && !FRV | 38 | depends on (!SPARC64 || PCI) && !SPARC32 && !M32R && !FRV |
39 | ---help--- | 39 | ---help--- |
40 | You should say Y here if you have a PC-style parallel port. All | 40 | You should say Y here if you have a PC-style parallel port. All |
41 | IBM PC compatible computers and some Alphas have PC-style | 41 | IBM PC compatible computers and some Alphas have PC-style |
@@ -85,7 +85,7 @@ config PARPORT_PC_PCMCIA | |||
85 | 85 | ||
86 | config PARPORT_IP32 | 86 | config PARPORT_IP32 |
87 | tristate "SGI IP32 builtin port (EXPERIMENTAL)" | 87 | tristate "SGI IP32 builtin port (EXPERIMENTAL)" |
88 | depends on SGI_IP32 && PARPORT && EXPERIMENTAL | 88 | depends on SGI_IP32 && EXPERIMENTAL |
89 | select PARPORT_NOT_PC | 89 | select PARPORT_NOT_PC |
90 | help | 90 | help |
91 | Say Y here if you need support for the parallel port on | 91 | Say Y here if you need support for the parallel port on |
@@ -94,7 +94,7 @@ config PARPORT_IP32 | |||
94 | 94 | ||
95 | config PARPORT_AMIGA | 95 | config PARPORT_AMIGA |
96 | tristate "Amiga builtin port" | 96 | tristate "Amiga builtin port" |
97 | depends on AMIGA && PARPORT | 97 | depends on AMIGA |
98 | select PARPORT_NOT_PC | 98 | select PARPORT_NOT_PC |
99 | help | 99 | help |
100 | Say Y here if you need support for the parallel port hardware on | 100 | Say Y here if you need support for the parallel port hardware on |
@@ -103,7 +103,7 @@ config PARPORT_AMIGA | |||
103 | 103 | ||
104 | config PARPORT_MFC3 | 104 | config PARPORT_MFC3 |
105 | tristate "Multiface III parallel port" | 105 | tristate "Multiface III parallel port" |
106 | depends on ZORRO && PARPORT | 106 | depends on ZORRO |
107 | select PARPORT_NOT_PC | 107 | select PARPORT_NOT_PC |
108 | help | 108 | help |
109 | Say Y here if you need parallel port support for the MFC3 card. | 109 | Say Y here if you need parallel port support for the MFC3 card. |
@@ -112,7 +112,7 @@ config PARPORT_MFC3 | |||
112 | 112 | ||
113 | config PARPORT_ATARI | 113 | config PARPORT_ATARI |
114 | tristate "Atari hardware" | 114 | tristate "Atari hardware" |
115 | depends on ATARI && PARPORT | 115 | depends on ATARI |
116 | select PARPORT_NOT_PC | 116 | select PARPORT_NOT_PC |
117 | help | 117 | help |
118 | Say Y here if you need support for the parallel port hardware on | 118 | Say Y here if you need support for the parallel port hardware on |
@@ -122,12 +122,11 @@ config PARPORT_ATARI | |||
122 | config PARPORT_GSC | 122 | config PARPORT_GSC |
123 | tristate | 123 | tristate |
124 | default GSC | 124 | default GSC |
125 | depends on PARPORT | ||
126 | select PARPORT_NOT_PC | 125 | select PARPORT_NOT_PC |
127 | 126 | ||
128 | config PARPORT_SUNBPP | 127 | config PARPORT_SUNBPP |
129 | tristate "Sparc hardware (EXPERIMENTAL)" | 128 | tristate "Sparc hardware (EXPERIMENTAL)" |
130 | depends on SBUS && PARPORT && EXPERIMENTAL | 129 | depends on SBUS && EXPERIMENTAL |
131 | select PARPORT_NOT_PC | 130 | select PARPORT_NOT_PC |
132 | help | 131 | help |
133 | This driver provides support for the bidirectional parallel port | 132 | This driver provides support for the bidirectional parallel port |
@@ -136,7 +135,6 @@ config PARPORT_SUNBPP | |||
136 | 135 | ||
137 | config PARPORT_AX88796 | 136 | config PARPORT_AX88796 |
138 | tristate "AX88796 Parallel Port" | 137 | tristate "AX88796 Parallel Port" |
139 | depends on PARPORT | ||
140 | select PARPORT_NOT_PC | 138 | select PARPORT_NOT_PC |
141 | help | 139 | help |
142 | Say Y here if you need support for the parallel port hardware on | 140 | Say Y here if you need support for the parallel port hardware on |
@@ -148,7 +146,6 @@ config PARPORT_AX88796 | |||
148 | 146 | ||
149 | config PARPORT_1284 | 147 | config PARPORT_1284 |
150 | bool "IEEE 1284 transfer modes" | 148 | bool "IEEE 1284 transfer modes" |
151 | depends on PARPORT | ||
152 | help | 149 | help |
153 | If you have a printer that supports status readback or device ID, or | 150 | If you have a printer that supports status readback or device ID, or |
154 | want to use a device that uses enhanced parallel port transfer modes | 151 | want to use a device that uses enhanced parallel port transfer modes |
@@ -159,5 +156,4 @@ config PARPORT_1284 | |||
159 | config PARPORT_NOT_PC | 156 | config PARPORT_NOT_PC |
160 | bool | 157 | bool |
161 | 158 | ||
162 | endmenu | 159 | endif # PARPORT |
163 | |||
diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c index 7bfbad57879d..5d58ad55d85c 100644 --- a/drivers/parport/parport_pc.c +++ b/drivers/parport/parport_pc.c | |||
@@ -2424,7 +2424,6 @@ static int __devinit sio_ite_8872_probe (struct pci_dev *pdev, int autoirq, | |||
2424 | u32 ite8872set; | 2424 | u32 ite8872set; |
2425 | u32 ite8872_lpt, ite8872_lpthi; | 2425 | u32 ite8872_lpt, ite8872_lpthi; |
2426 | u8 ite8872_irq, type; | 2426 | u8 ite8872_irq, type; |
2427 | char *fake_name = "parport probe"; | ||
2428 | int irq; | 2427 | int irq; |
2429 | int i; | 2428 | int i; |
2430 | 2429 | ||
@@ -2432,11 +2431,11 @@ static int __devinit sio_ite_8872_probe (struct pci_dev *pdev, int autoirq, | |||
2432 | 2431 | ||
2433 | // make sure which one chip | 2432 | // make sure which one chip |
2434 | for(i = 0; i < 5; i++) { | 2433 | for(i = 0; i < 5; i++) { |
2435 | base_res = request_region(inta_addr[i], 0x8, fake_name); | 2434 | base_res = request_region(inta_addr[i], 32, "it887x"); |
2436 | if (base_res) { | 2435 | if (base_res) { |
2437 | int test; | 2436 | int test; |
2438 | pci_write_config_dword (pdev, 0x60, | 2437 | pci_write_config_dword (pdev, 0x60, |
2439 | 0xe7000000 | inta_addr[i]); | 2438 | 0xe5000000 | inta_addr[i]); |
2440 | pci_write_config_dword (pdev, 0x78, | 2439 | pci_write_config_dword (pdev, 0x78, |
2441 | 0x00000000 | inta_addr[i]); | 2440 | 0x00000000 | inta_addr[i]); |
2442 | test = inb (inta_addr[i]); | 2441 | test = inb (inta_addr[i]); |
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index 10dbdec80416..1b7b2812bf2d 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c | |||
@@ -20,7 +20,7 @@ | |||
20 | #include <linux/stat.h> | 20 | #include <linux/stat.h> |
21 | #include <linux/topology.h> | 21 | #include <linux/topology.h> |
22 | #include <linux/mm.h> | 22 | #include <linux/mm.h> |
23 | 23 | #include <linux/capability.h> | |
24 | #include "pci.h" | 24 | #include "pci.h" |
25 | 25 | ||
26 | static int sysfs_initialized; /* = 0 */ | 26 | static int sysfs_initialized; /* = 0 */ |
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index a7bce75c6732..34b8dae0d90f 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c | |||
@@ -22,6 +22,18 @@ EXPORT_SYMBOL(pci_root_buses); | |||
22 | 22 | ||
23 | LIST_HEAD(pci_devices); | 23 | LIST_HEAD(pci_devices); |
24 | 24 | ||
25 | /* | ||
26 | * Some device drivers need know if pci is initiated. | ||
27 | * Basically, we think pci is not initiated when there | ||
28 | * is no device in list of pci_devices. | ||
29 | */ | ||
30 | int no_pci_devices(void) | ||
31 | { | ||
32 | return list_empty(&pci_devices); | ||
33 | } | ||
34 | |||
35 | EXPORT_SYMBOL(no_pci_devices); | ||
36 | |||
25 | #ifdef HAVE_PCI_LEGACY | 37 | #ifdef HAVE_PCI_LEGACY |
26 | /** | 38 | /** |
27 | * pci_create_legacy_files - create legacy I/O port and memory files | 39 | * pci_create_legacy_files - create legacy I/O port and memory files |
diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c index cfa0dfe61b1a..90adc62d07ff 100644 --- a/drivers/pci/proc.c +++ b/drivers/pci/proc.c | |||
@@ -11,7 +11,7 @@ | |||
11 | #include <linux/module.h> | 11 | #include <linux/module.h> |
12 | #include <linux/proc_fs.h> | 12 | #include <linux/proc_fs.h> |
13 | #include <linux/seq_file.h> | 13 | #include <linux/seq_file.h> |
14 | 14 | #include <linux/capability.h> | |
15 | #include <asm/uaccess.h> | 15 | #include <asm/uaccess.h> |
16 | #include <asm/byteorder.h> | 16 | #include <asm/byteorder.h> |
17 | #include "pci.h" | 17 | #include "pci.h" |
diff --git a/drivers/pci/search.c b/drivers/pci/search.c index 9f7090fa8771..c6e79d01ce3d 100644 --- a/drivers/pci/search.c +++ b/drivers/pci/search.c | |||
@@ -202,7 +202,7 @@ static struct pci_dev * pci_find_subsys(unsigned int vendor, | |||
202 | * can cause some machines to crash. So here we detect and flag that | 202 | * can cause some machines to crash. So here we detect and flag that |
203 | * situation and bail out early. | 203 | * situation and bail out early. |
204 | */ | 204 | */ |
205 | if (unlikely(list_empty(&pci_devices))) | 205 | if (unlikely(no_pci_devices())) |
206 | return NULL; | 206 | return NULL; |
207 | down_read(&pci_bus_sem); | 207 | down_read(&pci_bus_sem); |
208 | n = from ? from->global_list.next : pci_devices.next; | 208 | n = from ? from->global_list.next : pci_devices.next; |
@@ -277,7 +277,7 @@ pci_get_subsys(unsigned int vendor, unsigned int device, | |||
277 | * can cause some machines to crash. So here we detect and flag that | 277 | * can cause some machines to crash. So here we detect and flag that |
278 | * situation and bail out early. | 278 | * situation and bail out early. |
279 | */ | 279 | */ |
280 | if (unlikely(list_empty(&pci_devices))) | 280 | if (unlikely(no_pci_devices())) |
281 | return NULL; | 281 | return NULL; |
282 | down_read(&pci_bus_sem); | 282 | down_read(&pci_bus_sem); |
283 | n = from ? from->global_list.next : pci_devices.next; | 283 | n = from ? from->global_list.next : pci_devices.next; |
diff --git a/drivers/pnp/Kconfig b/drivers/pnp/Kconfig index 1959cef8e9de..821933f9aa57 100644 --- a/drivers/pnp/Kconfig +++ b/drivers/pnp/Kconfig | |||
@@ -2,11 +2,9 @@ | |||
2 | # Plug and Play configuration | 2 | # Plug and Play configuration |
3 | # | 3 | # |
4 | 4 | ||
5 | menu "Plug and Play support" | 5 | menuconfig PNP |
6 | depends on HAS_IOMEM | ||
7 | |||
8 | config PNP | ||
9 | bool "Plug and Play support" | 6 | bool "Plug and Play support" |
7 | depends on HAS_IOMEM | ||
10 | depends on ISA || ACPI | 8 | depends on ISA || ACPI |
11 | ---help--- | 9 | ---help--- |
12 | Plug and Play (PnP) is a standard for peripherals which allows those | 10 | Plug and Play (PnP) is a standard for peripherals which allows those |
@@ -22,15 +20,15 @@ config PNP | |||
22 | 20 | ||
23 | If unsure, say Y. | 21 | If unsure, say Y. |
24 | 22 | ||
23 | if PNP | ||
24 | |||
25 | config PNP_DEBUG | 25 | config PNP_DEBUG |
26 | bool "PnP Debug Messages" | 26 | bool "PnP Debug Messages" |
27 | depends on PNP | ||
28 | help | 27 | help |
29 | Say Y if you want the Plug and Play Layer to print debug messages. | 28 | Say Y if you want the Plug and Play Layer to print debug messages. |
30 | This is useful if you are developing a PnP driver or troubleshooting. | 29 | This is useful if you are developing a PnP driver or troubleshooting. |
31 | 30 | ||
32 | comment "Protocols" | 31 | comment "Protocols" |
33 | depends on PNP | ||
34 | 32 | ||
35 | source "drivers/pnp/isapnp/Kconfig" | 33 | source "drivers/pnp/isapnp/Kconfig" |
36 | 34 | ||
@@ -38,5 +36,4 @@ source "drivers/pnp/pnpbios/Kconfig" | |||
38 | 36 | ||
39 | source "drivers/pnp/pnpacpi/Kconfig" | 37 | source "drivers/pnp/pnpacpi/Kconfig" |
40 | 38 | ||
41 | endmenu | 39 | endif # PNP |
42 | |||
diff --git a/drivers/pnp/isapnp/Kconfig b/drivers/pnp/isapnp/Kconfig index 578651eeb4b0..f1ef36673ad4 100644 --- a/drivers/pnp/isapnp/Kconfig +++ b/drivers/pnp/isapnp/Kconfig | |||
@@ -3,7 +3,7 @@ | |||
3 | # | 3 | # |
4 | config ISAPNP | 4 | config ISAPNP |
5 | bool "ISA Plug and Play support" | 5 | bool "ISA Plug and Play support" |
6 | depends on PNP && ISA | 6 | depends on ISA |
7 | help | 7 | help |
8 | Say Y here if you would like support for ISA Plug and Play devices. | 8 | Say Y here if you would like support for ISA Plug and Play devices. |
9 | Some information is in <file:Documentation/isapnp.txt>. | 9 | Some information is in <file:Documentation/isapnp.txt>. |
diff --git a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c index a0b158704ca1..914d00c423ad 100644 --- a/drivers/pnp/isapnp/core.c +++ b/drivers/pnp/isapnp/core.c | |||
@@ -370,8 +370,6 @@ static int __init isapnp_read_tag(unsigned char *type, unsigned short *size) | |||
370 | #if 0 | 370 | #if 0 |
371 | printk(KERN_DEBUG "tag = 0x%x, type = 0x%x, size = %i\n", tag, *type, *size); | 371 | printk(KERN_DEBUG "tag = 0x%x, type = 0x%x, size = %i\n", tag, *type, *size); |
372 | #endif | 372 | #endif |
373 | if (type == 0) /* wrong type */ | ||
374 | return -1; | ||
375 | if (*type == 0xff && *size == 0xffff) /* probably invalid data */ | 373 | if (*type == 0xff && *size == 0xffff) /* probably invalid data */ |
376 | return -1; | 374 | return -1; |
377 | return 0; | 375 | return 0; |
diff --git a/drivers/pnp/pnpbios/Kconfig b/drivers/pnp/pnpbios/Kconfig index fab848cae89d..b986d9fa3b9a 100644 --- a/drivers/pnp/pnpbios/Kconfig +++ b/drivers/pnp/pnpbios/Kconfig | |||
@@ -3,7 +3,7 @@ | |||
3 | # | 3 | # |
4 | config PNPBIOS | 4 | config PNPBIOS |
5 | bool "Plug and Play BIOS support (EXPERIMENTAL)" | 5 | bool "Plug and Play BIOS support (EXPERIMENTAL)" |
6 | depends on PNP && ISA && X86 && EXPERIMENTAL | 6 | depends on ISA && X86 && EXPERIMENTAL |
7 | default n | 7 | default n |
8 | ---help--- | 8 | ---help--- |
9 | Linux uses the PNPBIOS as defined in "Plug and Play BIOS | 9 | Linux uses the PNPBIOS as defined in "Plug and Play BIOS |
diff --git a/drivers/sbus/char/cpwatchdog.c b/drivers/sbus/char/cpwatchdog.c index 022e869c44dd..7b5773d88212 100644 --- a/drivers/sbus/char/cpwatchdog.c +++ b/drivers/sbus/char/cpwatchdog.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/ioport.h> | 24 | #include <linux/ioport.h> |
25 | #include <linux/timer.h> | 25 | #include <linux/timer.h> |
26 | #include <linux/smp_lock.h> | 26 | #include <linux/smp_lock.h> |
27 | #include <linux/io.h> | ||
27 | #include <asm/irq.h> | 28 | #include <asm/irq.h> |
28 | #include <asm/ebus.h> | 29 | #include <asm/ebus.h> |
29 | #include <asm/oplib.h> | 30 | #include <asm/oplib.h> |
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 9d2119b53ac9..372723161c97 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig | |||
@@ -545,7 +545,7 @@ config SCSI_HPTIOP | |||
545 | 545 | ||
546 | config SCSI_BUSLOGIC | 546 | config SCSI_BUSLOGIC |
547 | tristate "BusLogic SCSI support" | 547 | tristate "BusLogic SCSI support" |
548 | depends on (PCI || ISA || MCA) && SCSI && ISA_DMA_API | 548 | depends on (PCI || ISA || MCA) && SCSI && ISA_DMA_API && VIRT_TO_BUS |
549 | ---help--- | 549 | ---help--- |
550 | This is support for BusLogic MultiMaster and FlashPoint SCSI Host | 550 | This is support for BusLogic MultiMaster and FlashPoint SCSI Host |
551 | Adapters. Consult the SCSI-HOWTO, available from | 551 | Adapters. Consult the SCSI-HOWTO, available from |
diff --git a/drivers/serial/68360serial.c b/drivers/serial/68360serial.c index 68817a7d8c0d..2aa6bfe8fdb3 100644 --- a/drivers/serial/68360serial.c +++ b/drivers/serial/68360serial.c | |||
@@ -934,8 +934,6 @@ static void change_speed(ser_info_t *info) | |||
934 | /* | 934 | /* |
935 | * Set up parity check flag | 935 | * Set up parity check flag |
936 | */ | 936 | */ |
937 | #define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK)) | ||
938 | |||
939 | info->read_status_mask = (BD_SC_EMPTY | BD_SC_OV); | 937 | info->read_status_mask = (BD_SC_EMPTY | BD_SC_OV); |
940 | if (I_INPCK(info->tty)) | 938 | if (I_INPCK(info->tty)) |
941 | info->read_status_mask |= BD_SC_FR | BD_SC_PR; | 939 | info->read_status_mask |= BD_SC_FR | BD_SC_PR; |
@@ -1527,11 +1525,6 @@ static void rs_360_set_termios(struct tty_struct *tty, struct ktermios *old_term | |||
1527 | { | 1525 | { |
1528 | ser_info_t *info = (ser_info_t *)tty->driver_data; | 1526 | ser_info_t *info = (ser_info_t *)tty->driver_data; |
1529 | 1527 | ||
1530 | if ( (tty->termios->c_cflag == old_termios->c_cflag) | ||
1531 | && ( RELEVANT_IFLAG(tty->termios->c_iflag) | ||
1532 | == RELEVANT_IFLAG(old_termios->c_iflag))) | ||
1533 | return; | ||
1534 | |||
1535 | change_speed(info); | 1528 | change_speed(info); |
1536 | 1529 | ||
1537 | #ifdef modem_control | 1530 | #ifdef modem_control |
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index c84dab083a85..0b3ec38ae614 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c | |||
@@ -2514,12 +2514,18 @@ static int __init serial8250_console_setup(struct console *co, char *options) | |||
2514 | return uart_set_options(port, co, baud, parity, bits, flow); | 2514 | return uart_set_options(port, co, baud, parity, bits, flow); |
2515 | } | 2515 | } |
2516 | 2516 | ||
2517 | static int __init serial8250_console_early_setup(void) | ||
2518 | { | ||
2519 | return serial8250_find_port_for_earlycon(); | ||
2520 | } | ||
2521 | |||
2517 | static struct uart_driver serial8250_reg; | 2522 | static struct uart_driver serial8250_reg; |
2518 | static struct console serial8250_console = { | 2523 | static struct console serial8250_console = { |
2519 | .name = "ttyS", | 2524 | .name = "ttyS", |
2520 | .write = serial8250_console_write, | 2525 | .write = serial8250_console_write, |
2521 | .device = uart_console_device, | 2526 | .device = uart_console_device, |
2522 | .setup = serial8250_console_setup, | 2527 | .setup = serial8250_console_setup, |
2528 | .early_setup = serial8250_console_early_setup, | ||
2523 | .flags = CON_PRINTBUFFER, | 2529 | .flags = CON_PRINTBUFFER, |
2524 | .index = -1, | 2530 | .index = -1, |
2525 | .data = &serial8250_reg, | 2531 | .data = &serial8250_reg, |
@@ -2533,7 +2539,7 @@ static int __init serial8250_console_init(void) | |||
2533 | } | 2539 | } |
2534 | console_initcall(serial8250_console_init); | 2540 | console_initcall(serial8250_console_init); |
2535 | 2541 | ||
2536 | static int __init find_port(struct uart_port *p) | 2542 | int serial8250_find_port(struct uart_port *p) |
2537 | { | 2543 | { |
2538 | int line; | 2544 | int line; |
2539 | struct uart_port *port; | 2545 | struct uart_port *port; |
@@ -2546,26 +2552,6 @@ static int __init find_port(struct uart_port *p) | |||
2546 | return -ENODEV; | 2552 | return -ENODEV; |
2547 | } | 2553 | } |
2548 | 2554 | ||
2549 | int __init serial8250_start_console(struct uart_port *port, char *options) | ||
2550 | { | ||
2551 | int line; | ||
2552 | |||
2553 | line = find_port(port); | ||
2554 | if (line < 0) | ||
2555 | return -ENODEV; | ||
2556 | |||
2557 | add_preferred_console("ttyS", line, options); | ||
2558 | printk("Adding console on ttyS%d at %s 0x%lx (options '%s')\n", | ||
2559 | line, port->iotype == UPIO_MEM ? "MMIO" : "I/O port", | ||
2560 | port->iotype == UPIO_MEM ? (unsigned long) port->mapbase : | ||
2561 | (unsigned long) port->iobase, options); | ||
2562 | if (!(serial8250_console.flags & CON_ENABLED)) { | ||
2563 | serial8250_console.flags &= ~CON_PRINTBUFFER; | ||
2564 | register_console(&serial8250_console); | ||
2565 | } | ||
2566 | return line; | ||
2567 | } | ||
2568 | |||
2569 | #define SERIAL8250_CONSOLE &serial8250_console | 2555 | #define SERIAL8250_CONSOLE &serial8250_console |
2570 | #else | 2556 | #else |
2571 | #define SERIAL8250_CONSOLE NULL | 2557 | #define SERIAL8250_CONSOLE NULL |
diff --git a/drivers/serial/8250_early.c b/drivers/serial/8250_early.c index 7e511199b4c5..947c20507e1f 100644 --- a/drivers/serial/8250_early.c +++ b/drivers/serial/8250_early.c | |||
@@ -17,13 +17,11 @@ | |||
17 | * we locate the device directly by its MMIO or I/O port address. | 17 | * we locate the device directly by its MMIO or I/O port address. |
18 | * | 18 | * |
19 | * The user can specify the device directly, e.g., | 19 | * The user can specify the device directly, e.g., |
20 | * console=uart,io,0x3f8,9600n8 | 20 | * earlycon=uart8250,io,0x3f8,9600n8 |
21 | * console=uart,mmio,0xff5e0000,115200n8 | 21 | * earlycon=uart8250,mmio,0xff5e0000,115200n8 |
22 | * or platform code can call early_uart_console_init() to set | 22 | * or |
23 | * the early UART device. | 23 | * console=uart8250,io,0x3f8,9600n8 |
24 | * | 24 | * console=uart8250,mmio,0xff5e0000,115200n8 |
25 | * After the normal serial driver starts, we try to locate the | ||
26 | * matching ttyS device and start a console there. | ||
27 | */ | 25 | */ |
28 | 26 | ||
29 | #include <linux/tty.h> | 27 | #include <linux/tty.h> |
@@ -32,17 +30,21 @@ | |||
32 | #include <linux/serial_core.h> | 30 | #include <linux/serial_core.h> |
33 | #include <linux/serial_reg.h> | 31 | #include <linux/serial_reg.h> |
34 | #include <linux/serial.h> | 32 | #include <linux/serial.h> |
33 | #include <linux/serial_8250.h> | ||
35 | #include <asm/io.h> | 34 | #include <asm/io.h> |
36 | #include <asm/serial.h> | 35 | #include <asm/serial.h> |
36 | #ifdef CONFIG_FIX_EARLYCON_MEM | ||
37 | #include <asm/pgtable.h> | ||
38 | #include <asm/fixmap.h> | ||
39 | #endif | ||
37 | 40 | ||
38 | struct early_uart_device { | 41 | struct early_serial8250_device { |
39 | struct uart_port port; | 42 | struct uart_port port; |
40 | char options[16]; /* e.g., 115200n8 */ | 43 | char options[16]; /* e.g., 115200n8 */ |
41 | unsigned int baud; | 44 | unsigned int baud; |
42 | }; | 45 | }; |
43 | 46 | ||
44 | static struct early_uart_device early_device __initdata; | 47 | static struct early_serial8250_device early_device; |
45 | static int early_uart_registered __initdata; | ||
46 | 48 | ||
47 | static unsigned int __init serial_in(struct uart_port *port, int offset) | 49 | static unsigned int __init serial_in(struct uart_port *port, int offset) |
48 | { | 50 | { |
@@ -80,7 +82,7 @@ static void __init putc(struct uart_port *port, int c) | |||
80 | serial_out(port, UART_TX, c); | 82 | serial_out(port, UART_TX, c); |
81 | } | 83 | } |
82 | 84 | ||
83 | static void __init early_uart_write(struct console *console, const char *s, unsigned int count) | 85 | static void __init early_serial8250_write(struct console *console, const char *s, unsigned int count) |
84 | { | 86 | { |
85 | struct uart_port *port = &early_device.port; | 87 | struct uart_port *port = &early_device.port; |
86 | unsigned int ier; | 88 | unsigned int ier; |
@@ -111,7 +113,7 @@ static unsigned int __init probe_baud(struct uart_port *port) | |||
111 | return (port->uartclk / 16) / quot; | 113 | return (port->uartclk / 16) / quot; |
112 | } | 114 | } |
113 | 115 | ||
114 | static void __init init_port(struct early_uart_device *device) | 116 | static void __init init_port(struct early_serial8250_device *device) |
115 | { | 117 | { |
116 | struct uart_port *port = &device->port; | 118 | struct uart_port *port = &device->port; |
117 | unsigned int divisor; | 119 | unsigned int divisor; |
@@ -130,10 +132,9 @@ static void __init init_port(struct early_uart_device *device) | |||
130 | serial_out(port, UART_LCR, c & ~UART_LCR_DLAB); | 132 | serial_out(port, UART_LCR, c & ~UART_LCR_DLAB); |
131 | } | 133 | } |
132 | 134 | ||
133 | static int __init parse_options(struct early_uart_device *device, char *options) | 135 | static int __init parse_options(struct early_serial8250_device *device, char *options) |
134 | { | 136 | { |
135 | struct uart_port *port = &device->port; | 137 | struct uart_port *port = &device->port; |
136 | int mapsize = 64; | ||
137 | int mmio, length; | 138 | int mmio, length; |
138 | 139 | ||
139 | if (!options) | 140 | if (!options) |
@@ -143,12 +144,18 @@ static int __init parse_options(struct early_uart_device *device, char *options) | |||
143 | if (!strncmp(options, "mmio,", 5)) { | 144 | if (!strncmp(options, "mmio,", 5)) { |
144 | port->iotype = UPIO_MEM; | 145 | port->iotype = UPIO_MEM; |
145 | port->mapbase = simple_strtoul(options + 5, &options, 0); | 146 | port->mapbase = simple_strtoul(options + 5, &options, 0); |
146 | port->membase = ioremap(port->mapbase, mapsize); | 147 | #ifdef CONFIG_FIX_EARLYCON_MEM |
148 | set_fixmap_nocache(FIX_EARLYCON_MEM_BASE, port->mapbase & PAGE_MASK); | ||
149 | port->membase = (void __iomem *)__fix_to_virt(FIX_EARLYCON_MEM_BASE); | ||
150 | port->membase += port->mapbase & ~PAGE_MASK; | ||
151 | #else | ||
152 | port->membase = ioremap(port->mapbase, 64); | ||
147 | if (!port->membase) { | 153 | if (!port->membase) { |
148 | printk(KERN_ERR "%s: Couldn't ioremap 0x%lx\n", | 154 | printk(KERN_ERR "%s: Couldn't ioremap 0x%lx\n", |
149 | __FUNCTION__, port->mapbase); | 155 | __FUNCTION__, port->mapbase); |
150 | return -ENOMEM; | 156 | return -ENOMEM; |
151 | } | 157 | } |
158 | #endif | ||
152 | mmio = 1; | 159 | mmio = 1; |
153 | } else if (!strncmp(options, "io,", 3)) { | 160 | } else if (!strncmp(options, "io,", 3)) { |
154 | port->iotype = UPIO_PORT; | 161 | port->iotype = UPIO_PORT; |
@@ -175,9 +182,16 @@ static int __init parse_options(struct early_uart_device *device, char *options) | |||
175 | return 0; | 182 | return 0; |
176 | } | 183 | } |
177 | 184 | ||
178 | static int __init early_uart_setup(struct console *console, char *options) | 185 | static struct console early_serial8250_console __initdata = { |
186 | .name = "uart", | ||
187 | .write = early_serial8250_write, | ||
188 | .flags = CON_PRINTBUFFER | CON_BOOT, | ||
189 | .index = -1, | ||
190 | }; | ||
191 | |||
192 | static int __init early_serial8250_setup(char *options) | ||
179 | { | 193 | { |
180 | struct early_uart_device *device = &early_device; | 194 | struct early_serial8250_device *device = &early_device; |
181 | int err; | 195 | int err; |
182 | 196 | ||
183 | if (device->port.membase || device->port.iobase) | 197 | if (device->port.membase || device->port.iobase) |
@@ -190,61 +204,48 @@ static int __init early_uart_setup(struct console *console, char *options) | |||
190 | return 0; | 204 | return 0; |
191 | } | 205 | } |
192 | 206 | ||
193 | static struct console early_uart_console __initdata = { | 207 | int __init setup_early_serial8250_console(char *cmdline) |
194 | .name = "uart", | ||
195 | .write = early_uart_write, | ||
196 | .setup = early_uart_setup, | ||
197 | .flags = CON_PRINTBUFFER, | ||
198 | .index = -1, | ||
199 | }; | ||
200 | |||
201 | static int __init early_uart_console_init(void) | ||
202 | { | ||
203 | if (!early_uart_registered) { | ||
204 | register_console(&early_uart_console); | ||
205 | early_uart_registered = 1; | ||
206 | } | ||
207 | return 0; | ||
208 | } | ||
209 | console_initcall(early_uart_console_init); | ||
210 | |||
211 | int __init early_serial_console_init(char *cmdline) | ||
212 | { | 208 | { |
213 | char *options; | 209 | char *options; |
214 | int err; | 210 | int err; |
215 | 211 | ||
216 | options = strstr(cmdline, "console=uart,"); | 212 | options = strstr(cmdline, "uart8250,"); |
217 | if (!options) | 213 | if (!options) { |
218 | return -ENODEV; | 214 | options = strstr(cmdline, "uart,"); |
215 | if (!options) | ||
216 | return 0; | ||
217 | } | ||
219 | 218 | ||
220 | options = strchr(cmdline, ',') + 1; | 219 | options = strchr(cmdline, ',') + 1; |
221 | if ((err = early_uart_setup(NULL, options)) < 0) | 220 | if ((err = early_serial8250_setup(options)) < 0) |
222 | return err; | 221 | return err; |
223 | return early_uart_console_init(); | 222 | |
223 | register_console(&early_serial8250_console); | ||
224 | |||
225 | return 0; | ||
224 | } | 226 | } |
225 | 227 | ||
226 | static int __init early_uart_console_switch(void) | 228 | int __init serial8250_find_port_for_earlycon(void) |
227 | { | 229 | { |
228 | struct early_uart_device *device = &early_device; | 230 | struct early_serial8250_device *device = &early_device; |
229 | struct uart_port *port = &device->port; | 231 | struct uart_port *port = &device->port; |
230 | int mmio, line; | 232 | int line; |
233 | int ret; | ||
231 | 234 | ||
232 | if (!(early_uart_console.flags & CON_ENABLED)) | 235 | if (!device->port.membase && !device->port.iobase) |
233 | return 0; | 236 | return -ENODEV; |
234 | 237 | ||
235 | /* Try to start the normal driver on a matching line. */ | 238 | line = serial8250_find_port(port); |
236 | mmio = (port->iotype == UPIO_MEM); | ||
237 | line = serial8250_start_console(port, device->options); | ||
238 | if (line < 0) | 239 | if (line < 0) |
239 | printk("No ttyS device at %s 0x%lx for console\n", | 240 | return -ENODEV; |
240 | mmio ? "MMIO" : "I/O port", | ||
241 | mmio ? port->mapbase : | ||
242 | (unsigned long) port->iobase); | ||
243 | 241 | ||
244 | unregister_console(&early_uart_console); | 242 | ret = update_console_cmdline("uart", 8250, |
245 | if (mmio) | 243 | "ttyS", line, device->options); |
246 | iounmap(port->membase); | 244 | if (ret < 0) |
245 | ret = update_console_cmdline("uart", 0, | ||
246 | "ttyS", line, device->options); | ||
247 | 247 | ||
248 | return 0; | 248 | return ret; |
249 | } | 249 | } |
250 | late_initcall(early_uart_console_switch); | 250 | |
251 | early_param("earlycon", setup_early_serial8250_console); | ||
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 2adbed4e10f3..cab42cbd920d 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig | |||
@@ -62,8 +62,22 @@ config SERIAL_8250_CONSOLE | |||
62 | kernel will automatically use the first serial line, /dev/ttyS0, as | 62 | kernel will automatically use the first serial line, /dev/ttyS0, as |
63 | system console. | 63 | system console. |
64 | 64 | ||
65 | you can set that using a kernel command line option such as | ||
66 | "console=uart8250,io,0x3f8,9600n8" | ||
67 | "console=uart8250,mmio,0xff5e0000,115200n8". | ||
68 | and it will switch to normal serial console when correponding port is | ||
69 | ready. | ||
70 | "earlycon=uart8250,io,0x3f8,9600n8" | ||
71 | "earlycon=uart8250,mmio,0xff5e0000,115200n8". | ||
72 | it will not only setup early console. | ||
73 | |||
65 | If unsure, say N. | 74 | If unsure, say N. |
66 | 75 | ||
76 | config FIX_EARLYCON_MEM | ||
77 | bool | ||
78 | depends on X86 | ||
79 | default y | ||
80 | |||
67 | config SERIAL_8250_GSC | 81 | config SERIAL_8250_GSC |
68 | tristate | 82 | tristate |
69 | depends on SERIAL_8250 && GSC | 83 | depends on SERIAL_8250 && GSC |
diff --git a/drivers/serial/atmel_serial.c b/drivers/serial/atmel_serial.c index 3320bcd92c0a..4d6b3c56d20e 100644 --- a/drivers/serial/atmel_serial.c +++ b/drivers/serial/atmel_serial.c | |||
@@ -114,6 +114,7 @@ struct atmel_uart_port { | |||
114 | struct uart_port uart; /* uart */ | 114 | struct uart_port uart; /* uart */ |
115 | struct clk *clk; /* uart clock */ | 115 | struct clk *clk; /* uart clock */ |
116 | unsigned short suspended; /* is port suspended? */ | 116 | unsigned short suspended; /* is port suspended? */ |
117 | int break_active; /* break being received */ | ||
117 | }; | 118 | }; |
118 | 119 | ||
119 | static struct atmel_uart_port atmel_ports[ATMEL_MAX_UART]; | 120 | static struct atmel_uart_port atmel_ports[ATMEL_MAX_UART]; |
@@ -252,6 +253,7 @@ static void atmel_break_ctl(struct uart_port *port, int break_state) | |||
252 | */ | 253 | */ |
253 | static void atmel_rx_chars(struct uart_port *port) | 254 | static void atmel_rx_chars(struct uart_port *port) |
254 | { | 255 | { |
256 | struct atmel_uart_port *atmel_port = (struct atmel_uart_port *) port; | ||
255 | struct tty_struct *tty = port->info->tty; | 257 | struct tty_struct *tty = port->info->tty; |
256 | unsigned int status, ch, flg; | 258 | unsigned int status, ch, flg; |
257 | 259 | ||
@@ -267,13 +269,29 @@ static void atmel_rx_chars(struct uart_port *port) | |||
267 | * note that the error handling code is | 269 | * note that the error handling code is |
268 | * out of the main execution path | 270 | * out of the main execution path |
269 | */ | 271 | */ |
270 | if (unlikely(status & (ATMEL_US_PARE | ATMEL_US_FRAME | ATMEL_US_OVRE | ATMEL_US_RXBRK))) { | 272 | if (unlikely(status & (ATMEL_US_PARE | ATMEL_US_FRAME |
273 | | ATMEL_US_OVRE | ATMEL_US_RXBRK) | ||
274 | || atmel_port->break_active)) { | ||
271 | UART_PUT_CR(port, ATMEL_US_RSTSTA); /* clear error */ | 275 | UART_PUT_CR(port, ATMEL_US_RSTSTA); /* clear error */ |
272 | if (status & ATMEL_US_RXBRK) { | 276 | if (status & ATMEL_US_RXBRK |
277 | && !atmel_port->break_active) { | ||
273 | status &= ~(ATMEL_US_PARE | ATMEL_US_FRAME); /* ignore side-effect */ | 278 | status &= ~(ATMEL_US_PARE | ATMEL_US_FRAME); /* ignore side-effect */ |
274 | port->icount.brk++; | 279 | port->icount.brk++; |
280 | atmel_port->break_active = 1; | ||
281 | UART_PUT_IER(port, ATMEL_US_RXBRK); | ||
275 | if (uart_handle_break(port)) | 282 | if (uart_handle_break(port)) |
276 | goto ignore_char; | 283 | goto ignore_char; |
284 | } else { | ||
285 | /* | ||
286 | * This is either the end-of-break | ||
287 | * condition or we've received at | ||
288 | * least one character without RXBRK | ||
289 | * being set. In both cases, the next | ||
290 | * RXBRK will indicate start-of-break. | ||
291 | */ | ||
292 | UART_PUT_IDR(port, ATMEL_US_RXBRK); | ||
293 | status &= ~ATMEL_US_RXBRK; | ||
294 | atmel_port->break_active = 0; | ||
277 | } | 295 | } |
278 | if (status & ATMEL_US_PARE) | 296 | if (status & ATMEL_US_PARE) |
279 | port->icount.parity++; | 297 | port->icount.parity++; |
@@ -352,6 +370,16 @@ static irqreturn_t atmel_interrupt(int irq, void *dev_id) | |||
352 | /* Interrupt receive */ | 370 | /* Interrupt receive */ |
353 | if (pending & ATMEL_US_RXRDY) | 371 | if (pending & ATMEL_US_RXRDY) |
354 | atmel_rx_chars(port); | 372 | atmel_rx_chars(port); |
373 | else if (pending & ATMEL_US_RXBRK) { | ||
374 | /* | ||
375 | * End of break detected. If it came along | ||
376 | * with a character, atmel_rx_chars will | ||
377 | * handle it. | ||
378 | */ | ||
379 | UART_PUT_CR(port, ATMEL_US_RSTSTA); | ||
380 | UART_PUT_IDR(port, ATMEL_US_RXBRK); | ||
381 | atmel_port->break_active = 0; | ||
382 | } | ||
355 | 383 | ||
356 | // TODO: All reads to CSR will clear these interrupts! | 384 | // TODO: All reads to CSR will clear these interrupts! |
357 | if (pending & ATMEL_US_RIIC) port->icount.rng++; | 385 | if (pending & ATMEL_US_RIIC) port->icount.rng++; |
diff --git a/drivers/serial/ip22zilog.c b/drivers/serial/ip22zilog.c index c3abfb39f316..f3257f708ef9 100644 --- a/drivers/serial/ip22zilog.c +++ b/drivers/serial/ip22zilog.c | |||
@@ -862,6 +862,7 @@ ip22zilog_set_termios(struct uart_port *port, struct ktermios *termios, | |||
862 | up->cflag = termios->c_cflag; | 862 | up->cflag = termios->c_cflag; |
863 | 863 | ||
864 | ip22zilog_maybe_update_regs(up, ZILOG_CHANNEL_FROM_PORT(port)); | 864 | ip22zilog_maybe_update_regs(up, ZILOG_CHANNEL_FROM_PORT(port)); |
865 | uart_update_timeout(port, termios->c_cflag, baud); | ||
865 | 866 | ||
866 | spin_unlock_irqrestore(&up->port.lock, flags); | 867 | spin_unlock_irqrestore(&up->port.lock, flags); |
867 | } | 868 | } |
@@ -1017,6 +1018,8 @@ ip22serial_console_termios(struct console *con, char *options) | |||
1017 | } | 1018 | } |
1018 | 1019 | ||
1019 | con->cflag = cflag | CS8; /* 8N1 */ | 1020 | con->cflag = cflag | CS8; /* 8N1 */ |
1021 | |||
1022 | uart_update_timeout(&ip22zilog_port_table[con->index].port, cflag, baud); | ||
1020 | } | 1023 | } |
1021 | 1024 | ||
1022 | static int __init ip22zilog_console_setup(struct console *con, char *options) | 1025 | static int __init ip22zilog_console_setup(struct console *con, char *options) |
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index 326020f86f75..9c57486c2e7f 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c | |||
@@ -1910,6 +1910,12 @@ uart_set_options(struct uart_port *port, struct console *co, | |||
1910 | if (flow == 'r') | 1910 | if (flow == 'r') |
1911 | termios.c_cflag |= CRTSCTS; | 1911 | termios.c_cflag |= CRTSCTS; |
1912 | 1912 | ||
1913 | /* | ||
1914 | * some uarts on other side don't support no flow control. | ||
1915 | * So we set * DTR in host uart to make them happy | ||
1916 | */ | ||
1917 | port->mctrl |= TIOCM_DTR; | ||
1918 | |||
1913 | port->ops->set_termios(port, &termios, NULL); | 1919 | port->ops->set_termios(port, &termios, NULL); |
1914 | co->cflag = termios.c_cflag; | 1920 | co->cflag = termios.c_cflag; |
1915 | 1921 | ||
diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index 1f89496d530e..672cd1042539 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c | |||
@@ -367,7 +367,9 @@ static void sci_init_pins_scif(struct uart_port *port, unsigned int cflag) | |||
367 | } else { | 367 | } else { |
368 | #ifdef CONFIG_CPU_SUBTYPE_SH7343 | 368 | #ifdef CONFIG_CPU_SUBTYPE_SH7343 |
369 | /* Nothing */ | 369 | /* Nothing */ |
370 | #elif defined(CONFIG_CPU_SUBTYPE_SH7780) || defined(CONFIG_CPU_SUBTYPE_SH7785) | 370 | #elif defined(CONFIG_CPU_SUBTYPE_SH7780) || \ |
371 | defined(CONFIG_CPU_SUBTYPE_SH7785) || \ | ||
372 | defined(CONFIG_CPU_SUBTYPE_SHX3) | ||
371 | ctrl_outw(0x0080, SCSPTR0); /* Set RTS = 1 */ | 373 | ctrl_outw(0x0080, SCSPTR0); /* Set RTS = 1 */ |
372 | #else | 374 | #else |
373 | ctrl_outw(0x0080, SCSPTR2); /* Set RTS = 1 */ | 375 | ctrl_outw(0x0080, SCSPTR2); /* Set RTS = 1 */ |
diff --git a/drivers/serial/sh-sci.h b/drivers/serial/sh-sci.h index fb04fb5f9843..247fb66bf0f4 100644 --- a/drivers/serial/sh-sci.h +++ b/drivers/serial/sh-sci.h | |||
@@ -53,7 +53,12 @@ | |||
53 | # define SCIF_ORER 0x0001 /* overrun error bit */ | 53 | # define SCIF_ORER 0x0001 /* overrun error bit */ |
54 | # define SCSCR_INIT(port) 0x3a /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ | 54 | # define SCSCR_INIT(port) 0x3a /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ |
55 | # define SCIF_ONLY | 55 | # define SCIF_ONLY |
56 | #elif defined(CONFIG_CPU_SUBTYPE_SH7750) || defined(CONFIG_CPU_SUBTYPE_SH7751) | 56 | #elif defined(CONFIG_CPU_SUBTYPE_SH7750) || \ |
57 | defined(CONFIG_CPU_SUBTYPE_SH7750R) || \ | ||
58 | defined(CONFIG_CPU_SUBTYPE_SH7750S) || \ | ||
59 | defined(CONFIG_CPU_SUBTYPE_SH7091) || \ | ||
60 | defined(CONFIG_CPU_SUBTYPE_SH7751) || \ | ||
61 | defined(CONFIG_CPU_SUBTYPE_SH7751R) | ||
57 | # define SCSPTR1 0xffe0001c /* 8 bit SCI */ | 62 | # define SCSPTR1 0xffe0001c /* 8 bit SCI */ |
58 | # define SCSPTR2 0xFFE80020 /* 16 bit SCIF */ | 63 | # define SCSPTR2 0xFFE80020 /* 16 bit SCIF */ |
59 | # define SCIF_ORER 0x0001 /* overrun error bit */ | 64 | # define SCIF_ORER 0x0001 /* overrun error bit */ |
@@ -73,7 +78,7 @@ | |||
73 | # define SCPDR 0xA4050136 /* 16 bit SCIF */ | 78 | # define SCPDR 0xA4050136 /* 16 bit SCIF */ |
74 | # define SCSCR_INIT(port) 0x0030 /* TIE=0,RIE=0,TE=1,RE=1 */ | 79 | # define SCSCR_INIT(port) 0x0030 /* TIE=0,RIE=0,TE=1,RE=1 */ |
75 | # define SCIF_ONLY | 80 | # define SCIF_ONLY |
76 | #elif defined(CONFIG_CPU_SUBTYPE_SH7710) || defined(CONFIG_CPU_SUBTYPE_SH7712) | 81 | #elif defined(CONFIG_CPU_SUBTYPE_SH7710) || defined(CONFIG_CPU_SUBTYPE_SH7712) |
77 | # define SCSPTR0 0xA4400000 /* 16 bit SCIF */ | 82 | # define SCSPTR0 0xA4400000 /* 16 bit SCIF */ |
78 | # define SCI_NPORTS 2 | 83 | # define SCI_NPORTS 2 |
79 | # define SCIF_ORER 0x0001 /* overrun error bit */ | 84 | # define SCIF_ORER 0x0001 /* overrun error bit */ |
@@ -168,6 +173,14 @@ | |||
168 | # define SCIF_ORER 0x0001 /* overrun error bit */ | 173 | # define SCIF_ORER 0x0001 /* overrun error bit */ |
169 | # define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ | 174 | # define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ |
170 | # define SCIF_ONLY | 175 | # define SCIF_ONLY |
176 | #elif defined(CONFIG_CPU_SUBTYPE_SHX3) | ||
177 | # define SCSPTR0 0xffc30020 /* 16 bit SCIF */ | ||
178 | # define SCSPTR1 0xffc40020 /* 16 bit SCIF */ | ||
179 | # define SCSPTR2 0xffc50020 /* 16 bit SCIF */ | ||
180 | # define SCSPTR3 0xffc60020 /* 16 bit SCIF */ | ||
181 | # define SCIF_ORER 0x0001 /* Overrun error bit */ | ||
182 | # define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ | ||
183 | # define SCIF_ONLY | ||
171 | #else | 184 | #else |
172 | # error CPU subtype not defined | 185 | # error CPU subtype not defined |
173 | #endif | 186 | #endif |
@@ -177,10 +190,15 @@ | |||
177 | #define SCI_CTRL_FLAGS_RIE 0x40 /* all */ | 190 | #define SCI_CTRL_FLAGS_RIE 0x40 /* all */ |
178 | #define SCI_CTRL_FLAGS_TE 0x20 /* all */ | 191 | #define SCI_CTRL_FLAGS_TE 0x20 /* all */ |
179 | #define SCI_CTRL_FLAGS_RE 0x10 /* all */ | 192 | #define SCI_CTRL_FLAGS_RE 0x10 /* all */ |
180 | #if defined(CONFIG_CPU_SUBTYPE_SH7750) || \ | 193 | #if defined(CONFIG_CPU_SUBTYPE_SH7750) || \ |
181 | defined(CONFIG_CPU_SUBTYPE_SH7751) || \ | 194 | defined(CONFIG_CPU_SUBTYPE_SH7091) || \ |
182 | defined(CONFIG_CPU_SUBTYPE_SH7780) || \ | 195 | defined(CONFIG_CPU_SUBTYPE_SH7750R) || \ |
183 | defined(CONFIG_CPU_SUBTYPE_SH7785) | 196 | defined(CONFIG_CPU_SUBTYPE_SH7750S) || \ |
197 | defined(CONFIG_CPU_SUBTYPE_SH7751) || \ | ||
198 | defined(CONFIG_CPU_SUBTYPE_SH7751R) || \ | ||
199 | defined(CONFIG_CPU_SUBTYPE_SH7780) || \ | ||
200 | defined(CONFIG_CPU_SUBTYPE_SH7785) || \ | ||
201 | defined(CONFIG_CPU_SUBTYPE_SHX3) | ||
184 | #define SCI_CTRL_FLAGS_REIE 0x08 /* 7750 SCIF */ | 202 | #define SCI_CTRL_FLAGS_REIE 0x08 /* 7750 SCIF */ |
185 | #else | 203 | #else |
186 | #define SCI_CTRL_FLAGS_REIE 0 | 204 | #define SCI_CTRL_FLAGS_REIE 0 |
@@ -514,8 +532,12 @@ static inline void set_sh771x_scif_pfc(struct uart_port *port) | |||
514 | } | 532 | } |
515 | } | 533 | } |
516 | 534 | ||
517 | #elif defined(CONFIG_CPU_SUBTYPE_SH7750) || \ | 535 | #elif defined(CONFIG_CPU_SUBTYPE_SH7750) || \ |
518 | defined(CONFIG_CPU_SUBTYPE_SH7751) || \ | 536 | defined(CONFIG_CPU_SUBTYPE_SH7751) || \ |
537 | defined(CONFIG_CPU_SUBTYPE_SH7751R) || \ | ||
538 | defined(CONFIG_CPU_SUBTYPE_SH7750R) || \ | ||
539 | defined(CONFIG_CPU_SUBTYPE_SH7750S) || \ | ||
540 | defined(CONFIG_CPU_SUBTYPE_SH7091) || \ | ||
519 | defined(CONFIG_CPU_SUBTYPE_SH4_202) | 541 | defined(CONFIG_CPU_SUBTYPE_SH4_202) |
520 | static inline int sci_rxd_in(struct uart_port *port) | 542 | static inline int sci_rxd_in(struct uart_port *port) |
521 | { | 543 | { |
@@ -653,6 +675,18 @@ static inline int sci_rxd_in(struct uart_port *port) | |||
653 | return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */ | 675 | return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */ |
654 | return 1; | 676 | return 1; |
655 | } | 677 | } |
678 | #elif defined(CONFIG_CPU_SUBTYPE_SHX3) | ||
679 | static inline int sci_rxd_in(struct uart_port *port) | ||
680 | { | ||
681 | if (port->mapbase == 0xffc30000) | ||
682 | return ctrl_inw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */ | ||
683 | if (port->mapbase == 0xffc40000) | ||
684 | return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */ | ||
685 | if (port->mapbase == 0xffc50000) | ||
686 | return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */ | ||
687 | if (port->mapbase == 0xffc60000) | ||
688 | return ctrl_inw(SCSPTR3) & 0x0001 ? 1 : 0; /* SCIF */ | ||
689 | } | ||
656 | #endif | 690 | #endif |
657 | 691 | ||
658 | /* | 692 | /* |
diff --git a/drivers/serial/sn_console.c b/drivers/serial/sn_console.c index a27e9e92cb5e..41fc61264443 100644 --- a/drivers/serial/sn_console.c +++ b/drivers/serial/sn_console.c | |||
@@ -759,7 +759,7 @@ static void __init sn_sal_switch_to_interrupts(struct sn_cons_port *port) | |||
759 | */ | 759 | */ |
760 | 760 | ||
761 | static void sn_sal_console_write(struct console *, const char *, unsigned); | 761 | static void sn_sal_console_write(struct console *, const char *, unsigned); |
762 | static int __init sn_sal_console_setup(struct console *, char *); | 762 | static int sn_sal_console_setup(struct console *, char *); |
763 | static struct uart_driver sal_console_uart; | 763 | static struct uart_driver sal_console_uart; |
764 | extern struct tty_driver *uart_console_device(struct console *, int *); | 764 | extern struct tty_driver *uart_console_device(struct console *, int *); |
765 | 765 | ||
@@ -1006,7 +1006,7 @@ sn_sal_console_write(struct console *co, const char *s, unsigned count) | |||
1006 | * here so providing it is easier. | 1006 | * here so providing it is easier. |
1007 | * | 1007 | * |
1008 | */ | 1008 | */ |
1009 | static int __init sn_sal_console_setup(struct console *co, char *options) | 1009 | static int sn_sal_console_setup(struct console *co, char *options) |
1010 | { | 1010 | { |
1011 | return 0; | 1011 | return 0; |
1012 | } | 1012 | } |
diff --git a/drivers/serial/sunhv.c b/drivers/serial/sunhv.c index 96557e6dba60..17bcca53d6a1 100644 --- a/drivers/serial/sunhv.c +++ b/drivers/serial/sunhv.c | |||
@@ -440,8 +440,16 @@ static void sunhv_console_write_paged(struct console *con, const char *s, unsign | |||
440 | { | 440 | { |
441 | struct uart_port *port = sunhv_port; | 441 | struct uart_port *port = sunhv_port; |
442 | unsigned long flags; | 442 | unsigned long flags; |
443 | int locked = 1; | ||
444 | |||
445 | local_irq_save(flags); | ||
446 | if (port->sysrq) { | ||
447 | locked = 0; | ||
448 | } else if (oops_in_progress) { | ||
449 | locked = spin_trylock(&port->lock); | ||
450 | } else | ||
451 | spin_lock(&port->lock); | ||
443 | 452 | ||
444 | spin_lock_irqsave(&port->lock, flags); | ||
445 | while (n > 0) { | 453 | while (n > 0) { |
446 | unsigned long ra = __pa(con_write_page); | 454 | unsigned long ra = __pa(con_write_page); |
447 | unsigned long page_bytes; | 455 | unsigned long page_bytes; |
@@ -469,7 +477,10 @@ static void sunhv_console_write_paged(struct console *con, const char *s, unsign | |||
469 | ra += written; | 477 | ra += written; |
470 | } | 478 | } |
471 | } | 479 | } |
472 | spin_unlock_irqrestore(&port->lock, flags); | 480 | |
481 | if (locked) | ||
482 | spin_unlock(&port->lock); | ||
483 | local_irq_restore(flags); | ||
473 | } | 484 | } |
474 | 485 | ||
475 | static inline void sunhv_console_putchar(struct uart_port *port, char c) | 486 | static inline void sunhv_console_putchar(struct uart_port *port, char c) |
@@ -488,7 +499,15 @@ static void sunhv_console_write_bychar(struct console *con, const char *s, unsig | |||
488 | { | 499 | { |
489 | struct uart_port *port = sunhv_port; | 500 | struct uart_port *port = sunhv_port; |
490 | unsigned long flags; | 501 | unsigned long flags; |
491 | int i; | 502 | int i, locked = 1; |
503 | |||
504 | local_irq_save(flags); | ||
505 | if (port->sysrq) { | ||
506 | locked = 0; | ||
507 | } else if (oops_in_progress) { | ||
508 | locked = spin_trylock(&port->lock); | ||
509 | } else | ||
510 | spin_lock(&port->lock); | ||
492 | 511 | ||
493 | spin_lock_irqsave(&port->lock, flags); | 512 | spin_lock_irqsave(&port->lock, flags); |
494 | for (i = 0; i < n; i++) { | 513 | for (i = 0; i < n; i++) { |
@@ -496,7 +515,10 @@ static void sunhv_console_write_bychar(struct console *con, const char *s, unsig | |||
496 | sunhv_console_putchar(port, '\r'); | 515 | sunhv_console_putchar(port, '\r'); |
497 | sunhv_console_putchar(port, *s++); | 516 | sunhv_console_putchar(port, *s++); |
498 | } | 517 | } |
499 | spin_unlock_irqrestore(&port->lock, flags); | 518 | |
519 | if (locked) | ||
520 | spin_unlock(&port->lock); | ||
521 | local_irq_restore(flags); | ||
500 | } | 522 | } |
501 | 523 | ||
502 | static struct console sunhv_console = { | 524 | static struct console sunhv_console = { |
diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c index deb9ab4b5a0b..8a0f9e4408d4 100644 --- a/drivers/serial/sunsab.c +++ b/drivers/serial/sunsab.c | |||
@@ -860,22 +860,31 @@ static int num_channels; | |||
860 | static void sunsab_console_putchar(struct uart_port *port, int c) | 860 | static void sunsab_console_putchar(struct uart_port *port, int c) |
861 | { | 861 | { |
862 | struct uart_sunsab_port *up = (struct uart_sunsab_port *)port; | 862 | struct uart_sunsab_port *up = (struct uart_sunsab_port *)port; |
863 | unsigned long flags; | ||
864 | |||
865 | spin_lock_irqsave(&up->port.lock, flags); | ||
866 | 863 | ||
867 | sunsab_tec_wait(up); | 864 | sunsab_tec_wait(up); |
868 | writeb(c, &up->regs->w.tic); | 865 | writeb(c, &up->regs->w.tic); |
869 | |||
870 | spin_unlock_irqrestore(&up->port.lock, flags); | ||
871 | } | 866 | } |
872 | 867 | ||
873 | static void sunsab_console_write(struct console *con, const char *s, unsigned n) | 868 | static void sunsab_console_write(struct console *con, const char *s, unsigned n) |
874 | { | 869 | { |
875 | struct uart_sunsab_port *up = &sunsab_ports[con->index]; | 870 | struct uart_sunsab_port *up = &sunsab_ports[con->index]; |
871 | unsigned long flags; | ||
872 | int locked = 1; | ||
873 | |||
874 | local_irq_save(flags); | ||
875 | if (up->port.sysrq) { | ||
876 | locked = 0; | ||
877 | } else if (oops_in_progress) { | ||
878 | locked = spin_trylock(&up->port.lock); | ||
879 | } else | ||
880 | spin_lock(&up->port.lock); | ||
876 | 881 | ||
877 | uart_console_write(&up->port, s, n, sunsab_console_putchar); | 882 | uart_console_write(&up->port, s, n, sunsab_console_putchar); |
878 | sunsab_tec_wait(up); | 883 | sunsab_tec_wait(up); |
884 | |||
885 | if (locked) | ||
886 | spin_unlock(&up->port.lock); | ||
887 | local_irq_restore(flags); | ||
879 | } | 888 | } |
880 | 889 | ||
881 | static int sunsab_console_setup(struct console *con, char *options) | 890 | static int sunsab_console_setup(struct console *con, char *options) |
diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c index 2a63cdba3208..26d720baf88c 100644 --- a/drivers/serial/sunsu.c +++ b/drivers/serial/sunsu.c | |||
@@ -1288,7 +1288,17 @@ static void sunsu_console_write(struct console *co, const char *s, | |||
1288 | unsigned int count) | 1288 | unsigned int count) |
1289 | { | 1289 | { |
1290 | struct uart_sunsu_port *up = &sunsu_ports[co->index]; | 1290 | struct uart_sunsu_port *up = &sunsu_ports[co->index]; |
1291 | unsigned long flags; | ||
1291 | unsigned int ier; | 1292 | unsigned int ier; |
1293 | int locked = 1; | ||
1294 | |||
1295 | local_irq_save(flags); | ||
1296 | if (up->port.sysrq) { | ||
1297 | locked = 0; | ||
1298 | } else if (oops_in_progress) { | ||
1299 | locked = spin_trylock(&up->port.lock); | ||
1300 | } else | ||
1301 | spin_lock(&up->port.lock); | ||
1292 | 1302 | ||
1293 | /* | 1303 | /* |
1294 | * First save the UER then disable the interrupts | 1304 | * First save the UER then disable the interrupts |
@@ -1304,6 +1314,10 @@ static void sunsu_console_write(struct console *co, const char *s, | |||
1304 | */ | 1314 | */ |
1305 | wait_for_xmitr(up); | 1315 | wait_for_xmitr(up); |
1306 | serial_out(up, UART_IER, ier); | 1316 | serial_out(up, UART_IER, ier); |
1317 | |||
1318 | if (locked) | ||
1319 | spin_unlock(&up->port.lock); | ||
1320 | local_irq_restore(flags); | ||
1307 | } | 1321 | } |
1308 | 1322 | ||
1309 | /* | 1323 | /* |
diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c index 15b6e1cb040b..0a3e10a4a35d 100644 --- a/drivers/serial/sunzilog.c +++ b/drivers/serial/sunzilog.c | |||
@@ -9,7 +9,7 @@ | |||
9 | * C. Dost, Pete Zaitcev, Ted Ts'o and Alex Buell for their | 9 | * C. Dost, Pete Zaitcev, Ted Ts'o and Alex Buell for their |
10 | * work there. | 10 | * work there. |
11 | * | 11 | * |
12 | * Copyright (C) 2002, 2006 David S. Miller (davem@davemloft.net) | 12 | * Copyright (C) 2002, 2006, 2007 David S. Miller (davem@davemloft.net) |
13 | */ | 13 | */ |
14 | 14 | ||
15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
@@ -1151,11 +1151,22 @@ sunzilog_console_write(struct console *con, const char *s, unsigned int count) | |||
1151 | { | 1151 | { |
1152 | struct uart_sunzilog_port *up = &sunzilog_port_table[con->index]; | 1152 | struct uart_sunzilog_port *up = &sunzilog_port_table[con->index]; |
1153 | unsigned long flags; | 1153 | unsigned long flags; |
1154 | int locked = 1; | ||
1155 | |||
1156 | local_irq_save(flags); | ||
1157 | if (up->port.sysrq) { | ||
1158 | locked = 0; | ||
1159 | } else if (oops_in_progress) { | ||
1160 | locked = spin_trylock(&up->port.lock); | ||
1161 | } else | ||
1162 | spin_lock(&up->port.lock); | ||
1154 | 1163 | ||
1155 | spin_lock_irqsave(&up->port.lock, flags); | ||
1156 | uart_console_write(&up->port, s, count, sunzilog_putchar); | 1164 | uart_console_write(&up->port, s, count, sunzilog_putchar); |
1157 | udelay(2); | 1165 | udelay(2); |
1158 | spin_unlock_irqrestore(&up->port.lock, flags); | 1166 | |
1167 | if (locked) | ||
1168 | spin_unlock(&up->port.lock); | ||
1169 | local_irq_restore(flags); | ||
1159 | } | 1170 | } |
1160 | 1171 | ||
1161 | static int __init sunzilog_console_setup(struct console *con, char *options) | 1172 | static int __init sunzilog_console_setup(struct console *con, char *options) |
diff --git a/drivers/telephony/Kconfig b/drivers/telephony/Kconfig index dd1d6a53f3c0..8f530e68263b 100644 --- a/drivers/telephony/Kconfig +++ b/drivers/telephony/Kconfig | |||
@@ -2,11 +2,9 @@ | |||
2 | # Telephony device configuration | 2 | # Telephony device configuration |
3 | # | 3 | # |
4 | 4 | ||
5 | menu "Telephony Support" | 5 | menuconfig PHONE |
6 | tristate "Telephony support" | ||
6 | depends on HAS_IOMEM | 7 | depends on HAS_IOMEM |
7 | |||
8 | config PHONE | ||
9 | tristate "Linux telephony support" | ||
10 | ---help--- | 8 | ---help--- |
11 | Say Y here if you have a telephony card, which for example allows | 9 | Say Y here if you have a telephony card, which for example allows |
12 | you to use a regular phone for voice-over-IP applications. | 10 | you to use a regular phone for voice-over-IP applications. |
@@ -17,9 +15,10 @@ config PHONE | |||
17 | To compile this driver as a module, choose M here: the | 15 | To compile this driver as a module, choose M here: the |
18 | module will be called phonedev. | 16 | module will be called phonedev. |
19 | 17 | ||
18 | if PHONE | ||
19 | |||
20 | config PHONE_IXJ | 20 | config PHONE_IXJ |
21 | tristate "QuickNet Internet LineJack/PhoneJack support" | 21 | tristate "QuickNet Internet LineJack/PhoneJack support" |
22 | depends on PHONE | ||
23 | ---help--- | 22 | ---help--- |
24 | Say M if you have a telephony card manufactured by Quicknet | 23 | Say M if you have a telephony card manufactured by Quicknet |
25 | Technologies, Inc. These include the Internet PhoneJACK and | 24 | Technologies, Inc. These include the Internet PhoneJACK and |
@@ -44,5 +43,4 @@ config PHONE_IXJ_PCMCIA | |||
44 | cards manufactured by Quicknet Technologies, Inc. This changes the | 43 | cards manufactured by Quicknet Technologies, Inc. This changes the |
45 | card initialization code to work with the card manager daemon. | 44 | card initialization code to work with the card manager daemon. |
46 | 45 | ||
47 | endmenu | 46 | endif # PHONE |
48 | |||
diff --git a/drivers/video/pvr2fb.c b/drivers/video/pvr2fb.c index df2909ae704c..2ba959a83eb0 100644 --- a/drivers/video/pvr2fb.c +++ b/drivers/video/pvr2fb.c | |||
@@ -115,11 +115,11 @@ enum { VO_PAL, VO_NTSC, VO_VGA }; | |||
115 | enum { PAL_ARGB1555, PAL_RGB565, PAL_ARGB4444, PAL_ARGB8888 }; | 115 | enum { PAL_ARGB1555, PAL_RGB565, PAL_ARGB4444, PAL_ARGB8888 }; |
116 | 116 | ||
117 | struct pvr2_params { unsigned int val; char *name; }; | 117 | struct pvr2_params { unsigned int val; char *name; }; |
118 | static struct pvr2_params cables[] __initdata = { | 118 | static struct pvr2_params cables[] __devinitdata = { |
119 | { CT_VGA, "VGA" }, { CT_RGB, "RGB" }, { CT_COMPOSITE, "COMPOSITE" }, | 119 | { CT_VGA, "VGA" }, { CT_RGB, "RGB" }, { CT_COMPOSITE, "COMPOSITE" }, |
120 | }; | 120 | }; |
121 | 121 | ||
122 | static struct pvr2_params outputs[] __initdata = { | 122 | static struct pvr2_params outputs[] __devinitdata = { |
123 | { VO_PAL, "PAL" }, { VO_NTSC, "NTSC" }, { VO_VGA, "VGA" }, | 123 | { VO_PAL, "PAL" }, { VO_NTSC, "NTSC" }, { VO_VGA, "VGA" }, |
124 | }; | 124 | }; |
125 | 125 | ||
@@ -147,16 +147,16 @@ static struct pvr2fb_par { | |||
147 | 147 | ||
148 | static struct fb_info *fb_info; | 148 | static struct fb_info *fb_info; |
149 | 149 | ||
150 | static struct fb_fix_screeninfo pvr2_fix __initdata = { | 150 | static struct fb_fix_screeninfo pvr2_fix __devinitdata = { |
151 | .id = "NEC PowerVR2", | 151 | .id = "NEC PowerVR2", |
152 | .type = FB_TYPE_PACKED_PIXELS, | 152 | .type = FB_TYPE_PACKED_PIXELS, |
153 | .visual = FB_VISUAL_TRUECOLOR, | 153 | .visual = FB_VISUAL_TRUECOLOR, |
154 | .ypanstep = 1, | 154 | .ypanstep = 1, |
155 | .ywrapstep = 1, | 155 | .ywrapstep = 1, |
156 | .accel = FB_ACCEL_NONE, | 156 | .accel = FB_ACCEL_NONE, |
157 | }; | 157 | }; |
158 | 158 | ||
159 | static struct fb_var_screeninfo pvr2_var __initdata = { | 159 | static struct fb_var_screeninfo pvr2_var __devinitdata = { |
160 | .xres = 640, | 160 | .xres = 640, |
161 | .yres = 480, | 161 | .yres = 480, |
162 | .xres_virtual = 640, | 162 | .xres_virtual = 640, |
@@ -195,10 +195,6 @@ static unsigned int shdma = PVR2_CASCADE_CHAN; | |||
195 | static unsigned int pvr2dma = ONCHIP_NR_DMA_CHANNELS; | 195 | static unsigned int pvr2dma = ONCHIP_NR_DMA_CHANNELS; |
196 | #endif | 196 | #endif |
197 | 197 | ||
198 | /* Interface used by the world */ | ||
199 | |||
200 | int pvr2fb_setup(char*); | ||
201 | |||
202 | static int pvr2fb_setcolreg(unsigned int regno, unsigned int red, unsigned int green, unsigned int blue, | 198 | static int pvr2fb_setcolreg(unsigned int regno, unsigned int red, unsigned int green, unsigned int blue, |
203 | unsigned int transp, struct fb_info *info); | 199 | unsigned int transp, struct fb_info *info); |
204 | static int pvr2fb_blank(int blank, struct fb_info *info); | 200 | static int pvr2fb_blank(int blank, struct fb_info *info); |
@@ -227,12 +223,12 @@ static struct fb_ops pvr2fb_ops = { | |||
227 | #ifdef CONFIG_SH_DMA | 223 | #ifdef CONFIG_SH_DMA |
228 | .fb_write = pvr2fb_write, | 224 | .fb_write = pvr2fb_write, |
229 | #endif | 225 | #endif |
230 | .fb_fillrect = cfb_fillrect, | 226 | .fb_fillrect = cfb_fillrect, |
231 | .fb_copyarea = cfb_copyarea, | 227 | .fb_copyarea = cfb_copyarea, |
232 | .fb_imageblit = cfb_imageblit, | 228 | .fb_imageblit = cfb_imageblit, |
233 | }; | 229 | }; |
234 | 230 | ||
235 | static struct fb_videomode pvr2_modedb[] __initdata = { | 231 | static struct fb_videomode pvr2_modedb[] __devinitdata = { |
236 | /* | 232 | /* |
237 | * Broadcast video modes (PAL and NTSC). I'm unfamiliar with | 233 | * Broadcast video modes (PAL and NTSC). I'm unfamiliar with |
238 | * PAL-M and PAL-N, but from what I've read both modes parallel PAL and | 234 | * PAL-M and PAL-N, but from what I've read both modes parallel PAL and |
@@ -252,7 +248,7 @@ static struct fb_videomode pvr2_modedb[] __initdata = { | |||
252 | /* 640x480 @ 60hz (VGA) */ | 248 | /* 640x480 @ 60hz (VGA) */ |
253 | "vga_640x480", 60, 640, 480, VGA_CLK, 38, 33, 0, 18, 146, 26, | 249 | "vga_640x480", 60, 640, 480, VGA_CLK, 38, 33, 0, 18, 146, 26, |
254 | 0, FB_VMODE_YWRAP | 250 | 0, FB_VMODE_YWRAP |
255 | }, | 251 | }, |
256 | }; | 252 | }; |
257 | 253 | ||
258 | #define NUM_TOTAL_MODES ARRAY_SIZE(pvr2_modedb) | 254 | #define NUM_TOTAL_MODES ARRAY_SIZE(pvr2_modedb) |
@@ -262,7 +258,7 @@ static struct fb_videomode pvr2_modedb[] __initdata = { | |||
262 | #define DEFMODE_VGA 2 | 258 | #define DEFMODE_VGA 2 |
263 | 259 | ||
264 | static int defmode = DEFMODE_NTSC; | 260 | static int defmode = DEFMODE_NTSC; |
265 | static char *mode_option __initdata = NULL; | 261 | static char *mode_option __devinitdata = NULL; |
266 | 262 | ||
267 | static inline void pvr2fb_set_pal_type(unsigned int type) | 263 | static inline void pvr2fb_set_pal_type(unsigned int type) |
268 | { | 264 | { |
@@ -293,7 +289,7 @@ static void set_color_bitfields(struct fb_var_screeninfo *var) | |||
293 | { | 289 | { |
294 | switch (var->bits_per_pixel) { | 290 | switch (var->bits_per_pixel) { |
295 | case 16: /* RGB 565 */ | 291 | case 16: /* RGB 565 */ |
296 | pvr2fb_set_pal_type(PAL_RGB565); | 292 | pvr2fb_set_pal_type(PAL_RGB565); |
297 | var->red.offset = 11; var->red.length = 5; | 293 | var->red.offset = 11; var->red.length = 5; |
298 | var->green.offset = 5; var->green.length = 6; | 294 | var->green.offset = 5; var->green.length = 6; |
299 | var->blue.offset = 0; var->blue.length = 5; | 295 | var->blue.offset = 0; var->blue.length = 5; |
@@ -306,7 +302,7 @@ static void set_color_bitfields(struct fb_var_screeninfo *var) | |||
306 | var->transp.offset = 0; var->transp.length = 0; | 302 | var->transp.offset = 0; var->transp.length = 0; |
307 | break; | 303 | break; |
308 | case 32: /* ARGB 8888 */ | 304 | case 32: /* ARGB 8888 */ |
309 | pvr2fb_set_pal_type(PAL_ARGB8888); | 305 | pvr2fb_set_pal_type(PAL_ARGB8888); |
310 | var->red.offset = 16; var->red.length = 8; | 306 | var->red.offset = 16; var->red.length = 8; |
311 | var->green.offset = 8; var->green.length = 8; | 307 | var->green.offset = 8; var->green.length = 8; |
312 | var->blue.offset = 0; var->blue.length = 8; | 308 | var->blue.offset = 0; var->blue.length = 8; |
@@ -379,13 +375,13 @@ static int pvr2fb_set_par(struct fb_info *info) | |||
379 | var->vmode &= FB_VMODE_MASK; | 375 | var->vmode &= FB_VMODE_MASK; |
380 | if (var->vmode & FB_VMODE_INTERLACED && video_output != VO_VGA) | 376 | if (var->vmode & FB_VMODE_INTERLACED && video_output != VO_VGA) |
381 | par->is_interlaced = 1; | 377 | par->is_interlaced = 1; |
382 | /* | 378 | /* |
383 | * XXX: Need to be more creative with this (i.e. allow doublecan for | 379 | * XXX: Need to be more creative with this (i.e. allow doublecan for |
384 | * PAL/NTSC output). | 380 | * PAL/NTSC output). |
385 | */ | 381 | */ |
386 | if (var->vmode & FB_VMODE_DOUBLE && video_output == VO_VGA) | 382 | if (var->vmode & FB_VMODE_DOUBLE && video_output == VO_VGA) |
387 | par->is_doublescan = 1; | 383 | par->is_doublescan = 1; |
388 | 384 | ||
389 | par->hsync_total = var->left_margin + var->xres + var->right_margin + | 385 | par->hsync_total = var->left_margin + var->xres + var->right_margin + |
390 | var->hsync_len; | 386 | var->hsync_len; |
391 | par->vsync_total = var->upper_margin + var->yres + var->lower_margin + | 387 | par->vsync_total = var->upper_margin + var->yres + var->lower_margin + |
@@ -408,7 +404,7 @@ static int pvr2fb_set_par(struct fb_info *info) | |||
408 | } else { | 404 | } else { |
409 | /* VGA mode */ | 405 | /* VGA mode */ |
410 | /* XXX: What else needs to be checked? */ | 406 | /* XXX: What else needs to be checked? */ |
411 | /* | 407 | /* |
412 | * XXX: We have a little freedom in VGA modes, what ranges | 408 | * XXX: We have a little freedom in VGA modes, what ranges |
413 | * should be here (i.e. hsync/vsync totals, etc.)? | 409 | * should be here (i.e. hsync/vsync totals, etc.)? |
414 | */ | 410 | */ |
@@ -419,8 +415,8 @@ static int pvr2fb_set_par(struct fb_info *info) | |||
419 | /* Calculate the remainding offsets */ | 415 | /* Calculate the remainding offsets */ |
420 | par->diwstart_h = par->borderstart_h + var->left_margin; | 416 | par->diwstart_h = par->borderstart_h + var->left_margin; |
421 | par->diwstart_v = par->borderstart_v + var->upper_margin; | 417 | par->diwstart_v = par->borderstart_v + var->upper_margin; |
422 | par->borderstop_h = par->diwstart_h + var->xres + | 418 | par->borderstop_h = par->diwstart_h + var->xres + |
423 | var->right_margin; | 419 | var->right_margin; |
424 | par->borderstop_v = par->diwstart_v + var->yres + | 420 | par->borderstop_v = par->diwstart_v + var->yres + |
425 | var->lower_margin; | 421 | var->lower_margin; |
426 | 422 | ||
@@ -465,12 +461,12 @@ static int pvr2fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) | |||
465 | set_color_bitfields(var); | 461 | set_color_bitfields(var); |
466 | 462 | ||
467 | if (var->vmode & FB_VMODE_YWRAP) { | 463 | if (var->vmode & FB_VMODE_YWRAP) { |
468 | if (var->xoffset || var->yoffset < 0 || | 464 | if (var->xoffset || var->yoffset < 0 || |
469 | var->yoffset >= var->yres_virtual) { | 465 | var->yoffset >= var->yres_virtual) { |
470 | var->xoffset = var->yoffset = 0; | 466 | var->xoffset = var->yoffset = 0; |
471 | } else { | 467 | } else { |
472 | if (var->xoffset > var->xres_virtual - var->xres || | 468 | if (var->xoffset > var->xres_virtual - var->xres || |
473 | var->yoffset > var->yres_virtual - var->yres || | 469 | var->yoffset > var->yres_virtual - var->yres || |
474 | var->xoffset < 0 || var->yoffset < 0) | 470 | var->xoffset < 0 || var->yoffset < 0) |
475 | var->xoffset = var->yoffset = 0; | 471 | var->xoffset = var->yoffset = 0; |
476 | } | 472 | } |
@@ -478,7 +474,7 @@ static int pvr2fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) | |||
478 | var->xoffset = var->yoffset = 0; | 474 | var->xoffset = var->yoffset = 0; |
479 | } | 475 | } |
480 | 476 | ||
481 | /* | 477 | /* |
482 | * XXX: Need to be more creative with this (i.e. allow doublecan for | 478 | * XXX: Need to be more creative with this (i.e. allow doublecan for |
483 | * PAL/NTSC output). | 479 | * PAL/NTSC output). |
484 | */ | 480 | */ |
@@ -507,7 +503,7 @@ static int pvr2fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) | |||
507 | var->vsync_len = par->borderstop_v + | 503 | var->vsync_len = par->borderstop_v + |
508 | (par->vsync_total - par->borderstop_v); | 504 | (par->vsync_total - par->borderstop_v); |
509 | } | 505 | } |
510 | 506 | ||
511 | hsync_total = var->left_margin + var->xres + var->right_margin + | 507 | hsync_total = var->left_margin + var->xres + var->right_margin + |
512 | var->hsync_len; | 508 | var->hsync_len; |
513 | vtotal = var->upper_margin + var->yres + var->lower_margin + | 509 | vtotal = var->upper_margin + var->yres + var->lower_margin + |
@@ -531,7 +527,7 @@ static int pvr2fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) | |||
531 | } | 527 | } |
532 | } | 528 | } |
533 | } | 529 | } |
534 | 530 | ||
535 | /* Check memory sizes */ | 531 | /* Check memory sizes */ |
536 | line_length = get_line_length(var->xres_virtual, var->bits_per_pixel); | 532 | line_length = get_line_length(var->xres_virtual, var->bits_per_pixel); |
537 | if (line_length * var->yres_virtual > info->fix.smem_len) | 533 | if (line_length * var->yres_virtual > info->fix.smem_len) |
@@ -552,7 +548,7 @@ static void pvr2_update_display(struct fb_info *info) | |||
552 | DISP_DIWADDRS); | 548 | DISP_DIWADDRS); |
553 | } | 549 | } |
554 | 550 | ||
555 | /* | 551 | /* |
556 | * Initialize the video mode. Currently, the 16bpp and 24bpp modes aren't | 552 | * Initialize the video mode. Currently, the 16bpp and 24bpp modes aren't |
557 | * very stable. It's probably due to the fact that a lot of the 2D video | 553 | * very stable. It's probably due to the fact that a lot of the 2D video |
558 | * registers are still undocumented. | 554 | * registers are still undocumented. |
@@ -592,18 +588,18 @@ static void pvr2_init_display(struct fb_info *info) | |||
592 | /* display window start position */ | 588 | /* display window start position */ |
593 | fb_writel(par->diwstart_h, DISP_DIWHSTRT); | 589 | fb_writel(par->diwstart_h, DISP_DIWHSTRT); |
594 | fb_writel((par->diwstart_v << 16) | par->diwstart_v, DISP_DIWVSTRT); | 590 | fb_writel((par->diwstart_v << 16) | par->diwstart_v, DISP_DIWVSTRT); |
595 | 591 | ||
596 | /* misc. settings */ | 592 | /* misc. settings */ |
597 | fb_writel((0x16 << 16) | par->is_lowres, DISP_DIWCONF); | 593 | fb_writel((0x16 << 16) | par->is_lowres, DISP_DIWCONF); |
598 | 594 | ||
599 | /* clock doubler (for VGA), scan doubler, display enable */ | 595 | /* clock doubler (for VGA), scan doubler, display enable */ |
600 | fb_writel(((video_output == VO_VGA) << 23) | | 596 | fb_writel(((video_output == VO_VGA) << 23) | |
601 | (par->is_doublescan << 1) | 1, DISP_DIWMODE); | 597 | (par->is_doublescan << 1) | 1, DISP_DIWMODE); |
602 | 598 | ||
603 | /* bits per pixel */ | 599 | /* bits per pixel */ |
604 | fb_writel(fb_readl(DISP_DIWMODE) | (--bytesperpixel << 2), DISP_DIWMODE); | 600 | fb_writel(fb_readl(DISP_DIWMODE) | (--bytesperpixel << 2), DISP_DIWMODE); |
605 | 601 | ||
606 | /* video enable, color sync, interlace, | 602 | /* video enable, color sync, interlace, |
607 | * hsync and vsync polarity (currently unused) */ | 603 | * hsync and vsync polarity (currently unused) */ |
608 | fb_writel(0x100 | ((par->is_interlaced /*|4*/) << 4), DISP_SYNCCONF); | 604 | fb_writel(0x100 | ((par->is_interlaced /*|4*/) << 4), DISP_SYNCCONF); |
609 | } | 605 | } |
@@ -657,7 +653,7 @@ static irqreturn_t pvr2fb_interrupt(int irq, void *dev_id) | |||
657 | static int pvr2_init_cable(void) | 653 | static int pvr2_init_cable(void) |
658 | { | 654 | { |
659 | if (cable_type < 0) { | 655 | if (cable_type < 0) { |
660 | fb_writel((fb_readl(PCTRA) & 0xfff0ffff) | 0x000a0000, | 656 | fb_writel((fb_readl(PCTRA) & 0xfff0ffff) | 0x000a0000, |
661 | PCTRA); | 657 | PCTRA); |
662 | cable_type = (fb_readw(PDTRA) >> 8) & 3; | 658 | cable_type = (fb_readw(PDTRA) >> 8) & 3; |
663 | } | 659 | } |
@@ -687,7 +683,7 @@ static ssize_t pvr2fb_write(struct fb_info *info, const char *buf, | |||
687 | pages = kmalloc(nr_pages * sizeof(struct page *), GFP_KERNEL); | 683 | pages = kmalloc(nr_pages * sizeof(struct page *), GFP_KERNEL); |
688 | if (!pages) | 684 | if (!pages) |
689 | return -ENOMEM; | 685 | return -ENOMEM; |
690 | 686 | ||
691 | down_read(¤t->mm->mmap_sem); | 687 | down_read(¤t->mm->mmap_sem); |
692 | ret = get_user_pages(current, current->mm, (unsigned long)buf, | 688 | ret = get_user_pages(current, current->mm, (unsigned long)buf, |
693 | nr_pages, WRITE, 0, pages, NULL); | 689 | nr_pages, WRITE, 0, pages, NULL); |
@@ -700,7 +696,7 @@ static ssize_t pvr2fb_write(struct fb_info *info, const char *buf, | |||
700 | } | 696 | } |
701 | 697 | ||
702 | dma_configure_channel(shdma, 0x12c1); | 698 | dma_configure_channel(shdma, 0x12c1); |
703 | 699 | ||
704 | dst = (unsigned long)fb_info->screen_base + *ppos; | 700 | dst = (unsigned long)fb_info->screen_base + *ppos; |
705 | start = (unsigned long)page_address(pages[0]); | 701 | start = (unsigned long)page_address(pages[0]); |
706 | end = (unsigned long)page_address(pages[nr_pages]); | 702 | end = (unsigned long)page_address(pages[nr_pages]); |
@@ -744,7 +740,7 @@ out_unmap: | |||
744 | kfree(pages); | 740 | kfree(pages); |
745 | 741 | ||
746 | return ret; | 742 | return ret; |
747 | } | 743 | } |
748 | #endif /* CONFIG_SH_DMA */ | 744 | #endif /* CONFIG_SH_DMA */ |
749 | 745 | ||
750 | /** | 746 | /** |
@@ -765,21 +761,21 @@ out_unmap: | |||
765 | * in for flexibility anyways. Who knows, maybe someone has tv-out on a | 761 | * in for flexibility anyways. Who knows, maybe someone has tv-out on a |
766 | * PCI-based version of these things ;-) | 762 | * PCI-based version of these things ;-) |
767 | */ | 763 | */ |
768 | static int __init pvr2fb_common_init(void) | 764 | static int __devinit pvr2fb_common_init(void) |
769 | { | 765 | { |
770 | struct pvr2fb_par *par = currentpar; | 766 | struct pvr2fb_par *par = currentpar; |
771 | unsigned long modememused, rev; | 767 | unsigned long modememused, rev; |
772 | 768 | ||
773 | fb_info->screen_base = ioremap_nocache(pvr2_fix.smem_start, | 769 | fb_info->screen_base = ioremap_nocache(pvr2_fix.smem_start, |
774 | pvr2_fix.smem_len); | 770 | pvr2_fix.smem_len); |
775 | 771 | ||
776 | if (!fb_info->screen_base) { | 772 | if (!fb_info->screen_base) { |
777 | printk(KERN_ERR "pvr2fb: Failed to remap smem space\n"); | 773 | printk(KERN_ERR "pvr2fb: Failed to remap smem space\n"); |
778 | goto out_err; | 774 | goto out_err; |
779 | } | 775 | } |
780 | 776 | ||
781 | par->mmio_base = (unsigned long)ioremap_nocache(pvr2_fix.mmio_start, | 777 | par->mmio_base = (unsigned long)ioremap_nocache(pvr2_fix.mmio_start, |
782 | pvr2_fix.mmio_len); | 778 | pvr2_fix.mmio_len); |
783 | if (!par->mmio_base) { | 779 | if (!par->mmio_base) { |
784 | printk(KERN_ERR "pvr2fb: Failed to remap mmio space\n"); | 780 | printk(KERN_ERR "pvr2fb: Failed to remap mmio space\n"); |
785 | goto out_err; | 781 | goto out_err; |
@@ -820,7 +816,7 @@ static int __init pvr2fb_common_init(void) | |||
820 | printk("fb%d: %s (rev %ld.%ld) frame buffer device, using %ldk/%ldk of video memory\n", | 816 | printk("fb%d: %s (rev %ld.%ld) frame buffer device, using %ldk/%ldk of video memory\n", |
821 | fb_info->node, fb_info->fix.id, (rev >> 4) & 0x0f, rev & 0x0f, | 817 | fb_info->node, fb_info->fix.id, (rev >> 4) & 0x0f, rev & 0x0f, |
822 | modememused >> 10, (unsigned long)(fb_info->fix.smem_len >> 10)); | 818 | modememused >> 10, (unsigned long)(fb_info->fix.smem_len >> 10)); |
823 | printk("fb%d: Mode %dx%d-%d pitch = %ld cable: %s video output: %s\n", | 819 | printk("fb%d: Mode %dx%d-%d pitch = %ld cable: %s video output: %s\n", |
824 | fb_info->node, fb_info->var.xres, fb_info->var.yres, | 820 | fb_info->node, fb_info->var.xres, fb_info->var.yres, |
825 | fb_info->var.bits_per_pixel, | 821 | fb_info->var.bits_per_pixel, |
826 | get_line_length(fb_info->var.xres, fb_info->var.bits_per_pixel), | 822 | get_line_length(fb_info->var.xres, fb_info->var.bits_per_pixel), |
@@ -878,8 +874,8 @@ static int __init pvr2fb_dc_init(void) | |||
878 | video_output = VO_NTSC; | 874 | video_output = VO_NTSC; |
879 | } | 875 | } |
880 | } | 876 | } |
881 | 877 | ||
882 | /* | 878 | /* |
883 | * Nothing exciting about the DC PVR2 .. only a measly 8MiB. | 879 | * Nothing exciting about the DC PVR2 .. only a measly 8MiB. |
884 | */ | 880 | */ |
885 | pvr2_fix.smem_start = 0xa5000000; /* RAM starts here */ | 881 | pvr2_fix.smem_start = 0xa5000000; /* RAM starts here */ |
@@ -903,7 +899,7 @@ static int __init pvr2fb_dc_init(void) | |||
903 | return pvr2fb_common_init(); | 899 | return pvr2fb_common_init(); |
904 | } | 900 | } |
905 | 901 | ||
906 | static void pvr2fb_dc_exit(void) | 902 | static void __exit pvr2fb_dc_exit(void) |
907 | { | 903 | { |
908 | if (fb_info->screen_base) { | 904 | if (fb_info->screen_base) { |
909 | iounmap(fb_info->screen_base); | 905 | iounmap(fb_info->screen_base); |
@@ -987,13 +983,13 @@ static int __init pvr2fb_pci_init(void) | |||
987 | return pci_register_driver(&pvr2fb_pci_driver); | 983 | return pci_register_driver(&pvr2fb_pci_driver); |
988 | } | 984 | } |
989 | 985 | ||
990 | static void pvr2fb_pci_exit(void) | 986 | static void __exit pvr2fb_pci_exit(void) |
991 | { | 987 | { |
992 | pci_unregister_driver(&pvr2fb_pci_driver); | 988 | pci_unregister_driver(&pvr2fb_pci_driver); |
993 | } | 989 | } |
994 | #endif /* CONFIG_PCI */ | 990 | #endif /* CONFIG_PCI */ |
995 | 991 | ||
996 | static int __init pvr2_get_param(const struct pvr2_params *p, const char *s, | 992 | static int __devinit pvr2_get_param(const struct pvr2_params *p, const char *s, |
997 | int val, int size) | 993 | int val, int size) |
998 | { | 994 | { |
999 | int i; | 995 | int i; |
@@ -1021,7 +1017,7 @@ static int __init pvr2_get_param(const struct pvr2_params *p, const char *s, | |||
1021 | */ | 1017 | */ |
1022 | 1018 | ||
1023 | #ifndef MODULE | 1019 | #ifndef MODULE |
1024 | int __init pvr2fb_setup(char *options) | 1020 | static int __init pvr2fb_setup(char *options) |
1025 | { | 1021 | { |
1026 | char *this_opt; | 1022 | char *this_opt; |
1027 | char cable_arg[80]; | 1023 | char cable_arg[80]; |
@@ -1061,7 +1057,7 @@ static struct pvr2_board { | |||
1061 | int (*init)(void); | 1057 | int (*init)(void); |
1062 | void (*exit)(void); | 1058 | void (*exit)(void); |
1063 | char name[16]; | 1059 | char name[16]; |
1064 | } board_list[] = { | 1060 | } board_driver[] = { |
1065 | #ifdef CONFIG_SH_DREAMCAST | 1061 | #ifdef CONFIG_SH_DREAMCAST |
1066 | { pvr2fb_dc_init, pvr2fb_dc_exit, "Sega DC PVR2" }, | 1062 | { pvr2fb_dc_init, pvr2fb_dc_exit, "Sega DC PVR2" }, |
1067 | #endif | 1063 | #endif |
@@ -1071,7 +1067,7 @@ static struct pvr2_board { | |||
1071 | { 0, }, | 1067 | { 0, }, |
1072 | }; | 1068 | }; |
1073 | 1069 | ||
1074 | int __init pvr2fb_init(void) | 1070 | static int __init pvr2fb_init(void) |
1075 | { | 1071 | { |
1076 | int i, ret = -ENODEV; | 1072 | int i, ret = -ENODEV; |
1077 | int size; | 1073 | int size; |
@@ -1095,8 +1091,8 @@ int __init pvr2fb_init(void) | |||
1095 | 1091 | ||
1096 | currentpar = (struct pvr2fb_par *)(fb_info + 1); | 1092 | currentpar = (struct pvr2fb_par *)(fb_info + 1); |
1097 | 1093 | ||
1098 | for (i = 0; i < ARRAY_SIZE(board_list); i++) { | 1094 | for (i = 0; i < ARRAY_SIZE(board_driver); i++) { |
1099 | struct pvr2_board *pvr_board = board_list + i; | 1095 | struct pvr2_board *pvr_board = board_driver + i; |
1100 | 1096 | ||
1101 | if (!pvr_board->init) | 1097 | if (!pvr_board->init) |
1102 | continue; | 1098 | continue; |
@@ -1118,13 +1114,13 @@ static void __exit pvr2fb_exit(void) | |||
1118 | { | 1114 | { |
1119 | int i; | 1115 | int i; |
1120 | 1116 | ||
1121 | for (i = 0; i < ARRAY_SIZE(board_list); i++) { | 1117 | for (i = 0; i < ARRAY_SIZE(board_driver); i++) { |
1122 | struct pvr2_board *pvr_board = board_list + i; | 1118 | struct pvr2_board *pvr_board = board_driver + i; |
1123 | 1119 | ||
1124 | if (pvr_board->exit) | 1120 | if (pvr_board->exit) |
1125 | pvr_board->exit(); | 1121 | pvr_board->exit(); |
1126 | } | 1122 | } |
1127 | 1123 | ||
1128 | #ifdef CONFIG_SH_STORE_QUEUES | 1124 | #ifdef CONFIG_SH_STORE_QUEUES |
1129 | sq_unmap(pvr2fb_map); | 1125 | sq_unmap(pvr2fb_map); |
1130 | #endif | 1126 | #endif |
@@ -1139,4 +1135,3 @@ module_exit(pvr2fb_exit); | |||
1139 | MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>, M. R. Brown <mrbrown@0xd6.org>"); | 1135 | MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>, M. R. Brown <mrbrown@0xd6.org>"); |
1140 | MODULE_DESCRIPTION("Framebuffer driver for NEC PowerVR 2 based graphics boards"); | 1136 | MODULE_DESCRIPTION("Framebuffer driver for NEC PowerVR 2 based graphics boards"); |
1141 | MODULE_LICENSE("GPL"); | 1137 | MODULE_LICENSE("GPL"); |
1142 | |||
diff --git a/drivers/w1/Kconfig b/drivers/w1/Kconfig index ca75b3ad3a2e..6854fd6b9714 100644 --- a/drivers/w1/Kconfig +++ b/drivers/w1/Kconfig | |||
@@ -1,8 +1,6 @@ | |||
1 | menu "Dallas's 1-wire bus" | 1 | menuconfig W1 |
2 | depends on HAS_IOMEM | ||
3 | |||
4 | config W1 | ||
5 | tristate "Dallas's 1-wire support" | 2 | tristate "Dallas's 1-wire support" |
3 | depends on HAS_IOMEM | ||
6 | ---help--- | 4 | ---help--- |
7 | Dallas' 1-wire bus is useful to connect slow 1-pin devices | 5 | Dallas' 1-wire bus is useful to connect slow 1-pin devices |
8 | such as iButtons and thermal sensors. | 6 | such as iButtons and thermal sensors. |
@@ -12,8 +10,10 @@ config W1 | |||
12 | This W1 support can also be built as a module. If so, the module | 10 | This W1 support can also be built as a module. If so, the module |
13 | will be called wire.ko. | 11 | will be called wire.ko. |
14 | 12 | ||
13 | if W1 | ||
14 | |||
15 | config W1_CON | 15 | config W1_CON |
16 | depends on CONNECTOR && W1 | 16 | depends on CONNECTOR |
17 | bool "Userspace communication over connector" | 17 | bool "Userspace communication over connector" |
18 | default y | 18 | default y |
19 | --- help --- | 19 | --- help --- |
@@ -27,4 +27,4 @@ config W1_CON | |||
27 | source drivers/w1/masters/Kconfig | 27 | source drivers/w1/masters/Kconfig |
28 | source drivers/w1/slaves/Kconfig | 28 | source drivers/w1/slaves/Kconfig |
29 | 29 | ||
30 | endmenu | 30 | endif # W1 |
diff --git a/drivers/w1/masters/Kconfig b/drivers/w1/masters/Kconfig index 8f779338f744..8236d447adf5 100644 --- a/drivers/w1/masters/Kconfig +++ b/drivers/w1/masters/Kconfig | |||
@@ -3,11 +3,10 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | menu "1-wire Bus Masters" | 5 | menu "1-wire Bus Masters" |
6 | depends on W1 | ||
7 | 6 | ||
8 | config W1_MASTER_MATROX | 7 | config W1_MASTER_MATROX |
9 | tristate "Matrox G400 transport layer for 1-wire" | 8 | tristate "Matrox G400 transport layer for 1-wire" |
10 | depends on W1 && PCI | 9 | depends on PCI |
11 | help | 10 | help |
12 | Say Y here if you want to communicate with your 1-wire devices | 11 | Say Y here if you want to communicate with your 1-wire devices |
13 | using Matrox's G400 GPIO pins. | 12 | using Matrox's G400 GPIO pins. |
@@ -17,7 +16,7 @@ config W1_MASTER_MATROX | |||
17 | 16 | ||
18 | config W1_MASTER_DS2490 | 17 | config W1_MASTER_DS2490 |
19 | tristate "DS2490 USB <-> W1 transport layer for 1-wire" | 18 | tristate "DS2490 USB <-> W1 transport layer for 1-wire" |
20 | depends on W1 && USB | 19 | depends on USB |
21 | help | 20 | help |
22 | Say Y here if you want to have a driver for DS2490 based USB <-> W1 bridges, | 21 | Say Y here if you want to have a driver for DS2490 based USB <-> W1 bridges, |
23 | for example DS9490*. | 22 | for example DS9490*. |
@@ -27,7 +26,7 @@ config W1_MASTER_DS2490 | |||
27 | 26 | ||
28 | config W1_MASTER_DS2482 | 27 | config W1_MASTER_DS2482 |
29 | tristate "Maxim DS2482 I2C to 1-Wire bridge" | 28 | tristate "Maxim DS2482 I2C to 1-Wire bridge" |
30 | depends on I2C && W1 && EXPERIMENTAL | 29 | depends on I2C && EXPERIMENTAL |
31 | help | 30 | help |
32 | If you say yes here you get support for the Maxim DS2482 | 31 | If you say yes here you get support for the Maxim DS2482 |
33 | I2C to 1-Wire bridge. | 32 | I2C to 1-Wire bridge. |
diff --git a/drivers/w1/slaves/Kconfig b/drivers/w1/slaves/Kconfig index df95d6c2cefa..3df29a122f84 100644 --- a/drivers/w1/slaves/Kconfig +++ b/drivers/w1/slaves/Kconfig | |||
@@ -3,25 +3,21 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | menu "1-wire Slaves" | 5 | menu "1-wire Slaves" |
6 | depends on W1 | ||
7 | 6 | ||
8 | config W1_SLAVE_THERM | 7 | config W1_SLAVE_THERM |
9 | tristate "Thermal family implementation" | 8 | tristate "Thermal family implementation" |
10 | depends on W1 | ||
11 | help | 9 | help |
12 | Say Y here if you want to connect 1-wire thermal sensors to your | 10 | Say Y here if you want to connect 1-wire thermal sensors to your |
13 | wire. | 11 | wire. |
14 | 12 | ||
15 | config W1_SLAVE_SMEM | 13 | config W1_SLAVE_SMEM |
16 | tristate "Simple 64bit memory family implementation" | 14 | tristate "Simple 64bit memory family implementation" |
17 | depends on W1 | ||
18 | help | 15 | help |
19 | Say Y here if you want to connect 1-wire | 16 | Say Y here if you want to connect 1-wire |
20 | simple 64bit memory rom(ds2401/ds2411/ds1990*) to your wire. | 17 | simple 64bit memory rom(ds2401/ds2411/ds1990*) to your wire. |
21 | 18 | ||
22 | config W1_SLAVE_DS2433 | 19 | config W1_SLAVE_DS2433 |
23 | tristate "4kb EEPROM family support (DS2433)" | 20 | tristate "4kb EEPROM family support (DS2433)" |
24 | depends on W1 | ||
25 | help | 21 | help |
26 | Say Y here if you want to use a 1-wire | 22 | Say Y here if you want to use a 1-wire |
27 | 4kb EEPROM family device (DS2433). | 23 | 4kb EEPROM family device (DS2433). |