aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms/iseries
diff options
context:
space:
mode:
authorStephen Rothwell <sfr@canb.auug.org.au>2007-12-07 00:10:22 -0500
committerPaul Mackerras <paulus@samba.org>2007-12-10 21:46:11 -0500
commit1dee20262f4b16db73b2f24036bd423e8a7d693d (patch)
tree5556bf57ef7d71bf22343c48c3f20715df6cb56d /arch/powerpc/platforms/iseries
parent1be9ad650986a87c25686abda97bdea330359708 (diff)
[POWERPC] iSeries: Merge vpdinfo.c into pci.c
There was only one global function in vpdinfo.c and it was only called from pci.c, so merge them and make the function static. Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/platforms/iseries')
-rw-r--r--arch/powerpc/platforms/iseries/Makefile2
-rw-r--r--arch/powerpc/platforms/iseries/pci.c218
-rw-r--r--arch/powerpc/platforms/iseries/pci.h6
-rw-r--r--arch/powerpc/platforms/iseries/vpdinfo.c252
4 files changed, 219 insertions, 259 deletions
diff --git a/arch/powerpc/platforms/iseries/Makefile b/arch/powerpc/platforms/iseries/Makefile
index a65f1b44abf8..cc7161ff1666 100644
--- a/arch/powerpc/platforms/iseries/Makefile
+++ b/arch/powerpc/platforms/iseries/Makefile
@@ -5,7 +5,7 @@ extra-y += dt.o
5obj-y += exception.o 5obj-y += exception.o
6obj-y += hvlog.o hvlpconfig.o lpardata.o setup.o dt_mod.o mf.o lpevents.o \ 6obj-y += hvlog.o hvlpconfig.o lpardata.o setup.o dt_mod.o mf.o lpevents.o \
7 hvcall.o proc.o htab.o iommu.o misc.o irq.o 7 hvcall.o proc.o htab.o iommu.o misc.o irq.o
8obj-$(CONFIG_PCI) += pci.o vpdinfo.o 8obj-$(CONFIG_PCI) += pci.o
9obj-$(CONFIG_SMP) += smp.o 9obj-$(CONFIG_SMP) += smp.o
10obj-$(CONFIG_VIOPATH) += viopath.o vio.o 10obj-$(CONFIG_VIOPATH) += viopath.o vio.o
11obj-$(CONFIG_MODULES) += ksyms.o 11obj-$(CONFIG_MODULES) += ksyms.o
diff --git a/arch/powerpc/platforms/iseries/pci.c b/arch/powerpc/platforms/iseries/pci.c
index 5466975bc906..68f248b4c696 100644
--- a/arch/powerpc/platforms/iseries/pci.c
+++ b/arch/powerpc/platforms/iseries/pci.c
@@ -1,5 +1,6 @@
1/* 1/*
2 * Copyright (C) 2001 Allan Trautman, IBM Corporation 2 * Copyright (C) 2001 Allan Trautman, IBM Corporation
3 * Copyright (C) 2005,2007 Stephen Rothwell, IBM Corp
3 * 4 *
4 * iSeries specific routines for PCI. 5 * iSeries specific routines for PCI.
5 * 6 *
@@ -26,6 +27,7 @@
26#include <linux/module.h> 27#include <linux/module.h>
27#include <linux/pci.h> 28#include <linux/pci.h>
28 29
30#include <asm/types.h>
29#include <asm/io.h> 31#include <asm/io.h>
30#include <asm/irq.h> 32#include <asm/irq.h>
31#include <asm/prom.h> 33#include <asm/prom.h>
@@ -35,6 +37,7 @@
35#include <asm/abs_addr.h> 37#include <asm/abs_addr.h>
36#include <asm/firmware.h> 38#include <asm/firmware.h>
37 39
40#include <asm/iseries/hv_types.h>
38#include <asm/iseries/hv_call_xm.h> 41#include <asm/iseries/hv_call_xm.h>
39#include <asm/iseries/mf.h> 42#include <asm/iseries/mf.h>
40#include <asm/iseries/iommu.h> 43#include <asm/iseries/iommu.h>
@@ -80,6 +83,221 @@ static inline u64 iseries_ds_addr(struct device_node *node)
80} 83}
81 84
82/* 85/*
86 * Size of Bus VPD data
87 */
88#define BUS_VPDSIZE 1024
89
90/*
91 * Bus Vpd Tags
92 */
93#define VPD_END_OF_AREA 0x79
94#define VPD_ID_STRING 0x82
95#define VPD_VENDOR_AREA 0x84
96
97/*
98 * Mfg Area Tags
99 */
100#define VPD_FRU_FRAME_ID 0x4649 /* "FI" */
101#define VPD_SLOT_MAP_FORMAT 0x4D46 /* "MF" */
102#define VPD_SLOT_MAP 0x534D /* "SM" */
103
104/*
105 * Structures of the areas
106 */
107struct mfg_vpd_area {
108 u16 tag;
109 u8 length;
110 u8 data1;
111 u8 data2;
112};
113#define MFG_ENTRY_SIZE 3
114
115struct slot_map {
116 u8 agent;
117 u8 secondary_agent;
118 u8 phb;
119 char card_location[3];
120 char parms[8];
121 char reserved[2];
122};
123#define SLOT_ENTRY_SIZE 16
124
125/*
126 * Parse the Slot Area
127 */
128static void __init iseries_parse_slot_area(struct slot_map *map, int len,
129 HvAgentId agent, u8 *phb, char card[4])
130{
131 /*
132 * Parse Slot label until we find the one requested
133 */
134 while (len > 0) {
135 if (map->agent == agent) {
136 /*
137 * If Phb wasn't found, grab the entry first one found.
138 */
139 if (*phb == 0xff)
140 *phb = map->phb;
141 /* Found it, extract the data. */
142 if (map->phb == *phb) {
143 memcpy(card, &map->card_location, 3);
144 card[3] = 0;
145 break;
146 }
147 }
148 /* Point to the next Slot */
149 map = (struct slot_map *)((char *)map + SLOT_ENTRY_SIZE);
150 len -= SLOT_ENTRY_SIZE;
151 }
152}
153
154/*
155 * Parse the Mfg Area
156 */
157static void __init iseries_parse_mfg_area(struct mfg_vpd_area *area, int len,
158 HvAgentId agent, u8 *phb, u8 *frame, char card[4])
159{
160 u16 slot_map_fmt = 0;
161
162 /* Parse Mfg Data */
163 while (len > 0) {
164 int mfg_tag_len = area->length;
165 /* Frame ID (FI 4649020310 ) */
166 if (area->tag == VPD_FRU_FRAME_ID)
167 *frame = area->data1;
168 /* Slot Map Format (MF 4D46020004 ) */
169 else if (area->tag == VPD_SLOT_MAP_FORMAT)
170 slot_map_fmt = (area->data1 * 256)
171 + area->data2;
172 /* Slot Map (SM 534D90 */
173 else if (area->tag == VPD_SLOT_MAP) {
174 struct slot_map *slot_map;
175
176 if (slot_map_fmt == 0x1004)
177 slot_map = (struct slot_map *)((char *)area
178 + MFG_ENTRY_SIZE + 1);
179 else
180 slot_map = (struct slot_map *)((char *)area
181 + MFG_ENTRY_SIZE);
182 iseries_parse_slot_area(slot_map, mfg_tag_len,
183 agent, phb, card);
184 }
185 /*
186 * Point to the next Mfg Area
187 * Use defined size, sizeof give wrong answer
188 */
189 area = (struct mfg_vpd_area *)((char *)area + mfg_tag_len
190 + MFG_ENTRY_SIZE);
191 len -= (mfg_tag_len + MFG_ENTRY_SIZE);
192 }
193}
194
195/*
196 * Look for "BUS".. Data is not Null terminated.
197 * PHBID of 0xFF indicates PHB was not found in VPD Data.
198 */
199static u8 __init iseries_parse_phbid(u8 *area, int len)
200{
201 while (len > 0) {
202 if ((*area == 'B') && (*(area + 1) == 'U')
203 && (*(area + 2) == 'S')) {
204 area += 3;
205 while (*area == ' ')
206 area++;
207 return *area & 0x0F;
208 }
209 area++;
210 len--;
211 }
212 return 0xff;
213}
214
215/*
216 * Parse out the VPD Areas
217 */
218static void __init iseries_parse_vpd(u8 *data, int data_len,
219 HvAgentId agent, u8 *frame, char card[4])
220{
221 u8 phb = 0xff;
222
223 while (data_len > 0) {
224 int len;
225 u8 tag = *data;
226
227 if (tag == VPD_END_OF_AREA)
228 break;
229 len = *(data + 1) + (*(data + 2) * 256);
230 data += 3;
231 data_len -= 3;
232 if (tag == VPD_ID_STRING)
233 phb = iseries_parse_phbid(data, len);
234 else if (tag == VPD_VENDOR_AREA)
235 iseries_parse_mfg_area((struct mfg_vpd_area *)data, len,
236 agent, &phb, frame, card);
237 /* Point to next Area. */
238 data += len;
239 data_len -= len;
240 }
241}
242
243static int __init iseries_get_location_code(u16 bus, HvAgentId agent,
244 u8 *frame, char card[4])
245{
246 int status = 0;
247 int bus_vpd_len = 0;
248 u8 *bus_vpd = kmalloc(BUS_VPDSIZE, GFP_KERNEL);
249
250 if (bus_vpd == NULL) {
251 printk("PCI: Bus VPD Buffer allocation failure.\n");
252 return 0;
253 }
254 bus_vpd_len = HvCallPci_getBusVpd(bus, iseries_hv_addr(bus_vpd),
255 BUS_VPDSIZE);
256 if (bus_vpd_len == 0) {
257 printk("PCI: Bus VPD Buffer zero length.\n");
258 goto out_free;
259 }
260 /* printk("PCI: bus_vpd: %p, %d\n",bus_vpd, bus_vpd_len); */
261 /* Make sure this is what I think it is */
262 if (*bus_vpd != VPD_ID_STRING) {
263 printk("PCI: Bus VPD Buffer missing starting tag.\n");
264 goto out_free;
265 }
266 iseries_parse_vpd(bus_vpd, bus_vpd_len, agent, frame, card);
267 status = 1;
268out_free:
269 kfree(bus_vpd);
270 return status;
271}
272
273/*
274 * Prints the device information.
275 * - Pass in pci_dev* pointer to the device.
276 * - Pass in the device count
277 *
278 * Format:
279 * PCI: Bus 0, Device 26, Vendor 0x12AE Frame 1, Card C10 Ethernet
280 * controller
281 */
282static void __init iseries_device_information(struct pci_dev *pdev, int count,
283 u16 bus, HvSubBusNumber subbus)
284{
285 u8 frame = 0;
286 char card[4];
287 HvAgentId agent;
288
289 agent = ISERIES_PCI_AGENTID(ISERIES_GET_DEVICE_FROM_SUBBUS(subbus),
290 ISERIES_GET_FUNCTION_FROM_SUBBUS(subbus));
291
292 if (iseries_get_location_code(bus, agent, &frame, card)) {
293 printk("%d. PCI: Bus%3d, Device%3d, Vendor %04X Frame%3d, "
294 "Card %4s 0x%04X\n", count, bus,
295 PCI_SLOT(pdev->devfn), pdev->vendor, frame,
296 card, (int)(pdev->class >> 8));
297 }
298}
299
300/*
83 * iomm_table_allocate_entry 301 * iomm_table_allocate_entry
84 * 302 *
85 * Adds pci_dev entry in address translation table 303 * Adds pci_dev entry in address translation table
diff --git a/arch/powerpc/platforms/iseries/pci.h b/arch/powerpc/platforms/iseries/pci.h
index 5f517cf23082..180aa74afb2d 100644
--- a/arch/powerpc/platforms/iseries/pci.h
+++ b/arch/powerpc/platforms/iseries/pci.h
@@ -30,10 +30,6 @@
30 * End Change Activity 30 * End Change Activity
31 */ 31 */
32 32
33#include <asm/iseries/hv_types.h>
34
35struct pci_dev; /* For Forward Reference */
36
37/* 33/*
38 * Decodes Linux DevFn to iSeries DevFn, bridge device, or function. 34 * Decodes Linux DevFn to iSeries DevFn, bridge device, or function.
39 * For Linux, see PCI_SLOT and PCI_FUNC in include/linux/pci.h 35 * For Linux, see PCI_SLOT and PCI_FUNC in include/linux/pci.h
@@ -47,8 +43,6 @@ struct pci_dev; /* For Forward Reference */
47#define ISERIES_GET_DEVICE_FROM_SUBBUS(subbus) ((subbus >> 5) & 0x7) 43#define ISERIES_GET_DEVICE_FROM_SUBBUS(subbus) ((subbus >> 5) & 0x7)
48#define ISERIES_GET_FUNCTION_FROM_SUBBUS(subbus) ((subbus >> 2) & 0x7) 44#define ISERIES_GET_FUNCTION_FROM_SUBBUS(subbus) ((subbus >> 2) & 0x7)
49 45
50extern void iseries_device_information(struct pci_dev *pdev, int count,
51 u16 bus, HvSubBusNumber subbus);
52#ifdef CONFIG_PCI 46#ifdef CONFIG_PCI
53extern void iSeries_pcibios_init(void); 47extern void iSeries_pcibios_init(void);
54extern void iSeries_pci_final_fixup(void); 48extern void iSeries_pci_final_fixup(void);
diff --git a/arch/powerpc/platforms/iseries/vpdinfo.c b/arch/powerpc/platforms/iseries/vpdinfo.c
deleted file mode 100644
index aec82e365576..000000000000
--- a/arch/powerpc/platforms/iseries/vpdinfo.c
+++ /dev/null
@@ -1,252 +0,0 @@
1/*
2 * This code gets the card location of the hardware
3 * Copyright (C) 2001 <Allan H Trautman> <IBM Corp>
4 * Copyright (C) 2005 Stephen Rothwel, IBM Corp
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the:
18 * Free Software Foundation, Inc.,
19 * 59 Temple Place, Suite 330,
20 * Boston, MA 02111-1307 USA
21 *
22 * Change Activity:
23 * Created, Feb 2, 2001
24 * Ported to ppc64, August 20, 2001
25 * End Change Activity
26 */
27#include <linux/init.h>
28#include <linux/module.h>
29#include <linux/pci.h>
30
31#include <asm/types.h>
32#include <asm/resource.h>
33#include <asm/abs_addr.h>
34#include <asm/iseries/hv_types.h>
35
36#include "pci.h"
37#include "call_pci.h"
38
39/*
40 * Size of Bus VPD data
41 */
42#define BUS_VPDSIZE 1024
43
44/*
45 * Bus Vpd Tags
46 */
47#define VPD_END_OF_AREA 0x79
48#define VPD_ID_STRING 0x82
49#define VPD_VENDOR_AREA 0x84
50
51/*
52 * Mfg Area Tags
53 */
54#define VPD_FRU_FRAME_ID 0x4649 /* "FI" */
55#define VPD_SLOT_MAP_FORMAT 0x4D46 /* "MF" */
56#define VPD_SLOT_MAP 0x534D /* "SM" */
57
58/*
59 * Structures of the areas
60 */
61struct mfg_vpd_area {
62 u16 tag;
63 u8 length;
64 u8 data1;
65 u8 data2;
66};
67#define MFG_ENTRY_SIZE 3
68
69struct slot_map {
70 u8 agent;
71 u8 secondary_agent;
72 u8 phb;
73 char card_location[3];
74 char parms[8];
75 char reserved[2];
76};
77#define SLOT_ENTRY_SIZE 16
78
79/*
80 * Parse the Slot Area
81 */
82static void __init iseries_parse_slot_area(struct slot_map *map, int len,
83 HvAgentId agent, u8 *phb, char card[4])
84{
85 /*
86 * Parse Slot label until we find the one requested
87 */
88 while (len > 0) {
89 if (map->agent == agent) {
90 /*
91 * If Phb wasn't found, grab the entry first one found.
92 */
93 if (*phb == 0xff)
94 *phb = map->phb;
95 /* Found it, extract the data. */
96 if (map->phb == *phb) {
97 memcpy(card, &map->card_location, 3);
98 card[3] = 0;
99 break;
100 }
101 }
102 /* Point to the next Slot */
103 map = (struct slot_map *)((char *)map + SLOT_ENTRY_SIZE);
104 len -= SLOT_ENTRY_SIZE;
105 }
106}
107
108/*
109 * Parse the Mfg Area
110 */
111static void __init iseries_parse_mfg_area(struct mfg_vpd_area *area, int len,
112 HvAgentId agent, u8 *phb, u8 *frame, char card[4])
113{
114 u16 slot_map_fmt = 0;
115
116 /* Parse Mfg Data */
117 while (len > 0) {
118 int mfg_tag_len = area->length;
119 /* Frame ID (FI 4649020310 ) */
120 if (area->tag == VPD_FRU_FRAME_ID)
121 *frame = area->data1;
122 /* Slot Map Format (MF 4D46020004 ) */
123 else if (area->tag == VPD_SLOT_MAP_FORMAT)
124 slot_map_fmt = (area->data1 * 256)
125 + area->data2;
126 /* Slot Map (SM 534D90 */
127 else if (area->tag == VPD_SLOT_MAP) {
128 struct slot_map *slot_map;
129
130 if (slot_map_fmt == 0x1004)
131 slot_map = (struct slot_map *)((char *)area
132 + MFG_ENTRY_SIZE + 1);
133 else
134 slot_map = (struct slot_map *)((char *)area
135 + MFG_ENTRY_SIZE);
136 iseries_parse_slot_area(slot_map, mfg_tag_len,
137 agent, phb, card);
138 }
139 /*
140 * Point to the next Mfg Area
141 * Use defined size, sizeof give wrong answer
142 */
143 area = (struct mfg_vpd_area *)((char *)area + mfg_tag_len
144 + MFG_ENTRY_SIZE);
145 len -= (mfg_tag_len + MFG_ENTRY_SIZE);
146 }
147}
148
149/*
150 * Look for "BUS".. Data is not Null terminated.
151 * PHBID of 0xFF indicates PHB was not found in VPD Data.
152 */
153static u8 __init iseries_parse_phbid(u8 *area, int len)
154{
155 while (len > 0) {
156 if ((*area == 'B') && (*(area + 1) == 'U')
157 && (*(area + 2) == 'S')) {
158 area += 3;
159 while (*area == ' ')
160 area++;
161 return *area & 0x0F;
162 }
163 area++;
164 len--;
165 }
166 return 0xff;
167}
168
169/*
170 * Parse out the VPD Areas
171 */
172static void __init iseries_parse_vpd(u8 *data, int data_len,
173 HvAgentId agent, u8 *frame, char card[4])
174{
175 u8 phb = 0xff;
176
177 while (data_len > 0) {
178 int len;
179 u8 tag = *data;
180
181 if (tag == VPD_END_OF_AREA)
182 break;
183 len = *(data + 1) + (*(data + 2) * 256);
184 data += 3;
185 data_len -= 3;
186 if (tag == VPD_ID_STRING)
187 phb = iseries_parse_phbid(data, len);
188 else if (tag == VPD_VENDOR_AREA)
189 iseries_parse_mfg_area((struct mfg_vpd_area *)data, len,
190 agent, &phb, frame, card);
191 /* Point to next Area. */
192 data += len;
193 data_len -= len;
194 }
195}
196
197static int __init iseries_get_location_code(u16 bus, HvAgentId agent,
198 u8 *frame, char card[4])
199{
200 int status = 0;
201 int bus_vpd_len = 0;
202 u8 *bus_vpd = kmalloc(BUS_VPDSIZE, GFP_KERNEL);
203
204 if (bus_vpd == NULL) {
205 printk("PCI: Bus VPD Buffer allocation failure.\n");
206 return 0;
207 }
208 bus_vpd_len = HvCallPci_getBusVpd(bus, iseries_hv_addr(bus_vpd),
209 BUS_VPDSIZE);
210 if (bus_vpd_len == 0) {
211 printk("PCI: Bus VPD Buffer zero length.\n");
212 goto out_free;
213 }
214 /* printk("PCI: bus_vpd: %p, %d\n",bus_vpd, bus_vpd_len); */
215 /* Make sure this is what I think it is */
216 if (*bus_vpd != VPD_ID_STRING) {
217 printk("PCI: Bus VPD Buffer missing starting tag.\n");
218 goto out_free;
219 }
220 iseries_parse_vpd(bus_vpd, bus_vpd_len, agent, frame, card);
221 status = 1;
222out_free:
223 kfree(bus_vpd);
224 return status;
225}
226
227/*
228 * Prints the device information.
229 * - Pass in pci_dev* pointer to the device.
230 * - Pass in the device count
231 *
232 * Format:
233 * PCI: Bus 0, Device 26, Vendor 0x12AE Frame 1, Card C10 Ethernet
234 * controller
235 */
236void __init iseries_device_information(struct pci_dev *pdev, int count,
237 u16 bus, HvSubBusNumber subbus)
238{
239 u8 frame = 0;
240 char card[4];
241 HvAgentId agent;
242
243 agent = ISERIES_PCI_AGENTID(ISERIES_GET_DEVICE_FROM_SUBBUS(subbus),
244 ISERIES_GET_FUNCTION_FROM_SUBBUS(subbus));
245
246 if (iseries_get_location_code(bus, agent, &frame, card)) {
247 printk("%d. PCI: Bus%3d, Device%3d, Vendor %04X Frame%3d, "
248 "Card %4s 0x%04X\n", count, bus,
249 PCI_SLOT(pdev->devfn), pdev->vendor, frame,
250 card, (int)(pdev->class >> 8));
251 }
252}