~ubuntu-branches/ubuntu/vivid/linux-backports-modules-3.2.0/vivid

« back to all changes in this revision

Viewing changes to updates/net/ixgbe/src/kcompat.c

  • Committer: Package Import Robot
  • Author(s): Leann Ogasawara
  • Date: 2012-04-24 09:15:36 UTC
  • Revision ID: package-import@ubuntu.com-20120424091536-g1ubxt3rtf9vbtal
Tags: 3.2.0-24.7
* Bump ABI for Precise 3.2.0-24.37
* Added Intel OEM ixgbe 3.8.21 driver
  - LP: #978324

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*******************************************************************************
 
2
 
 
3
  Intel 10 Gigabit PCI Express Linux driver
 
4
  Copyright(c) 1999 - 2012 Intel Corporation.
 
5
 
 
6
  This program is free software; you can redistribute it and/or modify it
 
7
  under the terms and conditions of the GNU General Public License,
 
8
  version 2, as published by the Free Software Foundation.
 
9
 
 
10
  This program is distributed in the hope it will be useful, but WITHOUT
 
11
  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 
12
  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 
13
  more details.
 
14
 
 
15
  You should have received a copy of the GNU General Public License along with
 
16
  this program; if not, write to the Free Software Foundation, Inc.,
 
17
  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
 
18
 
 
19
  The full GNU General Public License is included in this distribution in
 
20
  the file called "COPYING".
 
21
 
 
22
  Contact Information:
 
23
  e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
 
24
  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
 
25
 
 
26
*******************************************************************************/
 
27
 
 
28
#include "ixgbe.h"
 
29
#include "kcompat.h"
 
30
 
 
31
/*****************************************************************************/
 
32
#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,8) )
 
33
/* From lib/vsprintf.c */
 
34
#include <asm/div64.h>
 
35
 
 
36
static int skip_atoi(const char **s)
 
37
{
 
38
        int i=0;
 
39
 
 
40
        while (isdigit(**s))
 
41
                i = i*10 + *((*s)++) - '0';
 
42
        return i;
 
43
}
 
44
 
 
45
#define _kc_ZEROPAD     1               /* pad with zero */
 
46
#define _kc_SIGN        2               /* unsigned/signed long */
 
47
#define _kc_PLUS        4               /* show plus */
 
48
#define _kc_SPACE       8               /* space if plus */
 
49
#define _kc_LEFT        16              /* left justified */
 
50
#define _kc_SPECIAL     32              /* 0x */
 
51
#define _kc_LARGE       64              /* use 'ABCDEF' instead of 'abcdef' */
 
52
 
 
53
static char * number(char * buf, char * end, long long num, int base, int size, int precision, int type)
 
54
{
 
55
        char c,sign,tmp[66];
 
56
        const char *digits;
 
57
        const char small_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
 
58
        const char large_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
 
59
        int i;
 
60
 
 
61
        digits = (type & _kc_LARGE) ? large_digits : small_digits;
 
62
        if (type & _kc_LEFT)
 
63
                type &= ~_kc_ZEROPAD;
 
64
        if (base < 2 || base > 36)
 
65
                return 0;
 
66
        c = (type & _kc_ZEROPAD) ? '0' : ' ';
 
67
        sign = 0;
 
68
        if (type & _kc_SIGN) {
 
69
                if (num < 0) {
 
70
                        sign = '-';
 
71
                        num = -num;
 
72
                        size--;
 
73
                } else if (type & _kc_PLUS) {
 
74
                        sign = '+';
 
75
                        size--;
 
76
                } else if (type & _kc_SPACE) {
 
77
                        sign = ' ';
 
78
                        size--;
 
79
                }
 
80
        }
 
81
        if (type & _kc_SPECIAL) {
 
82
                if (base == 16)
 
83
                        size -= 2;
 
84
                else if (base == 8)
 
85
                        size--;
 
86
        }
 
87
        i = 0;
 
88
        if (num == 0)
 
89
                tmp[i++]='0';
 
90
        else while (num != 0)
 
91
                tmp[i++] = digits[do_div(num,base)];
 
92
        if (i > precision)
 
93
                precision = i;
 
94
        size -= precision;
 
95
        if (!(type&(_kc_ZEROPAD+_kc_LEFT))) {
 
96
                while(size-->0) {
 
97
                        if (buf <= end)
 
98
                                *buf = ' ';
 
99
                        ++buf;
 
100
                }
 
101
        }
 
102
        if (sign) {
 
103
                if (buf <= end)
 
104
                        *buf = sign;
 
105
                ++buf;
 
106
        }
 
107
        if (type & _kc_SPECIAL) {
 
108
                if (base==8) {
 
109
                        if (buf <= end)
 
110
                                *buf = '0';
 
111
                        ++buf;
 
112
                } else if (base==16) {
 
113
                        if (buf <= end)
 
114
                                *buf = '0';
 
115
                        ++buf;
 
116
                        if (buf <= end)
 
117
                                *buf = digits[33];
 
118
                        ++buf;
 
119
                }
 
120
        }
 
121
        if (!(type & _kc_LEFT)) {
 
122
                while (size-- > 0) {
 
123
                        if (buf <= end)
 
124
                                *buf = c;
 
125
                        ++buf;
 
126
                }
 
127
        }
 
128
        while (i < precision--) {
 
129
                if (buf <= end)
 
130
                        *buf = '0';
 
131
                ++buf;
 
132
        }
 
133
        while (i-- > 0) {
 
134
                if (buf <= end)
 
135
                        *buf = tmp[i];
 
136
                ++buf;
 
137
        }
 
138
        while (size-- > 0) {
 
139
                if (buf <= end)
 
140
                        *buf = ' ';
 
141
                ++buf;
 
142
        }
 
143
        return buf;
 
144
}
 
145
 
 
146
int _kc_vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
 
147
{
 
148
        int len;
 
149
        unsigned long long num;
 
150
        int i, base;
 
151
        char *str, *end, c;
 
152
        const char *s;
 
153
 
 
154
        int flags;              /* flags to number() */
 
155
 
 
156
        int field_width;        /* width of output field */
 
157
        int precision;          /* min. # of digits for integers; max
 
158
                                   number of chars for from string */
 
159
        int qualifier;          /* 'h', 'l', or 'L' for integer fields */
 
160
                                /* 'z' support added 23/7/1999 S.H.    */
 
161
                                /* 'z' changed to 'Z' --davidm 1/25/99 */
 
162
 
 
163
        str = buf;
 
164
        end = buf + size - 1;
 
165
 
 
166
        if (end < buf - 1) {
 
167
                end = ((void *) -1);
 
168
                size = end - buf + 1;
 
169
        }
 
170
 
 
171
        for (; *fmt ; ++fmt) {
 
172
                if (*fmt != '%') {
 
173
                        if (str <= end)
 
174
                                *str = *fmt;
 
175
                        ++str;
 
176
                        continue;
 
177
                }
 
178
 
 
179
                /* process flags */
 
180
                flags = 0;
 
181
                repeat:
 
182
                        ++fmt;          /* this also skips first '%' */
 
183
                        switch (*fmt) {
 
184
                                case '-': flags |= _kc_LEFT; goto repeat;
 
185
                                case '+': flags |= _kc_PLUS; goto repeat;
 
186
                                case ' ': flags |= _kc_SPACE; goto repeat;
 
187
                                case '#': flags |= _kc_SPECIAL; goto repeat;
 
188
                                case '0': flags |= _kc_ZEROPAD; goto repeat;
 
189
                        }
 
190
 
 
191
                /* get field width */
 
192
                field_width = -1;
 
193
                if (isdigit(*fmt))
 
194
                        field_width = skip_atoi(&fmt);
 
195
                else if (*fmt == '*') {
 
196
                        ++fmt;
 
197
                        /* it's the next argument */
 
198
                        field_width = va_arg(args, int);
 
199
                        if (field_width < 0) {
 
200
                                field_width = -field_width;
 
201
                                flags |= _kc_LEFT;
 
202
                        }
 
203
                }
 
204
 
 
205
                /* get the precision */
 
206
                precision = -1;
 
207
                if (*fmt == '.') {
 
208
                        ++fmt;  
 
209
                        if (isdigit(*fmt))
 
210
                                precision = skip_atoi(&fmt);
 
211
                        else if (*fmt == '*') {
 
212
                                ++fmt;
 
213
                                /* it's the next argument */
 
214
                                precision = va_arg(args, int);
 
215
                        }
 
216
                        if (precision < 0)
 
217
                                precision = 0;
 
218
                }
 
219
 
 
220
                /* get the conversion qualifier */
 
221
                qualifier = -1;
 
222
                if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt =='Z') {
 
223
                        qualifier = *fmt;
 
224
                        ++fmt;
 
225
                }
 
226
 
 
227
                /* default base */
 
228
                base = 10;
 
229
 
 
230
                switch (*fmt) {
 
231
                        case 'c':
 
232
                                if (!(flags & _kc_LEFT)) {
 
233
                                        while (--field_width > 0) {
 
234
                                                if (str <= end)
 
235
                                                        *str = ' ';
 
236
                                                ++str;
 
237
                                        }
 
238
                                }
 
239
                                c = (unsigned char) va_arg(args, int);
 
240
                                if (str <= end)
 
241
                                        *str = c;
 
242
                                ++str;
 
243
                                while (--field_width > 0) {
 
244
                                        if (str <= end)
 
245
                                                *str = ' ';
 
246
                                        ++str;
 
247
                                }
 
248
                                continue;
 
249
 
 
250
                        case 's':
 
251
                                s = va_arg(args, char *);
 
252
                                if (!s)
 
253
                                        s = "<NULL>";
 
254
 
 
255
                                len = strnlen(s, precision);
 
256
 
 
257
                                if (!(flags & _kc_LEFT)) {
 
258
                                        while (len < field_width--) {
 
259
                                                if (str <= end)
 
260
                                                        *str = ' ';
 
261
                                                ++str;
 
262
                                        }
 
263
                                }
 
264
                                for (i = 0; i < len; ++i) {
 
265
                                        if (str <= end)
 
266
                                                *str = *s;
 
267
                                        ++str; ++s;
 
268
                                }
 
269
                                while (len < field_width--) {
 
270
                                        if (str <= end)
 
271
                                                *str = ' ';
 
272
                                        ++str;
 
273
                                }
 
274
                                continue;
 
275
 
 
276
                        case 'p':
 
277
                                if (field_width == -1) {
 
278
                                        field_width = 2*sizeof(void *);
 
279
                                        flags |= _kc_ZEROPAD;
 
280
                                }
 
281
                                str = number(str, end,
 
282
                                                (unsigned long) va_arg(args, void *),
 
283
                                                16, field_width, precision, flags);
 
284
                                continue;
 
285
 
 
286
 
 
287
                        case 'n':
 
288
                                /* FIXME:
 
289
                                * What does C99 say about the overflow case here? */
 
290
                                if (qualifier == 'l') {
 
291
                                        long * ip = va_arg(args, long *);
 
292
                                        *ip = (str - buf);
 
293
                                } else if (qualifier == 'Z') {
 
294
                                        size_t * ip = va_arg(args, size_t *);
 
295
                                        *ip = (str - buf);
 
296
                                } else {
 
297
                                        int * ip = va_arg(args, int *);
 
298
                                        *ip = (str - buf);
 
299
                                }
 
300
                                continue;
 
301
 
 
302
                        case '%':
 
303
                                if (str <= end)
 
304
                                        *str = '%';
 
305
                                ++str;
 
306
                                continue;
 
307
 
 
308
                                /* integer number formats - set up the flags and "break" */
 
309
                        case 'o':
 
310
                                base = 8;
 
311
                                break;
 
312
 
 
313
                        case 'X':
 
314
                                flags |= _kc_LARGE;
 
315
                        case 'x':
 
316
                                base = 16;
 
317
                                break;
 
318
 
 
319
                        case 'd':
 
320
                        case 'i':
 
321
                                flags |= _kc_SIGN;
 
322
                        case 'u':
 
323
                                break;
 
324
 
 
325
                        default:
 
326
                                if (str <= end)
 
327
                                        *str = '%';
 
328
                                ++str;
 
329
                                if (*fmt) {
 
330
                                        if (str <= end)
 
331
                                                *str = *fmt;
 
332
                                        ++str;
 
333
                                } else {
 
334
                                        --fmt;
 
335
                                }
 
336
                                continue;
 
337
                }
 
338
                if (qualifier == 'L')
 
339
                        num = va_arg(args, long long);
 
340
                else if (qualifier == 'l') {
 
341
                        num = va_arg(args, unsigned long);
 
342
                        if (flags & _kc_SIGN)
 
343
                                num = (signed long) num;
 
344
                } else if (qualifier == 'Z') {
 
345
                        num = va_arg(args, size_t);
 
346
                } else if (qualifier == 'h') {
 
347
                        num = (unsigned short) va_arg(args, int);
 
348
                        if (flags & _kc_SIGN)
 
349
                                num = (signed short) num;
 
350
                } else {
 
351
                        num = va_arg(args, unsigned int);
 
352
                        if (flags & _kc_SIGN)
 
353
                                num = (signed int) num;
 
354
                }
 
355
                str = number(str, end, num, base,
 
356
                                field_width, precision, flags);
 
357
        }
 
358
        if (str <= end)
 
359
                *str = '\0';
 
360
        else if (size > 0)
 
361
                /* don't write out a null byte if the buf size is zero */
 
362
                *end = '\0';
 
363
        /* the trailing null byte doesn't count towards the total
 
364
        * ++str;
 
365
        */
 
366
        return str-buf;
 
367
}
 
368
 
 
369
int _kc_snprintf(char * buf, size_t size, const char *fmt, ...)
 
370
{
 
371
        va_list args;
 
372
        int i;
 
373
 
 
374
        va_start(args, fmt);
 
375
        i = _kc_vsnprintf(buf,size,fmt,args);
 
376
        va_end(args);
 
377
        return i;
 
378
}
 
379
#endif /* < 2.4.8 */
 
380
 
 
381
/*****************************************************************************/
 
382
#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,13) )
 
383
 
 
384
/**************************************/
 
385
/* PCI DMA MAPPING */
 
386
 
 
387
#if defined(CONFIG_HIGHMEM)
 
388
 
 
389
#ifndef PCI_DRAM_OFFSET
 
390
#define PCI_DRAM_OFFSET 0
 
391
#endif
 
392
 
 
393
u64
 
394
_kc_pci_map_page(struct pci_dev *dev, struct page *page, unsigned long offset,
 
395
                 size_t size, int direction)
 
396
{
 
397
        return (((u64) (page - mem_map) << PAGE_SHIFT) + offset +
 
398
                PCI_DRAM_OFFSET);
 
399
}
 
400
 
 
401
#else /* CONFIG_HIGHMEM */
 
402
 
 
403
u64
 
404
_kc_pci_map_page(struct pci_dev *dev, struct page *page, unsigned long offset,
 
405
                 size_t size, int direction)
 
406
{
 
407
        return pci_map_single(dev, (void *)page_address(page) + offset, size,
 
408
                              direction);
 
409
}
 
410
 
 
411
#endif /* CONFIG_HIGHMEM */
 
412
 
 
413
void
 
414
_kc_pci_unmap_page(struct pci_dev *dev, u64 dma_addr, size_t size,
 
415
                   int direction)
 
416
{
 
417
        return pci_unmap_single(dev, dma_addr, size, direction);
 
418
}
 
419
 
 
420
#endif /* 2.4.13 => 2.4.3 */
 
421
 
 
422
/*****************************************************************************/
 
423
#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,3) )
 
424
 
 
425
/**************************************/
 
426
/* PCI DRIVER API */
 
427
 
 
428
int
 
429
_kc_pci_set_dma_mask(struct pci_dev *dev, dma_addr_t mask)
 
430
{
 
431
        if (!pci_dma_supported(dev, mask))
 
432
                return -EIO;
 
433
        dev->dma_mask = mask;
 
434
        return 0;
 
435
}
 
436
 
 
437
int
 
438
_kc_pci_request_regions(struct pci_dev *dev, char *res_name)
 
439
{
 
440
        int i;
 
441
 
 
442
        for (i = 0; i < 6; i++) {
 
443
                if (pci_resource_len(dev, i) == 0)
 
444
                        continue;
 
445
 
 
446
                if (pci_resource_flags(dev, i) & IORESOURCE_IO) {
 
447
                        if (!request_region(pci_resource_start(dev, i), pci_resource_len(dev, i), res_name)) {
 
448
                                pci_release_regions(dev);
 
449
                                return -EBUSY;
 
450
                        }
 
451
                } else if (pci_resource_flags(dev, i) & IORESOURCE_MEM) {
 
452
                        if (!request_mem_region(pci_resource_start(dev, i), pci_resource_len(dev, i), res_name)) {
 
453
                                pci_release_regions(dev);
 
454
                                return -EBUSY;
 
455
                        }
 
456
                }
 
457
        }
 
458
        return 0;
 
459
}
 
460
 
 
461
void
 
462
_kc_pci_release_regions(struct pci_dev *dev)
 
463
{
 
464
        int i;
 
465
 
 
466
        for (i = 0; i < 6; i++) {
 
467
                if (pci_resource_len(dev, i) == 0)
 
468
                        continue;
 
469
 
 
470
                if (pci_resource_flags(dev, i) & IORESOURCE_IO)
 
471
                        release_region(pci_resource_start(dev, i), pci_resource_len(dev, i));
 
472
 
 
473
                else if (pci_resource_flags(dev, i) & IORESOURCE_MEM)
 
474
                        release_mem_region(pci_resource_start(dev, i), pci_resource_len(dev, i));
 
475
        }
 
476
}
 
477
 
 
478
/**************************************/
 
479
/* NETWORK DRIVER API */
 
480
 
 
481
struct net_device *
 
482
_kc_alloc_etherdev(int sizeof_priv)
 
483
{
 
484
        struct net_device *dev;
 
485
        int alloc_size;
 
486
 
 
487
        alloc_size = sizeof(*dev) + sizeof_priv + IFNAMSIZ + 31;
 
488
        dev = kzalloc(alloc_size, GFP_KERNEL);
 
489
        if (!dev)
 
490
                return NULL;
 
491
 
 
492
        if (sizeof_priv)
 
493
                dev->priv = (void *) (((unsigned long)(dev + 1) + 31) & ~31);
 
494
        dev->name[0] = '\0';
 
495
        ether_setup(dev);
 
496
 
 
497
        return dev;
 
498
}
 
499
 
 
500
int
 
501
_kc_is_valid_ether_addr(u8 *addr)
 
502
{
 
503
        const char zaddr[6] = { 0, };
 
504
 
 
505
        return !(addr[0] & 1) && memcmp(addr, zaddr, 6);
 
506
}
 
507
 
 
508
#endif /* 2.4.3 => 2.4.0 */
 
509
 
 
510
/*****************************************************************************/
 
511
#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,6) )
 
512
 
 
513
int
 
514
_kc_pci_set_power_state(struct pci_dev *dev, int state)
 
515
{
 
516
        return 0;
 
517
}
 
518
 
 
519
int
 
520
_kc_pci_enable_wake(struct pci_dev *pdev, u32 state, int enable)
 
521
{
 
522
        return 0;
 
523
}
 
524
 
 
525
#endif /* 2.4.6 => 2.4.3 */
 
526
 
 
527
/*****************************************************************************/
 
528
#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) )
 
529
void _kc_skb_fill_page_desc(struct sk_buff *skb, int i, struct page *page,
 
530
                            int off, int size)
 
531
{
 
532
        skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
 
533
        frag->page = page;
 
534
        frag->page_offset = off;
 
535
        frag->size = size;
 
536
        skb_shinfo(skb)->nr_frags = i + 1;
 
537
}
 
538
 
 
539
/*
 
540
 * Original Copyright:
 
541
 * find_next_bit.c: fallback find next bit implementation
 
542
 *
 
543
 * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
 
544
 * Written by David Howells (dhowells@redhat.com)
 
545
 */
 
546
 
 
547
/**
 
548
 * find_next_bit - find the next set bit in a memory region
 
549
 * @addr: The address to base the search on
 
550
 * @offset: The bitnumber to start searching at
 
551
 * @size: The maximum size to search
 
552
 */
 
553
unsigned long find_next_bit(const unsigned long *addr, unsigned long size,
 
554
                            unsigned long offset)
 
555
{
 
556
        const unsigned long *p = addr + BITOP_WORD(offset);
 
557
        unsigned long result = offset & ~(BITS_PER_LONG-1);
 
558
        unsigned long tmp;
 
559
 
 
560
        if (offset >= size)
 
561
                return size;
 
562
        size -= result;
 
563
        offset %= BITS_PER_LONG;
 
564
        if (offset) {
 
565
                tmp = *(p++);
 
566
                tmp &= (~0UL << offset);
 
567
                if (size < BITS_PER_LONG)
 
568
                        goto found_first;
 
569
                if (tmp)
 
570
                        goto found_middle;
 
571
                size -= BITS_PER_LONG;
 
572
                result += BITS_PER_LONG;
 
573
        }
 
574
        while (size & ~(BITS_PER_LONG-1)) {
 
575
                if ((tmp = *(p++)))
 
576
                        goto found_middle;
 
577
                result += BITS_PER_LONG;
 
578
                size -= BITS_PER_LONG;
 
579
        }
 
580
        if (!size)
 
581
                return result;
 
582
        tmp = *p;
 
583
 
 
584
found_first:
 
585
        tmp &= (~0UL >> (BITS_PER_LONG - size));
 
586
        if (tmp == 0UL)         /* Are any bits set? */
 
587
                return result + size;   /* Nope. */
 
588
found_middle:
 
589
        return result + ffs(tmp);
 
590
}
 
591
 
 
592
size_t _kc_strlcpy(char *dest, const char *src, size_t size)
 
593
{
 
594
        size_t ret = strlen(src);
 
595
 
 
596
        if (size) {
 
597
                size_t len = (ret >= size) ? size - 1 : ret;
 
598
                memcpy(dest, src, len);
 
599
                dest[len] = '\0';
 
600
        }
 
601
        return ret;
 
602
}
 
603
 
 
604
#endif /* 2.6.0 => 2.4.6 */
 
605
 
 
606
/*****************************************************************************/
 
607
#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,4) )
 
608
int _kc_scnprintf(char * buf, size_t size, const char *fmt, ...)
 
609
{
 
610
        va_list args;
 
611
        int i;
 
612
 
 
613
        va_start(args, fmt);
 
614
        i = vsnprintf(buf, size, fmt, args);
 
615
        va_end(args);
 
616
        return (i >= size) ? (size - 1) : i;
 
617
}
 
618
#endif /* < 2.6.4 */
 
619
 
 
620
/*****************************************************************************/
 
621
#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) )
 
622
DECLARE_BITMAP(_kcompat_node_online_map, MAX_NUMNODES) = {1};
 
623
#endif /* < 2.6.10 */
 
624
 
 
625
/*****************************************************************************/
 
626
#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13) )
 
627
char *_kc_kstrdup(const char *s, unsigned int gfp)
 
628
{
 
629
        size_t len;
 
630
        char *buf;
 
631
 
 
632
        if (!s)
 
633
                return NULL;
 
634
 
 
635
        len = strlen(s) + 1;
 
636
        buf = kmalloc(len, gfp);
 
637
        if (buf)
 
638
                memcpy(buf, s, len);
 
639
        return buf;
 
640
}
 
641
#endif /* < 2.6.13 */
 
642
 
 
643
/*****************************************************************************/
 
644
#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14) )
 
645
void *_kc_kzalloc(size_t size, int flags)
 
646
{
 
647
        void *ret = kmalloc(size, flags);
 
648
        if (ret)
 
649
                memset(ret, 0, size);
 
650
        return ret;
 
651
}
 
652
#endif /* <= 2.6.13 */
 
653
 
 
654
/*****************************************************************************/
 
655
#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) )
 
656
int _kc_skb_pad(struct sk_buff *skb, int pad)
 
657
{
 
658
        int ntail;
 
659
        
 
660
        /* If the skbuff is non linear tailroom is always zero.. */
 
661
        if(!skb_cloned(skb) && skb_tailroom(skb) >= pad) {
 
662
                memset(skb->data+skb->len, 0, pad);
 
663
                return 0;
 
664
        }
 
665
        
 
666
        ntail = skb->data_len + pad - (skb->end - skb->tail);
 
667
        if (likely(skb_cloned(skb) || ntail > 0)) {
 
668
                if (pskb_expand_head(skb, 0, ntail, GFP_ATOMIC));
 
669
                        goto free_skb;
 
670
        }
 
671
 
 
672
#ifdef MAX_SKB_FRAGS
 
673
        if (skb_is_nonlinear(skb) &&
 
674
            !__pskb_pull_tail(skb, skb->data_len))
 
675
                goto free_skb;
 
676
 
 
677
#endif
 
678
        memset(skb->data + skb->len, 0, pad);
 
679
        return 0;
 
680
 
 
681
free_skb:
 
682
        kfree_skb(skb);
 
683
        return -ENOMEM;
 
684
 
685
 
 
686
#if (!(RHEL_RELEASE_CODE && RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(5,4)))
 
687
int _kc_pci_save_state(struct pci_dev *pdev)
 
688
{
 
689
        struct adapter_struct *adapter = pci_get_drvdata(pdev);
 
690
        int size = PCI_CONFIG_SPACE_LEN, i;
 
691
        u16 pcie_cap_offset, pcie_link_status;
 
692
 
 
693
#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) )
 
694
        /* no ->dev for 2.4 kernels */
 
695
        WARN_ON(pdev->dev.driver_data == NULL);
 
696
#endif
 
697
        pcie_cap_offset = pci_find_capability(pdev, PCI_CAP_ID_EXP);
 
698
        if (pcie_cap_offset) {
 
699
                if (!pci_read_config_word(pdev,
 
700
                                          pcie_cap_offset + PCIE_LINK_STATUS,
 
701
                                          &pcie_link_status))
 
702
                size = PCIE_CONFIG_SPACE_LEN;
 
703
        }
 
704
        pci_config_space_ich8lan();
 
705
#ifdef HAVE_PCI_ERS
 
706
        if (adapter->config_space == NULL)
 
707
#else
 
708
        WARN_ON(adapter->config_space != NULL);
 
709
#endif
 
710
                adapter->config_space = kmalloc(size, GFP_KERNEL);
 
711
        if (!adapter->config_space) {
 
712
                printk(KERN_ERR "Out of memory in pci_save_state\n");
 
713
                return -ENOMEM;
 
714
        }
 
715
        for (i = 0; i < (size / 4); i++)
 
716
                pci_read_config_dword(pdev, i * 4, &adapter->config_space[i]);
 
717
        return 0;
 
718
}
 
719
 
 
720
void _kc_pci_restore_state(struct pci_dev *pdev)
 
721
{
 
722
        struct adapter_struct *adapter = pci_get_drvdata(pdev);
 
723
        int size = PCI_CONFIG_SPACE_LEN, i;
 
724
        u16 pcie_cap_offset;
 
725
        u16 pcie_link_status;
 
726
 
 
727
        if (adapter->config_space != NULL) {
 
728
                pcie_cap_offset = pci_find_capability(pdev, PCI_CAP_ID_EXP);
 
729
                if (pcie_cap_offset &&
 
730
                    !pci_read_config_word(pdev,
 
731
                                          pcie_cap_offset + PCIE_LINK_STATUS,
 
732
                                          &pcie_link_status))
 
733
                        size = PCIE_CONFIG_SPACE_LEN;
 
734
 
 
735
                pci_config_space_ich8lan();
 
736
                for (i = 0; i < (size / 4); i++)
 
737
                pci_write_config_dword(pdev, i * 4, adapter->config_space[i]);
 
738
#ifndef HAVE_PCI_ERS
 
739
                kfree(adapter->config_space);
 
740
                adapter->config_space = NULL;
 
741
#endif
 
742
        }
 
743
}
 
744
#endif /* !(RHEL_RELEASE_CODE >= RHEL 5.4) */
 
745
 
 
746
#ifdef HAVE_PCI_ERS
 
747
void _kc_free_netdev(struct net_device *netdev)
 
748
{
 
749
        struct adapter_struct *adapter = netdev_priv(netdev);
 
750
 
 
751
        if (adapter->config_space != NULL)
 
752
                kfree(adapter->config_space);
 
753
#ifdef CONFIG_SYSFS
 
754
        if (netdev->reg_state == NETREG_UNINITIALIZED) {
 
755
                kfree((char *)netdev - netdev->padded);
 
756
        } else {
 
757
                BUG_ON(netdev->reg_state != NETREG_UNREGISTERED);
 
758
                netdev->reg_state = NETREG_RELEASED;
 
759
                class_device_put(&netdev->class_dev);
 
760
        }
 
761
#else
 
762
        kfree((char *)netdev - netdev->padded);
 
763
#endif
 
764
}
 
765
#endif
 
766
 
 
767
void *_kc_kmemdup(const void *src, size_t len, unsigned gfp)
 
768
{
 
769
        void *p;
 
770
 
 
771
        p = kzalloc(len, gfp);
 
772
        if (p)
 
773
                memcpy(p, src, len);
 
774
        return p;
 
775
}
 
776
#endif /* <= 2.6.19 */
 
777
 
 
778
/*****************************************************************************/
 
779
#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) )
 
780
/* hexdump code taken from lib/hexdump.c */
 
781
static void _kc_hex_dump_to_buffer(const void *buf, size_t len, int rowsize,
 
782
                        int groupsize, unsigned char *linebuf,
 
783
                        size_t linebuflen, bool ascii)
 
784
{
 
785
        const u8 *ptr = buf;
 
786
        u8 ch;
 
787
        int j, lx = 0;
 
788
        int ascii_column;
 
789
 
 
790
        if (rowsize != 16 && rowsize != 32)
 
791
                rowsize = 16;
 
792
 
 
793
        if (!len)
 
794
                goto nil;
 
795
        if (len > rowsize)              /* limit to one line at a time */
 
796
                len = rowsize;
 
797
        if ((len % groupsize) != 0)     /* no mixed size output */
 
798
                groupsize = 1;
 
799
 
 
800
        switch (groupsize) {
 
801
        case 8: {
 
802
                const u64 *ptr8 = buf;
 
803
                int ngroups = len / groupsize;
 
804
 
 
805
                for (j = 0; j < ngroups; j++)
 
806
                        lx += scnprintf((char *)(linebuf + lx), linebuflen - lx,
 
807
                                "%s%16.16llx", j ? " " : "",
 
808
                                (unsigned long long)*(ptr8 + j));
 
809
                ascii_column = 17 * ngroups + 2;
 
810
                break;
 
811
        }
 
812
 
 
813
        case 4: {
 
814
                const u32 *ptr4 = buf;
 
815
                int ngroups = len / groupsize;
 
816
 
 
817
                for (j = 0; j < ngroups; j++)
 
818
                        lx += scnprintf((char *)(linebuf + lx), linebuflen - lx,
 
819
                                "%s%8.8x", j ? " " : "", *(ptr4 + j));
 
820
                ascii_column = 9 * ngroups + 2;
 
821
                break;
 
822
        }
 
823
 
 
824
        case 2: {
 
825
                const u16 *ptr2 = buf;
 
826
                int ngroups = len / groupsize;
 
827
 
 
828
                for (j = 0; j < ngroups; j++)
 
829
                        lx += scnprintf((char *)(linebuf + lx), linebuflen - lx,
 
830
                                "%s%4.4x", j ? " " : "", *(ptr2 + j));
 
831
                ascii_column = 5 * ngroups + 2;
 
832
                break;
 
833
        }
 
834
 
 
835
        default:
 
836
                for (j = 0; (j < len) && (lx + 3) <= linebuflen; j++) {
 
837
                        ch = ptr[j];
 
838
                        linebuf[lx++] = hex_asc(ch >> 4);
 
839
                        linebuf[lx++] = hex_asc(ch & 0x0f);
 
840
                        linebuf[lx++] = ' ';
 
841
                }
 
842
                if (j)
 
843
                        lx--;
 
844
 
 
845
                ascii_column = 3 * rowsize + 2;
 
846
                break;
 
847
        }
 
848
        if (!ascii)
 
849
                goto nil;
 
850
 
 
851
        while (lx < (linebuflen - 1) && lx < (ascii_column - 1))
 
852
                linebuf[lx++] = ' ';
 
853
        for (j = 0; (j < len) && (lx + 2) < linebuflen; j++)
 
854
                linebuf[lx++] = (isascii(ptr[j]) && isprint(ptr[j])) ? ptr[j]
 
855
                                : '.';
 
856
nil:
 
857
        linebuf[lx++] = '\0';
 
858
}
 
859
 
 
860
void _kc_print_hex_dump(const char *level,
 
861
                        const char *prefix_str, int prefix_type,
 
862
                        int rowsize, int groupsize,
 
863
                        const void *buf, size_t len, bool ascii)
 
864
{
 
865
        const u8 *ptr = buf;
 
866
        int i, linelen, remaining = len;
 
867
        unsigned char linebuf[200];
 
868
 
 
869
        if (rowsize != 16 && rowsize != 32)
 
870
                rowsize = 16;
 
871
 
 
872
        for (i = 0; i < len; i += rowsize) {
 
873
                linelen = min(remaining, rowsize);
 
874
                remaining -= rowsize;
 
875
                _kc_hex_dump_to_buffer(ptr + i, linelen, rowsize, groupsize,
 
876
                                linebuf, sizeof(linebuf), ascii);
 
877
 
 
878
                switch (prefix_type) {
 
879
                case DUMP_PREFIX_ADDRESS:
 
880
                        printk("%s%s%*p: %s\n", level, prefix_str,
 
881
                                (int)(2 * sizeof(void *)), ptr + i, linebuf);
 
882
                        break;
 
883
                case DUMP_PREFIX_OFFSET:
 
884
                        printk("%s%s%.8x: %s\n", level, prefix_str, i, linebuf);
 
885
                        break;
 
886
                default:
 
887
                        printk("%s%s%s\n", level, prefix_str, linebuf);
 
888
                        break;
 
889
                }
 
890
        }
 
891
}
 
892
#endif /* < 2.6.22 */
 
893
 
 
894
/*****************************************************************************/
 
895
#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23) )
 
896
int ixgbe_dcb_netlink_register(void)
 
897
{
 
898
        return 0;
 
899
}
 
900
 
 
901
int ixgbe_dcb_netlink_unregister(void)
 
902
{
 
903
        return 0;
 
904
}
 
905
 
 
906
int ixgbe_copy_dcb_cfg(struct ixgbe_dcb_config *src_dcb_cfg,
 
907
                       struct ixgbe_dcb_config *dst_dcb_cfg, int tc_max)
 
908
{
 
909
        return 0;
 
910
}
 
911
#endif /* < 2.6.23 */
 
912
 
 
913
/*****************************************************************************/
 
914
#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) )
 
915
#ifdef NAPI
 
916
struct net_device *napi_to_poll_dev(struct napi_struct *napi)
 
917
{
 
918
        struct adapter_q_vector *q_vector = container_of(napi,
 
919
                                                        struct adapter_q_vector,
 
920
                                                        napi);
 
921
        return &q_vector->poll_dev;
 
922
}
 
923
 
 
924
int __kc_adapter_clean(struct net_device *netdev, int *budget)
 
925
{
 
926
        int work_done;
 
927
        int work_to_do = min(*budget, netdev->quota);
 
928
        /* kcompat.h netif_napi_add puts napi struct in "fake netdev->priv" */
 
929
        struct napi_struct *napi = netdev->priv;
 
930
        work_done = napi->poll(napi, work_to_do);
 
931
        *budget -= work_done;
 
932
        netdev->quota -= work_done;
 
933
        return (work_done >= work_to_do) ? 1 : 0;
 
934
}
 
935
#endif /* NAPI */
 
936
#endif /* <= 2.6.24 */
 
937
 
 
938
/*****************************************************************************/
 
939
#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26) )
 
940
void _kc_pci_disable_link_state(struct pci_dev *pdev, int state)
 
941
{
 
942
        struct pci_dev *parent = pdev->bus->self;
 
943
        u16 link_state;
 
944
        int pos;
 
945
 
 
946
        if (!parent)
 
947
                return;
 
948
 
 
949
        pos = pci_find_capability(parent, PCI_CAP_ID_EXP);
 
950
        if (pos) {
 
951
                pci_read_config_word(parent, pos + PCI_EXP_LNKCTL, &link_state);
 
952
                link_state &= ~state;
 
953
                pci_write_config_word(parent, pos + PCI_EXP_LNKCTL, link_state);
 
954
        }
 
955
}
 
956
#endif /* < 2.6.26 */
 
957
 
 
958
/*****************************************************************************/
 
959
#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) )
 
960
#ifdef HAVE_TX_MQ
 
961
void _kc_netif_tx_stop_all_queues(struct net_device *netdev)
 
962
{
 
963
        struct adapter_struct *adapter = netdev_priv(netdev);
 
964
        int i;
 
965
 
 
966
        netif_stop_queue(netdev);
 
967
        if (netif_is_multiqueue(netdev))
 
968
                for (i = 0; i < adapter->num_tx_queues; i++)
 
969
                        netif_stop_subqueue(netdev, i);
 
970
}
 
971
void _kc_netif_tx_wake_all_queues(struct net_device *netdev)
 
972
{
 
973
        struct adapter_struct *adapter = netdev_priv(netdev);
 
974
        int i;
 
975
 
 
976
        netif_wake_queue(netdev);
 
977
        if (netif_is_multiqueue(netdev))
 
978
                for (i = 0; i < adapter->num_tx_queues; i++)
 
979
                        netif_wake_subqueue(netdev, i);
 
980
}
 
981
void _kc_netif_tx_start_all_queues(struct net_device *netdev)
 
982
{
 
983
        struct adapter_struct *adapter = netdev_priv(netdev);
 
984
        int i;
 
985
 
 
986
        netif_start_queue(netdev);
 
987
        if (netif_is_multiqueue(netdev))
 
988
                for (i = 0; i < adapter->num_tx_queues; i++)
 
989
                        netif_start_subqueue(netdev, i);
 
990
}
 
991
#endif /* HAVE_TX_MQ */
 
992
 
 
993
#ifndef __WARN_printf
 
994
void __kc_warn_slowpath(const char *file, int line, const char *fmt, ...)
 
995
{
 
996
        va_list args;
 
997
 
 
998
        printk(KERN_WARNING "------------[ cut here ]------------\n");
 
999
        printk(KERN_WARNING "WARNING: at %s:%d %s()\n", file, line);
 
1000
        va_start(args, fmt);
 
1001
        vprintk(fmt, args);
 
1002
        va_end(args);
 
1003
 
 
1004
        dump_stack();
 
1005
}
 
1006
#endif /* __WARN_printf */
 
1007
#endif /* < 2.6.27 */
 
1008
 
 
1009
/*****************************************************************************/
 
1010
#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) )
 
1011
 
 
1012
int
 
1013
_kc_pci_prepare_to_sleep(struct pci_dev *dev)
 
1014
{
 
1015
        pci_power_t target_state;
 
1016
        int error;
 
1017
 
 
1018
        target_state = pci_choose_state(dev, PMSG_SUSPEND);
 
1019
 
 
1020
        pci_enable_wake(dev, target_state, true);
 
1021
 
 
1022
        error = pci_set_power_state(dev, target_state);
 
1023
 
 
1024
        if (error)
 
1025
                pci_enable_wake(dev, target_state, false);
 
1026
 
 
1027
        return error;
 
1028
}
 
1029
 
 
1030
int
 
1031
_kc_pci_wake_from_d3(struct pci_dev *dev, bool enable)
 
1032
{
 
1033
        int err;
 
1034
 
 
1035
        err = pci_enable_wake(dev, PCI_D3cold, enable);
 
1036
        if (err)
 
1037
                goto out;
 
1038
 
 
1039
        err = pci_enable_wake(dev, PCI_D3hot, enable);
 
1040
 
 
1041
out:
 
1042
        return err;
 
1043
}
 
1044
 
 
1045
void _kc_skb_add_rx_frag(struct sk_buff *skb, int i, struct page *page,
 
1046
                         int off, int size)
 
1047
{
 
1048
        skb_fill_page_desc(skb, i, page, off, size);
 
1049
        skb->len += size;
 
1050
        skb->data_len += size;
 
1051
        skb->truesize += size;
 
1052
}
 
1053
#endif /* < 2.6.28 */
 
1054
 
 
1055
/*****************************************************************************/
 
1056
#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) )
 
1057
#ifdef HAVE_NETDEV_SELECT_QUEUE
 
1058
#include <net/ip.h>
 
1059
static u32 _kc_simple_tx_hashrnd;
 
1060
static u32 _kc_simple_tx_hashrnd_initialized;
 
1061
 
 
1062
u16 _kc_skb_tx_hash(struct net_device *dev, struct sk_buff *skb)
 
1063
{
 
1064
        u32 addr1, addr2, ports;
 
1065
        u32 hash, ihl;
 
1066
        u8 ip_proto = 0;
 
1067
 
 
1068
        if (unlikely(!_kc_simple_tx_hashrnd_initialized)) {
 
1069
                get_random_bytes(&_kc_simple_tx_hashrnd, 4);
 
1070
                _kc_simple_tx_hashrnd_initialized = 1;
 
1071
        }
 
1072
 
 
1073
        switch (skb->protocol) {
 
1074
        case htons(ETH_P_IP):
 
1075
                if (!(ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)))
 
1076
                        ip_proto = ip_hdr(skb)->protocol;
 
1077
                addr1 = ip_hdr(skb)->saddr;
 
1078
                addr2 = ip_hdr(skb)->daddr;
 
1079
                ihl = ip_hdr(skb)->ihl;
 
1080
                break;
 
1081
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 
1082
        case htons(ETH_P_IPV6):
 
1083
                ip_proto = ipv6_hdr(skb)->nexthdr;
 
1084
                addr1 = ipv6_hdr(skb)->saddr.s6_addr32[3];
 
1085
                addr2 = ipv6_hdr(skb)->daddr.s6_addr32[3];
 
1086
                ihl = (40 >> 2);
 
1087
                break;
 
1088
#endif
 
1089
        default:
 
1090
                return 0;
 
1091
        }
 
1092
 
 
1093
 
 
1094
        switch (ip_proto) {
 
1095
        case IPPROTO_TCP:
 
1096
        case IPPROTO_UDP:
 
1097
        case IPPROTO_DCCP:
 
1098
        case IPPROTO_ESP:
 
1099
        case IPPROTO_AH:
 
1100
        case IPPROTO_SCTP:
 
1101
        case IPPROTO_UDPLITE:
 
1102
                ports = *((u32 *) (skb_network_header(skb) + (ihl * 4)));
 
1103
                break;
 
1104
 
 
1105
        default:
 
1106
                ports = 0;
 
1107
                break;
 
1108
        }
 
1109
 
 
1110
        hash = jhash_3words(addr1, addr2, ports, _kc_simple_tx_hashrnd);
 
1111
 
 
1112
        return (u16) (((u64) hash * dev->real_num_tx_queues) >> 32);
 
1113
}
 
1114
#endif /* HAVE_NETDEV_SELECT_QUEUE */
 
1115
#endif /* < 2.6.30 */
 
1116
 
 
1117
#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) )
 
1118
#ifdef HAVE_TX_MQ
 
1119
#ifndef CONFIG_NETDEVICES_MULTIQUEUE
 
1120
void _kc_netif_set_real_num_tx_queues(struct net_device *dev, unsigned int txq)
 
1121
{
 
1122
        unsigned int real_num = dev->real_num_tx_queues;
 
1123
        struct Qdisc *qdisc;
 
1124
        int i;
 
1125
 
 
1126
        if (unlikely(txq > dev->num_tx_queues))
 
1127
                ;
 
1128
        else if (txq > real_num)
 
1129
                dev->real_num_tx_queues = txq;
 
1130
        else if ( txq < real_num) {
 
1131
                dev->real_num_tx_queues = txq;
 
1132
                for (i = txq; i < dev->num_tx_queues; i++) {
 
1133
                        qdisc = netdev_get_tx_queue(dev, i)->qdisc;
 
1134
                        if (qdisc) {
 
1135
                                spin_lock_bh(qdisc_lock(qdisc));        
 
1136
                                qdisc_reset(qdisc);
 
1137
                                spin_unlock_bh(qdisc_lock(qdisc));
 
1138
                        }
 
1139
                }
 
1140
        }
 
1141
}
 
1142
#endif /* CONFIG_NETDEVICES_MULTIQUEUE */
 
1143
#endif /* HAVE_TX_MQ */
 
1144
#endif /* < 2.6.35 */
 
1145
 
 
1146
/*****************************************************************************/
 
1147
#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) )
 
1148
static const u32 _kc_flags_dup_features =
 
1149
        (ETH_FLAG_LRO | ETH_FLAG_NTUPLE | ETH_FLAG_RXHASH);
 
1150
 
 
1151
u32 _kc_ethtool_op_get_flags(struct net_device *dev)
 
1152
{
 
1153
        return dev->features & _kc_flags_dup_features;
 
1154
}
 
1155
 
 
1156
int _kc_ethtool_op_set_flags(struct net_device *dev, u32 data, u32 supported)
 
1157
{
 
1158
        if (data & ~supported)
 
1159
                return -EINVAL;
 
1160
 
 
1161
        dev->features = ((dev->features & ~_kc_flags_dup_features) |
 
1162
                         (data & _kc_flags_dup_features));
 
1163
        return 0;
 
1164
}
 
1165
#endif /* < 2.6.36 */
 
1166
 
 
1167
/******************************************************************************/
 
1168
#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39) )
 
1169
#if (!(RHEL_RELEASE_CODE && RHEL_RELEASE_CODE > RHEL_RELEASE_VERSION(6,0)))
 
1170
u8 _kc_netdev_get_num_tc(struct net_device *dev)
 
1171
{
 
1172
        struct adapter_struct *kc_adapter = netdev_priv(dev);
 
1173
        if (kc_adapter->flags & IXGBE_FLAG_DCB_ENABLED)
 
1174
                return kc_adapter->tc;
 
1175
        else
 
1176
                return 0;
 
1177
}
 
1178
 
 
1179
u8 _kc_netdev_get_prio_tc_map(struct net_device *dev, u8 up)
 
1180
{
 
1181
        struct adapter_struct *kc_adapter = netdev_priv(dev);
 
1182
        int tc;
 
1183
        u8 map;
 
1184
 
 
1185
        for (tc = 0; tc < IXGBE_DCB_MAX_TRAFFIC_CLASS; tc++) {
 
1186
                map = kc_adapter->dcb_cfg.tc_config[tc].path[0].up_to_tc_bitmap;
 
1187
 
 
1188
                if (map & (1 << up))
 
1189
                        return tc;      
 
1190
        }
 
1191
 
 
1192
        return 0;
 
1193
}
 
1194
#endif /* !(RHEL_RELEASE_CODE > RHEL_RELEASE_VERSION(6,0)) */
 
1195
#endif /* < 2.6.39 */