Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging-2.6:
Staging/vt66*: kconfig, depends on WLAN
Staging: batman-adv: introduce missing kfree
Staging: batman-adv: Add Kconfig dependancies on PROC_FS and PACKET.
Staging: panel: Adjust range for PANEL_KEYPAD in Kconfig
Staging: panel: Fix compilation error with custom lcd charset
Staging: ramzswap: remove ARM specific d-cache hack
Staging: rtl8192x: fix printk formats
Staging: wlan-ng: fix Correct size given to memset
staging: rtl8192su: add USB VID/PID for HWNUm-300
staging: fix rtl8192su compilation errors with mac80211
staging: fix rtl8192e compilation errors with mac80211
Staging: fix rtl8187se compilation errors with mac80211
Staging: rtl8192su: fix test for negative error in rtl8192_rx_isr()
Staging: comedi: jr3_pci: Don't ioremap too much space. Check result.
Staging: comedi: removed "depricated" from COMEDI_CB_BLOCK
Staging: comedi: usbdux.c: fix locking up of the driver when the comedi ringbuffer runs empty
Staging: dst: remove from the tree
Staging: sm7xx: add a new framebuffer driver
Staging: batman: fix debug Kconfig option

+3696 -4672
+2 -2
drivers/staging/Kconfig
··· 87 87 88 88 source "drivers/staging/dream/Kconfig" 89 89 90 - source "drivers/staging/dst/Kconfig" 91 - 92 90 source "drivers/staging/pohmelfs/Kconfig" 93 91 94 92 source "drivers/staging/b3dfg/Kconfig" ··· 142 144 source "drivers/staging/wavelan/Kconfig" 143 145 144 146 source "drivers/staging/netwave/Kconfig" 147 + 148 + source "drivers/staging/sm7xx/Kconfig" 145 149 146 150 endif # !STAGING_EXCLUDE_BUILD 147 151 endif # STAGING
+1 -1
drivers/staging/Makefile
··· 26 26 obj-$(CONFIG_INPUT_MIMIO) += mimio/ 27 27 obj-$(CONFIG_TRANZPORT) += frontier/ 28 28 obj-$(CONFIG_DREAM) += dream/ 29 - obj-$(CONFIG_DST) += dst/ 30 29 obj-$(CONFIG_POHMELFS) += pohmelfs/ 31 30 obj-$(CONFIG_B3DFG) += b3dfg/ 32 31 obj-$(CONFIG_IDE_PHISON) += phison/ ··· 52 53 obj-$(CONFIG_WAVELAN) += wavelan/ 53 54 obj-$(CONFIG_PCMCIA_WAVELAN) += wavelan/ 54 55 obj-$(CONFIG_PCMCIA_NETWAVE) += netwave/ 56 + obj-$(CONFIG_FB_SM7XX) += sm7xx/
+1
drivers/staging/batman-adv/Kconfig
··· 4 4 5 5 config BATMAN_ADV 6 6 tristate "B.A.T.M.A.N. Advanced Meshing Protocol" 7 + depends on PROC_FS && PACKET 7 8 default n 8 9 ---help--- 9 10
+3 -1
drivers/staging/batman-adv/send.c
··· 363 363 return; 364 364 365 365 forw_packet->packet_buff = kmalloc(packet_len, GFP_ATOMIC); 366 - if (!forw_packet->packet_buff) 366 + if (!forw_packet->packet_buff) { 367 + kfree(forw_packet); 367 368 return; 369 + } 368 370 369 371 forw_packet->packet_len = packet_len; 370 372 memcpy(forw_packet->packet_buff, packet_buff, forw_packet->packet_len);
+1 -1
drivers/staging/comedi/comedi.h
··· 451 451 452 452 #define COMEDI_CB_EOS 1 /* end of scan */ 453 453 #define COMEDI_CB_EOA 2 /* end of acquisition */ 454 - #define COMEDI_CB_BLOCK 4 /* DEPRECATED: convenient block size */ 454 + #define COMEDI_CB_BLOCK 4 /* data has arrived: wakes up read() / write() */ 455 455 #define COMEDI_CB_EOBUF 8 /* DEPRECATED: end of buffer */ 456 456 #define COMEDI_CB_ERROR 16 /* card error during acquisition */ 457 457 #define COMEDI_CB_OVERFLOW 32 /* buffer overflow/underflow */
+5 -2
drivers/staging/comedi/drivers/jr3_pci.c
··· 849 849 } 850 850 851 851 devpriv->pci_enabled = 1; 852 - devpriv->iobase = 853 - ioremap(pci_resource_start(card, 0), sizeof(struct jr3_t)); 852 + devpriv->iobase = ioremap(pci_resource_start(card, 0), 853 + offsetof(struct jr3_t, channel[devpriv->n_channels])); 854 + if (!devpriv->iobase) 855 + return -ENOMEM; 856 + 854 857 result = alloc_subdevices(dev, devpriv->n_channels); 855 858 if (result < 0) 856 859 goto out;
+4 -1
drivers/staging/comedi/drivers/usbdux.c
··· 1 - #define DRIVER_VERSION "v2.3" 1 + #define DRIVER_VERSION "v2.4" 2 2 #define DRIVER_AUTHOR "Bernd Porr, BerndPorr@f2s.com" 3 3 #define DRIVER_DESC "Stirling/ITL USB-DUX -- Bernd.Porr@f2s.com" 4 4 /* ··· 81 81 * 2.1: changed PWM API 82 82 * 2.2: added firmware kernel request to fix an udev problem 83 83 * 2.3: corrected a bug in bulk timeouts which were far too short 84 + * 2.4: fixed a bug which causes the driver to hang when it ran out of data. 85 + * Thanks to Jan-Matthias Braun and Ian to spot the bug and fix it. 84 86 * 85 87 */ 86 88 ··· 534 532 } 535 533 } 536 534 /* tell comedi that data is there */ 535 + s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOS; 537 536 comedi_event(this_usbduxsub->comedidev, s); 538 537 } 539 538
-67
drivers/staging/dst/Kconfig
··· 1 - config DST 2 - tristate "Distributed storage" 3 - depends on NET && CRYPTO && SYSFS && BLK_DEV 4 - select CONNECTOR 5 - ---help--- 6 - DST is a network block device storage, which can be used to organize 7 - exported storage on the remote nodes into the local block device. 8 - 9 - DST works on top of any network media and protocol; it is just a matter 10 - of configuration utility to understand the correct addresses. The most 11 - common example is TCP over IP, which allows to pass through firewalls and 12 - create remote backup storage in a different datacenter. DST requires 13 - single port to be enabled on the exporting node and outgoing connections 14 - on the local node. 15 - 16 - DST works with in-kernel client and server, which improves performance by 17 - eliminating unneded data copies and by not depending on the version 18 - of the external IO components. It requires userspace configuration utility 19 - though. 20 - 21 - DST uses transaction model, when each store has to be explicitly acked 22 - from the remote node to be considered as successfully written. There 23 - may be lots of in-flight transactions. When remote host does not ack 24 - the transaction it will be resent predefined number of times with specified 25 - timeouts between them. All those parameters are configurable. Transactions 26 - are marked as failed after all resends complete unsuccessfully; having 27 - long enough resend timeout and/or large number of resends allows not to 28 - return error to the higher (FS usually) layer in case of short network 29 - problems or remote node outages. In case of network RAID setup this means 30 - that storage will not degrade until transactions are marked as failed, and 31 - thus will not force checksum recalculation and data rebuild. In case of 32 - connection failure DST will try to reconnect to the remote node automatically. 33 - DST sends ping commands at idle time to detect if remote node is alive. 34 - 35 - Because of transactional model it is possible to use zero-copy sending 36 - without worry of data corruption (which in turn could be detected by the 37 - strong checksums though). 38 - 39 - DST may fully encrypt the data channel in case of untrusted channel and implement 40 - strong checksum of the transferred data. It is possible to configure algorithms 41 - and crypto keys; they should match on both sides of the network channel. 42 - Crypto processing does not introduce noticeble performance overhead, since DST 43 - uses configurable pool of threads to perform crypto processing. 44 - 45 - DST utilizes memory pool model of all its transaction allocations (it is the 46 - only additional allocation on the client) and server allocations (bio pools, 47 - while pages are allocated from the slab). 48 - 49 - At startup DST performs a simple negotiation with the export node to determine 50 - access permissions and size of the exported storage. It can be extended if 51 - new parameters should be autonegotiated. 52 - 53 - DST carries block IO flags in the protocol, which allows to transparently implement 54 - barriers and sync/flush operations. Those flags are used in the export node where 55 - IO against the local storage is performed, which means that sync write will be sync 56 - on the remote node too, which in turn improves data integrity and improved resistance 57 - to errors and data corruption during power outages or storage damages. 58 - 59 - Homepage: http://www.ioremap.net/projects/dst 60 - Userspace configuration utility and the latest releases: http://www.ioremap.net/archive/dst/ 61 - 62 - config DST_DEBUG 63 - bool "DST debug" 64 - depends on DST 65 - ---help--- 66 - This option will enable HEAVY debugging of the DST. 67 - Turn it on ONLY if you have to debug some really obscure problem.
-3
drivers/staging/dst/Makefile
··· 1 - obj-$(CONFIG_DST) += nst.o 2 - 3 - nst-y := dcore.o state.o export.o thread_pool.o crypto.o trans.o
-733
drivers/staging/dst/crypto.c
··· 1 - /* 2 - * 2007+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net> 3 - * All rights reserved. 4 - * 5 - * This program is free software; you can redistribute it and/or modify 6 - * it under the terms of the GNU General Public License as published by 7 - * the Free Software Foundation; either version 2 of the License, or 8 - * (at your option) any later version. 9 - * 10 - * This program is distributed in the hope that it will be useful, 11 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 - * GNU General Public License for more details. 14 - */ 15 - 16 - #include <linux/bio.h> 17 - #include <linux/crypto.h> 18 - #include <linux/dst.h> 19 - #include <linux/kernel.h> 20 - #include <linux/scatterlist.h> 21 - #include <linux/slab.h> 22 - 23 - /* 24 - * Tricky bastard, but IV can be more complex with time... 25 - */ 26 - static inline u64 dst_gen_iv(struct dst_trans *t) 27 - { 28 - return t->gen; 29 - } 30 - 31 - /* 32 - * Crypto machinery: hash/cipher support for the given crypto controls. 33 - */ 34 - static struct crypto_hash *dst_init_hash(struct dst_crypto_ctl *ctl, u8 *key) 35 - { 36 - int err; 37 - struct crypto_hash *hash; 38 - 39 - hash = crypto_alloc_hash(ctl->hash_algo, 0, CRYPTO_ALG_ASYNC); 40 - if (IS_ERR(hash)) { 41 - err = PTR_ERR(hash); 42 - dprintk("%s: failed to allocate hash '%s', err: %d.\n", 43 - __func__, ctl->hash_algo, err); 44 - goto err_out_exit; 45 - } 46 - 47 - ctl->crypto_attached_size = crypto_hash_digestsize(hash); 48 - 49 - if (!ctl->hash_keysize) 50 - return hash; 51 - 52 - err = crypto_hash_setkey(hash, key, ctl->hash_keysize); 53 - if (err) { 54 - dprintk("%s: failed to set key for hash '%s', err: %d.\n", 55 - __func__, ctl->hash_algo, err); 56 - goto err_out_free; 57 - } 58 - 59 - return hash; 60 - 61 - err_out_free: 62 - crypto_free_hash(hash); 63 - err_out_exit: 64 - return ERR_PTR(err); 65 - } 66 - 67 - static struct crypto_ablkcipher *dst_init_cipher(struct dst_crypto_ctl *ctl, 68 - u8 *key) 69 - { 70 - int err = -EINVAL; 71 - struct crypto_ablkcipher *cipher; 72 - 73 - if (!ctl->cipher_keysize) 74 - goto err_out_exit; 75 - 76 - cipher = crypto_alloc_ablkcipher(ctl->cipher_algo, 0, 0); 77 - if (IS_ERR(cipher)) { 78 - err = PTR_ERR(cipher); 79 - dprintk("%s: failed to allocate cipher '%s', err: %d.\n", 80 - __func__, ctl->cipher_algo, err); 81 - goto err_out_exit; 82 - } 83 - 84 - crypto_ablkcipher_clear_flags(cipher, ~0); 85 - 86 - err = crypto_ablkcipher_setkey(cipher, key, ctl->cipher_keysize); 87 - if (err) { 88 - dprintk("%s: failed to set key for cipher '%s', err: %d.\n", 89 - __func__, ctl->cipher_algo, err); 90 - goto err_out_free; 91 - } 92 - 93 - return cipher; 94 - 95 - err_out_free: 96 - crypto_free_ablkcipher(cipher); 97 - err_out_exit: 98 - return ERR_PTR(err); 99 - } 100 - 101 - /* 102 - * Crypto engine has a pool of pages to encrypt data into before sending 103 - * it over the network. This pool is freed/allocated here. 104 - */ 105 - static void dst_crypto_pages_free(struct dst_crypto_engine *e) 106 - { 107 - unsigned int i; 108 - 109 - for (i = 0; i < e->page_num; ++i) 110 - __free_page(e->pages[i]); 111 - kfree(e->pages); 112 - } 113 - 114 - static int dst_crypto_pages_alloc(struct dst_crypto_engine *e, int num) 115 - { 116 - int i; 117 - 118 - e->pages = kmalloc(num * sizeof(struct page **), GFP_KERNEL); 119 - if (!e->pages) 120 - return -ENOMEM; 121 - 122 - for (i = 0; i < num; ++i) { 123 - e->pages[i] = alloc_page(GFP_KERNEL); 124 - if (!e->pages[i]) 125 - goto err_out_free_pages; 126 - } 127 - 128 - e->page_num = num; 129 - return 0; 130 - 131 - err_out_free_pages: 132 - while (--i >= 0) 133 - __free_page(e->pages[i]); 134 - 135 - kfree(e->pages); 136 - return -ENOMEM; 137 - } 138 - 139 - /* 140 - * Initialize crypto engine for given node. 141 - * Setup cipher/hash, keys, pool of threads and private data. 142 - */ 143 - static int dst_crypto_engine_init(struct dst_crypto_engine *e, 144 - struct dst_node *n) 145 - { 146 - int err; 147 - struct dst_crypto_ctl *ctl = &n->crypto; 148 - 149 - err = dst_crypto_pages_alloc(e, n->max_pages); 150 - if (err) 151 - goto err_out_exit; 152 - 153 - e->size = PAGE_SIZE; 154 - e->data = kmalloc(e->size, GFP_KERNEL); 155 - if (!e->data) { 156 - err = -ENOMEM; 157 - goto err_out_free_pages; 158 - } 159 - 160 - if (ctl->hash_algo[0]) { 161 - e->hash = dst_init_hash(ctl, n->hash_key); 162 - if (IS_ERR(e->hash)) { 163 - err = PTR_ERR(e->hash); 164 - e->hash = NULL; 165 - goto err_out_free; 166 - } 167 - } 168 - 169 - if (ctl->cipher_algo[0]) { 170 - e->cipher = dst_init_cipher(ctl, n->cipher_key); 171 - if (IS_ERR(e->cipher)) { 172 - err = PTR_ERR(e->cipher); 173 - e->cipher = NULL; 174 - goto err_out_free_hash; 175 - } 176 - } 177 - 178 - return 0; 179 - 180 - err_out_free_hash: 181 - crypto_free_hash(e->hash); 182 - err_out_free: 183 - kfree(e->data); 184 - err_out_free_pages: 185 - dst_crypto_pages_free(e); 186 - err_out_exit: 187 - return err; 188 - } 189 - 190 - static void dst_crypto_engine_exit(struct dst_crypto_engine *e) 191 - { 192 - if (e->hash) 193 - crypto_free_hash(e->hash); 194 - if (e->cipher) 195 - crypto_free_ablkcipher(e->cipher); 196 - dst_crypto_pages_free(e); 197 - kfree(e->data); 198 - } 199 - 200 - /* 201 - * Waiting for cipher processing to be completed. 202 - */ 203 - struct dst_crypto_completion { 204 - struct completion complete; 205 - int error; 206 - }; 207 - 208 - static void dst_crypto_complete(struct crypto_async_request *req, int err) 209 - { 210 - struct dst_crypto_completion *c = req->data; 211 - 212 - if (err == -EINPROGRESS) 213 - return; 214 - 215 - dprintk("%s: req: %p, err: %d.\n", __func__, req, err); 216 - c->error = err; 217 - complete(&c->complete); 218 - } 219 - 220 - static int dst_crypto_process(struct ablkcipher_request *req, 221 - struct scatterlist *sg_dst, struct scatterlist *sg_src, 222 - void *iv, int enc, unsigned long timeout) 223 - { 224 - struct dst_crypto_completion c; 225 - int err; 226 - 227 - init_completion(&c.complete); 228 - c.error = -EINPROGRESS; 229 - 230 - ablkcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, 231 - dst_crypto_complete, &c); 232 - 233 - ablkcipher_request_set_crypt(req, sg_src, sg_dst, sg_src->length, iv); 234 - 235 - if (enc) 236 - err = crypto_ablkcipher_encrypt(req); 237 - else 238 - err = crypto_ablkcipher_decrypt(req); 239 - 240 - switch (err) { 241 - case -EINPROGRESS: 242 - case -EBUSY: 243 - err = wait_for_completion_interruptible_timeout(&c.complete, 244 - timeout); 245 - if (!err) 246 - err = -ETIMEDOUT; 247 - else 248 - err = c.error; 249 - break; 250 - default: 251 - break; 252 - } 253 - 254 - return err; 255 - } 256 - 257 - /* 258 - * DST uses generic iteration approach for data crypto processing. 259 - * Single block IO request is switched into array of scatterlists, 260 - * which are submitted to the crypto processing iterator. 261 - * 262 - * Input and output iterator initialization are different, since 263 - * in output case we can not encrypt data in-place and need a 264 - * temporary storage, which is then being sent to the remote peer. 265 - */ 266 - static int dst_trans_iter_out(struct bio *bio, struct dst_crypto_engine *e, 267 - int (*iterator) (struct dst_crypto_engine *e, 268 - struct scatterlist *dst, 269 - struct scatterlist *src)) 270 - { 271 - struct bio_vec *bv; 272 - int err, i; 273 - 274 - sg_init_table(e->src, bio->bi_vcnt); 275 - sg_init_table(e->dst, bio->bi_vcnt); 276 - 277 - bio_for_each_segment(bv, bio, i) { 278 - sg_set_page(&e->src[i], bv->bv_page, bv->bv_len, bv->bv_offset); 279 - sg_set_page(&e->dst[i], e->pages[i], bv->bv_len, bv->bv_offset); 280 - 281 - err = iterator(e, &e->dst[i], &e->src[i]); 282 - if (err) 283 - return err; 284 - } 285 - 286 - return 0; 287 - } 288 - 289 - static int dst_trans_iter_in(struct bio *bio, struct dst_crypto_engine *e, 290 - int (*iterator) (struct dst_crypto_engine *e, 291 - struct scatterlist *dst, 292 - struct scatterlist *src)) 293 - { 294 - struct bio_vec *bv; 295 - int err, i; 296 - 297 - sg_init_table(e->src, bio->bi_vcnt); 298 - sg_init_table(e->dst, bio->bi_vcnt); 299 - 300 - bio_for_each_segment(bv, bio, i) { 301 - sg_set_page(&e->src[i], bv->bv_page, bv->bv_len, bv->bv_offset); 302 - sg_set_page(&e->dst[i], bv->bv_page, bv->bv_len, bv->bv_offset); 303 - 304 - err = iterator(e, &e->dst[i], &e->src[i]); 305 - if (err) 306 - return err; 307 - } 308 - 309 - return 0; 310 - } 311 - 312 - static int dst_crypt_iterator(struct dst_crypto_engine *e, 313 - struct scatterlist *sg_dst, struct scatterlist *sg_src) 314 - { 315 - struct ablkcipher_request *req = e->data; 316 - u8 iv[32]; 317 - 318 - memset(iv, 0, sizeof(iv)); 319 - 320 - memcpy(iv, &e->iv, sizeof(e->iv)); 321 - 322 - return dst_crypto_process(req, sg_dst, sg_src, iv, e->enc, e->timeout); 323 - } 324 - 325 - static int dst_crypt(struct dst_crypto_engine *e, struct bio *bio) 326 - { 327 - struct ablkcipher_request *req = e->data; 328 - 329 - memset(req, 0, sizeof(struct ablkcipher_request)); 330 - ablkcipher_request_set_tfm(req, e->cipher); 331 - 332 - if (e->enc) 333 - return dst_trans_iter_out(bio, e, dst_crypt_iterator); 334 - else 335 - return dst_trans_iter_in(bio, e, dst_crypt_iterator); 336 - } 337 - 338 - static int dst_hash_iterator(struct dst_crypto_engine *e, 339 - struct scatterlist *sg_dst, struct scatterlist *sg_src) 340 - { 341 - return crypto_hash_update(e->data, sg_src, sg_src->length); 342 - } 343 - 344 - static int dst_hash(struct dst_crypto_engine *e, struct bio *bio, void *dst) 345 - { 346 - struct hash_desc *desc = e->data; 347 - int err; 348 - 349 - desc->tfm = e->hash; 350 - desc->flags = 0; 351 - 352 - err = crypto_hash_init(desc); 353 - if (err) 354 - return err; 355 - 356 - err = dst_trans_iter_in(bio, e, dst_hash_iterator); 357 - if (err) 358 - return err; 359 - 360 - err = crypto_hash_final(desc, dst); 361 - if (err) 362 - return err; 363 - 364 - return 0; 365 - } 366 - 367 - /* 368 - * Initialize/cleanup a crypto thread. The only thing it should 369 - * do is to allocate a pool of pages as temporary storage. 370 - * And to setup cipher and/or hash. 371 - */ 372 - static void *dst_crypto_thread_init(void *data) 373 - { 374 - struct dst_node *n = data; 375 - struct dst_crypto_engine *e; 376 - int err = -ENOMEM; 377 - 378 - e = kzalloc(sizeof(struct dst_crypto_engine), GFP_KERNEL); 379 - if (!e) 380 - goto err_out_exit; 381 - e->src = kcalloc(2 * n->max_pages, sizeof(struct scatterlist), 382 - GFP_KERNEL); 383 - if (!e->src) 384 - goto err_out_free; 385 - 386 - e->dst = e->src + n->max_pages; 387 - 388 - err = dst_crypto_engine_init(e, n); 389 - if (err) 390 - goto err_out_free_all; 391 - 392 - return e; 393 - 394 - err_out_free_all: 395 - kfree(e->src); 396 - err_out_free: 397 - kfree(e); 398 - err_out_exit: 399 - return ERR_PTR(err); 400 - } 401 - 402 - static void dst_crypto_thread_cleanup(void *private) 403 - { 404 - struct dst_crypto_engine *e = private; 405 - 406 - dst_crypto_engine_exit(e); 407 - kfree(e->src); 408 - kfree(e); 409 - } 410 - 411 - /* 412 - * Initialize crypto engine for given node: store keys, create pool 413 - * of threads, initialize each one. 414 - * 415 - * Each thread has unique ID, but 0 and 1 are reserved for receiving and 416 - * accepting threads (if export node), so IDs could start from 2, but starting 417 - * them from 10 allows easily understand what this thread is for. 418 - */ 419 - int dst_node_crypto_init(struct dst_node *n, struct dst_crypto_ctl *ctl) 420 - { 421 - void *key = (ctl + 1); 422 - int err = -ENOMEM, i; 423 - char name[32]; 424 - 425 - if (ctl->hash_keysize) { 426 - n->hash_key = kmalloc(ctl->hash_keysize, GFP_KERNEL); 427 - if (!n->hash_key) 428 - goto err_out_exit; 429 - memcpy(n->hash_key, key, ctl->hash_keysize); 430 - } 431 - 432 - if (ctl->cipher_keysize) { 433 - n->cipher_key = kmalloc(ctl->cipher_keysize, GFP_KERNEL); 434 - if (!n->cipher_key) 435 - goto err_out_free_hash; 436 - memcpy(n->cipher_key, key, ctl->cipher_keysize); 437 - } 438 - memcpy(&n->crypto, ctl, sizeof(struct dst_crypto_ctl)); 439 - 440 - for (i = 0; i < ctl->thread_num; ++i) { 441 - snprintf(name, sizeof(name), "%s-crypto-%d", n->name, i); 442 - /* Unique ids... */ 443 - err = thread_pool_add_worker(n->pool, name, i + 10, 444 - dst_crypto_thread_init, dst_crypto_thread_cleanup, n); 445 - if (err) 446 - goto err_out_free_threads; 447 - } 448 - 449 - return 0; 450 - 451 - err_out_free_threads: 452 - while (--i >= 0) 453 - thread_pool_del_worker_id(n->pool, i+10); 454 - 455 - if (ctl->cipher_keysize) 456 - kfree(n->cipher_key); 457 - ctl->cipher_keysize = 0; 458 - err_out_free_hash: 459 - if (ctl->hash_keysize) 460 - kfree(n->hash_key); 461 - ctl->hash_keysize = 0; 462 - err_out_exit: 463 - return err; 464 - } 465 - 466 - void dst_node_crypto_exit(struct dst_node *n) 467 - { 468 - struct dst_crypto_ctl *ctl = &n->crypto; 469 - 470 - if (ctl->cipher_algo[0] || ctl->hash_algo[0]) { 471 - kfree(n->hash_key); 472 - kfree(n->cipher_key); 473 - } 474 - } 475 - 476 - /* 477 - * Thrad pool setup callback. Just stores a transaction in private data. 478 - */ 479 - static int dst_trans_crypto_setup(void *crypto_engine, void *trans) 480 - { 481 - struct dst_crypto_engine *e = crypto_engine; 482 - 483 - e->private = trans; 484 - return 0; 485 - } 486 - 487 - #if 0 488 - static void dst_dump_bio(struct bio *bio) 489 - { 490 - u8 *p; 491 - struct bio_vec *bv; 492 - int i; 493 - 494 - bio_for_each_segment(bv, bio, i) { 495 - dprintk("%s: %llu/%u: size: %u, offset: %u, data: ", 496 - __func__, bio->bi_sector, bio->bi_size, 497 - bv->bv_len, bv->bv_offset); 498 - 499 - p = kmap(bv->bv_page) + bv->bv_offset; 500 - for (i = 0; i < bv->bv_len; ++i) 501 - printk(KERN_DEBUG "%02x ", p[i]); 502 - kunmap(bv->bv_page); 503 - printk("\n"); 504 - } 505 - } 506 - #endif 507 - 508 - /* 509 - * Encrypt/hash data and send it to the network. 510 - */ 511 - static int dst_crypto_process_sending(struct dst_crypto_engine *e, 512 - struct bio *bio, u8 *hash) 513 - { 514 - int err; 515 - 516 - if (e->cipher) { 517 - err = dst_crypt(e, bio); 518 - if (err) 519 - goto err_out_exit; 520 - } 521 - 522 - if (e->hash) { 523 - err = dst_hash(e, bio, hash); 524 - if (err) 525 - goto err_out_exit; 526 - 527 - #ifdef CONFIG_DST_DEBUG 528 - { 529 - unsigned int i; 530 - 531 - /* dst_dump_bio(bio); */ 532 - 533 - printk(KERN_DEBUG "%s: bio: %llu/%u, rw: %lu, hash: ", 534 - __func__, (u64)bio->bi_sector, 535 - bio->bi_size, bio_data_dir(bio)); 536 - for (i = 0; i < crypto_hash_digestsize(e->hash); ++i) 537 - printk("%02x ", hash[i]); 538 - printk("\n"); 539 - } 540 - #endif 541 - } 542 - 543 - return 0; 544 - 545 - err_out_exit: 546 - return err; 547 - } 548 - 549 - /* 550 - * Check if received data is valid. Decipher if it is. 551 - */ 552 - static int dst_crypto_process_receiving(struct dst_crypto_engine *e, 553 - struct bio *bio, u8 *hash, u8 *recv_hash) 554 - { 555 - int err; 556 - 557 - if (e->hash) { 558 - int mismatch; 559 - 560 - err = dst_hash(e, bio, hash); 561 - if (err) 562 - goto err_out_exit; 563 - 564 - mismatch = !!memcmp(recv_hash, hash, 565 - crypto_hash_digestsize(e->hash)); 566 - #ifdef CONFIG_DST_DEBUG 567 - /* dst_dump_bio(bio); */ 568 - 569 - printk(KERN_DEBUG "%s: bio: %llu/%u, rw: %lu, hash mismatch: %d", 570 - __func__, (u64)bio->bi_sector, bio->bi_size, 571 - bio_data_dir(bio), mismatch); 572 - if (mismatch) { 573 - unsigned int i; 574 - 575 - printk(", recv/calc: "); 576 - for (i = 0; i < crypto_hash_digestsize(e->hash); ++i) 577 - printk("%02x/%02x ", recv_hash[i], hash[i]); 578 - 579 - } 580 - printk("\n"); 581 - #endif 582 - err = -1; 583 - if (mismatch) 584 - goto err_out_exit; 585 - } 586 - 587 - if (e->cipher) { 588 - err = dst_crypt(e, bio); 589 - if (err) 590 - goto err_out_exit; 591 - } 592 - 593 - return 0; 594 - 595 - err_out_exit: 596 - return err; 597 - } 598 - 599 - /* 600 - * Thread pool callback to encrypt data and send it to the netowork. 601 - */ 602 - static int dst_trans_crypto_action(void *crypto_engine, void *schedule_data) 603 - { 604 - struct dst_crypto_engine *e = crypto_engine; 605 - struct dst_trans *t = schedule_data; 606 - struct bio *bio = t->bio; 607 - int err; 608 - 609 - dprintk("%s: t: %p, gen: %llu, cipher: %p, hash: %p.\n", 610 - __func__, t, t->gen, e->cipher, e->hash); 611 - 612 - e->enc = t->enc; 613 - e->iv = dst_gen_iv(t); 614 - 615 - if (bio_data_dir(bio) == WRITE) { 616 - err = dst_crypto_process_sending(e, bio, t->cmd.hash); 617 - if (err) 618 - goto err_out_exit; 619 - 620 - if (e->hash) { 621 - t->cmd.csize = crypto_hash_digestsize(e->hash); 622 - t->cmd.size += t->cmd.csize; 623 - } 624 - 625 - return dst_trans_send(t); 626 - } else { 627 - u8 *hash = e->data + e->size/2; 628 - 629 - err = dst_crypto_process_receiving(e, bio, hash, t->cmd.hash); 630 - if (err) 631 - goto err_out_exit; 632 - 633 - dst_trans_remove(t); 634 - dst_trans_put(t); 635 - } 636 - 637 - return 0; 638 - 639 - err_out_exit: 640 - t->error = err; 641 - dst_trans_put(t); 642 - return err; 643 - } 644 - 645 - /* 646 - * Schedule crypto processing for given transaction. 647 - */ 648 - int dst_trans_crypto(struct dst_trans *t) 649 - { 650 - struct dst_node *n = t->n; 651 - int err; 652 - 653 - err = thread_pool_schedule(n->pool, 654 - dst_trans_crypto_setup, dst_trans_crypto_action, 655 - t, MAX_SCHEDULE_TIMEOUT); 656 - if (err) 657 - goto err_out_exit; 658 - 659 - return 0; 660 - 661 - err_out_exit: 662 - dst_trans_put(t); 663 - return err; 664 - } 665 - 666 - /* 667 - * Crypto machinery for the export node. 668 - */ 669 - static int dst_export_crypto_setup(void *crypto_engine, void *bio) 670 - { 671 - struct dst_crypto_engine *e = crypto_engine; 672 - 673 - e->private = bio; 674 - return 0; 675 - } 676 - 677 - static int dst_export_crypto_action(void *crypto_engine, void *schedule_data) 678 - { 679 - struct dst_crypto_engine *e = crypto_engine; 680 - struct bio *bio = schedule_data; 681 - struct dst_export_priv *p = bio->bi_private; 682 - int err; 683 - 684 - dprintk("%s: e: %p, data: %p, bio: %llu/%u, dir: %lu.\n", 685 - __func__, e, e->data, (u64)bio->bi_sector, 686 - bio->bi_size, bio_data_dir(bio)); 687 - 688 - e->enc = (bio_data_dir(bio) == READ); 689 - e->iv = p->cmd.id; 690 - 691 - if (bio_data_dir(bio) == WRITE) { 692 - u8 *hash = e->data + e->size/2; 693 - 694 - err = dst_crypto_process_receiving(e, bio, hash, p->cmd.hash); 695 - if (err) 696 - goto err_out_exit; 697 - 698 - generic_make_request(bio); 699 - } else { 700 - err = dst_crypto_process_sending(e, bio, p->cmd.hash); 701 - if (err) 702 - goto err_out_exit; 703 - 704 - if (e->hash) { 705 - p->cmd.csize = crypto_hash_digestsize(e->hash); 706 - p->cmd.size += p->cmd.csize; 707 - } 708 - 709 - err = dst_export_send_bio(bio); 710 - } 711 - return 0; 712 - 713 - err_out_exit: 714 - bio_put(bio); 715 - return err; 716 - } 717 - 718 - int dst_export_crypto(struct dst_node *n, struct bio *bio) 719 - { 720 - int err; 721 - 722 - err = thread_pool_schedule(n->pool, 723 - dst_export_crypto_setup, dst_export_crypto_action, 724 - bio, MAX_SCHEDULE_TIMEOUT); 725 - if (err) 726 - goto err_out_exit; 727 - 728 - return 0; 729 - 730 - err_out_exit: 731 - bio_put(bio); 732 - return err; 733 - }
-968
drivers/staging/dst/dcore.c
··· 1 - /* 2 - * 2007+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net> 3 - * All rights reserved. 4 - * 5 - * This program is free software; you can redistribute it and/or modify 6 - * it under the terms of the GNU General Public License as published by 7 - * the Free Software Foundation; either version 2 of the License, or 8 - * (at your option) any later version. 9 - * 10 - * This program is distributed in the hope that it will be useful, 11 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 - * GNU General Public License for more details. 14 - */ 15 - 16 - #include <linux/module.h> 17 - #include <linux/kernel.h> 18 - #include <linux/blkdev.h> 19 - #include <linux/bio.h> 20 - #include <linux/buffer_head.h> 21 - #include <linux/connector.h> 22 - #include <linux/dst.h> 23 - #include <linux/device.h> 24 - #include <linux/jhash.h> 25 - #include <linux/idr.h> 26 - #include <linux/init.h> 27 - #include <linux/namei.h> 28 - #include <linux/slab.h> 29 - #include <linux/socket.h> 30 - 31 - #include <linux/in.h> 32 - #include <linux/in6.h> 33 - 34 - #include <net/sock.h> 35 - 36 - static int dst_major; 37 - 38 - static DEFINE_MUTEX(dst_hash_lock); 39 - static struct list_head *dst_hashtable; 40 - static unsigned int dst_hashtable_size = 128; 41 - module_param(dst_hashtable_size, uint, 0644); 42 - 43 - static char dst_name[] = "Dementianting goldfish"; 44 - 45 - static DEFINE_IDR(dst_index_idr); 46 - static struct cb_id cn_dst_id = { CN_DST_IDX, CN_DST_VAL }; 47 - 48 - /* 49 - * DST sysfs tree for device called 'storage': 50 - * 51 - * /sys/bus/dst/devices/storage/ 52 - * /sys/bus/dst/devices/storage/type : 192.168.4.80:1025 53 - * /sys/bus/dst/devices/storage/size : 800 54 - * /sys/bus/dst/devices/storage/name : storage 55 - */ 56 - 57 - static int dst_dev_match(struct device *dev, struct device_driver *drv) 58 - { 59 - return 1; 60 - } 61 - 62 - static struct bus_type dst_dev_bus_type = { 63 - .name = "dst", 64 - .match = &dst_dev_match, 65 - }; 66 - 67 - static void dst_node_release(struct device *dev) 68 - { 69 - struct dst_info *info = container_of(dev, struct dst_info, device); 70 - 71 - kfree(info); 72 - } 73 - 74 - static struct device dst_node_dev = { 75 - .bus = &dst_dev_bus_type, 76 - .release = &dst_node_release 77 - }; 78 - 79 - /* 80 - * Setting size of the node after it was changed. 81 - */ 82 - static void dst_node_set_size(struct dst_node *n) 83 - { 84 - struct block_device *bdev; 85 - 86 - set_capacity(n->disk, n->size >> 9); 87 - 88 - bdev = bdget_disk(n->disk, 0); 89 - if (bdev) { 90 - mutex_lock(&bdev->bd_inode->i_mutex); 91 - i_size_write(bdev->bd_inode, n->size); 92 - mutex_unlock(&bdev->bd_inode->i_mutex); 93 - bdput(bdev); 94 - } 95 - } 96 - 97 - /* 98 - * Distributed storage request processing function. 99 - */ 100 - static int dst_request(struct request_queue *q, struct bio *bio) 101 - { 102 - struct dst_node *n = q->queuedata; 103 - int err = -EIO; 104 - 105 - if (bio_empty_barrier(bio) && !blk_queue_discard(q)) { 106 - /* 107 - * This is a dirty^Wnice hack, but if we complete this 108 - * operation with -EOPNOTSUPP like intended, XFS 109 - * will stuck and freeze the machine. This may be 110 - * not particulary XFS problem though, but it is the 111 - * only FS which sends empty barrier at umount time 112 - * I worked with. 113 - * 114 - * Empty barriers are not allowed anyway, see 51fd77bd9f512 115 - * for example, although later it was changed to 116 - * bio_rw_flagged(bio, BIO_RW_DISCARD) only, which does not 117 - * work in this case. 118 - */ 119 - /* err = -EOPNOTSUPP; */ 120 - err = 0; 121 - goto end_io; 122 - } 123 - 124 - bio_get(bio); 125 - 126 - return dst_process_bio(n, bio); 127 - 128 - end_io: 129 - bio_endio(bio, err); 130 - return err; 131 - } 132 - 133 - /* 134 - * Open/close callbacks for appropriate block device. 135 - */ 136 - static int dst_bdev_open(struct block_device *bdev, fmode_t mode) 137 - { 138 - struct dst_node *n = bdev->bd_disk->private_data; 139 - 140 - dst_node_get(n); 141 - return 0; 142 - } 143 - 144 - static int dst_bdev_release(struct gendisk *disk, fmode_t mode) 145 - { 146 - struct dst_node *n = disk->private_data; 147 - 148 - dst_node_put(n); 149 - return 0; 150 - } 151 - 152 - static struct block_device_operations dst_blk_ops = { 153 - .open = dst_bdev_open, 154 - .release = dst_bdev_release, 155 - .owner = THIS_MODULE, 156 - }; 157 - 158 - /* 159 - * Block layer binding - disk is created when array is fully configured 160 - * by userspace request. 161 - */ 162 - static int dst_node_create_disk(struct dst_node *n) 163 - { 164 - int err = -ENOMEM; 165 - u32 index = 0; 166 - 167 - n->queue = blk_init_queue(NULL, NULL); 168 - if (!n->queue) 169 - goto err_out_exit; 170 - 171 - n->queue->queuedata = n; 172 - blk_queue_make_request(n->queue, dst_request); 173 - blk_queue_max_phys_segments(n->queue, n->max_pages); 174 - blk_queue_max_hw_segments(n->queue, n->max_pages); 175 - 176 - err = -ENOMEM; 177 - n->disk = alloc_disk(1); 178 - if (!n->disk) 179 - goto err_out_free_queue; 180 - 181 - if (!(n->state->permissions & DST_PERM_WRITE)) { 182 - printk(KERN_INFO "DST node %s attached read-only.\n", n->name); 183 - set_disk_ro(n->disk, 1); 184 - } 185 - 186 - if (!idr_pre_get(&dst_index_idr, GFP_KERNEL)) 187 - goto err_out_put; 188 - 189 - mutex_lock(&dst_hash_lock); 190 - err = idr_get_new(&dst_index_idr, NULL, &index); 191 - mutex_unlock(&dst_hash_lock); 192 - if (err) 193 - goto err_out_put; 194 - 195 - n->disk->major = dst_major; 196 - n->disk->first_minor = index; 197 - n->disk->fops = &dst_blk_ops; 198 - n->disk->queue = n->queue; 199 - n->disk->private_data = n; 200 - snprintf(n->disk->disk_name, sizeof(n->disk->disk_name), 201 - "dst-%s", n->name); 202 - 203 - return 0; 204 - 205 - err_out_put: 206 - put_disk(n->disk); 207 - err_out_free_queue: 208 - blk_cleanup_queue(n->queue); 209 - err_out_exit: 210 - return err; 211 - } 212 - 213 - /* 214 - * Sysfs machinery: show device's size. 215 - */ 216 - static ssize_t dst_show_size(struct device *dev, 217 - struct device_attribute *attr, char *buf) 218 - { 219 - struct dst_info *info = container_of(dev, struct dst_info, device); 220 - 221 - return sprintf(buf, "%llu\n", info->size); 222 - } 223 - 224 - /* 225 - * Show local exported device. 226 - */ 227 - static ssize_t dst_show_local(struct device *dev, 228 - struct device_attribute *attr, char *buf) 229 - { 230 - struct dst_info *info = container_of(dev, struct dst_info, device); 231 - 232 - return sprintf(buf, "%s\n", info->local); 233 - } 234 - 235 - /* 236 - * Shows type of the remote node - device major/minor number 237 - * for local nodes and address (af_inet ipv4/ipv6 only) for remote nodes. 238 - */ 239 - static ssize_t dst_show_type(struct device *dev, 240 - struct device_attribute *attr, char *buf) 241 - { 242 - struct dst_info *info = container_of(dev, struct dst_info, device); 243 - int family = info->net.addr.sa_family; 244 - 245 - if (family == AF_INET) { 246 - struct sockaddr_in *sin = (struct sockaddr_in *)&info->net.addr; 247 - return sprintf(buf, "%u.%u.%u.%u:%d\n", 248 - NIPQUAD(sin->sin_addr.s_addr), ntohs(sin->sin_port)); 249 - } else if (family == AF_INET6) { 250 - struct sockaddr_in6 *sin = (struct sockaddr_in6 *) 251 - &info->net.addr; 252 - return sprintf(buf, 253 - "%pi6:%d\n", 254 - &sin->sin6_addr, ntohs(sin->sin6_port)); 255 - } else { 256 - int i, sz = PAGE_SIZE - 2; /* 0 symbol and '\n' below */ 257 - int size, addrlen = info->net.addr.sa_data_len; 258 - unsigned char *a = (unsigned char *)&info->net.addr.sa_data; 259 - char *buf_orig = buf; 260 - 261 - size = snprintf(buf, sz, "family: %d, addrlen: %u, addr: ", 262 - family, addrlen); 263 - sz -= size; 264 - buf += size; 265 - 266 - for (i = 0; i < addrlen; ++i) { 267 - if (sz < 3) 268 - break; 269 - 270 - size = snprintf(buf, sz, "%02x ", a[i]); 271 - sz -= size; 272 - buf += size; 273 - } 274 - buf += sprintf(buf, "\n"); 275 - 276 - return buf - buf_orig; 277 - } 278 - return 0; 279 - } 280 - 281 - static struct device_attribute dst_node_attrs[] = { 282 - __ATTR(size, 0444, dst_show_size, NULL), 283 - __ATTR(type, 0444, dst_show_type, NULL), 284 - __ATTR(local, 0444, dst_show_local, NULL), 285 - }; 286 - 287 - static int dst_create_node_attributes(struct dst_node *n) 288 - { 289 - int err, i; 290 - 291 - for (i = 0; i < ARRAY_SIZE(dst_node_attrs); ++i) { 292 - err = device_create_file(&n->info->device, 293 - &dst_node_attrs[i]); 294 - if (err) 295 - goto err_out_remove_all; 296 - } 297 - return 0; 298 - 299 - err_out_remove_all: 300 - while (--i >= 0) 301 - device_remove_file(&n->info->device, 302 - &dst_node_attrs[i]); 303 - 304 - return err; 305 - } 306 - 307 - static void dst_remove_node_attributes(struct dst_node *n) 308 - { 309 - int i; 310 - 311 - for (i = 0; i < ARRAY_SIZE(dst_node_attrs); ++i) 312 - device_remove_file(&n->info->device, 313 - &dst_node_attrs[i]); 314 - } 315 - 316 - /* 317 - * Sysfs cleanup and initialization. 318 - * Shows number of useful parameters. 319 - */ 320 - static void dst_node_sysfs_exit(struct dst_node *n) 321 - { 322 - if (n->info) { 323 - dst_remove_node_attributes(n); 324 - device_unregister(&n->info->device); 325 - n->info = NULL; 326 - } 327 - } 328 - 329 - static int dst_node_sysfs_init(struct dst_node *n) 330 - { 331 - int err; 332 - 333 - n->info = kzalloc(sizeof(struct dst_info), GFP_KERNEL); 334 - if (!n->info) 335 - return -ENOMEM; 336 - 337 - memcpy(&n->info->device, &dst_node_dev, sizeof(struct device)); 338 - n->info->size = n->size; 339 - 340 - dev_set_name(&n->info->device, "dst-%s", n->name); 341 - err = device_register(&n->info->device); 342 - if (err) { 343 - dprintk(KERN_ERR "Failed to register node '%s', err: %d.\n", 344 - n->name, err); 345 - goto err_out_exit; 346 - } 347 - 348 - dst_create_node_attributes(n); 349 - 350 - return 0; 351 - 352 - err_out_exit: 353 - kfree(n->info); 354 - n->info = NULL; 355 - return err; 356 - } 357 - 358 - /* 359 - * DST node hash tables machinery. 360 - */ 361 - static inline unsigned int dst_hash(char *str, unsigned int size) 362 - { 363 - return jhash(str, size, 0) % dst_hashtable_size; 364 - } 365 - 366 - static void dst_node_remove(struct dst_node *n) 367 - { 368 - mutex_lock(&dst_hash_lock); 369 - list_del_init(&n->node_entry); 370 - mutex_unlock(&dst_hash_lock); 371 - } 372 - 373 - static void dst_node_add(struct dst_node *n) 374 - { 375 - unsigned hash = dst_hash(n->name, sizeof(n->name)); 376 - 377 - mutex_lock(&dst_hash_lock); 378 - list_add_tail(&n->node_entry, &dst_hashtable[hash]); 379 - mutex_unlock(&dst_hash_lock); 380 - } 381 - 382 - /* 383 - * Cleaning node when it is about to be freed. 384 - * There are still users of the socket though, 385 - * so connection cleanup should be protected. 386 - */ 387 - static void dst_node_cleanup(struct dst_node *n) 388 - { 389 - struct dst_state *st = n->state; 390 - 391 - if (!st) 392 - return; 393 - 394 - if (n->queue) { 395 - blk_cleanup_queue(n->queue); 396 - 397 - mutex_lock(&dst_hash_lock); 398 - idr_remove(&dst_index_idr, n->disk->first_minor); 399 - mutex_unlock(&dst_hash_lock); 400 - 401 - put_disk(n->disk); 402 - } 403 - 404 - if (n->bdev) { 405 - sync_blockdev(n->bdev); 406 - close_bdev_exclusive(n->bdev, FMODE_READ|FMODE_WRITE); 407 - } 408 - 409 - dst_state_lock(st); 410 - st->need_exit = 1; 411 - dst_state_exit_connected(st); 412 - dst_state_unlock(st); 413 - 414 - wake_up(&st->thread_wait); 415 - 416 - dst_state_put(st); 417 - n->state = NULL; 418 - } 419 - 420 - /* 421 - * Free security attributes attached to given node. 422 - */ 423 - static void dst_security_exit(struct dst_node *n) 424 - { 425 - struct dst_secure *s, *tmp; 426 - 427 - list_for_each_entry_safe(s, tmp, &n->security_list, sec_entry) { 428 - list_del(&s->sec_entry); 429 - kfree(s); 430 - } 431 - } 432 - 433 - /* 434 - * Free node when there are no more users. 435 - * Actually node has to be freed on behalf od userspace process, 436 - * since there are number of threads, which are embedded in the 437 - * node, so they can not exit and free node from there, that is 438 - * why there is a wakeup if reference counter is not equal to zero. 439 - */ 440 - void dst_node_put(struct dst_node *n) 441 - { 442 - if (unlikely(!n)) 443 - return; 444 - 445 - dprintk("%s: n: %p, refcnt: %d.\n", 446 - __func__, n, atomic_read(&n->refcnt)); 447 - 448 - if (atomic_dec_and_test(&n->refcnt)) { 449 - dst_node_remove(n); 450 - n->trans_scan_timeout = 0; 451 - dst_node_cleanup(n); 452 - thread_pool_destroy(n->pool); 453 - dst_node_sysfs_exit(n); 454 - dst_node_crypto_exit(n); 455 - dst_security_exit(n); 456 - dst_node_trans_exit(n); 457 - 458 - kfree(n); 459 - 460 - dprintk("%s: freed n: %p.\n", __func__, n); 461 - } else { 462 - wake_up(&n->wait); 463 - } 464 - } 465 - 466 - /* 467 - * Setting up export device: lookup by the name, get its size 468 - * and setup listening socket, which will accept clients, which 469 - * will submit IO for given storage. 470 - */ 471 - static int dst_setup_export(struct dst_node *n, struct dst_ctl *ctl, 472 - struct dst_export_ctl *le) 473 - { 474 - int err; 475 - 476 - snprintf(n->info->local, sizeof(n->info->local), "%s", le->device); 477 - 478 - n->bdev = open_bdev_exclusive(le->device, FMODE_READ|FMODE_WRITE, NULL); 479 - if (IS_ERR(n->bdev)) 480 - return PTR_ERR(n->bdev); 481 - 482 - if (n->size != 0) 483 - n->size = min_t(loff_t, n->bdev->bd_inode->i_size, n->size); 484 - else 485 - n->size = n->bdev->bd_inode->i_size; 486 - 487 - n->info->size = n->size; 488 - err = dst_node_init_listened(n, le); 489 - if (err) 490 - goto err_out_cleanup; 491 - 492 - return 0; 493 - 494 - err_out_cleanup: 495 - close_bdev_exclusive(n->bdev, FMODE_READ|FMODE_WRITE); 496 - n->bdev = NULL; 497 - 498 - return err; 499 - } 500 - 501 - /* Empty thread pool callbacks for the network processing threads. */ 502 - static inline void *dst_thread_network_init(void *data) 503 - { 504 - dprintk("%s: data: %p.\n", __func__, data); 505 - return data; 506 - } 507 - 508 - static inline void dst_thread_network_cleanup(void *data) 509 - { 510 - dprintk("%s: data: %p.\n", __func__, data); 511 - } 512 - 513 - /* 514 - * Allocate DST node and initialize some of its parameters. 515 - */ 516 - static struct dst_node *dst_alloc_node(struct dst_ctl *ctl, 517 - int (*start)(struct dst_node *), 518 - int num) 519 - { 520 - struct dst_node *n; 521 - int err; 522 - 523 - n = kzalloc(sizeof(struct dst_node), GFP_KERNEL); 524 - if (!n) 525 - return NULL; 526 - 527 - INIT_LIST_HEAD(&n->node_entry); 528 - 529 - INIT_LIST_HEAD(&n->security_list); 530 - mutex_init(&n->security_lock); 531 - 532 - init_waitqueue_head(&n->wait); 533 - 534 - n->trans_scan_timeout = msecs_to_jiffies(ctl->trans_scan_timeout); 535 - if (!n->trans_scan_timeout) 536 - n->trans_scan_timeout = HZ; 537 - 538 - n->trans_max_retries = ctl->trans_max_retries; 539 - if (!n->trans_max_retries) 540 - n->trans_max_retries = 10; 541 - 542 - /* 543 - * Pretty much arbitrary default numbers. 544 - * 32 matches maximum number of pages in bio originated from ext3 (31). 545 - */ 546 - n->max_pages = ctl->max_pages; 547 - if (!n->max_pages) 548 - n->max_pages = 32; 549 - 550 - if (n->max_pages > 1024) 551 - n->max_pages = 1024; 552 - 553 - n->start = start; 554 - n->size = ctl->size; 555 - 556 - atomic_set(&n->refcnt, 1); 557 - atomic_long_set(&n->gen, 0); 558 - snprintf(n->name, sizeof(n->name), "%s", ctl->name); 559 - 560 - err = dst_node_sysfs_init(n); 561 - if (err) 562 - goto err_out_free; 563 - 564 - n->pool = thread_pool_create(num, n->name, dst_thread_network_init, 565 - dst_thread_network_cleanup, n); 566 - if (IS_ERR(n->pool)) { 567 - err = PTR_ERR(n->pool); 568 - goto err_out_sysfs_exit; 569 - } 570 - 571 - dprintk("%s: n: %p, name: %s.\n", __func__, n, n->name); 572 - 573 - return n; 574 - 575 - err_out_sysfs_exit: 576 - dst_node_sysfs_exit(n); 577 - err_out_free: 578 - kfree(n); 579 - return NULL; 580 - } 581 - 582 - /* 583 - * Starting a node, connected to the remote server: 584 - * register block device and initialize transaction mechanism. 585 - * In revers order though. 586 - * 587 - * It will autonegotiate some parameters with the remote node 588 - * and update local if needed. 589 - * 590 - * Transaction initialization should be the last thing before 591 - * starting the node, since transaction should include not only 592 - * block IO, but also crypto related data (if any), which are 593 - * initialized separately. 594 - */ 595 - static int dst_start_remote(struct dst_node *n) 596 - { 597 - int err; 598 - 599 - err = dst_node_trans_init(n, sizeof(struct dst_trans)); 600 - if (err) 601 - return err; 602 - 603 - err = dst_node_create_disk(n); 604 - if (err) 605 - return err; 606 - 607 - dst_node_set_size(n); 608 - add_disk(n->disk); 609 - 610 - dprintk("DST: started remote node '%s', minor: %d.\n", 611 - n->name, n->disk->first_minor); 612 - 613 - return 0; 614 - } 615 - 616 - /* 617 - * Adding remote node and initialize connection. 618 - */ 619 - static int dst_add_remote(struct dst_node *n, struct dst_ctl *ctl, 620 - void *data, unsigned int size) 621 - { 622 - int err; 623 - struct dst_network_ctl *rctl = data; 624 - 625 - if (n) 626 - return -EEXIST; 627 - 628 - if (size != sizeof(struct dst_network_ctl)) 629 - return -EINVAL; 630 - 631 - n = dst_alloc_node(ctl, dst_start_remote, 1); 632 - if (!n) 633 - return -ENOMEM; 634 - 635 - memcpy(&n->info->net, rctl, sizeof(struct dst_network_ctl)); 636 - err = dst_node_init_connected(n, rctl); 637 - if (err) 638 - goto err_out_free; 639 - 640 - dst_node_add(n); 641 - 642 - return 0; 643 - 644 - err_out_free: 645 - dst_node_put(n); 646 - return err; 647 - } 648 - 649 - /* 650 - * Adding export node: initializing block device and listening socket. 651 - */ 652 - static int dst_add_export(struct dst_node *n, struct dst_ctl *ctl, 653 - void *data, unsigned int size) 654 - { 655 - int err; 656 - struct dst_export_ctl *le = data; 657 - 658 - if (n) 659 - return -EEXIST; 660 - 661 - if (size != sizeof(struct dst_export_ctl)) 662 - return -EINVAL; 663 - 664 - n = dst_alloc_node(ctl, dst_start_export, 2); 665 - if (!n) 666 - return -EINVAL; 667 - 668 - err = dst_setup_export(n, ctl, le); 669 - if (err) 670 - goto err_out_free; 671 - 672 - dst_node_add(n); 673 - 674 - return 0; 675 - 676 - err_out_free: 677 - dst_node_put(n); 678 - return err; 679 - } 680 - 681 - static int dst_node_remove_unload(struct dst_node *n) 682 - { 683 - printk(KERN_INFO "STOPPED name: '%s', size: %llu.\n", 684 - n->name, n->size); 685 - 686 - if (n->disk) 687 - del_gendisk(n->disk); 688 - 689 - dst_node_remove(n); 690 - dst_node_sysfs_exit(n); 691 - 692 - /* 693 - * This is not a hack. Really. 694 - * Node's reference counter allows to implement fine grained 695 - * node freeing, but since all transactions (which hold node's 696 - * reference counter) are processed in the dedicated thread, 697 - * it is possible that reference will hit zero in that thread, 698 - * so we will not be able to exit thread and cleanup the node. 699 - * 700 - * So, we remove disk, so no new activity is possible, and 701 - * wait until all pending transaction are completed (either 702 - * in receiving thread or by timeout in workqueue), in this 703 - * case reference counter will be less or equal to 2 (once set in 704 - * dst_alloc_node() and then in connector message parser; 705 - * or when we force module unloading, and connector message 706 - * parser does not hold a reference, in this case reference 707 - * counter will be equal to 1), 708 - * and subsequent dst_node_put() calls will free the node. 709 - */ 710 - dprintk("%s: going to sleep with %d refcnt.\n", 711 - __func__, atomic_read(&n->refcnt)); 712 - wait_event(n->wait, atomic_read(&n->refcnt) <= 2); 713 - 714 - dst_node_put(n); 715 - return 0; 716 - } 717 - 718 - /* 719 - * Remove node from the hash table. 720 - */ 721 - static int dst_del_node(struct dst_node *n, struct dst_ctl *ctl, 722 - void *data, unsigned int size) 723 - { 724 - if (!n) 725 - return -ENODEV; 726 - 727 - return dst_node_remove_unload(n); 728 - } 729 - 730 - /* 731 - * Initialize crypto processing for given node. 732 - */ 733 - static int dst_crypto_init(struct dst_node *n, struct dst_ctl *ctl, 734 - void *data, unsigned int size) 735 - { 736 - struct dst_crypto_ctl *crypto = data; 737 - 738 - if (!n) 739 - return -ENODEV; 740 - 741 - if (size != sizeof(struct dst_crypto_ctl) + crypto->hash_keysize + 742 - crypto->cipher_keysize) 743 - return -EINVAL; 744 - 745 - if (n->trans_cache) 746 - return -EEXIST; 747 - 748 - return dst_node_crypto_init(n, crypto); 749 - } 750 - 751 - /* 752 - * Security attributes for given node. 753 - */ 754 - static int dst_security_init(struct dst_node *n, struct dst_ctl *ctl, 755 - void *data, unsigned int size) 756 - { 757 - struct dst_secure *s; 758 - 759 - if (!n) 760 - return -ENODEV; 761 - 762 - if (size != sizeof(struct dst_secure_user)) 763 - return -EINVAL; 764 - 765 - s = kmalloc(sizeof(struct dst_secure), GFP_KERNEL); 766 - if (!s) 767 - return -ENOMEM; 768 - 769 - memcpy(&s->sec, data, size); 770 - 771 - mutex_lock(&n->security_lock); 772 - list_add_tail(&s->sec_entry, &n->security_list); 773 - mutex_unlock(&n->security_lock); 774 - 775 - return 0; 776 - } 777 - 778 - /* 779 - * Kill'em all! 780 - */ 781 - static int dst_start_node(struct dst_node *n, struct dst_ctl *ctl, 782 - void *data, unsigned int size) 783 - { 784 - int err; 785 - 786 - if (!n) 787 - return -ENODEV; 788 - 789 - if (n->trans_cache) 790 - return 0; 791 - 792 - err = n->start(n); 793 - if (err) 794 - return err; 795 - 796 - printk(KERN_INFO "STARTED name: '%s', size: %llu.\n", n->name, n->size); 797 - return 0; 798 - } 799 - 800 - typedef int (*dst_command_func)(struct dst_node *n, struct dst_ctl *ctl, 801 - void *data, unsigned int size); 802 - 803 - /* 804 - * List of userspace commands. 805 - */ 806 - static dst_command_func dst_commands[] = { 807 - [DST_ADD_REMOTE] = &dst_add_remote, 808 - [DST_ADD_EXPORT] = &dst_add_export, 809 - [DST_DEL_NODE] = &dst_del_node, 810 - [DST_CRYPTO] = &dst_crypto_init, 811 - [DST_SECURITY] = &dst_security_init, 812 - [DST_START] = &dst_start_node, 813 - }; 814 - 815 - /* 816 - * Configuration parser. 817 - */ 818 - static void cn_dst_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp) 819 - { 820 - struct dst_ctl *ctl; 821 - int err; 822 - struct dst_ctl_ack ack; 823 - struct dst_node *n = NULL, *tmp; 824 - unsigned int hash; 825 - 826 - if (!cap_raised(nsp->eff_cap, CAP_SYS_ADMIN)) { 827 - err = -EPERM; 828 - goto out; 829 - } 830 - 831 - if (msg->len < sizeof(struct dst_ctl)) { 832 - err = -EBADMSG; 833 - goto out; 834 - } 835 - 836 - ctl = (struct dst_ctl *)msg->data; 837 - 838 - if (ctl->cmd >= DST_CMD_MAX) { 839 - err = -EINVAL; 840 - goto out; 841 - } 842 - hash = dst_hash(ctl->name, sizeof(ctl->name)); 843 - 844 - mutex_lock(&dst_hash_lock); 845 - list_for_each_entry(tmp, &dst_hashtable[hash], node_entry) { 846 - if (!memcmp(tmp->name, ctl->name, sizeof(tmp->name))) { 847 - n = tmp; 848 - dst_node_get(n); 849 - break; 850 - } 851 - } 852 - mutex_unlock(&dst_hash_lock); 853 - 854 - err = dst_commands[ctl->cmd](n, ctl, msg->data + sizeof(struct dst_ctl), 855 - msg->len - sizeof(struct dst_ctl)); 856 - 857 - dst_node_put(n); 858 - out: 859 - memcpy(&ack.msg, msg, sizeof(struct cn_msg)); 860 - 861 - ack.msg.ack = msg->ack + 1; 862 - ack.msg.len = sizeof(struct dst_ctl_ack) - sizeof(struct cn_msg); 863 - 864 - ack.error = err; 865 - 866 - cn_netlink_send(&ack.msg, 0, GFP_KERNEL); 867 - } 868 - 869 - /* 870 - * Global initialization: sysfs, hash table, block device registration, 871 - * connector and various caches. 872 - */ 873 - static int __init dst_sysfs_init(void) 874 - { 875 - return bus_register(&dst_dev_bus_type); 876 - } 877 - 878 - static void dst_sysfs_exit(void) 879 - { 880 - bus_unregister(&dst_dev_bus_type); 881 - } 882 - 883 - static int __init dst_hashtable_init(void) 884 - { 885 - unsigned int i; 886 - 887 - dst_hashtable = kcalloc(dst_hashtable_size, sizeof(struct list_head), 888 - GFP_KERNEL); 889 - if (!dst_hashtable) 890 - return -ENOMEM; 891 - 892 - for (i = 0; i < dst_hashtable_size; ++i) 893 - INIT_LIST_HEAD(&dst_hashtable[i]); 894 - 895 - return 0; 896 - } 897 - 898 - static void dst_hashtable_exit(void) 899 - { 900 - unsigned int i; 901 - struct dst_node *n, *tmp; 902 - 903 - for (i = 0; i < dst_hashtable_size; ++i) { 904 - list_for_each_entry_safe(n, tmp, &dst_hashtable[i], node_entry) { 905 - dst_node_remove_unload(n); 906 - } 907 - } 908 - 909 - kfree(dst_hashtable); 910 - } 911 - 912 - static int __init dst_sys_init(void) 913 - { 914 - int err = -ENOMEM; 915 - 916 - err = dst_hashtable_init(); 917 - if (err) 918 - goto err_out_exit; 919 - 920 - err = dst_export_init(); 921 - if (err) 922 - goto err_out_hashtable_exit; 923 - 924 - err = register_blkdev(dst_major, DST_NAME); 925 - if (err < 0) 926 - goto err_out_export_exit; 927 - if (err) 928 - dst_major = err; 929 - 930 - err = dst_sysfs_init(); 931 - if (err) 932 - goto err_out_unregister; 933 - 934 - err = cn_add_callback(&cn_dst_id, "DST", cn_dst_callback); 935 - if (err) 936 - goto err_out_sysfs_exit; 937 - 938 - printk(KERN_INFO "Distributed storage, '%s' release.\n", dst_name); 939 - 940 - return 0; 941 - 942 - err_out_sysfs_exit: 943 - dst_sysfs_exit(); 944 - err_out_unregister: 945 - unregister_blkdev(dst_major, DST_NAME); 946 - err_out_export_exit: 947 - dst_export_exit(); 948 - err_out_hashtable_exit: 949 - dst_hashtable_exit(); 950 - err_out_exit: 951 - return err; 952 - } 953 - 954 - static void __exit dst_sys_exit(void) 955 - { 956 - cn_del_callback(&cn_dst_id); 957 - unregister_blkdev(dst_major, DST_NAME); 958 - dst_hashtable_exit(); 959 - dst_sysfs_exit(); 960 - dst_export_exit(); 961 - } 962 - 963 - module_init(dst_sys_init); 964 - module_exit(dst_sys_exit); 965 - 966 - MODULE_DESCRIPTION("Distributed storage"); 967 - MODULE_AUTHOR("Evgeniy Polyakov <zbr@ioremap.net>"); 968 - MODULE_LICENSE("GPL");
-660
drivers/staging/dst/export.c
··· 1 - /* 2 - * 2007+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net> 3 - * All rights reserved. 4 - * 5 - * This program is free software; you can redistribute it and/or modify 6 - * it under the terms of the GNU General Public License as published by 7 - * the Free Software Foundation; either version 2 of the License, or 8 - * (at your option) any later version. 9 - * 10 - * This program is distributed in the hope that it will be useful, 11 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 - * GNU General Public License for more details. 14 - */ 15 - 16 - #include <linux/blkdev.h> 17 - #include <linux/bio.h> 18 - #include <linux/dst.h> 19 - #include <linux/in.h> 20 - #include <linux/in6.h> 21 - #include <linux/poll.h> 22 - #include <linux/slab.h> 23 - #include <linux/socket.h> 24 - 25 - #include <net/sock.h> 26 - 27 - /* 28 - * Export bioset is used for server block IO requests. 29 - */ 30 - static struct bio_set *dst_bio_set; 31 - 32 - int __init dst_export_init(void) 33 - { 34 - int err = -ENOMEM; 35 - 36 - dst_bio_set = bioset_create(32, sizeof(struct dst_export_priv)); 37 - if (!dst_bio_set) 38 - goto err_out_exit; 39 - 40 - return 0; 41 - 42 - err_out_exit: 43 - return err; 44 - } 45 - 46 - void dst_export_exit(void) 47 - { 48 - bioset_free(dst_bio_set); 49 - } 50 - 51 - /* 52 - * When client connects and autonegotiates with the server node, 53 - * its permissions are checked in a security attributes and sent 54 - * back. 55 - */ 56 - static unsigned int dst_check_permissions(struct dst_state *main, 57 - struct dst_state *st) 58 - { 59 - struct dst_node *n = main->node; 60 - struct dst_secure *sentry; 61 - struct dst_secure_user *s; 62 - struct saddr *sa = &st->ctl.addr; 63 - unsigned int perm = 0; 64 - 65 - mutex_lock(&n->security_lock); 66 - list_for_each_entry(sentry, &n->security_list, sec_entry) { 67 - s = &sentry->sec; 68 - 69 - if (s->addr.sa_family != sa->sa_family) 70 - continue; 71 - 72 - if (s->addr.sa_data_len != sa->sa_data_len) 73 - continue; 74 - 75 - /* 76 - * This '2' below is a port field. This may be very wrong to do 77 - * in atalk for example though. If there will be any need 78 - * to extent protocol to something else, I can create 79 - * per-family helpers and use them instead of this memcmp. 80 - */ 81 - if (memcmp(s->addr.sa_data + 2, sa->sa_data + 2, 82 - sa->sa_data_len - 2)) 83 - continue; 84 - 85 - perm = s->permissions; 86 - } 87 - mutex_unlock(&n->security_lock); 88 - 89 - return perm; 90 - } 91 - 92 - /* 93 - * Accept new client: allocate appropriate network state and check permissions. 94 - */ 95 - static struct dst_state *dst_accept_client(struct dst_state *st) 96 - { 97 - unsigned int revents = 0; 98 - unsigned int err_mask = POLLERR | POLLHUP | POLLRDHUP; 99 - unsigned int mask = err_mask | POLLIN; 100 - struct dst_node *n = st->node; 101 - int err = 0; 102 - struct socket *sock = NULL; 103 - struct dst_state *new; 104 - 105 - while (!err && !sock) { 106 - revents = dst_state_poll(st); 107 - 108 - if (!(revents & mask)) { 109 - DEFINE_WAIT(wait); 110 - 111 - for (;;) { 112 - prepare_to_wait(&st->thread_wait, 113 - &wait, TASK_INTERRUPTIBLE); 114 - if (!n->trans_scan_timeout || st->need_exit) 115 - break; 116 - 117 - revents = dst_state_poll(st); 118 - 119 - if (revents & mask) 120 - break; 121 - 122 - if (signal_pending(current)) 123 - break; 124 - 125 - /* 126 - * Magic HZ? Polling check above is not safe in 127 - * all cases (like socket reset in BH context), 128 - * so it is simpler just to postpone it to the 129 - * process context instead of implementing 130 - * special locking there. 131 - */ 132 - schedule_timeout(HZ); 133 - } 134 - finish_wait(&st->thread_wait, &wait); 135 - } 136 - 137 - err = -ECONNRESET; 138 - dst_state_lock(st); 139 - 140 - dprintk("%s: st: %p, revents: %x [err: %d, in: %d].\n", 141 - __func__, st, revents, revents & err_mask, 142 - revents & POLLIN); 143 - 144 - if (revents & err_mask) { 145 - dprintk("%s: revents: %x, socket: %p, err: %d.\n", 146 - __func__, revents, st->socket, err); 147 - err = -ECONNRESET; 148 - } 149 - 150 - if (!n->trans_scan_timeout || st->need_exit) 151 - err = -ENODEV; 152 - 153 - if (st->socket && (revents & POLLIN)) 154 - err = kernel_accept(st->socket, &sock, 0); 155 - 156 - dst_state_unlock(st); 157 - } 158 - 159 - if (err) 160 - goto err_out_exit; 161 - 162 - new = dst_state_alloc(st->node); 163 - if (IS_ERR(new)) { 164 - err = -ENOMEM; 165 - goto err_out_release; 166 - } 167 - new->socket = sock; 168 - 169 - new->ctl.addr.sa_data_len = sizeof(struct sockaddr); 170 - err = kernel_getpeername(sock, (struct sockaddr *)&new->ctl.addr, 171 - (int *)&new->ctl.addr.sa_data_len); 172 - if (err) 173 - goto err_out_put; 174 - 175 - new->permissions = dst_check_permissions(st, new); 176 - if (new->permissions == 0) { 177 - err = -EPERM; 178 - dst_dump_addr(sock, (struct sockaddr *)&new->ctl.addr, 179 - "Client is not allowed to connect"); 180 - goto err_out_put; 181 - } 182 - 183 - err = dst_poll_init(new); 184 - if (err) 185 - goto err_out_put; 186 - 187 - dst_dump_addr(sock, (struct sockaddr *)&new->ctl.addr, 188 - "Connected client"); 189 - 190 - return new; 191 - 192 - err_out_put: 193 - dst_state_put(new); 194 - err_out_release: 195 - sock_release(sock); 196 - err_out_exit: 197 - return ERR_PTR(err); 198 - } 199 - 200 - /* 201 - * Each server's block request sometime finishes. 202 - * Usually it happens in hard irq context of the appropriate controller, 203 - * so to play good with all cases we just queue BIO into the queue 204 - * and wake up processing thread, which gets completed request and 205 - * send (encrypting if needed) it back to the client (if it was a read 206 - * request), or sends back reply that writing successfully completed. 207 - */ 208 - static int dst_export_process_request_queue(struct dst_state *st) 209 - { 210 - unsigned long flags; 211 - struct dst_export_priv *p = NULL; 212 - struct bio *bio; 213 - int err = 0; 214 - 215 - while (!list_empty(&st->request_list)) { 216 - spin_lock_irqsave(&st->request_lock, flags); 217 - if (!list_empty(&st->request_list)) { 218 - p = list_first_entry(&st->request_list, 219 - struct dst_export_priv, request_entry); 220 - list_del(&p->request_entry); 221 - } 222 - spin_unlock_irqrestore(&st->request_lock, flags); 223 - 224 - if (!p) 225 - break; 226 - 227 - bio = p->bio; 228 - 229 - if (dst_need_crypto(st->node) && (bio_data_dir(bio) == READ)) 230 - err = dst_export_crypto(st->node, bio); 231 - else 232 - err = dst_export_send_bio(bio); 233 - 234 - if (err) 235 - break; 236 - } 237 - 238 - return err; 239 - } 240 - 241 - /* 242 - * Cleanup export state. 243 - * It has to wait until all requests are finished, 244 - * and then free them all. 245 - */ 246 - static void dst_state_cleanup_export(struct dst_state *st) 247 - { 248 - struct dst_export_priv *p; 249 - unsigned long flags; 250 - 251 - /* 252 - * This loop waits for all pending bios to be completed and freed. 253 - */ 254 - while (atomic_read(&st->refcnt) > 1) { 255 - dprintk("%s: st: %p, refcnt: %d, list_empty: %d.\n", 256 - __func__, st, atomic_read(&st->refcnt), 257 - list_empty(&st->request_list)); 258 - wait_event_timeout(st->thread_wait, 259 - (atomic_read(&st->refcnt) == 1) || 260 - !list_empty(&st->request_list), 261 - HZ/2); 262 - 263 - while (!list_empty(&st->request_list)) { 264 - p = NULL; 265 - spin_lock_irqsave(&st->request_lock, flags); 266 - if (!list_empty(&st->request_list)) { 267 - p = list_first_entry(&st->request_list, 268 - struct dst_export_priv, request_entry); 269 - list_del(&p->request_entry); 270 - } 271 - spin_unlock_irqrestore(&st->request_lock, flags); 272 - 273 - if (p) 274 - bio_put(p->bio); 275 - 276 - dprintk("%s: st: %p, refcnt: %d, list_empty: %d, p: " 277 - "%p.\n", __func__, st, atomic_read(&st->refcnt), 278 - list_empty(&st->request_list), p); 279 - } 280 - } 281 - 282 - dst_state_put(st); 283 - } 284 - 285 - /* 286 - * Client accepting thread. 287 - * Not only accepts new connection, but also schedules receiving thread 288 - * and performs request completion described above. 289 - */ 290 - static int dst_accept(void *init_data, void *schedule_data) 291 - { 292 - struct dst_state *main_st = schedule_data; 293 - struct dst_node *n = init_data; 294 - struct dst_state *st; 295 - int err; 296 - 297 - while (n->trans_scan_timeout && !main_st->need_exit) { 298 - dprintk("%s: main_st: %p, n: %p.\n", __func__, main_st, n); 299 - st = dst_accept_client(main_st); 300 - if (IS_ERR(st)) 301 - continue; 302 - 303 - err = dst_state_schedule_receiver(st); 304 - if (!err) { 305 - while (n->trans_scan_timeout) { 306 - err = wait_event_interruptible_timeout(st->thread_wait, 307 - !list_empty(&st->request_list) || 308 - !n->trans_scan_timeout || 309 - st->need_exit, 310 - HZ); 311 - 312 - if (!n->trans_scan_timeout || st->need_exit) 313 - break; 314 - 315 - if (list_empty(&st->request_list)) 316 - continue; 317 - 318 - err = dst_export_process_request_queue(st); 319 - if (err) 320 - break; 321 - } 322 - 323 - st->need_exit = 1; 324 - wake_up(&st->thread_wait); 325 - } 326 - 327 - dst_state_cleanup_export(st); 328 - } 329 - 330 - dprintk("%s: freeing listening socket st: %p.\n", __func__, main_st); 331 - 332 - dst_state_lock(main_st); 333 - dst_poll_exit(main_st); 334 - dst_state_socket_release(main_st); 335 - dst_state_unlock(main_st); 336 - dst_state_put(main_st); 337 - dprintk("%s: freed listening socket st: %p.\n", __func__, main_st); 338 - 339 - return 0; 340 - } 341 - 342 - int dst_start_export(struct dst_node *n) 343 - { 344 - if (list_empty(&n->security_list)) { 345 - printk(KERN_ERR "You are trying to export node '%s' " 346 - "without security attributes.\nNo clients will " 347 - "be allowed to connect. Exiting.\n", n->name); 348 - return -EINVAL; 349 - } 350 - return dst_node_trans_init(n, sizeof(struct dst_export_priv)); 351 - } 352 - 353 - /* 354 - * Initialize listening state and schedule accepting thread. 355 - */ 356 - int dst_node_init_listened(struct dst_node *n, struct dst_export_ctl *le) 357 - { 358 - struct dst_state *st; 359 - int err = -ENOMEM; 360 - struct dst_network_ctl *ctl = &le->ctl; 361 - 362 - memcpy(&n->info->net, ctl, sizeof(struct dst_network_ctl)); 363 - 364 - st = dst_state_alloc(n); 365 - if (IS_ERR(st)) { 366 - err = PTR_ERR(st); 367 - goto err_out_exit; 368 - } 369 - memcpy(&st->ctl, ctl, sizeof(struct dst_network_ctl)); 370 - 371 - err = dst_state_socket_create(st); 372 - if (err) 373 - goto err_out_put; 374 - 375 - st->socket->sk->sk_reuse = 1; 376 - 377 - err = kernel_bind(st->socket, (struct sockaddr *)&ctl->addr, 378 - ctl->addr.sa_data_len); 379 - if (err) 380 - goto err_out_socket_release; 381 - 382 - err = kernel_listen(st->socket, 1024); 383 - if (err) 384 - goto err_out_socket_release; 385 - n->state = st; 386 - 387 - err = dst_poll_init(st); 388 - if (err) 389 - goto err_out_socket_release; 390 - 391 - dst_state_get(st); 392 - 393 - err = thread_pool_schedule(n->pool, dst_thread_setup, 394 - dst_accept, st, MAX_SCHEDULE_TIMEOUT); 395 - if (err) 396 - goto err_out_poll_exit; 397 - 398 - return 0; 399 - 400 - err_out_poll_exit: 401 - dst_poll_exit(st); 402 - err_out_socket_release: 403 - dst_state_socket_release(st); 404 - err_out_put: 405 - dst_state_put(st); 406 - err_out_exit: 407 - n->state = NULL; 408 - return err; 409 - } 410 - 411 - /* 412 - * Free bio and related private data. 413 - * Also drop a reference counter for appropriate state, 414 - * which waits when there are no more block IOs in-flight. 415 - */ 416 - static void dst_bio_destructor(struct bio *bio) 417 - { 418 - struct bio_vec *bv; 419 - struct dst_export_priv *priv = bio->bi_private; 420 - int i; 421 - 422 - bio_for_each_segment(bv, bio, i) { 423 - if (!bv->bv_page) 424 - break; 425 - 426 - __free_page(bv->bv_page); 427 - } 428 - 429 - if (priv) 430 - dst_state_put(priv->state); 431 - bio_free(bio, dst_bio_set); 432 - } 433 - 434 - /* 435 - * Block IO completion. Queue request to be sent back to 436 - * the client (or just confirmation). 437 - */ 438 - static void dst_bio_end_io(struct bio *bio, int err) 439 - { 440 - struct dst_export_priv *p = bio->bi_private; 441 - struct dst_state *st = p->state; 442 - unsigned long flags; 443 - 444 - spin_lock_irqsave(&st->request_lock, flags); 445 - list_add_tail(&p->request_entry, &st->request_list); 446 - spin_unlock_irqrestore(&st->request_lock, flags); 447 - 448 - wake_up(&st->thread_wait); 449 - } 450 - 451 - /* 452 - * Allocate read request for the server. 453 - */ 454 - static int dst_export_read_request(struct bio *bio, unsigned int total_size) 455 - { 456 - unsigned int size; 457 - struct page *page; 458 - int err; 459 - 460 - while (total_size) { 461 - err = -ENOMEM; 462 - page = alloc_page(GFP_KERNEL); 463 - if (!page) 464 - goto err_out_exit; 465 - 466 - size = min_t(unsigned int, PAGE_SIZE, total_size); 467 - 468 - err = bio_add_page(bio, page, size, 0); 469 - dprintk("%s: bio: %llu/%u, size: %u, err: %d.\n", 470 - __func__, (u64)bio->bi_sector, bio->bi_size, 471 - size, err); 472 - if (err <= 0) 473 - goto err_out_free_page; 474 - 475 - total_size -= size; 476 - } 477 - 478 - return 0; 479 - 480 - err_out_free_page: 481 - __free_page(page); 482 - err_out_exit: 483 - return err; 484 - } 485 - 486 - /* 487 - * Allocate write request for the server. 488 - * Should not only get pages, but also read data from the network. 489 - */ 490 - static int dst_export_write_request(struct dst_state *st, 491 - struct bio *bio, unsigned int total_size) 492 - { 493 - unsigned int size; 494 - struct page *page; 495 - void *data; 496 - int err; 497 - 498 - while (total_size) { 499 - err = -ENOMEM; 500 - page = alloc_page(GFP_KERNEL); 501 - if (!page) 502 - goto err_out_exit; 503 - 504 - data = kmap(page); 505 - if (!data) 506 - goto err_out_free_page; 507 - 508 - size = min_t(unsigned int, PAGE_SIZE, total_size); 509 - 510 - err = dst_data_recv(st, data, size); 511 - if (err) 512 - goto err_out_unmap_page; 513 - 514 - err = bio_add_page(bio, page, size, 0); 515 - if (err <= 0) 516 - goto err_out_unmap_page; 517 - 518 - kunmap(page); 519 - 520 - total_size -= size; 521 - } 522 - 523 - return 0; 524 - 525 - err_out_unmap_page: 526 - kunmap(page); 527 - err_out_free_page: 528 - __free_page(page); 529 - err_out_exit: 530 - return err; 531 - } 532 - 533 - /* 534 - * Groovy, we've gotten an IO request from the client. 535 - * Allocate BIO from the bioset, private data from the mempool 536 - * and lots of pages for IO. 537 - */ 538 - int dst_process_io(struct dst_state *st) 539 - { 540 - struct dst_node *n = st->node; 541 - struct dst_cmd *cmd = st->data; 542 - struct bio *bio; 543 - struct dst_export_priv *priv; 544 - int err = -ENOMEM; 545 - 546 - if (unlikely(!n->bdev)) { 547 - err = -EINVAL; 548 - goto err_out_exit; 549 - } 550 - 551 - bio = bio_alloc_bioset(GFP_KERNEL, 552 - PAGE_ALIGN(cmd->size) >> PAGE_SHIFT, 553 - dst_bio_set); 554 - if (!bio) 555 - goto err_out_exit; 556 - 557 - priv = (struct dst_export_priv *)(((void *)bio) - 558 - sizeof (struct dst_export_priv)); 559 - 560 - priv->state = dst_state_get(st); 561 - priv->bio = bio; 562 - 563 - bio->bi_private = priv; 564 - bio->bi_end_io = dst_bio_end_io; 565 - bio->bi_destructor = dst_bio_destructor; 566 - bio->bi_bdev = n->bdev; 567 - 568 - /* 569 - * Server side is only interested in two low bits: 570 - * uptodate (set by itself actually) and rw block 571 - */ 572 - bio->bi_flags |= cmd->flags & 3; 573 - 574 - bio->bi_rw = cmd->rw; 575 - bio->bi_size = 0; 576 - bio->bi_sector = cmd->sector; 577 - 578 - dst_bio_to_cmd(bio, &priv->cmd, DST_IO_RESPONSE, cmd->id); 579 - 580 - priv->cmd.flags = 0; 581 - priv->cmd.size = cmd->size; 582 - 583 - if (bio_data_dir(bio) == WRITE) { 584 - err = dst_recv_cdata(st, priv->cmd.hash); 585 - if (err) 586 - goto err_out_free; 587 - 588 - err = dst_export_write_request(st, bio, cmd->size); 589 - if (err) 590 - goto err_out_free; 591 - 592 - if (dst_need_crypto(n)) 593 - return dst_export_crypto(n, bio); 594 - } else { 595 - err = dst_export_read_request(bio, cmd->size); 596 - if (err) 597 - goto err_out_free; 598 - } 599 - 600 - dprintk("%s: bio: %llu/%u, rw: %lu, dir: %lu, flags: %lx, phys: %d.\n", 601 - __func__, (u64)bio->bi_sector, bio->bi_size, 602 - bio->bi_rw, bio_data_dir(bio), 603 - bio->bi_flags, bio->bi_phys_segments); 604 - 605 - generic_make_request(bio); 606 - 607 - return 0; 608 - 609 - err_out_free: 610 - bio_put(bio); 611 - err_out_exit: 612 - return err; 613 - } 614 - 615 - /* 616 - * Ok, block IO is ready, let's send it back to the client... 617 - */ 618 - int dst_export_send_bio(struct bio *bio) 619 - { 620 - struct dst_export_priv *p = bio->bi_private; 621 - struct dst_state *st = p->state; 622 - struct dst_cmd *cmd = &p->cmd; 623 - int err; 624 - 625 - dprintk("%s: id: %llu, bio: %llu/%u, csize: %u, flags: %lu, rw: %lu.\n", 626 - __func__, cmd->id, (u64)bio->bi_sector, bio->bi_size, 627 - cmd->csize, bio->bi_flags, bio->bi_rw); 628 - 629 - dst_convert_cmd(cmd); 630 - 631 - dst_state_lock(st); 632 - if (!st->socket) { 633 - err = -ECONNRESET; 634 - goto err_out_unlock; 635 - } 636 - 637 - if (bio_data_dir(bio) == WRITE) { 638 - /* ... or just confirmation that writing has completed. */ 639 - cmd->size = cmd->csize = 0; 640 - err = dst_data_send_header(st->socket, cmd, 641 - sizeof(struct dst_cmd), 0); 642 - if (err) 643 - goto err_out_unlock; 644 - } else { 645 - err = dst_send_bio(st, cmd, bio); 646 - if (err) 647 - goto err_out_unlock; 648 - } 649 - 650 - dst_state_unlock(st); 651 - 652 - bio_put(bio); 653 - return 0; 654 - 655 - err_out_unlock: 656 - dst_state_unlock(st); 657 - 658 - bio_put(bio); 659 - return err; 660 - }
-844
drivers/staging/dst/state.c
··· 1 - /* 2 - * 2007+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net> 3 - * All rights reserved. 4 - * 5 - * This program is free software; you can redistribute it and/or modify 6 - * it under the terms of the GNU General Public License as published by 7 - * the Free Software Foundation; either version 2 of the License, or 8 - * (at your option) any later version. 9 - * 10 - * This program is distributed in the hope that it will be useful, 11 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 - * GNU General Public License for more details. 14 - */ 15 - 16 - #include <linux/buffer_head.h> 17 - #include <linux/blkdev.h> 18 - #include <linux/bio.h> 19 - #include <linux/connector.h> 20 - #include <linux/dst.h> 21 - #include <linux/device.h> 22 - #include <linux/in.h> 23 - #include <linux/in6.h> 24 - #include <linux/socket.h> 25 - #include <linux/slab.h> 26 - 27 - #include <net/sock.h> 28 - 29 - /* 30 - * Polling machinery. 31 - */ 32 - 33 - struct dst_poll_helper { 34 - poll_table pt; 35 - struct dst_state *st; 36 - }; 37 - 38 - static int dst_queue_wake(wait_queue_t *wait, unsigned mode, 39 - int sync, void *key) 40 - { 41 - struct dst_state *st = container_of(wait, struct dst_state, wait); 42 - 43 - wake_up(&st->thread_wait); 44 - return 1; 45 - } 46 - 47 - static void dst_queue_func(struct file *file, wait_queue_head_t *whead, 48 - poll_table *pt) 49 - { 50 - struct dst_state *st = container_of(pt, struct dst_poll_helper, pt)->st; 51 - 52 - st->whead = whead; 53 - init_waitqueue_func_entry(&st->wait, dst_queue_wake); 54 - add_wait_queue(whead, &st->wait); 55 - } 56 - 57 - void dst_poll_exit(struct dst_state *st) 58 - { 59 - if (st->whead) { 60 - remove_wait_queue(st->whead, &st->wait); 61 - st->whead = NULL; 62 - } 63 - } 64 - 65 - int dst_poll_init(struct dst_state *st) 66 - { 67 - struct dst_poll_helper ph; 68 - 69 - ph.st = st; 70 - init_poll_funcptr(&ph.pt, &dst_queue_func); 71 - 72 - st->socket->ops->poll(NULL, st->socket, &ph.pt); 73 - return 0; 74 - } 75 - 76 - /* 77 - * Header receiving function - may block. 78 - */ 79 - static int dst_data_recv_header(struct socket *sock, 80 - void *data, unsigned int size, int block) 81 - { 82 - struct msghdr msg; 83 - struct kvec iov; 84 - int err; 85 - 86 - iov.iov_base = data; 87 - iov.iov_len = size; 88 - 89 - msg.msg_iov = (struct iovec *)&iov; 90 - msg.msg_iovlen = 1; 91 - msg.msg_name = NULL; 92 - msg.msg_namelen = 0; 93 - msg.msg_control = NULL; 94 - msg.msg_controllen = 0; 95 - msg.msg_flags = (block) ? MSG_WAITALL : MSG_DONTWAIT; 96 - 97 - err = kernel_recvmsg(sock, &msg, &iov, 1, iov.iov_len, 98 - msg.msg_flags); 99 - if (err != size) 100 - return -1; 101 - 102 - return 0; 103 - } 104 - 105 - /* 106 - * Header sending function - may block. 107 - */ 108 - int dst_data_send_header(struct socket *sock, 109 - void *data, unsigned int size, int more) 110 - { 111 - struct msghdr msg; 112 - struct kvec iov; 113 - int err; 114 - 115 - iov.iov_base = data; 116 - iov.iov_len = size; 117 - 118 - msg.msg_iov = (struct iovec *)&iov; 119 - msg.msg_iovlen = 1; 120 - msg.msg_name = NULL; 121 - msg.msg_namelen = 0; 122 - msg.msg_control = NULL; 123 - msg.msg_controllen = 0; 124 - msg.msg_flags = MSG_WAITALL | (more ? MSG_MORE : 0); 125 - 126 - err = kernel_sendmsg(sock, &msg, &iov, 1, iov.iov_len); 127 - if (err != size) { 128 - dprintk("%s: size: %u, more: %d, err: %d.\n", 129 - __func__, size, more, err); 130 - return -1; 131 - } 132 - 133 - return 0; 134 - } 135 - 136 - /* 137 - * Block autoconfiguration: request size of the storage and permissions. 138 - */ 139 - static int dst_request_remote_config(struct dst_state *st) 140 - { 141 - struct dst_node *n = st->node; 142 - int err = -EINVAL; 143 - struct dst_cmd *cmd = st->data; 144 - 145 - memset(cmd, 0, sizeof(struct dst_cmd)); 146 - cmd->cmd = DST_CFG; 147 - 148 - dst_convert_cmd(cmd); 149 - 150 - err = dst_data_send_header(st->socket, cmd, sizeof(struct dst_cmd), 0); 151 - if (err) 152 - goto out; 153 - 154 - err = dst_data_recv_header(st->socket, cmd, sizeof(struct dst_cmd), 1); 155 - if (err) 156 - goto out; 157 - 158 - dst_convert_cmd(cmd); 159 - 160 - if (cmd->cmd != DST_CFG) { 161 - err = -EINVAL; 162 - dprintk("%s: checking result: cmd: %d, size reported: %llu.\n", 163 - __func__, cmd->cmd, cmd->sector); 164 - goto out; 165 - } 166 - 167 - if (n->size != 0) 168 - n->size = min_t(loff_t, n->size, cmd->sector); 169 - else 170 - n->size = cmd->sector; 171 - 172 - n->info->size = n->size; 173 - st->permissions = cmd->rw; 174 - 175 - out: 176 - dprintk("%s: n: %p, err: %d, size: %llu, permission: %x.\n", 177 - __func__, n, err, n->size, st->permissions); 178 - return err; 179 - } 180 - 181 - /* 182 - * Socket machinery. 183 - */ 184 - 185 - #define DST_DEFAULT_TIMEO 20000 186 - 187 - int dst_state_socket_create(struct dst_state *st) 188 - { 189 - int err; 190 - struct socket *sock; 191 - struct dst_network_ctl *ctl = &st->ctl; 192 - 193 - err = sock_create(ctl->addr.sa_family, ctl->type, ctl->proto, &sock); 194 - if (err < 0) 195 - return err; 196 - 197 - sock->sk->sk_sndtimeo = sock->sk->sk_rcvtimeo = 198 - msecs_to_jiffies(DST_DEFAULT_TIMEO); 199 - sock->sk->sk_allocation = GFP_NOIO; 200 - 201 - st->socket = st->read_socket = sock; 202 - return 0; 203 - } 204 - 205 - void dst_state_socket_release(struct dst_state *st) 206 - { 207 - dprintk("%s: st: %p, socket: %p, n: %p.\n", 208 - __func__, st, st->socket, st->node); 209 - if (st->socket) { 210 - sock_release(st->socket); 211 - st->socket = NULL; 212 - st->read_socket = NULL; 213 - } 214 - } 215 - 216 - void dst_dump_addr(struct socket *sk, struct sockaddr *sa, char *str) 217 - { 218 - if (sk->ops->family == AF_INET) { 219 - struct sockaddr_in *sin = (struct sockaddr_in *)sa; 220 - printk(KERN_INFO "%s %u.%u.%u.%u:%d.\n", str, 221 - NIPQUAD(sin->sin_addr.s_addr), ntohs(sin->sin_port)); 222 - } else if (sk->ops->family == AF_INET6) { 223 - struct sockaddr_in6 *sin = (struct sockaddr_in6 *)sa; 224 - printk(KERN_INFO "%s %pi6:%d", 225 - str, &sin->sin6_addr, ntohs(sin->sin6_port)); 226 - } 227 - } 228 - 229 - void dst_state_exit_connected(struct dst_state *st) 230 - { 231 - if (st->socket) { 232 - dst_poll_exit(st); 233 - st->socket->ops->shutdown(st->socket, 2); 234 - 235 - dst_dump_addr(st->socket, (struct sockaddr *)&st->ctl.addr, 236 - "Disconnected peer"); 237 - dst_state_socket_release(st); 238 - } 239 - } 240 - 241 - static int dst_state_init_connected(struct dst_state *st) 242 - { 243 - int err; 244 - struct dst_network_ctl *ctl = &st->ctl; 245 - 246 - err = dst_state_socket_create(st); 247 - if (err) 248 - goto err_out_exit; 249 - 250 - err = kernel_connect(st->socket, (struct sockaddr *)&st->ctl.addr, 251 - st->ctl.addr.sa_data_len, 0); 252 - if (err) 253 - goto err_out_release; 254 - 255 - err = dst_poll_init(st); 256 - if (err) 257 - goto err_out_release; 258 - 259 - dst_dump_addr(st->socket, (struct sockaddr *)&ctl->addr, 260 - "Connected to peer"); 261 - 262 - return 0; 263 - 264 - err_out_release: 265 - dst_state_socket_release(st); 266 - err_out_exit: 267 - return err; 268 - } 269 - 270 - /* 271 - * State reset is used to reconnect to the remote peer. 272 - * May fail, but who cares, we will try again later. 273 - */ 274 - static inline void dst_state_reset_nolock(struct dst_state *st) 275 - { 276 - dst_state_exit_connected(st); 277 - dst_state_init_connected(st); 278 - } 279 - 280 - static inline void dst_state_reset(struct dst_state *st) 281 - { 282 - dst_state_lock(st); 283 - dst_state_reset_nolock(st); 284 - dst_state_unlock(st); 285 - } 286 - 287 - /* 288 - * Basic network sending/receiving functions. 289 - * Blocked mode is used. 290 - */ 291 - static int dst_data_recv_raw(struct dst_state *st, void *buf, u64 size) 292 - { 293 - struct msghdr msg; 294 - struct kvec iov; 295 - int err; 296 - 297 - BUG_ON(!size); 298 - 299 - iov.iov_base = buf; 300 - iov.iov_len = size; 301 - 302 - msg.msg_iov = (struct iovec *)&iov; 303 - msg.msg_iovlen = 1; 304 - msg.msg_name = NULL; 305 - msg.msg_namelen = 0; 306 - msg.msg_control = NULL; 307 - msg.msg_controllen = 0; 308 - msg.msg_flags = MSG_DONTWAIT; 309 - 310 - err = kernel_recvmsg(st->socket, &msg, &iov, 1, iov.iov_len, 311 - msg.msg_flags); 312 - if (err <= 0) { 313 - dprintk("%s: failed to recv data: size: %llu, err: %d.\n", 314 - __func__, size, err); 315 - if (err == 0) 316 - err = -ECONNRESET; 317 - 318 - dst_state_exit_connected(st); 319 - } 320 - 321 - return err; 322 - } 323 - 324 - /* 325 - * Ping command to early detect failed nodes. 326 - */ 327 - static int dst_send_ping(struct dst_state *st) 328 - { 329 - struct dst_cmd *cmd = st->data; 330 - int err = -ECONNRESET; 331 - 332 - dst_state_lock(st); 333 - if (st->socket) { 334 - memset(cmd, 0, sizeof(struct dst_cmd)); 335 - 336 - cmd->cmd = __cpu_to_be32(DST_PING); 337 - 338 - err = dst_data_send_header(st->socket, cmd, 339 - sizeof(struct dst_cmd), 0); 340 - } 341 - dprintk("%s: st: %p, socket: %p, err: %d.\n", __func__, 342 - st, st->socket, err); 343 - dst_state_unlock(st); 344 - 345 - return err; 346 - } 347 - 348 - /* 349 - * Receiving function, which should either return error or read 350 - * whole block request. If there was no traffic for a one second, 351 - * send a ping, since remote node may die. 352 - */ 353 - int dst_data_recv(struct dst_state *st, void *data, unsigned int size) 354 - { 355 - unsigned int revents = 0; 356 - unsigned int err_mask = POLLERR | POLLHUP | POLLRDHUP; 357 - unsigned int mask = err_mask | POLLIN; 358 - struct dst_node *n = st->node; 359 - int err = 0; 360 - 361 - while (size && !err) { 362 - revents = dst_state_poll(st); 363 - 364 - if (!(revents & mask)) { 365 - DEFINE_WAIT(wait); 366 - 367 - for (;;) { 368 - prepare_to_wait(&st->thread_wait, &wait, 369 - TASK_INTERRUPTIBLE); 370 - if (!n->trans_scan_timeout || st->need_exit) 371 - break; 372 - 373 - revents = dst_state_poll(st); 374 - 375 - if (revents & mask) 376 - break; 377 - 378 - if (signal_pending(current)) 379 - break; 380 - 381 - if (!schedule_timeout(HZ)) { 382 - err = dst_send_ping(st); 383 - if (err) 384 - return err; 385 - } 386 - 387 - continue; 388 - } 389 - finish_wait(&st->thread_wait, &wait); 390 - } 391 - 392 - err = -ECONNRESET; 393 - dst_state_lock(st); 394 - 395 - if (st->socket && (st->read_socket == st->socket) && 396 - (revents & POLLIN)) { 397 - err = dst_data_recv_raw(st, data, size); 398 - if (err > 0) { 399 - data += err; 400 - size -= err; 401 - err = 0; 402 - } 403 - } 404 - 405 - if (revents & err_mask || !st->socket) { 406 - dprintk("%s: revents: %x, socket: %p, size: %u, " 407 - "err: %d.\n", __func__, revents, 408 - st->socket, size, err); 409 - err = -ECONNRESET; 410 - } 411 - 412 - dst_state_unlock(st); 413 - 414 - if (!n->trans_scan_timeout) 415 - err = -ENODEV; 416 - } 417 - 418 - return err; 419 - } 420 - 421 - /* 422 - * Send block autoconf reply. 423 - */ 424 - static int dst_process_cfg(struct dst_state *st) 425 - { 426 - struct dst_node *n = st->node; 427 - struct dst_cmd *cmd = st->data; 428 - int err; 429 - 430 - cmd->sector = n->size; 431 - cmd->rw = st->permissions; 432 - 433 - dst_convert_cmd(cmd); 434 - 435 - dst_state_lock(st); 436 - err = dst_data_send_header(st->socket, cmd, sizeof(struct dst_cmd), 0); 437 - dst_state_unlock(st); 438 - 439 - return err; 440 - } 441 - 442 - /* 443 - * Receive block IO from the network. 444 - */ 445 - static int dst_recv_bio(struct dst_state *st, struct bio *bio, 446 - unsigned int total_size) 447 - { 448 - struct bio_vec *bv; 449 - int i, err; 450 - void *data; 451 - unsigned int sz; 452 - 453 - bio_for_each_segment(bv, bio, i) { 454 - sz = min(total_size, bv->bv_len); 455 - 456 - dprintk("%s: bio: %llu/%u, total: %u, len: %u, sz: %u, " 457 - "off: %u.\n", __func__, (u64)bio->bi_sector, 458 - bio->bi_size, total_size, bv->bv_len, sz, 459 - bv->bv_offset); 460 - 461 - data = kmap(bv->bv_page) + bv->bv_offset; 462 - err = dst_data_recv(st, data, sz); 463 - kunmap(bv->bv_page); 464 - 465 - bv->bv_len = sz; 466 - 467 - if (err) 468 - return err; 469 - 470 - total_size -= sz; 471 - if (total_size == 0) 472 - break; 473 - } 474 - 475 - return 0; 476 - } 477 - 478 - /* 479 - * Our block IO has just completed and arrived: get it. 480 - */ 481 - static int dst_process_io_response(struct dst_state *st) 482 - { 483 - struct dst_node *n = st->node; 484 - struct dst_cmd *cmd = st->data; 485 - struct dst_trans *t; 486 - int err = 0; 487 - struct bio *bio; 488 - 489 - mutex_lock(&n->trans_lock); 490 - t = dst_trans_search(n, cmd->id); 491 - mutex_unlock(&n->trans_lock); 492 - 493 - if (!t) 494 - goto err_out_exit; 495 - 496 - bio = t->bio; 497 - 498 - dprintk("%s: bio: %llu/%u, cmd_size: %u, csize: %u, dir: %lu.\n", 499 - __func__, (u64)bio->bi_sector, bio->bi_size, cmd->size, 500 - cmd->csize, bio_data_dir(bio)); 501 - 502 - if (bio_data_dir(bio) == READ) { 503 - if (bio->bi_size != cmd->size - cmd->csize) 504 - goto err_out_exit; 505 - 506 - if (dst_need_crypto(n)) { 507 - err = dst_recv_cdata(st, t->cmd.hash); 508 - if (err) 509 - goto err_out_exit; 510 - } 511 - 512 - err = dst_recv_bio(st, t->bio, bio->bi_size); 513 - if (err) 514 - goto err_out_exit; 515 - 516 - if (dst_need_crypto(n)) 517 - return dst_trans_crypto(t); 518 - } else { 519 - err = -EBADMSG; 520 - if (cmd->size || cmd->csize) 521 - goto err_out_exit; 522 - } 523 - 524 - dst_trans_remove(t); 525 - dst_trans_put(t); 526 - 527 - return 0; 528 - 529 - err_out_exit: 530 - return err; 531 - } 532 - 533 - /* 534 - * Receive crypto data. 535 - */ 536 - int dst_recv_cdata(struct dst_state *st, void *cdata) 537 - { 538 - struct dst_cmd *cmd = st->data; 539 - struct dst_node *n = st->node; 540 - struct dst_crypto_ctl *c = &n->crypto; 541 - int err; 542 - 543 - if (cmd->csize != c->crypto_attached_size) { 544 - dprintk("%s: cmd: cmd: %u, sector: %llu, size: %u, " 545 - "csize: %u != digest size %u.\n", 546 - __func__, cmd->cmd, cmd->sector, cmd->size, 547 - cmd->csize, c->crypto_attached_size); 548 - err = -EINVAL; 549 - goto err_out_exit; 550 - } 551 - 552 - err = dst_data_recv(st, cdata, cmd->csize); 553 - if (err) 554 - goto err_out_exit; 555 - 556 - cmd->size -= cmd->csize; 557 - return 0; 558 - 559 - err_out_exit: 560 - return err; 561 - } 562 - 563 - /* 564 - * Receive the command and start its processing. 565 - */ 566 - static int dst_recv_processing(struct dst_state *st) 567 - { 568 - int err = -EINTR; 569 - struct dst_cmd *cmd = st->data; 570 - 571 - /* 572 - * If socket will be reset after this statement, then 573 - * dst_data_recv() will just fail and loop will 574 - * start again, so it can be done without any locks. 575 - * 576 - * st->read_socket is needed to prevents state machine 577 - * breaking between this data reading and subsequent one 578 - * in protocol specific functions during connection reset. 579 - * In case of reset we have to read next command and do 580 - * not expect data for old command to magically appear in 581 - * new connection. 582 - */ 583 - st->read_socket = st->socket; 584 - err = dst_data_recv(st, cmd, sizeof(struct dst_cmd)); 585 - if (err) 586 - goto out_exit; 587 - 588 - dst_convert_cmd(cmd); 589 - 590 - dprintk("%s: cmd: %u, size: %u, csize: %u, id: %llu, " 591 - "sector: %llu, flags: %llx, rw: %llx.\n", 592 - __func__, cmd->cmd, cmd->size, 593 - cmd->csize, cmd->id, cmd->sector, 594 - cmd->flags, cmd->rw); 595 - 596 - /* 597 - * This should catch protocol breakage and random garbage 598 - * instead of commands. 599 - */ 600 - if (unlikely(cmd->csize > st->size - sizeof(struct dst_cmd))) { 601 - err = -EBADMSG; 602 - goto out_exit; 603 - } 604 - 605 - err = -EPROTO; 606 - switch (cmd->cmd) { 607 - case DST_IO_RESPONSE: 608 - err = dst_process_io_response(st); 609 - break; 610 - case DST_IO: 611 - err = dst_process_io(st); 612 - break; 613 - case DST_CFG: 614 - err = dst_process_cfg(st); 615 - break; 616 - case DST_PING: 617 - err = 0; 618 - break; 619 - default: 620 - break; 621 - } 622 - 623 - out_exit: 624 - return err; 625 - } 626 - 627 - /* 628 - * Receiving thread. For the client node we should try to reconnect, 629 - * for accepted client we just drop the state and expect it to reconnect. 630 - */ 631 - static int dst_recv(void *init_data, void *schedule_data) 632 - { 633 - struct dst_state *st = schedule_data; 634 - struct dst_node *n = init_data; 635 - int err = 0; 636 - 637 - dprintk("%s: start st: %p, n: %p, scan: %lu, need_exit: %d.\n", 638 - __func__, st, n, n->trans_scan_timeout, st->need_exit); 639 - 640 - while (n->trans_scan_timeout && !st->need_exit) { 641 - err = dst_recv_processing(st); 642 - if (err < 0) { 643 - if (!st->ctl.type) 644 - break; 645 - 646 - if (!n->trans_scan_timeout || st->need_exit) 647 - break; 648 - 649 - dst_state_reset(st); 650 - msleep(1000); 651 - } 652 - } 653 - 654 - st->need_exit = 1; 655 - wake_up(&st->thread_wait); 656 - 657 - dprintk("%s: freeing receiving socket st: %p.\n", __func__, st); 658 - dst_state_lock(st); 659 - dst_state_exit_connected(st); 660 - dst_state_unlock(st); 661 - dst_state_put(st); 662 - 663 - dprintk("%s: freed receiving socket st: %p.\n", __func__, st); 664 - 665 - return err; 666 - } 667 - 668 - /* 669 - * Network state dies here and borns couple of lines below. 670 - * This object is the main network state processing engine: 671 - * sending, receiving, reconnections, all network related 672 - * tasks are handled on behalf of the state. 673 - */ 674 - static void dst_state_free(struct dst_state *st) 675 - { 676 - dprintk("%s: st: %p.\n", __func__, st); 677 - if (st->cleanup) 678 - st->cleanup(st); 679 - kfree(st->data); 680 - kfree(st); 681 - } 682 - 683 - struct dst_state *dst_state_alloc(struct dst_node *n) 684 - { 685 - struct dst_state *st; 686 - int err = -ENOMEM; 687 - 688 - st = kzalloc(sizeof(struct dst_state), GFP_KERNEL); 689 - if (!st) 690 - goto err_out_exit; 691 - 692 - st->node = n; 693 - st->need_exit = 0; 694 - 695 - st->size = PAGE_SIZE; 696 - st->data = kmalloc(st->size, GFP_KERNEL); 697 - if (!st->data) 698 - goto err_out_free; 699 - 700 - spin_lock_init(&st->request_lock); 701 - INIT_LIST_HEAD(&st->request_list); 702 - 703 - mutex_init(&st->state_lock); 704 - init_waitqueue_head(&st->thread_wait); 705 - 706 - /* 707 - * One for processing thread, another one for node itself. 708 - */ 709 - atomic_set(&st->refcnt, 2); 710 - 711 - dprintk("%s: st: %p, n: %p.\n", __func__, st, st->node); 712 - 713 - return st; 714 - 715 - err_out_free: 716 - kfree(st); 717 - err_out_exit: 718 - return ERR_PTR(err); 719 - } 720 - 721 - int dst_state_schedule_receiver(struct dst_state *st) 722 - { 723 - return thread_pool_schedule_private(st->node->pool, dst_thread_setup, 724 - dst_recv, st, MAX_SCHEDULE_TIMEOUT, st->node); 725 - } 726 - 727 - /* 728 - * Initialize client's connection to the remote peer: allocate state, 729 - * connect and perform block IO autoconfiguration. 730 - */ 731 - int dst_node_init_connected(struct dst_node *n, struct dst_network_ctl *r) 732 - { 733 - struct dst_state *st; 734 - int err = -ENOMEM; 735 - 736 - st = dst_state_alloc(n); 737 - if (IS_ERR(st)) { 738 - err = PTR_ERR(st); 739 - goto err_out_exit; 740 - } 741 - memcpy(&st->ctl, r, sizeof(struct dst_network_ctl)); 742 - 743 - err = dst_state_init_connected(st); 744 - if (err) 745 - goto err_out_free_data; 746 - 747 - err = dst_request_remote_config(st); 748 - if (err) 749 - goto err_out_exit_connected; 750 - n->state = st; 751 - 752 - err = dst_state_schedule_receiver(st); 753 - if (err) 754 - goto err_out_exit_connected; 755 - 756 - return 0; 757 - 758 - err_out_exit_connected: 759 - dst_state_exit_connected(st); 760 - err_out_free_data: 761 - dst_state_free(st); 762 - err_out_exit: 763 - n->state = NULL; 764 - return err; 765 - } 766 - 767 - void dst_state_put(struct dst_state *st) 768 - { 769 - dprintk("%s: st: %p, refcnt: %d.\n", 770 - __func__, st, atomic_read(&st->refcnt)); 771 - if (atomic_dec_and_test(&st->refcnt)) 772 - dst_state_free(st); 773 - } 774 - 775 - /* 776 - * Send block IO to the network one by one using zero-copy ->sendpage(). 777 - */ 778 - int dst_send_bio(struct dst_state *st, struct dst_cmd *cmd, struct bio *bio) 779 - { 780 - struct bio_vec *bv; 781 - struct dst_crypto_ctl *c = &st->node->crypto; 782 - int err, i = 0; 783 - int flags = MSG_WAITALL; 784 - 785 - err = dst_data_send_header(st->socket, cmd, 786 - sizeof(struct dst_cmd) + c->crypto_attached_size, bio->bi_vcnt); 787 - if (err) 788 - goto err_out_exit; 789 - 790 - bio_for_each_segment(bv, bio, i) { 791 - if (i < bio->bi_vcnt - 1) 792 - flags |= MSG_MORE; 793 - 794 - err = kernel_sendpage(st->socket, bv->bv_page, bv->bv_offset, 795 - bv->bv_len, flags); 796 - if (err <= 0) 797 - goto err_out_exit; 798 - } 799 - 800 - return 0; 801 - 802 - err_out_exit: 803 - dprintk("%s: %d/%d, flags: %x, err: %d.\n", 804 - __func__, i, bio->bi_vcnt, flags, err); 805 - return err; 806 - } 807 - 808 - /* 809 - * Send transaction to the remote peer. 810 - */ 811 - int dst_trans_send(struct dst_trans *t) 812 - { 813 - int err; 814 - struct dst_state *st = t->n->state; 815 - struct bio *bio = t->bio; 816 - 817 - dst_convert_cmd(&t->cmd); 818 - 819 - dst_state_lock(st); 820 - if (!st->socket) { 821 - err = dst_state_init_connected(st); 822 - if (err) 823 - goto err_out_unlock; 824 - } 825 - 826 - if (bio_data_dir(bio) == WRITE) { 827 - err = dst_send_bio(st, &t->cmd, t->bio); 828 - } else { 829 - err = dst_data_send_header(st->socket, &t->cmd, 830 - sizeof(struct dst_cmd), 0); 831 - } 832 - if (err) 833 - goto err_out_reset; 834 - 835 - dst_state_unlock(st); 836 - return 0; 837 - 838 - err_out_reset: 839 - dst_state_reset_nolock(st); 840 - err_out_unlock: 841 - dst_state_unlock(st); 842 - 843 - return err; 844 - }
-348
drivers/staging/dst/thread_pool.c
··· 1 - /* 2 - * 2007+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net> 3 - * All rights reserved. 4 - * 5 - * This program is free software; you can redistribute it and/or modify 6 - * it under the terms of the GNU General Public License as published by 7 - * the Free Software Foundation; either version 2 of the License, or 8 - * (at your option) any later version. 9 - * 10 - * This program is distributed in the hope that it will be useful, 11 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 - * GNU General Public License for more details. 14 - */ 15 - 16 - #include <linux/kernel.h> 17 - #include <linux/dst.h> 18 - #include <linux/kthread.h> 19 - #include <linux/slab.h> 20 - 21 - /* 22 - * Thread pool abstraction allows to schedule a work to be performed 23 - * on behalf of kernel thread. One does not operate with threads itself, 24 - * instead user provides setup and cleanup callbacks for thread pool itself, 25 - * and action and cleanup callbacks for each submitted work. 26 - * 27 - * Each worker has private data initialized at creation time and data, 28 - * provided by user at scheduling time. 29 - * 30 - * When action is being performed, thread can not be used by other users, 31 - * instead they will sleep until there is free thread to pick their work. 32 - */ 33 - struct thread_pool_worker { 34 - struct list_head worker_entry; 35 - 36 - struct task_struct *thread; 37 - 38 - struct thread_pool *pool; 39 - 40 - int error; 41 - int has_data; 42 - int need_exit; 43 - unsigned int id; 44 - 45 - wait_queue_head_t wait; 46 - 47 - void *private; 48 - void *schedule_data; 49 - 50 - int (*action)(void *private, void *schedule_data); 51 - void (*cleanup)(void *private); 52 - }; 53 - 54 - static void thread_pool_exit_worker(struct thread_pool_worker *w) 55 - { 56 - kthread_stop(w->thread); 57 - 58 - w->cleanup(w->private); 59 - kfree(w); 60 - } 61 - 62 - /* 63 - * Called to mark thread as ready and allow users to schedule new work. 64 - */ 65 - static void thread_pool_worker_make_ready(struct thread_pool_worker *w) 66 - { 67 - struct thread_pool *p = w->pool; 68 - 69 - mutex_lock(&p->thread_lock); 70 - 71 - if (!w->need_exit) { 72 - list_move_tail(&w->worker_entry, &p->ready_list); 73 - w->has_data = 0; 74 - mutex_unlock(&p->thread_lock); 75 - 76 - wake_up(&p->wait); 77 - } else { 78 - p->thread_num--; 79 - list_del(&w->worker_entry); 80 - mutex_unlock(&p->thread_lock); 81 - 82 - thread_pool_exit_worker(w); 83 - } 84 - } 85 - 86 - /* 87 - * Thread action loop: waits until there is new work. 88 - */ 89 - static int thread_pool_worker_func(void *data) 90 - { 91 - struct thread_pool_worker *w = data; 92 - 93 - while (!kthread_should_stop()) { 94 - wait_event_interruptible(w->wait, 95 - kthread_should_stop() || w->has_data); 96 - 97 - if (kthread_should_stop()) 98 - break; 99 - 100 - if (!w->has_data) 101 - continue; 102 - 103 - w->action(w->private, w->schedule_data); 104 - thread_pool_worker_make_ready(w); 105 - } 106 - 107 - return 0; 108 - } 109 - 110 - /* 111 - * Remove single worker without specifying which one. 112 - */ 113 - void thread_pool_del_worker(struct thread_pool *p) 114 - { 115 - struct thread_pool_worker *w = NULL; 116 - 117 - while (!w && p->thread_num) { 118 - wait_event(p->wait, !list_empty(&p->ready_list) || 119 - !p->thread_num); 120 - 121 - dprintk("%s: locking list_empty: %d, thread_num: %d.\n", 122 - __func__, list_empty(&p->ready_list), 123 - p->thread_num); 124 - 125 - mutex_lock(&p->thread_lock); 126 - if (!list_empty(&p->ready_list)) { 127 - w = list_first_entry(&p->ready_list, 128 - struct thread_pool_worker, 129 - worker_entry); 130 - 131 - dprintk("%s: deleting w: %p, thread_num: %d, " 132 - "list: %p [%p.%p].\n", __func__, 133 - w, p->thread_num, &p->ready_list, 134 - p->ready_list.prev, p->ready_list.next); 135 - 136 - p->thread_num--; 137 - list_del(&w->worker_entry); 138 - } 139 - mutex_unlock(&p->thread_lock); 140 - } 141 - 142 - if (w) 143 - thread_pool_exit_worker(w); 144 - dprintk("%s: deleted w: %p, thread_num: %d.\n", 145 - __func__, w, p->thread_num); 146 - } 147 - 148 - /* 149 - * Remove a worker with given ID. 150 - */ 151 - void thread_pool_del_worker_id(struct thread_pool *p, unsigned int id) 152 - { 153 - struct thread_pool_worker *w; 154 - int found = 0; 155 - 156 - mutex_lock(&p->thread_lock); 157 - list_for_each_entry(w, &p->ready_list, worker_entry) { 158 - if (w->id == id) { 159 - found = 1; 160 - p->thread_num--; 161 - list_del(&w->worker_entry); 162 - break; 163 - } 164 - } 165 - 166 - if (!found) { 167 - list_for_each_entry(w, &p->active_list, worker_entry) { 168 - if (w->id == id) { 169 - w->need_exit = 1; 170 - break; 171 - } 172 - } 173 - } 174 - mutex_unlock(&p->thread_lock); 175 - 176 - if (found) 177 - thread_pool_exit_worker(w); 178 - } 179 - 180 - /* 181 - * Add new worker thread with given parameters. 182 - * If initialization callback fails, return error. 183 - */ 184 - int thread_pool_add_worker(struct thread_pool *p, 185 - char *name, 186 - unsigned int id, 187 - void *(*init)(void *private), 188 - void (*cleanup)(void *private), 189 - void *private) 190 - { 191 - struct thread_pool_worker *w; 192 - int err = -ENOMEM; 193 - 194 - w = kzalloc(sizeof(struct thread_pool_worker), GFP_KERNEL); 195 - if (!w) 196 - goto err_out_exit; 197 - 198 - w->pool = p; 199 - init_waitqueue_head(&w->wait); 200 - w->cleanup = cleanup; 201 - w->id = id; 202 - 203 - w->thread = kthread_run(thread_pool_worker_func, w, "%s", name); 204 - if (IS_ERR(w->thread)) { 205 - err = PTR_ERR(w->thread); 206 - goto err_out_free; 207 - } 208 - 209 - w->private = init(private); 210 - if (IS_ERR(w->private)) { 211 - err = PTR_ERR(w->private); 212 - goto err_out_stop_thread; 213 - } 214 - 215 - mutex_lock(&p->thread_lock); 216 - list_add_tail(&w->worker_entry, &p->ready_list); 217 - p->thread_num++; 218 - mutex_unlock(&p->thread_lock); 219 - 220 - return 0; 221 - 222 - err_out_stop_thread: 223 - kthread_stop(w->thread); 224 - err_out_free: 225 - kfree(w); 226 - err_out_exit: 227 - return err; 228 - } 229 - 230 - /* 231 - * Destroy the whole pool. 232 - */ 233 - void thread_pool_destroy(struct thread_pool *p) 234 - { 235 - while (p->thread_num) { 236 - dprintk("%s: num: %d.\n", __func__, p->thread_num); 237 - thread_pool_del_worker(p); 238 - } 239 - 240 - kfree(p); 241 - } 242 - 243 - /* 244 - * Create a pool with given number of threads. 245 - * They will have sequential IDs started from zero. 246 - */ 247 - struct thread_pool *thread_pool_create(int num, char *name, 248 - void *(*init)(void *private), 249 - void (*cleanup)(void *private), 250 - void *private) 251 - { 252 - struct thread_pool_worker *w, *tmp; 253 - struct thread_pool *p; 254 - int err = -ENOMEM; 255 - int i; 256 - 257 - p = kzalloc(sizeof(struct thread_pool), GFP_KERNEL); 258 - if (!p) 259 - goto err_out_exit; 260 - 261 - init_waitqueue_head(&p->wait); 262 - mutex_init(&p->thread_lock); 263 - INIT_LIST_HEAD(&p->ready_list); 264 - INIT_LIST_HEAD(&p->active_list); 265 - p->thread_num = 0; 266 - 267 - for (i = 0; i < num; ++i) { 268 - err = thread_pool_add_worker(p, name, i, init, 269 - cleanup, private); 270 - if (err) 271 - goto err_out_free_all; 272 - } 273 - 274 - return p; 275 - 276 - err_out_free_all: 277 - list_for_each_entry_safe(w, tmp, &p->ready_list, worker_entry) { 278 - list_del(&w->worker_entry); 279 - thread_pool_exit_worker(w); 280 - } 281 - kfree(p); 282 - err_out_exit: 283 - return ERR_PTR(err); 284 - } 285 - 286 - /* 287 - * Schedule execution of the action on a given thread, 288 - * provided ID pointer has to match previously stored 289 - * private data. 290 - */ 291 - int thread_pool_schedule_private(struct thread_pool *p, 292 - int (*setup)(void *private, void *data), 293 - int (*action)(void *private, void *data), 294 - void *data, long timeout, void *id) 295 - { 296 - struct thread_pool_worker *w, *tmp, *worker = NULL; 297 - int err = 0; 298 - 299 - while (!worker && !err) { 300 - timeout = wait_event_interruptible_timeout(p->wait, 301 - !list_empty(&p->ready_list), 302 - timeout); 303 - 304 - if (!timeout) { 305 - err = -ETIMEDOUT; 306 - break; 307 - } 308 - 309 - worker = NULL; 310 - mutex_lock(&p->thread_lock); 311 - list_for_each_entry_safe(w, tmp, &p->ready_list, worker_entry) { 312 - if (id && id != w->private) 313 - continue; 314 - 315 - worker = w; 316 - 317 - list_move_tail(&w->worker_entry, &p->active_list); 318 - 319 - err = setup(w->private, data); 320 - if (!err) { 321 - w->schedule_data = data; 322 - w->action = action; 323 - w->has_data = 1; 324 - wake_up(&w->wait); 325 - } else { 326 - list_move_tail(&w->worker_entry, 327 - &p->ready_list); 328 - } 329 - 330 - break; 331 - } 332 - mutex_unlock(&p->thread_lock); 333 - } 334 - 335 - return err; 336 - } 337 - 338 - /* 339 - * Schedule execution on arbitrary thread from the pool. 340 - */ 341 - int thread_pool_schedule(struct thread_pool *p, 342 - int (*setup)(void *private, void *data), 343 - int (*action)(void *private, void *data), 344 - void *data, long timeout) 345 - { 346 - return thread_pool_schedule_private(p, setup, 347 - action, data, timeout, NULL); 348 - }
-337
drivers/staging/dst/trans.c
··· 1 - /* 2 - * 2007+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net> 3 - * All rights reserved. 4 - * 5 - * This program is free software; you can redistribute it and/or modify 6 - * it under the terms of the GNU General Public License as published by 7 - * the Free Software Foundation; either version 2 of the License, or 8 - * (at your option) any later version. 9 - * 10 - * This program is distributed in the hope that it will be useful, 11 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 - * GNU General Public License for more details. 14 - */ 15 - 16 - #include <linux/bio.h> 17 - #include <linux/dst.h> 18 - #include <linux/slab.h> 19 - #include <linux/mempool.h> 20 - 21 - /* 22 - * Transaction memory pool size. 23 - */ 24 - static int dst_mempool_num = 32; 25 - module_param(dst_mempool_num, int, 0644); 26 - 27 - /* 28 - * Transaction tree management. 29 - */ 30 - static inline int dst_trans_cmp(dst_gen_t gen, dst_gen_t new) 31 - { 32 - if (gen < new) 33 - return 1; 34 - if (gen > new) 35 - return -1; 36 - return 0; 37 - } 38 - 39 - struct dst_trans *dst_trans_search(struct dst_node *node, dst_gen_t gen) 40 - { 41 - struct rb_root *root = &node->trans_root; 42 - struct rb_node *n = root->rb_node; 43 - struct dst_trans *t, *ret = NULL; 44 - int cmp; 45 - 46 - while (n) { 47 - t = rb_entry(n, struct dst_trans, trans_entry); 48 - 49 - cmp = dst_trans_cmp(t->gen, gen); 50 - if (cmp < 0) 51 - n = n->rb_left; 52 - else if (cmp > 0) 53 - n = n->rb_right; 54 - else { 55 - ret = t; 56 - break; 57 - } 58 - } 59 - 60 - dprintk("%s: %s transaction: id: %llu.\n", __func__, 61 - (ret) ? "found" : "not found", gen); 62 - 63 - return ret; 64 - } 65 - 66 - static int dst_trans_insert(struct dst_trans *new) 67 - { 68 - struct rb_root *root = &new->n->trans_root; 69 - struct rb_node **n = &root->rb_node, *parent = NULL; 70 - struct dst_trans *ret = NULL, *t; 71 - int cmp; 72 - 73 - while (*n) { 74 - parent = *n; 75 - 76 - t = rb_entry(parent, struct dst_trans, trans_entry); 77 - 78 - cmp = dst_trans_cmp(t->gen, new->gen); 79 - if (cmp < 0) 80 - n = &parent->rb_left; 81 - else if (cmp > 0) 82 - n = &parent->rb_right; 83 - else { 84 - ret = t; 85 - break; 86 - } 87 - } 88 - 89 - new->send_time = jiffies; 90 - if (ret) { 91 - printk(KERN_DEBUG "%s: exist: old: gen: %llu, bio: %llu/%u, " 92 - "send_time: %lu, new: gen: %llu, bio: %llu/%u, " 93 - "send_time: %lu.\n", __func__, 94 - ret->gen, (u64)ret->bio->bi_sector, 95 - ret->bio->bi_size, ret->send_time, 96 - new->gen, (u64)new->bio->bi_sector, 97 - new->bio->bi_size, new->send_time); 98 - return -EEXIST; 99 - } 100 - 101 - rb_link_node(&new->trans_entry, parent, n); 102 - rb_insert_color(&new->trans_entry, root); 103 - 104 - dprintk("%s: inserted: gen: %llu, bio: %llu/%u, send_time: %lu.\n", 105 - __func__, new->gen, (u64)new->bio->bi_sector, 106 - new->bio->bi_size, new->send_time); 107 - 108 - return 0; 109 - } 110 - 111 - int dst_trans_remove_nolock(struct dst_trans *t) 112 - { 113 - struct dst_node *n = t->n; 114 - 115 - if (t->trans_entry.rb_parent_color) { 116 - rb_erase(&t->trans_entry, &n->trans_root); 117 - t->trans_entry.rb_parent_color = 0; 118 - } 119 - return 0; 120 - } 121 - 122 - int dst_trans_remove(struct dst_trans *t) 123 - { 124 - int ret; 125 - struct dst_node *n = t->n; 126 - 127 - mutex_lock(&n->trans_lock); 128 - ret = dst_trans_remove_nolock(t); 129 - mutex_unlock(&n->trans_lock); 130 - 131 - return ret; 132 - } 133 - 134 - /* 135 - * When transaction is completed and there are no more users, 136 - * we complete appriate block IO request with given error status. 137 - */ 138 - void dst_trans_put(struct dst_trans *t) 139 - { 140 - if (atomic_dec_and_test(&t->refcnt)) { 141 - struct bio *bio = t->bio; 142 - 143 - dprintk("%s: completed t: %p, gen: %llu, bio: %p.\n", 144 - __func__, t, t->gen, bio); 145 - 146 - bio_endio(bio, t->error); 147 - bio_put(bio); 148 - 149 - dst_node_put(t->n); 150 - mempool_free(t, t->n->trans_pool); 151 - } 152 - } 153 - 154 - /* 155 - * Process given block IO request: allocate transaction, insert it into the tree 156 - * and send/schedule crypto processing. 157 - */ 158 - int dst_process_bio(struct dst_node *n, struct bio *bio) 159 - { 160 - struct dst_trans *t; 161 - int err = -ENOMEM; 162 - 163 - t = mempool_alloc(n->trans_pool, GFP_NOFS); 164 - if (!t) 165 - goto err_out_exit; 166 - 167 - t->n = dst_node_get(n); 168 - t->bio = bio; 169 - t->error = 0; 170 - t->retries = 0; 171 - atomic_set(&t->refcnt, 1); 172 - t->gen = atomic_long_inc_return(&n->gen); 173 - 174 - t->enc = bio_data_dir(bio); 175 - dst_bio_to_cmd(bio, &t->cmd, DST_IO, t->gen); 176 - 177 - mutex_lock(&n->trans_lock); 178 - err = dst_trans_insert(t); 179 - mutex_unlock(&n->trans_lock); 180 - if (err) 181 - goto err_out_free; 182 - 183 - dprintk("%s: gen: %llu, bio: %llu/%u, dir/enc: %d, need_crypto: %d.\n", 184 - __func__, t->gen, (u64)bio->bi_sector, 185 - bio->bi_size, t->enc, dst_need_crypto(n)); 186 - 187 - if (dst_need_crypto(n) && t->enc) 188 - dst_trans_crypto(t); 189 - else 190 - dst_trans_send(t); 191 - 192 - return 0; 193 - 194 - err_out_free: 195 - dst_node_put(n); 196 - mempool_free(t, n->trans_pool); 197 - err_out_exit: 198 - bio_endio(bio, err); 199 - bio_put(bio); 200 - return err; 201 - } 202 - 203 - /* 204 - * Scan for timeout/stale transactions. 205 - * Each transaction is being resent multiple times before error completion. 206 - */ 207 - static void dst_trans_scan(struct work_struct *work) 208 - { 209 - struct dst_node *n = container_of(work, struct dst_node, 210 - trans_work.work); 211 - struct rb_node *rb_node; 212 - struct dst_trans *t; 213 - unsigned long timeout = n->trans_scan_timeout; 214 - int num = 10 * n->trans_max_retries; 215 - 216 - mutex_lock(&n->trans_lock); 217 - 218 - for (rb_node = rb_first(&n->trans_root); rb_node; ) { 219 - t = rb_entry(rb_node, struct dst_trans, trans_entry); 220 - 221 - if (timeout && time_after(t->send_time + timeout, jiffies) 222 - && t->retries == 0) 223 - break; 224 - #if 0 225 - dprintk("%s: t: %p, gen: %llu, n: %s, retries: %u, max: %u.\n", 226 - __func__, t, t->gen, n->name, 227 - t->retries, n->trans_max_retries); 228 - #endif 229 - if (--num == 0) 230 - break; 231 - 232 - dst_trans_get(t); 233 - 234 - rb_node = rb_next(rb_node); 235 - 236 - if (timeout && (++t->retries < n->trans_max_retries)) { 237 - dst_trans_send(t); 238 - } else { 239 - t->error = -ETIMEDOUT; 240 - dst_trans_remove_nolock(t); 241 - dst_trans_put(t); 242 - } 243 - 244 - dst_trans_put(t); 245 - } 246 - 247 - mutex_unlock(&n->trans_lock); 248 - 249 - /* 250 - * If no timeout specified then system is in the middle of exiting 251 - * process, so no need to reschedule scanning process again. 252 - */ 253 - if (timeout) { 254 - if (!num) 255 - timeout = HZ; 256 - schedule_delayed_work(&n->trans_work, timeout); 257 - } 258 - } 259 - 260 - /* 261 - * Flush all transactions and mark them as timed out. 262 - * Destroy transaction pools. 263 - */ 264 - void dst_node_trans_exit(struct dst_node *n) 265 - { 266 - struct dst_trans *t; 267 - struct rb_node *rb_node; 268 - 269 - if (!n->trans_cache) 270 - return; 271 - 272 - dprintk("%s: n: %p, cancelling the work.\n", __func__, n); 273 - cancel_delayed_work_sync(&n->trans_work); 274 - flush_scheduled_work(); 275 - dprintk("%s: n: %p, work has been cancelled.\n", __func__, n); 276 - 277 - for (rb_node = rb_first(&n->trans_root); rb_node; ) { 278 - t = rb_entry(rb_node, struct dst_trans, trans_entry); 279 - 280 - dprintk("%s: t: %p, gen: %llu, n: %s.\n", 281 - __func__, t, t->gen, n->name); 282 - 283 - rb_node = rb_next(rb_node); 284 - 285 - t->error = -ETIMEDOUT; 286 - dst_trans_remove_nolock(t); 287 - dst_trans_put(t); 288 - } 289 - 290 - mempool_destroy(n->trans_pool); 291 - kmem_cache_destroy(n->trans_cache); 292 - } 293 - 294 - /* 295 - * Initialize transaction storage for given node. 296 - * Transaction stores not only control information, 297 - * but also network command and crypto data (if needed) 298 - * to reduce number of allocations. Thus transaction size 299 - * differs from node to node. 300 - */ 301 - int dst_node_trans_init(struct dst_node *n, unsigned int size) 302 - { 303 - /* 304 - * We need this, since node with given name can be dropped from the 305 - * hash table, but be still alive, so subsequent creation of the node 306 - * with the same name may collide with existing cache name. 307 - */ 308 - 309 - snprintf(n->cache_name, sizeof(n->cache_name), "%s-%p", n->name, n); 310 - 311 - n->trans_cache = kmem_cache_create(n->cache_name, 312 - size + n->crypto.crypto_attached_size, 313 - 0, 0, NULL); 314 - if (!n->trans_cache) 315 - goto err_out_exit; 316 - 317 - n->trans_pool = mempool_create_slab_pool(dst_mempool_num, 318 - n->trans_cache); 319 - if (!n->trans_pool) 320 - goto err_out_cache_destroy; 321 - 322 - mutex_init(&n->trans_lock); 323 - n->trans_root = RB_ROOT; 324 - 325 - INIT_DELAYED_WORK(&n->trans_work, dst_trans_scan); 326 - schedule_delayed_work(&n->trans_work, n->trans_scan_timeout); 327 - 328 - dprintk("%s: n: %p, size: %u, crypto: %u.\n", 329 - __func__, n, size, n->crypto.crypto_attached_size); 330 - 331 - return 0; 332 - 333 - err_out_cache_destroy: 334 - kmem_cache_destroy(n->trans_cache); 335 - err_out_exit: 336 - return -ENOMEM; 337 - }
+1 -1
drivers/staging/panel/Kconfig
··· 47 47 config PANEL_KEYPAD 48 48 depends on PANEL && PANEL_PROFILE="0" 49 49 int "Keypad type (0=none, 1=old 6 keys, 2=new 6 keys, 3=Nexcom 4 keys)" 50 - range 0 4 50 + range 0 3 51 51 default 0 52 52 ---help--- 53 53 This enables and configures a keypad connected to the parallel port.
+1 -1
drivers/staging/panel/panel.c
··· 378 378 379 379 #ifdef CONFIG_PANEL_LCD_CHARSET 380 380 #undef DEFAULT_LCD_CHARSET 381 - #define DEFAULT_LCD_CHARSET 381 + #define DEFAULT_LCD_CHARSET CONFIG_PANEL_LCD_CHARSET 382 382 #endif 383 383 384 384 #endif /* DEFAULT_PROFILE == 0 */
-1
drivers/staging/ramzswap/TODO
··· 1 1 TODO: 2 2 - Add support for swap notifiers 3 - - Remove CONFIG_ARM hack 4 3 5 4 Please send patches to Greg Kroah-Hartman <greg@kroah.com> and 6 5 Nitin Gupta <ngupta@vflare.org>
+3 -25
drivers/staging/ramzswap/ramzswap_drv.c
··· 222 222 return ret; 223 223 } 224 224 225 - static void ramzswap_flush_dcache_page(struct page *page) 226 - { 227 - #ifdef CONFIG_ARM 228 - int flag = 0; 229 - /* 230 - * Ugly hack to get flush_dcache_page() work on ARM. 231 - * page_mapping(page) == NULL after clearing this swap cache flag. 232 - * Without clearing this flag, flush_dcache_page() will simply set 233 - * "PG_dcache_dirty" bit and return. 234 - */ 235 - if (PageSwapCache(page)) { 236 - flag = 1; 237 - ClearPageSwapCache(page); 238 - } 239 - #endif 240 - flush_dcache_page(page); 241 - #ifdef CONFIG_ARM 242 - if (flag) 243 - SetPageSwapCache(page); 244 - #endif 245 - } 246 - 247 225 void ramzswap_ioctl_get_stats(struct ramzswap *rzs, 248 226 struct ramzswap_ioctl_stats *s) 249 227 { ··· 633 655 memset(user_mem, 0, PAGE_SIZE); 634 656 kunmap_atomic(user_mem, KM_USER0); 635 657 636 - ramzswap_flush_dcache_page(page); 658 + flush_dcache_page(page); 637 659 638 660 set_bit(BIO_UPTODATE, &bio->bi_flags); 639 661 bio_endio(bio, 0); ··· 657 679 kunmap_atomic(user_mem, KM_USER0); 658 680 kunmap_atomic(cmem, KM_USER1); 659 681 660 - ramzswap_flush_dcache_page(page); 682 + flush_dcache_page(page); 661 683 662 684 set_bit(BIO_UPTODATE, &bio->bi_flags); 663 685 bio_endio(bio, 0); ··· 757 779 goto out; 758 780 } 759 781 760 - ramzswap_flush_dcache_page(page); 782 + flush_dcache_page(page); 761 783 762 784 set_bit(BIO_UPTODATE, &bio->bi_flags); 763 785 bio_endio(bio, 0);
+5 -5
drivers/staging/rtl8187se/ieee80211/ieee80211.h
··· 1318 1318 struct sk_buff *frag, 1319 1319 int hdr_len); 1320 1320 1321 - extern int ieee80211_xmit(struct sk_buff *skb, 1321 + extern int ieee80211_rtl_xmit(struct sk_buff *skb, 1322 1322 struct net_device *dev); 1323 1323 extern void ieee80211_txb_free(struct ieee80211_txb *); 1324 1324 1325 1325 1326 1326 /* ieee80211_rx.c */ 1327 - extern int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, 1327 + extern int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb, 1328 1328 struct ieee80211_rx_stats *rx_stats); 1329 1329 extern void ieee80211_rx_mgt(struct ieee80211_device *ieee, 1330 1330 struct ieee80211_hdr_4addr *header, ··· 1376 1376 extern void ieee80211_softmac_start_protocol(struct ieee80211_device *ieee); 1377 1377 extern void ieee80211_softmac_stop_protocol(struct ieee80211_device *ieee); 1378 1378 extern void ieee80211_reset_queue(struct ieee80211_device *ieee); 1379 - extern void ieee80211_wake_queue(struct ieee80211_device *ieee); 1380 - extern void ieee80211_stop_queue(struct ieee80211_device *ieee); 1379 + extern void ieee80211_rtl_wake_queue(struct ieee80211_device *ieee); 1380 + extern void ieee80211_rtl_stop_queue(struct ieee80211_device *ieee); 1381 1381 extern struct sk_buff *ieee80211_get_beacon(struct ieee80211_device *ieee); 1382 1382 extern void ieee80211_start_send_beacons(struct ieee80211_device *ieee); 1383 1383 extern void ieee80211_stop_send_beacons(struct ieee80211_device *ieee); ··· 1385 1385 extern void notify_wx_assoc_event(struct ieee80211_device *ieee); 1386 1386 extern void ieee80211_ps_tx_ack(struct ieee80211_device *ieee, short success); 1387 1387 extern void SendDisassociation(struct ieee80211_device *ieee,u8* asSta,u8 asRsn); 1388 - extern void ieee80211_start_scan(struct ieee80211_device *ieee); 1388 + extern void ieee80211_rtl_start_scan(struct ieee80211_device *ieee); 1389 1389 1390 1390 //Add for RF power on power off by lizhaoming 080512 1391 1391 extern void SendDisassociation(struct ieee80211_device *ieee,
+1 -1
drivers/staging/rtl8187se/ieee80211/ieee80211_rx.c
··· 469 469 /* All received frames are sent to this function. @skb contains the frame in 470 470 * IEEE 802.11 format, i.e., in the format it was sent over air. 471 471 * This function is called only as a tasklet (software IRQ). */ 472 - int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, 472 + int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb, 473 473 struct ieee80211_rx_stats *rx_stats) 474 474 { 475 475 struct net_device *dev = ieee->dev;
+7 -7
drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c
··· 689 689 } 690 690 691 691 /* called with ieee->lock held */ 692 - void ieee80211_start_scan(struct ieee80211_device *ieee) 692 + void ieee80211_rtl_start_scan(struct ieee80211_device *ieee) 693 693 { 694 694 if(IS_DOT11D_ENABLE(ieee) ) 695 695 { ··· 1196 1196 } 1197 1197 } 1198 1198 1199 - void ieee80211_auth_challenge(struct ieee80211_device *ieee, u8 *challenge, int chlen) 1199 + void ieee80211_rtl_auth_challenge(struct ieee80211_device *ieee, u8 *challenge, int chlen) 1200 1200 { 1201 1201 u8 *c; 1202 1202 struct sk_buff *skb; ··· 1898 1898 1899 1899 ieee80211_associate_step2(ieee); 1900 1900 }else{ 1901 - ieee80211_auth_challenge(ieee, challenge, chlen); 1901 + ieee80211_rtl_auth_challenge(ieee, challenge, chlen); 1902 1902 } 1903 1903 }else{ 1904 1904 ieee->softmac_stats.rx_auth_rs_err++; ··· 2047 2047 2048 2048 } 2049 2049 2050 - void ieee80211_wake_queue(struct ieee80211_device *ieee) 2050 + void ieee80211_rtl_wake_queue(struct ieee80211_device *ieee) 2051 2051 { 2052 2052 2053 2053 unsigned long flags; ··· 2089 2089 } 2090 2090 2091 2091 2092 - void ieee80211_stop_queue(struct ieee80211_device *ieee) 2092 + void ieee80211_rtl_stop_queue(struct ieee80211_device *ieee) 2093 2093 { 2094 2094 //unsigned long flags; 2095 2095 //spin_lock_irqsave(&ieee->lock,flags); ··· 2301 2301 //#else 2302 2302 if (ieee->state == IEEE80211_NOLINK){ 2303 2303 ieee->actscanning = true; 2304 - ieee80211_start_scan(ieee); 2304 + ieee80211_rtl_start_scan(ieee); 2305 2305 } 2306 2306 //#endif 2307 2307 spin_unlock_irqrestore(&ieee->lock, flags); ··· 2357 2357 if(ieee->state == IEEE80211_NOLINK){ 2358 2358 ieee->beinretry = false; 2359 2359 ieee->actscanning = true; 2360 - ieee80211_start_scan(ieee); 2360 + ieee80211_rtl_start_scan(ieee); 2361 2361 } 2362 2362 //YJ,add,080828, notify os here 2363 2363 if(ieee->state == IEEE80211_NOLINK)
+1 -1
drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c
··· 304 304 } 305 305 306 306 /* SKBs are added to the ieee->tx_queue. */ 307 - int ieee80211_xmit(struct sk_buff *skb, 307 + int ieee80211_rtl_xmit(struct sk_buff *skb, 308 308 struct net_device *dev) 309 309 { 310 310 struct ieee80211_device *ieee = netdev_priv(dev);
+5 -5
drivers/staging/rtl8187se/r8180_core.c
··· 1811 1811 if(priv->rx_skb->len > 4) 1812 1812 skb_trim(priv->rx_skb,priv->rx_skb->len-4); 1813 1813 #ifndef RX_DONT_PASS_UL 1814 - if(!ieee80211_rx(priv->ieee80211, 1814 + if(!ieee80211_rtl_rx(priv->ieee80211, 1815 1815 priv->rx_skb, &stats)){ 1816 1816 #endif // RX_DONT_PASS_UL 1817 1817 ··· 1917 1917 if (!check_nic_enought_desc(dev, priority)){ 1918 1918 DMESGW("Error: no descriptor left by previous TX (avail %d) ", 1919 1919 get_curr_tx_free_desc(dev, priority)); 1920 - ieee80211_stop_queue(priv->ieee80211); 1920 + ieee80211_rtl_stop_queue(priv->ieee80211); 1921 1921 } 1922 1922 rtl8180_tx(dev, skb->data, skb->len, priority, morefrag,0,rate); 1923 1923 if (!check_nic_enought_desc(dev, priority)) 1924 - ieee80211_stop_queue(priv->ieee80211); 1924 + ieee80211_rtl_stop_queue(priv->ieee80211); 1925 1925 1926 1926 spin_unlock_irqrestore(&priv->tx_lock,flags); 1927 1927 } ··· 3680 3680 .ndo_set_mac_address = r8180_set_mac_adr, 3681 3681 .ndo_validate_addr = eth_validate_addr, 3682 3682 .ndo_change_mtu = eth_change_mtu, 3683 - .ndo_start_xmit = ieee80211_xmit, 3683 + .ndo_start_xmit = ieee80211_rtl_xmit, 3684 3684 }; 3685 3685 3686 3686 static int __devinit rtl8180_pci_probe(struct pci_dev *pdev, ··· 3900 3900 spin_unlock_irqrestore(&priv->tx_lock,flags); 3901 3901 3902 3902 if(enough_desc) 3903 - ieee80211_wake_queue(priv->ieee80211); 3903 + ieee80211_rtl_wake_queue(priv->ieee80211); 3904 3904 } 3905 3905 3906 3906 void rtl8180_tx_isr(struct net_device *dev, int pri,short error)
+1 -1
drivers/staging/rtl8187se/r8180_wx.c
··· 377 377 // queue_work(priv->ieee80211->wq, &priv->ieee80211->wx_sync_scan_wq); 378 378 //printk("start scan============================>\n"); 379 379 ieee80211_softmac_ips_scan_syncro(priv->ieee80211); 380 - //ieee80211_start_scan(priv->ieee80211); 380 + //ieee80211_rtl_start_scan(priv->ieee80211); 381 381 /* intentionally forget to up sem */ 382 382 // up(&priv->ieee80211->wx_sem); 383 383 ret = 0;
+6 -6
drivers/staging/rtl8192e/ieee80211.h
··· 303 303 #define ieee80211_rx_mgt ieee80211_rx_mgt_rsl 304 304 305 305 #define ieee80211_get_beacon ieee80211_get_beacon_rsl 306 - #define ieee80211_wake_queue ieee80211_wake_queue_rsl 307 - #define ieee80211_stop_queue ieee80211_stop_queue_rsl 306 + #define ieee80211_rtl_wake_queue ieee80211_rtl_wake_queue_rsl 307 + #define ieee80211_rtl_stop_queue ieee80211_rtl_stop_queue_rsl 308 308 #define ieee80211_reset_queue ieee80211_reset_queue_rsl 309 309 #define ieee80211_softmac_stop_protocol ieee80211_softmac_stop_protocol_rsl 310 310 #define ieee80211_softmac_start_protocol ieee80211_softmac_start_protocol_rsl ··· 2435 2435 struct sk_buff *frag, 2436 2436 int hdr_len); 2437 2437 2438 - extern int ieee80211_xmit(struct sk_buff *skb, 2438 + extern int ieee80211_rtl_xmit(struct sk_buff *skb, 2439 2439 struct net_device *dev); 2440 2440 extern void ieee80211_txb_free(struct ieee80211_txb *); 2441 2441 2442 2442 2443 2443 /* ieee80211_rx.c */ 2444 - extern int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, 2444 + extern int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb, 2445 2445 struct ieee80211_rx_stats *rx_stats); 2446 2446 extern void ieee80211_rx_mgt(struct ieee80211_device *ieee, 2447 2447 struct ieee80211_hdr_4addr *header, ··· 2502 2502 extern void ieee80211_softmac_start_protocol(struct ieee80211_device *ieee); 2503 2503 extern void ieee80211_softmac_stop_protocol(struct ieee80211_device *ieee); 2504 2504 extern void ieee80211_reset_queue(struct ieee80211_device *ieee); 2505 - extern void ieee80211_wake_queue(struct ieee80211_device *ieee); 2506 - extern void ieee80211_stop_queue(struct ieee80211_device *ieee); 2505 + extern void ieee80211_rtl_wake_queue(struct ieee80211_device *ieee); 2506 + extern void ieee80211_rtl_stop_queue(struct ieee80211_device *ieee); 2507 2507 extern struct sk_buff *ieee80211_get_beacon(struct ieee80211_device *ieee); 2508 2508 extern void ieee80211_start_send_beacons(struct ieee80211_device *ieee); 2509 2509 extern void ieee80211_stop_send_beacons(struct ieee80211_device *ieee);
+6 -6
drivers/staging/rtl8192e/ieee80211/ieee80211.h
··· 333 333 #define ieee80211_rx_mgt ieee80211_rx_mgt_rsl 334 334 335 335 #define ieee80211_get_beacon ieee80211_get_beacon_rsl 336 - #define ieee80211_wake_queue ieee80211_wake_queue_rsl 337 - #define ieee80211_stop_queue ieee80211_stop_queue_rsl 336 + #define ieee80211_rtl_wake_queue ieee80211_rtl_wake_queue_rsl 337 + #define ieee80211_rtl_stop_queue ieee80211_rtl_stop_queue_rsl 338 338 #define ieee80211_reset_queue ieee80211_reset_queue_rsl 339 339 #define ieee80211_softmac_stop_protocol ieee80211_softmac_stop_protocol_rsl 340 340 #define ieee80211_softmac_start_protocol ieee80211_softmac_start_protocol_rsl ··· 2546 2546 struct sk_buff *frag, 2547 2547 int hdr_len); 2548 2548 2549 - extern int ieee80211_xmit(struct sk_buff *skb, 2549 + extern int ieee80211_rtl_xmit(struct sk_buff *skb, 2550 2550 struct net_device *dev); 2551 2551 extern void ieee80211_txb_free(struct ieee80211_txb *); 2552 2552 2553 2553 2554 2554 /* ieee80211_rx.c */ 2555 - extern int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, 2555 + extern int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb, 2556 2556 struct ieee80211_rx_stats *rx_stats); 2557 2557 extern void ieee80211_rx_mgt(struct ieee80211_device *ieee, 2558 2558 struct ieee80211_hdr_4addr *header, ··· 2613 2613 extern void ieee80211_softmac_start_protocol(struct ieee80211_device *ieee); 2614 2614 extern void ieee80211_softmac_stop_protocol(struct ieee80211_device *ieee); 2615 2615 extern void ieee80211_reset_queue(struct ieee80211_device *ieee); 2616 - extern void ieee80211_wake_queue(struct ieee80211_device *ieee); 2617 - extern void ieee80211_stop_queue(struct ieee80211_device *ieee); 2616 + extern void ieee80211_rtl_wake_queue(struct ieee80211_device *ieee); 2617 + extern void ieee80211_rtl_stop_queue(struct ieee80211_device *ieee); 2618 2618 extern struct sk_buff *ieee80211_get_beacon(struct ieee80211_device *ieee); 2619 2619 extern void ieee80211_start_send_beacons(struct ieee80211_device *ieee); 2620 2620 extern void ieee80211_stop_send_beacons(struct ieee80211_device *ieee);
+5 -5
drivers/staging/rtl8192e/ieee80211/ieee80211_module.c
··· 119 119 ieee = (struct ieee80211_device *)dev->priv; 120 120 #endif 121 121 #if 0 122 - dev->hard_start_xmit = ieee80211_xmit; 122 + dev->hard_start_xmit = ieee80211_rtl_xmit; 123 123 #endif 124 124 125 125 memset(ieee, 0, sizeof(struct ieee80211_device)+sizeof_priv); ··· 333 333 extern int ieee80211_crypto_wep_init(void); 334 334 extern void ieee80211_crypto_wep_exit(void); 335 335 336 - int __init ieee80211_init(void) 336 + int __init ieee80211_rtl_init(void) 337 337 { 338 338 struct proc_dir_entry *e; 339 339 int retval; ··· 389 389 return 0; 390 390 } 391 391 392 - void __exit ieee80211_exit(void) 392 + void __exit ieee80211_rtl_exit(void) 393 393 { 394 394 if (ieee80211_proc) { 395 395 remove_proc_entry("debug_level", ieee80211_proc); ··· 412 412 MODULE_PARM_DESC(debug, "debug output mask"); 413 413 414 414 415 - //module_exit(ieee80211_exit); 416 - //module_init(ieee80211_init); 415 + //module_exit(ieee80211_rtl_exit); 416 + //module_init(ieee80211_rtl_init); 417 417 #endif 418 418 #endif 419 419
+1 -1
drivers/staging/rtl8192e/ieee80211/ieee80211_rx.c
··· 923 923 /* All received frames are sent to this function. @skb contains the frame in 924 924 * IEEE 802.11 format, i.e., in the format it was sent over air. 925 925 * This function is called only as a tasklet (software IRQ). */ 926 - int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, 926 + int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb, 927 927 struct ieee80211_rx_stats *rx_stats) 928 928 { 929 929 struct net_device *dev = ieee->dev;
+12 -12
drivers/staging/rtl8192e/ieee80211/ieee80211_softmac.c
··· 684 684 } 685 685 686 686 /* called with ieee->lock held */ 687 - void ieee80211_start_scan(struct ieee80211_device *ieee) 687 + void ieee80211_rtl_start_scan(struct ieee80211_device *ieee) 688 688 { 689 689 #ifdef ENABLE_DOT11D 690 690 if(IS_DOT11D_ENABLE(ieee) ) ··· 1430 1430 } 1431 1431 } 1432 1432 1433 - void ieee80211_auth_challenge(struct ieee80211_device *ieee, u8 *challenge, int chlen) 1433 + void ieee80211_rtl_auth_challenge(struct ieee80211_device *ieee, u8 *challenge, int chlen) 1434 1434 { 1435 1435 u8 *c; 1436 1436 struct sk_buff *skb; ··· 2262 2262 2263 2263 ieee80211_associate_step2(ieee); 2264 2264 }else{ 2265 - ieee80211_auth_challenge(ieee, challenge, chlen); 2265 + ieee80211_rtl_auth_challenge(ieee, challenge, chlen); 2266 2266 } 2267 2267 }else{ 2268 2268 ieee->softmac_stats.rx_auth_rs_err++; ··· 2376 2376 * to check it any more. 2377 2377 * */ 2378 2378 //printk("error:no descriptor left@queue_index %d\n", queue_index); 2379 - //ieee80211_stop_queue(ieee); 2379 + //ieee80211_rtl_stop_queue(ieee); 2380 2380 #ifdef USB_TX_DRIVER_AGGREGATION_ENABLE 2381 2381 skb_queue_tail(&ieee->skb_drv_aggQ[queue_index], txb->fragments[i]); 2382 2382 #else ··· 2440 2440 2441 2441 } 2442 2442 2443 - void ieee80211_wake_queue(struct ieee80211_device *ieee) 2443 + void ieee80211_rtl_wake_queue(struct ieee80211_device *ieee) 2444 2444 { 2445 2445 2446 2446 unsigned long flags; ··· 2481 2481 } 2482 2482 2483 2483 2484 - void ieee80211_stop_queue(struct ieee80211_device *ieee) 2484 + void ieee80211_rtl_stop_queue(struct ieee80211_device *ieee) 2485 2485 { 2486 2486 //unsigned long flags; 2487 2487 //spin_lock_irqsave(&ieee->lock,flags); ··· 2706 2706 2707 2707 if (ieee->state == IEEE80211_NOLINK){ 2708 2708 ieee->actscanning = true; 2709 - ieee80211_start_scan(ieee); 2709 + ieee80211_rtl_start_scan(ieee); 2710 2710 } 2711 2711 spin_unlock_irqrestore(&ieee->lock, flags); 2712 2712 } ··· 2775 2775 { 2776 2776 ieee->is_roaming= false; 2777 2777 ieee->actscanning = true; 2778 - ieee80211_start_scan(ieee); 2778 + ieee80211_rtl_start_scan(ieee); 2779 2779 } 2780 2780 spin_unlock_irqrestore(&ieee->lock, flags); 2781 2781 ··· 3497 3497 3498 3498 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) 3499 3499 //EXPORT_SYMBOL(ieee80211_get_beacon); 3500 - //EXPORT_SYMBOL(ieee80211_wake_queue); 3501 - //EXPORT_SYMBOL(ieee80211_stop_queue); 3500 + //EXPORT_SYMBOL(ieee80211_rtl_wake_queue); 3501 + //EXPORT_SYMBOL(ieee80211_rtl_stop_queue); 3502 3502 //EXPORT_SYMBOL(ieee80211_reset_queue); 3503 3503 //EXPORT_SYMBOL(ieee80211_softmac_stop_protocol); 3504 3504 //EXPORT_SYMBOL(ieee80211_softmac_start_protocol); ··· 3518 3518 //EXPORT_SYMBOL(ieee80211_start_scan_syncro); 3519 3519 #else 3520 3520 EXPORT_SYMBOL_NOVERS(ieee80211_get_beacon); 3521 - EXPORT_SYMBOL_NOVERS(ieee80211_wake_queue); 3522 - EXPORT_SYMBOL_NOVERS(ieee80211_stop_queue); 3521 + EXPORT_SYMBOL_NOVERS(ieee80211_rtl_wake_queue); 3522 + EXPORT_SYMBOL_NOVERS(ieee80211_rtl_stop_queue); 3523 3523 EXPORT_SYMBOL_NOVERS(ieee80211_reset_queue); 3524 3524 EXPORT_SYMBOL_NOVERS(ieee80211_softmac_stop_protocol); 3525 3525 EXPORT_SYMBOL_NOVERS(ieee80211_softmac_start_protocol);
+1 -1
drivers/staging/rtl8192e/ieee80211/ieee80211_tx.c
··· 604 604 } 605 605 } 606 606 607 - int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) 607 + int ieee80211_rtl_xmit(struct sk_buff *skb, struct net_device *dev) 608 608 { 609 609 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)) 610 610 struct ieee80211_device *ieee = netdev_priv(dev);
+1 -1
drivers/staging/rtl8192e/ieee80211/ieee80211_wx.c
··· 976 976 { 977 977 if (len != ie[1]+2) 978 978 { 979 - printk("len:%d, ie:%d\n", len, ie[1]); 979 + printk("len:%zu, ie:%d\n", len, ie[1]); 980 980 return -EINVAL; 981 981 } 982 982 buf = kmalloc(len, GFP_KERNEL);
+3 -3
drivers/staging/rtl8192e/ieee80211/rtl819x_BAProc.c
··· 382 382 383 383 if (skb->len < sizeof( struct ieee80211_hdr_3addr) + 9) 384 384 { 385 - IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in BAREQ(%d / %d)\n", skb->len, (sizeof( struct ieee80211_hdr_3addr) + 9)); 385 + IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in BAREQ(%d / %zu)\n", skb->len, (sizeof( struct ieee80211_hdr_3addr) + 9)); 386 386 return -1; 387 387 } 388 388 ··· 481 481 482 482 if (skb->len < sizeof( struct ieee80211_hdr_3addr) + 9) 483 483 { 484 - IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in BARSP(%d / %d)\n", skb->len, (sizeof( struct ieee80211_hdr_3addr) + 9)); 484 + IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in BARSP(%d / %zu)\n", skb->len, (sizeof( struct ieee80211_hdr_3addr) + 9)); 485 485 return -1; 486 486 } 487 487 rsp = ( struct ieee80211_hdr_3addr*)skb->data; ··· 611 611 612 612 if (skb->len < sizeof( struct ieee80211_hdr_3addr) + 6) 613 613 { 614 - IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in DELBA(%d / %d)\n", skb->len, (sizeof( struct ieee80211_hdr_3addr) + 6)); 614 + IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in DELBA(%d / %zu)\n", skb->len, (sizeof( struct ieee80211_hdr_3addr) + 6)); 615 615 return -1; 616 616 } 617 617
+7 -7
drivers/staging/rtl8192e/r8192E_core.c
··· 5795 5795 stats.fragoffset = 0; 5796 5796 stats.ntotalfrag = 1; 5797 5797 5798 - if(!ieee80211_rx(priv->ieee80211, skb, &stats)){ 5798 + if(!ieee80211_rtl_rx(priv->ieee80211, skb, &stats)){ 5799 5799 dev_kfree_skb_any(skb); 5800 5800 } else { 5801 5801 priv->stats.rxok++; ··· 5837 5837 .ndo_do_ioctl = rtl8192_ioctl, 5838 5838 .ndo_set_multicast_list = r8192_set_multicast, 5839 5839 .ndo_set_mac_address = r8192_set_mac_adr, 5840 - .ndo_start_xmit = ieee80211_xmit, 5840 + .ndo_start_xmit = ieee80211_rtl_xmit, 5841 5841 }; 5842 5842 5843 5843 /**************************************************************************** ··· 6121 6121 RT_TRACE(COMP_DOWN, "wlan driver removed\n"); 6122 6122 } 6123 6123 6124 - extern int ieee80211_init(void); 6125 - extern void ieee80211_exit(void); 6124 + extern int ieee80211_rtl_init(void); 6125 + extern void ieee80211_rtl_exit(void); 6126 6126 6127 6127 static int __init rtl8192_pci_module_init(void) 6128 6128 { 6129 6129 int retval; 6130 6130 6131 - retval = ieee80211_init(); 6131 + retval = ieee80211_rtl_init(); 6132 6132 if (retval) 6133 6133 return retval; 6134 6134 ··· 6153 6153 6154 6154 RT_TRACE(COMP_DOWN, "Exiting"); 6155 6155 rtl8192_proc_module_remove(); 6156 - ieee80211_exit(); 6156 + ieee80211_rtl_exit(); 6157 6157 } 6158 6158 6159 6159 //warning message WB ··· 6313 6313 spin_unlock_irqrestore(&priv->tx_lock,flags); 6314 6314 6315 6315 if(enough_desc) 6316 - ieee80211_wake_queue(priv->ieee80211); 6316 + ieee80211_rtl_wake_queue(priv->ieee80211); 6317 6317 #endif 6318 6318 } 6319 6319
+4 -4
drivers/staging/rtl8192su/ieee80211/ieee80211.h
··· 1721 1721 struct sk_buff *frag, 1722 1722 int hdr_len); 1723 1723 1724 - extern int rtl8192_ieee80211_xmit(struct sk_buff *skb, 1724 + extern int rtl8192_ieee80211_rtl_xmit(struct sk_buff *skb, 1725 1725 struct net_device *dev); 1726 1726 extern void ieee80211_txb_free(struct ieee80211_txb *); 1727 1727 1728 1728 1729 1729 /* ieee80211_rx.c */ 1730 - extern int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, 1730 + extern int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb, 1731 1731 struct ieee80211_rx_stats *rx_stats); 1732 1732 extern void ieee80211_rx_mgt(struct ieee80211_device *ieee, 1733 1733 struct ieee80211_hdr_4addr *header, ··· 1783 1783 extern void ieee80211_softmac_start_protocol(struct ieee80211_device *ieee); 1784 1784 extern void ieee80211_softmac_stop_protocol(struct ieee80211_device *ieee); 1785 1785 extern void ieee80211_reset_queue(struct ieee80211_device *ieee); 1786 - extern void ieee80211_wake_queue(struct ieee80211_device *ieee); 1787 - extern void ieee80211_stop_queue(struct ieee80211_device *ieee); 1786 + extern void ieee80211_rtl_wake_queue(struct ieee80211_device *ieee); 1787 + extern void ieee80211_rtl_stop_queue(struct ieee80211_device *ieee); 1788 1788 extern struct sk_buff *ieee80211_get_beacon(struct ieee80211_device *ieee); 1789 1789 extern void ieee80211_start_send_beacons(struct ieee80211_device *ieee); 1790 1790 extern void ieee80211_stop_send_beacons(struct ieee80211_device *ieee);
+3 -3
drivers/staging/rtl8192su/ieee80211/ieee80211_rx.c
··· 208 208 * 209 209 * Responsible for handling management control frames 210 210 * 211 - * Called by ieee80211_rx */ 211 + * Called by ieee80211_rtl_rx */ 212 212 static inline int 213 213 ieee80211_rx_frame_mgmt(struct ieee80211_device *ieee, struct sk_buff *skb, 214 214 struct ieee80211_rx_stats *rx_stats, u16 type, ··· 289 289 return 0; 290 290 } 291 291 292 - /* Called only as a tasklet (software IRQ), by ieee80211_rx */ 292 + /* Called only as a tasklet (software IRQ), by ieee80211_rtl_rx */ 293 293 static inline int 294 294 ieee80211_rx_frame_decrypt(struct ieee80211_device* ieee, struct sk_buff *skb, 295 295 struct ieee80211_crypt_data *crypt) ··· 858 858 /* All received frames are sent to this function. @skb contains the frame in 859 859 * IEEE 802.11 format, i.e., in the format it was sent over air. 860 860 * This function is called only as a tasklet (software IRQ). */ 861 - int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, 861 + int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb, 862 862 struct ieee80211_rx_stats *rx_stats) 863 863 { 864 864 struct net_device *dev = ieee->dev;
+8 -8
drivers/staging/rtl8192su/ieee80211/ieee80211_softmac.c
··· 610 610 } 611 611 612 612 /* called with ieee->lock held */ 613 - void ieee80211_start_scan(struct ieee80211_device *ieee) 613 + void ieee80211_rtl_start_scan(struct ieee80211_device *ieee) 614 614 { 615 615 if(IS_DOT11D_ENABLE(ieee) ) 616 616 { ··· 1281 1281 } 1282 1282 } 1283 1283 1284 - void ieee80211_auth_challenge(struct ieee80211_device *ieee, u8 *challenge, int chlen) 1284 + void ieee80211_rtl_auth_challenge(struct ieee80211_device *ieee, u8 *challenge, int chlen) 1285 1285 { 1286 1286 u8 *c; 1287 1287 struct sk_buff *skb; ··· 2054 2054 2055 2055 ieee80211_associate_step2(ieee); 2056 2056 }else{ 2057 - ieee80211_auth_challenge(ieee, challenge, chlen); 2057 + ieee80211_rtl_auth_challenge(ieee, challenge, chlen); 2058 2058 } 2059 2059 }else{ 2060 2060 ieee->softmac_stats.rx_auth_rs_err++; ··· 2162 2162 * to check it any more. 2163 2163 * */ 2164 2164 //printk("error:no descriptor left@queue_index %d, %d, %d\n", queue_index, skb_queue_len(&ieee->skb_waitQ[queue_index]), ieee->check_nic_enough_desc(ieee->dev,queue_index)); 2165 - //ieee80211_stop_queue(ieee); 2165 + //ieee80211_rtl_stop_queue(ieee); 2166 2166 skb_queue_tail(&ieee->skb_waitQ[queue_index], txb->fragments[i]); 2167 2167 }else{ 2168 2168 ieee->softmac_data_hard_start_xmit( ··· 2222 2222 2223 2223 } 2224 2224 2225 - void ieee80211_wake_queue(struct ieee80211_device *ieee) 2225 + void ieee80211_rtl_wake_queue(struct ieee80211_device *ieee) 2226 2226 { 2227 2227 2228 2228 unsigned long flags; ··· 2263 2263 } 2264 2264 2265 2265 2266 - void ieee80211_stop_queue(struct ieee80211_device *ieee) 2266 + void ieee80211_rtl_stop_queue(struct ieee80211_device *ieee) 2267 2267 { 2268 2268 //unsigned long flags; 2269 2269 //spin_lock_irqsave(&ieee->lock,flags); ··· 2479 2479 2480 2480 if (ieee->state == IEEE80211_NOLINK){ 2481 2481 ieee->actscanning = true; 2482 - ieee80211_start_scan(ieee); 2482 + ieee80211_rtl_start_scan(ieee); 2483 2483 } 2484 2484 spin_unlock_irqrestore(&ieee->lock, flags); 2485 2485 } ··· 2552 2552 if(ieee->state == IEEE80211_NOLINK) 2553 2553 { 2554 2554 ieee->actscanning = true; 2555 - ieee80211_start_scan(ieee); 2555 + ieee80211_rtl_start_scan(ieee); 2556 2556 } 2557 2557 spin_unlock_irqrestore(&ieee->lock, flags); 2558 2558
+1 -1
drivers/staging/rtl8192su/ieee80211/ieee80211_tx.c
··· 604 604 } 605 605 } 606 606 607 - int rtl8192_ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) 607 + int rtl8192_ieee80211_rtl_xmit(struct sk_buff *skb, struct net_device *dev) 608 608 { 609 609 struct ieee80211_device *ieee = netdev_priv(dev); 610 610 struct ieee80211_txb *txb = NULL;
+6 -4
drivers/staging/rtl8192su/r8192U_core.c
··· 126 126 {USB_DEVICE(0x2001, 0x3301)}, 127 127 /* Zinwell */ 128 128 {USB_DEVICE(0x5a57, 0x0290)}, 129 + /* Guillemot */ 130 + {USB_DEVICE(0x06f8, 0xe031)}, 129 131 //92SU 130 132 {USB_DEVICE(0x0bda, 0x8172)}, 131 133 {} ··· 1503 1501 urb->context = skb; 1504 1502 skb_queue_tail(&priv->rx_queue, skb); 1505 1503 err = usb_submit_urb(urb, GFP_ATOMIC); 1506 - if(err && err != EPERM) 1504 + if(err && err != -EPERM) 1507 1505 printk("can not submit rxurb, err is %x,URB status is %x\n",err,urb->status); 1508 1506 } 1509 1507 ··· 7157 7155 unicast_packet = true; 7158 7156 } 7159 7157 7160 - if(!ieee80211_rx(priv->ieee80211,skb, &stats)) { 7158 + if(!ieee80211_rtl_rx(priv->ieee80211,skb, &stats)) { 7161 7159 dev_kfree_skb_any(skb); 7162 7160 } else { 7163 7161 // priv->stats.rxoktotal++; //YJ,test,090108 ··· 7428 7426 .ndo_set_mac_address = r8192_set_mac_adr, 7429 7427 .ndo_validate_addr = eth_validate_addr, 7430 7428 .ndo_change_mtu = eth_change_mtu, 7431 - .ndo_start_xmit = rtl8192_ieee80211_xmit, 7429 + .ndo_start_xmit = rtl8192_ieee80211_rtl_xmit, 7432 7430 }; 7433 7431 7434 7432 static int __devinit rtl8192_usb_probe(struct usb_interface *intf, ··· 7621 7619 spin_unlock_irqrestore(&priv->tx_lock,flags); 7622 7620 7623 7621 if(enough_desc) 7624 - ieee80211_wake_queue(priv->ieee80211); 7622 + ieee80211_rtl_wake_queue(priv->ieee80211); 7625 7623 } 7626 7624 7627 7625 void EnableHWSecurityConfig8192(struct net_device *dev)
+1 -1
drivers/staging/rtl8192u/ieee80211/ieee80211_wx.c
··· 845 845 { 846 846 if (len != ie[1]+2) 847 847 { 848 - printk("len:%d, ie:%d\n", len, ie[1]); 848 + printk("len:%zu, ie:%d\n", len, ie[1]); 849 849 return -EINVAL; 850 850 } 851 851 buf = kmalloc(len, GFP_KERNEL);
+3 -3
drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c
··· 340 340 341 341 if (skb->len < sizeof( struct ieee80211_hdr_3addr) + 9) 342 342 { 343 - IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in BAREQ(%d / %d)\n", skb->len, (sizeof( struct ieee80211_hdr_3addr) + 9)); 343 + IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in BAREQ(%d / %zu)\n", skb->len, (sizeof( struct ieee80211_hdr_3addr) + 9)); 344 344 return -1; 345 345 } 346 346 ··· 439 439 440 440 if (skb->len < sizeof( struct ieee80211_hdr_3addr) + 9) 441 441 { 442 - IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in BARSP(%d / %d)\n", skb->len, (sizeof( struct ieee80211_hdr_3addr) + 9)); 442 + IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in BARSP(%d / %zu)\n", skb->len, (sizeof( struct ieee80211_hdr_3addr) + 9)); 443 443 return -1; 444 444 } 445 445 rsp = ( struct ieee80211_hdr_3addr*)skb->data; ··· 569 569 570 570 if (skb->len < sizeof( struct ieee80211_hdr_3addr) + 6) 571 571 { 572 - IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in DELBA(%d / %d)\n", skb->len, (sizeof( struct ieee80211_hdr_3addr) + 6)); 572 + IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in DELBA(%d / %zu)\n", skb->len, (sizeof( struct ieee80211_hdr_3addr) + 6)); 573 573 return -1; 574 574 } 575 575
+15
drivers/staging/sm7xx/Kconfig
··· 1 + config FB_SM7XX 2 + tristate "Silicon Motion SM7XX Frame Buffer Support" 3 + depends on FB 4 + select FB_CFB_FILLRECT 5 + select FB_CFB_COPYAREA 6 + select FB_CFB_IMAGEBLIT 7 + help 8 + Frame Buffer driver for the Silicon Motion SM7XX serial graphic card. 9 + 10 + config FB_SM7XX_ACCEL 11 + bool "Siliconmotion Acceleration functions (EXPERIMENTAL)" 12 + depends on FB_SM7XX && EXPERIMENTAL 13 + help 14 + This will compile the Trident frame buffer device with 15 + acceleration functions.
+3
drivers/staging/sm7xx/Makefile
··· 1 + obj-$(CONFIG_FB_SM7XX) += sm7xx.o 2 + 3 + sm7xx-y := smtcfb.o
+10
drivers/staging/sm7xx/TODO
··· 1 + TODO: 2 + - Dual head support 3 + - use kernel coding style 4 + - checkpatch.pl clean 5 + - refine the code and remove unused code 6 + - use kernel framebuffer mode setting instead of hard code 7 + - move it to drivers/video/sm7xx/ or make it be drivers/video/sm7xxfb.c 8 + 9 + Please send any patches to Greg Kroah-Hartman <greg@kroah.com> and 10 + Teddy Wang <teddy.wang@siliconmotion.com.cn>.
+979
drivers/staging/sm7xx/smtc2d.c
··· 1 + /* 2 + * Silicon Motion SM7XX 2D drawing engine functions. 3 + * 4 + * Copyright (C) 2006 Silicon Motion Technology Corp. 5 + * Author: Boyod boyod.yang@siliconmotion.com.cn 6 + * 7 + * Copyright (C) 2009 Lemote, Inc. 8 + * Author: Wu Zhangjin, wuzj@lemote.com 9 + * 10 + * This file is subject to the terms and conditions of the GNU General Public 11 + * License. See the file COPYING in the main directory of this archive for 12 + * more details. 13 + * 14 + * Version 0.10.26192.21.01 15 + * - Add PowerPC support 16 + * - Add 2D support for Lynx - 17 + * Verified on 2.6.19.2 18 + * Boyod.yang <boyod.yang@siliconmotion.com.cn> 19 + */ 20 + 21 + unsigned char smtc_de_busy; 22 + 23 + void SMTC_write2Dreg(unsigned long nOffset, unsigned long nData) 24 + { 25 + writel(nData, smtc_2DBaseAddress + nOffset); 26 + } 27 + 28 + unsigned long SMTC_read2Dreg(unsigned long nOffset) 29 + { 30 + return readl(smtc_2DBaseAddress + nOffset); 31 + } 32 + 33 + void SMTC_write2Ddataport(unsigned long nOffset, unsigned long nData) 34 + { 35 + writel(nData, smtc_2Ddataport + nOffset); 36 + } 37 + 38 + /********************************************************************** 39 + * 40 + * deInit 41 + * 42 + * Purpose 43 + * Drawing engine initialization. 44 + * 45 + **********************************************************************/ 46 + 47 + void deInit(unsigned int nModeWidth, unsigned int nModeHeight, 48 + unsigned int bpp) 49 + { 50 + /* Get current power configuration. */ 51 + unsigned char clock; 52 + clock = smtc_seqr(0x21); 53 + 54 + /* initialize global 'mutex lock' variable */ 55 + smtc_de_busy = 0; 56 + 57 + /* Enable 2D Drawing Engine */ 58 + smtc_seqw(0x21, clock & 0xF8); 59 + 60 + SMTC_write2Dreg(DE_CLIP_TL, 61 + FIELD_VALUE(0, DE_CLIP_TL, TOP, 0) | 62 + FIELD_SET(0, DE_CLIP_TL, STATUS, DISABLE) | 63 + FIELD_SET(0, DE_CLIP_TL, INHIBIT, OUTSIDE) | 64 + FIELD_VALUE(0, DE_CLIP_TL, LEFT, 0)); 65 + 66 + if (bpp >= 24) { 67 + SMTC_write2Dreg(DE_PITCH, 68 + FIELD_VALUE(0, DE_PITCH, DESTINATION, 69 + nModeWidth * 3) | FIELD_VALUE(0, 70 + DE_PITCH, 71 + SOURCE, 72 + nModeWidth 73 + * 3)); 74 + } else { 75 + SMTC_write2Dreg(DE_PITCH, 76 + FIELD_VALUE(0, DE_PITCH, DESTINATION, 77 + nModeWidth) | FIELD_VALUE(0, 78 + DE_PITCH, 79 + SOURCE, 80 + nModeWidth)); 81 + } 82 + 83 + SMTC_write2Dreg(DE_WINDOW_WIDTH, 84 + FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION, 85 + nModeWidth) | FIELD_VALUE(0, 86 + DE_WINDOW_WIDTH, 87 + SOURCE, 88 + nModeWidth)); 89 + 90 + switch (bpp) { 91 + case 8: 92 + SMTC_write2Dreg(DE_STRETCH_FORMAT, 93 + FIELD_SET(0, DE_STRETCH_FORMAT, PATTERN_XY, 94 + NORMAL) | FIELD_VALUE(0, 95 + DE_STRETCH_FORMAT, 96 + PATTERN_Y, 97 + 0) | 98 + FIELD_VALUE(0, DE_STRETCH_FORMAT, PATTERN_X, 99 + 0) | FIELD_SET(0, DE_STRETCH_FORMAT, 100 + PIXEL_FORMAT, 101 + 8) | FIELD_SET(0, 102 + DE_STRETCH_FORMAT, 103 + ADDRESSING, 104 + XY) | 105 + FIELD_VALUE(0, DE_STRETCH_FORMAT, 106 + SOURCE_HEIGHT, 3)); 107 + break; 108 + case 24: 109 + SMTC_write2Dreg(DE_STRETCH_FORMAT, 110 + FIELD_SET(0, DE_STRETCH_FORMAT, PATTERN_XY, 111 + NORMAL) | FIELD_VALUE(0, 112 + DE_STRETCH_FORMAT, 113 + PATTERN_Y, 114 + 0) | 115 + FIELD_VALUE(0, DE_STRETCH_FORMAT, PATTERN_X, 116 + 0) | FIELD_SET(0, DE_STRETCH_FORMAT, 117 + PIXEL_FORMAT, 118 + 24) | FIELD_SET(0, 119 + DE_STRETCH_FORMAT, 120 + ADDRESSING, 121 + XY) | 122 + FIELD_VALUE(0, DE_STRETCH_FORMAT, 123 + SOURCE_HEIGHT, 3)); 124 + break; 125 + case 16: 126 + default: 127 + SMTC_write2Dreg(DE_STRETCH_FORMAT, 128 + FIELD_SET(0, DE_STRETCH_FORMAT, PATTERN_XY, 129 + NORMAL) | FIELD_VALUE(0, 130 + DE_STRETCH_FORMAT, 131 + PATTERN_Y, 132 + 0) | 133 + FIELD_VALUE(0, DE_STRETCH_FORMAT, PATTERN_X, 134 + 0) | FIELD_SET(0, DE_STRETCH_FORMAT, 135 + PIXEL_FORMAT, 136 + 16) | FIELD_SET(0, 137 + DE_STRETCH_FORMAT, 138 + ADDRESSING, 139 + XY) | 140 + FIELD_VALUE(0, DE_STRETCH_FORMAT, 141 + SOURCE_HEIGHT, 3)); 142 + break; 143 + } 144 + 145 + SMTC_write2Dreg(DE_MASKS, 146 + FIELD_VALUE(0, DE_MASKS, BYTE_MASK, 0xFFFF) | 147 + FIELD_VALUE(0, DE_MASKS, BIT_MASK, 0xFFFF)); 148 + SMTC_write2Dreg(DE_COLOR_COMPARE_MASK, 149 + FIELD_VALUE(0, DE_COLOR_COMPARE_MASK, MASKS, \ 150 + 0xFFFFFF)); 151 + SMTC_write2Dreg(DE_COLOR_COMPARE, 152 + FIELD_VALUE(0, DE_COLOR_COMPARE, COLOR, 0xFFFFFF)); 153 + } 154 + 155 + void deVerticalLine(unsigned long dst_base, 156 + unsigned long dst_pitch, 157 + unsigned long nX, 158 + unsigned long nY, 159 + unsigned long dst_height, unsigned long nColor) 160 + { 161 + deWaitForNotBusy(); 162 + 163 + SMTC_write2Dreg(DE_WINDOW_DESTINATION_BASE, 164 + FIELD_VALUE(0, DE_WINDOW_DESTINATION_BASE, ADDRESS, 165 + dst_base)); 166 + 167 + SMTC_write2Dreg(DE_PITCH, 168 + FIELD_VALUE(0, DE_PITCH, DESTINATION, dst_pitch) | 169 + FIELD_VALUE(0, DE_PITCH, SOURCE, dst_pitch)); 170 + 171 + SMTC_write2Dreg(DE_WINDOW_WIDTH, 172 + FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION, 173 + dst_pitch) | FIELD_VALUE(0, DE_WINDOW_WIDTH, 174 + SOURCE, 175 + dst_pitch)); 176 + 177 + SMTC_write2Dreg(DE_FOREGROUND, 178 + FIELD_VALUE(0, DE_FOREGROUND, COLOR, nColor)); 179 + 180 + SMTC_write2Dreg(DE_DESTINATION, 181 + FIELD_SET(0, DE_DESTINATION, WRAP, DISABLE) | 182 + FIELD_VALUE(0, DE_DESTINATION, X, nX) | 183 + FIELD_VALUE(0, DE_DESTINATION, Y, nY)); 184 + 185 + SMTC_write2Dreg(DE_DIMENSION, 186 + FIELD_VALUE(0, DE_DIMENSION, X, 1) | 187 + FIELD_VALUE(0, DE_DIMENSION, Y_ET, dst_height)); 188 + 189 + SMTC_write2Dreg(DE_CONTROL, 190 + FIELD_SET(0, DE_CONTROL, STATUS, START) | 191 + FIELD_SET(0, DE_CONTROL, DIRECTION, LEFT_TO_RIGHT) | 192 + FIELD_SET(0, DE_CONTROL, MAJOR, Y) | 193 + FIELD_SET(0, DE_CONTROL, STEP_X, NEGATIVE) | 194 + FIELD_SET(0, DE_CONTROL, STEP_Y, POSITIVE) | 195 + FIELD_SET(0, DE_CONTROL, LAST_PIXEL, OFF) | 196 + FIELD_SET(0, DE_CONTROL, COMMAND, SHORT_STROKE) | 197 + FIELD_SET(0, DE_CONTROL, ROP_SELECT, ROP2) | 198 + FIELD_VALUE(0, DE_CONTROL, ROP, 0x0C)); 199 + 200 + smtc_de_busy = 1; 201 + } 202 + 203 + void deHorizontalLine(unsigned long dst_base, 204 + unsigned long dst_pitch, 205 + unsigned long nX, 206 + unsigned long nY, 207 + unsigned long dst_width, unsigned long nColor) 208 + { 209 + deWaitForNotBusy(); 210 + 211 + SMTC_write2Dreg(DE_WINDOW_DESTINATION_BASE, 212 + FIELD_VALUE(0, DE_WINDOW_DESTINATION_BASE, ADDRESS, 213 + dst_base)); 214 + 215 + SMTC_write2Dreg(DE_PITCH, 216 + FIELD_VALUE(0, DE_PITCH, DESTINATION, dst_pitch) | 217 + FIELD_VALUE(0, DE_PITCH, SOURCE, dst_pitch)); 218 + 219 + SMTC_write2Dreg(DE_WINDOW_WIDTH, 220 + FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION, 221 + dst_pitch) | FIELD_VALUE(0, DE_WINDOW_WIDTH, 222 + SOURCE, 223 + dst_pitch)); 224 + SMTC_write2Dreg(DE_FOREGROUND, 225 + FIELD_VALUE(0, DE_FOREGROUND, COLOR, nColor)); 226 + SMTC_write2Dreg(DE_DESTINATION, 227 + FIELD_SET(0, DE_DESTINATION, WRAP, 228 + DISABLE) | FIELD_VALUE(0, DE_DESTINATION, X, 229 + nX) | FIELD_VALUE(0, 230 + DE_DESTINATION, 231 + Y, 232 + nY)); 233 + SMTC_write2Dreg(DE_DIMENSION, 234 + FIELD_VALUE(0, DE_DIMENSION, X, 235 + dst_width) | FIELD_VALUE(0, DE_DIMENSION, 236 + Y_ET, 1)); 237 + SMTC_write2Dreg(DE_CONTROL, 238 + FIELD_SET(0, DE_CONTROL, STATUS, START) | FIELD_SET(0, 239 + DE_CONTROL, 240 + DIRECTION, 241 + RIGHT_TO_LEFT) 242 + | FIELD_SET(0, DE_CONTROL, MAJOR, X) | FIELD_SET(0, 243 + DE_CONTROL, 244 + STEP_X, 245 + POSITIVE) 246 + | FIELD_SET(0, DE_CONTROL, STEP_Y, 247 + NEGATIVE) | FIELD_SET(0, DE_CONTROL, 248 + LAST_PIXEL, 249 + OFF) | FIELD_SET(0, 250 + DE_CONTROL, 251 + COMMAND, 252 + SHORT_STROKE) 253 + | FIELD_SET(0, DE_CONTROL, ROP_SELECT, 254 + ROP2) | FIELD_VALUE(0, DE_CONTROL, ROP, 255 + 0x0C)); 256 + 257 + smtc_de_busy = 1; 258 + } 259 + 260 + void deLine(unsigned long dst_base, 261 + unsigned long dst_pitch, 262 + unsigned long nX1, 263 + unsigned long nY1, 264 + unsigned long nX2, unsigned long nY2, unsigned long nColor) 265 + { 266 + unsigned long nCommand = 267 + FIELD_SET(0, DE_CONTROL, STATUS, START) | 268 + FIELD_SET(0, DE_CONTROL, DIRECTION, LEFT_TO_RIGHT) | 269 + FIELD_SET(0, DE_CONTROL, MAJOR, X) | 270 + FIELD_SET(0, DE_CONTROL, STEP_X, POSITIVE) | 271 + FIELD_SET(0, DE_CONTROL, STEP_Y, POSITIVE) | 272 + FIELD_SET(0, DE_CONTROL, LAST_PIXEL, OFF) | 273 + FIELD_SET(0, DE_CONTROL, ROP_SELECT, ROP2) | 274 + FIELD_VALUE(0, DE_CONTROL, ROP, 0x0C); 275 + unsigned long DeltaX; 276 + unsigned long DeltaY; 277 + 278 + /* Calculate delta X */ 279 + if (nX1 <= nX2) 280 + DeltaX = nX2 - nX1; 281 + else { 282 + DeltaX = nX1 - nX2; 283 + nCommand = FIELD_SET(nCommand, DE_CONTROL, STEP_X, NEGATIVE); 284 + } 285 + 286 + /* Calculate delta Y */ 287 + if (nY1 <= nY2) 288 + DeltaY = nY2 - nY1; 289 + else { 290 + DeltaY = nY1 - nY2; 291 + nCommand = FIELD_SET(nCommand, DE_CONTROL, STEP_Y, NEGATIVE); 292 + } 293 + 294 + /* Determine the major axis */ 295 + if (DeltaX < DeltaY) 296 + nCommand = FIELD_SET(nCommand, DE_CONTROL, MAJOR, Y); 297 + 298 + /* Vertical line? */ 299 + if (nX1 == nX2) 300 + deVerticalLine(dst_base, dst_pitch, nX1, nY1, DeltaY, nColor); 301 + 302 + /* Horizontal line? */ 303 + else if (nY1 == nY2) 304 + deHorizontalLine(dst_base, dst_pitch, nX1, nY1, \ 305 + DeltaX, nColor); 306 + 307 + /* Diagonal line? */ 308 + else if (DeltaX == DeltaY) { 309 + deWaitForNotBusy(); 310 + 311 + SMTC_write2Dreg(DE_WINDOW_DESTINATION_BASE, 312 + FIELD_VALUE(0, DE_WINDOW_DESTINATION_BASE, 313 + ADDRESS, dst_base)); 314 + 315 + SMTC_write2Dreg(DE_PITCH, 316 + FIELD_VALUE(0, DE_PITCH, DESTINATION, 317 + dst_pitch) | FIELD_VALUE(0, 318 + DE_PITCH, 319 + SOURCE, 320 + dst_pitch)); 321 + 322 + SMTC_write2Dreg(DE_WINDOW_WIDTH, 323 + FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION, 324 + dst_pitch) | FIELD_VALUE(0, 325 + DE_WINDOW_WIDTH, 326 + SOURCE, 327 + dst_pitch)); 328 + 329 + SMTC_write2Dreg(DE_FOREGROUND, 330 + FIELD_VALUE(0, DE_FOREGROUND, COLOR, nColor)); 331 + 332 + SMTC_write2Dreg(DE_DESTINATION, 333 + FIELD_SET(0, DE_DESTINATION, WRAP, DISABLE) | 334 + FIELD_VALUE(0, DE_DESTINATION, X, 1) | 335 + FIELD_VALUE(0, DE_DESTINATION, Y, nY1)); 336 + 337 + SMTC_write2Dreg(DE_DIMENSION, 338 + FIELD_VALUE(0, DE_DIMENSION, X, 1) | 339 + FIELD_VALUE(0, DE_DIMENSION, Y_ET, DeltaX)); 340 + 341 + SMTC_write2Dreg(DE_CONTROL, 342 + FIELD_SET(nCommand, DE_CONTROL, COMMAND, 343 + SHORT_STROKE)); 344 + } 345 + 346 + /* Generic line */ 347 + else { 348 + unsigned int k1, k2, et, w; 349 + if (DeltaX < DeltaY) { 350 + k1 = 2 * DeltaX; 351 + et = k1 - DeltaY; 352 + k2 = et - DeltaY; 353 + w = DeltaY + 1; 354 + } else { 355 + k1 = 2 * DeltaY; 356 + et = k1 - DeltaX; 357 + k2 = et - DeltaX; 358 + w = DeltaX + 1; 359 + } 360 + 361 + deWaitForNotBusy(); 362 + 363 + SMTC_write2Dreg(DE_WINDOW_DESTINATION_BASE, 364 + FIELD_VALUE(0, DE_WINDOW_DESTINATION_BASE, 365 + ADDRESS, dst_base)); 366 + 367 + SMTC_write2Dreg(DE_PITCH, 368 + FIELD_VALUE(0, DE_PITCH, DESTINATION, 369 + dst_pitch) | FIELD_VALUE(0, 370 + DE_PITCH, 371 + SOURCE, 372 + dst_pitch)); 373 + 374 + SMTC_write2Dreg(DE_WINDOW_WIDTH, 375 + FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION, 376 + dst_pitch) | FIELD_VALUE(0, 377 + DE_WINDOW_WIDTH, 378 + SOURCE, 379 + dst_pitch)); 380 + 381 + SMTC_write2Dreg(DE_FOREGROUND, 382 + FIELD_VALUE(0, DE_FOREGROUND, COLOR, nColor)); 383 + 384 + SMTC_write2Dreg(DE_SOURCE, 385 + FIELD_SET(0, DE_SOURCE, WRAP, DISABLE) | 386 + FIELD_VALUE(0, DE_SOURCE, X_K1, k1) | 387 + FIELD_VALUE(0, DE_SOURCE, Y_K2, k2)); 388 + 389 + SMTC_write2Dreg(DE_DESTINATION, 390 + FIELD_SET(0, DE_DESTINATION, WRAP, DISABLE) | 391 + FIELD_VALUE(0, DE_DESTINATION, X, nX1) | 392 + FIELD_VALUE(0, DE_DESTINATION, Y, nY1)); 393 + 394 + SMTC_write2Dreg(DE_DIMENSION, 395 + FIELD_VALUE(0, DE_DIMENSION, X, w) | 396 + FIELD_VALUE(0, DE_DIMENSION, Y_ET, et)); 397 + 398 + SMTC_write2Dreg(DE_CONTROL, 399 + FIELD_SET(nCommand, DE_CONTROL, COMMAND, 400 + LINE_DRAW)); 401 + } 402 + 403 + smtc_de_busy = 1; 404 + } 405 + 406 + void deFillRect(unsigned long dst_base, 407 + unsigned long dst_pitch, 408 + unsigned long dst_X, 409 + unsigned long dst_Y, 410 + unsigned long dst_width, 411 + unsigned long dst_height, unsigned long nColor) 412 + { 413 + deWaitForNotBusy(); 414 + 415 + SMTC_write2Dreg(DE_WINDOW_DESTINATION_BASE, 416 + FIELD_VALUE(0, DE_WINDOW_DESTINATION_BASE, ADDRESS, 417 + dst_base)); 418 + 419 + if (dst_pitch) { 420 + SMTC_write2Dreg(DE_PITCH, 421 + FIELD_VALUE(0, DE_PITCH, DESTINATION, 422 + dst_pitch) | FIELD_VALUE(0, 423 + DE_PITCH, 424 + SOURCE, 425 + dst_pitch)); 426 + 427 + SMTC_write2Dreg(DE_WINDOW_WIDTH, 428 + FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION, 429 + dst_pitch) | FIELD_VALUE(0, 430 + DE_WINDOW_WIDTH, 431 + SOURCE, 432 + dst_pitch)); 433 + } 434 + 435 + SMTC_write2Dreg(DE_FOREGROUND, 436 + FIELD_VALUE(0, DE_FOREGROUND, COLOR, nColor)); 437 + 438 + SMTC_write2Dreg(DE_DESTINATION, 439 + FIELD_SET(0, DE_DESTINATION, WRAP, DISABLE) | 440 + FIELD_VALUE(0, DE_DESTINATION, X, dst_X) | 441 + FIELD_VALUE(0, DE_DESTINATION, Y, dst_Y)); 442 + 443 + SMTC_write2Dreg(DE_DIMENSION, 444 + FIELD_VALUE(0, DE_DIMENSION, X, dst_width) | 445 + FIELD_VALUE(0, DE_DIMENSION, Y_ET, dst_height)); 446 + 447 + SMTC_write2Dreg(DE_CONTROL, 448 + FIELD_SET(0, DE_CONTROL, STATUS, START) | 449 + FIELD_SET(0, DE_CONTROL, DIRECTION, LEFT_TO_RIGHT) | 450 + FIELD_SET(0, DE_CONTROL, LAST_PIXEL, OFF) | 451 + FIELD_SET(0, DE_CONTROL, COMMAND, RECTANGLE_FILL) | 452 + FIELD_SET(0, DE_CONTROL, ROP_SELECT, ROP2) | 453 + FIELD_VALUE(0, DE_CONTROL, ROP, 0x0C)); 454 + 455 + smtc_de_busy = 1; 456 + } 457 + 458 + /********************************************************************** 459 + * 460 + * deRotatePattern 461 + * 462 + * Purpose 463 + * Rotate the given pattern if necessary 464 + * 465 + * Parameters 466 + * [in] 467 + * pPattern - Pointer to DE_SURFACE structure containing 468 + * pattern attributes 469 + * patternX - X position (0-7) of pattern origin 470 + * patternY - Y position (0-7) of pattern origin 471 + * 472 + * [out] 473 + * pattern_dstaddr - Pointer to pre-allocated buffer containing 474 + * rotated pattern 475 + * 476 + **********************************************************************/ 477 + void deRotatePattern(unsigned char *pattern_dstaddr, 478 + unsigned long pattern_src_addr, 479 + unsigned long pattern_BPP, 480 + unsigned long pattern_stride, int patternX, int patternY) 481 + { 482 + unsigned int i; 483 + unsigned long pattern[PATTERN_WIDTH * PATTERN_HEIGHT]; 484 + unsigned int x, y; 485 + unsigned char *pjPatByte; 486 + 487 + if (pattern_dstaddr != NULL) { 488 + deWaitForNotBusy(); 489 + 490 + if (patternX || patternY) { 491 + /* Rotate pattern */ 492 + pjPatByte = (unsigned char *)pattern; 493 + 494 + switch (pattern_BPP) { 495 + case 8: 496 + { 497 + for (y = 0; y < 8; y++) { 498 + unsigned char *pjBuffer = 499 + pattern_dstaddr + 500 + ((patternY + y) & 7) * 8; 501 + for (x = 0; x < 8; x++) { 502 + pjBuffer[(patternX + 503 + x) & 7] = 504 + pjPatByte[x]; 505 + } 506 + pjPatByte += pattern_stride; 507 + } 508 + break; 509 + } 510 + 511 + case 16: 512 + { 513 + for (y = 0; y < 8; y++) { 514 + unsigned short *pjBuffer = 515 + (unsigned short *) 516 + pattern_dstaddr + 517 + ((patternY + y) & 7) * 8; 518 + for (x = 0; x < 8; x++) { 519 + pjBuffer[(patternX + 520 + x) & 7] = 521 + ((unsigned short *) 522 + pjPatByte)[x]; 523 + } 524 + pjPatByte += pattern_stride; 525 + } 526 + break; 527 + } 528 + 529 + case 32: 530 + { 531 + for (y = 0; y < 8; y++) { 532 + unsigned long *pjBuffer = 533 + (unsigned long *) 534 + pattern_dstaddr + 535 + ((patternY + y) & 7) * 8; 536 + for (x = 0; x < 8; x++) { 537 + pjBuffer[(patternX + 538 + x) & 7] = 539 + ((unsigned long *) 540 + pjPatByte)[x]; 541 + } 542 + pjPatByte += pattern_stride; 543 + } 544 + break; 545 + } 546 + } 547 + } else { 548 + /*Don't rotate,just copy pattern into pattern_dstaddr*/ 549 + for (i = 0; i < (pattern_BPP * 2); i++) { 550 + ((unsigned long *)pattern_dstaddr)[i] = 551 + pattern[i]; 552 + } 553 + } 554 + 555 + } 556 + } 557 + 558 + /********************************************************************** 559 + * 560 + * deCopy 561 + * 562 + * Purpose 563 + * Copy a rectangular area of the source surface to a destination surface 564 + * 565 + * Remarks 566 + * Source bitmap must have the same color depth (BPP) as the destination 567 + * bitmap. 568 + * 569 + **********************************************************************/ 570 + void deCopy(unsigned long dst_base, 571 + unsigned long dst_pitch, 572 + unsigned long dst_BPP, 573 + unsigned long dst_X, 574 + unsigned long dst_Y, 575 + unsigned long dst_width, 576 + unsigned long dst_height, 577 + unsigned long src_base, 578 + unsigned long src_pitch, 579 + unsigned long src_X, 580 + unsigned long src_Y, pTransparent pTransp, unsigned char nROP2) 581 + { 582 + unsigned long nDirection = 0; 583 + unsigned long nTransparent = 0; 584 + /* Direction of ROP2 operation: 585 + * 1 = Left to Right, 586 + * (-1) = Right to Left 587 + */ 588 + unsigned long opSign = 1; 589 + /* xWidth is in pixels */ 590 + unsigned long xWidth = 192 / (dst_BPP / 8); 591 + unsigned long de_ctrl = 0; 592 + 593 + deWaitForNotBusy(); 594 + 595 + SMTC_write2Dreg(DE_WINDOW_DESTINATION_BASE, 596 + FIELD_VALUE(0, DE_WINDOW_DESTINATION_BASE, ADDRESS, 597 + dst_base)); 598 + 599 + SMTC_write2Dreg(DE_WINDOW_SOURCE_BASE, 600 + FIELD_VALUE(0, DE_WINDOW_SOURCE_BASE, ADDRESS, 601 + src_base)); 602 + 603 + if (dst_pitch && src_pitch) { 604 + SMTC_write2Dreg(DE_PITCH, 605 + FIELD_VALUE(0, DE_PITCH, DESTINATION, 606 + dst_pitch) | FIELD_VALUE(0, 607 + DE_PITCH, 608 + SOURCE, 609 + src_pitch)); 610 + 611 + SMTC_write2Dreg(DE_WINDOW_WIDTH, 612 + FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION, 613 + dst_pitch) | FIELD_VALUE(0, 614 + DE_WINDOW_WIDTH, 615 + SOURCE, 616 + src_pitch)); 617 + } 618 + 619 + /* Set transparent bits if necessary */ 620 + if (pTransp != NULL) { 621 + nTransparent = 622 + pTransp->match | pTransp->select | pTransp->control; 623 + 624 + /* Set color compare register */ 625 + SMTC_write2Dreg(DE_COLOR_COMPARE, 626 + FIELD_VALUE(0, DE_COLOR_COMPARE, COLOR, 627 + pTransp->color)); 628 + } 629 + 630 + /* Determine direction of operation */ 631 + if (src_Y < dst_Y) { 632 + /* +----------+ 633 + |S | 634 + | +----------+ 635 + | | | | 636 + | | | | 637 + +---|------+ | 638 + | D | 639 + +----------+ */ 640 + 641 + nDirection = BOTTOM_TO_TOP; 642 + } else if (src_Y > dst_Y) { 643 + /* +----------+ 644 + |D | 645 + | +----------+ 646 + | | | | 647 + | | | | 648 + +---|------+ | 649 + | S | 650 + +----------+ */ 651 + 652 + nDirection = TOP_TO_BOTTOM; 653 + } else { 654 + /* src_Y == dst_Y */ 655 + 656 + if (src_X <= dst_X) { 657 + /* +------+---+------+ 658 + |S | | D| 659 + | | | | 660 + | | | | 661 + | | | | 662 + +------+---+------+ */ 663 + 664 + nDirection = RIGHT_TO_LEFT; 665 + } else { 666 + /* src_X > dst_X */ 667 + 668 + /* +------+---+------+ 669 + |D | | S| 670 + | | | | 671 + | | | | 672 + | | | | 673 + +------+---+------+ */ 674 + 675 + nDirection = LEFT_TO_RIGHT; 676 + } 677 + } 678 + 679 + if ((nDirection == BOTTOM_TO_TOP) || (nDirection == RIGHT_TO_LEFT)) { 680 + src_X += dst_width - 1; 681 + src_Y += dst_height - 1; 682 + dst_X += dst_width - 1; 683 + dst_Y += dst_height - 1; 684 + opSign = (-1); 685 + } 686 + 687 + if (dst_BPP >= 24) { 688 + src_X *= 3; 689 + src_Y *= 3; 690 + dst_X *= 3; 691 + dst_Y *= 3; 692 + dst_width *= 3; 693 + if ((nDirection == BOTTOM_TO_TOP) 694 + || (nDirection == RIGHT_TO_LEFT)) { 695 + src_X += 2; 696 + dst_X += 2; 697 + } 698 + } 699 + 700 + /* Workaround for 192 byte hw bug */ 701 + if ((nROP2 != 0x0C) && ((dst_width * (dst_BPP / 8)) >= 192)) { 702 + /* 703 + * Perform the ROP2 operation in chunks of (xWidth * 704 + * dst_height) 705 + */ 706 + while (1) { 707 + deWaitForNotBusy(); 708 + 709 + SMTC_write2Dreg(DE_SOURCE, 710 + FIELD_SET(0, DE_SOURCE, WRAP, DISABLE) | 711 + FIELD_VALUE(0, DE_SOURCE, X_K1, src_X) | 712 + FIELD_VALUE(0, DE_SOURCE, Y_K2, src_Y)); 713 + 714 + SMTC_write2Dreg(DE_DESTINATION, 715 + FIELD_SET(0, DE_DESTINATION, WRAP, 716 + DISABLE) | FIELD_VALUE(0, 717 + DE_DESTINATION, 718 + X, 719 + dst_X) 720 + | FIELD_VALUE(0, DE_DESTINATION, Y, 721 + dst_Y)); 722 + 723 + SMTC_write2Dreg(DE_DIMENSION, 724 + FIELD_VALUE(0, DE_DIMENSION, X, 725 + xWidth) | FIELD_VALUE(0, 726 + DE_DIMENSION, 727 + Y_ET, 728 + dst_height)); 729 + 730 + de_ctrl = 731 + FIELD_VALUE(0, DE_CONTROL, ROP, 732 + nROP2) | nTransparent | FIELD_SET(0, 733 + DE_CONTROL, 734 + ROP_SELECT, 735 + ROP2) 736 + | FIELD_SET(0, DE_CONTROL, COMMAND, 737 + BITBLT) | ((nDirection == 738 + 1) ? FIELD_SET(0, 739 + DE_CONTROL, 740 + DIRECTION, 741 + RIGHT_TO_LEFT) 742 + : FIELD_SET(0, DE_CONTROL, 743 + DIRECTION, 744 + LEFT_TO_RIGHT)) | 745 + FIELD_SET(0, DE_CONTROL, STATUS, START); 746 + 747 + SMTC_write2Dreg(DE_CONTROL, de_ctrl); 748 + 749 + src_X += (opSign * xWidth); 750 + dst_X += (opSign * xWidth); 751 + dst_width -= xWidth; 752 + 753 + if (dst_width <= 0) { 754 + /* ROP2 operation is complete */ 755 + break; 756 + } 757 + 758 + if (xWidth > dst_width) 759 + xWidth = dst_width; 760 + } 761 + } else { 762 + deWaitForNotBusy(); 763 + SMTC_write2Dreg(DE_SOURCE, 764 + FIELD_SET(0, DE_SOURCE, WRAP, DISABLE) | 765 + FIELD_VALUE(0, DE_SOURCE, X_K1, src_X) | 766 + FIELD_VALUE(0, DE_SOURCE, Y_K2, src_Y)); 767 + 768 + SMTC_write2Dreg(DE_DESTINATION, 769 + FIELD_SET(0, DE_DESTINATION, WRAP, DISABLE) | 770 + FIELD_VALUE(0, DE_DESTINATION, X, dst_X) | 771 + FIELD_VALUE(0, DE_DESTINATION, Y, dst_Y)); 772 + 773 + SMTC_write2Dreg(DE_DIMENSION, 774 + FIELD_VALUE(0, DE_DIMENSION, X, dst_width) | 775 + FIELD_VALUE(0, DE_DIMENSION, Y_ET, dst_height)); 776 + 777 + de_ctrl = FIELD_VALUE(0, DE_CONTROL, ROP, nROP2) | 778 + nTransparent | 779 + FIELD_SET(0, DE_CONTROL, ROP_SELECT, ROP2) | 780 + FIELD_SET(0, DE_CONTROL, COMMAND, BITBLT) | 781 + ((nDirection == 1) ? FIELD_SET(0, DE_CONTROL, DIRECTION, 782 + RIGHT_TO_LEFT) 783 + : FIELD_SET(0, DE_CONTROL, DIRECTION, 784 + LEFT_TO_RIGHT)) | FIELD_SET(0, DE_CONTROL, 785 + STATUS, START); 786 + SMTC_write2Dreg(DE_CONTROL, de_ctrl); 787 + } 788 + 789 + smtc_de_busy = 1; 790 + } 791 + 792 + /* 793 + * This function sets the pixel format that will apply to the 2D Engine. 794 + */ 795 + void deSetPixelFormat(unsigned long bpp) 796 + { 797 + unsigned long de_format; 798 + 799 + de_format = SMTC_read2Dreg(DE_STRETCH_FORMAT); 800 + 801 + switch (bpp) { 802 + case 8: 803 + de_format = 804 + FIELD_SET(de_format, DE_STRETCH_FORMAT, PIXEL_FORMAT, 8); 805 + break; 806 + default: 807 + case 16: 808 + de_format = 809 + FIELD_SET(de_format, DE_STRETCH_FORMAT, PIXEL_FORMAT, 16); 810 + break; 811 + case 32: 812 + de_format = 813 + FIELD_SET(de_format, DE_STRETCH_FORMAT, PIXEL_FORMAT, 32); 814 + break; 815 + } 816 + 817 + SMTC_write2Dreg(DE_STRETCH_FORMAT, de_format); 818 + } 819 + 820 + /* 821 + * System memory to Video memory monochrome expansion. 822 + * 823 + * Source is monochrome image in system memory. This function expands the 824 + * monochrome data to color image in video memory. 825 + */ 826 + 827 + long deSystemMem2VideoMemMonoBlt(const char *pSrcbuf, 828 + long srcDelta, 829 + unsigned long startBit, 830 + unsigned long dBase, 831 + unsigned long dPitch, 832 + unsigned long bpp, 833 + unsigned long dx, unsigned long dy, 834 + unsigned long width, unsigned long height, 835 + unsigned long fColor, 836 + unsigned long bColor, 837 + unsigned long rop2) { 838 + unsigned long bytePerPixel; 839 + unsigned long ulBytesPerScan; 840 + unsigned long ul4BytesPerScan; 841 + unsigned long ulBytesRemain; 842 + unsigned long de_ctrl = 0; 843 + unsigned char ajRemain[4]; 844 + long i, j; 845 + 846 + bytePerPixel = bpp / 8; 847 + 848 + /* Just make sure the start bit is within legal range */ 849 + startBit &= 7; 850 + 851 + ulBytesPerScan = (width + startBit + 7) / 8; 852 + ul4BytesPerScan = ulBytesPerScan & ~3; 853 + ulBytesRemain = ulBytesPerScan & 3; 854 + 855 + if (smtc_de_busy) 856 + deWaitForNotBusy(); 857 + 858 + /* 859 + * 2D Source Base. Use 0 for HOST Blt. 860 + */ 861 + 862 + SMTC_write2Dreg(DE_WINDOW_SOURCE_BASE, 0); 863 + 864 + /* 865 + * 2D Destination Base. 866 + * 867 + * It is an address offset (128 bit aligned) from the beginning of 868 + * frame buffer. 869 + */ 870 + 871 + SMTC_write2Dreg(DE_WINDOW_DESTINATION_BASE, dBase); 872 + 873 + if (dPitch) { 874 + 875 + /* 876 + * Program pitch (distance between the 1st points of two 877 + * adjacent lines). 878 + * 879 + * Note that input pitch is BYTE value, but the 2D Pitch 880 + * register uses pixel values. Need Byte to pixel convertion. 881 + */ 882 + 883 + SMTC_write2Dreg(DE_PITCH, 884 + FIELD_VALUE(0, DE_PITCH, DESTINATION, 885 + dPitch / 886 + bytePerPixel) | FIELD_VALUE(0, 887 + DE_PITCH, 888 + SOURCE, 889 + dPitch / 890 + bytePerPixel)); 891 + 892 + /* Screen Window width in Pixels. 893 + * 894 + * 2D engine uses this value to calculate the linear address in 895 + * frame buffer for a given point. 896 + */ 897 + 898 + SMTC_write2Dreg(DE_WINDOW_WIDTH, 899 + FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION, 900 + (dPitch / 901 + bytePerPixel)) | FIELD_VALUE(0, 902 + DE_WINDOW_WIDTH, 903 + SOURCE, 904 + (dPitch 905 + / 906 + bytePerPixel))); 907 + } 908 + /* Note: For 2D Source in Host Write, only X_K1 field is needed, and 909 + * Y_K2 field is not used. For mono bitmap, use startBit for X_K1. 910 + */ 911 + 912 + SMTC_write2Dreg(DE_SOURCE, 913 + FIELD_SET(0, DE_SOURCE, WRAP, DISABLE) | 914 + FIELD_VALUE(0, DE_SOURCE, X_K1, startBit) | 915 + FIELD_VALUE(0, DE_SOURCE, Y_K2, 0)); 916 + 917 + SMTC_write2Dreg(DE_DESTINATION, 918 + FIELD_SET(0, DE_DESTINATION, WRAP, DISABLE) | 919 + FIELD_VALUE(0, DE_DESTINATION, X, dx) | 920 + FIELD_VALUE(0, DE_DESTINATION, Y, dy)); 921 + 922 + SMTC_write2Dreg(DE_DIMENSION, 923 + FIELD_VALUE(0, DE_DIMENSION, X, width) | 924 + FIELD_VALUE(0, DE_DIMENSION, Y_ET, height)); 925 + 926 + SMTC_write2Dreg(DE_FOREGROUND, fColor); 927 + SMTC_write2Dreg(DE_BACKGROUND, bColor); 928 + 929 + if (bpp) 930 + deSetPixelFormat(bpp); 931 + /* Set the pixel format of the destination */ 932 + 933 + de_ctrl = FIELD_VALUE(0, DE_CONTROL, ROP, rop2) | 934 + FIELD_SET(0, DE_CONTROL, ROP_SELECT, ROP2) | 935 + FIELD_SET(0, DE_CONTROL, COMMAND, HOST_WRITE) | 936 + FIELD_SET(0, DE_CONTROL, HOST, MONO) | 937 + FIELD_SET(0, DE_CONTROL, STATUS, START); 938 + 939 + SMTC_write2Dreg(DE_CONTROL, de_ctrl | deGetTransparency()); 940 + 941 + /* Write MONO data (line by line) to 2D Engine data port */ 942 + for (i = 0; i < height; i++) { 943 + /* For each line, send the data in chunks of 4 bytes */ 944 + for (j = 0; j < (ul4BytesPerScan / 4); j++) 945 + SMTC_write2Ddataport(0, 946 + *(unsigned long *)(pSrcbuf + 947 + (j * 4))); 948 + 949 + if (ulBytesRemain) { 950 + memcpy(ajRemain, pSrcbuf + ul4BytesPerScan, 951 + ulBytesRemain); 952 + SMTC_write2Ddataport(0, *(unsigned long *)ajRemain); 953 + } 954 + 955 + pSrcbuf += srcDelta; 956 + } 957 + smtc_de_busy = 1; 958 + 959 + return 0; 960 + } 961 + 962 + /* 963 + * This function gets the transparency status from DE_CONTROL register. 964 + * It returns a double word with the transparent fields properly set, 965 + * while other fields are 0. 966 + */ 967 + unsigned long deGetTransparency(void) 968 + { 969 + unsigned long de_ctrl; 970 + 971 + de_ctrl = SMTC_read2Dreg(DE_CONTROL); 972 + 973 + de_ctrl &= 974 + FIELD_MASK(DE_CONTROL_TRANSPARENCY_MATCH) | 975 + FIELD_MASK(DE_CONTROL_TRANSPARENCY_SELECT) | 976 + FIELD_MASK(DE_CONTROL_TRANSPARENCY); 977 + 978 + return de_ctrl; 979 + }
+530
drivers/staging/sm7xx/smtc2d.h
··· 1 + /* 2 + * Silicon Motion SM712 2D drawing engine functions. 3 + * 4 + * Copyright (C) 2006 Silicon Motion Technology Corp. 5 + * Author: Ge Wang, gewang@siliconmotion.com 6 + * 7 + * Copyright (C) 2009 Lemote, Inc. 8 + * Author: Wu Zhangjin, wuzj@lemote.com 9 + * 10 + * This file is subject to the terms and conditions of the GNU General Public 11 + * License. See the file COPYING in the main directory of this archive for 12 + * more details. 13 + */ 14 + 15 + #ifndef NULL 16 + #define NULL 0 17 + #endif 18 + 19 + /* Internal macros */ 20 + 21 + #define _F_START(f) (0 ? f) 22 + #define _F_END(f) (1 ? f) 23 + #define _F_SIZE(f) (1 + _F_END(f) - _F_START(f)) 24 + #define _F_MASK(f) (((1ULL << _F_SIZE(f)) - 1) << _F_START(f)) 25 + #define _F_NORMALIZE(v, f) (((v) & _F_MASK(f)) >> _F_START(f)) 26 + #define _F_DENORMALIZE(v, f) (((v) << _F_START(f)) & _F_MASK(f)) 27 + 28 + /* Global macros */ 29 + 30 + #define FIELD_GET(x, reg, field) \ 31 + ( \ 32 + _F_NORMALIZE((x), reg ## _ ## field) \ 33 + ) 34 + 35 + #define FIELD_SET(x, reg, field, value) \ 36 + ( \ 37 + (x & ~_F_MASK(reg ## _ ## field)) \ 38 + | _F_DENORMALIZE(reg ## _ ## field ## _ ## value, reg ## _ ## field) \ 39 + ) 40 + 41 + #define FIELD_VALUE(x, reg, field, value) \ 42 + ( \ 43 + (x & ~_F_MASK(reg ## _ ## field)) \ 44 + | _F_DENORMALIZE(value, reg ## _ ## field) \ 45 + ) 46 + 47 + #define FIELD_CLEAR(reg, field) \ 48 + ( \ 49 + ~_F_MASK(reg ## _ ## field) \ 50 + ) 51 + 52 + /* Field Macros */ 53 + 54 + #define FIELD_START(field) (0 ? field) 55 + #define FIELD_END(field) (1 ? field) 56 + #define FIELD_SIZE(field) \ 57 + (1 + FIELD_END(field) - FIELD_START(field)) 58 + 59 + #define FIELD_MASK(field) \ 60 + (((1 << (FIELD_SIZE(field)-1)) \ 61 + | ((1 << (FIELD_SIZE(field)-1)) - 1)) \ 62 + << FIELD_START(field)) 63 + 64 + #define FIELD_NORMALIZE(reg, field) \ 65 + (((reg) & FIELD_MASK(field)) >> FIELD_START(field)) 66 + 67 + #define FIELD_DENORMALIZE(field, value) \ 68 + (((value) << FIELD_START(field)) & FIELD_MASK(field)) 69 + 70 + #define FIELD_INIT(reg, field, value) \ 71 + FIELD_DENORMALIZE(reg ## _ ## field, \ 72 + reg ## _ ## field ## _ ## value) 73 + 74 + #define FIELD_INIT_VAL(reg, field, value) \ 75 + (FIELD_DENORMALIZE(reg ## _ ## field, value)) 76 + 77 + #define FIELD_VAL_SET(x, r, f, v) ({ \ 78 + x = (x & ~FIELD_MASK(r ## _ ## f)) \ 79 + | FIELD_DENORMALIZE(r ## _ ## f, r ## _ ## f ## _ ## v) \ 80 + }) 81 + 82 + #define RGB(r, g, b) ((unsigned long)(((r) << 16) | ((g) << 8) | (b))) 83 + 84 + /* Transparent info definition */ 85 + typedef struct { 86 + unsigned long match; /* Matching pixel is OPAQUE/TRANSPARENT */ 87 + unsigned long select; /* Transparency controlled by SRC/DST */ 88 + unsigned long control; /* ENABLE/DISABLE transparency */ 89 + unsigned long color; /* Transparent color */ 90 + } Transparent, *pTransparent; 91 + 92 + #define PIXEL_DEPTH_1_BP 0 /* 1 bit per pixel */ 93 + #define PIXEL_DEPTH_8_BPP 1 /* 8 bits per pixel */ 94 + #define PIXEL_DEPTH_16_BPP 2 /* 16 bits per pixel */ 95 + #define PIXEL_DEPTH_32_BPP 3 /* 32 bits per pixel */ 96 + #define PIXEL_DEPTH_YUV422 8 /* 16 bits per pixel YUV422 */ 97 + #define PIXEL_DEPTH_YUV420 9 /* 16 bits per pixel YUV420 */ 98 + 99 + #define PATTERN_WIDTH 8 100 + #define PATTERN_HEIGHT 8 101 + 102 + #define TOP_TO_BOTTOM 0 103 + #define BOTTOM_TO_TOP 1 104 + #define RIGHT_TO_LEFT BOTTOM_TO_TOP 105 + #define LEFT_TO_RIGHT TOP_TO_BOTTOM 106 + 107 + /* Constants used in Transparent structure */ 108 + #define MATCH_OPAQUE 0x00000000 109 + #define MATCH_TRANSPARENT 0x00000400 110 + #define SOURCE 0x00000000 111 + #define DESTINATION 0x00000200 112 + 113 + /* 2D registers. */ 114 + 115 + #define DE_SOURCE 0x000000 116 + #define DE_SOURCE_WRAP 31 : 31 117 + #define DE_SOURCE_WRAP_DISABLE 0 118 + #define DE_SOURCE_WRAP_ENABLE 1 119 + #define DE_SOURCE_X_K1 29 : 16 120 + #define DE_SOURCE_Y_K2 15 : 0 121 + 122 + #define DE_DESTINATION 0x000004 123 + #define DE_DESTINATION_WRAP 31 : 31 124 + #define DE_DESTINATION_WRAP_DISABLE 0 125 + #define DE_DESTINATION_WRAP_ENABLE 1 126 + #define DE_DESTINATION_X 28 : 16 127 + #define DE_DESTINATION_Y 15 : 0 128 + 129 + #define DE_DIMENSION 0x000008 130 + #define DE_DIMENSION_X 28 : 16 131 + #define DE_DIMENSION_Y_ET 15 : 0 132 + 133 + #define DE_CONTROL 0x00000C 134 + #define DE_CONTROL_STATUS 31 : 31 135 + #define DE_CONTROL_STATUS_STOP 0 136 + #define DE_CONTROL_STATUS_START 1 137 + #define DE_CONTROL_PATTERN 30 : 30 138 + #define DE_CONTROL_PATTERN_MONO 0 139 + #define DE_CONTROL_PATTERN_COLOR 1 140 + #define DE_CONTROL_UPDATE_DESTINATION_X 29 : 29 141 + #define DE_CONTROL_UPDATE_DESTINATION_X_DISABLE 0 142 + #define DE_CONTROL_UPDATE_DESTINATION_X_ENABLE 1 143 + #define DE_CONTROL_QUICK_START 28 : 28 144 + #define DE_CONTROL_QUICK_START_DISABLE 0 145 + #define DE_CONTROL_QUICK_START_ENABLE 1 146 + #define DE_CONTROL_DIRECTION 27 : 27 147 + #define DE_CONTROL_DIRECTION_LEFT_TO_RIGHT 0 148 + #define DE_CONTROL_DIRECTION_RIGHT_TO_LEFT 1 149 + #define DE_CONTROL_MAJOR 26 : 26 150 + #define DE_CONTROL_MAJOR_X 0 151 + #define DE_CONTROL_MAJOR_Y 1 152 + #define DE_CONTROL_STEP_X 25 : 25 153 + #define DE_CONTROL_STEP_X_POSITIVE 1 154 + #define DE_CONTROL_STEP_X_NEGATIVE 0 155 + #define DE_CONTROL_STEP_Y 24 : 24 156 + #define DE_CONTROL_STEP_Y_POSITIVE 1 157 + #define DE_CONTROL_STEP_Y_NEGATIVE 0 158 + #define DE_CONTROL_STRETCH 23 : 23 159 + #define DE_CONTROL_STRETCH_DISABLE 0 160 + #define DE_CONTROL_STRETCH_ENABLE 1 161 + #define DE_CONTROL_HOST 22 : 22 162 + #define DE_CONTROL_HOST_COLOR 0 163 + #define DE_CONTROL_HOST_MONO 1 164 + #define DE_CONTROL_LAST_PIXEL 21 : 21 165 + #define DE_CONTROL_LAST_PIXEL_OFF 0 166 + #define DE_CONTROL_LAST_PIXEL_ON 1 167 + #define DE_CONTROL_COMMAND 20 : 16 168 + #define DE_CONTROL_COMMAND_BITBLT 0 169 + #define DE_CONTROL_COMMAND_RECTANGLE_FILL 1 170 + #define DE_CONTROL_COMMAND_DE_TILE 2 171 + #define DE_CONTROL_COMMAND_TRAPEZOID_FILL 3 172 + #define DE_CONTROL_COMMAND_ALPHA_BLEND 4 173 + #define DE_CONTROL_COMMAND_RLE_STRIP 5 174 + #define DE_CONTROL_COMMAND_SHORT_STROKE 6 175 + #define DE_CONTROL_COMMAND_LINE_DRAW 7 176 + #define DE_CONTROL_COMMAND_HOST_WRITE 8 177 + #define DE_CONTROL_COMMAND_HOST_READ 9 178 + #define DE_CONTROL_COMMAND_HOST_WRITE_BOTTOM_UP 10 179 + #define DE_CONTROL_COMMAND_ROTATE 11 180 + #define DE_CONTROL_COMMAND_FONT 12 181 + #define DE_CONTROL_COMMAND_TEXTURE_LOAD 15 182 + #define DE_CONTROL_ROP_SELECT 15 : 15 183 + #define DE_CONTROL_ROP_SELECT_ROP3 0 184 + #define DE_CONTROL_ROP_SELECT_ROP2 1 185 + #define DE_CONTROL_ROP2_SOURCE 14 : 14 186 + #define DE_CONTROL_ROP2_SOURCE_BITMAP 0 187 + #define DE_CONTROL_ROP2_SOURCE_PATTERN 1 188 + #define DE_CONTROL_MONO_DATA 13 : 12 189 + #define DE_CONTROL_MONO_DATA_NOT_PACKED 0 190 + #define DE_CONTROL_MONO_DATA_8_PACKED 1 191 + #define DE_CONTROL_MONO_DATA_16_PACKED 2 192 + #define DE_CONTROL_MONO_DATA_32_PACKED 3 193 + #define DE_CONTROL_REPEAT_ROTATE 11 : 11 194 + #define DE_CONTROL_REPEAT_ROTATE_DISABLE 0 195 + #define DE_CONTROL_REPEAT_ROTATE_ENABLE 1 196 + #define DE_CONTROL_TRANSPARENCY_MATCH 10 : 10 197 + #define DE_CONTROL_TRANSPARENCY_MATCH_OPAQUE 0 198 + #define DE_CONTROL_TRANSPARENCY_MATCH_TRANSPARENT 1 199 + #define DE_CONTROL_TRANSPARENCY_SELECT 9 : 9 200 + #define DE_CONTROL_TRANSPARENCY_SELECT_SOURCE 0 201 + #define DE_CONTROL_TRANSPARENCY_SELECT_DESTINATION 1 202 + #define DE_CONTROL_TRANSPARENCY 8 : 8 203 + #define DE_CONTROL_TRANSPARENCY_DISABLE 0 204 + #define DE_CONTROL_TRANSPARENCY_ENABLE 1 205 + #define DE_CONTROL_ROP 7 : 0 206 + 207 + /* Pseudo fields. */ 208 + 209 + #define DE_CONTROL_SHORT_STROKE_DIR 27 : 24 210 + #define DE_CONTROL_SHORT_STROKE_DIR_225 0 211 + #define DE_CONTROL_SHORT_STROKE_DIR_135 1 212 + #define DE_CONTROL_SHORT_STROKE_DIR_315 2 213 + #define DE_CONTROL_SHORT_STROKE_DIR_45 3 214 + #define DE_CONTROL_SHORT_STROKE_DIR_270 4 215 + #define DE_CONTROL_SHORT_STROKE_DIR_90 5 216 + #define DE_CONTROL_SHORT_STROKE_DIR_180 8 217 + #define DE_CONTROL_SHORT_STROKE_DIR_0 10 218 + #define DE_CONTROL_ROTATION 25 : 24 219 + #define DE_CONTROL_ROTATION_0 0 220 + #define DE_CONTROL_ROTATION_270 1 221 + #define DE_CONTROL_ROTATION_90 2 222 + #define DE_CONTROL_ROTATION_180 3 223 + 224 + #define DE_PITCH 0x000010 225 + #define DE_PITCH_DESTINATION 28 : 16 226 + #define DE_PITCH_SOURCE 12 : 0 227 + 228 + #define DE_FOREGROUND 0x000014 229 + #define DE_FOREGROUND_COLOR 31 : 0 230 + 231 + #define DE_BACKGROUND 0x000018 232 + #define DE_BACKGROUND_COLOR 31 : 0 233 + 234 + #define DE_STRETCH_FORMAT 0x00001C 235 + #define DE_STRETCH_FORMAT_PATTERN_XY 30 : 30 236 + #define DE_STRETCH_FORMAT_PATTERN_XY_NORMAL 0 237 + #define DE_STRETCH_FORMAT_PATTERN_XY_OVERWRITE 1 238 + #define DE_STRETCH_FORMAT_PATTERN_Y 29 : 27 239 + #define DE_STRETCH_FORMAT_PATTERN_X 25 : 23 240 + #define DE_STRETCH_FORMAT_PIXEL_FORMAT 21 : 20 241 + #define DE_STRETCH_FORMAT_PIXEL_FORMAT_8 0 242 + #define DE_STRETCH_FORMAT_PIXEL_FORMAT_16 1 243 + #define DE_STRETCH_FORMAT_PIXEL_FORMAT_24 3 244 + #define DE_STRETCH_FORMAT_PIXEL_FORMAT_32 2 245 + #define DE_STRETCH_FORMAT_ADDRESSING 19 : 16 246 + #define DE_STRETCH_FORMAT_ADDRESSING_XY 0 247 + #define DE_STRETCH_FORMAT_ADDRESSING_LINEAR 15 248 + #define DE_STRETCH_FORMAT_SOURCE_HEIGHT 11 : 0 249 + 250 + #define DE_COLOR_COMPARE 0x000020 251 + #define DE_COLOR_COMPARE_COLOR 23 : 0 252 + 253 + #define DE_COLOR_COMPARE_MASK 0x000024 254 + #define DE_COLOR_COMPARE_MASK_MASKS 23 : 0 255 + 256 + #define DE_MASKS 0x000028 257 + #define DE_MASKS_BYTE_MASK 31 : 16 258 + #define DE_MASKS_BIT_MASK 15 : 0 259 + 260 + #define DE_CLIP_TL 0x00002C 261 + #define DE_CLIP_TL_TOP 31 : 16 262 + #define DE_CLIP_TL_STATUS 13 : 13 263 + #define DE_CLIP_TL_STATUS_DISABLE 0 264 + #define DE_CLIP_TL_STATUS_ENABLE 1 265 + #define DE_CLIP_TL_INHIBIT 12 : 12 266 + #define DE_CLIP_TL_INHIBIT_OUTSIDE 0 267 + #define DE_CLIP_TL_INHIBIT_INSIDE 1 268 + #define DE_CLIP_TL_LEFT 11 : 0 269 + 270 + #define DE_CLIP_BR 0x000030 271 + #define DE_CLIP_BR_BOTTOM 31 : 16 272 + #define DE_CLIP_BR_RIGHT 12 : 0 273 + 274 + #define DE_MONO_PATTERN_LOW 0x000034 275 + #define DE_MONO_PATTERN_LOW_PATTERN 31 : 0 276 + 277 + #define DE_MONO_PATTERN_HIGH 0x000038 278 + #define DE_MONO_PATTERN_HIGH_PATTERN 31 : 0 279 + 280 + #define DE_WINDOW_WIDTH 0x00003C 281 + #define DE_WINDOW_WIDTH_DESTINATION 28 : 16 282 + #define DE_WINDOW_WIDTH_SOURCE 12 : 0 283 + 284 + #define DE_WINDOW_SOURCE_BASE 0x000040 285 + #define DE_WINDOW_SOURCE_BASE_EXT 27 : 27 286 + #define DE_WINDOW_SOURCE_BASE_EXT_LOCAL 0 287 + #define DE_WINDOW_SOURCE_BASE_EXT_EXTERNAL 1 288 + #define DE_WINDOW_SOURCE_BASE_CS 26 : 26 289 + #define DE_WINDOW_SOURCE_BASE_CS_0 0 290 + #define DE_WINDOW_SOURCE_BASE_CS_1 1 291 + #define DE_WINDOW_SOURCE_BASE_ADDRESS 25 : 0 292 + 293 + #define DE_WINDOW_DESTINATION_BASE 0x000044 294 + #define DE_WINDOW_DESTINATION_BASE_EXT 27 : 27 295 + #define DE_WINDOW_DESTINATION_BASE_EXT_LOCAL 0 296 + #define DE_WINDOW_DESTINATION_BASE_EXT_EXTERNAL 1 297 + #define DE_WINDOW_DESTINATION_BASE_CS 26 : 26 298 + #define DE_WINDOW_DESTINATION_BASE_CS_0 0 299 + #define DE_WINDOW_DESTINATION_BASE_CS_1 1 300 + #define DE_WINDOW_DESTINATION_BASE_ADDRESS 25 : 0 301 + 302 + #define DE_ALPHA 0x000048 303 + #define DE_ALPHA_VALUE 7 : 0 304 + 305 + #define DE_WRAP 0x00004C 306 + #define DE_WRAP_X 31 : 16 307 + #define DE_WRAP_Y 15 : 0 308 + 309 + #define DE_STATUS 0x000050 310 + #define DE_STATUS_CSC 1 : 1 311 + #define DE_STATUS_CSC_CLEAR 0 312 + #define DE_STATUS_CSC_NOT_ACTIVE 0 313 + #define DE_STATUS_CSC_ACTIVE 1 314 + #define DE_STATUS_2D 0 : 0 315 + #define DE_STATUS_2D_CLEAR 0 316 + #define DE_STATUS_2D_NOT_ACTIVE 0 317 + #define DE_STATUS_2D_ACTIVE 1 318 + 319 + /* Color Space Conversion registers. */ 320 + 321 + #define CSC_Y_SOURCE_BASE 0x0000C8 322 + #define CSC_Y_SOURCE_BASE_EXT 27 : 27 323 + #define CSC_Y_SOURCE_BASE_EXT_LOCAL 0 324 + #define CSC_Y_SOURCE_BASE_EXT_EXTERNAL 1 325 + #define CSC_Y_SOURCE_BASE_CS 26 : 26 326 + #define CSC_Y_SOURCE_BASE_CS_0 0 327 + #define CSC_Y_SOURCE_BASE_CS_1 1 328 + #define CSC_Y_SOURCE_BASE_ADDRESS 25 : 0 329 + 330 + #define CSC_CONSTANTS 0x0000CC 331 + #define CSC_CONSTANTS_Y 31 : 24 332 + #define CSC_CONSTANTS_R 23 : 16 333 + #define CSC_CONSTANTS_G 15 : 8 334 + #define CSC_CONSTANTS_B 7 : 0 335 + 336 + #define CSC_Y_SOURCE_X 0x0000D0 337 + #define CSC_Y_SOURCE_X_INTEGER 26 : 16 338 + #define CSC_Y_SOURCE_X_FRACTION 15 : 3 339 + 340 + #define CSC_Y_SOURCE_Y 0x0000D4 341 + #define CSC_Y_SOURCE_Y_INTEGER 27 : 16 342 + #define CSC_Y_SOURCE_Y_FRACTION 15 : 3 343 + 344 + #define CSC_U_SOURCE_BASE 0x0000D8 345 + #define CSC_U_SOURCE_BASE_EXT 27 : 27 346 + #define CSC_U_SOURCE_BASE_EXT_LOCAL 0 347 + #define CSC_U_SOURCE_BASE_EXT_EXTERNAL 1 348 + #define CSC_U_SOURCE_BASE_CS 26 : 26 349 + #define CSC_U_SOURCE_BASE_CS_0 0 350 + #define CSC_U_SOURCE_BASE_CS_1 1 351 + #define CSC_U_SOURCE_BASE_ADDRESS 25 : 0 352 + 353 + #define CSC_V_SOURCE_BASE 0x0000DC 354 + #define CSC_V_SOURCE_BASE_EXT 27 : 27 355 + #define CSC_V_SOURCE_BASE_EXT_LOCAL 0 356 + #define CSC_V_SOURCE_BASE_EXT_EXTERNAL 1 357 + #define CSC_V_SOURCE_BASE_CS 26 : 26 358 + #define CSC_V_SOURCE_BASE_CS_0 0 359 + #define CSC_V_SOURCE_BASE_CS_1 1 360 + #define CSC_V_SOURCE_BASE_ADDRESS 25 : 0 361 + 362 + #define CSC_SOURCE_DIMENSION 0x0000E0 363 + #define CSC_SOURCE_DIMENSION_X 31 : 16 364 + #define CSC_SOURCE_DIMENSION_Y 15 : 0 365 + 366 + #define CSC_SOURCE_PITCH 0x0000E4 367 + #define CSC_SOURCE_PITCH_Y 31 : 16 368 + #define CSC_SOURCE_PITCH_UV 15 : 0 369 + 370 + #define CSC_DESTINATION 0x0000E8 371 + #define CSC_DESTINATION_WRAP 31 : 31 372 + #define CSC_DESTINATION_WRAP_DISABLE 0 373 + #define CSC_DESTINATION_WRAP_ENABLE 1 374 + #define CSC_DESTINATION_X 27 : 16 375 + #define CSC_DESTINATION_Y 11 : 0 376 + 377 + #define CSC_DESTINATION_DIMENSION 0x0000EC 378 + #define CSC_DESTINATION_DIMENSION_X 31 : 16 379 + #define CSC_DESTINATION_DIMENSION_Y 15 : 0 380 + 381 + #define CSC_DESTINATION_PITCH 0x0000F0 382 + #define CSC_DESTINATION_PITCH_X 31 : 16 383 + #define CSC_DESTINATION_PITCH_Y 15 : 0 384 + 385 + #define CSC_SCALE_FACTOR 0x0000F4 386 + #define CSC_SCALE_FACTOR_HORIZONTAL 31 : 16 387 + #define CSC_SCALE_FACTOR_VERTICAL 15 : 0 388 + 389 + #define CSC_DESTINATION_BASE 0x0000F8 390 + #define CSC_DESTINATION_BASE_EXT 27 : 27 391 + #define CSC_DESTINATION_BASE_EXT_LOCAL 0 392 + #define CSC_DESTINATION_BASE_EXT_EXTERNAL 1 393 + #define CSC_DESTINATION_BASE_CS 26 : 26 394 + #define CSC_DESTINATION_BASE_CS_0 0 395 + #define CSC_DESTINATION_BASE_CS_1 1 396 + #define CSC_DESTINATION_BASE_ADDRESS 25 : 0 397 + 398 + #define CSC_CONTROL 0x0000FC 399 + #define CSC_CONTROL_STATUS 31 : 31 400 + #define CSC_CONTROL_STATUS_STOP 0 401 + #define CSC_CONTROL_STATUS_START 1 402 + #define CSC_CONTROL_SOURCE_FORMAT 30 : 28 403 + #define CSC_CONTROL_SOURCE_FORMAT_YUV422 0 404 + #define CSC_CONTROL_SOURCE_FORMAT_YUV420I 1 405 + #define CSC_CONTROL_SOURCE_FORMAT_YUV420 2 406 + #define CSC_CONTROL_SOURCE_FORMAT_YVU9 3 407 + #define CSC_CONTROL_SOURCE_FORMAT_IYU1 4 408 + #define CSC_CONTROL_SOURCE_FORMAT_IYU2 5 409 + #define CSC_CONTROL_SOURCE_FORMAT_RGB565 6 410 + #define CSC_CONTROL_SOURCE_FORMAT_RGB8888 7 411 + #define CSC_CONTROL_DESTINATION_FORMAT 27 : 26 412 + #define CSC_CONTROL_DESTINATION_FORMAT_RGB565 0 413 + #define CSC_CONTROL_DESTINATION_FORMAT_RGB8888 1 414 + #define CSC_CONTROL_HORIZONTAL_FILTER 25 : 25 415 + #define CSC_CONTROL_HORIZONTAL_FILTER_DISABLE 0 416 + #define CSC_CONTROL_HORIZONTAL_FILTER_ENABLE 1 417 + #define CSC_CONTROL_VERTICAL_FILTER 24 : 24 418 + #define CSC_CONTROL_VERTICAL_FILTER_DISABLE 0 419 + #define CSC_CONTROL_VERTICAL_FILTER_ENABLE 1 420 + #define CSC_CONTROL_BYTE_ORDER 23 : 23 421 + #define CSC_CONTROL_BYTE_ORDER_YUYV 0 422 + #define CSC_CONTROL_BYTE_ORDER_UYVY 1 423 + 424 + #define DE_DATA_PORT_501 0x110000 425 + #define DE_DATA_PORT_712 0x400000 426 + #define DE_DATA_PORT_722 0x6000 427 + 428 + /* point to virtual Memory Map IO starting address */ 429 + extern char *smtc_RegBaseAddress; 430 + /* point to virtual video memory starting address */ 431 + extern char *smtc_VRAMBaseAddress; 432 + extern unsigned char smtc_de_busy; 433 + 434 + extern unsigned long memRead32(unsigned long nOffset); 435 + extern void memWrite32(unsigned long nOffset, unsigned long nData); 436 + extern unsigned long SMTC_read2Dreg(unsigned long nOffset); 437 + 438 + /* 2D functions */ 439 + extern void deInit(unsigned int nModeWidth, unsigned int nModeHeight, 440 + unsigned int bpp); 441 + 442 + extern void deWaitForNotBusy(void); 443 + 444 + extern void deVerticalLine(unsigned long dst_base, 445 + unsigned long dst_pitch, 446 + unsigned long nX, 447 + unsigned long nY, 448 + unsigned long dst_height, 449 + unsigned long nColor); 450 + 451 + extern void deHorizontalLine(unsigned long dst_base, 452 + unsigned long dst_pitch, 453 + unsigned long nX, 454 + unsigned long nY, 455 + unsigned long dst_width, 456 + unsigned long nColor); 457 + 458 + extern void deLine(unsigned long dst_base, 459 + unsigned long dst_pitch, 460 + unsigned long nX1, 461 + unsigned long nY1, 462 + unsigned long nX2, 463 + unsigned long nY2, 464 + unsigned long nColor); 465 + 466 + extern void deFillRect(unsigned long dst_base, 467 + unsigned long dst_pitch, 468 + unsigned long dst_X, 469 + unsigned long dst_Y, 470 + unsigned long dst_width, 471 + unsigned long dst_height, 472 + unsigned long nColor); 473 + 474 + extern void deRotatePattern(unsigned char *pattern_dstaddr, 475 + unsigned long pattern_src_addr, 476 + unsigned long pattern_BPP, 477 + unsigned long pattern_stride, 478 + int patternX, 479 + int patternY); 480 + 481 + extern void deCopy(unsigned long dst_base, 482 + unsigned long dst_pitch, 483 + unsigned long dst_BPP, 484 + unsigned long dst_X, 485 + unsigned long dst_Y, 486 + unsigned long dst_width, 487 + unsigned long dst_height, 488 + unsigned long src_base, 489 + unsigned long src_pitch, 490 + unsigned long src_X, 491 + unsigned long src_Y, 492 + pTransparent pTransp, 493 + unsigned char nROP2); 494 + 495 + /* 496 + * System memory to Video memory monochrome expansion. 497 + * 498 + * Source is monochrome image in system memory. This function expands the 499 + * monochrome data to color image in video memory. 500 + * 501 + * @pSrcbuf: pointer to start of source buffer in system memory 502 + * @srcDelta: Pitch value (in bytes) of the source buffer, +ive means top 503 + * down and -ive mean button up 504 + * @startBit: Mono data can start at any bit in a byte, this value should 505 + * be 0 to 7 506 + * @dBase: Address of destination : offset in frame buffer 507 + * @dPitch: Pitch value of destination surface in BYTE 508 + * @bpp: Color depth of destination surface 509 + * @dx, dy: Starting coordinate of destination surface 510 + * @width, height: width and height of rectange in pixel value 511 + * @fColor,bColor: Foreground, Background color (corresponding to a 1, 0 in 512 + * the monochrome data) 513 + * @rop2: ROP value 514 + */ 515 + 516 + extern long deSystemMem2VideoMemMonoBlt( 517 + const char *pSrcbuf, 518 + long srcDelta, 519 + unsigned long startBit, 520 + unsigned long dBase, 521 + unsigned long dPitch, 522 + unsigned long bpp, 523 + unsigned long dx, unsigned long dy, 524 + unsigned long width, unsigned long height, 525 + unsigned long fColor, 526 + unsigned long bColor, 527 + unsigned long rop2); 528 + 529 + extern unsigned long deGetTransparency(void); 530 + extern void deSetPixelFormat(unsigned long bpp);
+1253
drivers/staging/sm7xx/smtcfb.c
··· 1 + /* 2 + * Silicon Motion SM7XX frame buffer device 3 + * 4 + * Copyright (C) 2006 Silicon Motion Technology Corp. 5 + * Authors: Ge Wang, gewang@siliconmotion.com 6 + * Boyod boyod.yang@siliconmotion.com.cn 7 + * 8 + * Copyright (C) 2009 Lemote, Inc. 9 + * Author: Wu Zhangjin, wuzj@lemote.com 10 + * 11 + * This file is subject to the terms and conditions of the GNU General Public 12 + * License. See the file COPYING in the main directory of this archive for 13 + * more details. 14 + * 15 + * Version 0.10.26192.21.01 16 + * - Add PowerPC/Big endian support 17 + * - Add 2D support for Lynx 18 + * - Verified on2.6.19.2 Boyod.yang <boyod.yang@siliconmotion.com.cn> 19 + * 20 + * Version 0.09.2621.00.01 21 + * - Only support Linux Kernel's version 2.6.21. 22 + * Boyod.yang <boyod.yang@siliconmotion.com.cn> 23 + * 24 + * Version 0.09 25 + * - Only support Linux Kernel's version 2.6.12. 26 + * Boyod.yang <boyod.yang@siliconmotion.com.cn> 27 + */ 28 + 29 + #ifndef __KERNEL__ 30 + #define __KERNEL__ 31 + #endif 32 + 33 + #include <linux/io.h> 34 + #include <linux/fb.h> 35 + #include <linux/pci.h> 36 + #include <linux/init.h> 37 + #include <linux/uaccess.h> 38 + #include <linux/console.h> 39 + #include <linux/screen_info.h> 40 + 41 + #ifdef CONFIG_PM 42 + #include <linux/pm.h> 43 + #endif 44 + 45 + struct screen_info smtc_screen_info; 46 + 47 + #include "smtcfb.h" 48 + #include "smtc2d.h" 49 + 50 + #ifdef DEBUG 51 + #define smdbg(format, arg...) printk(KERN_DEBUG format , ## arg) 52 + #else 53 + #define smdbg(format, arg...) 54 + #endif 55 + 56 + /* 57 + * Private structure 58 + */ 59 + struct smtcfb_info { 60 + /* 61 + * The following is a pointer to be passed into the 62 + * functions below. The modules outside the main 63 + * voyager.c driver have no knowledge as to what 64 + * is within this structure. 65 + */ 66 + struct fb_info fb; 67 + struct display_switch *dispsw; 68 + struct pci_dev *dev; 69 + signed int currcon; 70 + 71 + struct { 72 + u8 red, green, blue; 73 + } palette[NR_RGB]; 74 + 75 + u_int palette_size; 76 + }; 77 + 78 + struct par_info { 79 + /* 80 + * Hardware 81 + */ 82 + u16 chipID; 83 + unsigned char __iomem *m_pMMIO; 84 + char __iomem *m_pLFB; 85 + char *m_pDPR; 86 + char *m_pVPR; 87 + char *m_pCPR; 88 + 89 + u_int width; 90 + u_int height; 91 + u_int hz; 92 + u_long BaseAddressInVRAM; 93 + u8 chipRevID; 94 + }; 95 + 96 + struct vesa_mode_table { 97 + char mode_index[6]; 98 + u16 lfb_width; 99 + u16 lfb_height; 100 + u16 lfb_depth; 101 + }; 102 + 103 + static struct vesa_mode_table vesa_mode[] = { 104 + {"0x301", 640, 480, 8}, 105 + {"0x303", 800, 600, 8}, 106 + {"0x305", 1024, 768, 8}, 107 + {"0x307", 1280, 1024, 8}, 108 + 109 + {"0x311", 640, 480, 16}, 110 + {"0x314", 800, 600, 16}, 111 + {"0x317", 1024, 768, 16}, 112 + {"0x31A", 1280, 1024, 16}, 113 + 114 + {"0x312", 640, 480, 24}, 115 + {"0x315", 800, 600, 24}, 116 + {"0x318", 1024, 768, 24}, 117 + {"0x31B", 1280, 1024, 24}, 118 + }; 119 + 120 + char __iomem *smtc_RegBaseAddress; /* Memory Map IO starting address */ 121 + char __iomem *smtc_VRAMBaseAddress; /* video memory starting address */ 122 + 123 + char *smtc_2DBaseAddress; /* 2D engine starting address */ 124 + char *smtc_2Ddataport; /* 2D data port offset */ 125 + short smtc_2Dacceleration; 126 + 127 + static u32 colreg[17]; 128 + static struct par_info hw; /* hardware information */ 129 + 130 + u16 smtc_ChipIDs[] = { 131 + 0x710, 132 + 0x712, 133 + 0x720 134 + }; 135 + 136 + #define numSMTCchipIDs (sizeof(smtc_ChipIDs) / sizeof(u16)) 137 + 138 + void deWaitForNotBusy(void) 139 + { 140 + unsigned long i = 0x1000000; 141 + while (i--) { 142 + if ((smtc_seqr(0x16) & 0x18) == 0x10) 143 + break; 144 + } 145 + smtc_de_busy = 0; 146 + } 147 + 148 + static void sm712_set_timing(struct smtcfb_info *sfb, 149 + struct par_info *ppar_info) 150 + { 151 + int i = 0, j = 0; 152 + u32 m_nScreenStride; 153 + 154 + smdbg("\nppar_info->width = %d ppar_info->height = %d" 155 + "sfb->fb.var.bits_per_pixel = %d ppar_info->hz = %d\n", 156 + ppar_info->width, ppar_info->height, 157 + sfb->fb.var.bits_per_pixel, ppar_info->hz); 158 + 159 + for (j = 0; j < numVGAModes; j++) { 160 + if (VGAMode[j].mmSizeX == ppar_info->width && 161 + VGAMode[j].mmSizeY == ppar_info->height && 162 + VGAMode[j].bpp == sfb->fb.var.bits_per_pixel && 163 + VGAMode[j].hz == ppar_info->hz) { 164 + 165 + smdbg("\nVGAMode[j].mmSizeX = %d VGAMode[j].mmSizeY =" 166 + "%d VGAMode[j].bpp = %d" 167 + "VGAMode[j].hz=%d\n", 168 + VGAMode[j].mmSizeX, VGAMode[j].mmSizeY, 169 + VGAMode[j].bpp, VGAMode[j].hz); 170 + 171 + smdbg("VGAMode index=%d\n", j); 172 + 173 + smtc_mmiowb(0x0, 0x3c6); 174 + 175 + smtc_seqw(0, 0x1); 176 + 177 + smtc_mmiowb(VGAMode[j].Init_MISC, 0x3c2); 178 + 179 + /* init SEQ register SR00 - SR04 */ 180 + for (i = 0; i < SIZE_SR00_SR04; i++) 181 + smtc_seqw(i, VGAMode[j].Init_SR00_SR04[i]); 182 + 183 + /* init SEQ register SR10 - SR24 */ 184 + for (i = 0; i < SIZE_SR10_SR24; i++) 185 + smtc_seqw(i + 0x10, 186 + VGAMode[j].Init_SR10_SR24[i]); 187 + 188 + /* init SEQ register SR30 - SR75 */ 189 + for (i = 0; i < SIZE_SR30_SR75; i++) 190 + if (((i + 0x30) != 0x62) \ 191 + && ((i + 0x30) != 0x6a) \ 192 + && ((i + 0x30) != 0x6b)) 193 + smtc_seqw(i + 0x30, 194 + VGAMode[j].Init_SR30_SR75[i]); 195 + 196 + /* init SEQ register SR80 - SR93 */ 197 + for (i = 0; i < SIZE_SR80_SR93; i++) 198 + smtc_seqw(i + 0x80, 199 + VGAMode[j].Init_SR80_SR93[i]); 200 + 201 + /* init SEQ register SRA0 - SRAF */ 202 + for (i = 0; i < SIZE_SRA0_SRAF; i++) 203 + smtc_seqw(i + 0xa0, 204 + VGAMode[j].Init_SRA0_SRAF[i]); 205 + 206 + /* init Graphic register GR00 - GR08 */ 207 + for (i = 0; i < SIZE_GR00_GR08; i++) 208 + smtc_grphw(i, VGAMode[j].Init_GR00_GR08[i]); 209 + 210 + /* init Attribute register AR00 - AR14 */ 211 + for (i = 0; i < SIZE_AR00_AR14; i++) 212 + smtc_attrw(i, VGAMode[j].Init_AR00_AR14[i]); 213 + 214 + /* init CRTC register CR00 - CR18 */ 215 + for (i = 0; i < SIZE_CR00_CR18; i++) 216 + smtc_crtcw(i, VGAMode[j].Init_CR00_CR18[i]); 217 + 218 + /* init CRTC register CR30 - CR4D */ 219 + for (i = 0; i < SIZE_CR30_CR4D; i++) 220 + smtc_crtcw(i + 0x30, 221 + VGAMode[j].Init_CR30_CR4D[i]); 222 + 223 + /* init CRTC register CR90 - CRA7 */ 224 + for (i = 0; i < SIZE_CR90_CRA7; i++) 225 + smtc_crtcw(i + 0x90, 226 + VGAMode[j].Init_CR90_CRA7[i]); 227 + } 228 + } 229 + smtc_mmiowb(0x67, 0x3c2); 230 + 231 + /* set VPR registers */ 232 + writel(0x0, ppar_info->m_pVPR + 0x0C); 233 + writel(0x0, ppar_info->m_pVPR + 0x40); 234 + 235 + /* set data width */ 236 + m_nScreenStride = 237 + (ppar_info->width * sfb->fb.var.bits_per_pixel) / 64; 238 + switch (sfb->fb.var.bits_per_pixel) { 239 + case 8: 240 + writel(0x0, ppar_info->m_pVPR + 0x0); 241 + break; 242 + case 16: 243 + writel(0x00020000, ppar_info->m_pVPR + 0x0); 244 + break; 245 + case 24: 246 + writel(0x00040000, ppar_info->m_pVPR + 0x0); 247 + break; 248 + case 32: 249 + writel(0x00030000, ppar_info->m_pVPR + 0x0); 250 + break; 251 + } 252 + writel((u32) (((m_nScreenStride + 2) << 16) | m_nScreenStride), 253 + ppar_info->m_pVPR + 0x10); 254 + 255 + } 256 + 257 + static void sm712_setpalette(int regno, unsigned red, unsigned green, 258 + unsigned blue, struct fb_info *info) 259 + { 260 + struct par_info *cur_par = (struct par_info *)info->par; 261 + 262 + if (cur_par->BaseAddressInVRAM) 263 + /* 264 + * second display palette for dual head. Enable CRT RAM, 6-bit 265 + * RAM 266 + */ 267 + smtc_seqw(0x66, (smtc_seqr(0x66) & 0xC3) | 0x20); 268 + else 269 + /* primary display palette. Enable LCD RAM only, 6-bit RAM */ 270 + smtc_seqw(0x66, (smtc_seqr(0x66) & 0xC3) | 0x10); 271 + smtc_mmiowb(regno, dac_reg); 272 + smtc_mmiowb(red >> 10, dac_val); 273 + smtc_mmiowb(green >> 10, dac_val); 274 + smtc_mmiowb(blue >> 10, dac_val); 275 + } 276 + 277 + static void smtc_set_timing(struct smtcfb_info *sfb, struct par_info 278 + *ppar_info) 279 + { 280 + switch (ppar_info->chipID) { 281 + case 0x710: 282 + case 0x712: 283 + case 0x720: 284 + sm712_set_timing(sfb, ppar_info); 285 + break; 286 + } 287 + } 288 + 289 + static struct fb_var_screeninfo smtcfb_var = { 290 + .xres = 1024, 291 + .yres = 600, 292 + .xres_virtual = 1024, 293 + .yres_virtual = 600, 294 + .bits_per_pixel = 16, 295 + .red = {16, 8, 0}, 296 + .green = {8, 8, 0}, 297 + .blue = {0, 8, 0}, 298 + .activate = FB_ACTIVATE_NOW, 299 + .height = -1, 300 + .width = -1, 301 + .vmode = FB_VMODE_NONINTERLACED, 302 + }; 303 + 304 + static struct fb_fix_screeninfo smtcfb_fix = { 305 + .id = "sm712fb", 306 + .type = FB_TYPE_PACKED_PIXELS, 307 + .visual = FB_VISUAL_TRUECOLOR, 308 + .line_length = 800 * 3, 309 + .accel = FB_ACCEL_SMI_LYNX, 310 + }; 311 + 312 + /* chan_to_field 313 + * 314 + * convert a colour value into a field position 315 + * 316 + * from pxafb.c 317 + */ 318 + 319 + static inline unsigned int chan_to_field(unsigned int chan, 320 + struct fb_bitfield *bf) 321 + { 322 + chan &= 0xffff; 323 + chan >>= 16 - bf->length; 324 + return chan << bf->offset; 325 + } 326 + 327 + static int smtcfb_blank(int blank_mode, struct fb_info *info) 328 + { 329 + /* clear DPMS setting */ 330 + switch (blank_mode) { 331 + case FB_BLANK_UNBLANK: 332 + /* Screen On: HSync: On, VSync : On */ 333 + smtc_seqw(0x01, (smtc_seqr(0x01) & (~0x20))); 334 + smtc_seqw(0x6a, 0x16); 335 + smtc_seqw(0x6b, 0x02); 336 + smtc_seqw(0x21, (smtc_seqr(0x21) & 0x77)); 337 + smtc_seqw(0x22, (smtc_seqr(0x22) & (~0x30))); 338 + smtc_seqw(0x23, (smtc_seqr(0x23) & (~0xc0))); 339 + smtc_seqw(0x24, (smtc_seqr(0x24) | 0x01)); 340 + smtc_seqw(0x31, (smtc_seqr(0x31) | 0x03)); 341 + break; 342 + case FB_BLANK_NORMAL: 343 + /* Screen Off: HSync: On, VSync : On Soft blank */ 344 + smtc_seqw(0x01, (smtc_seqr(0x01) & (~0x20))); 345 + smtc_seqw(0x6a, 0x16); 346 + smtc_seqw(0x6b, 0x02); 347 + smtc_seqw(0x22, (smtc_seqr(0x22) & (~0x30))); 348 + smtc_seqw(0x23, (smtc_seqr(0x23) & (~0xc0))); 349 + smtc_seqw(0x24, (smtc_seqr(0x24) | 0x01)); 350 + smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00)); 351 + break; 352 + case FB_BLANK_VSYNC_SUSPEND: 353 + /* Screen On: HSync: On, VSync : Off */ 354 + smtc_seqw(0x01, (smtc_seqr(0x01) | 0x20)); 355 + smtc_seqw(0x20, (smtc_seqr(0x20) & (~0xB0))); 356 + smtc_seqw(0x6a, 0x0c); 357 + smtc_seqw(0x6b, 0x02); 358 + smtc_seqw(0x21, (smtc_seqr(0x21) | 0x88)); 359 + smtc_seqw(0x22, ((smtc_seqr(0x22) & (~0x30)) | 0x20)); 360 + smtc_seqw(0x23, ((smtc_seqr(0x23) & (~0xc0)) | 0x20)); 361 + smtc_seqw(0x24, (smtc_seqr(0x24) & (~0x01))); 362 + smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00)); 363 + smtc_seqw(0x34, (smtc_seqr(0x34) | 0x80)); 364 + break; 365 + case FB_BLANK_HSYNC_SUSPEND: 366 + /* Screen On: HSync: Off, VSync : On */ 367 + smtc_seqw(0x01, (smtc_seqr(0x01) | 0x20)); 368 + smtc_seqw(0x20, (smtc_seqr(0x20) & (~0xB0))); 369 + smtc_seqw(0x6a, 0x0c); 370 + smtc_seqw(0x6b, 0x02); 371 + smtc_seqw(0x21, (smtc_seqr(0x21) | 0x88)); 372 + smtc_seqw(0x22, ((smtc_seqr(0x22) & (~0x30)) | 0x10)); 373 + smtc_seqw(0x23, ((smtc_seqr(0x23) & (~0xc0)) | 0xD8)); 374 + smtc_seqw(0x24, (smtc_seqr(0x24) & (~0x01))); 375 + smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00)); 376 + smtc_seqw(0x34, (smtc_seqr(0x34) | 0x80)); 377 + break; 378 + case FB_BLANK_POWERDOWN: 379 + /* Screen On: HSync: Off, VSync : Off */ 380 + smtc_seqw(0x01, (smtc_seqr(0x01) | 0x20)); 381 + smtc_seqw(0x20, (smtc_seqr(0x20) & (~0xB0))); 382 + smtc_seqw(0x6a, 0x0c); 383 + smtc_seqw(0x6b, 0x02); 384 + smtc_seqw(0x21, (smtc_seqr(0x21) | 0x88)); 385 + smtc_seqw(0x22, ((smtc_seqr(0x22) & (~0x30)) | 0x30)); 386 + smtc_seqw(0x23, ((smtc_seqr(0x23) & (~0xc0)) | 0xD8)); 387 + smtc_seqw(0x24, (smtc_seqr(0x24) & (~0x01))); 388 + smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00)); 389 + smtc_seqw(0x34, (smtc_seqr(0x34) | 0x80)); 390 + break; 391 + default: 392 + return -EINVAL; 393 + } 394 + 395 + return 0; 396 + } 397 + 398 + static int smtc_setcolreg(unsigned regno, unsigned red, unsigned green, 399 + unsigned blue, unsigned trans, struct fb_info *info) 400 + { 401 + struct smtcfb_info *sfb = (struct smtcfb_info *)info; 402 + u32 val; 403 + 404 + if (regno > 255) 405 + return 1; 406 + 407 + switch (sfb->fb.fix.visual) { 408 + case FB_VISUAL_DIRECTCOLOR: 409 + case FB_VISUAL_TRUECOLOR: 410 + /* 411 + * 16/32 bit true-colour, use pseuo-palette for 16 base color 412 + */ 413 + if (regno < 16) { 414 + if (sfb->fb.var.bits_per_pixel == 16) { 415 + u32 *pal = sfb->fb.pseudo_palette; 416 + val = chan_to_field(red, &sfb->fb.var.red); 417 + val |= chan_to_field(green, \ 418 + &sfb->fb.var.green); 419 + val |= chan_to_field(blue, &sfb->fb.var.blue); 420 + #ifdef __BIG_ENDIAN 421 + pal[regno] = 422 + ((red & 0xf800) >> 8) | 423 + ((green & 0xe000) >> 13) | 424 + ((green & 0x1c00) << 3) | 425 + ((blue & 0xf800) >> 3); 426 + #else 427 + pal[regno] = val; 428 + #endif 429 + } else { 430 + u32 *pal = sfb->fb.pseudo_palette; 431 + val = chan_to_field(red, &sfb->fb.var.red); 432 + val |= chan_to_field(green, \ 433 + &sfb->fb.var.green); 434 + val |= chan_to_field(blue, &sfb->fb.var.blue); 435 + #ifdef __BIG_ENDIAN 436 + val = 437 + (val & 0xff00ff00 >> 8) | 438 + (val & 0x00ff00ff << 8); 439 + #endif 440 + pal[regno] = val; 441 + } 442 + } 443 + break; 444 + 445 + case FB_VISUAL_PSEUDOCOLOR: 446 + /* color depth 8 bit */ 447 + sm712_setpalette(regno, red, green, blue, info); 448 + break; 449 + 450 + default: 451 + return 1; /* unknown type */ 452 + } 453 + 454 + return 0; 455 + 456 + } 457 + 458 + #ifdef __BIG_ENDIAN 459 + static ssize_t smtcfb_read(struct fb_info *info, char __user * buf, size_t 460 + count, loff_t *ppos) 461 + { 462 + unsigned long p = *ppos; 463 + 464 + u32 *buffer, *dst; 465 + u32 __iomem *src; 466 + int c, i, cnt = 0, err = 0; 467 + unsigned long total_size; 468 + 469 + if (!info || !info->screen_base) 470 + return -ENODEV; 471 + 472 + if (info->state != FBINFO_STATE_RUNNING) 473 + return -EPERM; 474 + 475 + total_size = info->screen_size; 476 + 477 + if (total_size == 0) 478 + total_size = info->fix.smem_len; 479 + 480 + if (p >= total_size) 481 + return 0; 482 + 483 + if (count >= total_size) 484 + count = total_size; 485 + 486 + if (count + p > total_size) 487 + count = total_size - p; 488 + 489 + buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count, GFP_KERNEL); 490 + if (!buffer) 491 + return -ENOMEM; 492 + 493 + src = (u32 __iomem *) (info->screen_base + p); 494 + 495 + if (info->fbops->fb_sync) 496 + info->fbops->fb_sync(info); 497 + 498 + while (count) { 499 + c = (count > PAGE_SIZE) ? PAGE_SIZE : count; 500 + dst = buffer; 501 + for (i = c >> 2; i--;) { 502 + *dst = fb_readl(src++); 503 + *dst = 504 + (*dst & 0xff00ff00 >> 8) | 505 + (*dst & 0x00ff00ff << 8); 506 + dst++; 507 + } 508 + if (c & 3) { 509 + u8 *dst8 = (u8 *) dst; 510 + u8 __iomem *src8 = (u8 __iomem *) src; 511 + 512 + for (i = c & 3; i--;) { 513 + if (i & 1) { 514 + *dst8++ = fb_readb(++src8); 515 + } else { 516 + *dst8++ = fb_readb(--src8); 517 + src8 += 2; 518 + } 519 + } 520 + src = (u32 __iomem *) src8; 521 + } 522 + 523 + if (copy_to_user(buf, buffer, c)) { 524 + err = -EFAULT; 525 + break; 526 + } 527 + *ppos += c; 528 + buf += c; 529 + cnt += c; 530 + count -= c; 531 + } 532 + 533 + kfree(buffer); 534 + 535 + return (err) ? err : cnt; 536 + } 537 + 538 + static ssize_t 539 + smtcfb_write(struct fb_info *info, const char __user *buf, size_t count, 540 + loff_t *ppos) 541 + { 542 + unsigned long p = *ppos; 543 + 544 + u32 *buffer, *src; 545 + u32 __iomem *dst; 546 + int c, i, cnt = 0, err = 0; 547 + unsigned long total_size; 548 + 549 + if (!info || !info->screen_base) 550 + return -ENODEV; 551 + 552 + if (info->state != FBINFO_STATE_RUNNING) 553 + return -EPERM; 554 + 555 + total_size = info->screen_size; 556 + 557 + if (total_size == 0) 558 + total_size = info->fix.smem_len; 559 + 560 + if (p > total_size) 561 + return -EFBIG; 562 + 563 + if (count > total_size) { 564 + err = -EFBIG; 565 + count = total_size; 566 + } 567 + 568 + if (count + p > total_size) { 569 + if (!err) 570 + err = -ENOSPC; 571 + 572 + count = total_size - p; 573 + } 574 + 575 + buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count, GFP_KERNEL); 576 + if (!buffer) 577 + return -ENOMEM; 578 + 579 + dst = (u32 __iomem *) (info->screen_base + p); 580 + 581 + if (info->fbops->fb_sync) 582 + info->fbops->fb_sync(info); 583 + 584 + while (count) { 585 + c = (count > PAGE_SIZE) ? PAGE_SIZE : count; 586 + src = buffer; 587 + 588 + if (copy_from_user(src, buf, c)) { 589 + err = -EFAULT; 590 + break; 591 + } 592 + 593 + for (i = c >> 2; i--;) { 594 + fb_writel((*src & 0xff00ff00 >> 8) | 595 + (*src & 0x00ff00ff << 8), dst++); 596 + src++; 597 + } 598 + if (c & 3) { 599 + u8 *src8 = (u8 *) src; 600 + u8 __iomem *dst8 = (u8 __iomem *) dst; 601 + 602 + for (i = c & 3; i--;) { 603 + if (i & 1) { 604 + fb_writeb(*src8++, ++dst8); 605 + } else { 606 + fb_writeb(*src8++, --dst8); 607 + dst8 += 2; 608 + } 609 + } 610 + dst = (u32 __iomem *) dst8; 611 + } 612 + 613 + *ppos += c; 614 + buf += c; 615 + cnt += c; 616 + count -= c; 617 + } 618 + 619 + kfree(buffer); 620 + 621 + return (cnt) ? cnt : err; 622 + } 623 + #endif /* ! __BIG_ENDIAN */ 624 + 625 + #include "smtc2d.c" 626 + 627 + void smtcfb_copyarea(struct fb_info *info, const struct fb_copyarea *area) 628 + { 629 + struct par_info *p = (struct par_info *)info->par; 630 + 631 + if (smtc_2Dacceleration) { 632 + if (!area->width || !area->height) 633 + return; 634 + 635 + deCopy(p->BaseAddressInVRAM, 0, info->var.bits_per_pixel, 636 + area->dx, area->dy, area->width, area->height, 637 + p->BaseAddressInVRAM, 0, area->sx, area->sy, 0, 0xC); 638 + 639 + } else 640 + cfb_copyarea(info, area); 641 + } 642 + 643 + void smtcfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) 644 + { 645 + struct par_info *p = (struct par_info *)info->par; 646 + 647 + if (smtc_2Dacceleration) { 648 + if (!rect->width || !rect->height) 649 + return; 650 + if (info->var.bits_per_pixel >= 24) 651 + deFillRect(p->BaseAddressInVRAM, 0, rect->dx * 3, 652 + rect->dy * 3, rect->width * 3, rect->height, 653 + rect->color); 654 + else 655 + deFillRect(p->BaseAddressInVRAM, 0, rect->dx, rect->dy, 656 + rect->width, rect->height, rect->color); 657 + } else 658 + cfb_fillrect(info, rect); 659 + } 660 + 661 + void smtcfb_imageblit(struct fb_info *info, const struct fb_image *image) 662 + { 663 + struct par_info *p = (struct par_info *)info->par; 664 + u32 bg_col = 0, fg_col = 0; 665 + 666 + if ((smtc_2Dacceleration) && (image->depth == 1)) { 667 + if (smtc_de_busy) 668 + deWaitForNotBusy(); 669 + 670 + switch (info->var.bits_per_pixel) { 671 + case 8: 672 + bg_col = image->bg_color; 673 + fg_col = image->fg_color; 674 + break; 675 + case 16: 676 + bg_col = 677 + ((u32 *) (info->pseudo_palette))[image->bg_color]; 678 + fg_col = 679 + ((u32 *) (info->pseudo_palette))[image->fg_color]; 680 + break; 681 + case 32: 682 + bg_col = 683 + ((u32 *) (info->pseudo_palette))[image->bg_color]; 684 + fg_col = 685 + ((u32 *) (info->pseudo_palette))[image->fg_color]; 686 + break; 687 + } 688 + 689 + deSystemMem2VideoMemMonoBlt( 690 + image->data, 691 + image->width / 8, 692 + 0, 693 + p->BaseAddressInVRAM, 694 + 0, 695 + 0, 696 + image->dx, image->dy, 697 + image->width, image->height, 698 + fg_col, bg_col, 699 + 0x0C); 700 + 701 + } else 702 + cfb_imageblit(info, image); 703 + } 704 + 705 + static struct fb_ops smtcfb_ops = { 706 + .owner = THIS_MODULE, 707 + .fb_setcolreg = smtc_setcolreg, 708 + .fb_blank = smtcfb_blank, 709 + .fb_fillrect = smtcfb_fillrect, 710 + .fb_imageblit = smtcfb_imageblit, 711 + .fb_copyarea = smtcfb_copyarea, 712 + #ifdef __BIG_ENDIAN 713 + .fb_read = smtcfb_read, 714 + .fb_write = smtcfb_write, 715 + #endif 716 + 717 + }; 718 + 719 + void smtcfb_setmode(struct smtcfb_info *sfb) 720 + { 721 + switch (sfb->fb.var.bits_per_pixel) { 722 + case 32: 723 + sfb->fb.fix.visual = FB_VISUAL_TRUECOLOR; 724 + sfb->fb.fix.line_length = sfb->fb.var.xres * 4; 725 + sfb->fb.var.red.length = 8; 726 + sfb->fb.var.green.length = 8; 727 + sfb->fb.var.blue.length = 8; 728 + sfb->fb.var.red.offset = 16; 729 + sfb->fb.var.green.offset = 8; 730 + sfb->fb.var.blue.offset = 0; 731 + 732 + break; 733 + case 8: 734 + sfb->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR; 735 + sfb->fb.fix.line_length = sfb->fb.var.xres; 736 + sfb->fb.var.red.offset = 5; 737 + sfb->fb.var.red.length = 3; 738 + sfb->fb.var.green.offset = 2; 739 + sfb->fb.var.green.length = 3; 740 + sfb->fb.var.blue.offset = 0; 741 + sfb->fb.var.blue.length = 2; 742 + break; 743 + case 24: 744 + sfb->fb.fix.visual = FB_VISUAL_TRUECOLOR; 745 + sfb->fb.fix.line_length = sfb->fb.var.xres * 3; 746 + sfb->fb.var.red.length = 8; 747 + sfb->fb.var.green.length = 8; 748 + sfb->fb.var.blue.length = 8; 749 + 750 + sfb->fb.var.red.offset = 16; 751 + sfb->fb.var.green.offset = 8; 752 + sfb->fb.var.blue.offset = 0; 753 + 754 + break; 755 + case 16: 756 + default: 757 + sfb->fb.fix.visual = FB_VISUAL_TRUECOLOR; 758 + sfb->fb.fix.line_length = sfb->fb.var.xres * 2; 759 + 760 + sfb->fb.var.red.length = 5; 761 + sfb->fb.var.green.length = 6; 762 + sfb->fb.var.blue.length = 5; 763 + 764 + sfb->fb.var.red.offset = 11; 765 + sfb->fb.var.green.offset = 5; 766 + sfb->fb.var.blue.offset = 0; 767 + 768 + break; 769 + } 770 + 771 + hw.width = sfb->fb.var.xres; 772 + hw.height = sfb->fb.var.yres; 773 + hw.hz = 60; 774 + smtc_set_timing(sfb, &hw); 775 + if (smtc_2Dacceleration) { 776 + printk("2D acceleration enabled!\n"); 777 + /* Init smtc drawing engine */ 778 + deInit(sfb->fb.var.xres, sfb->fb.var.yres, 779 + sfb->fb.var.bits_per_pixel); 780 + } 781 + } 782 + 783 + /* 784 + * Alloc struct smtcfb_info and assign the default value 785 + */ 786 + static struct smtcfb_info *smtc_alloc_fb_info(struct pci_dev *dev, 787 + char *name) 788 + { 789 + struct smtcfb_info *sfb; 790 + 791 + sfb = kmalloc(sizeof(struct smtcfb_info), GFP_KERNEL); 792 + 793 + if (!sfb) 794 + return NULL; 795 + 796 + memset(sfb, 0, sizeof(struct smtcfb_info)); 797 + 798 + sfb->currcon = -1; 799 + sfb->dev = dev; 800 + 801 + /*** Init sfb->fb with default value ***/ 802 + sfb->fb.flags = FBINFO_FLAG_DEFAULT; 803 + sfb->fb.fbops = &smtcfb_ops; 804 + sfb->fb.var = smtcfb_var; 805 + sfb->fb.fix = smtcfb_fix; 806 + 807 + strcpy(sfb->fb.fix.id, name); 808 + 809 + sfb->fb.fix.type = FB_TYPE_PACKED_PIXELS; 810 + sfb->fb.fix.type_aux = 0; 811 + sfb->fb.fix.xpanstep = 0; 812 + sfb->fb.fix.ypanstep = 0; 813 + sfb->fb.fix.ywrapstep = 0; 814 + sfb->fb.fix.accel = FB_ACCEL_SMI_LYNX; 815 + 816 + sfb->fb.var.nonstd = 0; 817 + sfb->fb.var.activate = FB_ACTIVATE_NOW; 818 + sfb->fb.var.height = -1; 819 + sfb->fb.var.width = -1; 820 + /* text mode acceleration */ 821 + sfb->fb.var.accel_flags = FB_ACCELF_TEXT; 822 + sfb->fb.var.vmode = FB_VMODE_NONINTERLACED; 823 + sfb->fb.par = &hw; 824 + sfb->fb.pseudo_palette = colreg; 825 + 826 + return sfb; 827 + } 828 + 829 + /* 830 + * Unmap in the memory mapped IO registers 831 + */ 832 + 833 + static void smtc_unmap_mmio(struct smtcfb_info *sfb) 834 + { 835 + if (sfb && smtc_RegBaseAddress) 836 + smtc_RegBaseAddress = NULL; 837 + } 838 + 839 + /* 840 + * Map in the screen memory 841 + */ 842 + 843 + static int smtc_map_smem(struct smtcfb_info *sfb, 844 + struct pci_dev *dev, u_long smem_len) 845 + { 846 + if (sfb->fb.var.bits_per_pixel == 32) { 847 + #ifdef __BIG_ENDIAN 848 + sfb->fb.fix.smem_start = pci_resource_start(dev, 0) 849 + + 0x800000; 850 + #else 851 + sfb->fb.fix.smem_start = pci_resource_start(dev, 0); 852 + #endif 853 + } else { 854 + sfb->fb.fix.smem_start = pci_resource_start(dev, 0); 855 + } 856 + 857 + sfb->fb.fix.smem_len = smem_len; 858 + 859 + sfb->fb.screen_base = smtc_VRAMBaseAddress; 860 + 861 + if (!sfb->fb.screen_base) { 862 + printk(KERN_INFO "%s: unable to map screen memory\n", 863 + sfb->fb.fix.id); 864 + return -ENOMEM; 865 + } 866 + 867 + return 0; 868 + } 869 + 870 + /* 871 + * Unmap in the screen memory 872 + * 873 + */ 874 + static void smtc_unmap_smem(struct smtcfb_info *sfb) 875 + { 876 + if (sfb && sfb->fb.screen_base) { 877 + iounmap(sfb->fb.screen_base); 878 + sfb->fb.screen_base = NULL; 879 + } 880 + } 881 + 882 + /* 883 + * We need to wake up the LynxEM+, and make sure its in linear memory mode. 884 + */ 885 + static inline void sm7xx_init_hw(void) 886 + { 887 + outb_p(0x18, 0x3c4); 888 + outb_p(0x11, 0x3c5); 889 + } 890 + 891 + static void smtc_free_fb_info(struct smtcfb_info *sfb) 892 + { 893 + if (sfb) { 894 + fb_alloc_cmap(&sfb->fb.cmap, 0, 0); 895 + kfree(sfb); 896 + } 897 + } 898 + 899 + /* 900 + * sm712vga_setup - process command line options, get vga parameter 901 + * @options: string of options 902 + * Returns zero. 903 + * 904 + */ 905 + static int __init __maybe_unused sm712vga_setup(char *options) 906 + { 907 + int index; 908 + 909 + if (!options || !*options) { 910 + smdbg("\n No vga parameter\n"); 911 + return -EINVAL; 912 + } 913 + 914 + smtc_screen_info.lfb_width = 0; 915 + smtc_screen_info.lfb_height = 0; 916 + smtc_screen_info.lfb_depth = 0; 917 + 918 + smdbg("\nsm712vga_setup = %s\n", options); 919 + 920 + for (index = 0; 921 + index < (sizeof(vesa_mode) / sizeof(struct vesa_mode_table)); 922 + index++) { 923 + if (strstr(options, vesa_mode[index].mode_index)) { 924 + smtc_screen_info.lfb_width = vesa_mode[index].lfb_width; 925 + smtc_screen_info.lfb_height = 926 + vesa_mode[index].lfb_height; 927 + smtc_screen_info.lfb_depth = vesa_mode[index].lfb_depth; 928 + return 0; 929 + } 930 + } 931 + 932 + return -1; 933 + } 934 + __setup("vga=", sm712vga_setup); 935 + 936 + /* Jason (08/13/2009) 937 + * Original init function changed to probe method to be used by pci_drv 938 + * process used to detect chips replaced with kernel process in pci_drv 939 + */ 940 + static int __init smtcfb_pci_probe(struct pci_dev *pdev, 941 + const struct pci_device_id *ent) 942 + { 943 + struct smtcfb_info *sfb; 944 + u_long smem_size = 0x00800000; /* default 8MB */ 945 + char name[16]; 946 + int err; 947 + unsigned long pFramebufferPhysical; 948 + 949 + printk(KERN_INFO 950 + "Silicon Motion display driver " SMTC_LINUX_FB_VERSION "\n"); 951 + 952 + err = pci_enable_device(pdev); /* enable SMTC chip */ 953 + 954 + if (err) 955 + return err; 956 + err = -ENOMEM; 957 + 958 + hw.chipID = ent->device; 959 + sprintf(name, "sm%Xfb", hw.chipID); 960 + 961 + sfb = smtc_alloc_fb_info(pdev, name); 962 + 963 + if (!sfb) 964 + goto failed; 965 + /* Jason (08/13/2009) 966 + * Store fb_info to be further used when suspending and resuming 967 + */ 968 + pci_set_drvdata(pdev, sfb); 969 + 970 + sm7xx_init_hw(); 971 + 972 + /*get mode parameter from smtc_screen_info */ 973 + if (smtc_screen_info.lfb_width != 0) { 974 + sfb->fb.var.xres = smtc_screen_info.lfb_width; 975 + sfb->fb.var.yres = smtc_screen_info.lfb_height; 976 + sfb->fb.var.bits_per_pixel = smtc_screen_info.lfb_depth; 977 + } else { 978 + /* default resolution 1024x600 16bit mode */ 979 + sfb->fb.var.xres = SCREEN_X_RES; 980 + sfb->fb.var.yres = SCREEN_Y_RES; 981 + sfb->fb.var.bits_per_pixel = SCREEN_BPP; 982 + } 983 + 984 + #ifdef __BIG_ENDIAN 985 + if (sfb->fb.var.bits_per_pixel == 24) 986 + sfb->fb.var.bits_per_pixel = (smtc_screen_info.lfb_depth = 32); 987 + #endif 988 + /* Map address and memory detection */ 989 + pFramebufferPhysical = pci_resource_start(pdev, 0); 990 + pci_read_config_byte(pdev, PCI_REVISION_ID, &hw.chipRevID); 991 + 992 + switch (hw.chipID) { 993 + case 0x710: 994 + case 0x712: 995 + sfb->fb.fix.mmio_start = pFramebufferPhysical + 0x00400000; 996 + sfb->fb.fix.mmio_len = 0x00400000; 997 + smem_size = SM712_VIDEOMEMORYSIZE; 998 + #ifdef __BIG_ENDIAN 999 + hw.m_pLFB = (smtc_VRAMBaseAddress = 1000 + ioremap(pFramebufferPhysical, 0x00c00000)); 1001 + #else 1002 + hw.m_pLFB = (smtc_VRAMBaseAddress = 1003 + ioremap(pFramebufferPhysical, 0x00800000)); 1004 + #endif 1005 + hw.m_pMMIO = (smtc_RegBaseAddress = 1006 + smtc_VRAMBaseAddress + 0x00700000); 1007 + smtc_2DBaseAddress = (hw.m_pDPR = 1008 + smtc_VRAMBaseAddress + 0x00408000); 1009 + smtc_2Ddataport = smtc_VRAMBaseAddress + DE_DATA_PORT_712; 1010 + hw.m_pVPR = hw.m_pLFB + 0x0040c000; 1011 + #ifdef __BIG_ENDIAN 1012 + if (sfb->fb.var.bits_per_pixel == 32) { 1013 + smtc_VRAMBaseAddress += 0x800000; 1014 + hw.m_pLFB += 0x800000; 1015 + printk(KERN_INFO 1016 + "\nsmtc_VRAMBaseAddress=%p hw.m_pLFB=%p\n", 1017 + smtc_VRAMBaseAddress, hw.m_pLFB); 1018 + } 1019 + #endif 1020 + if (!smtc_RegBaseAddress) { 1021 + printk(KERN_INFO 1022 + "%s: unable to map memory mapped IO\n", 1023 + sfb->fb.fix.id); 1024 + return -ENOMEM; 1025 + } 1026 + 1027 + /* set MCLK = 14.31818 * (0x16 / 0x2) */ 1028 + smtc_seqw(0x6a, 0x16); 1029 + smtc_seqw(0x6b, 0x02); 1030 + smtc_seqw(0x62, 0x3e); 1031 + /* enable PCI burst */ 1032 + smtc_seqw(0x17, 0x20); 1033 + /* enable word swap */ 1034 + #ifdef __BIG_ENDIAN 1035 + if (sfb->fb.var.bits_per_pixel == 32) 1036 + smtc_seqw(0x17, 0x30); 1037 + #endif 1038 + #ifdef CONFIG_FB_SM7XX_ACCEL 1039 + smtc_2Dacceleration = 1; 1040 + #endif 1041 + break; 1042 + case 0x720: 1043 + sfb->fb.fix.mmio_start = pFramebufferPhysical; 1044 + sfb->fb.fix.mmio_len = 0x00200000; 1045 + smem_size = SM722_VIDEOMEMORYSIZE; 1046 + smtc_2DBaseAddress = (hw.m_pDPR = 1047 + ioremap(pFramebufferPhysical, 0x00a00000)); 1048 + hw.m_pLFB = (smtc_VRAMBaseAddress = 1049 + smtc_2DBaseAddress + 0x00200000); 1050 + hw.m_pMMIO = (smtc_RegBaseAddress = 1051 + smtc_2DBaseAddress + 0x000c0000); 1052 + smtc_2Ddataport = smtc_2DBaseAddress + DE_DATA_PORT_722; 1053 + hw.m_pVPR = smtc_2DBaseAddress + 0x800; 1054 + 1055 + smtc_seqw(0x62, 0xff); 1056 + smtc_seqw(0x6a, 0x0d); 1057 + smtc_seqw(0x6b, 0x02); 1058 + smtc_2Dacceleration = 0; 1059 + break; 1060 + default: 1061 + printk(KERN_INFO 1062 + "No valid Silicon Motion display chip was detected!\n"); 1063 + 1064 + smtc_free_fb_info(sfb); 1065 + return err; 1066 + } 1067 + 1068 + /* can support 32 bpp */ 1069 + if (15 == sfb->fb.var.bits_per_pixel) 1070 + sfb->fb.var.bits_per_pixel = 16; 1071 + 1072 + sfb->fb.var.xres_virtual = sfb->fb.var.xres; 1073 + sfb->fb.var.yres_virtual = sfb->fb.var.yres; 1074 + err = smtc_map_smem(sfb, pdev, smem_size); 1075 + if (err) 1076 + goto failed; 1077 + 1078 + smtcfb_setmode(sfb); 1079 + /* Primary display starting from 0 postion */ 1080 + hw.BaseAddressInVRAM = 0; 1081 + sfb->fb.par = &hw; 1082 + 1083 + err = register_framebuffer(&sfb->fb); 1084 + if (err < 0) 1085 + goto failed; 1086 + 1087 + printk(KERN_INFO "Silicon Motion SM%X Rev%X primary display mode" 1088 + "%dx%d-%d Init Complete.\n", hw.chipID, hw.chipRevID, 1089 + sfb->fb.var.xres, sfb->fb.var.yres, 1090 + sfb->fb.var.bits_per_pixel); 1091 + 1092 + return 0; 1093 + 1094 + failed: 1095 + printk(KERN_INFO "Silicon Motion, Inc. primary display init fail\n"); 1096 + 1097 + smtc_unmap_smem(sfb); 1098 + smtc_unmap_mmio(sfb); 1099 + smtc_free_fb_info(sfb); 1100 + 1101 + return err; 1102 + } 1103 + 1104 + 1105 + /* Jason (08/11/2009) PCI_DRV wrapper essential structs */ 1106 + static struct pci_device_id smtcfb_pci_table[] = { 1107 + {0x126f, 0x710, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, 1108 + {0x126f, 0x712, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, 1109 + {0x126f, 0x720, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, 1110 + {0,} 1111 + }; 1112 + 1113 + 1114 + /* Jason (08/14/2009) 1115 + * do some clean up when the driver module is removed 1116 + */ 1117 + static void __devexit smtcfb_pci_remove(struct pci_dev *pdev) 1118 + { 1119 + struct smtcfb_info *sfb; 1120 + 1121 + sfb = pci_get_drvdata(pdev); 1122 + pci_set_drvdata(pdev, NULL); 1123 + smtc_unmap_smem(sfb); 1124 + smtc_unmap_mmio(sfb); 1125 + unregister_framebuffer(&sfb->fb); 1126 + smtc_free_fb_info(sfb); 1127 + } 1128 + 1129 + /* Jason (08/14/2009) 1130 + * suspend function, called when the suspend event is triggered 1131 + */ 1132 + static int __maybe_unused smtcfb_suspend(struct pci_dev *pdev, pm_message_t msg) 1133 + { 1134 + struct smtcfb_info *sfb; 1135 + int retv; 1136 + 1137 + sfb = pci_get_drvdata(pdev); 1138 + 1139 + /* set the hw in sleep mode use externel clock and self memory refresh 1140 + * so that we can turn off internal PLLs later on 1141 + */ 1142 + smtc_seqw(0x20, (smtc_seqr(0x20) | 0xc0)); 1143 + smtc_seqw(0x69, (smtc_seqr(0x69) & 0xf7)); 1144 + 1145 + switch (msg.event) { 1146 + case PM_EVENT_FREEZE: 1147 + case PM_EVENT_PRETHAW: 1148 + pdev->dev.power.power_state = msg; 1149 + return 0; 1150 + } 1151 + 1152 + /* when doing suspend, call fb apis and pci apis */ 1153 + if (msg.event == PM_EVENT_SUSPEND) { 1154 + acquire_console_sem(); 1155 + fb_set_suspend(&sfb->fb, 1); 1156 + release_console_sem(); 1157 + retv = pci_save_state(pdev); 1158 + pci_disable_device(pdev); 1159 + retv = pci_choose_state(pdev, msg); 1160 + retv = pci_set_power_state(pdev, retv); 1161 + } 1162 + 1163 + pdev->dev.power.power_state = msg; 1164 + 1165 + /* additionaly turn off all function blocks including internal PLLs */ 1166 + smtc_seqw(0x21, 0xff); 1167 + 1168 + return 0; 1169 + } 1170 + 1171 + static int __maybe_unused smtcfb_resume(struct pci_dev *pdev) 1172 + { 1173 + struct smtcfb_info *sfb; 1174 + int retv; 1175 + 1176 + sfb = pci_get_drvdata(pdev); 1177 + 1178 + /* when resuming, restore pci data and fb cursor */ 1179 + if (pdev->dev.power.power_state.event != PM_EVENT_FREEZE) { 1180 + retv = pci_set_power_state(pdev, PCI_D0); 1181 + retv = pci_restore_state(pdev); 1182 + if (pci_enable_device(pdev)) 1183 + return -1; 1184 + pci_set_master(pdev); 1185 + } 1186 + 1187 + /* reinit hardware */ 1188 + sm7xx_init_hw(); 1189 + switch (hw.chipID) { 1190 + case 0x710: 1191 + case 0x712: 1192 + /* set MCLK = 14.31818 * (0x16 / 0x2) */ 1193 + smtc_seqw(0x6a, 0x16); 1194 + smtc_seqw(0x6b, 0x02); 1195 + smtc_seqw(0x62, 0x3e); 1196 + /* enable PCI burst */ 1197 + smtc_seqw(0x17, 0x20); 1198 + #ifdef __BIG_ENDIAN 1199 + if (sfb->fb.var.bits_per_pixel == 32) 1200 + smtc_seqw(0x17, 0x30); 1201 + #endif 1202 + break; 1203 + case 0x720: 1204 + smtc_seqw(0x62, 0xff); 1205 + smtc_seqw(0x6a, 0x0d); 1206 + smtc_seqw(0x6b, 0x02); 1207 + break; 1208 + } 1209 + 1210 + smtc_seqw(0x34, (smtc_seqr(0x34) | 0xc0)); 1211 + smtc_seqw(0x33, ((smtc_seqr(0x33) | 0x08) & 0xfb)); 1212 + 1213 + smtcfb_setmode(sfb); 1214 + 1215 + acquire_console_sem(); 1216 + fb_set_suspend(&sfb->fb, 0); 1217 + release_console_sem(); 1218 + 1219 + return 0; 1220 + } 1221 + 1222 + /* Jason (08/13/2009) 1223 + * pci_driver struct used to wrap the original driver 1224 + * so that it can be registered into the kernel and 1225 + * the proper method would be called when suspending and resuming 1226 + */ 1227 + static struct pci_driver smtcfb_driver = { 1228 + .name = "smtcfb", 1229 + .id_table = smtcfb_pci_table, 1230 + .probe = smtcfb_pci_probe, 1231 + .remove = __devexit_p(smtcfb_pci_remove), 1232 + #ifdef CONFIG_PM 1233 + .suspend = smtcfb_suspend, 1234 + .resume = smtcfb_resume, 1235 + #endif 1236 + }; 1237 + 1238 + static int __init smtcfb_init(void) 1239 + { 1240 + return pci_register_driver(&smtcfb_driver); 1241 + } 1242 + 1243 + static void __exit smtcfb_exit(void) 1244 + { 1245 + pci_unregister_driver(&smtcfb_driver); 1246 + } 1247 + 1248 + module_init(smtcfb_init); 1249 + module_exit(smtcfb_exit); 1250 + 1251 + MODULE_AUTHOR("Siliconmotion "); 1252 + MODULE_DESCRIPTION("Framebuffer driver for SMI Graphic Cards"); 1253 + MODULE_LICENSE("GPL");
+793
drivers/staging/sm7xx/smtcfb.h
··· 1 + /* 2 + * Silicon Motion SM712 frame buffer device 3 + * 4 + * Copyright (C) 2006 Silicon Motion Technology Corp. 5 + * Authors: Ge Wang, gewang@siliconmotion.com 6 + * Boyod boyod.yang@siliconmotion.com.cn 7 + * 8 + * Copyright (C) 2009 Lemote, Inc. 9 + * Author: Wu Zhangjin, wuzj@lemote.com 10 + * 11 + * This file is subject to the terms and conditions of the GNU General Public 12 + * License. See the file COPYING in the main directory of this archive for 13 + * more details. 14 + */ 15 + 16 + #define SMTC_LINUX_FB_VERSION "version 0.11.2619.21.01 July 27, 2008" 17 + 18 + #define NR_PALETTE 256 19 + #define NR_RGB 2 20 + 21 + #define FB_ACCEL_SMI_LYNX 88 22 + 23 + #ifdef __BIG_ENDIAN 24 + #define PC_VGA 0 25 + #else 26 + #define PC_VGA 1 27 + #endif 28 + 29 + #define SCREEN_X_RES 1024 30 + #define SCREEN_Y_RES 600 31 + #define SCREEN_BPP 16 32 + 33 + #ifndef FIELD_OFFSET 34 + #define FIELD_OFSFET(type, field) \ 35 + ((unsigned long) (PUCHAR) & (((type *)0)->field)) 36 + #endif 37 + 38 + /*Assume SM712 graphics chip has 4MB VRAM */ 39 + #define SM712_VIDEOMEMORYSIZE 0x00400000 40 + /*Assume SM722 graphics chip has 8MB VRAM */ 41 + #define SM722_VIDEOMEMORYSIZE 0x00800000 42 + 43 + #define dac_reg (0x3c8) 44 + #define dac_val (0x3c9) 45 + 46 + extern char *smtc_RegBaseAddress; 47 + #define smtc_mmiowb(dat, reg) writeb(dat, smtc_RegBaseAddress + reg) 48 + #define smtc_mmioww(dat, reg) writew(dat, smtc_RegBaseAddress + reg) 49 + #define smtc_mmiowl(dat, reg) writel(dat, smtc_RegBaseAddress + reg) 50 + 51 + #define smtc_mmiorb(reg) readb(smtc_RegBaseAddress + reg) 52 + #define smtc_mmiorw(reg) readw(smtc_RegBaseAddress + reg) 53 + #define smtc_mmiorl(reg) readl(smtc_RegBaseAddress + reg) 54 + 55 + #define SIZE_SR00_SR04 (0x04 - 0x00 + 1) 56 + #define SIZE_SR10_SR24 (0x24 - 0x10 + 1) 57 + #define SIZE_SR30_SR75 (0x75 - 0x30 + 1) 58 + #define SIZE_SR80_SR93 (0x93 - 0x80 + 1) 59 + #define SIZE_SRA0_SRAF (0xAF - 0xA0 + 1) 60 + #define SIZE_GR00_GR08 (0x08 - 0x00 + 1) 61 + #define SIZE_AR00_AR14 (0x14 - 0x00 + 1) 62 + #define SIZE_CR00_CR18 (0x18 - 0x00 + 1) 63 + #define SIZE_CR30_CR4D (0x4D - 0x30 + 1) 64 + #define SIZE_CR90_CRA7 (0xA7 - 0x90 + 1) 65 + #define SIZE_VPR (0x6C + 1) 66 + #define SIZE_DPR (0x44 + 1) 67 + 68 + static inline void smtc_crtcw(int reg, int val) 69 + { 70 + smtc_mmiowb(reg, 0x3d4); 71 + smtc_mmiowb(val, 0x3d5); 72 + } 73 + 74 + static inline unsigned int smtc_crtcr(int reg) 75 + { 76 + smtc_mmiowb(reg, 0x3d4); 77 + return smtc_mmiorb(0x3d5); 78 + } 79 + 80 + static inline void smtc_grphw(int reg, int val) 81 + { 82 + smtc_mmiowb(reg, 0x3ce); 83 + smtc_mmiowb(val, 0x3cf); 84 + } 85 + 86 + static inline unsigned int smtc_grphr(int reg) 87 + { 88 + smtc_mmiowb(reg, 0x3ce); 89 + return smtc_mmiorb(0x3cf); 90 + } 91 + 92 + static inline void smtc_attrw(int reg, int val) 93 + { 94 + smtc_mmiorb(0x3da); 95 + smtc_mmiowb(reg, 0x3c0); 96 + smtc_mmiorb(0x3c1); 97 + smtc_mmiowb(val, 0x3c0); 98 + } 99 + 100 + static inline void smtc_seqw(int reg, int val) 101 + { 102 + smtc_mmiowb(reg, 0x3c4); 103 + smtc_mmiowb(val, 0x3c5); 104 + } 105 + 106 + static inline unsigned int smtc_seqr(int reg) 107 + { 108 + smtc_mmiowb(reg, 0x3c4); 109 + return smtc_mmiorb(0x3c5); 110 + } 111 + 112 + /* The next structure holds all information relevant for a specific video mode. 113 + */ 114 + 115 + struct ModeInit { 116 + int mmSizeX; 117 + int mmSizeY; 118 + int bpp; 119 + int hz; 120 + unsigned char Init_MISC; 121 + unsigned char Init_SR00_SR04[SIZE_SR00_SR04]; 122 + unsigned char Init_SR10_SR24[SIZE_SR10_SR24]; 123 + unsigned char Init_SR30_SR75[SIZE_SR30_SR75]; 124 + unsigned char Init_SR80_SR93[SIZE_SR80_SR93]; 125 + unsigned char Init_SRA0_SRAF[SIZE_SRA0_SRAF]; 126 + unsigned char Init_GR00_GR08[SIZE_GR00_GR08]; 127 + unsigned char Init_AR00_AR14[SIZE_AR00_AR14]; 128 + unsigned char Init_CR00_CR18[SIZE_CR00_CR18]; 129 + unsigned char Init_CR30_CR4D[SIZE_CR30_CR4D]; 130 + unsigned char Init_CR90_CRA7[SIZE_CR90_CRA7]; 131 + }; 132 + 133 + /********************************************************************** 134 + SM712 Mode table. 135 + **********************************************************************/ 136 + struct ModeInit VGAMode[] = { 137 + { 138 + /* mode#0: 640 x 480 16Bpp 60Hz */ 139 + 640, 480, 16, 60, 140 + /* Init_MISC */ 141 + 0xE3, 142 + { /* Init_SR0_SR4 */ 143 + 0x03, 0x01, 0x0F, 0x00, 0x0E, 144 + }, 145 + { /* Init_SR10_SR24 */ 146 + 0xFF, 0xBE, 0xEF, 0xFF, 0x00, 0x0E, 0x17, 0x2C, 147 + 0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 148 + 0xC4, 0x30, 0x02, 0x01, 0x01, 149 + }, 150 + { /* Init_SR30_SR75 */ 151 + 0x32, 0x03, 0xA0, 0x09, 0xC0, 0x32, 0x32, 0x32, 152 + 0x32, 0x32, 0x32, 0x32, 0x00, 0x00, 0x03, 0xFF, 153 + 0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC, 154 + 0x20, 0x0C, 0x44, 0x20, 0x00, 0x32, 0x32, 0x32, 155 + 0x04, 0x24, 0x63, 0x4F, 0x52, 0x0B, 0xDF, 0xEA, 156 + 0x04, 0x50, 0x19, 0x32, 0x32, 0x00, 0x00, 0x32, 157 + 0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00, 158 + 0x50, 0x03, 0x74, 0x14, 0x07, 0x82, 0x07, 0x04, 159 + 0x00, 0x45, 0x30, 0x30, 0x40, 0x30, 160 + }, 161 + { /* Init_SR80_SR93 */ 162 + 0xFF, 0x07, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x32, 163 + 0xF7, 0x00, 0x00, 0x00, 0xEF, 0xFF, 0x32, 0x32, 164 + 0x00, 0x00, 0x00, 0x00, 165 + }, 166 + { /* Init_SRA0_SRAF */ 167 + 0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED, 168 + 0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xFF, 0xDF, 169 + }, 170 + { /* Init_GR00_GR08 */ 171 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 172 + 0xFF, 173 + }, 174 + { /* Init_AR00_AR14 */ 175 + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 176 + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 177 + 0x41, 0x00, 0x0F, 0x00, 0x00, 178 + }, 179 + { /* Init_CR00_CR18 */ 180 + 0x5F, 0x4F, 0x4F, 0x00, 0x53, 0x1F, 0x0B, 0x3E, 181 + 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 182 + 0xEA, 0x0C, 0xDF, 0x50, 0x40, 0xDF, 0x00, 0xE3, 183 + 0xFF, 184 + }, 185 + { /* Init_CR30_CR4D */ 186 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x03, 0x20, 187 + 0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xFF, 0xFD, 188 + 0x5F, 0x4F, 0x00, 0x54, 0x00, 0x0B, 0xDF, 0x00, 189 + 0xEA, 0x0C, 0x2E, 0x00, 0x4F, 0xDF, 190 + }, 191 + { /* Init_CR90_CRA7 */ 192 + 0x56, 0xDD, 0x5E, 0xEA, 0x87, 0x44, 0x8F, 0x55, 193 + 0x0A, 0x8F, 0x55, 0x0A, 0x00, 0x00, 0x18, 0x00, 194 + 0x11, 0x10, 0x0B, 0x0A, 0x0A, 0x0A, 0x0A, 0x00, 195 + }, 196 + }, 197 + { 198 + /* mode#1: 640 x 480 24Bpp 60Hz */ 199 + 640, 480, 24, 60, 200 + /* Init_MISC */ 201 + 0xE3, 202 + { /* Init_SR0_SR4 */ 203 + 0x03, 0x01, 0x0F, 0x00, 0x0E, 204 + }, 205 + { /* Init_SR10_SR24 */ 206 + 0xFF, 0xBE, 0xEF, 0xFF, 0x00, 0x0E, 0x17, 0x2C, 207 + 0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 208 + 0xC4, 0x30, 0x02, 0x01, 0x01, 209 + }, 210 + { /* Init_SR30_SR75 */ 211 + 0x32, 0x03, 0xA0, 0x09, 0xC0, 0x32, 0x32, 0x32, 212 + 0x32, 0x32, 0x32, 0x32, 0x00, 0x00, 0x03, 0xFF, 213 + 0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC, 214 + 0x20, 0x0C, 0x44, 0x20, 0x00, 0x32, 0x32, 0x32, 215 + 0x04, 0x24, 0x63, 0x4F, 0x52, 0x0B, 0xDF, 0xEA, 216 + 0x04, 0x50, 0x19, 0x32, 0x32, 0x00, 0x00, 0x32, 217 + 0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00, 218 + 0x50, 0x03, 0x74, 0x14, 0x07, 0x82, 0x07, 0x04, 219 + 0x00, 0x45, 0x30, 0x30, 0x40, 0x30, 220 + }, 221 + { /* Init_SR80_SR93 */ 222 + 0xFF, 0x07, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x32, 223 + 0xF7, 0x00, 0x00, 0x00, 0xEF, 0xFF, 0x32, 0x32, 224 + 0x00, 0x00, 0x00, 0x00, 225 + }, 226 + { /* Init_SRA0_SRAF */ 227 + 0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED, 228 + 0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xFF, 0xDF, 229 + }, 230 + { /* Init_GR00_GR08 */ 231 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 232 + 0xFF, 233 + }, 234 + { /* Init_AR00_AR14 */ 235 + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 236 + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 237 + 0x41, 0x00, 0x0F, 0x00, 0x00, 238 + }, 239 + { /* Init_CR00_CR18 */ 240 + 0x5F, 0x4F, 0x4F, 0x00, 0x53, 0x1F, 0x0B, 0x3E, 241 + 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 242 + 0xEA, 0x0C, 0xDF, 0x50, 0x40, 0xDF, 0x00, 0xE3, 243 + 0xFF, 244 + }, 245 + { /* Init_CR30_CR4D */ 246 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x03, 0x20, 247 + 0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xFF, 0xFD, 248 + 0x5F, 0x4F, 0x00, 0x54, 0x00, 0x0B, 0xDF, 0x00, 249 + 0xEA, 0x0C, 0x2E, 0x00, 0x4F, 0xDF, 250 + }, 251 + { /* Init_CR90_CRA7 */ 252 + 0x56, 0xDD, 0x5E, 0xEA, 0x87, 0x44, 0x8F, 0x55, 253 + 0x0A, 0x8F, 0x55, 0x0A, 0x00, 0x00, 0x18, 0x00, 254 + 0x11, 0x10, 0x0B, 0x0A, 0x0A, 0x0A, 0x0A, 0x00, 255 + }, 256 + }, 257 + { 258 + /* mode#0: 640 x 480 32Bpp 60Hz */ 259 + 640, 480, 32, 60, 260 + /* Init_MISC */ 261 + 0xE3, 262 + { /* Init_SR0_SR4 */ 263 + 0x03, 0x01, 0x0F, 0x00, 0x0E, 264 + }, 265 + { /* Init_SR10_SR24 */ 266 + 0xFF, 0xBE, 0xEF, 0xFF, 0x00, 0x0E, 0x17, 0x2C, 267 + 0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 268 + 0xC4, 0x30, 0x02, 0x01, 0x01, 269 + }, 270 + { /* Init_SR30_SR75 */ 271 + 0x32, 0x03, 0xA0, 0x09, 0xC0, 0x32, 0x32, 0x32, 272 + 0x32, 0x32, 0x32, 0x32, 0x00, 0x00, 0x03, 0xFF, 273 + 0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC, 274 + 0x20, 0x0C, 0x44, 0x20, 0x00, 0x32, 0x32, 0x32, 275 + 0x04, 0x24, 0x63, 0x4F, 0x52, 0x0B, 0xDF, 0xEA, 276 + 0x04, 0x50, 0x19, 0x32, 0x32, 0x00, 0x00, 0x32, 277 + 0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00, 278 + 0x50, 0x03, 0x74, 0x14, 0x07, 0x82, 0x07, 0x04, 279 + 0x00, 0x45, 0x30, 0x30, 0x40, 0x30, 280 + }, 281 + { /* Init_SR80_SR93 */ 282 + 0xFF, 0x07, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x32, 283 + 0xF7, 0x00, 0x00, 0x00, 0xEF, 0xFF, 0x32, 0x32, 284 + 0x00, 0x00, 0x00, 0x00, 285 + }, 286 + { /* Init_SRA0_SRAF */ 287 + 0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED, 288 + 0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xFF, 0xDF, 289 + }, 290 + { /* Init_GR00_GR08 */ 291 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 292 + 0xFF, 293 + }, 294 + { /* Init_AR00_AR14 */ 295 + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 296 + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 297 + 0x41, 0x00, 0x0F, 0x00, 0x00, 298 + }, 299 + { /* Init_CR00_CR18 */ 300 + 0x5F, 0x4F, 0x4F, 0x00, 0x53, 0x1F, 0x0B, 0x3E, 301 + 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 302 + 0xEA, 0x0C, 0xDF, 0x50, 0x40, 0xDF, 0x00, 0xE3, 303 + 0xFF, 304 + }, 305 + { /* Init_CR30_CR4D */ 306 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x03, 0x20, 307 + 0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xFF, 0xFD, 308 + 0x5F, 0x4F, 0x00, 0x54, 0x00, 0x0B, 0xDF, 0x00, 309 + 0xEA, 0x0C, 0x2E, 0x00, 0x4F, 0xDF, 310 + }, 311 + { /* Init_CR90_CRA7 */ 312 + 0x56, 0xDD, 0x5E, 0xEA, 0x87, 0x44, 0x8F, 0x55, 313 + 0x0A, 0x8F, 0x55, 0x0A, 0x00, 0x00, 0x18, 0x00, 314 + 0x11, 0x10, 0x0B, 0x0A, 0x0A, 0x0A, 0x0A, 0x00, 315 + }, 316 + }, 317 + 318 + { /* mode#2: 800 x 600 16Bpp 60Hz */ 319 + 800, 600, 16, 60, 320 + /* Init_MISC */ 321 + 0x2B, 322 + { /* Init_SR0_SR4 */ 323 + 0x03, 0x01, 0x0F, 0x03, 0x0E, 324 + }, 325 + { /* Init_SR10_SR24 */ 326 + 0xFF, 0xBE, 0xEE, 0xFF, 0x00, 0x0E, 0x17, 0x2C, 327 + 0x99, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 328 + 0xC4, 0x30, 0x02, 0x01, 0x01, 329 + }, 330 + { /* Init_SR30_SR75 */ 331 + 0x34, 0x03, 0x20, 0x09, 0xC0, 0x24, 0x24, 0x24, 332 + 0x24, 0x24, 0x24, 0x24, 0x00, 0x00, 0x03, 0xFF, 333 + 0x00, 0xFC, 0x00, 0x00, 0x20, 0x38, 0x00, 0xFC, 334 + 0x20, 0x0C, 0x44, 0x20, 0x00, 0x24, 0x24, 0x24, 335 + 0x04, 0x48, 0x83, 0x63, 0x68, 0x72, 0x57, 0x58, 336 + 0x04, 0x55, 0x59, 0x24, 0x24, 0x00, 0x00, 0x24, 337 + 0x01, 0x80, 0x7A, 0x1A, 0x1A, 0x00, 0x00, 0x00, 338 + 0x50, 0x03, 0x74, 0x14, 0x1C, 0x85, 0x35, 0x13, 339 + 0x02, 0x45, 0x30, 0x35, 0x40, 0x20, 340 + }, 341 + { /* Init_SR80_SR93 */ 342 + 0x00, 0x00, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x24, 343 + 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x24, 0x24, 344 + 0x00, 0x00, 0x00, 0x00, 345 + }, 346 + { /* Init_SRA0_SRAF */ 347 + 0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED, 348 + 0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xBF, 0xDF, 349 + }, 350 + { /* Init_GR00_GR08 */ 351 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 352 + 0xFF, 353 + }, 354 + { /* Init_AR00_AR14 */ 355 + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 356 + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 357 + 0x41, 0x00, 0x0F, 0x00, 0x00, 358 + }, 359 + { /* Init_CR00_CR18 */ 360 + 0x7F, 0x63, 0x63, 0x00, 0x68, 0x18, 0x72, 0xF0, 361 + 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 362 + 0x58, 0x0C, 0x57, 0x64, 0x40, 0x57, 0x00, 0xE3, 363 + 0xFF, 364 + }, 365 + { /* Init_CR30_CR4D */ 366 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x03, 0x20, 367 + 0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xBF, 0xFD, 368 + 0x7F, 0x63, 0x00, 0x69, 0x18, 0x72, 0x57, 0x00, 369 + 0x58, 0x0C, 0xE0, 0x20, 0x63, 0x57, 370 + }, 371 + { /* Init_CR90_CRA7 */ 372 + 0x56, 0x4B, 0x5E, 0x55, 0x86, 0x9D, 0x8E, 0xAA, 373 + 0xDB, 0x2A, 0xDF, 0x33, 0x00, 0x00, 0x18, 0x00, 374 + 0x20, 0x1F, 0x1A, 0x19, 0x0F, 0x0F, 0x0F, 0x00, 375 + }, 376 + }, 377 + { /* mode#3: 800 x 600 24Bpp 60Hz */ 378 + 800, 600, 24, 60, 379 + 0x2B, 380 + { /* Init_SR0_SR4 */ 381 + 0x03, 0x01, 0x0F, 0x03, 0x0E, 382 + }, 383 + { /* Init_SR10_SR24 */ 384 + 0xFF, 0xBE, 0xEE, 0xFF, 0x00, 0x0E, 0x17, 0x2C, 385 + 0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 386 + 0xC4, 0x30, 0x02, 0x01, 0x01, 387 + }, 388 + { /* Init_SR30_SR75 */ 389 + 0x36, 0x03, 0x20, 0x09, 0xC0, 0x36, 0x36, 0x36, 390 + 0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x03, 0xFF, 391 + 0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC, 392 + 0x20, 0x0C, 0x44, 0x20, 0x00, 0x36, 0x36, 0x36, 393 + 0x04, 0x48, 0x83, 0x63, 0x68, 0x72, 0x57, 0x58, 394 + 0x04, 0x55, 0x59, 0x36, 0x36, 0x00, 0x00, 0x36, 395 + 0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00, 396 + 0x50, 0x03, 0x74, 0x14, 0x1C, 0x85, 0x35, 0x13, 397 + 0x02, 0x45, 0x30, 0x30, 0x40, 0x20, 398 + }, 399 + { /* Init_SR80_SR93 */ 400 + 0xFF, 0x07, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x36, 401 + 0xF7, 0x00, 0x00, 0x00, 0xEF, 0xFF, 0x36, 0x36, 402 + 0x00, 0x00, 0x00, 0x00, 403 + }, 404 + { /* Init_SRA0_SRAF */ 405 + 0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED, 406 + 0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xBF, 0xDF, 407 + }, 408 + { /* Init_GR00_GR08 */ 409 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 410 + 0xFF, 411 + }, 412 + { /* Init_AR00_AR14 */ 413 + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 414 + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 415 + 0x41, 0x00, 0x0F, 0x00, 0x00, 416 + }, 417 + { /* Init_CR00_CR18 */ 418 + 0x7F, 0x63, 0x63, 0x00, 0x68, 0x18, 0x72, 0xF0, 419 + 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 420 + 0x58, 0x0C, 0x57, 0x64, 0x40, 0x57, 0x00, 0xE3, 421 + 0xFF, 422 + }, 423 + { /* Init_CR30_CR4D */ 424 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x03, 0x20, 425 + 0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xBF, 0xFD, 426 + 0x7F, 0x63, 0x00, 0x69, 0x18, 0x72, 0x57, 0x00, 427 + 0x58, 0x0C, 0xE0, 0x20, 0x63, 0x57, 428 + }, 429 + { /* Init_CR90_CRA7 */ 430 + 0x56, 0x4B, 0x5E, 0x55, 0x86, 0x9D, 0x8E, 0xAA, 431 + 0xDB, 0x2A, 0xDF, 0x33, 0x00, 0x00, 0x18, 0x00, 432 + 0x20, 0x1F, 0x1A, 0x19, 0x0F, 0x0F, 0x0F, 0x00, 433 + }, 434 + }, 435 + { /* mode#7: 800 x 600 32Bpp 60Hz */ 436 + 800, 600, 32, 60, 437 + /* Init_MISC */ 438 + 0x2B, 439 + { /* Init_SR0_SR4 */ 440 + 0x03, 0x01, 0x0F, 0x03, 0x0E, 441 + }, 442 + { /* Init_SR10_SR24 */ 443 + 0xFF, 0xBE, 0xEE, 0xFF, 0x00, 0x0E, 0x17, 0x2C, 444 + 0x99, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 445 + 0xC4, 0x30, 0x02, 0x01, 0x01, 446 + }, 447 + { /* Init_SR30_SR75 */ 448 + 0x34, 0x03, 0x20, 0x09, 0xC0, 0x24, 0x24, 0x24, 449 + 0x24, 0x24, 0x24, 0x24, 0x00, 0x00, 0x03, 0xFF, 450 + 0x00, 0xFC, 0x00, 0x00, 0x20, 0x38, 0x00, 0xFC, 451 + 0x20, 0x0C, 0x44, 0x20, 0x00, 0x24, 0x24, 0x24, 452 + 0x04, 0x48, 0x83, 0x63, 0x68, 0x72, 0x57, 0x58, 453 + 0x04, 0x55, 0x59, 0x24, 0x24, 0x00, 0x00, 0x24, 454 + 0x01, 0x80, 0x7A, 0x1A, 0x1A, 0x00, 0x00, 0x00, 455 + 0x50, 0x03, 0x74, 0x14, 0x1C, 0x85, 0x35, 0x13, 456 + 0x02, 0x45, 0x30, 0x35, 0x40, 0x20, 457 + }, 458 + { /* Init_SR80_SR93 */ 459 + 0x00, 0x00, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x24, 460 + 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x24, 0x24, 461 + 0x00, 0x00, 0x00, 0x00, 462 + }, 463 + { /* Init_SRA0_SRAF */ 464 + 0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED, 465 + 0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xBF, 0xDF, 466 + }, 467 + { /* Init_GR00_GR08 */ 468 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 469 + 0xFF, 470 + }, 471 + { /* Init_AR00_AR14 */ 472 + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 473 + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 474 + 0x41, 0x00, 0x0F, 0x00, 0x00, 475 + }, 476 + { /* Init_CR00_CR18 */ 477 + 0x7F, 0x63, 0x63, 0x00, 0x68, 0x18, 0x72, 0xF0, 478 + 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 479 + 0x58, 0x0C, 0x57, 0x64, 0x40, 0x57, 0x00, 0xE3, 480 + 0xFF, 481 + }, 482 + { /* Init_CR30_CR4D */ 483 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x03, 0x20, 484 + 0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xBF, 0xFD, 485 + 0x7F, 0x63, 0x00, 0x69, 0x18, 0x72, 0x57, 0x00, 486 + 0x58, 0x0C, 0xE0, 0x20, 0x63, 0x57, 487 + }, 488 + { /* Init_CR90_CRA7 */ 489 + 0x56, 0x4B, 0x5E, 0x55, 0x86, 0x9D, 0x8E, 0xAA, 490 + 0xDB, 0x2A, 0xDF, 0x33, 0x00, 0x00, 0x18, 0x00, 491 + 0x20, 0x1F, 0x1A, 0x19, 0x0F, 0x0F, 0x0F, 0x00, 492 + }, 493 + }, 494 + /* We use 1024x768 table to light 1024x600 panel for lemote */ 495 + { /* mode#4: 1024 x 600 16Bpp 60Hz */ 496 + 1024, 600, 16, 60, 497 + /* Init_MISC */ 498 + 0xEB, 499 + { /* Init_SR0_SR4 */ 500 + 0x03, 0x01, 0x0F, 0x00, 0x0E, 501 + }, 502 + { /* Init_SR10_SR24 */ 503 + 0xC8, 0x40, 0x14, 0x60, 0x00, 0x0A, 0x17, 0x20, 504 + 0x51, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 505 + 0xC4, 0x30, 0x02, 0x00, 0x01, 506 + }, 507 + { /* Init_SR30_SR75 */ 508 + 0x22, 0x03, 0x24, 0x09, 0xC0, 0x22, 0x22, 0x22, 509 + 0x22, 0x22, 0x22, 0x22, 0x00, 0x00, 0x03, 0xFF, 510 + 0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC, 511 + 0x20, 0x0C, 0x44, 0x20, 0x00, 0x22, 0x22, 0x22, 512 + 0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03, 513 + 0x00, 0x60, 0x59, 0x22, 0x22, 0x00, 0x00, 0x22, 514 + 0x01, 0x80, 0x7A, 0x1A, 0x1A, 0x00, 0x00, 0x00, 515 + 0x50, 0x03, 0x16, 0x02, 0x0D, 0x82, 0x09, 0x02, 516 + 0x04, 0x45, 0x3F, 0x30, 0x40, 0x20, 517 + }, 518 + { /* Init_SR80_SR93 */ 519 + 0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A, 520 + 0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A, 521 + 0x00, 0x00, 0x00, 0x00, 522 + }, 523 + { /* Init_SRA0_SRAF */ 524 + 0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED, 525 + 0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF, 526 + }, 527 + { /* Init_GR00_GR08 */ 528 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 529 + 0xFF, 530 + }, 531 + { /* Init_AR00_AR14 */ 532 + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 533 + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 534 + 0x41, 0x00, 0x0F, 0x00, 0x00, 535 + }, 536 + { /* Init_CR00_CR18 */ 537 + 0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5, 538 + 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 539 + 0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3, 540 + 0xFF, 541 + }, 542 + { /* Init_CR30_CR4D */ 543 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20, 544 + 0x00, 0x00, 0x00, 0x40, 0x00, 0xFF, 0xBF, 0xFF, 545 + 0xA3, 0x7F, 0x00, 0x82, 0x0b, 0x6f, 0x57, 0x00, 546 + 0x5c, 0x0f, 0xE0, 0xe0, 0x7F, 0x57, 547 + }, 548 + { /* Init_CR90_CRA7 */ 549 + 0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26, 550 + 0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00, 551 + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03, 552 + }, 553 + }, 554 + { /* mode#5: 1024 x 768 24Bpp 60Hz */ 555 + 1024, 768, 24, 60, 556 + /* Init_MISC */ 557 + 0xEB, 558 + { /* Init_SR0_SR4 */ 559 + 0x03, 0x01, 0x0F, 0x03, 0x0E, 560 + }, 561 + { /* Init_SR10_SR24 */ 562 + 0xF3, 0xB6, 0xC0, 0xDD, 0x00, 0x0E, 0x17, 0x2C, 563 + 0x99, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 564 + 0xC4, 0x30, 0x02, 0x01, 0x01, 565 + }, 566 + { /* Init_SR30_SR75 */ 567 + 0x38, 0x03, 0x20, 0x09, 0xC0, 0x3A, 0x3A, 0x3A, 568 + 0x3A, 0x3A, 0x3A, 0x3A, 0x00, 0x00, 0x03, 0xFF, 569 + 0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC, 570 + 0x20, 0x0C, 0x44, 0x20, 0x00, 0x00, 0x00, 0x3A, 571 + 0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03, 572 + 0x00, 0x60, 0x59, 0x3A, 0x3A, 0x00, 0x00, 0x3A, 573 + 0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00, 574 + 0x50, 0x03, 0x74, 0x14, 0x3B, 0x0D, 0x09, 0x02, 575 + 0x04, 0x45, 0x30, 0x30, 0x40, 0x20, 576 + }, 577 + { /* Init_SR80_SR93 */ 578 + 0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A, 579 + 0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A, 580 + 0x00, 0x00, 0x00, 0x00, 581 + }, 582 + { /* Init_SRA0_SRAF */ 583 + 0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED, 584 + 0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF, 585 + }, 586 + { /* Init_GR00_GR08 */ 587 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 588 + 0xFF, 589 + }, 590 + { /* Init_AR00_AR14 */ 591 + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 592 + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 593 + 0x41, 0x00, 0x0F, 0x00, 0x00, 594 + }, 595 + { /* Init_CR00_CR18 */ 596 + 0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5, 597 + 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 598 + 0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3, 599 + 0xFF, 600 + }, 601 + { /* Init_CR30_CR4D */ 602 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20, 603 + 0x00, 0x00, 0x00, 0x40, 0x00, 0xFF, 0xBF, 0xFF, 604 + 0xA3, 0x7F, 0x00, 0x86, 0x15, 0x24, 0xFF, 0x00, 605 + 0x01, 0x07, 0xE5, 0x20, 0x7F, 0xFF, 606 + }, 607 + { /* Init_CR90_CRA7 */ 608 + 0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26, 609 + 0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00, 610 + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03, 611 + }, 612 + }, 613 + { /* mode#4: 1024 x 768 32Bpp 60Hz */ 614 + 1024, 768, 32, 60, 615 + /* Init_MISC */ 616 + 0xEB, 617 + { /* Init_SR0_SR4 */ 618 + 0x03, 0x01, 0x0F, 0x03, 0x0E, 619 + }, 620 + { /* Init_SR10_SR24 */ 621 + 0xF3, 0xB6, 0xC0, 0xDD, 0x00, 0x0E, 0x17, 0x2C, 622 + 0x99, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 623 + 0xC4, 0x32, 0x02, 0x01, 0x01, 624 + }, 625 + { /* Init_SR30_SR75 */ 626 + 0x38, 0x03, 0x20, 0x09, 0xC0, 0x3A, 0x3A, 0x3A, 627 + 0x3A, 0x3A, 0x3A, 0x3A, 0x00, 0x00, 0x03, 0xFF, 628 + 0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC, 629 + 0x20, 0x0C, 0x44, 0x20, 0x00, 0x00, 0x00, 0x3A, 630 + 0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03, 631 + 0x00, 0x60, 0x59, 0x3A, 0x3A, 0x00, 0x00, 0x3A, 632 + 0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00, 633 + 0x50, 0x03, 0x74, 0x14, 0x3B, 0x0D, 0x09, 0x02, 634 + 0x04, 0x45, 0x30, 0x30, 0x40, 0x20, 635 + }, 636 + { /* Init_SR80_SR93 */ 637 + 0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A, 638 + 0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A, 639 + 0x00, 0x00, 0x00, 0x00, 640 + }, 641 + { /* Init_SRA0_SRAF */ 642 + 0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED, 643 + 0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF, 644 + }, 645 + { /* Init_GR00_GR08 */ 646 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 647 + 0xFF, 648 + }, 649 + { /* Init_AR00_AR14 */ 650 + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 651 + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 652 + 0x41, 0x00, 0x0F, 0x00, 0x00, 653 + }, 654 + { /* Init_CR00_CR18 */ 655 + 0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5, 656 + 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 657 + 0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3, 658 + 0xFF, 659 + }, 660 + { /* Init_CR30_CR4D */ 661 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20, 662 + 0x00, 0x00, 0x00, 0x40, 0x00, 0xFF, 0xBF, 0xFF, 663 + 0xA3, 0x7F, 0x00, 0x86, 0x15, 0x24, 0xFF, 0x00, 664 + 0x01, 0x07, 0xE5, 0x20, 0x7F, 0xFF, 665 + }, 666 + { /* Init_CR90_CRA7 */ 667 + 0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26, 668 + 0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00, 669 + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03, 670 + }, 671 + }, 672 + { /* mode#6: 320 x 240 16Bpp 60Hz */ 673 + 320, 240, 16, 60, 674 + /* Init_MISC */ 675 + 0xEB, 676 + { /* Init_SR0_SR4 */ 677 + 0x03, 0x01, 0x0F, 0x03, 0x0E, 678 + }, 679 + { /* Init_SR10_SR24 */ 680 + 0xF3, 0xB6, 0xC0, 0xDD, 0x00, 0x0E, 0x17, 0x2C, 681 + 0x99, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 682 + 0xC4, 0x32, 0x02, 0x01, 0x01, 683 + }, 684 + { /* Init_SR30_SR75 */ 685 + 0x38, 0x03, 0x20, 0x09, 0xC0, 0x3A, 0x3A, 0x3A, 686 + 0x3A, 0x3A, 0x3A, 0x3A, 0x00, 0x00, 0x03, 0xFF, 687 + 0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC, 688 + 0x20, 0x0C, 0x44, 0x20, 0x00, 0x00, 0x00, 0x3A, 689 + 0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03, 690 + 0x00, 0x60, 0x59, 0x3A, 0x3A, 0x00, 0x00, 0x3A, 691 + 0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00, 692 + 0x50, 0x03, 0x74, 0x14, 0x08, 0x43, 0x08, 0x43, 693 + 0x04, 0x45, 0x30, 0x30, 0x40, 0x20, 694 + }, 695 + { /* Init_SR80_SR93 */ 696 + 0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A, 697 + 0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A, 698 + 0x00, 0x00, 0x00, 0x00, 699 + }, 700 + { /* Init_SRA0_SRAF */ 701 + 0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED, 702 + 0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF, 703 + }, 704 + { /* Init_GR00_GR08 */ 705 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 706 + 0xFF, 707 + }, 708 + { /* Init_AR00_AR14 */ 709 + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 710 + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 711 + 0x41, 0x00, 0x0F, 0x00, 0x00, 712 + }, 713 + { /* Init_CR00_CR18 */ 714 + 0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5, 715 + 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 716 + 0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3, 717 + 0xFF, 718 + }, 719 + { /* Init_CR30_CR4D */ 720 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20, 721 + 0x00, 0x00, 0x30, 0x40, 0x00, 0xFF, 0xBF, 0xFF, 722 + 0x2E, 0x27, 0x00, 0x2b, 0x0c, 0x0F, 0xEF, 0x00, 723 + 0xFe, 0x0f, 0x01, 0xC0, 0x27, 0xEF, 724 + }, 725 + { /* Init_CR90_CRA7 */ 726 + 0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26, 727 + 0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00, 728 + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03, 729 + }, 730 + }, 731 + 732 + { /* mode#8: 320 x 240 32Bpp 60Hz */ 733 + 320, 240, 32, 60, 734 + /* Init_MISC */ 735 + 0xEB, 736 + { /* Init_SR0_SR4 */ 737 + 0x03, 0x01, 0x0F, 0x03, 0x0E, 738 + }, 739 + { /* Init_SR10_SR24 */ 740 + 0xF3, 0xB6, 0xC0, 0xDD, 0x00, 0x0E, 0x17, 0x2C, 741 + 0x99, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 742 + 0xC4, 0x32, 0x02, 0x01, 0x01, 743 + }, 744 + { /* Init_SR30_SR75 */ 745 + 0x38, 0x03, 0x20, 0x09, 0xC0, 0x3A, 0x3A, 0x3A, 746 + 0x3A, 0x3A, 0x3A, 0x3A, 0x00, 0x00, 0x03, 0xFF, 747 + 0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC, 748 + 0x20, 0x0C, 0x44, 0x20, 0x00, 0x00, 0x00, 0x3A, 749 + 0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03, 750 + 0x00, 0x60, 0x59, 0x3A, 0x3A, 0x00, 0x00, 0x3A, 751 + 0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00, 752 + 0x50, 0x03, 0x74, 0x14, 0x08, 0x43, 0x08, 0x43, 753 + 0x04, 0x45, 0x30, 0x30, 0x40, 0x20, 754 + }, 755 + { /* Init_SR80_SR93 */ 756 + 0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A, 757 + 0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A, 758 + 0x00, 0x00, 0x00, 0x00, 759 + }, 760 + { /* Init_SRA0_SRAF */ 761 + 0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED, 762 + 0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF, 763 + }, 764 + { /* Init_GR00_GR08 */ 765 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 766 + 0xFF, 767 + }, 768 + { /* Init_AR00_AR14 */ 769 + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 770 + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 771 + 0x41, 0x00, 0x0F, 0x00, 0x00, 772 + }, 773 + { /* Init_CR00_CR18 */ 774 + 0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5, 775 + 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 776 + 0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3, 777 + 0xFF, 778 + }, 779 + { /* Init_CR30_CR4D */ 780 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20, 781 + 0x00, 0x00, 0x30, 0x40, 0x00, 0xFF, 0xBF, 0xFF, 782 + 0x2E, 0x27, 0x00, 0x2b, 0x0c, 0x0F, 0xEF, 0x00, 783 + 0xFe, 0x0f, 0x01, 0xC0, 0x27, 0xEF, 784 + }, 785 + { /* Init_CR90_CRA7 */ 786 + 0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26, 787 + 0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00, 788 + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03, 789 + }, 790 + }, 791 + }; 792 + 793 + #define numVGAModes (sizeof(VGAMode) / sizeof(struct ModeInit))
+1 -1
drivers/staging/vt6655/Kconfig
··· 1 1 config VT6655 2 2 tristate "VIA Technologies VT6655 support" 3 - depends on PCI 3 + depends on PCI && WLAN 4 4 select WIRELESS_EXT 5 5 select WEXT_PRIV 6 6 ---help---
+1 -1
drivers/staging/vt6656/Kconfig
··· 1 1 config VT6656 2 2 tristate "VIA Technologies VT6656 support" 3 - depends on USB 3 + depends on USB && WLAN 4 4 select WIRELESS_EXT 5 5 select WEXT_PRIV 6 6 ---help---
+1 -1
drivers/staging/wlan-ng/prism2fw.c
··· 439 439 } 440 440 } 441 441 *nfchunks = 0; 442 - memset(fchunk, 0, sizeof(fchunk)); 442 + memset(fchunk, 0, sizeof(*fchunk)); 443 443 444 444 } 445 445
-587
include/linux/dst.h
··· 1 - /* 2 - * 2007+ Copyright (c) Evgeniy Polyakov <johnpol@2ka.mipt.ru> 3 - * All rights reserved. 4 - * 5 - * This program is free software; you can redistribute it and/or modify 6 - * it under the terms of the GNU General Public License as published by 7 - * the Free Software Foundation; either version 2 of the License, or 8 - * (at your option) any later version. 9 - * 10 - * This program is distributed in the hope that it will be useful, 11 - * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 - * GNU General Public License for more details. 14 - */ 15 - 16 - #ifndef __DST_H 17 - #define __DST_H 18 - 19 - #include <linux/types.h> 20 - #include <linux/connector.h> 21 - 22 - #define DST_NAMELEN 32 23 - #define DST_NAME "dst" 24 - 25 - enum { 26 - /* Remove node with given id from storage */ 27 - DST_DEL_NODE = 0, 28 - /* Add remote node with given id to the storage */ 29 - DST_ADD_REMOTE, 30 - /* Add local node with given id to the storage to be exported and used by remote peers */ 31 - DST_ADD_EXPORT, 32 - /* Crypto initialization command (hash/cipher used to protect the connection) */ 33 - DST_CRYPTO, 34 - /* Security attributes for given connection (permissions for example) */ 35 - DST_SECURITY, 36 - /* Register given node in the block layer subsystem */ 37 - DST_START, 38 - DST_CMD_MAX 39 - }; 40 - 41 - struct dst_ctl 42 - { 43 - /* Storage name */ 44 - char name[DST_NAMELEN]; 45 - /* Command flags */ 46 - __u32 flags; 47 - /* Command itself (see above) */ 48 - __u32 cmd; 49 - /* Maximum number of pages per single request in this device */ 50 - __u32 max_pages; 51 - /* Stale/error transaction scanning timeout in milliseconds */ 52 - __u32 trans_scan_timeout; 53 - /* Maximum number of retry sends before completing transaction as broken */ 54 - __u32 trans_max_retries; 55 - /* Storage size */ 56 - __u64 size; 57 - }; 58 - 59 - /* Reply command carries completion status */ 60 - struct dst_ctl_ack 61 - { 62 - struct cn_msg msg; 63 - int error; 64 - int unused[3]; 65 - }; 66 - 67 - /* 68 - * Unfortunaltely socket address structure is not exported to userspace 69 - * and is redefined there. 70 - */ 71 - #define SADDR_MAX_DATA 128 72 - 73 - struct saddr { 74 - /* address family, AF_xxx */ 75 - unsigned short sa_family; 76 - /* 14 bytes of protocol address */ 77 - char sa_data[SADDR_MAX_DATA]; 78 - /* Number of bytes used in sa_data */ 79 - unsigned short sa_data_len; 80 - }; 81 - 82 - /* Address structure */ 83 - struct dst_network_ctl 84 - { 85 - /* Socket type: datagram, stream...*/ 86 - unsigned int type; 87 - /* Let me guess, is it a Jupiter diameter? */ 88 - unsigned int proto; 89 - /* Peer's address */ 90 - struct saddr addr; 91 - }; 92 - 93 - struct dst_crypto_ctl 94 - { 95 - /* Cipher and hash names */ 96 - char cipher_algo[DST_NAMELEN]; 97 - char hash_algo[DST_NAMELEN]; 98 - 99 - /* Key sizes. Can be zero for digest for example */ 100 - unsigned int cipher_keysize, hash_keysize; 101 - /* Alignment. Calculated by the DST itself. */ 102 - unsigned int crypto_attached_size; 103 - /* Number of threads to perform crypto operations */ 104 - int thread_num; 105 - }; 106 - 107 - /* Export security attributes have this bits checked in when client connects */ 108 - #define DST_PERM_READ (1<<0) 109 - #define DST_PERM_WRITE (1<<1) 110 - 111 - /* 112 - * Right now it is simple model, where each remote address 113 - * is assigned to set of permissions it is allowed to perform. 114 - * In real world block device does not know anything but 115 - * reading and writing, so it should be more than enough. 116 - */ 117 - struct dst_secure_user 118 - { 119 - unsigned int permissions; 120 - struct saddr addr; 121 - }; 122 - 123 - /* 124 - * Export control command: device to export and network address to accept 125 - * clients to work with given device 126 - */ 127 - struct dst_export_ctl 128 - { 129 - char device[DST_NAMELEN]; 130 - struct dst_network_ctl ctl; 131 - }; 132 - 133 - enum { 134 - DST_CFG = 1, /* Request remote configuration */ 135 - DST_IO, /* IO command */ 136 - DST_IO_RESPONSE, /* IO response */ 137 - DST_PING, /* Keepalive message */ 138 - DST_NCMD_MAX, 139 - }; 140 - 141 - struct dst_cmd 142 - { 143 - /* Network command itself, see above */ 144 - __u32 cmd; 145 - /* 146 - * Size of the attached data 147 - * (in most cases, for READ command it means how many bytes were requested) 148 - */ 149 - __u32 size; 150 - /* Crypto size: number of attached bytes with digest/hmac */ 151 - __u32 csize; 152 - /* Here we can carry secret data */ 153 - __u32 reserved; 154 - /* Read/write bits, see how they are encoded in bio structure */ 155 - __u64 rw; 156 - /* BIO flags */ 157 - __u64 flags; 158 - /* Unique command id (like transaction ID) */ 159 - __u64 id; 160 - /* Sector to start IO from */ 161 - __u64 sector; 162 - /* Hash data is placed after this header */ 163 - __u8 hash[0]; 164 - }; 165 - 166 - /* 167 - * Convert command to/from network byte order. 168 - * We do not use hton*() functions, since there is 169 - * no 64-bit implementation. 170 - */ 171 - static inline void dst_convert_cmd(struct dst_cmd *c) 172 - { 173 - c->cmd = __cpu_to_be32(c->cmd); 174 - c->csize = __cpu_to_be32(c->csize); 175 - c->size = __cpu_to_be32(c->size); 176 - c->sector = __cpu_to_be64(c->sector); 177 - c->id = __cpu_to_be64(c->id); 178 - c->flags = __cpu_to_be64(c->flags); 179 - c->rw = __cpu_to_be64(c->rw); 180 - } 181 - 182 - /* Transaction id */ 183 - typedef __u64 dst_gen_t; 184 - 185 - #ifdef __KERNEL__ 186 - 187 - #include <linux/blkdev.h> 188 - #include <linux/bio.h> 189 - #include <linux/device.h> 190 - #include <linux/mempool.h> 191 - #include <linux/net.h> 192 - #include <linux/poll.h> 193 - #include <linux/rbtree.h> 194 - 195 - #ifdef CONFIG_DST_DEBUG 196 - #define dprintk(f, a...) printk(KERN_NOTICE f, ##a) 197 - #else 198 - static inline void __attribute__ ((format (printf, 1, 2))) 199 - dprintk(const char *fmt, ...) {} 200 - #endif 201 - 202 - struct dst_node; 203 - 204 - struct dst_trans 205 - { 206 - /* DST node we are working with */ 207 - struct dst_node *n; 208 - 209 - /* Entry inside transaction tree */ 210 - struct rb_node trans_entry; 211 - 212 - /* Merlin kills this transaction when this memory cell equals zero */ 213 - atomic_t refcnt; 214 - 215 - /* How this transaction should be processed by crypto engine */ 216 - short enc; 217 - /* How many times this transaction was resent */ 218 - short retries; 219 - /* Completion status */ 220 - int error; 221 - 222 - /* When did we send it to the remote peer */ 223 - long send_time; 224 - 225 - /* My name is... 226 - * Well, computers does not speak, they have unique id instead */ 227 - dst_gen_t gen; 228 - 229 - /* Block IO we are working with */ 230 - struct bio *bio; 231 - 232 - /* Network command for above block IO request */ 233 - struct dst_cmd cmd; 234 - }; 235 - 236 - struct dst_crypto_engine 237 - { 238 - /* What should we do with all block requests */ 239 - struct crypto_hash *hash; 240 - struct crypto_ablkcipher *cipher; 241 - 242 - /* Pool of pages used to encrypt data into before sending */ 243 - int page_num; 244 - struct page **pages; 245 - 246 - /* What to do with current request */ 247 - int enc; 248 - /* Who we are and where do we go */ 249 - struct scatterlist *src, *dst; 250 - 251 - /* Maximum timeout waiting for encryption to be completed */ 252 - long timeout; 253 - /* IV is a 64-bit sequential counter */ 254 - u64 iv; 255 - 256 - /* Secret data */ 257 - void *private; 258 - 259 - /* Cached temporary data lives here */ 260 - int size; 261 - void *data; 262 - }; 263 - 264 - struct dst_state 265 - { 266 - /* The main state protection */ 267 - struct mutex state_lock; 268 - 269 - /* Polling machinery for sockets */ 270 - wait_queue_t wait; 271 - wait_queue_head_t *whead; 272 - /* Most of events are being waited here */ 273 - wait_queue_head_t thread_wait; 274 - 275 - /* Who owns this? */ 276 - struct dst_node *node; 277 - 278 - /* Network address for this state */ 279 - struct dst_network_ctl ctl; 280 - 281 - /* Permissions to work with: read-only or rw connection */ 282 - u32 permissions; 283 - 284 - /* Called when we need to clean private data */ 285 - void (* cleanup)(struct dst_state *st); 286 - 287 - /* Used by the server: BIO completion queues BIOs here */ 288 - struct list_head request_list; 289 - spinlock_t request_lock; 290 - 291 - /* Guess what? No, it is not number of planets */ 292 - atomic_t refcnt; 293 - 294 - /* This flags is set when connection should be dropped */ 295 - int need_exit; 296 - 297 - /* 298 - * Socket to work with. Second pointer is used for 299 - * lockless check if socket was changed before performing 300 - * next action (like working with cached polling result) 301 - */ 302 - struct socket *socket, *read_socket; 303 - 304 - /* Cached preallocated data */ 305 - void *data; 306 - unsigned int size; 307 - 308 - /* Currently processed command */ 309 - struct dst_cmd cmd; 310 - }; 311 - 312 - struct dst_info 313 - { 314 - /* Device size */ 315 - u64 size; 316 - 317 - /* Local device name for export devices */ 318 - char local[DST_NAMELEN]; 319 - 320 - /* Network setup */ 321 - struct dst_network_ctl net; 322 - 323 - /* Sysfs bits use this */ 324 - struct device device; 325 - }; 326 - 327 - struct dst_node 328 - { 329 - struct list_head node_entry; 330 - 331 - /* Hi, my name is stored here */ 332 - char name[DST_NAMELEN]; 333 - /* My cache name is stored here */ 334 - char cache_name[DST_NAMELEN]; 335 - 336 - /* Block device attached to given node. 337 - * Only valid for exporting nodes */ 338 - struct block_device *bdev; 339 - /* Network state machine for given peer */ 340 - struct dst_state *state; 341 - 342 - /* Block IO machinery */ 343 - struct request_queue *queue; 344 - struct gendisk *disk; 345 - 346 - /* Number of threads in processing pool */ 347 - int thread_num; 348 - /* Maximum number of pages in single IO */ 349 - int max_pages; 350 - 351 - /* I'm that big in bytes */ 352 - loff_t size; 353 - 354 - /* Exported to userspace node information */ 355 - struct dst_info *info; 356 - 357 - /* 358 - * Security attribute list. 359 - * Used only by exporting node currently. 360 - */ 361 - struct list_head security_list; 362 - struct mutex security_lock; 363 - 364 - /* 365 - * When this unerflows below zero, university collapses. 366 - * But this will not happen, since node will be freed, 367 - * when reference counter reaches zero. 368 - */ 369 - atomic_t refcnt; 370 - 371 - /* How precisely should I be started? */ 372 - int (*start)(struct dst_node *); 373 - 374 - /* Crypto capabilities */ 375 - struct dst_crypto_ctl crypto; 376 - u8 *hash_key; 377 - u8 *cipher_key; 378 - 379 - /* Pool of processing thread */ 380 - struct thread_pool *pool; 381 - 382 - /* Transaction IDs live here */ 383 - atomic_long_t gen; 384 - 385 - /* 386 - * How frequently and how many times transaction 387 - * tree should be scanned to drop stale objects. 388 - */ 389 - long trans_scan_timeout; 390 - int trans_max_retries; 391 - 392 - /* Small gnomes live here */ 393 - struct rb_root trans_root; 394 - struct mutex trans_lock; 395 - 396 - /* 397 - * Transaction cache/memory pool. 398 - * It is big enough to contain not only transaction 399 - * itself, but additional crypto data (digest/hmac). 400 - */ 401 - struct kmem_cache *trans_cache; 402 - mempool_t *trans_pool; 403 - 404 - /* This entity scans transaction tree */ 405 - struct delayed_work trans_work; 406 - 407 - wait_queue_head_t wait; 408 - }; 409 - 410 - /* Kernel representation of the security attribute */ 411 - struct dst_secure 412 - { 413 - struct list_head sec_entry; 414 - struct dst_secure_user sec; 415 - }; 416 - 417 - int dst_process_bio(struct dst_node *n, struct bio *bio); 418 - 419 - int dst_node_init_connected(struct dst_node *n, struct dst_network_ctl *r); 420 - int dst_node_init_listened(struct dst_node *n, struct dst_export_ctl *le); 421 - 422 - static inline struct dst_state *dst_state_get(struct dst_state *st) 423 - { 424 - BUG_ON(atomic_read(&st->refcnt) == 0); 425 - atomic_inc(&st->refcnt); 426 - return st; 427 - } 428 - 429 - void dst_state_put(struct dst_state *st); 430 - 431 - struct dst_state *dst_state_alloc(struct dst_node *n); 432 - int dst_state_socket_create(struct dst_state *st); 433 - void dst_state_socket_release(struct dst_state *st); 434 - 435 - void dst_state_exit_connected(struct dst_state *st); 436 - 437 - int dst_state_schedule_receiver(struct dst_state *st); 438 - 439 - void dst_dump_addr(struct socket *sk, struct sockaddr *sa, char *str); 440 - 441 - static inline void dst_state_lock(struct dst_state *st) 442 - { 443 - mutex_lock(&st->state_lock); 444 - } 445 - 446 - static inline void dst_state_unlock(struct dst_state *st) 447 - { 448 - mutex_unlock(&st->state_lock); 449 - } 450 - 451 - void dst_poll_exit(struct dst_state *st); 452 - int dst_poll_init(struct dst_state *st); 453 - 454 - static inline unsigned int dst_state_poll(struct dst_state *st) 455 - { 456 - unsigned int revents = POLLHUP | POLLERR; 457 - 458 - dst_state_lock(st); 459 - if (st->socket) 460 - revents = st->socket->ops->poll(NULL, st->socket, NULL); 461 - dst_state_unlock(st); 462 - 463 - return revents; 464 - } 465 - 466 - static inline int dst_thread_setup(void *private, void *data) 467 - { 468 - return 0; 469 - } 470 - 471 - void dst_node_put(struct dst_node *n); 472 - 473 - static inline struct dst_node *dst_node_get(struct dst_node *n) 474 - { 475 - atomic_inc(&n->refcnt); 476 - return n; 477 - } 478 - 479 - int dst_data_recv(struct dst_state *st, void *data, unsigned int size); 480 - int dst_recv_cdata(struct dst_state *st, void *cdata); 481 - int dst_data_send_header(struct socket *sock, 482 - void *data, unsigned int size, int more); 483 - 484 - int dst_send_bio(struct dst_state *st, struct dst_cmd *cmd, struct bio *bio); 485 - 486 - int dst_process_io(struct dst_state *st); 487 - int dst_export_crypto(struct dst_node *n, struct bio *bio); 488 - int dst_export_send_bio(struct bio *bio); 489 - int dst_start_export(struct dst_node *n); 490 - 491 - int __init dst_export_init(void); 492 - void dst_export_exit(void); 493 - 494 - /* Private structure for export block IO requests */ 495 - struct dst_export_priv 496 - { 497 - struct list_head request_entry; 498 - struct dst_state *state; 499 - struct bio *bio; 500 - struct dst_cmd cmd; 501 - }; 502 - 503 - static inline void dst_trans_get(struct dst_trans *t) 504 - { 505 - atomic_inc(&t->refcnt); 506 - } 507 - 508 - struct dst_trans *dst_trans_search(struct dst_node *node, dst_gen_t gen); 509 - int dst_trans_remove(struct dst_trans *t); 510 - int dst_trans_remove_nolock(struct dst_trans *t); 511 - void dst_trans_put(struct dst_trans *t); 512 - 513 - /* 514 - * Convert bio into network command. 515 - */ 516 - static inline void dst_bio_to_cmd(struct bio *bio, struct dst_cmd *cmd, 517 - u32 command, u64 id) 518 - { 519 - cmd->cmd = command; 520 - cmd->flags = (bio->bi_flags << BIO_POOL_BITS) >> BIO_POOL_BITS; 521 - cmd->rw = bio->bi_rw; 522 - cmd->size = bio->bi_size; 523 - cmd->csize = 0; 524 - cmd->id = id; 525 - cmd->sector = bio->bi_sector; 526 - }; 527 - 528 - int dst_trans_send(struct dst_trans *t); 529 - int dst_trans_crypto(struct dst_trans *t); 530 - 531 - int dst_node_crypto_init(struct dst_node *n, struct dst_crypto_ctl *ctl); 532 - void dst_node_crypto_exit(struct dst_node *n); 533 - 534 - static inline int dst_need_crypto(struct dst_node *n) 535 - { 536 - struct dst_crypto_ctl *c = &n->crypto; 537 - /* 538 - * Logical OR is appropriate here, but boolean one produces 539 - * more optimal code, so it is used instead. 540 - */ 541 - return (c->hash_algo[0] | c->cipher_algo[0]); 542 - } 543 - 544 - int dst_node_trans_init(struct dst_node *n, unsigned int size); 545 - void dst_node_trans_exit(struct dst_node *n); 546 - 547 - /* 548 - * Pool of threads. 549 - * Ready list contains threads currently free to be used, 550 - * active one contains threads with some work scheduled for them. 551 - * Caller can wait in given queue when thread is ready. 552 - */ 553 - struct thread_pool 554 - { 555 - int thread_num; 556 - struct mutex thread_lock; 557 - struct list_head ready_list, active_list; 558 - 559 - wait_queue_head_t wait; 560 - }; 561 - 562 - void thread_pool_del_worker(struct thread_pool *p); 563 - void thread_pool_del_worker_id(struct thread_pool *p, unsigned int id); 564 - int thread_pool_add_worker(struct thread_pool *p, 565 - char *name, 566 - unsigned int id, 567 - void *(* init)(void *data), 568 - void (* cleanup)(void *data), 569 - void *data); 570 - 571 - void thread_pool_destroy(struct thread_pool *p); 572 - struct thread_pool *thread_pool_create(int num, char *name, 573 - void *(* init)(void *data), 574 - void (* cleanup)(void *data), 575 - void *data); 576 - 577 - int thread_pool_schedule(struct thread_pool *p, 578 - int (* setup)(void *stored_private, void *setup_data), 579 - int (* action)(void *stored_private, void *setup_data), 580 - void *setup_data, long timeout); 581 - int thread_pool_schedule_private(struct thread_pool *p, 582 - int (* setup)(void *private, void *data), 583 - int (* action)(void *private, void *data), 584 - void *data, long timeout, void *id); 585 - 586 - #endif /* __KERNEL__ */ 587 - #endif /* __DST_H */