Commit 04a17ede authored by Linus Torvalds's avatar Linus Torvalds

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()
parents e6b92572 ec10574d
...@@ -13162,7 +13162,9 @@ F: drivers/pci/hotplug/s390_pci_hpc.c ...@@ -13162,7 +13162,9 @@ F: drivers/pci/hotplug/s390_pci_hpc.c
S390 VFIO-CCW DRIVER S390 VFIO-CCW DRIVER
M: Cornelia Huck <cohuck@redhat.com> 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: linux-s390@vger.kernel.org
L: kvm@vger.kernel.org L: kvm@vger.kernel.org
S: Supported S: Supported
......
...@@ -221,16 +221,22 @@ static inline struct ap_queue_status ap_aqic(ap_qid_t qid, ...@@ -221,16 +221,22 @@ static inline struct ap_queue_status ap_aqic(ap_qid_t qid,
void *ind) void *ind)
{ {
register unsigned long reg0 asm ("0") = qid | (3UL << 24); register unsigned long reg0 asm ("0") = qid | (3UL << 24);
register struct ap_qirq_ctrl reg1_in asm ("1") = qirqctrl; register union {
register struct ap_queue_status reg1_out asm ("1"); unsigned long value;
struct ap_qirq_ctrl qirqctrl;
struct ap_queue_status status;
} reg1 asm ("1");
register void *reg2 asm ("2") = ind; register void *reg2 asm ("2") = ind;
reg1.qirqctrl = qirqctrl;
asm volatile( asm volatile(
".long 0xb2af0000" /* PQAP(AQIC) */ ".long 0xb2af0000" /* PQAP(AQIC) */
: "=d" (reg1_out) : "+d" (reg1)
: "d" (reg0), "d" (reg1_in), "d" (reg2) : "d" (reg0), "d" (reg2)
: "cc"); : "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, ...@@ -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) register unsigned long reg0 asm ("0") = qid | (5UL << 24)
| ((ifbit & 0x01) << 22); | ((ifbit & 0x01) << 22);
register unsigned long reg1_in asm ("1") = apinfo->val; register union {
register struct ap_queue_status reg1_out asm ("1"); unsigned long value;
struct ap_queue_status status;
} reg1 asm ("1");
register unsigned long reg2 asm ("2"); register unsigned long reg2 asm ("2");
reg1.value = apinfo->val;
asm volatile( asm volatile(
".long 0xb2af0000" /* PQAP(QACT) */ ".long 0xb2af0000" /* PQAP(QACT) */
: "+d" (reg1_in), "=d" (reg1_out), "=d" (reg2) : "+d" (reg1), "=d" (reg2)
: "d" (reg0) : "d" (reg0)
: "cc"); : "cc");
apinfo->val = reg2; apinfo->val = reg2;
return reg1_out; return reg1.status;
} }
/** /**
......
...@@ -150,8 +150,8 @@ struct ica_xcRB { ...@@ -150,8 +150,8 @@ struct ica_xcRB {
* @cprb_len: CPRB header length [0x0020] * @cprb_len: CPRB header length [0x0020]
* @cprb_ver_id: CPRB version id. [0x04] * @cprb_ver_id: CPRB version id. [0x04]
* @pad_000: Alignment pad bytes * @pad_000: Alignment pad bytes
* @flags: Admin cmd [0x80] or functional cmd [0x00] * @flags: Admin bit [0x80], Special bit [0x20]
* @func_id: Function id / subtype [0x5434] * @func_id: Function id / subtype [0x5434] "T4"
* @source_id: Source id [originator id] * @source_id: Source id [originator id]
* @target_id: Target id [usage/ctrl domain id] * @target_id: Target id [usage/ctrl domain id]
* @ret_code: Return code * @ret_code: Return code
......
...@@ -81,30 +81,6 @@ static inline int notify_page_fault(struct pt_regs *regs) ...@@ -81,30 +81,6 @@ static inline int notify_page_fault(struct pt_regs *regs)
return ret; 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. * Find out which address space caused the exception.
* Access register mode is impossible, ignore space == 3. * Access register mode is impossible, ignore space == 3.
......
...@@ -382,9 +382,7 @@ static void zpci_irq_handler(struct airq_struct *airq) ...@@ -382,9 +382,7 @@ static void zpci_irq_handler(struct airq_struct *airq)
if (ai == -1UL) if (ai == -1UL)
break; break;
inc_irq_stat(IRQIO_MSI); inc_irq_stat(IRQIO_MSI);
airq_iv_lock(aibv, ai);
generic_handle_irq(airq_iv_get_data(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) ...@@ -410,7 +408,7 @@ int arch_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
zdev->aisb = aisb; zdev->aisb = aisb;
/* Create adapter interrupt vector */ /* 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) if (!zdev->aibv)
return -ENOMEM; return -ENOMEM;
......
...@@ -436,7 +436,7 @@ int clp_get_state(u32 fid, enum zpci_state *state) ...@@ -436,7 +436,7 @@ int clp_get_state(u32 fid, enum zpci_state *state)
struct clp_state_data sd = {fid, ZPCI_FN_STATE_RESERVED}; struct clp_state_data sd = {fid, ZPCI_FN_STATE_RESERVED};
int rc; int rc;
rrb = clp_alloc_block(GFP_KERNEL); rrb = clp_alloc_block(GFP_ATOMIC);
if (!rrb) if (!rrb)
return -ENOMEM; return -ENOMEM;
......
...@@ -1192,20 +1192,7 @@ static int dasd_hosts_show(struct seq_file *m, void *v) ...@@ -1192,20 +1192,7 @@ static int dasd_hosts_show(struct seq_file *m, void *v)
return rc; return rc;
} }
static int dasd_hosts_open(struct inode *inode, struct file *file) DEFINE_SHOW_ATTRIBUTE(dasd_hosts);
{
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,
};
static void dasd_hosts_exit(struct dasd_device *device) static void dasd_hosts_exit(struct dasd_device *device)
{ {
......
...@@ -339,8 +339,7 @@ dasd_proc_init(void) ...@@ -339,8 +339,7 @@ dasd_proc_init(void)
dasd_proc_root_entry = proc_mkdir("dasd", NULL); dasd_proc_root_entry = proc_mkdir("dasd", NULL);
if (!dasd_proc_root_entry) if (!dasd_proc_root_entry)
goto out_nodasd; goto out_nodasd;
dasd_devices_entry = proc_create_seq("devices", dasd_devices_entry = proc_create_seq("devices", 0444,
S_IFREG | S_IRUGO | S_IWUSR,
dasd_proc_root_entry, dasd_proc_root_entry,
&dasd_devices_seq_ops); &dasd_devices_seq_ops);
if (!dasd_devices_entry) if (!dasd_devices_entry)
......
...@@ -111,11 +111,8 @@ static const struct seq_operations tape_proc_seq = { ...@@ -111,11 +111,8 @@ static const struct seq_operations tape_proc_seq = {
void void
tape_proc_init(void) tape_proc_init(void)
{ {
tape_proc_devices = proc_create_seq("tapedevices", tape_proc_devices = proc_create_seq("tapedevices", 0444, NULL,
S_IFREG | S_IRUGO | S_IWUSR, NULL, &tape_proc_seq); &tape_proc_seq);
if (tape_proc_devices == NULL) {
return;
}
} }
/* /*
......
...@@ -190,19 +190,7 @@ static int qstat_show(struct seq_file *m, void *v) ...@@ -190,19 +190,7 @@ static int qstat_show(struct seq_file *m, void *v)
return 0; return 0;
} }
static int qstat_seq_open(struct inode *inode, struct file *filp) DEFINE_SHOW_ATTRIBUTE(qstat);
{
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,
};
static char *qperf_names[] = { static char *qperf_names[] = {
"Assumed adapter interrupts", "Assumed adapter interrupts",
...@@ -305,8 +293,8 @@ static void setup_debugfs_entry(struct qdio_q *q) ...@@ -305,8 +293,8 @@ static void setup_debugfs_entry(struct qdio_q *q)
snprintf(name, QDIO_DEBUGFS_NAME_LEN, "%s_%d", snprintf(name, QDIO_DEBUGFS_NAME_LEN, "%s_%d",
q->is_input_q ? "input" : "output", q->is_input_q ? "input" : "output",
q->nr); q->nr);
q->debugfs_q = debugfs_create_file(name, S_IFREG | S_IRUGO | S_IWUSR, q->debugfs_q = debugfs_create_file(name, 0444,
q->irq_ptr->debugfs_dev, q, &debugfs_fops); q->irq_ptr->debugfs_dev, q, &qstat_fops);
if (IS_ERR(q->debugfs_q)) if (IS_ERR(q->debugfs_q))
q->debugfs_q = NULL; q->debugfs_q = NULL;
} }
......
...@@ -130,7 +130,7 @@ static void fsm_io_request(struct vfio_ccw_private *private, ...@@ -130,7 +130,7 @@ static void fsm_io_request(struct vfio_ccw_private *private,
struct mdev_device *mdev = private->mdev; struct mdev_device *mdev = private->mdev;
char *errstr = "request"; char *errstr = "request";
private->state = VFIO_CCW_STATE_BOXED; private->state = VFIO_CCW_STATE_BUSY;
memcpy(scsw, io_region->scsw_area, sizeof(*scsw)); 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] = { ...@@ -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_IO_REQ] = fsm_io_request,
[VFIO_CCW_EVENT_INTERRUPT] = fsm_irq, [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_STATE_BUSY] = {
[VFIO_CCW_EVENT_NOT_OPER] = fsm_notoper, [VFIO_CCW_EVENT_NOT_OPER] = fsm_notoper,
[VFIO_CCW_EVENT_IO_REQ] = fsm_io_busy, [VFIO_CCW_EVENT_IO_REQ] = fsm_io_busy,
......
...@@ -63,7 +63,6 @@ enum vfio_ccw_state { ...@@ -63,7 +63,6 @@ enum vfio_ccw_state {
VFIO_CCW_STATE_NOT_OPER, VFIO_CCW_STATE_NOT_OPER,
VFIO_CCW_STATE_STANDBY, VFIO_CCW_STATE_STANDBY,
VFIO_CCW_STATE_IDLE, VFIO_CCW_STATE_IDLE,
VFIO_CCW_STATE_BOXED,
VFIO_CCW_STATE_BUSY, VFIO_CCW_STATE_BUSY,
/* last element! */ /* last element! */
NR_VFIO_CCW_STATES NR_VFIO_CCW_STATES
......
...@@ -299,7 +299,7 @@ static int ap_query_queue(ap_qid_t qid, int *queue_depth, int *device_type, ...@@ -299,7 +299,7 @@ static int ap_query_queue(ap_qid_t qid, int *queue_depth, int *device_type,
ap_max_domain_id = 15; ap_max_domain_id = 15;
switch (*device_type) { switch (*device_type) {
/* For CEX2 and CEX3 the available functions /* 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 * Instead it is coded into the type. So here
* modify the function bits based on the type. * 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) ...@@ -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 * matches for the card device with the given id
*/ */
static int __match_card_device_with_id(struct device *dev, void *data) 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,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; 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 * matches for the queue device with a given qid
*/ */
static int __match_queue_device_with_qid(struct device *dev, void *data) 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,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; return is_queue_dev(dev) && to_ap_queue(dev)->qid == (int)(long) data;
} }
/** /*
* ap_scan_bus(): Scan the AP bus for new devices * Helper function for ap_scan_bus().
* Runs periodically, workqueue timer (ap_config_time) * Does the scan bus job for the given adapter id.
*/ */
static void ap_scan_bus(struct work_struct *unused) static void _ap_scan_bus_adapter(int id)
{ {
struct ap_queue *aq; ap_qid_t qid;
unsigned int func;
struct ap_card *ac; struct ap_card *ac;
struct device *dev; struct device *dev;
ap_qid_t qid; struct ap_queue *aq;
int comp_type, depth = 0, type = 0; int rc, dom, depth, type, comp_type, borked;
unsigned int func = 0;
int rc, id, dom, borked, domains, defdomdevs = 0; /* check if there is a card device registered with this id */
dev = bus_find_device(&ap_bus_type, NULL,
AP_DBF(DBF_DEBUG, "%s running\n", __func__); (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;
}
ap_query_configuration(ap_configuration); /*
ap_select_domain(); * 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;
}
}
for (id = 0; id < AP_DEVICES; id++) { /*
/* check if device is registered */ * 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, dev = bus_find_device(&ap_bus_type, NULL,
(void *)(long) id, (void *)(long) qid,
__match_card_device_with_id); __match_queue_device_with_qid);
ac = dev ? to_ap_card(dev) : NULL; aq = dev ? to_ap_queue(dev) : NULL;
if (!ap_test_config_card_id(id)) { if (!ap_test_config_domain(dom)) {
if (dev) { if (dev) {
/* Card device has been removed from /* Queue device exists but has been
* configuration, remove the belonging * removed from configuration.
* 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); device_unregister(dev);
put_device(dev); put_device(dev);
} }
continue; continue;
} }
/* According to the configuration there should be a card /* try to fetch infos about this queue */
* device, so check if there is at least one valid queue rc = ap_query_queue(qid, &depth, &type, &func);
* and maybe create queue devices and the card device. if (dev) {
*/ if (rc == -ENODEV)
domains = 0; borked = 1;
for (dom = 0; dom < AP_DOMAINS; dom++) { else {
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); 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; borked = aq->state == AP_STATE_BORKED;
spin_unlock_bh(&aq->lock); 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 */ if (borked) /* Remove broken device */
aq = ap_queue_create(qid, comp_type); device_unregister(dev);
if (!aq) 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; continue;
aq->card = ac; ac->ap_dev.device.bus = &ap_bus_type;
aq->ap_dev.device.bus = &ap_bus_type; ac->ap_dev.device.parent = ap_root_device;
aq->ap_dev.device.parent = &ac->ap_dev.device; dev_set_name(&ac->ap_dev.device, "card%02x", id);
dev_set_name(&aq->ap_dev.device, /* Register card device with AP bus */
"%02x.%04x", id, dom); rc = device_register(&ac->ap_dev.device);
/* Register device */
rc = device_register(&aq->ap_dev.device);
if (rc) { if (rc) {
put_device(&aq->ap_dev.device); put_device(&ac->ap_dev.device);
continue; ac = NULL;
break;
} }
domains++; /* get it and thus adjust reference counter */
if (dom == ap_domain_index) get_device(&ac->ap_dev.device);
defdomdevs++; }
} /* end domain loop */ /* now create the new queue device */
if (ac) { aq = ap_queue_create(qid, comp_type);
/* remove card dev if there are no queue devices */ if (!aq)
if (!domains) continue;
device_unregister(&ac->ap_dev.device); aq->card = ac;
put_device(&ac->ap_dev.device); 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 device loop */ } /* end domain loop */
if (ac)
put_device(&ac->ap_dev.device);
}
if (ap_domain_index >= 0 && defdomdevs < 1) /**
AP_DBF(DBF_INFO, * ap_scan_bus(): Scan the AP bus for new devices
"no queue device with default domain %d available\n", * Runs periodically, workqueue timer (ap_config_time)
ap_domain_index); */
static void ap_scan_bus(struct work_struct *unused)
{
int id;
AP_DBF(DBF_DEBUG, "%s running\n", __func__);
ap_query_configuration(ap_configuration);
ap_select_domain();
/* loop over all possible adapters */
for (id = 0; id < AP_DEVICES; id++)
_ap_scan_bus_adapter(id);
/* 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); mod_timer(&ap_config_timer, jiffies + ap_config_time * HZ);
} }
......
...@@ -14,6 +14,9 @@ ...@@ -14,6 +14,9 @@
#include <asm/facility.h> #include <asm/facility.h>
#include "ap_bus.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. * ap_queue_enable_interruption(): Enable interruption on an AP queue.
...@@ -541,7 +544,25 @@ static ssize_t reset_show(struct device *dev, ...@@ -541,7 +544,25 @@ static ssize_t reset_show(struct device *dev,
return rc; 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, static ssize_t interrupt_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include <linux/mod_devicetable.h> #include <linux/mod_devicetable.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/string.h> #include <linux/string.h>
#include <asm/facility.h>
#include "vfio_ap_private.h" #include "vfio_ap_private.h"
#define VFIO_AP_ROOT_NAME "vfio_ap" #define VFIO_AP_ROOT_NAME "vfio_ap"
......
...@@ -51,6 +51,7 @@ struct error_hdr { ...@@ -51,6 +51,7 @@ struct error_hdr {
#define REP82_ERROR_FORMAT_FIELD 0x29 #define REP82_ERROR_FORMAT_FIELD 0x29
#define REP82_ERROR_INVALID_COMMAND 0x30 #define REP82_ERROR_INVALID_COMMAND 0x30
#define REP82_ERROR_MALFORMED_MSG 0x40 #define REP82_ERROR_MALFORMED_MSG 0x40
#define REP82_ERROR_INVALID_SPECIAL_CMD 0x41
#define REP82_ERROR_INVALID_DOMAIN_PRECHECK 0x42 #define REP82_ERROR_INVALID_DOMAIN_PRECHECK 0x42
#define REP82_ERROR_RESERVED_FIELDO 0x50 /* old value */ #define REP82_ERROR_RESERVED_FIELDO 0x50 /* old value */
#define REP82_ERROR_WORD_ALIGNMENT 0x60 #define REP82_ERROR_WORD_ALIGNMENT 0x60
...@@ -89,6 +90,7 @@ static inline int convert_error(struct zcrypt_queue *zq, ...@@ -89,6 +90,7 @@ static inline int convert_error(struct zcrypt_queue *zq,
case REP88_ERROR_MESSAGE_MALFORMD: case REP88_ERROR_MESSAGE_MALFORMD:
case REP82_ERROR_INVALID_DOMAIN_PRECHECK: case REP82_ERROR_INVALID_DOMAIN_PRECHECK:
case REP82_ERROR_INVALID_DOMAIN_PENDING: case REP82_ERROR_INVALID_DOMAIN_PENDING:
case REP82_ERROR_INVALID_SPECIAL_CMD:
// REP88_ERROR_INVALID_KEY // '82' CEX2A // REP88_ERROR_INVALID_KEY // '82' CEX2A
// REP88_ERROR_OPERAND // '84' CEX2A // REP88_ERROR_OPERAND // '84' CEX2A
// REP88_ERROR_OPERAND_EVEN_MOD // '85' CEX2A // REP88_ERROR_OPERAND_EVEN_MOD // '85' CEX2A
......
...@@ -2,7 +2,8 @@ ...@@ -2,7 +2,8 @@
/* /*
* lib/bust_spinlocks.c * 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() * bust_spinlocks() clears any spinlocks which would prevent oops, die(), BUG()
* and panic() information from reaching the user. * and panic() information from reaching the user.
...@@ -16,8 +17,7 @@ ...@@ -16,8 +17,7 @@
#include <linux/vt_kern.h> #include <linux/vt_kern.h>
#include <linux/console.h> #include <linux/console.h>
void bust_spinlocks(int yes)
void __attribute__((weak)) bust_spinlocks(int yes)
{ {
if (yes) { if (yes) {
++oops_in_progress; ++oops_in_progress;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment