diff options
| -rw-r--r-- | drivers/s390/crypto/ap_bus.c | 277 |
1 files changed, 160 insertions, 117 deletions
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c index 9f5a201c4c87..48ea0004a56d 100644 --- a/drivers/s390/crypto/ap_bus.c +++ b/drivers/s390/crypto/ap_bus.c | |||
| @@ -299,7 +299,7 @@ static int ap_query_queue(ap_qid_t qid, int *queue_depth, int *device_type, | |||
| 299 | ap_max_domain_id = 15; | 299 | ap_max_domain_id = 15; |
| 300 | switch (*device_type) { | 300 | switch (*device_type) { |
| 301 | /* For CEX2 and CEX3 the available functions | 301 | /* For CEX2 and CEX3 the available functions |
| 302 | * are not refrected by the facilities bits. | 302 | * are not reflected by the facilities bits. |
| 303 | * Instead it is coded into the type. So here | 303 | * Instead it is coded into the type. So here |
| 304 | * modify the function bits based on the type. | 304 | * modify the function bits based on the type. |
| 305 | */ | 305 | */ |
| @@ -1317,7 +1317,7 @@ static int ap_get_compatible_type(ap_qid_t qid, int rawtype, unsigned int func) | |||
| 1317 | } | 1317 | } |
| 1318 | 1318 | ||
| 1319 | /* | 1319 | /* |
| 1320 | * helper function to be used with bus_find_dev | 1320 | * Helper function to be used with bus_find_dev |
| 1321 | * matches for the card device with the given id | 1321 | * matches for the card device with the given id |
| 1322 | */ | 1322 | */ |
| 1323 | static int __match_card_device_with_id(struct device *dev, void *data) | 1323 | static int __match_card_device_with_id(struct device *dev, void *data) |
| @@ -1325,7 +1325,8 @@ static int __match_card_device_with_id(struct device *dev, void *data) | |||
| 1325 | return is_card_dev(dev) && to_ap_card(dev)->id == (int)(long) data; | 1325 | return is_card_dev(dev) && to_ap_card(dev)->id == (int)(long) data; |
| 1326 | } | 1326 | } |
| 1327 | 1327 | ||
| 1328 | /* helper function to be used with bus_find_dev | 1328 | /* |
| 1329 | * Helper function to be used with bus_find_dev | ||
| 1329 | * matches for the queue device with a given qid | 1330 | * matches for the queue device with a given qid |
| 1330 | */ | 1331 | */ |
| 1331 | static int __match_queue_device_with_qid(struct device *dev, void *data) | 1332 | static int __match_queue_device_with_qid(struct device *dev, void *data) |
| @@ -1333,143 +1334,185 @@ static int __match_queue_device_with_qid(struct device *dev, void *data) | |||
| 1333 | return is_queue_dev(dev) && to_ap_queue(dev)->qid == (int)(long) data; | 1334 | return is_queue_dev(dev) && to_ap_queue(dev)->qid == (int)(long) data; |
| 1334 | } | 1335 | } |
| 1335 | 1336 | ||
| 1336 | /** | 1337 | /* |
| 1337 | * ap_scan_bus(): Scan the AP bus for new devices | 1338 | * Helper function for ap_scan_bus(). |
| 1338 | * Runs periodically, workqueue timer (ap_config_time) | 1339 | * Does the scan bus job for the given adapter id. |
| 1339 | */ | 1340 | */ |
| 1340 | static void ap_scan_bus(struct work_struct *unused) | 1341 | static void _ap_scan_bus_adapter(int id) |
| 1341 | { | 1342 | { |
| 1342 | struct ap_queue *aq; | 1343 | ap_qid_t qid; |
| 1344 | unsigned int func; | ||
| 1343 | struct ap_card *ac; | 1345 | struct ap_card *ac; |
| 1344 | struct device *dev; | 1346 | struct device *dev; |
| 1345 | ap_qid_t qid; | 1347 | struct ap_queue *aq; |
| 1346 | int comp_type, depth = 0, type = 0; | 1348 | int rc, dom, depth, type, comp_type, borked; |
| 1347 | unsigned int func = 0; | 1349 | |
| 1348 | int rc, id, dom, borked, domains, defdomdevs = 0; | 1350 | /* check if there is a card device registered with this id */ |
| 1349 | 1351 | dev = bus_find_device(&ap_bus_type, NULL, | |
| 1350 | AP_DBF(DBF_DEBUG, "%s running\n", __func__); | 1352 | (void *)(long) id, |
| 1353 | __match_card_device_with_id); | ||
| 1354 | ac = dev ? to_ap_card(dev) : NULL; | ||
| 1355 | if (!ap_test_config_card_id(id)) { | ||
| 1356 | if (dev) { | ||
| 1357 | /* Card device has been removed from configuration */ | ||
| 1358 | bus_for_each_dev(&ap_bus_type, NULL, | ||
| 1359 | (void *)(long) id, | ||
| 1360 | __ap_queue_devices_with_id_unregister); | ||
| 1361 | device_unregister(dev); | ||
| 1362 | put_device(dev); | ||
| 1363 | } | ||
| 1364 | return; | ||
| 1365 | } | ||
| 1351 | 1366 | ||
| 1352 | ap_query_configuration(ap_configuration); | 1367 | /* |
| 1353 | ap_select_domain(); | 1368 | * This card id is enabled in the configuration. If we already have |
| 1369 | * a card device with this id, check if type and functions are still | ||
| 1370 | * the very same. Also verify that at least one queue is available. | ||
| 1371 | */ | ||
| 1372 | if (ac) { | ||
| 1373 | /* find the first valid queue */ | ||
| 1374 | for (dom = 0; dom < AP_DOMAINS; dom++) { | ||
| 1375 | qid = AP_MKQID(id, dom); | ||
| 1376 | if (ap_query_queue(qid, &depth, &type, &func) == 0) | ||
| 1377 | break; | ||
| 1378 | } | ||
| 1379 | borked = 0; | ||
| 1380 | if (dom >= AP_DOMAINS) { | ||
| 1381 | /* no accessible queue on this card */ | ||
| 1382 | borked = 1; | ||
| 1383 | } else if (ac->raw_hwtype != type) { | ||
| 1384 | /* card type has changed */ | ||
| 1385 | AP_DBF(DBF_INFO, "card=%02x type changed.\n", id); | ||
| 1386 | borked = 1; | ||
| 1387 | } else if (ac->functions != func) { | ||
| 1388 | /* card functions have changed */ | ||
| 1389 | AP_DBF(DBF_INFO, "card=%02x functions changed.\n", id); | ||
| 1390 | borked = 1; | ||
| 1391 | } | ||
| 1392 | if (borked) { | ||
| 1393 | /* unregister card device and associated queues */ | ||
| 1394 | bus_for_each_dev(&ap_bus_type, NULL, | ||
| 1395 | (void *)(long) id, | ||
| 1396 | __ap_queue_devices_with_id_unregister); | ||
| 1397 | device_unregister(dev); | ||
| 1398 | put_device(dev); | ||
| 1399 | /* go back if there is no valid queue on this card */ | ||
| 1400 | if (dom >= AP_DOMAINS) | ||
| 1401 | return; | ||
| 1402 | ac = NULL; | ||
| 1403 | } | ||
| 1404 | } | ||
| 1354 | 1405 | ||
| 1355 | for (id = 0; id < AP_DEVICES; id++) { | 1406 | /* |
| 1356 | /* check if device is registered */ | 1407 | * Go through all possible queue ids. Check and maybe create or release |
| 1408 | * queue devices for this card. If there exists no card device yet, | ||
| 1409 | * create a card device also. | ||
| 1410 | */ | ||
| 1411 | for (dom = 0; dom < AP_DOMAINS; dom++) { | ||
| 1412 | qid = AP_MKQID(id, dom); | ||
| 1357 | dev = bus_find_device(&ap_bus_type, NULL, | 1413 | dev = bus_find_device(&ap_bus_type, NULL, |
| 1358 | (void *)(long) id, | 1414 | (void *)(long) qid, |
| 1359 | __match_card_device_with_id); | 1415 | __match_queue_device_with_qid); |
| 1360 | ac = dev ? to_ap_card(dev) : NULL; | 1416 | aq = dev ? to_ap_queue(dev) : NULL; |
| 1361 | if (!ap_test_config_card_id(id)) { | 1417 | if (!ap_test_config_domain(dom)) { |
| 1362 | if (dev) { | 1418 | if (dev) { |
| 1363 | /* Card device has been removed from | 1419 | /* Queue device exists but has been |
| 1364 | * configuration, remove the belonging | 1420 | * removed from configuration. |
| 1365 | * queue devices. | ||
| 1366 | */ | 1421 | */ |
| 1367 | bus_for_each_dev(&ap_bus_type, NULL, | ||
| 1368 | (void *)(long) id, | ||
| 1369 | __ap_queue_devices_with_id_unregister); | ||
| 1370 | /* now remove the card device */ | ||
| 1371 | device_unregister(dev); | 1422 | device_unregister(dev); |
| 1372 | put_device(dev); | 1423 | put_device(dev); |
| 1373 | } | 1424 | } |
| 1374 | continue; | 1425 | continue; |
| 1375 | } | 1426 | } |
| 1376 | /* According to the configuration there should be a card | 1427 | /* try to fetch infos about this queue */ |
| 1377 | * device, so check if there is at least one valid queue | 1428 | rc = ap_query_queue(qid, &depth, &type, &func); |
| 1378 | * and maybe create queue devices and the card device. | 1429 | if (dev) { |
| 1379 | */ | 1430 | if (rc == -ENODEV) |
| 1380 | domains = 0; | 1431 | borked = 1; |
| 1381 | for (dom = 0; dom < AP_DOMAINS; dom++) { | 1432 | else { |
| 1382 | qid = AP_MKQID(id, dom); | ||
| 1383 | dev = bus_find_device(&ap_bus_type, NULL, | ||
| 1384 | (void *)(long) qid, | ||
| 1385 | __match_queue_device_with_qid); | ||
| 1386 | aq = dev ? to_ap_queue(dev) : NULL; | ||
| 1387 | if (!ap_test_config_domain(dom)) { | ||
| 1388 | if (dev) { | ||
| 1389 | /* Queue device exists but has been | ||
| 1390 | * removed from configuration. | ||
| 1391 | */ | ||
| 1392 | device_unregister(dev); | ||
| 1393 | put_device(dev); | ||
| 1394 | } | ||
| 1395 | continue; | ||
| 1396 | } | ||
| 1397 | rc = ap_query_queue(qid, &depth, &type, &func); | ||
| 1398 | if (dev) { | ||
| 1399 | spin_lock_bh(&aq->lock); | 1433 | spin_lock_bh(&aq->lock); |
| 1400 | if (rc == -ENODEV || | ||
| 1401 | /* adapter reconfiguration */ | ||
| 1402 | (ac && ac->functions != func)) | ||
| 1403 | aq->state = AP_STATE_BORKED; | ||
| 1404 | borked = aq->state == AP_STATE_BORKED; | 1434 | borked = aq->state == AP_STATE_BORKED; |
| 1405 | spin_unlock_bh(&aq->lock); | 1435 | spin_unlock_bh(&aq->lock); |
| 1406 | if (borked) /* Remove broken device */ | ||
| 1407 | device_unregister(dev); | ||
| 1408 | put_device(dev); | ||
| 1409 | if (!borked) { | ||
| 1410 | domains++; | ||
| 1411 | if (dom == ap_domain_index) | ||
| 1412 | defdomdevs++; | ||
| 1413 | continue; | ||
| 1414 | } | ||
| 1415 | } | ||
| 1416 | if (rc) | ||
| 1417 | continue; | ||
| 1418 | /* a new queue device is needed, check out comp type */ | ||
| 1419 | comp_type = ap_get_compatible_type(qid, type, func); | ||
| 1420 | if (!comp_type) | ||
| 1421 | continue; | ||
| 1422 | /* maybe a card device needs to be created first */ | ||
| 1423 | if (!ac) { | ||
| 1424 | ac = ap_card_create(id, depth, type, | ||
| 1425 | comp_type, func); | ||
| 1426 | if (!ac) | ||
| 1427 | continue; | ||
| 1428 | ac->ap_dev.device.bus = &ap_bus_type; | ||
| 1429 | ac->ap_dev.device.parent = ap_root_device; | ||
| 1430 | dev_set_name(&ac->ap_dev.device, | ||
| 1431 | "card%02x", id); | ||
| 1432 | /* Register card with AP bus */ | ||
| 1433 | rc = device_register(&ac->ap_dev.device); | ||
| 1434 | if (rc) { | ||
| 1435 | put_device(&ac->ap_dev.device); | ||
| 1436 | ac = NULL; | ||
| 1437 | break; | ||
| 1438 | } | ||
| 1439 | /* get it and thus adjust reference counter */ | ||
| 1440 | get_device(&ac->ap_dev.device); | ||
| 1441 | } | 1436 | } |
| 1442 | /* now create the new queue device */ | 1437 | if (borked) /* Remove broken device */ |
| 1443 | aq = ap_queue_create(qid, comp_type); | 1438 | device_unregister(dev); |
| 1444 | if (!aq) | 1439 | put_device(dev); |
| 1440 | continue; | ||
| 1441 | } | ||
| 1442 | if (rc) | ||
| 1443 | continue; | ||
| 1444 | /* a new queue device is needed, check out comp type */ | ||
| 1445 | comp_type = ap_get_compatible_type(qid, type, func); | ||
| 1446 | if (!comp_type) | ||
| 1447 | continue; | ||
| 1448 | /* maybe a card device needs to be created first */ | ||
| 1449 | if (!ac) { | ||
| 1450 | ac = ap_card_create(id, depth, type, comp_type, func); | ||
| 1451 | if (!ac) | ||
| 1445 | continue; | 1452 | continue; |
| 1446 | aq->card = ac; | 1453 | ac->ap_dev.device.bus = &ap_bus_type; |
| 1447 | aq->ap_dev.device.bus = &ap_bus_type; | 1454 | ac->ap_dev.device.parent = ap_root_device; |
| 1448 | aq->ap_dev.device.parent = &ac->ap_dev.device; | 1455 | dev_set_name(&ac->ap_dev.device, "card%02x", id); |
| 1449 | dev_set_name(&aq->ap_dev.device, | 1456 | /* Register card device with AP bus */ |
| 1450 | "%02x.%04x", id, dom); | 1457 | rc = device_register(&ac->ap_dev.device); |
| 1451 | /* Register device */ | ||
| 1452 | rc = device_register(&aq->ap_dev.device); | ||
| 1453 | if (rc) { | 1458 | if (rc) { |
| 1454 | put_device(&aq->ap_dev.device); | 1459 | put_device(&ac->ap_dev.device); |
| 1455 | continue; | 1460 | ac = NULL; |
| 1461 | break; | ||
| 1456 | } | 1462 | } |
| 1457 | domains++; | 1463 | /* get it and thus adjust reference counter */ |
| 1458 | if (dom == ap_domain_index) | 1464 | get_device(&ac->ap_dev.device); |
| 1459 | defdomdevs++; | 1465 | } |
| 1460 | } /* end domain loop */ | 1466 | /* now create the new queue device */ |
| 1461 | if (ac) { | 1467 | aq = ap_queue_create(qid, comp_type); |
| 1462 | /* remove card dev if there are no queue devices */ | 1468 | if (!aq) |
| 1463 | if (!domains) | 1469 | continue; |
| 1464 | device_unregister(&ac->ap_dev.device); | 1470 | aq->card = ac; |
| 1465 | put_device(&ac->ap_dev.device); | 1471 | aq->ap_dev.device.bus = &ap_bus_type; |
| 1472 | aq->ap_dev.device.parent = &ac->ap_dev.device; | ||
| 1473 | dev_set_name(&aq->ap_dev.device, "%02x.%04x", id, dom); | ||
| 1474 | /* Register queue device */ | ||
| 1475 | rc = device_register(&aq->ap_dev.device); | ||
| 1476 | if (rc) { | ||
| 1477 | put_device(&aq->ap_dev.device); | ||
| 1478 | continue; | ||
| 1466 | } | 1479 | } |
| 1467 | } /* end device loop */ | 1480 | } /* end domain loop */ |
| 1481 | |||
| 1482 | if (ac) | ||
| 1483 | put_device(&ac->ap_dev.device); | ||
| 1484 | } | ||
| 1468 | 1485 | ||
| 1469 | if (ap_domain_index >= 0 && defdomdevs < 1) | 1486 | /** |
| 1470 | AP_DBF(DBF_INFO, | 1487 | * ap_scan_bus(): Scan the AP bus for new devices |
| 1471 | "no queue device with default domain %d available\n", | 1488 | * Runs periodically, workqueue timer (ap_config_time) |
| 1472 | ap_domain_index); | 1489 | */ |
| 1490 | static void ap_scan_bus(struct work_struct *unused) | ||
| 1491 | { | ||
| 1492 | int id; | ||
| 1493 | |||
| 1494 | AP_DBF(DBF_DEBUG, "%s running\n", __func__); | ||
| 1495 | |||
| 1496 | ap_query_configuration(ap_configuration); | ||
| 1497 | ap_select_domain(); | ||
| 1498 | |||
| 1499 | /* loop over all possible adapters */ | ||
| 1500 | for (id = 0; id < AP_DEVICES; id++) | ||
| 1501 | _ap_scan_bus_adapter(id); | ||
| 1502 | |||
| 1503 | /* check if there is at least one queue available with default domain */ | ||
| 1504 | if (ap_domain_index >= 0) { | ||
| 1505 | struct device *dev = | ||
| 1506 | bus_find_device(&ap_bus_type, NULL, | ||
| 1507 | (void *)(long) ap_domain_index, | ||
| 1508 | __match_queue_device_with_qid); | ||
| 1509 | if (dev) | ||
| 1510 | put_device(dev); | ||
| 1511 | else | ||
| 1512 | AP_DBF(DBF_INFO, | ||
| 1513 | "no queue device with default domain %d available\n", | ||
| 1514 | ap_domain_index); | ||
| 1515 | } | ||
| 1473 | 1516 | ||
| 1474 | mod_timer(&ap_config_timer, jiffies + ap_config_time * HZ); | 1517 | mod_timer(&ap_config_timer, jiffies + ap_config_time * HZ); |
| 1475 | } | 1518 | } |
