Blame view

drivers/rapidio/rio-scan.c 35.7 KB
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
1
2
3
4
5
6
  /*
   * RapidIO enumeration and discovery support
   *
   * Copyright 2005 MontaVista Software, Inc.
   * Matt Porter <mporter@kernel.crashing.org>
   *
e5cabeb3d   Alexandre Bounine   rapidio: add Port...
7
8
9
10
   * Copyright 2009 Integrated Device Technology, Inc.
   * Alex Bounine <alexandre.bounine@idt.com>
   * - Added Port-Write/Error Management initialization and handling
   *
933af4a6c   Thomas Moll   rapidio: add enab...
11
12
13
14
   * Copyright 2009 Sysgo AG
   * Thomas Moll <thomas.moll@sysgo.com>
   * - Added Input- Output- enable functionality, to allow full communication
   *
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
15
16
17
18
19
   * This program is free software; you can redistribute  it and/or modify it
   * under  the terms of  the GNU General  Public License as published by the
   * Free Software Foundation;  either version 2 of the  License, or (at your
   * option) any later version.
   */
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
20
21
22
23
  #include <linux/types.h>
  #include <linux/kernel.h>
  
  #include <linux/delay.h>
fa78cc517   Matt Porter   [PATCH] rapidio: ...
24
  #include <linux/dma-mapping.h>
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
25
26
27
28
29
30
31
32
  #include <linux/init.h>
  #include <linux/rio.h>
  #include <linux/rio_drv.h>
  #include <linux/rio_ids.h>
  #include <linux/rio_regs.h>
  #include <linux/module.h>
  #include <linux/spinlock.h>
  #include <linux/timer.h>
de25968cc   Tim Schmielau   [PATCH] fix more ...
33
34
  #include <linux/jiffies.h>
  #include <linux/slab.h>
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
35
36
37
38
39
  
  #include "rio.h"
  
  LIST_HEAD(rio_devices);
  static LIST_HEAD(rio_switches);
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
40
  static void rio_enum_timeout(unsigned long);
e5cabeb3d   Alexandre Bounine   rapidio: add Port...
41
  static void rio_init_em(struct rio_dev *rdev);
fa78cc517   Matt Porter   [PATCH] rapidio: ...
42
  DEFINE_SPINLOCK(rio_global_list_lock);
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
43
  static int next_destid = 0;
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
44
  static int next_net = 0;
af84ca38a   Alexandre Bounine   rapidio: add hand...
45
  static int next_comptag = 1;
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
46
47
48
49
50
51
52
53
54
55
56
  
  static struct timer_list rio_enum_timer =
  TIMER_INITIALIZER(rio_enum_timeout, 0, 0);
  
  static int rio_mport_phys_table[] = {
  	RIO_EFB_PAR_EP_ID,
  	RIO_EFB_PAR_EP_REC_ID,
  	RIO_EFB_SER_EP_ID,
  	RIO_EFB_SER_EP_REC_ID,
  	-1,
  };
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
57
58
59
60
61
62
63
64
65
66
67
68
69
70
  /**
   * rio_get_device_id - Get the base/extended device id for a device
   * @port: RIO master port
   * @destid: Destination ID of device
   * @hopcount: Hopcount to device
   *
   * Reads the base/extended device id from a device. Returns the
   * 8/16-bit device ID.
   */
  static u16 rio_get_device_id(struct rio_mport *port, u16 destid, u8 hopcount)
  {
  	u32 result;
  
  	rio_mport_read_config_32(port, destid, hopcount, RIO_DID_CSR, &result);
e04232360   Zhang Wei   [RAPIDIO] Auto-pr...
71
  	return RIO_GET_DID(port->sys_size, result);
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
72
73
74
75
76
77
78
79
80
81
82
  }
  
  /**
   * rio_set_device_id - Set the base/extended device id for a device
   * @port: RIO master port
   * @destid: Destination ID of device
   * @hopcount: Hopcount to device
   * @did: Device ID value to be written
   *
   * Writes the base/extended device id from a device.
   */
fa78cc517   Matt Porter   [PATCH] rapidio: ...
83
  static void rio_set_device_id(struct rio_mport *port, u16 destid, u8 hopcount, u16 did)
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
84
85
  {
  	rio_mport_write_config_32(port, destid, hopcount, RIO_DID_CSR,
e04232360   Zhang Wei   [RAPIDIO] Auto-pr...
86
  				  RIO_SET_DID(port->sys_size, did));
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
87
88
89
90
91
92
93
94
95
96
97
  }
  
  /**
   * rio_local_set_device_id - Set the base/extended device id for a port
   * @port: RIO master port
   * @did: Device ID value to be written
   *
   * Writes the base/extended device id from a device.
   */
  static void rio_local_set_device_id(struct rio_mport *port, u16 did)
  {
e04232360   Zhang Wei   [RAPIDIO] Auto-pr...
98
99
  	rio_local_write_config_32(port, RIO_DID_CSR, RIO_SET_DID(port->sys_size,
  				did));
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
  }
  
  /**
   * rio_clear_locks- Release all host locks and signal enumeration complete
   * @port: Master port to issue transaction
   *
   * Marks the component tag CSR on each device with the enumeration
   * complete flag. When complete, it then release the host locks on
   * each device. Returns 0 on success or %-EINVAL on failure.
   */
  static int rio_clear_locks(struct rio_mport *port)
  {
  	struct rio_dev *rdev;
  	u32 result;
  	int ret = 0;
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
  	/* Release host device id locks */
  	rio_local_write_config_32(port, RIO_HOST_DID_LOCK_CSR,
  				  port->host_deviceid);
  	rio_local_read_config_32(port, RIO_HOST_DID_LOCK_CSR, &result);
  	if ((result & 0xffff) != 0xffff) {
  		printk(KERN_INFO
  		       "RIO: badness when releasing host lock on master port, result %8.8x
  ",
  		       result);
  		ret = -EINVAL;
  	}
  	list_for_each_entry(rdev, &rio_devices, global_list) {
  		rio_write_config_32(rdev, RIO_HOST_DID_LOCK_CSR,
  				    port->host_deviceid);
  		rio_read_config_32(rdev, RIO_HOST_DID_LOCK_CSR, &result);
  		if ((result & 0xffff) != 0xffff) {
  			printk(KERN_INFO
  			       "RIO: badness when releasing host lock on vid %4.4x did %4.4x
  ",
  			       rdev->vid, rdev->did);
  			ret = -EINVAL;
  		}
af84ca38a   Alexandre Bounine   rapidio: add hand...
137
138
139
140
141
142
143
144
145
  
  		/* Mark device as discovered and enable master */
  		rio_read_config_32(rdev,
  				   rdev->phys_efptr + RIO_PORT_GEN_CTL_CSR,
  				   &result);
  		result |= RIO_PORT_GEN_DISCOVERED | RIO_PORT_GEN_MASTER;
  		rio_write_config_32(rdev,
  				    rdev->phys_efptr + RIO_PORT_GEN_CTL_CSR,
  				    result);
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
  	}
  
  	return ret;
  }
  
  /**
   * rio_enum_host- Set host lock and initialize host destination ID
   * @port: Master port to issue transaction
   *
   * Sets the local host master port lock and destination ID register
   * with the host device ID value. The host device ID value is provided
   * by the platform. Returns %0 on success or %-1 on failure.
   */
  static int rio_enum_host(struct rio_mport *port)
  {
  	u32 result;
  
  	/* Set master port host device id lock */
  	rio_local_write_config_32(port, RIO_HOST_DID_LOCK_CSR,
  				  port->host_deviceid);
  
  	rio_local_read_config_32(port, RIO_HOST_DID_LOCK_CSR, &result);
  	if ((result & 0xffff) != port->host_deviceid)
  		return -1;
  
  	/* Set master port destid and init destid ctr */
  	rio_local_set_device_id(port, port->host_deviceid);
  
  	if (next_destid == port->host_deviceid)
  		next_destid++;
  
  	return 0;
  }
  
  /**
   * rio_device_has_destid- Test if a device contains a destination ID register
   * @port: Master port to issue transaction
   * @src_ops: RIO device source operations
   * @dst_ops: RIO device destination operations
   *
   * Checks the provided @src_ops and @dst_ops for the necessary transaction
   * capabilities that indicate whether or not a device will implement a
   * destination ID register. Returns 1 if true or 0 if false.
   */
  static int rio_device_has_destid(struct rio_mport *port, int src_ops,
  				 int dst_ops)
  {
fa78cc517   Matt Porter   [PATCH] rapidio: ...
193
194
195
  	u32 mask = RIO_OPS_READ | RIO_OPS_WRITE | RIO_OPS_ATOMIC_TST_SWP | RIO_OPS_ATOMIC_INC | RIO_OPS_ATOMIC_DEC | RIO_OPS_ATOMIC_SET | RIO_OPS_ATOMIC_CLR;
  
  	return !!((src_ops | dst_ops) & mask);
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
  }
  
  /**
   * rio_release_dev- Frees a RIO device struct
   * @dev: LDM device associated with a RIO device struct
   *
   * Gets the RIO device struct associated a RIO device struct.
   * The RIO device struct is freed.
   */
  static void rio_release_dev(struct device *dev)
  {
  	struct rio_dev *rdev;
  
  	rdev = to_rio_dev(dev);
  	kfree(rdev);
  }
  
  /**
   * rio_is_switch- Tests if a RIO device has switch capabilities
   * @rdev: RIO device
   *
   * Gets the RIO device Processing Element Features register
   * contents and tests for switch capabilities. Returns 1 if
   * the device is a switch or 0 if it is not a switch.
   * The RIO device struct is freed.
   */
  static int rio_is_switch(struct rio_dev *rdev)
  {
  	if (rdev->pef & RIO_PEF_SWITCH)
  		return 1;
  	return 0;
  }
  
  /**
058f88d67   Alexandre Bounine   rapidio: modify i...
230
   * rio_switch_init - Sets switch operations for a particular vendor switch
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
231
   * @rdev: RIO device
058f88d67   Alexandre Bounine   rapidio: modify i...
232
   * @do_enum: Enumeration/Discovery mode flag
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
233
   *
058f88d67   Alexandre Bounine   rapidio: modify i...
234
235
236
   * Searches the RIO switch ops table for known switch types. If the vid
   * and did match a switch table entry, then call switch initialization
   * routine to setup switch-specific routines.
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
237
   */
058f88d67   Alexandre Bounine   rapidio: modify i...
238
  static void rio_switch_init(struct rio_dev *rdev, int do_enum)
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
239
  {
058f88d67   Alexandre Bounine   rapidio: modify i...
240
241
  	struct rio_switch_ops *cur = __start_rio_switch_ops;
  	struct rio_switch_ops *end = __end_rio_switch_ops;
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
242
243
244
  
  	while (cur < end) {
  		if ((cur->vid == rdev->vid) && (cur->did == rdev->did)) {
058f88d67   Alexandre Bounine   rapidio: modify i...
245
246
247
248
  			pr_debug("RIO: calling init routine for %s
  ",
  				 rio_name(rdev));
  			cur->init_hook(rdev, do_enum);
07590ff03   Alexandre Bounine   rapidio: add IDT ...
249
  			break;
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
250
251
252
  		}
  		cur++;
  	}
07590ff03   Alexandre Bounine   rapidio: add IDT ...
253
254
255
256
257
258
259
260
  	if ((cur >= end) && (rdev->pef & RIO_PEF_STD_RT)) {
  		pr_debug("RIO: adding STD routing ops for %s
  ",
  			rio_name(rdev));
  		rdev->rswitch->add_entry = rio_std_route_add_entry;
  		rdev->rswitch->get_entry = rio_std_route_get_entry;
  		rdev->rswitch->clr_table = rio_std_route_clr_table;
  	}
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
261
262
263
264
265
266
267
268
269
270
271
272
273
274
  	if (!rdev->rswitch->add_entry || !rdev->rswitch->get_entry)
  		printk(KERN_ERR "RIO: missing routing ops for %s
  ",
  		       rio_name(rdev));
  }
  
  /**
   * rio_add_device- Adds a RIO device to the device model
   * @rdev: RIO device
   *
   * Adds the RIO device to the global device list and adds the RIO
   * device to the RIO device list.  Creates the generic sysfs nodes
   * for an RIO device.
   */
5f28c5200   Yang Li   rio: warn_unused_...
275
  static int __devinit rio_add_device(struct rio_dev *rdev)
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
276
  {
5f28c5200   Yang Li   rio: warn_unused_...
277
278
279
280
281
  	int err;
  
  	err = device_add(&rdev->dev);
  	if (err)
  		return err;
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
282
283
284
285
286
287
  
  	spin_lock(&rio_global_list_lock);
  	list_add_tail(&rdev->global_list, &rio_devices);
  	spin_unlock(&rio_global_list_lock);
  
  	rio_create_sysfs_dev_files(rdev);
5f28c5200   Yang Li   rio: warn_unused_...
288
289
  
  	return 0;
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
290
291
292
  }
  
  /**
25985edce   Lucas De Marchi   Fix common misspe...
293
   * rio_enable_rx_tx_port - enable input receiver and output transmitter of
933af4a6c   Thomas Moll   rapidio: add enab...
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
   * given port
   * @port: Master port associated with the RIO network
   * @local: local=1 select local port otherwise a far device is reached
   * @destid: Destination ID of the device to check host bit
   * @hopcount: Number of hops to reach the target
   * @port_num: Port (-number on switch) to enable on a far end device
   *
   * Returns 0 or 1 from on General Control Command and Status Register
   * (EXT_PTR+0x3C)
   */
  inline int rio_enable_rx_tx_port(struct rio_mport *port,
  				 int local, u16 destid,
  				 u8 hopcount, u8 port_num) {
  #ifdef CONFIG_RAPIDIO_ENABLE_RX_TX_PORTS
  	u32 regval;
  	u32 ext_ftr_ptr;
  
  	/*
  	* enable rx input tx output port
  	*/
  	pr_debug("rio_enable_rx_tx_port(local = %d, destid = %d, hopcount = "
  		 "%d, port_num = %d)
  ", local, destid, hopcount, port_num);
  
  	ext_ftr_ptr = rio_mport_get_physefb(port, local, destid, hopcount);
  
  	if (local) {
  		rio_local_read_config_32(port, ext_ftr_ptr +
  				RIO_PORT_N_CTL_CSR(0),
  				&regval);
  	} else {
  		if (rio_mport_read_config_32(port, destid, hopcount,
  		ext_ftr_ptr + RIO_PORT_N_CTL_CSR(port_num), &regval) < 0)
  			return -EIO;
  	}
  
  	if (regval & RIO_PORT_N_CTL_P_TYP_SER) {
  		/* serial */
  		regval = regval | RIO_PORT_N_CTL_EN_RX_SER
  				| RIO_PORT_N_CTL_EN_TX_SER;
  	} else {
  		/* parallel */
  		regval = regval | RIO_PORT_N_CTL_EN_RX_PAR
  				| RIO_PORT_N_CTL_EN_TX_PAR;
  	}
  
  	if (local) {
  		rio_local_write_config_32(port, ext_ftr_ptr +
  					  RIO_PORT_N_CTL_CSR(0), regval);
  	} else {
  		if (rio_mport_write_config_32(port, destid, hopcount,
  		    ext_ftr_ptr + RIO_PORT_N_CTL_CSR(port_num), regval) < 0)
  			return -EIO;
  	}
  #endif
  	return 0;
  }
  
  /**
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
   * rio_setup_device- Allocates and sets up a RIO device
   * @net: RIO network
   * @port: Master port to send transactions
   * @destid: Current destination ID
   * @hopcount: Current hopcount
   * @do_enum: Enumeration/Discovery mode flag
   *
   * Allocates a RIO device and configures fields based on configuration
   * space contents. If device has a destination ID register, a destination
   * ID is either assigned in enumeration mode or read from configuration
   * space in discovery mode.  If the device has switch capabilities, then
   * a switch is allocated and configured appropriately. Returns a pointer
   * to a RIO device on success or NULL on failure.
   *
   */
181a6ff03   Li Yang   rapidio: fix sect...
368
  static struct rio_dev __devinit *rio_setup_device(struct rio_net *net,
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
369
370
371
  					struct rio_mport *port, u16 destid,
  					u8 hopcount, int do_enum)
  {
5f28c5200   Yang Li   rio: warn_unused_...
372
  	int ret = 0;
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
373
  	struct rio_dev *rdev;
5f28c5200   Yang Li   rio: warn_unused_...
374
  	struct rio_switch *rswitch = NULL;
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
375
  	int result, rdid;
ded057827   Alexandre Bounine   rapidio: integrat...
376
377
  	size_t size;
  	u32 swpinfo = 0;
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
378

ded057827   Alexandre Bounine   rapidio: integrat...
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
  	size = sizeof(struct rio_dev);
  	if (rio_mport_read_config_32(port, destid, hopcount,
  				     RIO_PEF_CAR, &result))
  		return NULL;
  
  	if (result & (RIO_PEF_SWITCH | RIO_PEF_MULTIPORT)) {
  		rio_mport_read_config_32(port, destid, hopcount,
  					 RIO_SWP_INFO_CAR, &swpinfo);
  		if (result & RIO_PEF_SWITCH) {
  			size += (RIO_GET_TOTAL_PORTS(swpinfo) *
  				sizeof(rswitch->nextdev[0])) + sizeof(*rswitch);
  		}
  	}
  
  	rdev = kzalloc(size, GFP_KERNEL);
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
394
  	if (!rdev)
5f28c5200   Yang Li   rio: warn_unused_...
395
  		return NULL;
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
396

eb188d0e8   Matt Porter   [PATCH] RapidIO s...
397
  	rdev->net = net;
ded057827   Alexandre Bounine   rapidio: integrat...
398
399
  	rdev->pef = result;
  	rdev->swpinfo = swpinfo;
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
400
401
402
403
404
405
406
407
408
409
410
411
412
  	rio_mport_read_config_32(port, destid, hopcount, RIO_DEV_ID_CAR,
  				 &result);
  	rdev->did = result >> 16;
  	rdev->vid = result & 0xffff;
  	rio_mport_read_config_32(port, destid, hopcount, RIO_DEV_INFO_CAR,
  				 &rdev->device_rev);
  	rio_mport_read_config_32(port, destid, hopcount, RIO_ASM_ID_CAR,
  				 &result);
  	rdev->asm_did = result >> 16;
  	rdev->asm_vid = result & 0xffff;
  	rio_mport_read_config_32(port, destid, hopcount, RIO_ASM_INFO_CAR,
  				 &result);
  	rdev->asm_rev = result >> 16;
e5cabeb3d   Alexandre Bounine   rapidio: add Port...
413
  	if (rdev->pef & RIO_PEF_EXT_FEATURES) {
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
414
  		rdev->efptr = result & 0xffff;
e5cabeb3d   Alexandre Bounine   rapidio: add Port...
415
416
417
418
419
420
  		rdev->phys_efptr = rio_mport_get_physefb(port, 0, destid,
  							 hopcount);
  
  		rdev->em_efptr = rio_mport_get_feature(port, 0, destid,
  						hopcount, RIO_EFB_ERR_MGMNT);
  	}
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
421
422
423
424
425
  
  	rio_mport_read_config_32(port, destid, hopcount, RIO_SRC_OPS_CAR,
  				 &rdev->src_ops);
  	rio_mport_read_config_32(port, destid, hopcount, RIO_DST_OPS_CAR,
  				 &rdev->dst_ops);
af84ca38a   Alexandre Bounine   rapidio: add hand...
426
427
428
429
430
431
432
433
434
435
  	if (do_enum) {
  		/* Assign component tag to device */
  		if (next_comptag >= 0x10000) {
  			pr_err("RIO: Component Tag Counter Overflow
  ");
  			goto cleanup;
  		}
  		rio_mport_write_config_32(port, destid, hopcount,
  					  RIO_COMPONENT_TAG_CSR, next_comptag);
  		rdev->comp_tag = next_comptag++;
558bda657   Alexandre Bounine   rapidio: use Comp...
436
437
438
439
  	}  else {
  		rio_mport_read_config_32(port, destid, hopcount,
  					 RIO_COMPONENT_TAG_CSR,
  					 &rdev->comp_tag);
af84ca38a   Alexandre Bounine   rapidio: add hand...
440
  	}
c70555b05   Alexandre Bounine   [PATCH] rapidio: ...
441
442
443
444
445
446
447
448
  	if (rio_device_has_destid(port, rdev->src_ops, rdev->dst_ops)) {
  		if (do_enum) {
  			rio_set_device_id(port, destid, hopcount, next_destid);
  			rdev->destid = next_destid++;
  			if (next_destid == port->host_deviceid)
  				next_destid++;
  		} else
  			rdev->destid = rio_get_device_id(port, destid, hopcount);
a93192a5d   Alexandre Bounine   rapidio: use comm...
449
450
451
452
453
454
455
456
457
  
  		rdev->hopcount = 0xff;
  	} else {
  		/* Switch device has an associated destID which
  		 * will be adjusted later
  		 */
  		rdev->destid = destid;
  		rdev->hopcount = hopcount;
  	}
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
458
459
460
  
  	/* If a PE has both switch and other functions, show it as a switch */
  	if (rio_is_switch(rdev)) {
ded057827   Alexandre Bounine   rapidio: integrat...
461
  		rswitch = rdev->rswitch;
558bda657   Alexandre Bounine   rapidio: use Comp...
462
  		rswitch->switchid = rdev->comp_tag & RIO_CTAG_UDEVID;
e5cabeb3d   Alexandre Bounine   rapidio: add Port...
463
  		rswitch->port_ok = 0;
e04232360   Zhang Wei   [RAPIDIO] Auto-pr...
464
465
466
  		rswitch->route_table = kzalloc(sizeof(u8)*
  					RIO_MAX_ROUTE_ENTRIES(port->sys_size),
  					GFP_KERNEL);
5f28c5200   Yang Li   rio: warn_unused_...
467
468
  		if (!rswitch->route_table)
  			goto cleanup;
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
469
  		/* Initialize switch route table */
e04232360   Zhang Wei   [RAPIDIO] Auto-pr...
470
471
  		for (rdid = 0; rdid < RIO_MAX_ROUTE_ENTRIES(port->sys_size);
  				rdid++)
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
472
  			rswitch->route_table[rdid] = RIO_INVALID_ROUTE;
b53c7583e   Kay Sievers   rapidio: struct d...
473
  		dev_set_name(&rdev->dev, "%02x:s:%04x", rdev->net->id,
ded057827   Alexandre Bounine   rapidio: integrat...
474
  			     rswitch->switchid);
058f88d67   Alexandre Bounine   rapidio: modify i...
475
  		rio_switch_init(rdev, do_enum);
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
476

ded057827   Alexandre Bounine   rapidio: integrat...
477
478
479
  		if (do_enum && rswitch->clr_table)
  			rswitch->clr_table(port, destid, hopcount,
  					   RIO_GLOBAL_TABLE);
07590ff03   Alexandre Bounine   rapidio: add IDT ...
480

eb188d0e8   Matt Porter   [PATCH] RapidIO s...
481
  		list_add_tail(&rswitch->node, &rio_switches);
933af4a6c   Thomas Moll   rapidio: add enab...
482
483
484
485
  	} else {
  		if (do_enum)
  			/*Enable Input Output Port (transmitter reviever)*/
  			rio_enable_rx_tx_port(port, 0, destid, hopcount, 0);
b53c7583e   Kay Sievers   rapidio: struct d...
486
487
  		dev_set_name(&rdev->dev, "%02x:e:%04x", rdev->net->id,
  			     rdev->destid);
933af4a6c   Thomas Moll   rapidio: add enab...
488
  	}
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
489
490
  
  	rdev->dev.bus = &rio_bus_type;
2c70f022e   Alexandre Bounine   rapidio: fix Rapi...
491
  	rdev->dev.parent = &rio_bus;
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
492
493
494
495
  
  	device_initialize(&rdev->dev);
  	rdev->dev.release = rio_release_dev;
  	rio_dev_get(rdev);
284901a90   Yang Hongyang   dma-mapping: repl...
496
  	rdev->dma_mask = DMA_BIT_MASK(32);
fa78cc517   Matt Porter   [PATCH] rapidio: ...
497
  	rdev->dev.dma_mask = &rdev->dma_mask;
284901a90   Yang Hongyang   dma-mapping: repl...
498
  	rdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
499

284fb68d0   Alexandre Bounine   rapidio: fix use ...
500
  	if (rdev->dst_ops & RIO_DST_OPS_DOORBELL)
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
501
502
  		rio_init_dbell_res(&rdev->riores[RIO_DOORBELL_RESOURCE],
  				   0, 0xffff);
5f28c5200   Yang Li   rio: warn_unused_...
503
504
505
  	ret = rio_add_device(rdev);
  	if (ret)
  		goto cleanup;
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
506

eb188d0e8   Matt Porter   [PATCH] RapidIO s...
507
  	return rdev;
5f28c5200   Yang Li   rio: warn_unused_...
508
509
  
  cleanup:
ad4ac17ad   Dan Carpenter   rapidio: fix pote...
510
  	if (rio_is_switch(rdev))
5f28c5200   Yang Li   rio: warn_unused_...
511
  		kfree(rswitch->route_table);
ded057827   Alexandre Bounine   rapidio: integrat...
512

5f28c5200   Yang Li   rio: warn_unused_...
513
514
  	kfree(rdev);
  	return NULL;
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
515
516
517
518
519
520
521
522
523
524
525
  }
  
  /**
   * rio_sport_is_active- Tests if a switch port has an active connection.
   * @port: Master port to send transaction
   * @destid: Associated destination ID for switch
   * @hopcount: Hopcount to reach switch
   * @sport: Switch port number
   *
   * Reads the port error status CSR for a particular switch port to
   * determine if the port has an active link.  Returns
e5cabeb3d   Alexandre Bounine   rapidio: add Port...
526
   * %RIO_PORT_N_ERR_STS_PORT_OK if the port is active or %0 if it is
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
527
528
529
530
531
   * inactive.
   */
  static int
  rio_sport_is_active(struct rio_mport *port, u16 destid, u8 hopcount, int sport)
  {
e5cabeb3d   Alexandre Bounine   rapidio: add Port...
532
  	u32 result = 0;
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
533
  	u32 ext_ftr_ptr;
e5cabeb3d   Alexandre Bounine   rapidio: add Port...
534
  	ext_ftr_ptr = rio_mport_get_efb(port, 0, destid, hopcount, 0);
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
535

e5cabeb3d   Alexandre Bounine   rapidio: add Port...
536
537
538
539
540
541
542
  	while (ext_ftr_ptr) {
  		rio_mport_read_config_32(port, destid, hopcount,
  					 ext_ftr_ptr, &result);
  		result = RIO_GET_BLOCK_ID(result);
  		if ((result == RIO_EFB_SER_EP_FREE_ID) ||
  		    (result == RIO_EFB_SER_EP_FREE_ID_V13P) ||
  		    (result == RIO_EFB_SER_EP_FREC_ID))
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
543
  			break;
e5cabeb3d   Alexandre Bounine   rapidio: add Port...
544
545
546
547
  
  		ext_ftr_ptr = rio_mport_get_efb(port, 0, destid, hopcount,
  						ext_ftr_ptr);
  	}
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
548
549
550
551
552
553
  
  	if (ext_ftr_ptr)
  		rio_mport_read_config_32(port, destid, hopcount,
  					 ext_ftr_ptr +
  					 RIO_PORT_N_ERR_STS_CSR(sport),
  					 &result);
e5cabeb3d   Alexandre Bounine   rapidio: add Port...
554
  	return result & RIO_PORT_N_ERR_STS_PORT_OK;
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
555
556
557
  }
  
  /**
818a04a0b   Alexandre Bounine   rapidio: add swit...
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
   * rio_lock_device - Acquires host device lock for specified device
   * @port: Master port to send transaction
   * @destid: Destination ID for device/switch
   * @hopcount: Hopcount to reach switch
   * @wait_ms: Max wait time in msec (0 = no timeout)
   *
   * Attepts to acquire host device lock for specified device
   * Returns 0 if device lock acquired or EINVAL if timeout expires.
   */
  static int
  rio_lock_device(struct rio_mport *port, u16 destid, u8 hopcount, int wait_ms)
  {
  	u32 result;
  	int tcnt = 0;
  
  	/* Attempt to acquire device lock */
  	rio_mport_write_config_32(port, destid, hopcount,
  				  RIO_HOST_DID_LOCK_CSR, port->host_deviceid);
  	rio_mport_read_config_32(port, destid, hopcount,
  				 RIO_HOST_DID_LOCK_CSR, &result);
  
  	while (result != port->host_deviceid) {
  		if (wait_ms != 0 && tcnt == wait_ms) {
  			pr_debug("RIO: timeout when locking device %x:%x
  ",
  				destid, hopcount);
  			return -EINVAL;
  		}
  
  		/* Delay a bit */
  		mdelay(1);
  		tcnt++;
  		/* Try to acquire device lock again */
  		rio_mport_write_config_32(port, destid,
  			hopcount,
  			RIO_HOST_DID_LOCK_CSR,
  			port->host_deviceid);
  		rio_mport_read_config_32(port, destid,
  			hopcount,
  			RIO_HOST_DID_LOCK_CSR, &result);
  	}
  
  	return 0;
  }
  
  /**
   * rio_unlock_device - Releases host device lock for specified device
   * @port: Master port to send transaction
   * @destid: Destination ID for device/switch
   * @hopcount: Hopcount to reach switch
   *
   * Returns 0 if device lock released or EINVAL if fails.
   */
  static int
  rio_unlock_device(struct rio_mport *port, u16 destid, u8 hopcount)
  {
  	u32 result;
  
  	/* Release device lock */
  	rio_mport_write_config_32(port, destid,
  				  hopcount,
  				  RIO_HOST_DID_LOCK_CSR,
  				  port->host_deviceid);
  	rio_mport_read_config_32(port, destid, hopcount,
  		RIO_HOST_DID_LOCK_CSR, &result);
  	if ((result & 0xffff) != 0xffff) {
  		pr_debug("RIO: badness when releasing device lock %x:%x
  ",
  			 destid, hopcount);
  		return -EINVAL;
  	}
  
  	return 0;
  }
  
  /**
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
634
   * rio_route_add_entry- Add a route entry to a switch routing table
a93192a5d   Alexandre Bounine   rapidio: use comm...
635
   * @rdev: RIO device
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
636
637
638
   * @table: Routing table ID
   * @route_destid: Destination ID to be routed
   * @route_port: Port number to be routed
818a04a0b   Alexandre Bounine   rapidio: add swit...
639
   * @lock: lock switch device flag
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
640
641
642
643
644
645
646
647
   *
   * Calls the switch specific add_entry() method to add a route entry
   * on a switch. The route table can be specified using the @table
   * argument if a switch has per port routing tables or the normal
   * use is to specific all tables (or the global table) by passing
   * %RIO_GLOBAL_TABLE in @table. Returns %0 on success or %-EINVAL
   * on failure.
   */
818a04a0b   Alexandre Bounine   rapidio: add swit...
648
  static int
a93192a5d   Alexandre Bounine   rapidio: use comm...
649
  rio_route_add_entry(struct rio_dev *rdev,
818a04a0b   Alexandre Bounine   rapidio: add swit...
650
  		    u16 table, u16 route_destid, u8 route_port, int lock)
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
651
  {
818a04a0b   Alexandre Bounine   rapidio: add swit...
652
653
654
  	int rc;
  
  	if (lock) {
a93192a5d   Alexandre Bounine   rapidio: use comm...
655
656
  		rc = rio_lock_device(rdev->net->hport, rdev->destid,
  				     rdev->hopcount, 1000);
818a04a0b   Alexandre Bounine   rapidio: add swit...
657
658
659
  		if (rc)
  			return rc;
  	}
a93192a5d   Alexandre Bounine   rapidio: use comm...
660
661
662
  	rc = rdev->rswitch->add_entry(rdev->net->hport, rdev->destid,
  				      rdev->hopcount, table,
  				      route_destid, route_port);
818a04a0b   Alexandre Bounine   rapidio: add swit...
663
  	if (lock)
a93192a5d   Alexandre Bounine   rapidio: use comm...
664
665
  		rio_unlock_device(rdev->net->hport, rdev->destid,
  				  rdev->hopcount);
818a04a0b   Alexandre Bounine   rapidio: add swit...
666
667
  
  	return rc;
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
668
669
670
671
  }
  
  /**
   * rio_route_get_entry- Read a route entry in a switch routing table
a93192a5d   Alexandre Bounine   rapidio: use comm...
672
   * @rdev: RIO device
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
673
674
675
   * @table: Routing table ID
   * @route_destid: Destination ID to be routed
   * @route_port: Pointer to read port number into
818a04a0b   Alexandre Bounine   rapidio: add swit...
676
   * @lock: lock switch device flag
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
677
678
679
680
681
682
683
684
685
   *
   * Calls the switch specific get_entry() method to read a route entry
   * in a switch. The route table can be specified using the @table
   * argument if a switch has per port routing tables or the normal
   * use is to specific all tables (or the global table) by passing
   * %RIO_GLOBAL_TABLE in @table. Returns %0 on success or %-EINVAL
   * on failure.
   */
  static int
a93192a5d   Alexandre Bounine   rapidio: use comm...
686
  rio_route_get_entry(struct rio_dev *rdev, u16 table,
818a04a0b   Alexandre Bounine   rapidio: add swit...
687
  		    u16 route_destid, u8 *route_port, int lock)
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
688
  {
818a04a0b   Alexandre Bounine   rapidio: add swit...
689
690
691
  	int rc;
  
  	if (lock) {
a93192a5d   Alexandre Bounine   rapidio: use comm...
692
693
  		rc = rio_lock_device(rdev->net->hport, rdev->destid,
  				     rdev->hopcount, 1000);
818a04a0b   Alexandre Bounine   rapidio: add swit...
694
695
696
  		if (rc)
  			return rc;
  	}
a93192a5d   Alexandre Bounine   rapidio: use comm...
697
698
699
  	rc = rdev->rswitch->get_entry(rdev->net->hport, rdev->destid,
  				      rdev->hopcount, table,
  				      route_destid, route_port);
818a04a0b   Alexandre Bounine   rapidio: add swit...
700
  	if (lock)
a93192a5d   Alexandre Bounine   rapidio: use comm...
701
702
  		rio_unlock_device(rdev->net->hport, rdev->destid,
  				  rdev->hopcount);
818a04a0b   Alexandre Bounine   rapidio: add swit...
703
704
  
  	return rc;
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
705
706
707
708
709
710
711
712
713
714
715
716
717
  }
  
  /**
   * rio_get_host_deviceid_lock- Reads the Host Device ID Lock CSR on a device
   * @port: Master port to send transaction
   * @hopcount: Number of hops to the device
   *
   * Used during enumeration to read the Host Device ID Lock CSR on a
   * RIO device. Returns the value of the lock register.
   */
  static u16 rio_get_host_deviceid_lock(struct rio_mport *port, u8 hopcount)
  {
  	u32 result;
e04232360   Zhang Wei   [RAPIDIO] Auto-pr...
718
  	rio_mport_read_config_32(port, RIO_ANY_DESTID(port->sys_size), hopcount,
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
719
720
721
722
723
724
  				 RIO_HOST_DID_LOCK_CSR, &result);
  
  	return (u16) (result & 0xffff);
  }
  
  /**
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
725
726
727
728
   * rio_enum_peer- Recursively enumerate a RIO network through a master port
   * @net: RIO network being enumerated
   * @port: Master port to send transactions
   * @hopcount: Number of hops into the network
68fe4df5d   Alexandre Bounine   rapidio: add rela...
729
730
   * @prev: Previous RIO device connected to the enumerated one
   * @prev_port: Port on previous RIO device
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
731
732
733
734
   *
   * Recursively enumerates a RIO network.  Transactions are sent via the
   * master port passed in @port.
   */
181a6ff03   Li Yang   rapidio: fix sect...
735
  static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port,
68fe4df5d   Alexandre Bounine   rapidio: add rela...
736
  			 u8 hopcount, struct rio_dev *prev, int prev_port)
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
737
738
  {
  	int port_num;
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
739
  	int cur_destid;
c70555b05   Alexandre Bounine   [PATCH] rapidio: ...
740
741
  	int sw_destid;
  	int sw_inport;
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
742
743
  	struct rio_dev *rdev;
  	u16 destid;
af84ca38a   Alexandre Bounine   rapidio: add hand...
744
  	u32 regval;
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
745
  	int tmp;
e274e0ed0   Alexandre Bounine   rapidio: add devi...
746
747
748
749
750
751
  	if (rio_mport_chk_dev_access(port,
  			RIO_ANY_DESTID(port->sys_size), hopcount)) {
  		pr_debug("RIO: device access check failed
  ");
  		return -1;
  	}
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
752
753
754
755
756
  	if (rio_get_host_deviceid_lock(port, hopcount) == port->host_deviceid) {
  		pr_debug("RIO: PE already discovered by this host
  ");
  		/*
  		 * Already discovered by this host. Add it as another
af84ca38a   Alexandre Bounine   rapidio: add hand...
757
  		 * link to the existing device.
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
758
  		 */
af84ca38a   Alexandre Bounine   rapidio: add hand...
759
760
761
762
763
764
765
766
767
768
769
770
771
  		rio_mport_read_config_32(port, RIO_ANY_DESTID(port->sys_size),
  				hopcount, RIO_COMPONENT_TAG_CSR, &regval);
  
  		if (regval) {
  			rdev = rio_get_comptag((regval & 0xffff), NULL);
  
  			if (rdev && prev && rio_is_switch(prev)) {
  				pr_debug("RIO: redundant path to %s
  ",
  					 rio_name(rdev));
  				prev->rswitch->nextdev[prev_port] = rdev;
  			}
  		}
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
772
773
774
775
  		return 0;
  	}
  
  	/* Attempt to acquire device lock */
e04232360   Zhang Wei   [RAPIDIO] Auto-pr...
776
777
  	rio_mport_write_config_32(port, RIO_ANY_DESTID(port->sys_size),
  				  hopcount,
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
778
779
780
781
782
783
  				  RIO_HOST_DID_LOCK_CSR, port->host_deviceid);
  	while ((tmp = rio_get_host_deviceid_lock(port, hopcount))
  	       < port->host_deviceid) {
  		/* Delay a bit */
  		mdelay(1);
  		/* Attempt to acquire device lock again */
e04232360   Zhang Wei   [RAPIDIO] Auto-pr...
784
785
  		rio_mport_write_config_32(port, RIO_ANY_DESTID(port->sys_size),
  					  hopcount,
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
786
787
788
789
790
791
792
793
794
795
796
797
  					  RIO_HOST_DID_LOCK_CSR,
  					  port->host_deviceid);
  	}
  
  	if (rio_get_host_deviceid_lock(port, hopcount) > port->host_deviceid) {
  		pr_debug(
  		    "RIO: PE locked by a higher priority host...retreating
  ");
  		return -1;
  	}
  
  	/* Setup new RIO device */
e04232360   Zhang Wei   [RAPIDIO] Auto-pr...
798
799
800
  	rdev = rio_setup_device(net, port, RIO_ANY_DESTID(port->sys_size),
  					hopcount, 1);
  	if (rdev) {
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
801
802
  		/* Add device to the global and bus/net specific list. */
  		list_add_tail(&rdev->net_list, &net->devices);
68fe4df5d   Alexandre Bounine   rapidio: add rela...
803
804
805
  		rdev->prev = prev;
  		if (prev && rio_is_switch(prev))
  			prev->rswitch->nextdev[prev_port] = rdev;
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
806
807
808
809
  	} else
  		return -1;
  
  	if (rio_is_switch(rdev)) {
ae05cbd5a   Alexandre Bounine   rapidio: use stor...
810
  		sw_inport = RIO_GET_PORT_NUM(rdev->swpinfo);
a93192a5d   Alexandre Bounine   rapidio: use comm...
811
  		rio_route_add_entry(rdev, RIO_GLOBAL_TABLE,
818a04a0b   Alexandre Bounine   rapidio: add swit...
812
  				    port->host_deviceid, sw_inport, 0);
c70555b05   Alexandre Bounine   [PATCH] rapidio: ...
813
  		rdev->rswitch->route_table[port->host_deviceid] = sw_inport;
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
814
815
  
  		for (destid = 0; destid < next_destid; destid++) {
c70555b05   Alexandre Bounine   [PATCH] rapidio: ...
816
817
  			if (destid == port->host_deviceid)
  				continue;
a93192a5d   Alexandre Bounine   rapidio: use comm...
818
  			rio_route_add_entry(rdev, RIO_GLOBAL_TABLE,
818a04a0b   Alexandre Bounine   rapidio: add swit...
819
  					    destid, sw_inport, 0);
c70555b05   Alexandre Bounine   [PATCH] rapidio: ...
820
  			rdev->rswitch->route_table[destid] = sw_inport;
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
821
  		}
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
822
823
824
  		pr_debug(
  		    "RIO: found %s (vid %4.4x did %4.4x) with %d ports
  ",
68fe4df5d   Alexandre Bounine   rapidio: add rela...
825
826
  		    rio_name(rdev), rdev->vid, rdev->did,
  		    RIO_GET_TOTAL_PORTS(rdev->swpinfo));
c70555b05   Alexandre Bounine   [PATCH] rapidio: ...
827
  		sw_destid = next_destid;
68fe4df5d   Alexandre Bounine   rapidio: add rela...
828
829
830
  		for (port_num = 0;
  		     port_num < RIO_GET_TOTAL_PORTS(rdev->swpinfo);
  		     port_num++) {
933af4a6c   Thomas Moll   rapidio: add enab...
831
832
833
834
  			/*Enable Input Output Port (transmitter reviever)*/
  			rio_enable_rx_tx_port(port, 0,
  					      RIO_ANY_DESTID(port->sys_size),
  					      hopcount, port_num);
e5cabeb3d   Alexandre Bounine   rapidio: add Port...
835
836
  			if (sw_inport == port_num) {
  				rdev->rswitch->port_ok |= (1 << port_num);
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
837
  				continue;
e5cabeb3d   Alexandre Bounine   rapidio: add Port...
838
  			}
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
839
840
841
842
  
  			cur_destid = next_destid;
  
  			if (rio_sport_is_active
e04232360   Zhang Wei   [RAPIDIO] Auto-pr...
843
844
  			    (port, RIO_ANY_DESTID(port->sys_size), hopcount,
  			     port_num)) {
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
845
846
847
848
  				pr_debug(
  				    "RIO: scanning device on port %d
  ",
  				    port_num);
e5cabeb3d   Alexandre Bounine   rapidio: add Port...
849
  				rdev->rswitch->port_ok |= (1 << port_num);
a93192a5d   Alexandre Bounine   rapidio: use comm...
850
  				rio_route_add_entry(rdev, RIO_GLOBAL_TABLE,
e04232360   Zhang Wei   [RAPIDIO] Auto-pr...
851
  						RIO_ANY_DESTID(port->sys_size),
818a04a0b   Alexandre Bounine   rapidio: add swit...
852
  						port_num, 0);
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
853

68fe4df5d   Alexandre Bounine   rapidio: add rela...
854
855
  				if (rio_enum_peer(net, port, hopcount + 1,
  						  rdev, port_num) < 0)
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
856
857
858
859
860
861
  					return -1;
  
  				/* Update routing tables */
  				if (next_destid > cur_destid) {
  					for (destid = cur_destid;
  					     destid < next_destid; destid++) {
c70555b05   Alexandre Bounine   [PATCH] rapidio: ...
862
863
  						if (destid == port->host_deviceid)
  							continue;
a93192a5d   Alexandre Bounine   rapidio: use comm...
864
  						rio_route_add_entry(rdev,
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
865
866
  								    RIO_GLOBAL_TABLE,
  								    destid,
818a04a0b   Alexandre Bounine   rapidio: add swit...
867
868
  								    port_num,
  								    0);
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
869
870
871
872
  						rdev->rswitch->
  						    route_table[destid] =
  						    port_num;
  					}
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
873
  				}
e5cabeb3d   Alexandre Bounine   rapidio: add Port...
874
875
876
877
878
879
880
881
  			} else {
  				/* If switch supports Error Management,
  				 * set PORT_LOCKOUT bit for unused port
  				 */
  				if (rdev->em_efptr)
  					rio_set_port_lockout(rdev, port_num, 1);
  
  				rdev->rswitch->port_ok &= ~(1 << port_num);
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
882
883
  			}
  		}
c70555b05   Alexandre Bounine   [PATCH] rapidio: ...
884

e5cabeb3d   Alexandre Bounine   rapidio: add Port...
885
886
887
888
889
890
891
892
893
894
  		/* Direct Port-write messages to the enumeratiing host */
  		if ((rdev->src_ops & RIO_SRC_OPS_PORT_WRITE) &&
  		    (rdev->em_efptr)) {
  			rio_write_config_32(rdev,
  					rdev->em_efptr + RIO_EM_PW_TGT_DEVID,
  					(port->host_deviceid << 16) |
  					(port->sys_size << 15));
  		}
  
  		rio_init_em(rdev);
c70555b05   Alexandre Bounine   [PATCH] rapidio: ...
895
896
897
898
899
900
  		/* Check for empty switch */
  		if (next_destid == sw_destid) {
  			next_destid++;
  			if (next_destid == port->host_deviceid)
  				next_destid++;
  		}
a93192a5d   Alexandre Bounine   rapidio: use comm...
901
  		rdev->destid = sw_destid;
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
902
903
904
905
906
907
908
909
910
911
912
913
  	} else
  		pr_debug("RIO: found %s (vid %4.4x did %4.4x)
  ",
  		    rio_name(rdev), rdev->vid, rdev->did);
  
  	return 0;
  }
  
  /**
   * rio_enum_complete- Tests if enumeration of a network is complete
   * @port: Master port to send transaction
   *
e5cabeb3d   Alexandre Bounine   rapidio: add Port...
914
915
   * Tests the Component Tag CSR for non-zero value (enumeration
   * complete flag). Return %1 if enumeration is complete or %0 if
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
916
917
918
919
   * enumeration is incomplete.
   */
  static int rio_enum_complete(struct rio_mport *port)
  {
af84ca38a   Alexandre Bounine   rapidio: add hand...
920
  	u32 regval;
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
921

af84ca38a   Alexandre Bounine   rapidio: add hand...
922
923
924
  	rio_local_read_config_32(port, port->phys_efptr + RIO_PORT_GEN_CTL_CSR,
  				 &regval);
  	return (regval & RIO_PORT_GEN_MASTER) ? 1 : 0;
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
925
926
927
928
929
930
931
932
  }
  
  /**
   * rio_disc_peer- Recursively discovers a RIO network through a master port
   * @net: RIO network being discovered
   * @port: Master port to send transactions
   * @destid: Current destination ID in network
   * @hopcount: Number of hops into the network
9b310acc3   Randy Dunlap   rapidio: fix new ...
933
934
   * @prev: previous rio_dev
   * @prev_port: previous port number
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
935
936
937
938
   *
   * Recursively discovers a RIO network.  Transactions are sent via the
   * master port passed in @port.
   */
181a6ff03   Li Yang   rapidio: fix sect...
939
  static int __devinit
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
940
  rio_disc_peer(struct rio_net *net, struct rio_mport *port, u16 destid,
17e962056   Alexandre Bounine   rapidio: add devi...
941
  	      u8 hopcount, struct rio_dev *prev, int prev_port)
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
942
943
  {
  	u8 port_num, route_port;
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
944
945
946
947
948
949
950
  	struct rio_dev *rdev;
  	u16 ndestid;
  
  	/* Setup new RIO device */
  	if ((rdev = rio_setup_device(net, port, destid, hopcount, 0))) {
  		/* Add device to the global and bus/net specific list. */
  		list_add_tail(&rdev->net_list, &net->devices);
17e962056   Alexandre Bounine   rapidio: add devi...
951
952
953
  		rdev->prev = prev;
  		if (prev && rio_is_switch(prev))
  			prev->rswitch->nextdev[prev_port] = rdev;
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
954
955
956
957
  	} else
  		return -1;
  
  	if (rio_is_switch(rdev)) {
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
958
  		/* Associated destid is how we accessed this switch */
a93192a5d   Alexandre Bounine   rapidio: use comm...
959
  		rdev->destid = destid;
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
960

eb188d0e8   Matt Porter   [PATCH] RapidIO s...
961
962
963
  		pr_debug(
  		    "RIO: found %s (vid %4.4x did %4.4x) with %d ports
  ",
68fe4df5d   Alexandre Bounine   rapidio: add rela...
964
965
966
967
968
  		    rio_name(rdev), rdev->vid, rdev->did,
  		    RIO_GET_TOTAL_PORTS(rdev->swpinfo));
  		for (port_num = 0;
  		     port_num < RIO_GET_TOTAL_PORTS(rdev->swpinfo);
  		     port_num++) {
ae05cbd5a   Alexandre Bounine   rapidio: use stor...
969
  			if (RIO_GET_PORT_NUM(rdev->swpinfo) == port_num)
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
970
971
972
973
974
975
976
977
  				continue;
  
  			if (rio_sport_is_active
  			    (port, destid, hopcount, port_num)) {
  				pr_debug(
  				    "RIO: scanning device on port %d
  ",
  				    port_num);
818a04a0b   Alexandre Bounine   rapidio: add swit...
978
979
  
  				rio_lock_device(port, destid, hopcount, 1000);
e04232360   Zhang Wei   [RAPIDIO] Auto-pr...
980
981
  				for (ndestid = 0;
  				     ndestid < RIO_ANY_DESTID(port->sys_size);
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
982
  				     ndestid++) {
a93192a5d   Alexandre Bounine   rapidio: use comm...
983
  					rio_route_get_entry(rdev,
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
984
985
  							    RIO_GLOBAL_TABLE,
  							    ndestid,
818a04a0b   Alexandre Bounine   rapidio: add swit...
986
  							    &route_port, 0);
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
987
988
989
  					if (route_port == port_num)
  						break;
  				}
af84ca38a   Alexandre Bounine   rapidio: add hand...
990
991
  				if (ndestid == RIO_ANY_DESTID(port->sys_size))
  					continue;
818a04a0b   Alexandre Bounine   rapidio: add swit...
992
  				rio_unlock_device(port, destid, hopcount);
17e962056   Alexandre Bounine   rapidio: add devi...
993
994
  				if (rio_disc_peer(net, port, ndestid,
  					hopcount + 1, rdev, port_num) < 0)
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
  					return -1;
  			}
  		}
  	} else
  		pr_debug("RIO: found %s (vid %4.4x did %4.4x)
  ",
  		    rio_name(rdev), rdev->vid, rdev->did);
  
  	return 0;
  }
  
  /**
   * rio_mport_is_active- Tests if master port link is active
   * @port: Master port to test
   *
   * Reads the port error status CSR for the master port to
   * determine if the port has an active link.  Returns
e5cabeb3d   Alexandre Bounine   rapidio: add Port...
1012
   * %RIO_PORT_N_ERR_STS_PORT_OK if the  master port is active
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
   * or %0 if it is inactive.
   */
  static int rio_mport_is_active(struct rio_mport *port)
  {
  	u32 result = 0;
  	u32 ext_ftr_ptr;
  	int *entry = rio_mport_phys_table;
  
  	do {
  		if ((ext_ftr_ptr =
  		     rio_mport_get_feature(port, 1, 0, 0, *entry)))
  			break;
  	} while (*++entry >= 0);
  
  	if (ext_ftr_ptr)
  		rio_local_read_config_32(port,
  					 ext_ftr_ptr +
  					 RIO_PORT_N_ERR_STS_CSR(port->index),
  					 &result);
e5cabeb3d   Alexandre Bounine   rapidio: add Port...
1032
  	return result & RIO_PORT_N_ERR_STS_PORT_OK;
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
  }
  
  /**
   * rio_alloc_net- Allocate and configure a new RIO network
   * @port: Master port associated with the RIO network
   *
   * Allocates a RIO network structure, initializes per-network
   * list heads, and adds the associated master port to the
   * network list of associated master ports. Returns a
   * RIO network pointer on success or %NULL on failure.
   */
  static struct rio_net __devinit *rio_alloc_net(struct rio_mport *port)
  {
  	struct rio_net *net;
dd00cc486   Yoann Padioleau   some kmalloc/mems...
1047
  	net = kzalloc(sizeof(struct rio_net), GFP_KERNEL);
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
1048
  	if (net) {
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
  		INIT_LIST_HEAD(&net->node);
  		INIT_LIST_HEAD(&net->devices);
  		INIT_LIST_HEAD(&net->mports);
  		list_add_tail(&port->nnode, &net->mports);
  		net->hport = port;
  		net->id = next_net++;
  	}
  	return net;
  }
  
  /**
c70555b05   Alexandre Bounine   [PATCH] rapidio: ...
1060
1061
1062
1063
1064
1065
1066
1067
1068
   * rio_update_route_tables- Updates route tables in switches
   * @port: Master port associated with the RIO network
   *
   * For each enumerated device, ensure that each switch in a system
   * has correct routing entries. Add routes for devices that where
   * unknown dirung the first enumeration pass through the switch.
   */
  static void rio_update_route_tables(struct rio_mport *port)
  {
ded057827   Alexandre Bounine   rapidio: integrat...
1069
  	struct rio_dev *rdev, *swrdev;
c70555b05   Alexandre Bounine   [PATCH] rapidio: ...
1070
1071
1072
1073
1074
  	struct rio_switch *rswitch;
  	u8 sport;
  	u16 destid;
  
  	list_for_each_entry(rdev, &rio_devices, global_list) {
a93192a5d   Alexandre Bounine   rapidio: use comm...
1075
  		destid = rdev->destid;
c70555b05   Alexandre Bounine   [PATCH] rapidio: ...
1076
1077
1078
1079
1080
1081
1082
  
  		list_for_each_entry(rswitch, &rio_switches, node) {
  
  			if (rio_is_switch(rdev)	&& (rdev->rswitch == rswitch))
  				continue;
  
  			if (RIO_INVALID_ROUTE == rswitch->route_table[destid]) {
ded057827   Alexandre Bounine   rapidio: integrat...
1083
  				swrdev = sw_to_rio_dev(rswitch);
07590ff03   Alexandre Bounine   rapidio: add IDT ...
1084
  				/* Skip if destid ends in empty switch*/
ded057827   Alexandre Bounine   rapidio: integrat...
1085
  				if (swrdev->destid == destid)
07590ff03   Alexandre Bounine   rapidio: add IDT ...
1086
  					continue;
c70555b05   Alexandre Bounine   [PATCH] rapidio: ...
1087

ded057827   Alexandre Bounine   rapidio: integrat...
1088
  				sport = RIO_GET_PORT_NUM(swrdev->swpinfo);
c70555b05   Alexandre Bounine   [PATCH] rapidio: ...
1089
1090
  
  				if (rswitch->add_entry)	{
ded057827   Alexandre Bounine   rapidio: integrat...
1091
  					rio_route_add_entry(swrdev,
818a04a0b   Alexandre Bounine   rapidio: add swit...
1092
1093
  						RIO_GLOBAL_TABLE, destid,
  						sport, 0);
c70555b05   Alexandre Bounine   [PATCH] rapidio: ...
1094
1095
1096
1097
1098
1099
1100
1101
  					rswitch->route_table[destid] = sport;
  				}
  			}
  		}
  	}
  }
  
  /**
e5cabeb3d   Alexandre Bounine   rapidio: add Port...
1102
   * rio_init_em - Initializes RIO Error Management (for switches)
97ef6f744   Randy Dunlap   rapidio: fix new ...
1103
   * @rdev: RIO device
e5cabeb3d   Alexandre Bounine   rapidio: add Port...
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
   *
   * For each enumerated switch, call device-specific error management
   * initialization routine (if supplied by the switch driver).
   */
  static void rio_init_em(struct rio_dev *rdev)
  {
  	if (rio_is_switch(rdev) && (rdev->em_efptr) &&
  	    (rdev->rswitch->em_init)) {
  		rdev->rswitch->em_init(rdev);
  	}
  }
  
  /**
   * rio_pw_enable - Enables/disables port-write handling by a master port
   * @port: Master port associated with port-write handling
   * @enable:  1=enable,  0=disable
   */
  static void rio_pw_enable(struct rio_mport *port, int enable)
  {
  	if (port->ops->pwenable)
  		port->ops->pwenable(port, enable);
  }
  
  /**
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
1128
1129
1130
1131
1132
1133
1134
1135
   * rio_enum_mport- Start enumeration through a master port
   * @mport: Master port to send transactions
   *
   * Starts the enumeration process. If somebody has enumerated our
   * master port device, then give up. If not and we have an active
   * link, then start recursive peer enumeration. Returns %0 if
   * enumeration succeeds or %-EBUSY if enumeration fails.
   */
37d33d151   Al Viro   rapidio section n...
1136
  int __devinit rio_enum_mport(struct rio_mport *mport)
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
  {
  	struct rio_net *net = NULL;
  	int rc = 0;
  
  	printk(KERN_INFO "RIO: enumerate master port %d, %s
  ", mport->id,
  	       mport->name);
  	/* If somebody else enumerated our master port device, bail. */
  	if (rio_enum_host(mport) < 0) {
  		printk(KERN_INFO
  		       "RIO: master port %d device has been enumerated by a remote host
  ",
  		       mport->id);
  		rc = -EBUSY;
  		goto out;
  	}
  
  	/* If master port has an active link, allocate net and enum peers */
  	if (rio_mport_is_active(mport)) {
  		if (!(net = rio_alloc_net(mport))) {
  			printk(KERN_ERR "RIO: failed to allocate new net
  ");
  			rc = -ENOMEM;
  			goto out;
  		}
933af4a6c   Thomas Moll   rapidio: add enab...
1162
1163
1164
  
  		/* Enable Input Output Port (transmitter reviever) */
  		rio_enable_rx_tx_port(mport, 1, 0, 0, 0);
af84ca38a   Alexandre Bounine   rapidio: add hand...
1165
1166
1167
  		/* Set component tag for host */
  		rio_local_write_config_32(mport, RIO_COMPONENT_TAG_CSR,
  					  next_comptag++);
68fe4df5d   Alexandre Bounine   rapidio: add rela...
1168
  		if (rio_enum_peer(net, mport, 0, NULL, 0) < 0) {
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
1169
1170
1171
1172
1173
1174
1175
1176
1177
  			/* A higher priority host won enumeration, bail. */
  			printk(KERN_INFO
  			       "RIO: master port %d device has lost enumeration to a remote host
  ",
  			       mport->id);
  			rio_clear_locks(mport);
  			rc = -EBUSY;
  			goto out;
  		}
c70555b05   Alexandre Bounine   [PATCH] rapidio: ...
1178
  		rio_update_route_tables(mport);
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
1179
  		rio_clear_locks(mport);
e5cabeb3d   Alexandre Bounine   rapidio: add Port...
1180
  		rio_pw_enable(mport, 1);
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
  	} else {
  		printk(KERN_INFO "RIO: master port %d link inactive
  ",
  		       mport->id);
  		rc = -EINVAL;
  	}
  
        out:
  	return rc;
  }
  
  /**
   * rio_build_route_tables- Generate route tables from switch route entries
   *
   * For each switch device, generate a route table by copying existing
   * route entries from the switch.
   */
  static void rio_build_route_tables(void)
  {
  	struct rio_dev *rdev;
  	int i;
  	u8 sport;
  
  	list_for_each_entry(rdev, &rio_devices, global_list)
818a04a0b   Alexandre Bounine   rapidio: add swit...
1205
  		if (rio_is_switch(rdev)) {
a93192a5d   Alexandre Bounine   rapidio: use comm...
1206
1207
  			rio_lock_device(rdev->net->hport, rdev->destid,
  					rdev->hopcount, 1000);
818a04a0b   Alexandre Bounine   rapidio: add swit...
1208
1209
1210
  			for (i = 0;
  			     i < RIO_MAX_ROUTE_ENTRIES(rdev->net->hport->sys_size);
  			     i++) {
a93192a5d   Alexandre Bounine   rapidio: use comm...
1211
1212
  				if (rio_route_get_entry(rdev,
  					RIO_GLOBAL_TABLE, i, &sport, 0) < 0)
818a04a0b   Alexandre Bounine   rapidio: add swit...
1213
1214
1215
1216
1217
  					continue;
  				rdev->rswitch->route_table[i] = sport;
  			}
  
  			rio_unlock_device(rdev->net->hport,
a93192a5d   Alexandre Bounine   rapidio: use comm...
1218
1219
  					  rdev->destid,
  					  rdev->hopcount);
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
  		}
  }
  
  /**
   * rio_enum_timeout- Signal that enumeration timed out
   * @data: Address of timeout flag.
   *
   * When the enumeration complete timer expires, set a flag that
   * signals to the discovery process that enumeration did not
   * complete in a sane amount of time.
   */
  static void rio_enum_timeout(unsigned long data)
  {
  	/* Enumeration timed out, set flag */
  	*(int *)data = 1;
  }
  
  /**
   * rio_disc_mport- Start discovery through a master port
   * @mport: Master port to send transactions
   *
   * Starts the discovery process. If we have an active link,
   * then wait for the signal that enumeration is complete.
   * When enumeration completion is signaled, start recursive
   * peer discovery. Returns %0 if discovery succeeds or %-EBUSY
   * on failure.
   */
37d33d151   Al Viro   rapidio section n...
1247
  int __devinit rio_disc_mport(struct rio_mport *mport)
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
  {
  	struct rio_net *net = NULL;
  	int enum_timeout_flag = 0;
  
  	printk(KERN_INFO "RIO: discover master port %d, %s
  ", mport->id,
  	       mport->name);
  
  	/* If master port has an active link, allocate net and discover peers */
  	if (rio_mport_is_active(mport)) {
  		if (!(net = rio_alloc_net(mport))) {
  			printk(KERN_ERR "RIO: Failed to allocate new net
  ");
  			goto bail;
  		}
  
  		pr_debug("RIO: wait for enumeration complete...");
  
  		rio_enum_timer.expires =
  		    jiffies + CONFIG_RAPIDIO_DISC_TIMEOUT * HZ;
  		rio_enum_timer.data = (unsigned long)&enum_timeout_flag;
  		add_timer(&rio_enum_timer);
  		while (!rio_enum_complete(mport)) {
  			mdelay(1);
  			if (enum_timeout_flag) {
  				del_timer_sync(&rio_enum_timer);
  				goto timeout;
  			}
  		}
  		del_timer_sync(&rio_enum_timer);
  
  		pr_debug("done
  ");
818a04a0b   Alexandre Bounine   rapidio: add swit...
1281
1282
1283
1284
1285
1286
  
  		/* Read DestID assigned by enumerator */
  		rio_local_read_config_32(mport, RIO_DID_CSR,
  					 &mport->host_deviceid);
  		mport->host_deviceid = RIO_GET_DID(mport->sys_size,
  						   mport->host_deviceid);
e04232360   Zhang Wei   [RAPIDIO] Auto-pr...
1287
  		if (rio_disc_peer(net, mport, RIO_ANY_DESTID(mport->sys_size),
17e962056   Alexandre Bounine   rapidio: add devi...
1288
  					0, NULL, 0) < 0) {
eb188d0e8   Matt Porter   [PATCH] RapidIO s...
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
  			printk(KERN_INFO
  			       "RIO: master port %d device has failed discovery
  ",
  			       mport->id);
  			goto bail;
  		}
  
  		rio_build_route_tables();
  	}
  
  	return 0;
  
        timeout:
  	pr_debug("timeout
  ");
        bail:
  	return -EBUSY;
  }