Commit 6bed05bc authored by Holger Dengler's avatar Holger Dengler Committed by Martin Schwidefsky

[S390] ap: toleration support for ap device type 10

Add toleration support for ap devices with device type 10.
Signed-off-by: default avatarHolger Dengler <hd@linux.vnet.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent fdb204d1
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
* Martin Schwidefsky <schwidefsky@de.ibm.com> * Martin Schwidefsky <schwidefsky@de.ibm.com>
* Ralph Wuerthner <rwuerthn@de.ibm.com> * Ralph Wuerthner <rwuerthn@de.ibm.com>
* Felix Beck <felix.beck@de.ibm.com> * Felix Beck <felix.beck@de.ibm.com>
* Holger Dengler <hd@linux.vnet.ibm.com>
* *
* Adjunct processor bus. * Adjunct processor bus.
* *
...@@ -222,47 +223,52 @@ ap_queue_interruption_control(ap_qid_t qid, void *ind) ...@@ -222,47 +223,52 @@ ap_queue_interruption_control(ap_qid_t qid, void *ind)
} }
#endif #endif
static inline struct ap_queue_status __ap_4096_commands_available(ap_qid_t qid, #ifdef CONFIG_64BIT
int *support) static inline struct ap_queue_status
__ap_query_functions(ap_qid_t qid, unsigned int *functions)
{ {
register unsigned long reg0 asm ("0") = 0UL | qid | (1UL << 23); register unsigned long reg0 asm ("0") = 0UL | qid | (1UL << 23);
register struct ap_queue_status reg1 asm ("1"); register struct ap_queue_status reg1 asm ("1") = AP_QUEUE_STATUS_INVALID;
register unsigned long reg2 asm ("2") = 0UL; register unsigned long reg2 asm ("2");
asm volatile( asm volatile(
".long 0xb2af0000\n" ".long 0xb2af0000\n"
"0: la %1,0\n" "0:\n"
"1:\n" EX_TABLE(0b, 0b)
EX_TABLE(0b, 1b) : "+d" (reg0), "+d" (reg1), "=d" (reg2)
: "+d" (reg0), "=d" (reg1), "=d" (reg2)
: :
: "cc"); : "cc");
if (reg2 & 0x6000000000000000ULL) *functions = (unsigned int)(reg2 >> 32);
*support = 1;
else
*support = 0;
return reg1; return reg1;
} }
#endif
/** /**
* ap_4096_commands_availablen(): Check for availability of 4096 bit RSA * ap_query_functions(): Query supported functions.
* support.
* @qid: The AP queue number * @qid: The AP queue number
* @functions: Pointer to functions field.
* *
* Returns 1 if 4096 bit RSA keys are support fo the AP, returns 0 if not. * Returns
* 0 on success.
* -ENODEV if queue not valid.
* -EBUSY if device busy.
* -EINVAL if query function is not supported
*/ */
int ap_4096_commands_available(ap_qid_t qid) static int ap_query_functions(ap_qid_t qid, unsigned int *functions)
{ {
#ifdef CONFIG_64BIT
struct ap_queue_status status; struct ap_queue_status status;
int i, support = 0; int i;
status = __ap_4096_commands_available(qid, &support); status = __ap_query_functions(qid, functions);
for (i = 0; i < AP_MAX_RESET; i++) { for (i = 0; i < AP_MAX_RESET; i++) {
if (ap_queue_status_invalid_test(&status))
return -ENODEV;
switch (status.response_code) { switch (status.response_code) {
case AP_RESPONSE_NORMAL: case AP_RESPONSE_NORMAL:
return support; return 0;
case AP_RESPONSE_RESET_IN_PROGRESS: case AP_RESPONSE_RESET_IN_PROGRESS:
case AP_RESPONSE_BUSY: case AP_RESPONSE_BUSY:
break; break;
...@@ -270,7 +276,7 @@ int ap_4096_commands_available(ap_qid_t qid) ...@@ -270,7 +276,7 @@ int ap_4096_commands_available(ap_qid_t qid)
case AP_RESPONSE_DECONFIGURED: case AP_RESPONSE_DECONFIGURED:
case AP_RESPONSE_CHECKSTOPPED: case AP_RESPONSE_CHECKSTOPPED:
case AP_RESPONSE_INVALID_ADDRESS: case AP_RESPONSE_INVALID_ADDRESS:
return 0; return -ENODEV;
case AP_RESPONSE_OTHERWISE_CHANGED: case AP_RESPONSE_OTHERWISE_CHANGED:
break; break;
default: default:
...@@ -278,10 +284,31 @@ int ap_4096_commands_available(ap_qid_t qid) ...@@ -278,10 +284,31 @@ int ap_4096_commands_available(ap_qid_t qid)
} }
if (i < AP_MAX_RESET - 1) { if (i < AP_MAX_RESET - 1) {
udelay(5); udelay(5);
status = __ap_4096_commands_available(qid, &support); status = __ap_query_functions(qid, functions);
} }
} }
return support; return -EBUSY;
#else
return -EINVAL;
#endif
}
/**
* ap_4096_commands_availablen(): Check for availability of 4096 bit RSA
* support.
* @qid: The AP queue number
*
* Returns 1 if 4096 bit RSA keys are support fo the AP, returns 0 if not.
*/
int ap_4096_commands_available(ap_qid_t qid)
{
unsigned int functions;
if (ap_query_functions(qid, &functions))
return 0;
return test_ap_facility(functions, 1) &&
test_ap_facility(functions, 2);
} }
EXPORT_SYMBOL(ap_4096_commands_available); EXPORT_SYMBOL(ap_4096_commands_available);
...@@ -1135,6 +1162,7 @@ static void ap_scan_bus(struct work_struct *unused) ...@@ -1135,6 +1162,7 @@ static void ap_scan_bus(struct work_struct *unused)
struct device *dev; struct device *dev;
ap_qid_t qid; ap_qid_t qid;
int queue_depth, device_type; int queue_depth, device_type;
unsigned int device_functions;
int rc, i; int rc, i;
if (ap_select_domain() != 0) if (ap_select_domain() != 0)
...@@ -1183,14 +1211,30 @@ static void ap_scan_bus(struct work_struct *unused) ...@@ -1183,14 +1211,30 @@ static void ap_scan_bus(struct work_struct *unused)
INIT_LIST_HEAD(&ap_dev->list); INIT_LIST_HEAD(&ap_dev->list);
setup_timer(&ap_dev->timeout, ap_request_timeout, setup_timer(&ap_dev->timeout, ap_request_timeout,
(unsigned long) ap_dev); (unsigned long) ap_dev);
if (device_type == 0) { switch (device_type) {
case 0:
if (ap_probe_device_type(ap_dev)) { if (ap_probe_device_type(ap_dev)) {
kfree(ap_dev); kfree(ap_dev);
continue; continue;
} }
} break;
else case 10:
if (ap_query_functions(qid, &device_functions)) {
kfree(ap_dev);
continue;
}
if (test_ap_facility(device_functions, 3))
ap_dev->device_type = AP_DEVICE_TYPE_CEX3C;
else if (test_ap_facility(device_functions, 4))
ap_dev->device_type = AP_DEVICE_TYPE_CEX3A;
else {
kfree(ap_dev);
continue;
}
break;
default:
ap_dev->device_type = device_type; ap_dev->device_type = device_type;
}
ap_dev->device.bus = &ap_bus_type; ap_dev->device.bus = &ap_bus_type;
ap_dev->device.parent = ap_root_device; ap_dev->device.parent = ap_root_device;
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
* Martin Schwidefsky <schwidefsky@de.ibm.com> * Martin Schwidefsky <schwidefsky@de.ibm.com>
* Ralph Wuerthner <rwuerthn@de.ibm.com> * Ralph Wuerthner <rwuerthn@de.ibm.com>
* Felix Beck <felix.beck@de.ibm.com> * Felix Beck <felix.beck@de.ibm.com>
* Holger Dengler <hd@linux.vnet.ibm.com>
* *
* Adjunct processor bus header file. * Adjunct processor bus header file.
* *
...@@ -72,7 +73,26 @@ struct ap_queue_status { ...@@ -72,7 +73,26 @@ struct ap_queue_status {
unsigned int int_enabled : 1; unsigned int int_enabled : 1;
unsigned int response_code : 8; unsigned int response_code : 8;
unsigned int pad2 : 16; unsigned int pad2 : 16;
}; } __packed;
#define AP_QUEUE_STATUS_INVALID \
{ 1, 1, 1, 0xF, 1, 0xFF, 0xFFFF }
static inline
int ap_queue_status_invalid_test(struct ap_queue_status *status)
{
struct ap_queue_status invalid = AP_QUEUE_STATUS_INVALID;
return !(memcmp(status, &invalid, sizeof(struct ap_queue_status)));
}
#define MAX_AP_FACILITY 31
static inline int test_ap_facility(unsigned int function, unsigned int nr)
{
if (nr > MAX_AP_FACILITY)
return 0;
return function & (unsigned int)(0x80000000 >> nr);
}
#define AP_RESPONSE_NORMAL 0x00 #define AP_RESPONSE_NORMAL 0x00
#define AP_RESPONSE_Q_NOT_AVAIL 0x01 #define AP_RESPONSE_Q_NOT_AVAIL 0x01
......
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