Skip to content

Commit d38a87d

Browse files
hfreudehcahca
authored andcommitted
s390/ap: Support driver_override for AP queue devices
Add a new sysfs attribute driver_override the AP queue's directory. Writing in a string overrides the default driver determination and the drivers are matched against this string instead. This overrules the driver binding determined by the apmask/aqmask bitmask fields. According to the common understanding of how the driver_override behavior shall work, there is no further checking done. Neither about the string which is given as override driver nor if this device is currently in use by an mdev device. Another patch may limit this behavior to refuse a mixed usage of the driver_override and apmask/aqmask feature. As there exists some tooling for this kind of driver_override (see package driverctl) the AP bus behavior for re-binding should be compatible to this. The steps for a driver_override are: 1) unbind the current driver from the device. For example echo "17.0005" > /sys/devices/ap/card17/17.0005/driver/unbind 2) set the new driver for this device in the sysfs driver_override attribute. For example echo "vfio_ap" > /sys//devices/ap/card17/17.0005/driver_override 3) trigger a bus reprobe of this device. For example echo "17.0005" > /sys/bus/ap/drivers_probe With the driverctl package this is more comfortable and the settings get persisted: driverctl -b ap set-override 17.0005 vfio_ap and unset with driverctl -b ap unset-override 17.0005 Signed-off-by: Harald Freudenberger <freude@linux.ibm.com> Reviewed-by: Holger Dengler <dengler@linux.ibm.com> Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
1 parent 6917f43 commit d38a87d

3 files changed

Lines changed: 110 additions & 27 deletions

File tree

drivers/s390/crypto/ap_bus.c

Lines changed: 73 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -853,20 +853,38 @@ static int __ap_revise_reserved(struct device *dev, void *dummy)
853853
int rc, card, queue, devres, drvres;
854854

855855
if (is_queue_dev(dev)) {
856-
card = AP_QID_CARD(to_ap_queue(dev)->qid);
857-
queue = AP_QID_QUEUE(to_ap_queue(dev)->qid);
858-
mutex_lock(&ap_perms_mutex);
859-
devres = test_bit_inv(card, ap_perms.apm) &&
860-
test_bit_inv(queue, ap_perms.aqm);
861-
mutex_unlock(&ap_perms_mutex);
862-
drvres = to_ap_drv(dev->driver)->flags
863-
& AP_DRIVER_FLAG_DEFAULT;
864-
if (!!devres != !!drvres) {
865-
pr_debug("reprobing queue=%02x.%04x\n", card, queue);
866-
rc = device_reprobe(dev);
867-
if (rc)
868-
AP_DBF_WARN("%s reprobing queue=%02x.%04x failed\n",
869-
__func__, card, queue);
856+
struct ap_driver *ap_drv = to_ap_drv(dev->driver);
857+
struct ap_queue *aq = to_ap_queue(dev);
858+
struct ap_device *ap_dev = &aq->ap_dev;
859+
860+
card = AP_QID_CARD(aq->qid);
861+
queue = AP_QID_QUEUE(aq->qid);
862+
863+
if (ap_dev->driver_override) {
864+
if (strcmp(ap_dev->driver_override,
865+
ap_drv->driver.name)) {
866+
pr_debug("reprobing queue=%02x.%04x\n", card, queue);
867+
rc = device_reprobe(dev);
868+
if (rc) {
869+
AP_DBF_WARN("%s reprobing queue=%02x.%04x failed\n",
870+
__func__, card, queue);
871+
}
872+
}
873+
} else {
874+
mutex_lock(&ap_perms_mutex);
875+
devres = test_bit_inv(card, ap_perms.apm) &&
876+
test_bit_inv(queue, ap_perms.aqm);
877+
mutex_unlock(&ap_perms_mutex);
878+
drvres = to_ap_drv(dev->driver)->flags
879+
& AP_DRIVER_FLAG_DEFAULT;
880+
if (!!devres != !!drvres) {
881+
pr_debug("reprobing queue=%02x.%04x\n", card, queue);
882+
rc = device_reprobe(dev);
883+
if (rc) {
884+
AP_DBF_WARN("%s reprobing queue=%02x.%04x failed\n",
885+
__func__, card, queue);
886+
}
887+
}
870888
}
871889
}
872890

@@ -891,15 +909,30 @@ static void ap_bus_revise_bindings(void)
891909
*/
892910
int ap_owned_by_def_drv(int card, int queue)
893911
{
912+
struct ap_queue *aq;
894913
int rc = 0;
895914

896915
if (card < 0 || card >= AP_DEVICES || queue < 0 || queue >= AP_DOMAINS)
897916
return -EINVAL;
898917

918+
aq = ap_get_qdev(AP_MKQID(card, queue));
919+
if (aq) {
920+
const struct device_driver *drv = aq->ap_dev.device.driver;
921+
const struct ap_driver *ap_drv = to_ap_drv(drv);
922+
bool override = !!aq->ap_dev.driver_override;
923+
924+
if (override && drv && ap_drv->flags & AP_DRIVER_FLAG_DEFAULT)
925+
rc = 1;
926+
put_device(&aq->ap_dev.device);
927+
if (override)
928+
goto out;
929+
}
930+
899931
if (test_bit_inv(card, ap_perms.apm) &&
900932
test_bit_inv(queue, ap_perms.aqm))
901933
rc = 1;
902934

935+
out:
903936
return rc;
904937
}
905938
EXPORT_SYMBOL(ap_owned_by_def_drv);
@@ -922,12 +955,10 @@ int ap_apqn_in_matrix_owned_by_def_drv(unsigned long *apm,
922955
int card, queue, rc = 0;
923956

924957
for (card = 0; !rc && card < AP_DEVICES; card++)
925-
if (test_bit_inv(card, apm) &&
926-
test_bit_inv(card, ap_perms.apm))
958+
if (test_bit_inv(card, apm))
927959
for (queue = 0; !rc && queue < AP_DOMAINS; queue++)
928-
if (test_bit_inv(queue, aqm) &&
929-
test_bit_inv(queue, ap_perms.aqm))
930-
rc = 1;
960+
if (test_bit_inv(queue, aqm))
961+
rc = ap_owned_by_def_drv(card, queue);
931962

932963
return rc;
933964
}
@@ -951,13 +982,19 @@ static int ap_device_probe(struct device *dev)
951982
*/
952983
card = AP_QID_CARD(to_ap_queue(dev)->qid);
953984
queue = AP_QID_QUEUE(to_ap_queue(dev)->qid);
954-
mutex_lock(&ap_perms_mutex);
955-
devres = test_bit_inv(card, ap_perms.apm) &&
956-
test_bit_inv(queue, ap_perms.aqm);
957-
mutex_unlock(&ap_perms_mutex);
958-
drvres = ap_drv->flags & AP_DRIVER_FLAG_DEFAULT;
959-
if (!!devres != !!drvres)
960-
goto out;
985+
if (ap_dev->driver_override) {
986+
if (strcmp(ap_dev->driver_override,
987+
ap_drv->driver.name))
988+
goto out;
989+
} else {
990+
mutex_lock(&ap_perms_mutex);
991+
devres = test_bit_inv(card, ap_perms.apm) &&
992+
test_bit_inv(queue, ap_perms.aqm);
993+
mutex_unlock(&ap_perms_mutex);
994+
drvres = ap_drv->flags & AP_DRIVER_FLAG_DEFAULT;
995+
if (!!devres != !!drvres)
996+
goto out;
997+
}
961998
}
962999

9631000
/*
@@ -983,8 +1020,17 @@ static int ap_device_probe(struct device *dev)
9831020
}
9841021

9851022
out:
986-
if (rc)
1023+
if (rc) {
9871024
put_device(dev);
1025+
} else {
1026+
if (is_queue_dev(dev)) {
1027+
pr_debug("queue=%02x.%04x new driver=%s\n",
1028+
card, queue, ap_drv->driver.name);
1029+
} else {
1030+
pr_debug("card=%02x new driver=%s\n",
1031+
to_ap_card(dev)->id, ap_drv->driver.name);
1032+
}
1033+
}
9881034
return rc;
9891035
}
9901036

drivers/s390/crypto/ap_bus.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ void ap_driver_unregister(struct ap_driver *);
166166
struct ap_device {
167167
struct device device;
168168
int device_type; /* AP device type. */
169+
const char *driver_override;
169170
};
170171

171172
#define to_ap_dev(x) container_of((x), struct ap_device, device)

drivers/s390/crypto/ap_queue.c

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -731,6 +731,41 @@ static ssize_t ap_functions_show(struct device *dev,
731731

732732
static DEVICE_ATTR_RO(ap_functions);
733733

734+
static ssize_t driver_override_show(struct device *dev,
735+
struct device_attribute *attr,
736+
char *buf)
737+
{
738+
struct ap_queue *aq = to_ap_queue(dev);
739+
struct ap_device *ap_dev = &aq->ap_dev;
740+
int rc;
741+
742+
device_lock(dev);
743+
if (ap_dev->driver_override)
744+
rc = sysfs_emit(buf, "%s\n", ap_dev->driver_override);
745+
else
746+
rc = sysfs_emit(buf, "\n");
747+
device_unlock(dev);
748+
749+
return rc;
750+
}
751+
752+
static ssize_t driver_override_store(struct device *dev,
753+
struct device_attribute *attr,
754+
const char *buf, size_t count)
755+
{
756+
struct ap_queue *aq = to_ap_queue(dev);
757+
struct ap_device *ap_dev = &aq->ap_dev;
758+
int rc;
759+
760+
rc = driver_set_override(dev, &ap_dev->driver_override, buf, count);
761+
if (rc)
762+
return rc;
763+
764+
return count;
765+
}
766+
767+
static DEVICE_ATTR_RW(driver_override);
768+
734769
#ifdef CONFIG_AP_DEBUG
735770
static ssize_t states_show(struct device *dev,
736771
struct device_attribute *attr, char *buf)
@@ -843,6 +878,7 @@ static struct attribute *ap_queue_dev_attrs[] = {
843878
&dev_attr_config.attr,
844879
&dev_attr_chkstop.attr,
845880
&dev_attr_ap_functions.attr,
881+
&dev_attr_driver_override.attr,
846882
#ifdef CONFIG_AP_DEBUG
847883
&dev_attr_states.attr,
848884
&dev_attr_last_err_rc.attr,

0 commit comments

Comments
 (0)