mirror of
https://github.com/torvalds/linux.git
synced 2024-11-22 12:11:40 +00:00
s390 updates for the 4.21 merge window
- A larger update for the zcrypt / AP bus code + Update two inline assemblies in the zcrypt driver to make gcc happy + Add a missing reply code for invalid special commands for zcrypt + Allow AP device reset to be triggered from user space + Split the AP scan function into smaller, more readable functions - Updates for vfio-ccw and vfio-ap + Add maintainers and reviewer for vfio-ccw + Include facility.h in vfio_ap_drv.c to avoid fragile include chain + Simplicy vfio-ccw state machine - Use the common code version of bust_spinlocks - Make use of the DEFINE_SHOW_ATTRIBUTE - Fix three incorrect file permissions in the DASD driver - Remove bit spin-lock from the PCI interrupt handler - Fix GFP_ATOMIC vs GFP_KERNEL in the PCI code -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQEcBAABCAAGBQJcLGoIAAoJEDjwexyKj9rgyN8IANaQvHbVBA3vz/Ssb6ZiR/K6 rTBoXjJQqyJ/cf6RZeFi1b4Douv4QWJw3s06KXbrdmK/ONm5rypXVfXlAhY71pg5 40BUb92MGXhJw6JFDQ50Udd6Z5r7r6RYR1puyg4tzHmBuNVL7FB5RqFm92UOkMOD ZI03G1sfA6/1XUKhNfCfNBB6Jt6V+iAAex8bgrp09wAeoGnAO20oFuis9u7pLlNm a5Cp9n7faXEN+qes1iBtVDr5o7opuhanwWKnhvsYTAbpOo7jGJ/47IPKT2Wfmurd wkMZBEC+Ntk/IfkaBzp7azeISZD5EbucTcgo/I9nzq/aWeflfXXeYl7My0aQB48= =Lqrh -----END PGP SIGNATURE----- Merge tag 's390-4.21-1' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux Pull s390 updates from Martin Schwidefsky: - A larger update for the zcrypt / AP bus code: + Update two inline assemblies in the zcrypt driver to make gcc happy + Add a missing reply code for invalid special commands for zcrypt + Allow AP device reset to be triggered from user space + Split the AP scan function into smaller, more readable functions - Updates for vfio-ccw and vfio-ap + Add maintainers and reviewer for vfio-ccw + Include facility.h in vfio_ap_drv.c to avoid fragile include chain + Simplicy vfio-ccw state machine - Use the common code version of bust_spinlocks - Make use of the DEFINE_SHOW_ATTRIBUTE - Fix three incorrect file permissions in the DASD driver - Remove bit spin-lock from the PCI interrupt handler - Fix GFP_ATOMIC vs GFP_KERNEL in the PCI code * tag 's390-4.21-1' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux: s390/zcrypt: rework ap scan bus code s390/zcrypt: make sysfs reset attribute trigger queue reset s390/pci: fix sleeping in atomic during hotplug s390/pci: remove bit_lock usage in interrupt handler s390/drivers: fix proc/debugfs file permissions s390: convert to DEFINE_SHOW_ATTRIBUTE MAINTAINERS/vfio-ccw: add Farhan and Eric, make Halil Reviewer vfio: ccw: Merge BUSY and BOXED states s390: use common bust_spinlocks() s390/zcrypt: improve special ap message cmd handling s390/ap: rework assembler functions to use unions for in/out register variables s390: vfio-ap: include <asm/facility> for test_facility()
This commit is contained in:
commit
04a17edeca
@ -13162,7 +13162,9 @@ F: drivers/pci/hotplug/s390_pci_hpc.c
|
||||
|
||||
S390 VFIO-CCW DRIVER
|
||||
M: Cornelia Huck <cohuck@redhat.com>
|
||||
M: Halil Pasic <pasic@linux.ibm.com>
|
||||
M: Farhan Ali <alifm@linux.ibm.com>
|
||||
M: Eric Farman <farman@linux.ibm.com>
|
||||
R: Halil Pasic <pasic@linux.ibm.com>
|
||||
L: linux-s390@vger.kernel.org
|
||||
L: kvm@vger.kernel.org
|
||||
S: Supported
|
||||
|
@ -221,16 +221,22 @@ static inline struct ap_queue_status ap_aqic(ap_qid_t qid,
|
||||
void *ind)
|
||||
{
|
||||
register unsigned long reg0 asm ("0") = qid | (3UL << 24);
|
||||
register struct ap_qirq_ctrl reg1_in asm ("1") = qirqctrl;
|
||||
register struct ap_queue_status reg1_out asm ("1");
|
||||
register union {
|
||||
unsigned long value;
|
||||
struct ap_qirq_ctrl qirqctrl;
|
||||
struct ap_queue_status status;
|
||||
} reg1 asm ("1");
|
||||
register void *reg2 asm ("2") = ind;
|
||||
|
||||
reg1.qirqctrl = qirqctrl;
|
||||
|
||||
asm volatile(
|
||||
".long 0xb2af0000" /* PQAP(AQIC) */
|
||||
: "=d" (reg1_out)
|
||||
: "d" (reg0), "d" (reg1_in), "d" (reg2)
|
||||
: "+d" (reg1)
|
||||
: "d" (reg0), "d" (reg2)
|
||||
: "cc");
|
||||
return reg1_out;
|
||||
|
||||
return reg1.status;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -264,17 +270,21 @@ static inline struct ap_queue_status ap_qact(ap_qid_t qid, int ifbit,
|
||||
{
|
||||
register unsigned long reg0 asm ("0") = qid | (5UL << 24)
|
||||
| ((ifbit & 0x01) << 22);
|
||||
register unsigned long reg1_in asm ("1") = apinfo->val;
|
||||
register struct ap_queue_status reg1_out asm ("1");
|
||||
register union {
|
||||
unsigned long value;
|
||||
struct ap_queue_status status;
|
||||
} reg1 asm ("1");
|
||||
register unsigned long reg2 asm ("2");
|
||||
|
||||
reg1.value = apinfo->val;
|
||||
|
||||
asm volatile(
|
||||
".long 0xb2af0000" /* PQAP(QACT) */
|
||||
: "+d" (reg1_in), "=d" (reg1_out), "=d" (reg2)
|
||||
: "+d" (reg1), "=d" (reg2)
|
||||
: "d" (reg0)
|
||||
: "cc");
|
||||
apinfo->val = reg2;
|
||||
return reg1_out;
|
||||
return reg1.status;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -150,8 +150,8 @@ struct ica_xcRB {
|
||||
* @cprb_len: CPRB header length [0x0020]
|
||||
* @cprb_ver_id: CPRB version id. [0x04]
|
||||
* @pad_000: Alignment pad bytes
|
||||
* @flags: Admin cmd [0x80] or functional cmd [0x00]
|
||||
* @func_id: Function id / subtype [0x5434]
|
||||
* @flags: Admin bit [0x80], Special bit [0x20]
|
||||
* @func_id: Function id / subtype [0x5434] "T4"
|
||||
* @source_id: Source id [originator id]
|
||||
* @target_id: Target id [usage/ctrl domain id]
|
||||
* @ret_code: Return code
|
||||
|
@ -81,30 +81,6 @@ static inline int notify_page_fault(struct pt_regs *regs)
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Unlock any spinlocks which will prevent us from getting the
|
||||
* message out.
|
||||
*/
|
||||
void bust_spinlocks(int yes)
|
||||
{
|
||||
if (yes) {
|
||||
oops_in_progress = 1;
|
||||
} else {
|
||||
int loglevel_save = console_loglevel;
|
||||
console_unblank();
|
||||
oops_in_progress = 0;
|
||||
/*
|
||||
* OK, the message is on the console. Now we call printk()
|
||||
* without oops_in_progress set so that printk will give klogd
|
||||
* a poke. Hold onto your hats...
|
||||
*/
|
||||
console_loglevel = 15;
|
||||
printk(" ");
|
||||
console_loglevel = loglevel_save;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Find out which address space caused the exception.
|
||||
* Access register mode is impossible, ignore space == 3.
|
||||
|
@ -382,9 +382,7 @@ static void zpci_irq_handler(struct airq_struct *airq)
|
||||
if (ai == -1UL)
|
||||
break;
|
||||
inc_irq_stat(IRQIO_MSI);
|
||||
airq_iv_lock(aibv, ai);
|
||||
generic_handle_irq(airq_iv_get_data(aibv, ai));
|
||||
airq_iv_unlock(aibv, ai);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -410,7 +408,7 @@ int arch_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
|
||||
zdev->aisb = aisb;
|
||||
|
||||
/* Create adapter interrupt vector */
|
||||
zdev->aibv = airq_iv_create(msi_vecs, AIRQ_IV_DATA | AIRQ_IV_BITLOCK);
|
||||
zdev->aibv = airq_iv_create(msi_vecs, AIRQ_IV_DATA);
|
||||
if (!zdev->aibv)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -436,7 +436,7 @@ int clp_get_state(u32 fid, enum zpci_state *state)
|
||||
struct clp_state_data sd = {fid, ZPCI_FN_STATE_RESERVED};
|
||||
int rc;
|
||||
|
||||
rrb = clp_alloc_block(GFP_KERNEL);
|
||||
rrb = clp_alloc_block(GFP_ATOMIC);
|
||||
if (!rrb)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -1192,20 +1192,7 @@ static int dasd_hosts_show(struct seq_file *m, void *v)
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int dasd_hosts_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct dasd_device *device = inode->i_private;
|
||||
|
||||
return single_open(file, dasd_hosts_show, device);
|
||||
}
|
||||
|
||||
static const struct file_operations dasd_hosts_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = dasd_hosts_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
DEFINE_SHOW_ATTRIBUTE(dasd_hosts);
|
||||
|
||||
static void dasd_hosts_exit(struct dasd_device *device)
|
||||
{
|
||||
|
@ -339,8 +339,7 @@ dasd_proc_init(void)
|
||||
dasd_proc_root_entry = proc_mkdir("dasd", NULL);
|
||||
if (!dasd_proc_root_entry)
|
||||
goto out_nodasd;
|
||||
dasd_devices_entry = proc_create_seq("devices",
|
||||
S_IFREG | S_IRUGO | S_IWUSR,
|
||||
dasd_devices_entry = proc_create_seq("devices", 0444,
|
||||
dasd_proc_root_entry,
|
||||
&dasd_devices_seq_ops);
|
||||
if (!dasd_devices_entry)
|
||||
|
@ -111,11 +111,8 @@ static const struct seq_operations tape_proc_seq = {
|
||||
void
|
||||
tape_proc_init(void)
|
||||
{
|
||||
tape_proc_devices = proc_create_seq("tapedevices",
|
||||
S_IFREG | S_IRUGO | S_IWUSR, NULL, &tape_proc_seq);
|
||||
if (tape_proc_devices == NULL) {
|
||||
return;
|
||||
}
|
||||
tape_proc_devices = proc_create_seq("tapedevices", 0444, NULL,
|
||||
&tape_proc_seq);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -190,19 +190,7 @@ static int qstat_show(struct seq_file *m, void *v)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qstat_seq_open(struct inode *inode, struct file *filp)
|
||||
{
|
||||
return single_open(filp, qstat_show,
|
||||
file_inode(filp)->i_private);
|
||||
}
|
||||
|
||||
static const struct file_operations debugfs_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = qstat_seq_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
DEFINE_SHOW_ATTRIBUTE(qstat);
|
||||
|
||||
static char *qperf_names[] = {
|
||||
"Assumed adapter interrupts",
|
||||
@ -305,8 +293,8 @@ static void setup_debugfs_entry(struct qdio_q *q)
|
||||
snprintf(name, QDIO_DEBUGFS_NAME_LEN, "%s_%d",
|
||||
q->is_input_q ? "input" : "output",
|
||||
q->nr);
|
||||
q->debugfs_q = debugfs_create_file(name, S_IFREG | S_IRUGO | S_IWUSR,
|
||||
q->irq_ptr->debugfs_dev, q, &debugfs_fops);
|
||||
q->debugfs_q = debugfs_create_file(name, 0444,
|
||||
q->irq_ptr->debugfs_dev, q, &qstat_fops);
|
||||
if (IS_ERR(q->debugfs_q))
|
||||
q->debugfs_q = NULL;
|
||||
}
|
||||
|
@ -130,7 +130,7 @@ static void fsm_io_request(struct vfio_ccw_private *private,
|
||||
struct mdev_device *mdev = private->mdev;
|
||||
char *errstr = "request";
|
||||
|
||||
private->state = VFIO_CCW_STATE_BOXED;
|
||||
private->state = VFIO_CCW_STATE_BUSY;
|
||||
|
||||
memcpy(scsw, io_region->scsw_area, sizeof(*scsw));
|
||||
|
||||
@ -216,11 +216,6 @@ fsm_func_t *vfio_ccw_jumptable[NR_VFIO_CCW_STATES][NR_VFIO_CCW_EVENTS] = {
|
||||
[VFIO_CCW_EVENT_IO_REQ] = fsm_io_request,
|
||||
[VFIO_CCW_EVENT_INTERRUPT] = fsm_irq,
|
||||
},
|
||||
[VFIO_CCW_STATE_BOXED] = {
|
||||
[VFIO_CCW_EVENT_NOT_OPER] = fsm_notoper,
|
||||
[VFIO_CCW_EVENT_IO_REQ] = fsm_io_busy,
|
||||
[VFIO_CCW_EVENT_INTERRUPT] = fsm_irq,
|
||||
},
|
||||
[VFIO_CCW_STATE_BUSY] = {
|
||||
[VFIO_CCW_EVENT_NOT_OPER] = fsm_notoper,
|
||||
[VFIO_CCW_EVENT_IO_REQ] = fsm_io_busy,
|
||||
|
@ -63,7 +63,6 @@ enum vfio_ccw_state {
|
||||
VFIO_CCW_STATE_NOT_OPER,
|
||||
VFIO_CCW_STATE_STANDBY,
|
||||
VFIO_CCW_STATE_IDLE,
|
||||
VFIO_CCW_STATE_BOXED,
|
||||
VFIO_CCW_STATE_BUSY,
|
||||
/* last element! */
|
||||
NR_VFIO_CCW_STATES
|
||||
|
@ -299,7 +299,7 @@ static int ap_query_queue(ap_qid_t qid, int *queue_depth, int *device_type,
|
||||
ap_max_domain_id = 15;
|
||||
switch (*device_type) {
|
||||
/* For CEX2 and CEX3 the available functions
|
||||
* are not refrected by the facilities bits.
|
||||
* are not reflected by the facilities bits.
|
||||
* Instead it is coded into the type. So here
|
||||
* modify the function bits based on the type.
|
||||
*/
|
||||
@ -1317,7 +1317,7 @@ static int ap_get_compatible_type(ap_qid_t qid, int rawtype, unsigned int func)
|
||||
}
|
||||
|
||||
/*
|
||||
* helper function to be used with bus_find_dev
|
||||
* Helper function to be used with bus_find_dev
|
||||
* matches for the card device with the given id
|
||||
*/
|
||||
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)
|
||||
return is_card_dev(dev) && to_ap_card(dev)->id == (int)(long) data;
|
||||
}
|
||||
|
||||
/* helper function to be used with bus_find_dev
|
||||
/*
|
||||
* Helper function to be used with bus_find_dev
|
||||
* matches for the queue device with a given qid
|
||||
*/
|
||||
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)
|
||||
return is_queue_dev(dev) && to_ap_queue(dev)->qid == (int)(long) data;
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper function for ap_scan_bus().
|
||||
* Does the scan bus job for the given adapter id.
|
||||
*/
|
||||
static void _ap_scan_bus_adapter(int id)
|
||||
{
|
||||
ap_qid_t qid;
|
||||
unsigned int func;
|
||||
struct ap_card *ac;
|
||||
struct device *dev;
|
||||
struct ap_queue *aq;
|
||||
int rc, dom, depth, type, comp_type, borked;
|
||||
|
||||
/* check if there is a card device registered with this id */
|
||||
dev = bus_find_device(&ap_bus_type, NULL,
|
||||
(void *)(long) id,
|
||||
__match_card_device_with_id);
|
||||
ac = dev ? to_ap_card(dev) : NULL;
|
||||
if (!ap_test_config_card_id(id)) {
|
||||
if (dev) {
|
||||
/* Card device has been removed from configuration */
|
||||
bus_for_each_dev(&ap_bus_type, NULL,
|
||||
(void *)(long) id,
|
||||
__ap_queue_devices_with_id_unregister);
|
||||
device_unregister(dev);
|
||||
put_device(dev);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* This card id is enabled in the configuration. If we already have
|
||||
* a card device with this id, check if type and functions are still
|
||||
* the very same. Also verify that at least one queue is available.
|
||||
*/
|
||||
if (ac) {
|
||||
/* find the first valid queue */
|
||||
for (dom = 0; dom < AP_DOMAINS; dom++) {
|
||||
qid = AP_MKQID(id, dom);
|
||||
if (ap_query_queue(qid, &depth, &type, &func) == 0)
|
||||
break;
|
||||
}
|
||||
borked = 0;
|
||||
if (dom >= AP_DOMAINS) {
|
||||
/* no accessible queue on this card */
|
||||
borked = 1;
|
||||
} else if (ac->raw_hwtype != type) {
|
||||
/* card type has changed */
|
||||
AP_DBF(DBF_INFO, "card=%02x type changed.\n", id);
|
||||
borked = 1;
|
||||
} else if (ac->functions != func) {
|
||||
/* card functions have changed */
|
||||
AP_DBF(DBF_INFO, "card=%02x functions changed.\n", id);
|
||||
borked = 1;
|
||||
}
|
||||
if (borked) {
|
||||
/* unregister card device and associated queues */
|
||||
bus_for_each_dev(&ap_bus_type, NULL,
|
||||
(void *)(long) id,
|
||||
__ap_queue_devices_with_id_unregister);
|
||||
device_unregister(dev);
|
||||
put_device(dev);
|
||||
/* go back if there is no valid queue on this card */
|
||||
if (dom >= AP_DOMAINS)
|
||||
return;
|
||||
ac = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Go through all possible queue ids. Check and maybe create or release
|
||||
* queue devices for this card. If there exists no card device yet,
|
||||
* create a card device also.
|
||||
*/
|
||||
for (dom = 0; dom < AP_DOMAINS; dom++) {
|
||||
qid = AP_MKQID(id, dom);
|
||||
dev = bus_find_device(&ap_bus_type, NULL,
|
||||
(void *)(long) qid,
|
||||
__match_queue_device_with_qid);
|
||||
aq = dev ? to_ap_queue(dev) : NULL;
|
||||
if (!ap_test_config_domain(dom)) {
|
||||
if (dev) {
|
||||
/* Queue device exists but has been
|
||||
* removed from configuration.
|
||||
*/
|
||||
device_unregister(dev);
|
||||
put_device(dev);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
/* try to fetch infos about this queue */
|
||||
rc = ap_query_queue(qid, &depth, &type, &func);
|
||||
if (dev) {
|
||||
if (rc == -ENODEV)
|
||||
borked = 1;
|
||||
else {
|
||||
spin_lock_bh(&aq->lock);
|
||||
borked = aq->state == AP_STATE_BORKED;
|
||||
spin_unlock_bh(&aq->lock);
|
||||
}
|
||||
if (borked) /* Remove broken device */
|
||||
device_unregister(dev);
|
||||
put_device(dev);
|
||||
continue;
|
||||
}
|
||||
if (rc)
|
||||
continue;
|
||||
/* a new queue device is needed, check out comp type */
|
||||
comp_type = ap_get_compatible_type(qid, type, func);
|
||||
if (!comp_type)
|
||||
continue;
|
||||
/* maybe a card device needs to be created first */
|
||||
if (!ac) {
|
||||
ac = ap_card_create(id, depth, type, comp_type, func);
|
||||
if (!ac)
|
||||
continue;
|
||||
ac->ap_dev.device.bus = &ap_bus_type;
|
||||
ac->ap_dev.device.parent = ap_root_device;
|
||||
dev_set_name(&ac->ap_dev.device, "card%02x", id);
|
||||
/* Register card device with AP bus */
|
||||
rc = device_register(&ac->ap_dev.device);
|
||||
if (rc) {
|
||||
put_device(&ac->ap_dev.device);
|
||||
ac = NULL;
|
||||
break;
|
||||
}
|
||||
/* get it and thus adjust reference counter */
|
||||
get_device(&ac->ap_dev.device);
|
||||
}
|
||||
/* now create the new queue device */
|
||||
aq = ap_queue_create(qid, comp_type);
|
||||
if (!aq)
|
||||
continue;
|
||||
aq->card = ac;
|
||||
aq->ap_dev.device.bus = &ap_bus_type;
|
||||
aq->ap_dev.device.parent = &ac->ap_dev.device;
|
||||
dev_set_name(&aq->ap_dev.device, "%02x.%04x", id, dom);
|
||||
/* Register queue device */
|
||||
rc = device_register(&aq->ap_dev.device);
|
||||
if (rc) {
|
||||
put_device(&aq->ap_dev.device);
|
||||
continue;
|
||||
}
|
||||
} /* end domain loop */
|
||||
|
||||
if (ac)
|
||||
put_device(&ac->ap_dev.device);
|
||||
}
|
||||
|
||||
/**
|
||||
* ap_scan_bus(): Scan the AP bus for new devices
|
||||
* Runs periodically, workqueue timer (ap_config_time)
|
||||
*/
|
||||
static void ap_scan_bus(struct work_struct *unused)
|
||||
{
|
||||
struct ap_queue *aq;
|
||||
struct ap_card *ac;
|
||||
struct device *dev;
|
||||
ap_qid_t qid;
|
||||
int comp_type, depth = 0, type = 0;
|
||||
unsigned int func = 0;
|
||||
int rc, id, dom, borked, domains, defdomdevs = 0;
|
||||
int id;
|
||||
|
||||
AP_DBF(DBF_DEBUG, "%s running\n", __func__);
|
||||
|
||||
ap_query_configuration(ap_configuration);
|
||||
ap_select_domain();
|
||||
|
||||
for (id = 0; id < AP_DEVICES; id++) {
|
||||
/* check if device is registered */
|
||||
dev = bus_find_device(&ap_bus_type, NULL,
|
||||
(void *)(long) id,
|
||||
__match_card_device_with_id);
|
||||
ac = dev ? to_ap_card(dev) : NULL;
|
||||
if (!ap_test_config_card_id(id)) {
|
||||
if (dev) {
|
||||
/* Card device has been removed from
|
||||
* configuration, remove the belonging
|
||||
* queue devices.
|
||||
*/
|
||||
bus_for_each_dev(&ap_bus_type, NULL,
|
||||
(void *)(long) id,
|
||||
__ap_queue_devices_with_id_unregister);
|
||||
/* now remove the card device */
|
||||
device_unregister(dev);
|
||||
put_device(dev);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
/* According to the configuration there should be a card
|
||||
* device, so check if there is at least one valid queue
|
||||
* and maybe create queue devices and the card device.
|
||||
*/
|
||||
domains = 0;
|
||||
for (dom = 0; dom < AP_DOMAINS; dom++) {
|
||||
qid = AP_MKQID(id, dom);
|
||||
dev = bus_find_device(&ap_bus_type, NULL,
|
||||
(void *)(long) qid,
|
||||
__match_queue_device_with_qid);
|
||||
aq = dev ? to_ap_queue(dev) : NULL;
|
||||
if (!ap_test_config_domain(dom)) {
|
||||
if (dev) {
|
||||
/* Queue device exists but has been
|
||||
* removed from configuration.
|
||||
*/
|
||||
device_unregister(dev);
|
||||
put_device(dev);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
rc = ap_query_queue(qid, &depth, &type, &func);
|
||||
if (dev) {
|
||||
spin_lock_bh(&aq->lock);
|
||||
if (rc == -ENODEV ||
|
||||
/* adapter reconfiguration */
|
||||
(ac && ac->functions != func))
|
||||
aq->state = AP_STATE_BORKED;
|
||||
borked = aq->state == AP_STATE_BORKED;
|
||||
spin_unlock_bh(&aq->lock);
|
||||
if (borked) /* Remove broken device */
|
||||
device_unregister(dev);
|
||||
put_device(dev);
|
||||
if (!borked) {
|
||||
domains++;
|
||||
if (dom == ap_domain_index)
|
||||
defdomdevs++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (rc)
|
||||
continue;
|
||||
/* a new queue device is needed, check out comp type */
|
||||
comp_type = ap_get_compatible_type(qid, type, func);
|
||||
if (!comp_type)
|
||||
continue;
|
||||
/* maybe a card device needs to be created first */
|
||||
if (!ac) {
|
||||
ac = ap_card_create(id, depth, type,
|
||||
comp_type, func);
|
||||
if (!ac)
|
||||
continue;
|
||||
ac->ap_dev.device.bus = &ap_bus_type;
|
||||
ac->ap_dev.device.parent = ap_root_device;
|
||||
dev_set_name(&ac->ap_dev.device,
|
||||
"card%02x", id);
|
||||
/* Register card with AP bus */
|
||||
rc = device_register(&ac->ap_dev.device);
|
||||
if (rc) {
|
||||
put_device(&ac->ap_dev.device);
|
||||
ac = NULL;
|
||||
break;
|
||||
}
|
||||
/* get it and thus adjust reference counter */
|
||||
get_device(&ac->ap_dev.device);
|
||||
}
|
||||
/* now create the new queue device */
|
||||
aq = ap_queue_create(qid, comp_type);
|
||||
if (!aq)
|
||||
continue;
|
||||
aq->card = ac;
|
||||
aq->ap_dev.device.bus = &ap_bus_type;
|
||||
aq->ap_dev.device.parent = &ac->ap_dev.device;
|
||||
dev_set_name(&aq->ap_dev.device,
|
||||
"%02x.%04x", id, dom);
|
||||
/* Register device */
|
||||
rc = device_register(&aq->ap_dev.device);
|
||||
if (rc) {
|
||||
put_device(&aq->ap_dev.device);
|
||||
continue;
|
||||
}
|
||||
domains++;
|
||||
if (dom == ap_domain_index)
|
||||
defdomdevs++;
|
||||
} /* end domain loop */
|
||||
if (ac) {
|
||||
/* remove card dev if there are no queue devices */
|
||||
if (!domains)
|
||||
device_unregister(&ac->ap_dev.device);
|
||||
put_device(&ac->ap_dev.device);
|
||||
}
|
||||
} /* end device loop */
|
||||
/* loop over all possible adapters */
|
||||
for (id = 0; id < AP_DEVICES; id++)
|
||||
_ap_scan_bus_adapter(id);
|
||||
|
||||
if (ap_domain_index >= 0 && defdomdevs < 1)
|
||||
AP_DBF(DBF_INFO,
|
||||
"no queue device with default domain %d available\n",
|
||||
ap_domain_index);
|
||||
/* check if there is at least one queue available with default domain */
|
||||
if (ap_domain_index >= 0) {
|
||||
struct device *dev =
|
||||
bus_find_device(&ap_bus_type, NULL,
|
||||
(void *)(long) ap_domain_index,
|
||||
__match_queue_device_with_qid);
|
||||
if (dev)
|
||||
put_device(dev);
|
||||
else
|
||||
AP_DBF(DBF_INFO,
|
||||
"no queue device with default domain %d available\n",
|
||||
ap_domain_index);
|
||||
}
|
||||
|
||||
mod_timer(&ap_config_timer, jiffies + ap_config_time * HZ);
|
||||
}
|
||||
|
@ -14,6 +14,9 @@
|
||||
#include <asm/facility.h>
|
||||
|
||||
#include "ap_bus.h"
|
||||
#include "ap_debug.h"
|
||||
|
||||
static void __ap_flush_queue(struct ap_queue *aq);
|
||||
|
||||
/**
|
||||
* ap_queue_enable_interruption(): Enable interruption on an AP queue.
|
||||
@ -541,7 +544,25 @@ static ssize_t reset_show(struct device *dev,
|
||||
return rc;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR_RO(reset);
|
||||
static ssize_t reset_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct ap_queue *aq = to_ap_queue(dev);
|
||||
|
||||
spin_lock_bh(&aq->lock);
|
||||
__ap_flush_queue(aq);
|
||||
aq->state = AP_STATE_RESET_START;
|
||||
ap_wait(ap_sm_event(aq, AP_EVENT_POLL));
|
||||
spin_unlock_bh(&aq->lock);
|
||||
|
||||
AP_DBF(DBF_INFO, "reset queue=%02x.%04x triggered by user\n",
|
||||
AP_QID_CARD(aq->qid), AP_QID_QUEUE(aq->qid));
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR_RW(reset);
|
||||
|
||||
static ssize_t interrupt_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string.h>
|
||||
#include <asm/facility.h>
|
||||
#include "vfio_ap_private.h"
|
||||
|
||||
#define VFIO_AP_ROOT_NAME "vfio_ap"
|
||||
|
@ -51,6 +51,7 @@ struct error_hdr {
|
||||
#define REP82_ERROR_FORMAT_FIELD 0x29
|
||||
#define REP82_ERROR_INVALID_COMMAND 0x30
|
||||
#define REP82_ERROR_MALFORMED_MSG 0x40
|
||||
#define REP82_ERROR_INVALID_SPECIAL_CMD 0x41
|
||||
#define REP82_ERROR_INVALID_DOMAIN_PRECHECK 0x42
|
||||
#define REP82_ERROR_RESERVED_FIELDO 0x50 /* old value */
|
||||
#define REP82_ERROR_WORD_ALIGNMENT 0x60
|
||||
@ -89,6 +90,7 @@ static inline int convert_error(struct zcrypt_queue *zq,
|
||||
case REP88_ERROR_MESSAGE_MALFORMD:
|
||||
case REP82_ERROR_INVALID_DOMAIN_PRECHECK:
|
||||
case REP82_ERROR_INVALID_DOMAIN_PENDING:
|
||||
case REP82_ERROR_INVALID_SPECIAL_CMD:
|
||||
// REP88_ERROR_INVALID_KEY // '82' CEX2A
|
||||
// REP88_ERROR_OPERAND // '84' CEX2A
|
||||
// REP88_ERROR_OPERAND_EVEN_MOD // '85' CEX2A
|
||||
|
@ -2,7 +2,8 @@
|
||||
/*
|
||||
* lib/bust_spinlocks.c
|
||||
*
|
||||
* Provides a minimal bust_spinlocks for architectures which don't have one of their own.
|
||||
* Provides a minimal bust_spinlocks for architectures which don't
|
||||
* have one of their own.
|
||||
*
|
||||
* bust_spinlocks() clears any spinlocks which would prevent oops, die(), BUG()
|
||||
* and panic() information from reaching the user.
|
||||
@ -16,8 +17,7 @@
|
||||
#include <linux/vt_kern.h>
|
||||
#include <linux/console.h>
|
||||
|
||||
|
||||
void __attribute__((weak)) bust_spinlocks(int yes)
|
||||
void bust_spinlocks(int yes)
|
||||
{
|
||||
if (yes) {
|
||||
++oops_in_progress;
|
||||
|
Loading…
Reference in New Issue
Block a user