mac80211: minstrel_ht: fix a crash in rate sorting
[cascardo/linux.git] / drivers / pci / hotplug / cpqphp_nvram.c
1 /*
2  * Compaq Hot Plug Controller Driver
3  *
4  * Copyright (C) 1995,2001 Compaq Computer Corporation
5  * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
6  * Copyright (C) 2001 IBM Corp.
7  *
8  * All rights reserved.
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or (at
13  * your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful, but
16  * WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
18  * NON INFRINGEMENT.  See the GNU General Public License for more
19  * details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24  *
25  * Send feedback to <greg@kroah.com>
26  *
27  */
28
29 #include <linux/module.h>
30 #include <linux/kernel.h>
31 #include <linux/types.h>
32 #include <linux/proc_fs.h>
33 #include <linux/slab.h>
34 #include <linux/workqueue.h>
35 #include <linux/pci.h>
36 #include <linux/pci_hotplug.h>
37 #include <asm/uaccess.h>
38 #include "cpqphp.h"
39 #include "cpqphp_nvram.h"
40
41
42 #define ROM_INT15_PHY_ADDR              0x0FF859
43 #define READ_EV                         0xD8A4
44 #define WRITE_EV                        0xD8A5
45
46 struct register_foo {
47         union {
48                 unsigned long lword;            /* eax */
49                 unsigned short word;            /* ax */
50
51                 struct {
52                         unsigned char low;      /* al */
53                         unsigned char high;     /* ah */
54                 } byte;
55         } data;
56
57         unsigned char opcode;   /* see below */
58         unsigned long length;   /* if the reg. is a pointer, how much data */
59 } __attribute__ ((packed));
60
61 struct all_reg {
62         struct register_foo eax_reg;
63         struct register_foo ebx_reg;
64         struct register_foo ecx_reg;
65         struct register_foo edx_reg;
66         struct register_foo edi_reg;
67         struct register_foo esi_reg;
68         struct register_foo eflags_reg;
69 } __attribute__ ((packed));
70
71
72 struct ev_hrt_header {
73         u8 Version;
74         u8 num_of_ctrl;
75         u8 next;
76 };
77
78 struct ev_hrt_ctrl {
79         u8 bus;
80         u8 device;
81         u8 function;
82         u8 mem_avail;
83         u8 p_mem_avail;
84         u8 io_avail;
85         u8 bus_avail;
86         u8 next;
87 };
88
89
90 static u8 evbuffer_init;
91 static u8 evbuffer_length;
92 static u8 evbuffer[1024];
93
94 static void __iomem *compaq_int15_entry_point;
95
96 /* lock for ordering int15_bios_call() */
97 static spinlock_t int15_lock;
98
99
100 /* This is a series of function that deals with
101  * setting & getting the hotplug resource table in some environment variable.
102  */
103
104 /*
105  * We really shouldn't be doing this unless there is a _very_ good reason to!!!
106  * greg k-h
107  */
108
109
110 static u32 add_byte(u32 **p_buffer, u8 value, u32 *used, u32 *avail)
111 {
112         u8 **tByte;
113
114         if ((*used + 1) > *avail)
115                 return(1);
116
117         *((u8*)*p_buffer) = value;
118         tByte = (u8**)p_buffer;
119         (*tByte)++;
120         *used+=1;
121         return(0);
122 }
123
124
125 static u32 add_dword(u32 **p_buffer, u32 value, u32 *used, u32 *avail)
126 {
127         if ((*used + 4) > *avail)
128                 return(1);
129
130         **p_buffer = value;
131         (*p_buffer)++;
132         *used+=4;
133         return(0);
134 }
135
136
137 /*
138  * check_for_compaq_ROM
139  *
140  * this routine verifies that the ROM OEM string is 'COMPAQ'
141  *
142  * returns 0 for non-Compaq ROM, 1 for Compaq ROM
143  */
144 static int check_for_compaq_ROM (void __iomem *rom_start)
145 {
146         u8 temp1, temp2, temp3, temp4, temp5, temp6;
147         int result = 0;
148
149         temp1 = readb(rom_start + 0xffea + 0);
150         temp2 = readb(rom_start + 0xffea + 1);
151         temp3 = readb(rom_start + 0xffea + 2);
152         temp4 = readb(rom_start + 0xffea + 3);
153         temp5 = readb(rom_start + 0xffea + 4);
154         temp6 = readb(rom_start + 0xffea + 5);
155         if ((temp1 == 'C') &&
156             (temp2 == 'O') &&
157             (temp3 == 'M') &&
158             (temp4 == 'P') &&
159             (temp5 == 'A') &&
160             (temp6 == 'Q')) {
161                 result = 1;
162         }
163         dbg ("%s - returned %d\n", __func__, result);
164         return result;
165 }
166
167
168 static u32 access_EV (u16 operation, u8 *ev_name, u8 *buffer, u32 *buf_size)
169 {
170         unsigned long flags;
171         int op = operation;
172         int ret_val;
173
174         if (!compaq_int15_entry_point)
175                 return -ENODEV;
176
177         spin_lock_irqsave(&int15_lock, flags);
178         __asm__ (
179                 "xorl   %%ebx,%%ebx\n" \
180                 "xorl    %%edx,%%edx\n" \
181                 "pushf\n" \
182                 "push %%cs\n" \
183                 "cli\n" \
184                 "call *%6\n"
185                 : "=c" (*buf_size), "=a" (ret_val)
186                 : "a" (op), "c" (*buf_size), "S" (ev_name),
187                 "D" (buffer), "m" (compaq_int15_entry_point)
188                 : "%ebx", "%edx");
189         spin_unlock_irqrestore(&int15_lock, flags);
190
191         return((ret_val & 0xFF00) >> 8);
192 }
193
194
195 /*
196  * load_HRT
197  *
198  * Read the hot plug Resource Table from NVRAM
199  */
200 static int load_HRT (void __iomem *rom_start)
201 {
202         u32 available;
203         u32 temp_dword;
204         u8 temp_byte = 0xFF;
205         u32 rc;
206
207         if (!check_for_compaq_ROM(rom_start)) {
208                 return -ENODEV;
209         }
210
211         available = 1024;
212
213         /* Now load the EV */
214         temp_dword = available;
215
216         rc = access_EV(READ_EV, "CQTHPS", evbuffer, &temp_dword);
217
218         evbuffer_length = temp_dword;
219
220         /* We're maintaining the resource lists so write FF to invalidate old
221          * info
222          */
223         temp_dword = 1;
224
225         rc = access_EV(WRITE_EV, "CQTHPS", &temp_byte, &temp_dword);
226
227         return rc;
228 }
229
230
231 /*
232  * store_HRT
233  *
234  * Save the hot plug Resource Table in NVRAM
235  */
236 static u32 store_HRT (void __iomem *rom_start)
237 {
238         u32 *buffer;
239         u32 *pFill;
240         u32 usedbytes;
241         u32 available;
242         u32 temp_dword;
243         u32 rc;
244         u8 loop;
245         u8 numCtrl = 0;
246         struct controller *ctrl;
247         struct pci_resource *resNode;
248         struct ev_hrt_header *p_EV_header;
249         struct ev_hrt_ctrl *p_ev_ctrl;
250
251         available = 1024;
252
253         if (!check_for_compaq_ROM(rom_start)) {
254                 return(1);
255         }
256
257         buffer = (u32*) evbuffer;
258
259         if (!buffer)
260                 return(1);
261
262         pFill = buffer;
263         usedbytes = 0;
264
265         p_EV_header = (struct ev_hrt_header *) pFill;
266
267         ctrl = cpqhp_ctrl_list;
268
269         /* The revision of this structure */
270         rc = add_byte(&pFill, 1 + ctrl->push_flag, &usedbytes, &available);
271         if (rc)
272                 return(rc);
273
274         /* The number of controllers */
275         rc = add_byte(&pFill, 1, &usedbytes, &available);
276         if (rc)
277                 return(rc);
278
279         while (ctrl) {
280                 p_ev_ctrl = (struct ev_hrt_ctrl *) pFill;
281
282                 numCtrl++;
283
284                 /* The bus number */
285                 rc = add_byte(&pFill, ctrl->bus, &usedbytes, &available);
286                 if (rc)
287                         return(rc);
288
289                 /* The device Number */
290                 rc = add_byte(&pFill, PCI_SLOT(ctrl->pci_dev->devfn), &usedbytes, &available);
291                 if (rc)
292                         return(rc);
293
294                 /* The function Number */
295                 rc = add_byte(&pFill, PCI_FUNC(ctrl->pci_dev->devfn), &usedbytes, &available);
296                 if (rc)
297                         return(rc);
298
299                 /* Skip the number of available entries */
300                 rc = add_dword(&pFill, 0, &usedbytes, &available);
301                 if (rc)
302                         return(rc);
303
304                 /* Figure out memory Available */
305
306                 resNode = ctrl->mem_head;
307
308                 loop = 0;
309
310                 while (resNode) {
311                         loop ++;
312
313                         /* base */
314                         rc = add_dword(&pFill, resNode->base, &usedbytes, &available);
315                         if (rc)
316                                 return(rc);
317
318                         /* length */
319                         rc = add_dword(&pFill, resNode->length, &usedbytes, &available);
320                         if (rc)
321                                 return(rc);
322
323                         resNode = resNode->next;
324                 }
325
326                 /* Fill in the number of entries */
327                 p_ev_ctrl->mem_avail = loop;
328
329                 /* Figure out prefetchable memory Available */
330
331                 resNode = ctrl->p_mem_head;
332
333                 loop = 0;
334
335                 while (resNode) {
336                         loop ++;
337
338                         /* base */
339                         rc = add_dword(&pFill, resNode->base, &usedbytes, &available);
340                         if (rc)
341                                 return(rc);
342
343                         /* length */
344                         rc = add_dword(&pFill, resNode->length, &usedbytes, &available);
345                         if (rc)
346                                 return(rc);
347
348                         resNode = resNode->next;
349                 }
350
351                 /* Fill in the number of entries */
352                 p_ev_ctrl->p_mem_avail = loop;
353
354                 /* Figure out IO Available */
355
356                 resNode = ctrl->io_head;
357
358                 loop = 0;
359
360                 while (resNode) {
361                         loop ++;
362
363                         /* base */
364                         rc = add_dword(&pFill, resNode->base, &usedbytes, &available);
365                         if (rc)
366                                 return(rc);
367
368                         /* length */
369                         rc = add_dword(&pFill, resNode->length, &usedbytes, &available);
370                         if (rc)
371                                 return(rc);
372
373                         resNode = resNode->next;
374                 }
375
376                 /* Fill in the number of entries */
377                 p_ev_ctrl->io_avail = loop;
378
379                 /* Figure out bus Available */
380
381                 resNode = ctrl->bus_head;
382
383                 loop = 0;
384
385                 while (resNode) {
386                         loop ++;
387
388                         /* base */
389                         rc = add_dword(&pFill, resNode->base, &usedbytes, &available);
390                         if (rc)
391                                 return(rc);
392
393                         /* length */
394                         rc = add_dword(&pFill, resNode->length, &usedbytes, &available);
395                         if (rc)
396                                 return(rc);
397
398                         resNode = resNode->next;
399                 }
400
401                 /* Fill in the number of entries */
402                 p_ev_ctrl->bus_avail = loop;
403
404                 ctrl = ctrl->next;
405         }
406
407         p_EV_header->num_of_ctrl = numCtrl;
408
409         /* Now store the EV */
410
411         temp_dword = usedbytes;
412
413         rc = access_EV(WRITE_EV, "CQTHPS", (u8*) buffer, &temp_dword);
414
415         dbg("usedbytes = 0x%x, length = 0x%x\n", usedbytes, temp_dword);
416
417         evbuffer_length = temp_dword;
418
419         if (rc) {
420                 err(msg_unable_to_save);
421                 return(1);
422         }
423
424         return(0);
425 }
426
427
428 void compaq_nvram_init (void __iomem *rom_start)
429 {
430         if (rom_start) {
431                 compaq_int15_entry_point = (rom_start + ROM_INT15_PHY_ADDR - ROM_PHY_ADDR);
432         }
433         dbg("int15 entry  = %p\n", compaq_int15_entry_point);
434
435         /* initialize our int15 lock */
436         spin_lock_init(&int15_lock);
437 }
438
439
440 int compaq_nvram_load (void __iomem *rom_start, struct controller *ctrl)
441 {
442         u8 bus, device, function;
443         u8 nummem, numpmem, numio, numbus;
444         u32 rc;
445         u8 *p_byte;
446         struct pci_resource *mem_node;
447         struct pci_resource *p_mem_node;
448         struct pci_resource *io_node;
449         struct pci_resource *bus_node;
450         struct ev_hrt_ctrl *p_ev_ctrl;
451         struct ev_hrt_header *p_EV_header;
452
453         if (!evbuffer_init) {
454                 /* Read the resource list information in from NVRAM */
455                 if (load_HRT(rom_start))
456                         memset (evbuffer, 0, 1024);
457
458                 evbuffer_init = 1;
459         }
460
461         /* If we saved information in NVRAM, use it now */
462         p_EV_header = (struct ev_hrt_header *) evbuffer;
463
464         /* The following code is for systems where version 1.0 of this
465          * driver has been loaded, but doesn't support the hardware.
466          * In that case, the driver would incorrectly store something
467          * in NVRAM.
468          */
469         if ((p_EV_header->Version == 2) ||
470             ((p_EV_header->Version == 1) && !ctrl->push_flag)) {
471                 p_byte = &(p_EV_header->next);
472
473                 p_ev_ctrl = (struct ev_hrt_ctrl *) &(p_EV_header->next);
474
475                 p_byte += 3;
476
477                 if (p_byte > ((u8*)p_EV_header + evbuffer_length))
478                         return 2;
479
480                 bus = p_ev_ctrl->bus;
481                 device = p_ev_ctrl->device;
482                 function = p_ev_ctrl->function;
483
484                 while ((bus != ctrl->bus) ||
485                        (device != PCI_SLOT(ctrl->pci_dev->devfn)) ||
486                        (function != PCI_FUNC(ctrl->pci_dev->devfn))) {
487                         nummem = p_ev_ctrl->mem_avail;
488                         numpmem = p_ev_ctrl->p_mem_avail;
489                         numio = p_ev_ctrl->io_avail;
490                         numbus = p_ev_ctrl->bus_avail;
491
492                         p_byte += 4;
493
494                         if (p_byte > ((u8*)p_EV_header + evbuffer_length))
495                                 return 2;
496
497                         /* Skip forward to the next entry */
498                         p_byte += (nummem + numpmem + numio + numbus) * 8;
499
500                         if (p_byte > ((u8*)p_EV_header + evbuffer_length))
501                                 return 2;
502
503                         p_ev_ctrl = (struct ev_hrt_ctrl *) p_byte;
504
505                         p_byte += 3;
506
507                         if (p_byte > ((u8*)p_EV_header + evbuffer_length))
508                                 return 2;
509
510                         bus = p_ev_ctrl->bus;
511                         device = p_ev_ctrl->device;
512                         function = p_ev_ctrl->function;
513                 }
514
515                 nummem = p_ev_ctrl->mem_avail;
516                 numpmem = p_ev_ctrl->p_mem_avail;
517                 numio = p_ev_ctrl->io_avail;
518                 numbus = p_ev_ctrl->bus_avail;
519
520                 p_byte += 4;
521
522                 if (p_byte > ((u8*)p_EV_header + evbuffer_length))
523                         return 2;
524
525                 while (nummem--) {
526                         mem_node = kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
527
528                         if (!mem_node)
529                                 break;
530
531                         mem_node->base = *(u32*)p_byte;
532                         dbg("mem base = %8.8x\n",mem_node->base);
533                         p_byte += 4;
534
535                         if (p_byte > ((u8*)p_EV_header + evbuffer_length)) {
536                                 kfree(mem_node);
537                                 return 2;
538                         }
539
540                         mem_node->length = *(u32*)p_byte;
541                         dbg("mem length = %8.8x\n",mem_node->length);
542                         p_byte += 4;
543
544                         if (p_byte > ((u8*)p_EV_header + evbuffer_length)) {
545                                 kfree(mem_node);
546                                 return 2;
547                         }
548
549                         mem_node->next = ctrl->mem_head;
550                         ctrl->mem_head = mem_node;
551                 }
552
553                 while (numpmem--) {
554                         p_mem_node = kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
555
556                         if (!p_mem_node)
557                                 break;
558
559                         p_mem_node->base = *(u32*)p_byte;
560                         dbg("pre-mem base = %8.8x\n",p_mem_node->base);
561                         p_byte += 4;
562
563                         if (p_byte > ((u8*)p_EV_header + evbuffer_length)) {
564                                 kfree(p_mem_node);
565                                 return 2;
566                         }
567
568                         p_mem_node->length = *(u32*)p_byte;
569                         dbg("pre-mem length = %8.8x\n",p_mem_node->length);
570                         p_byte += 4;
571
572                         if (p_byte > ((u8*)p_EV_header + evbuffer_length)) {
573                                 kfree(p_mem_node);
574                                 return 2;
575                         }
576
577                         p_mem_node->next = ctrl->p_mem_head;
578                         ctrl->p_mem_head = p_mem_node;
579                 }
580
581                 while (numio--) {
582                         io_node = kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
583
584                         if (!io_node)
585                                 break;
586
587                         io_node->base = *(u32*)p_byte;
588                         dbg("io base = %8.8x\n",io_node->base);
589                         p_byte += 4;
590
591                         if (p_byte > ((u8*)p_EV_header + evbuffer_length)) {
592                                 kfree(io_node);
593                                 return 2;
594                         }
595
596                         io_node->length = *(u32*)p_byte;
597                         dbg("io length = %8.8x\n",io_node->length);
598                         p_byte += 4;
599
600                         if (p_byte > ((u8*)p_EV_header + evbuffer_length)) {
601                                 kfree(io_node);
602                                 return 2;
603                         }
604
605                         io_node->next = ctrl->io_head;
606                         ctrl->io_head = io_node;
607                 }
608
609                 while (numbus--) {
610                         bus_node = kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
611
612                         if (!bus_node)
613                                 break;
614
615                         bus_node->base = *(u32*)p_byte;
616                         p_byte += 4;
617
618                         if (p_byte > ((u8*)p_EV_header + evbuffer_length)) {
619                                 kfree(bus_node);
620                                 return 2;
621                         }
622
623                         bus_node->length = *(u32*)p_byte;
624                         p_byte += 4;
625
626                         if (p_byte > ((u8*)p_EV_header + evbuffer_length)) {
627                                 kfree(bus_node);
628                                 return 2;
629                         }
630
631                         bus_node->next = ctrl->bus_head;
632                         ctrl->bus_head = bus_node;
633                 }
634
635                 /* If all of the following fail, we don't have any resources for
636                  * hot plug add
637                  */
638                 rc = 1;
639                 rc &= cpqhp_resource_sort_and_combine(&(ctrl->mem_head));
640                 rc &= cpqhp_resource_sort_and_combine(&(ctrl->p_mem_head));
641                 rc &= cpqhp_resource_sort_and_combine(&(ctrl->io_head));
642                 rc &= cpqhp_resource_sort_and_combine(&(ctrl->bus_head));
643
644                 if (rc)
645                         return(rc);
646         } else {
647                 if ((evbuffer[0] != 0) && (!ctrl->push_flag))
648                         return 1;
649         }
650
651         return 0;
652 }
653
654
655 int compaq_nvram_store (void __iomem *rom_start)
656 {
657         int rc = 1;
658
659         if (rom_start == NULL)
660                 return -ENODEV;
661
662         if (evbuffer_init) {
663                 rc = store_HRT(rom_start);
664                 if (rc) {
665                         err(msg_unable_to_save);
666                 }
667         }
668         return rc;
669 }
670