|
@@ -58,7 +58,7 @@ static inline void ap_schedule_poll_timer(void);
|
|
|
static int __ap_poll_device(struct ap_device *ap_dev, unsigned long *flags);
|
|
|
static int ap_device_remove(struct device *dev);
|
|
|
static int ap_device_probe(struct device *dev);
|
|
|
-static void ap_interrupt_handler(void *unused1, void *unused2);
|
|
|
+static void ap_interrupt_handler(struct airq_struct *airq);
|
|
|
static void ap_reset(struct ap_device *ap_dev);
|
|
|
static void ap_config_timeout(unsigned long ptr);
|
|
|
static int ap_select_domain(void);
|
|
@@ -106,7 +106,6 @@ static DECLARE_WAIT_QUEUE_HEAD(ap_poll_wait);
|
|
|
static struct task_struct *ap_poll_kthread = NULL;
|
|
|
static DEFINE_MUTEX(ap_poll_thread_mutex);
|
|
|
static DEFINE_SPINLOCK(ap_poll_timer_lock);
|
|
|
-static void *ap_interrupt_indicator;
|
|
|
static struct hrtimer ap_poll_timer;
|
|
|
/* In LPAR poll with 4kHz frequency. Poll every 250000 nanoseconds.
|
|
|
* If z/VM change to 1500000 nanoseconds to adjust to z/VM polling.*/
|
|
@@ -120,13 +119,21 @@ static int ap_suspend_flag;
|
|
|
static int user_set_domain = 0;
|
|
|
static struct bus_type ap_bus_type;
|
|
|
|
|
|
+/* Adapter interrupt definitions */
|
|
|
+static int ap_airq_flag;
|
|
|
+
|
|
|
+static struct airq_struct ap_airq = {
|
|
|
+ .handler = ap_interrupt_handler,
|
|
|
+ .isc = AP_ISC,
|
|
|
+};
|
|
|
+
|
|
|
/**
|
|
|
* ap_using_interrupts() - Returns non-zero if interrupt support is
|
|
|
* available.
|
|
|
*/
|
|
|
static inline int ap_using_interrupts(void)
|
|
|
{
|
|
|
- return ap_interrupt_indicator != NULL;
|
|
|
+ return ap_airq_flag;
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -588,7 +595,7 @@ static int ap_init_queue(ap_qid_t qid)
|
|
|
}
|
|
|
}
|
|
|
if (rc == 0 && ap_using_interrupts()) {
|
|
|
- rc = ap_queue_enable_interruption(qid, ap_interrupt_indicator);
|
|
|
+ rc = ap_queue_enable_interruption(qid, ap_airq.lsi_ptr);
|
|
|
/* If interruption mode is supported by the machine,
|
|
|
* but an AP can not be enabled for interruption then
|
|
|
* the AP will be discarded. */
|
|
@@ -821,13 +828,22 @@ static int ap_bus_suspend(struct device *dev, pm_message_t state)
|
|
|
|
|
|
static int ap_bus_resume(struct device *dev)
|
|
|
{
|
|
|
- int rc = 0;
|
|
|
struct ap_device *ap_dev = to_ap_dev(dev);
|
|
|
+ int rc;
|
|
|
|
|
|
if (ap_suspend_flag) {
|
|
|
ap_suspend_flag = 0;
|
|
|
- if (!ap_interrupts_available())
|
|
|
- ap_interrupt_indicator = NULL;
|
|
|
+ if (ap_interrupts_available()) {
|
|
|
+ if (!ap_using_interrupts()) {
|
|
|
+ rc = register_adapter_interrupt(&ap_airq);
|
|
|
+ ap_airq_flag = (rc == 0);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if (ap_using_interrupts()) {
|
|
|
+ unregister_adapter_interrupt(&ap_airq);
|
|
|
+ ap_airq_flag = 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
ap_query_configuration();
|
|
|
if (!user_set_domain) {
|
|
|
ap_domain_index = -1;
|
|
@@ -848,7 +864,10 @@ static int ap_bus_resume(struct device *dev)
|
|
|
tasklet_schedule(&ap_tasklet);
|
|
|
if (ap_thread_flag)
|
|
|
rc = ap_poll_thread_start();
|
|
|
- }
|
|
|
+ else
|
|
|
+ rc = 0;
|
|
|
+ } else
|
|
|
+ rc = 0;
|
|
|
if (AP_QID_QUEUE(ap_dev->qid) != ap_domain_index) {
|
|
|
spin_lock_bh(&ap_dev->lock);
|
|
|
ap_dev->qid = AP_MKQID(AP_QID_DEVICE(ap_dev->qid),
|
|
@@ -1266,7 +1285,7 @@ out:
|
|
|
return rc;
|
|
|
}
|
|
|
|
|
|
-static void ap_interrupt_handler(void *unused1, void *unused2)
|
|
|
+static void ap_interrupt_handler(struct airq_struct *airq)
|
|
|
{
|
|
|
inc_irq_stat(IRQIO_APB);
|
|
|
tasklet_schedule(&ap_tasklet);
|
|
@@ -1722,7 +1741,7 @@ static void ap_poll_all(unsigned long dummy)
|
|
|
* important that no requests on any AP get lost.
|
|
|
*/
|
|
|
if (ap_using_interrupts())
|
|
|
- xchg((u8 *)ap_interrupt_indicator, 0);
|
|
|
+ xchg(ap_airq.lsi_ptr, 0);
|
|
|
do {
|
|
|
flags = 0;
|
|
|
spin_lock(&ap_device_list_lock);
|
|
@@ -1881,13 +1900,8 @@ int __init ap_module_init(void)
|
|
|
return -ENODEV;
|
|
|
}
|
|
|
if (ap_interrupts_available()) {
|
|
|
- isc_register(AP_ISC);
|
|
|
- ap_interrupt_indicator = s390_register_adapter_interrupt(
|
|
|
- &ap_interrupt_handler, NULL, AP_ISC);
|
|
|
- if (IS_ERR(ap_interrupt_indicator)) {
|
|
|
- ap_interrupt_indicator = NULL;
|
|
|
- isc_unregister(AP_ISC);
|
|
|
- }
|
|
|
+ rc = register_adapter_interrupt(&ap_airq);
|
|
|
+ ap_airq_flag = (rc == 0);
|
|
|
}
|
|
|
|
|
|
register_reset_call(&ap_reset_call);
|
|
@@ -1955,10 +1969,8 @@ out_bus:
|
|
|
bus_unregister(&ap_bus_type);
|
|
|
out:
|
|
|
unregister_reset_call(&ap_reset_call);
|
|
|
- if (ap_using_interrupts()) {
|
|
|
- s390_unregister_adapter_interrupt(ap_interrupt_indicator, AP_ISC);
|
|
|
- isc_unregister(AP_ISC);
|
|
|
- }
|
|
|
+ if (ap_using_interrupts())
|
|
|
+ unregister_adapter_interrupt(&ap_airq);
|
|
|
return rc;
|
|
|
}
|
|
|
|
|
@@ -1994,10 +2006,8 @@ void ap_module_exit(void)
|
|
|
bus_remove_file(&ap_bus_type, ap_bus_attrs[i]);
|
|
|
bus_unregister(&ap_bus_type);
|
|
|
unregister_reset_call(&ap_reset_call);
|
|
|
- if (ap_using_interrupts()) {
|
|
|
- s390_unregister_adapter_interrupt(ap_interrupt_indicator, AP_ISC);
|
|
|
- isc_unregister(AP_ISC);
|
|
|
- }
|
|
|
+ if (ap_using_interrupts())
|
|
|
+ unregister_adapter_interrupt(&ap_airq);
|
|
|
}
|
|
|
|
|
|
module_init(ap_module_init);
|