diff options
Diffstat (limited to 'drivers/rapidio/rio.c')
-rw-r--r-- | drivers/rapidio/rio.c | 286 |
1 files changed, 239 insertions, 47 deletions
diff --git a/drivers/rapidio/rio.c b/drivers/rapidio/rio.c index cb1c08996fbb..b17d5218005e 100644 --- a/drivers/rapidio/rio.c +++ b/drivers/rapidio/rio.c | |||
@@ -7,7 +7,6 @@ | |||
7 | * | 7 | * |
8 | * Copyright 2009 Integrated Device Technology, Inc. | 8 | * Copyright 2009 Integrated Device Technology, Inc. |
9 | * Alex Bounine <alexandre.bounine@idt.com> | 9 | * Alex Bounine <alexandre.bounine@idt.com> |
10 | * - Added Port-Write/Error Management initialization and handling | ||
11 | * | 10 | * |
12 | * This program is free software; you can redistribute it and/or modify it | 11 | * This program is free software; you can redistribute it and/or modify it |
13 | * under the terms of the GNU General Public License as published by the | 12 | * under the terms of the GNU General Public License as published by the |
@@ -580,44 +579,6 @@ int rio_set_port_lockout(struct rio_dev *rdev, u32 pnum, int lock) | |||
580 | EXPORT_SYMBOL_GPL(rio_set_port_lockout); | 579 | EXPORT_SYMBOL_GPL(rio_set_port_lockout); |
581 | 580 | ||
582 | /** | 581 | /** |
583 | * rio_switch_init - Sets switch operations for a particular vendor switch | ||
584 | * @rdev: RIO device | ||
585 | * @do_enum: Enumeration/Discovery mode flag | ||
586 | * | ||
587 | * Searches the RIO switch ops table for known switch types. If the vid | ||
588 | * and did match a switch table entry, then call switch initialization | ||
589 | * routine to setup switch-specific routines. | ||
590 | */ | ||
591 | void rio_switch_init(struct rio_dev *rdev, int do_enum) | ||
592 | { | ||
593 | struct rio_switch_ops *cur = __start_rio_switch_ops; | ||
594 | struct rio_switch_ops *end = __end_rio_switch_ops; | ||
595 | |||
596 | while (cur < end) { | ||
597 | if ((cur->vid == rdev->vid) && (cur->did == rdev->did)) { | ||
598 | pr_debug("RIO: calling init routine for %s\n", | ||
599 | rio_name(rdev)); | ||
600 | cur->init_hook(rdev, do_enum); | ||
601 | break; | ||
602 | } | ||
603 | cur++; | ||
604 | } | ||
605 | |||
606 | if ((cur >= end) && (rdev->pef & RIO_PEF_STD_RT)) { | ||
607 | pr_debug("RIO: adding STD routing ops for %s\n", | ||
608 | rio_name(rdev)); | ||
609 | rdev->rswitch->add_entry = rio_std_route_add_entry; | ||
610 | rdev->rswitch->get_entry = rio_std_route_get_entry; | ||
611 | rdev->rswitch->clr_table = rio_std_route_clr_table; | ||
612 | } | ||
613 | |||
614 | if (!rdev->rswitch->add_entry || !rdev->rswitch->get_entry) | ||
615 | printk(KERN_ERR "RIO: missing routing ops for %s\n", | ||
616 | rio_name(rdev)); | ||
617 | } | ||
618 | EXPORT_SYMBOL_GPL(rio_switch_init); | ||
619 | |||
620 | /** | ||
621 | * rio_enable_rx_tx_port - enable input receiver and output transmitter of | 582 | * rio_enable_rx_tx_port - enable input receiver and output transmitter of |
622 | * given port | 583 | * given port |
623 | * @port: Master port associated with the RIO network | 584 | * @port: Master port associated with the RIO network |
@@ -970,8 +931,8 @@ int rio_inb_pwrite_handler(union rio_pw_msg *pw_msg) | |||
970 | /* | 931 | /* |
971 | * Process the port-write notification from switch | 932 | * Process the port-write notification from switch |
972 | */ | 933 | */ |
973 | if (rdev->rswitch->em_handle) | 934 | if (rdev->rswitch->ops && rdev->rswitch->ops->em_handle) |
974 | rdev->rswitch->em_handle(rdev, portnum); | 935 | rdev->rswitch->ops->em_handle(rdev, portnum); |
975 | 936 | ||
976 | rio_read_config_32(rdev, | 937 | rio_read_config_32(rdev, |
977 | rdev->phys_efptr + RIO_PORT_N_ERR_STS_CSR(portnum), | 938 | rdev->phys_efptr + RIO_PORT_N_ERR_STS_CSR(portnum), |
@@ -1207,8 +1168,9 @@ struct rio_dev *rio_get_device(u16 vid, u16 did, struct rio_dev *from) | |||
1207 | * @route_destid: destID entry in the RT | 1168 | * @route_destid: destID entry in the RT |
1208 | * @route_port: destination port for specified destID | 1169 | * @route_port: destination port for specified destID |
1209 | */ | 1170 | */ |
1210 | int rio_std_route_add_entry(struct rio_mport *mport, u16 destid, u8 hopcount, | 1171 | static int |
1211 | u16 table, u16 route_destid, u8 route_port) | 1172 | rio_std_route_add_entry(struct rio_mport *mport, u16 destid, u8 hopcount, |
1173 | u16 table, u16 route_destid, u8 route_port) | ||
1212 | { | 1174 | { |
1213 | if (table == RIO_GLOBAL_TABLE) { | 1175 | if (table == RIO_GLOBAL_TABLE) { |
1214 | rio_mport_write_config_32(mport, destid, hopcount, | 1176 | rio_mport_write_config_32(mport, destid, hopcount, |
@@ -1234,8 +1196,9 @@ int rio_std_route_add_entry(struct rio_mport *mport, u16 destid, u8 hopcount, | |||
1234 | * @route_destid: destID entry in the RT | 1196 | * @route_destid: destID entry in the RT |
1235 | * @route_port: returned destination port for specified destID | 1197 | * @route_port: returned destination port for specified destID |
1236 | */ | 1198 | */ |
1237 | int rio_std_route_get_entry(struct rio_mport *mport, u16 destid, u8 hopcount, | 1199 | static int |
1238 | u16 table, u16 route_destid, u8 *route_port) | 1200 | rio_std_route_get_entry(struct rio_mport *mport, u16 destid, u8 hopcount, |
1201 | u16 table, u16 route_destid, u8 *route_port) | ||
1239 | { | 1202 | { |
1240 | u32 result; | 1203 | u32 result; |
1241 | 1204 | ||
@@ -1259,8 +1222,9 @@ int rio_std_route_get_entry(struct rio_mport *mport, u16 destid, u8 hopcount, | |||
1259 | * @hopcount: Number of switch hops to the device | 1222 | * @hopcount: Number of switch hops to the device |
1260 | * @table: routing table ID (global or port-specific) | 1223 | * @table: routing table ID (global or port-specific) |
1261 | */ | 1224 | */ |
1262 | int rio_std_route_clr_table(struct rio_mport *mport, u16 destid, u8 hopcount, | 1225 | static int |
1263 | u16 table) | 1226 | rio_std_route_clr_table(struct rio_mport *mport, u16 destid, u8 hopcount, |
1227 | u16 table) | ||
1264 | { | 1228 | { |
1265 | u32 max_destid = 0xff; | 1229 | u32 max_destid = 0xff; |
1266 | u32 i, pef, id_inc = 1, ext_cfg = 0; | 1230 | u32 i, pef, id_inc = 1, ext_cfg = 0; |
@@ -1301,6 +1265,234 @@ int rio_std_route_clr_table(struct rio_mport *mport, u16 destid, u8 hopcount, | |||
1301 | return 0; | 1265 | return 0; |
1302 | } | 1266 | } |
1303 | 1267 | ||
1268 | /** | ||
1269 | * rio_lock_device - Acquires host device lock for specified device | ||
1270 | * @port: Master port to send transaction | ||
1271 | * @destid: Destination ID for device/switch | ||
1272 | * @hopcount: Hopcount to reach switch | ||
1273 | * @wait_ms: Max wait time in msec (0 = no timeout) | ||
1274 | * | ||
1275 | * Attepts to acquire host device lock for specified device | ||
1276 | * Returns 0 if device lock acquired or EINVAL if timeout expires. | ||
1277 | */ | ||
1278 | int rio_lock_device(struct rio_mport *port, u16 destid, | ||
1279 | u8 hopcount, int wait_ms) | ||
1280 | { | ||
1281 | u32 result; | ||
1282 | int tcnt = 0; | ||
1283 | |||
1284 | /* Attempt to acquire device lock */ | ||
1285 | rio_mport_write_config_32(port, destid, hopcount, | ||
1286 | RIO_HOST_DID_LOCK_CSR, port->host_deviceid); | ||
1287 | rio_mport_read_config_32(port, destid, hopcount, | ||
1288 | RIO_HOST_DID_LOCK_CSR, &result); | ||
1289 | |||
1290 | while (result != port->host_deviceid) { | ||
1291 | if (wait_ms != 0 && tcnt == wait_ms) { | ||
1292 | pr_debug("RIO: timeout when locking device %x:%x\n", | ||
1293 | destid, hopcount); | ||
1294 | return -EINVAL; | ||
1295 | } | ||
1296 | |||
1297 | /* Delay a bit */ | ||
1298 | mdelay(1); | ||
1299 | tcnt++; | ||
1300 | /* Try to acquire device lock again */ | ||
1301 | rio_mport_write_config_32(port, destid, | ||
1302 | hopcount, | ||
1303 | RIO_HOST_DID_LOCK_CSR, | ||
1304 | port->host_deviceid); | ||
1305 | rio_mport_read_config_32(port, destid, | ||
1306 | hopcount, | ||
1307 | RIO_HOST_DID_LOCK_CSR, &result); | ||
1308 | } | ||
1309 | |||
1310 | return 0; | ||
1311 | } | ||
1312 | EXPORT_SYMBOL_GPL(rio_lock_device); | ||
1313 | |||
1314 | /** | ||
1315 | * rio_unlock_device - Releases host device lock for specified device | ||
1316 | * @port: Master port to send transaction | ||
1317 | * @destid: Destination ID for device/switch | ||
1318 | * @hopcount: Hopcount to reach switch | ||
1319 | * | ||
1320 | * Returns 0 if device lock released or EINVAL if fails. | ||
1321 | */ | ||
1322 | int rio_unlock_device(struct rio_mport *port, u16 destid, u8 hopcount) | ||
1323 | { | ||
1324 | u32 result; | ||
1325 | |||
1326 | /* Release device lock */ | ||
1327 | rio_mport_write_config_32(port, destid, | ||
1328 | hopcount, | ||
1329 | RIO_HOST_DID_LOCK_CSR, | ||
1330 | port->host_deviceid); | ||
1331 | rio_mport_read_config_32(port, destid, hopcount, | ||
1332 | RIO_HOST_DID_LOCK_CSR, &result); | ||
1333 | if ((result & 0xffff) != 0xffff) { | ||
1334 | pr_debug("RIO: badness when releasing device lock %x:%x\n", | ||
1335 | destid, hopcount); | ||
1336 | return -EINVAL; | ||
1337 | } | ||
1338 | |||
1339 | return 0; | ||
1340 | } | ||
1341 | EXPORT_SYMBOL_GPL(rio_unlock_device); | ||
1342 | |||
1343 | /** | ||
1344 | * rio_route_add_entry- Add a route entry to a switch routing table | ||
1345 | * @rdev: RIO device | ||
1346 | * @table: Routing table ID | ||
1347 | * @route_destid: Destination ID to be routed | ||
1348 | * @route_port: Port number to be routed | ||
1349 | * @lock: apply a hardware lock on switch device flag (1=lock, 0=no_lock) | ||
1350 | * | ||
1351 | * If available calls the switch specific add_entry() method to add a route | ||
1352 | * entry into a switch routing table. Otherwise uses standard RT update method | ||
1353 | * as defined by RapidIO specification. A specific routing table can be selected | ||
1354 | * using the @table argument if a switch has per port routing tables or | ||
1355 | * the standard (or global) table may be used by passing | ||
1356 | * %RIO_GLOBAL_TABLE in @table. | ||
1357 | * | ||
1358 | * Returns %0 on success or %-EINVAL on failure. | ||
1359 | */ | ||
1360 | int rio_route_add_entry(struct rio_dev *rdev, | ||
1361 | u16 table, u16 route_destid, u8 route_port, int lock) | ||
1362 | { | ||
1363 | int rc = -EINVAL; | ||
1364 | struct rio_switch_ops *ops = rdev->rswitch->ops; | ||
1365 | |||
1366 | if (lock) { | ||
1367 | rc = rio_lock_device(rdev->net->hport, rdev->destid, | ||
1368 | rdev->hopcount, 1000); | ||
1369 | if (rc) | ||
1370 | return rc; | ||
1371 | } | ||
1372 | |||
1373 | spin_lock(&rdev->rswitch->lock); | ||
1374 | |||
1375 | if (ops == NULL || ops->add_entry == NULL) { | ||
1376 | rc = rio_std_route_add_entry(rdev->net->hport, rdev->destid, | ||
1377 | rdev->hopcount, table, | ||
1378 | route_destid, route_port); | ||
1379 | } else if (try_module_get(ops->owner)) { | ||
1380 | rc = ops->add_entry(rdev->net->hport, rdev->destid, | ||
1381 | rdev->hopcount, table, route_destid, | ||
1382 | route_port); | ||
1383 | module_put(ops->owner); | ||
1384 | } | ||
1385 | |||
1386 | spin_unlock(&rdev->rswitch->lock); | ||
1387 | |||
1388 | if (lock) | ||
1389 | rio_unlock_device(rdev->net->hport, rdev->destid, | ||
1390 | rdev->hopcount); | ||
1391 | |||
1392 | return rc; | ||
1393 | } | ||
1394 | EXPORT_SYMBOL_GPL(rio_route_add_entry); | ||
1395 | |||
1396 | /** | ||
1397 | * rio_route_get_entry- Read an entry from a switch routing table | ||
1398 | * @rdev: RIO device | ||
1399 | * @table: Routing table ID | ||
1400 | * @route_destid: Destination ID to be routed | ||
1401 | * @route_port: Pointer to read port number into | ||
1402 | * @lock: apply a hardware lock on switch device flag (1=lock, 0=no_lock) | ||
1403 | * | ||
1404 | * If available calls the switch specific get_entry() method to fetch a route | ||
1405 | * entry from a switch routing table. Otherwise uses standard RT read method | ||
1406 | * as defined by RapidIO specification. A specific routing table can be selected | ||
1407 | * using the @table argument if a switch has per port routing tables or | ||
1408 | * the standard (or global) table may be used by passing | ||
1409 | * %RIO_GLOBAL_TABLE in @table. | ||
1410 | * | ||
1411 | * Returns %0 on success or %-EINVAL on failure. | ||
1412 | */ | ||
1413 | int rio_route_get_entry(struct rio_dev *rdev, u16 table, | ||
1414 | u16 route_destid, u8 *route_port, int lock) | ||
1415 | { | ||
1416 | int rc = -EINVAL; | ||
1417 | struct rio_switch_ops *ops = rdev->rswitch->ops; | ||
1418 | |||
1419 | if (lock) { | ||
1420 | rc = rio_lock_device(rdev->net->hport, rdev->destid, | ||
1421 | rdev->hopcount, 1000); | ||
1422 | if (rc) | ||
1423 | return rc; | ||
1424 | } | ||
1425 | |||
1426 | spin_lock(&rdev->rswitch->lock); | ||
1427 | |||
1428 | if (ops == NULL || ops->get_entry == NULL) { | ||
1429 | rc = rio_std_route_get_entry(rdev->net->hport, rdev->destid, | ||
1430 | rdev->hopcount, table, | ||
1431 | route_destid, route_port); | ||
1432 | } else if (try_module_get(ops->owner)) { | ||
1433 | rc = ops->get_entry(rdev->net->hport, rdev->destid, | ||
1434 | rdev->hopcount, table, route_destid, | ||
1435 | route_port); | ||
1436 | module_put(ops->owner); | ||
1437 | } | ||
1438 | |||
1439 | spin_unlock(&rdev->rswitch->lock); | ||
1440 | |||
1441 | if (lock) | ||
1442 | rio_unlock_device(rdev->net->hport, rdev->destid, | ||
1443 | rdev->hopcount); | ||
1444 | return rc; | ||
1445 | } | ||
1446 | EXPORT_SYMBOL_GPL(rio_route_get_entry); | ||
1447 | |||
1448 | /** | ||
1449 | * rio_route_clr_table - Clear a switch routing table | ||
1450 | * @rdev: RIO device | ||
1451 | * @table: Routing table ID | ||
1452 | * @lock: apply a hardware lock on switch device flag (1=lock, 0=no_lock) | ||
1453 | * | ||
1454 | * If available calls the switch specific clr_table() method to clear a switch | ||
1455 | * routing table. Otherwise uses standard RT write method as defined by RapidIO | ||
1456 | * specification. A specific routing table can be selected using the @table | ||
1457 | * argument if a switch has per port routing tables or the standard (or global) | ||
1458 | * table may be used by passing %RIO_GLOBAL_TABLE in @table. | ||
1459 | * | ||
1460 | * Returns %0 on success or %-EINVAL on failure. | ||
1461 | */ | ||
1462 | int rio_route_clr_table(struct rio_dev *rdev, u16 table, int lock) | ||
1463 | { | ||
1464 | int rc = -EINVAL; | ||
1465 | struct rio_switch_ops *ops = rdev->rswitch->ops; | ||
1466 | |||
1467 | if (lock) { | ||
1468 | rc = rio_lock_device(rdev->net->hport, rdev->destid, | ||
1469 | rdev->hopcount, 1000); | ||
1470 | if (rc) | ||
1471 | return rc; | ||
1472 | } | ||
1473 | |||
1474 | spin_lock(&rdev->rswitch->lock); | ||
1475 | |||
1476 | if (ops == NULL || ops->clr_table == NULL) { | ||
1477 | rc = rio_std_route_clr_table(rdev->net->hport, rdev->destid, | ||
1478 | rdev->hopcount, table); | ||
1479 | } else if (try_module_get(ops->owner)) { | ||
1480 | rc = ops->clr_table(rdev->net->hport, rdev->destid, | ||
1481 | rdev->hopcount, table); | ||
1482 | |||
1483 | module_put(ops->owner); | ||
1484 | } | ||
1485 | |||
1486 | spin_unlock(&rdev->rswitch->lock); | ||
1487 | |||
1488 | if (lock) | ||
1489 | rio_unlock_device(rdev->net->hport, rdev->destid, | ||
1490 | rdev->hopcount); | ||
1491 | |||
1492 | return rc; | ||
1493 | } | ||
1494 | EXPORT_SYMBOL_GPL(rio_route_clr_table); | ||
1495 | |||
1304 | #ifdef CONFIG_RAPIDIO_DMA_ENGINE | 1496 | #ifdef CONFIG_RAPIDIO_DMA_ENGINE |
1305 | 1497 | ||
1306 | static bool rio_chan_filter(struct dma_chan *chan, void *arg) | 1498 | static bool rio_chan_filter(struct dma_chan *chan, void *arg) |