ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / arch / ia64 / sn / io / sn2 / pcibr / pcibr_hints.c
1 /*
2  * This file is subject to the terms and conditions of the GNU General Public
3  * License.  See the file "COPYING" in the main directory of this archive
4  * for more details.
5  *
6  * Copyright (C) 2001-2003 Silicon Graphics, Inc. All rights reserved.
7  */
8
9 #include <linux/types.h>
10 #include <asm/sn/sgi.h>
11 #include <asm/sn/iograph.h>
12 #include <asm/sn/pci/pcibr.h>
13 #include <asm/sn/pci/pcibr_private.h>
14 #include <asm/sn/pci/pci_defs.h>
15
16 pcibr_hints_t           pcibr_hints_get(vertex_hdl_t, int);
17 void                    pcibr_hints_fix_rrbs(vertex_hdl_t);
18 void                    pcibr_hints_dualslot(vertex_hdl_t, pciio_slot_t, pciio_slot_t);
19 void                    pcibr_hints_intr_bits(vertex_hdl_t, pcibr_intr_bits_f *);
20 void                    pcibr_set_rrb_callback(vertex_hdl_t, rrb_alloc_funct_t);
21 void                    pcibr_hints_handsoff(vertex_hdl_t);
22 void                    pcibr_hints_subdevs(vertex_hdl_t, pciio_slot_t, uint64_t);
23
24 pcibr_hints_t
25 pcibr_hints_get(vertex_hdl_t xconn_vhdl, int alloc)
26 {
27     arbitrary_info_t        ainfo = 0;
28     graph_error_t           rv;
29     pcibr_hints_t           hint;
30
31     rv = hwgraph_info_get_LBL(xconn_vhdl, INFO_LBL_PCIBR_HINTS, &ainfo);
32
33     if (alloc && (rv != GRAPH_SUCCESS)) {
34
35         hint = kmalloc(sizeof (*(hint)), GFP_KERNEL);
36         if ( !hint ) {
37                 printk(KERN_WARNING "pcibr_hints_get(): unable to allocate "
38                         "memory\n");
39                 goto abnormal_exit;
40         }
41         memset(hint, 0, sizeof (*(hint)));
42
43         hint->rrb_alloc_funct = NULL;
44         hint->ph_intr_bits = NULL;
45         rv = hwgraph_info_add_LBL(xconn_vhdl, 
46                                   INFO_LBL_PCIBR_HINTS,         
47                                   (arbitrary_info_t) hint);
48         if (rv != GRAPH_SUCCESS)
49             goto abnormal_exit;
50
51         rv = hwgraph_info_get_LBL(xconn_vhdl, INFO_LBL_PCIBR_HINTS, &ainfo);
52         
53         if (rv != GRAPH_SUCCESS)
54             goto abnormal_exit;
55
56         if (ainfo != (arbitrary_info_t) hint)
57             goto abnormal_exit;
58     }
59     return (pcibr_hints_t) ainfo;
60
61 abnormal_exit:
62     kfree(hint);
63     return NULL;
64
65 }
66
67 void
68 pcibr_hints_fix_some_rrbs(vertex_hdl_t xconn_vhdl, unsigned mask)
69 {
70     pcibr_hints_t           hint = pcibr_hints_get(xconn_vhdl, 1);
71
72     if (hint)
73         hint->ph_rrb_fixed = mask;
74     else
75         PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_HINTS, xconn_vhdl,
76                     "pcibr_hints_fix_rrbs: pcibr_hints_get failed\n"));
77 }
78
79 void
80 pcibr_hints_fix_rrbs(vertex_hdl_t xconn_vhdl)
81 {
82     pcibr_hints_fix_some_rrbs(xconn_vhdl, 0xFF);
83 }
84
85 void
86 pcibr_hints_dualslot(vertex_hdl_t xconn_vhdl,
87                      pciio_slot_t host,
88                      pciio_slot_t guest)
89 {
90     pcibr_hints_t           hint = pcibr_hints_get(xconn_vhdl, 1);
91
92     if (hint)
93         hint->ph_host_slot[guest] = host + 1;
94     else
95         PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_HINTS, xconn_vhdl,
96                     "pcibr_hints_dualslot: pcibr_hints_get failed\n"));
97 }
98
99 void
100 pcibr_hints_intr_bits(vertex_hdl_t xconn_vhdl,
101                       pcibr_intr_bits_f *xxx_intr_bits)
102 {
103     pcibr_hints_t           hint = pcibr_hints_get(xconn_vhdl, 1);
104
105     if (hint)
106         hint->ph_intr_bits = xxx_intr_bits;
107     else
108         PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_HINTS, xconn_vhdl,
109                     "pcibr_hints_intr_bits: pcibr_hints_get failed\n"));
110 }
111
112 void
113 pcibr_set_rrb_callback(vertex_hdl_t xconn_vhdl, rrb_alloc_funct_t rrb_alloc_funct)
114 {
115     pcibr_hints_t           hint = pcibr_hints_get(xconn_vhdl, 1);
116
117     if (hint)
118         hint->rrb_alloc_funct = rrb_alloc_funct;
119 }
120
121 void
122 pcibr_hints_handsoff(vertex_hdl_t xconn_vhdl)
123 {
124     pcibr_hints_t           hint = pcibr_hints_get(xconn_vhdl, 1);
125
126     if (hint)
127         hint->ph_hands_off = 1;
128     else
129         PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_HINTS, xconn_vhdl,
130                     "pcibr_hints_handsoff: pcibr_hints_get failed\n"));
131 }
132
133 void
134 pcibr_hints_subdevs(vertex_hdl_t xconn_vhdl,
135                     pciio_slot_t slot,
136                     uint64_t subdevs)
137 {
138     arbitrary_info_t        ainfo = 0;
139     char                    sdname[16];
140     vertex_hdl_t            pconn_vhdl = GRAPH_VERTEX_NONE;
141
142     sprintf(sdname, "%s/%d", EDGE_LBL_PCI, slot);
143     (void) hwgraph_path_add(xconn_vhdl, sdname, &pconn_vhdl);
144     if (pconn_vhdl == GRAPH_VERTEX_NONE) {
145         PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_HINTS, xconn_vhdl,
146                     "pcibr_hints_subdevs: hwgraph_path_create failed\n"));
147         return;
148     }
149     hwgraph_info_get_LBL(pconn_vhdl, INFO_LBL_SUBDEVS, &ainfo);
150     if (ainfo == 0) {
151         uint64_t                *subdevp;
152
153         subdevp = kmalloc(sizeof (*(subdevp)), GFP_KERNEL);
154         if (!subdevp) {
155             PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_HINTS, xconn_vhdl,
156                         "pcibr_hints_subdevs: subdev ptr alloc failed\n"));
157             return;
158         }
159         memset(subdevp, 0, sizeof (*(subdevp)));
160         *subdevp = subdevs;
161         hwgraph_info_add_LBL(pconn_vhdl, INFO_LBL_SUBDEVS, (arbitrary_info_t) subdevp);
162         hwgraph_info_get_LBL(pconn_vhdl, INFO_LBL_SUBDEVS, &ainfo);
163         if (ainfo == (arbitrary_info_t) subdevp)
164             return;
165         kfree(subdevp);
166         if (ainfo == (arbitrary_info_t) NULL) {
167             PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_HINTS, xconn_vhdl,
168                         "pcibr_hints_subdevs: null subdevs ptr\n"));
169             return;
170         }
171         PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_HINTS, xconn_vhdl,
172                     "pcibr_subdevs_get: dup subdev add_LBL\n"));
173     }
174     *(uint64_t *) ainfo = subdevs;
175 }