[Swan] Kernel crash with klips

David McCullough ucdevel at gmail.com
Wed Oct 23 08:16:01 EEST 2013


Slava Bendersky wrote the following:
> Hello David, 
> I patched kmod-libreswan and so far running ok, didn't crash and look solid. I will keep monitor it for next couple days. 
> Huge thank you for you help. Is this fix will be included in next releases ? 

Yep,  I will commit the change now,  thanks for trying it out :-)

Cheers,
Davidm

> ----- Original Message -----
> 
> From: "David McCullough" <ucdevel at gmail.com> 
> To: "Slava Bendersky" <volga629 at networklab.ca> 
> Cc: "Libreswan" <swan at lists.libreswan.org> 
> Sent: Tuesday, October 22, 2013 1:07:15 AM 
> Subject: Re: [Swan] Kernel crash with klips 
> 
> 
> 
> Slava Bendersky wrote the following: 
> > Hello David, 
> > Please see attached file. 
> 
> Try the attached patch to libreswan, this should fix it. 
> Its really only a problem when CONFIG_DEBUG_SG is enabled. 
> 
> Cheers, 
> Davidm 
> 
> > 
> > From: "David McCullough" <ucdevel at gmail.com> 
> > To: "Slava Bendersky" <volga629 at networklab.ca> 
> > Sent: Monday, October 21, 2013 9:21:23 PM 
> > Subject: Re: [Swan] Kernel crash with klips 
> > 
> > 
> > Slava Bendersky wrote the following: 
> > > Hello David, 
> > > If this this correct file ? 
> > 
> > Yes, send me the whole file as an attachment, no changes. 
> > I need to know which line is exactly line 65. 
> > 
> > Thanks, 
> > Davidm 
> > 
> > > Block on line 65 
> > > 
> > > vim /usr/src/kernels/3.2.2-10.nl.el6.x86_64/include/linux/scatterlist.h 
> > > 
> > > static inline void sg_assign_page(struct scatterlist *sg, struct page *page) 
> > > { 
> > > unsigned long page_link = sg->page_link & 0x3; 
> > > 
> > > /* 
> > > * In order for the low bit stealing approach to work, pages 
> > > * must be aligned at a 32-bit boundary as a minimum. 
> > > */ 
> > > BUG_ON((unsigned long) page & 0x03); 
> > > #ifdef CONFIG_DEBUG_SG 
> > > BUG_ON(sg->sg_magic != SG_MAGIC); 
> > > BUG_ON(sg_is_chain(sg)); 
> > > #endif 
> > > sg->page_link = page_link | (unsigned long) page; 
> > > } 
> > > 
> > > 
> > > 
> > > 
> > > Slava. 
> > > ----- Original Message ----- 
> > > 
> > > From: "David McCullough" <ucdevel at gmail.com> 
> > > To: "Slava Bendersky" <volga629 at networklab.ca> 
> > > Cc: swan at lists.libreswan.org 
> > > Sent: Sunday, October 20, 2013 11:48:28 PM 
> > > Subject: Re: [Swan] Kernel crash with klips 
> > > 
> > > 
> > > Slava Bendersky wrote the following: 
> > > > Hello David, 
> > > > I was be able get crash report, see attached text file. 
> > > 
> > > Cool, that helps a lot. 
> > > 
> > > Do you have a copy of /usr/include/include/linux/scatterlist.h ? 
> > > Specifically I need line 65. Perhaps if you have the kernel source 
> > > or headers in /usr/src/.... 
> > > 
> > > I recall seeing something similar with OCF so if we can figure out exactly 
> > > which "BUG" caused the oops we may be able to resolve it for you :-) 
> > > 
> > > Cheers, 
> > > Davidm 
> > > 
> > > > ----- Original Message ----- 
> > > > 
> > > > From: "Slava Bendersky" <volga629 at skillsearch.ca> 
> > > > To: "David McCullough" <ucdevel at gmail.com> 
> > > > Cc: swan at lists.libreswan.org 
> > > > Sent: Wednesday, October 9, 2013 5:45:48 PM 
> > > > Subject: Re: [Swan] Kernel crash with klips 
> > > > 
> > > > Hello Everyone, 
> > > > Finally I was be able catch first part of the crash. I hope it will give info. 
> > > > http://ctrlv.in/246071 
> > > > 
> > > > Slava. 
> > > > ----- Original Message ----- 
> > > > 
> > > > From: "David McCullough" <ucdevel at gmail.com> 
> > > > To: "Slava Bendersky" <volga629 at skillsearch.ca> 
> > > > Cc: swan at lists.libreswan.org 
> > > > Sent: Wednesday, October 2, 2013 11:46:20 PM 
> > > > Subject: Re: [Swan] Kernel crash with klips 
> > > > 
> > > > 
> > > > Slava Bendersky wrote the following: 
> > > > > Hello Everyone, 
> > > > > Trying get more information about constant kernel crash. Please see this screen shot http://ctrlv.in/243365 . 
> > > > > Libreswan 3.5 klips kernel 3.2.2-9.nl.el6.x86_64. This box is working for internal branch routing and it running quagga ospfd with vpn tunnel transport mode. 
> > > > 
> > > > Is there any chance you can retrieve the first part of the oops ? 
> > > > Can you reproduce it ? 
> > > > 
> > > > Thanks, 
> > > > Davidm 
> > > > 
> > > > 
> > > > > [root@ ~]# ipsec verify 
> > > > > Verifying installed system and configuration files 
> > > > > 
> > > > > Version check and ipsec on-path [OK] 
> > > > > Libreswan 3.5 (klips) on 3.2.2-9.nl.el6.x86_64 
> > > > > Checking for IPsec support in kernel [OK] 
> > > > > KLIPS: checking for NAT Traversal support [OK] 
> > > > > KLIPS: checking for OCF crypto offload support [OK] 
> > > > > KLIPS: IPsec SAref kernel support [OK] 
> > > > > KLIPS: IPsec SAref Bind kernel support [OK] 
> > > > > Pluto ipsec.conf syntax [OK] 
> > > > > 
> > > > > 
> > > > > 
> > > > > Slava. 
> > > > > 
> > > > 
> > > > > _______________________________________________ 
> > > > > Swan mailing list 
> > > > > Swan at lists.libreswan.org 
> > > > > https://lists.libreswan.org/mailman/listinfo/swan 
> > > > 
> > > > 
> > > > -- 
> > > > David McCullough, davidm at spottygum.com, Ph: 0410 560 763 
> > > > 
> > > > 
> > > > _______________________________________________ 
> > > > Swan mailing list 
> > > > Swan at lists.libreswan.org 
> > > > https://lists.libreswan.org/mailman/listinfo/swan 
> > > > 
> > > 
> > > > [ 122.209632] klips_info:ipsec_init: KLIPS startup, Libreswan KLIPS IPsec stack version: 3.5 
> > > > [ 122.211792] NET: Registered protocol family 15 
> > > > [ 122.224600] registered KLIPS /proc/sys/net 
> > > > [ 122.224603] klips_info:ipsec_alg_init: KLIPS alg v=0.8.1-0 (EALG_MAX=255, AALG_MAX=255) 
> > > > [ 122.224606] klips_info:ipsec_alg_init: calling ipsec_alg_static_init() 
> > > > [ 122.224613] ipsec_aes_init(alg_type=15 alg_id=12 name=aes): ret=0 
> > > > [ 122.224620] ipsec_aes_init(alg_type=14 alg_id=9 name=aes_mac): ret=0 
> > > > [ 122.224634] ipsec_3des_init(alg_type=15 alg_id=3 name=3des): ret=0 
> > > > [ 122.243327] KLIPS cryptoapi interface: alg_type=15 alg_id=12 name=cbc(aes) keyminbits=128 keymaxbits=256, found(0) 
> > > > [ 122.243337] KLIPS cryptoapi interface: alg_type=15 alg_id=253 name=cbc(twofish) keyminbits=128 keymaxbits=256, found(0) 
> > > > [ 122.262324] KLIPS cryptoapi interface: alg_type=15 alg_id=252 name=cbc(serpent) keyminbits=128 keymaxbits=256, found(0) 
> > > > [ 122.281322] KLIPS cryptoapi interface: alg_type=15 alg_id=6 name=cbc(cast5) keyminbits=128 keymaxbits=128, found(0) 
> > > > [ 122.281332] KLIPS cryptoapi interface: alg_type=15 alg_id=7 name=cbc(blowfish) keyminbits=96 keymaxbits=448, found(0) 
> > > > [ 122.298314] KLIPS cryptoapi interface: alg_type=15 alg_id=3 name=cbc(des3_ede) keyminbits=192 keymaxbits=192, found(0) 
> > > > [ 122.423733] 
> > > > [ 125.217139] ------------[ cut here ]------------ 
> > > > [ 125.217246] kernel BUG at include/linux/scatterlist.h:65! 
> > > > [ 125.217322] invalid opcode: 0000 [#1] SMP 
> > > > [ 125.217434] CPU 0 
> > > > [ 125.217476] Modules linked in: ipsec(O) camellia lzo cast6 cast5 deflate zlib_deflate cts gcm ccm serpent blowfish_generic blowfish_x86_64 blowfish_common twofish_generic twofish_x86_64_3way twofish_x86_64 twofish_common xcbc sha256_generic sha512_generic des_generic timeriomem_rng virtio_rng ipt_LOG xt_limit ipt_MASQUERADE xt_recent iptable_rawpost(O) xt_geoip(O) xt_comment iptable_nat xt_addrtype xt_NFLOG nfnetlink_log xt_mark iptable_mangle xt_helper iptable_raw xt_multiport xt_conntrack nf_nat_tftp nf_nat_snmp_basic nf_conntrack_snmp nf_nat_pptp nf_nat_proto_gre nf_nat_irc nf_nat_h323 nf_nat_ftp nf_nat_amanda nf_nat nf_conntrack_ipv4 nf_defrag_ipv4 ts_kmp nf_conntrack_amanda nf_conntrack_sane nf_conntrack_tftp nf_conntrack_proto_udplite nf_conntrack_proto_sctp nf_conntrack_pptp nf_conntrack_proto_gre nf_conntrack_netlink nfnetlink nf_conntrack_netbios_ns nf_conntrack_broadcast nf_conntrack_irc nf_conntrack_h323 nf_conntrack_ftp nf_conntrack xpp_usb(O) xpp(O) wctc4xxp(O) dahdi_transcode(O) wcb4xxp(O) wctdm(O) wcfxo(O) wctdm24xxp(O) wcte11xp(O) wct1xxp(O) wcte12xp(O) dahdi_voicebus(O) wct4xxp(O) dahdi(O) crc_ccitt ip_gre gre vmci(O) binfmt_misc l2tp_ppp pppox ppp_generic slhc l2tp_netlink l2tp_core ppdev joydev e1000 vmw_balloon parport_pc parport i2c_piix4 i2c_core shpchp mptspi mptscsih mptbase scsi_transport_spi [last unloaded: scsi_wait_scan] 
> > > > [ 125.221900] 
> > > > [ 125.221968] Pid: 0, comm: swapper/0 Tainted: G O 3.2.2-10.nl.el6.x86_64 #1 VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform 
> > > > [ 125.222271] RIP: 0010:[<ffffffffa04141d2>] [<ffffffffa04141d2>] _capi_cbc_encrypt+0x1a2/0x1f0 [ipsec] 
> > > > [ 125.222480] RSP: 0018:ffff880079603860 EFLAGS: 00010293 
> > > > [ 125.222587] RAX: ffffea0001d0f1c0 RBX: ffff880075741ab8 RCX: 0000000087654321 
> > > > [ 125.222713] RDX: 0000000000000000 RSI: ffff8800743c749a RDI: ffff8800743c74a2 
> > > > [ 125.222838] RBP: ffff880079603920 R08: 1b784d5c6042031a R09: 1b784d5c6042031a 
> > > > [ 125.222964] R10: ffff8800743c74a2 R11: 0000000000000005 R12: ffff880079603870 
> > > > [ 125.223089] R13: 0000000000000048 R14: ffff8800743c74a2 R15: ffff8800796038a0 
> > > > [ 125.223215] FS: 0000000000000000(0000) GS:ffff880079600000(0000) knlGS:0000000000000000 
> > > > [ 125.223379] CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b 
> > > > [ 125.223490] CR2: 00007fffa721d140 CR3: 0000000037cc7000 CR4: 00000000000006f0 
> > > > [ 125.223645] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 
> > > > [ 125.223790] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 
> > > > [ 125.223917] Process swapper/0 (pid: 0, threadinfo ffffffff81c00000, task ffffffff81c0d020) 
> > > > [ 125.224079] Stack: 
> > > > [ 125.224159] 0000000000000000 0000000000000000 1b784d5c6042031a 0000000000000000 
> > > > [ 125.224423] 0000000000000000 0000000000000000 0000000000000000 0000000000000000 
> > > > [ 125.224686] 0000000000000000 0000000000000000 0000000000000000 0000000000000000 
> > > > [ 125.224949] Call Trace: 
> > > > [ 125.225025] <IRQ> 
> > > > [ 125.225133] [<ffffffffa040c9b3>] ipsec_alg_esp_encrypt+0x73/0x160 [ipsec] 
> > > > [ 125.225262] [<ffffffffa0408048>] ipsec_rcv_esp_decrypt+0x88/0x130 [ipsec] 
> > > > [ 125.225390] [<ffffffffa03f3172>] ipsec_rcv_decrypt+0x32/0x60 [ipsec] 
> > > > [ 125.225513] [<ffffffffa03f5349>] ipsec_rsm+0x69/0x350 [ipsec] 
> > > > [ 125.225629] [<ffffffff8157e9f0>] ? ip_rcv_finish+0x5e0/0x5e0 
> > > > [ 125.225745] [<ffffffffa03f57b5>] ipsec_rcv+0x35/0xb0 [ipsec] 
> > > > [ 125.225858] [<ffffffff8157eb0d>] ip_local_deliver_finish+0x11d/0x400 
> > > > [ 125.225977] [<ffffffff8157ea3c>] ? ip_local_deliver_finish+0x4c/0x400 
> > > > [ 125.226098] [<ffffffff8157e1f0>] ip_local_deliver+0x80/0x90 
> > > > [ 125.226213] [<ffffffff8157e582>] ip_rcv_finish+0x172/0x5e0 
> > > > [ 125.226324] [<ffffffff8157e098>] ip_rcv+0x238/0x310 
> > > > [ 125.226429] [<ffffffff81541320>] __netif_receive_skb+0x2a0/0x840 
> > > > [ 125.226545] [<ffffffff81541185>] ? __netif_receive_skb+0x105/0x840 
> > > > [ 125.226662] [<ffffffff81541fda>] ? netif_receive_skb+0x2a/0x120 
> > > > [ 125.226777] [<ffffffff815420be>] netif_receive_skb+0x10e/0x120 
> > > > [ 125.226891] [<ffffffff81541fda>] ? netif_receive_skb+0x2a/0x120 
> > > > [ 125.227006] [<ffffffff8154257d>] ? dev_gro_receive+0x23d/0x390 
> > > > [ 125.227119] [<ffffffff8154248e>] ? dev_gro_receive+0x14e/0x390 
> > > > [ 125.227233] [<ffffffff81542120>] napi_skb_finish+0x50/0x70 
> > > > [ 125.227344] [<ffffffff81542795>] napi_gro_receive+0xc5/0xd0 
> > > > [ 125.227465] [<ffffffffa00706ae>] e1000_receive_skb+0x6e/0x90 [e1000] 
> > > > [ 125.227589] [<ffffffffa0073c9a>] e1000_clean_rx_irq+0x2fa/0x590 [e1000] 
> > > > [ 125.227717] [<ffffffffa0072a8e>] e1000_clean+0x1de/0x550 [e1000] 
> > > > [ 125.227834] [<ffffffff8131892c>] ? debug_object_activate+0x5c/0x160 
> > > > [ 125.227953] [<ffffffff8131892c>] ? debug_object_activate+0x5c/0x160 
> > > > [ 125.228074] [<ffffffff8101b8ef>] ? update_vsyscall+0x4f/0x130 
> > > > [ 125.228188] [<ffffffff81542995>] net_rx_action+0x145/0x3c0 
> > > > [ 125.228300] [<ffffffff810815b0>] __do_softirq+0xf0/0x390 
> > > > [ 125.228410] [<ffffffff816731fc>] call_softirq+0x1c/0x30 
> > > > [ 125.228518] [<ffffffff8101842d>] do_softirq+0xad/0xe0 
> > > > [ 125.228624] [<ffffffff810810e5>] irq_exit+0xf5/0x110 
> > > > [ 125.228730] [<ffffffff81673ad6>] do_IRQ+0x66/0xe0 
> > > > [ 125.228833] [<ffffffff81668733>] common_interrupt+0x73/0x73 
> > > > [ 125.228943] <EOI> 
> > > > [ 125.229045] [<ffffffff8101fadf>] ? default_idle+0x4f/0x340 
> > > > [ 125.229156] [<ffffffff810414ab>] ? native_safe_halt+0xb/0x10 
> > > > [ 125.229269] [<ffffffff810bae7d>] ? trace_hardirqs_on+0xd/0x10 
> > > > [ 125.229382] [<ffffffff8101fae4>] default_idle+0x54/0x340 
> > > > [ 125.229491] [<ffffffff81016136>] cpu_idle+0xe6/0x130 
> > > > [ 125.229597] [<ffffffff8164c95b>] rest_init+0xdb/0xf0 
> > > > [ 125.229703] [<ffffffff8164c880>] ? csum_partial_copy_generic+0x170/0x170 
> > > > [ 125.229827] [<ffffffff81ecbdaa>] start_kernel+0x3f3/0x3fe 
> > > > [ 125.229936] [<ffffffff81ecb346>] x86_64_start_reservations+0x131/0x135 
> > > > [ 125.230057] [<ffffffff81ecb44d>] x86_64_start_kernel+0x103/0x112 
> > > > [ 125.230172] Code: 5f c9 c3 66 0f 1f 44 00 00 44 89 e9 4c 89 fa 4c 89 fe ff 53 18 89 c3 eb b7 e8 3b 55 c6 e0 0f 0b eb fe 0f 0b 0f 1f 44 00 00 eb f9 <0f> 0b eb fe 8b 95 7c ff ff ff 4d 89 f9 45 89 e8 4c 89 f1 48 89 
> > > > [ 125.232246] RIP [<ffffffffa04141d2>] _capi_cbc_encrypt+0x1a2/0x1f0 [ipsec] 
> > > > [ 125.232403] RSP <ffff880079603860> 
> > > > 
> > > > crash> bt 
> > > > PID: 0 TASK: ffffffff81c0d020 CPU: 0 COMMAND: "swapper/0" 
> > > > #0 [ffff880079603510] machine_kexec at ffffffff8103c27e 
> > > > #1 [ffff880079603580] crash_kexec at ffffffff810d63a2 
> > > > #2 [ffff880079603650] oops_end at ffffffff81669638 
> > > > #3 [ffff880079603680] die at ffffffff8101982b 
> > > > #4 [ffff8800796036b0] do_trap at ffffffff81668ff4 
> > > > #5 [ffff880079603710] do_invalid_op at ffffffff81017775 
> > > > #6 [ffff8800796037b0] invalid_op at ffffffff81672f7b 
> > > > [exception RIP: _capi_cbc_encrypt+418] 
> > > > RIP: ffffffffa04141d2 RSP: ffff880079603860 RFLAGS: 00010293 
> > > > RAX: ffffea0001d0f1c0 RBX: ffff880075741ab8 RCX: 0000000087654321 
> > > > RDX: 0000000000000000 RSI: ffff8800743c749a RDI: ffff8800743c74a2 
> > > > RBP: ffff880079603920 R8: 1b784d5c6042031a R9: 1b784d5c6042031a 
> > > > R10: ffff8800743c74a2 R11: 0000000000000005 R12: ffff880079603870 
> > > > R13: 0000000000000048 R14: ffff8800743c74a2 R15: ffff8800796038a0 
> > > > ORIG_RAX: ffffffffffffffff CS: 0010 SS: 0018 
> > > > #7 [ffff880079603928] ipsec_alg_esp_encrypt at ffffffffa040c9b3 [ipsec] 
> > > > #8 [ffff880079603988] ipsec_rcv_esp_decrypt at ffffffffa0408048 [ipsec] 
> > > > #9 [ffff8800796039c8] ipsec_rcv_decrypt at ffffffffa03f3172 [ipsec] 
> > > > #10 [ffff8800796039e8] ipsec_rsm at ffffffffa03f5349 [ipsec] 
> > > > #11 [ffff880079603a08] ipsec_rcv at ffffffffa03f57b5 [ipsec] 
> > > > #12 [ffff880079603a28] ip_local_deliver_finish at ffffffff8157eb0d 
> > > > #13 [ffff880079603a78] ip_local_deliver at ffffffff8157e1f0 
> > > > #14 [ffff880079603aa8] ip_rcv_finish at ffffffff8157e582 
> > > > #15 [ffff880079603ad8] ip_rcv at ffffffff8157e098 
> > > > #16 [ffff880079603b18] __netif_receive_skb at ffffffff81541320 
> > > > #17 [ffff880079603b98] netif_receive_skb at ffffffff815420be 
> > > > #18 [ffff880079603bf8] napi_skb_finish at ffffffff81542120 
> > > > #19 [ffff880079603c18] napi_gro_receive at ffffffff81542795 
> > > > #20 [ffff880079603c38] e1000_receive_skb at ffffffffa00706ae [e1000] 
> > > > #21 [ffff880079603c68] e1000_clean_rx_irq at ffffffffa0073c9a [e1000] 
> > > > #22 [ffff880079603d38] e1000_clean at ffffffffa0072a8e [e1000] 
> > > > #23 [ffff880079603e18] net_rx_action at ffffffff81542995 
> > > > #24 [ffff880079603e98] __do_softirq at ffffffff810815b0 
> > > > #25 [ffff880079603f28] call_softirq at ffffffff816731fc 
> > > > #26 [ffff880079603f40] do_softirq at ffffffff8101842d 
> > > > #27 [ffff880079603f60] irq_exit at ffffffff810810e5 
> > > > #28 [ffff880079603f80] do_IRQ at ffffffff81673ad6 
> > > > --- <IRQ stack> --- 
> > > > #29 [ffffffff81c01de8] ret_from_intr at ffffffff81668733 
> > > > [exception RIP: native_safe_halt+11] 
> > > > RIP: ffffffff810414ab RSP: ffffffff81c01e98 RFLAGS: 00000246 
> > > > RAX: 0000000000000000 RBX: ffffffff81c00000 RCX: 0000000000000001 
> > > > RDX: ffffffff81c0d020 RSI: 0000000000000001 RDI: ffffffff8101fadf 
> > > > RBP: ffffffff81c01e98 R8: 0000000000000000 R9: 0000000000000000 
> > > > R10: 0000000000000000 R11: 0000000000000001 R12: 0000000000000046 
> > > > R13: 0000000000000001 R14: ffffffff8166c60b R15: ffffffff81c01e38 
> > > > ORIG_RAX: ffffffffffffff4d CS: 0010 SS: 0018 
> > > > #30 [ffffffff81c01e90] trace_hardirqs_on at ffffffff810bae7d 
> > > > #31 [ffffffff81c01ea0] default_idle at ffffffff8101fae4 
> > > > #32 [ffffffff81c01ec0] cpu_idle at ffffffff81016136 
> > > 
> > > 
> > > -- 
> > > David McCullough, davidm at spottygum.com, Ph: 0410 560 763 
> > > 
> > 
> > -- 
> > David McCullough, davidm at spottygum.com, Ph: 0410 560 763 
> > 
> 
> > [root at eusipgw01 ~]# cat /usr/src/kernels/3.2.2-10.nl.el6.x86_64/include/linux/scatterlist.h 
> > #ifndef _LINUX_SCATTERLIST_H 
> > #define _LINUX_SCATTERLIST_H 
> > 
> > #include <asm/types.h> 
> > #include <asm/scatterlist.h> 
> > #include <linux/mm.h> 
> > #include <linux/string.h> 
> > #include <asm/io.h> 
> > 
> > struct sg_table { 
> > struct scatterlist *sgl; /* the list */ 
> > unsigned int nents; /* number of mapped entries */ 
> > unsigned int orig_nents; /* original size of list */ 
> > }; 
> > 
> > /* 
> > * Notes on SG table design. 
> > * 
> > * Architectures must provide an unsigned long page_link field in the 
> > * scatterlist struct. We use that to place the page pointer AND encode 
> > * information about the sg table as well. The two lower bits are reserved 
> > * for this information. 
> > * 
> > * If bit 0 is set, then the page_link contains a pointer to the next sg 
> > * table list. Otherwise the next entry is at sg + 1. 
> > * 
> > * If bit 1 is set, then this sg entry is the last element in a list. 
> > * 
> > * See sg_next(). 
> > * 
> > */ 
> > 
> > #define SG_MAGIC 0x87654321 
> > 
> > /* 
> > * We overload the LSB of the page pointer to indicate whether it's 
> > * a valid sg entry, or whether it points to the start of a new scatterlist. 
> > * Those low bits are there for everyone! (thanks mason :-) 
> > */ 
> > #define sg_is_chain(sg) ((sg)->page_link & 0x01) 
> > #define sg_is_last(sg) ((sg)->page_link & 0x02) 
> > #define sg_chain_ptr(sg) \ 
> > ((struct scatterlist *) ((sg)->page_link & ~0x03)) 
> > 
> > /** 
> > * sg_assign_page - Assign a given page to an SG entry 
> > * @sg: SG entry 
> > * @page: The page 
> > * 
> > * Description: 
> > * Assign page to sg entry. Also see sg_set_page(), the most commonly used 
> > * variant. 
> > * 
> > **/ 
> > static inline void sg_assign_page(struct scatterlist *sg, struct page *page) 
> > { 
> > unsigned long page_link = sg->page_link & 0x3; 
> > 
> > /* 
> > * In order for the low bit stealing approach to work, pages 
> > * must be aligned at a 32-bit boundary as a minimum. 
> > */ 
> > BUG_ON((unsigned long) page & 0x03); 
> > #ifdef CONFIG_DEBUG_SG 
> > BUG_ON(sg->sg_magic != SG_MAGIC); 
> > BUG_ON(sg_is_chain(sg)); 
> > #endif 
> > sg->page_link = page_link | (unsigned long) page; 
> > } 
> > 
> > /** 
> > * sg_set_page - Set sg entry to point at given page 
> > * @sg: SG entry 
> > * @page: The page 
> > * @len: Length of data 
> > * @offset: Offset into page 
> > * 
> > * Description: 
> > * Use this function to set an sg entry pointing at a page, never assign 
> > * the page directly. We encode sg table information in the lower bits 
> > * of the page pointer. See sg_page() for looking up the page belonging 
> > * to an sg entry. 
> > * 
> > **/ 
> > static inline void sg_set_page(struct scatterlist *sg, struct page *page, 
> > unsigned int len, unsigned int offset) 
> > { 
> > sg_assign_page(sg, page); 
> > sg->offset = offset; 
> > sg->length = len; 
> > } 
> > 
> > static inline struct page *sg_page(struct scatterlist *sg) 
> > { 
> > #ifdef CONFIG_DEBUG_SG 
> > BUG_ON(sg->sg_magic != SG_MAGIC); 
> > BUG_ON(sg_is_chain(sg)); 
> > #endif 
> > return (struct page *)((sg)->page_link & ~0x3); 
> > } 
> > 
> > /** 
> > * sg_set_buf - Set sg entry to point at given data 
> > * @sg: SG entry 
> > * @buf: Data 
> > * @buflen: Data length 
> > * 
> > **/ 
> > static inline void sg_set_buf(struct scatterlist *sg, const void *buf, 
> > unsigned int buflen) 
> > { 
> > sg_set_page(sg, virt_to_page(buf), buflen, offset_in_page(buf)); 
> > } 
> > 
> > /* 
> > * Loop over each sg element, following the pointer to a new list if necessary 
> > */ 
> > #define for_each_sg(sglist, sg, nr, __i) \ 
> > for (__i = 0, sg = (sglist); __i < (nr); __i++, sg = sg_next(sg)) 
> > 
> > /** 
> > * sg_chain - Chain two sglists together 
> > * @prv: First scatterlist 
> > * @prv_nents: Number of entries in prv 
> > * @sgl: Second scatterlist 
> > * 
> > * Description: 
> > * Links @prv@ and @sgl@ together, to form a longer scatterlist. 
> > * 
> > **/ 
> > static inline void sg_chain(struct scatterlist *prv, unsigned int prv_nents, 
> > struct scatterlist *sgl) 
> > { 
> > #ifndef ARCH_HAS_SG_CHAIN 
> > BUG(); 
> > #endif 
> > 
> > /* 
> > * offset and length are unused for chain entry. Clear them. 
> > */ 
> > prv[prv_nents - 1].offset = 0; 
> > prv[prv_nents - 1].length = 0; 
> > 
> > /* 
> > * Set lowest bit to indicate a link pointer, and make sure to clear 
> > * the termination bit if it happens to be set. 
> > */ 
> > prv[prv_nents - 1].page_link = ((unsigned long) sgl | 0x01) & ~0x02; 
> > } 
> > 
> > /** 
> > * sg_mark_end - Mark the end of the scatterlist 
> > * @sg: SG entryScatterlist 
> > * 
> > * Description: 
> > * Marks the passed in sg entry as the termination point for the sg 
> > * table. A call to sg_next() on this entry will return NULL. 
> > * 
> > **/ 
> > static inline void sg_mark_end(struct scatterlist *sg) 
> > { 
> > #ifdef CONFIG_DEBUG_SG 
> > BUG_ON(sg->sg_magic != SG_MAGIC); 
> > #endif 
> > /* 
> > * Set termination bit, clear potential chain bit 
> > */ 
> > sg->page_link |= 0x02; 
> > sg->page_link &= ~0x01; 
> > } 
> > 
> > /** 
> > * sg_phys - Return physical address of an sg entry 
> > * @sg: SG entry 
> > * 
> > * Description: 
> > * This calls page_to_phys() on the page in this sg entry, and adds the 
> > * sg offset. The caller must know that it is legal to call page_to_phys() 
> > * on the sg page. 
> > * 
> > **/ 
> > static inline dma_addr_t sg_phys(struct scatterlist *sg) 
> > { 
> > return page_to_phys(sg_page(sg)) + sg->offset; 
> > } 
> > 
> > /** 
> > * sg_virt - Return virtual address of an sg entry 
> > * @sg: SG entry 
> > * 
> > * Description: 
> > * This calls page_address() on the page in this sg entry, and adds the 
> > * sg offset. The caller must know that the sg page has a valid virtual 
> > * mapping. 
> > * 
> > **/ 
> > static inline void *sg_virt(struct scatterlist *sg) 
> > { 
> > return page_address(sg_page(sg)) + sg->offset; 
> > } 
> > 
> > struct scatterlist *sg_next(struct scatterlist *); 
> > struct scatterlist *sg_last(struct scatterlist *s, unsigned int); 
> > void sg_init_table(struct scatterlist *, unsigned int); 
> > void sg_init_one(struct scatterlist *, const void *, unsigned int); 
> > 
> > typedef struct scatterlist *(sg_alloc_fn)(unsigned int, gfp_t); 
> > typedef void (sg_free_fn)(struct scatterlist *, unsigned int); 
> > 
> > void __sg_free_table(struct sg_table *, unsigned int, sg_free_fn *); 
> > void sg_free_table(struct sg_table *); 
> > int __sg_alloc_table(struct sg_table *, unsigned int, unsigned int, gfp_t, 
> > sg_alloc_fn *); 
> > int sg_alloc_table(struct sg_table *, unsigned int, gfp_t); 
> > 
> > size_t sg_copy_from_buffer(struct scatterlist *sgl, unsigned int nents, 
> > void *buf, size_t buflen); 
> > size_t sg_copy_to_buffer(struct scatterlist *sgl, unsigned int nents, 
> > void *buf, size_t buflen); 
> > 
> > /* 
> > * Maximum number of entries that will be allocated in one piece, if 
> > * a list larger than this is required then chaining will be utilized. 
> > */ 
> > #define SG_MAX_SINGLE_ALLOC (PAGE_SIZE / sizeof(struct scatterlist)) 
> > 
> > 
> > /* 
> > * Mapping sg iterator 
> > * 
> > * Iterates over sg entries mapping page-by-page. On each successful 
> > * iteration, @miter->page points to the mapped page and 
> > * @miter->length bytes of data can be accessed at @miter->addr. As 
> > * long as an interation is enclosed between start and stop, the user 
> > * is free to choose control structure and when to stop. 
> > * 
> > * @miter->consumed is set to @miter->length on each iteration. It 
> > * can be adjusted if the user can't consume all the bytes in one go. 
> > * Also, a stopped iteration can be resumed by calling next on it. 
> > * This is useful when iteration needs to release all resources and 
> > * continue later (e.g. at the next interrupt). 
> > */ 
> > 
> > #define SG_MITER_ATOMIC (1 << 0) /* use kmap_atomic */ 
> > #define SG_MITER_TO_SG (1 << 1) /* flush back to phys on unmap */ 
> > #define SG_MITER_FROM_SG (1 << 2) /* nop */ 
> > 
> > struct sg_mapping_iter { 
> > /* the following three fields can be accessed directly */ 
> > struct page *page; /* currently mapped page */ 
> > void *addr; /* pointer to the mapped area */ 
> > size_t length; /* length of the mapped area */ 
> > size_t consumed; /* number of consumed bytes */ 
> > 
> > /* these are internal states, keep away */ 
> > struct scatterlist *__sg; /* current entry */ 
> > unsigned int __nents; /* nr of remaining entries */ 
> > unsigned int __offset; /* offset within sg */ 
> > unsigned int __flags; 
> > }; 
> > 
> > void sg_miter_start(struct sg_mapping_iter *miter, struct scatterlist *sgl, 
> > unsigned int nents, unsigned int flags); 
> > bool sg_miter_next(struct sg_mapping_iter *miter); 
> > void sg_miter_stop(struct sg_mapping_iter *miter); 
> > 
> > #endif /* _LINUX_SCATTERLIST_H */ 
> 
> 
> -- 
> David McCullough, davidm at spottygum.com, Ph: 0410 560 763 
> 

-- 
David McCullough,  davidm at spottygum.com,   Ph: 0410 560 763


More information about the Swan mailing list