Commit 4fea49a7 authored by Alexandra Winter's avatar Alexandra Winter Committed by David S. Miller

s390/cio: Add new Operation Code OC3 to PNSO

Add support for operation code 3 (OC3) of the
Perform-Network-Subchannel-Operations (PNSO) function
of the Channel-Subsystem-Call (CHSC) instruction.

PNSO provides 2 operation codes:
OC0 - BRIDGE_INFO
OC3 - ADDR_INFO (new)

Extend the function calls to *pnso* to pass the OC and
add new response code 0108.

Support for OC3 is indicated by a flag in the css_general_characteristics.
Signed-off-by: default avatarAlexandra Winter <wintera@linux.ibm.com>
Reviewed-by: default avatarJulian Wiedmann <jwi@linux.ibm.com>
Reviewed-by: default avatarPeter Oberparleiter <oberpar@linux.ibm.com>
Reviewed-by: default avatarVineeth Vijayan <vneethv@linux.ibm.com>
Signed-off-by: default avatarJulian Wiedmann <jwi@linux.ibm.com>
Acked-by: default avatarHeiko Carstens <hca@linux.ibm.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent afb83012
...@@ -238,7 +238,6 @@ extern void ccw_device_get_schid(struct ccw_device *, struct subchannel_id *); ...@@ -238,7 +238,6 @@ extern void ccw_device_get_schid(struct ccw_device *, struct subchannel_id *);
struct channel_path_desc_fmt0 *ccw_device_get_chp_desc(struct ccw_device *, int); struct channel_path_desc_fmt0 *ccw_device_get_chp_desc(struct ccw_device *, int);
u8 *ccw_device_get_util_str(struct ccw_device *cdev, int chp_idx); u8 *ccw_device_get_util_str(struct ccw_device *cdev, int chp_idx);
int ccw_device_pnso(struct ccw_device *cdev, int ccw_device_pnso(struct ccw_device *cdev,
struct chsc_pnso_area *pnso_area, struct chsc_pnso_area *pnso_area, u8 oc,
struct chsc_pnso_resume_token resume_token, struct chsc_pnso_resume_token resume_token, int cnc);
int cnc);
#endif /* _S390_CCWDEV_H_ */ #endif /* _S390_CCWDEV_H_ */
...@@ -11,6 +11,13 @@ ...@@ -11,6 +11,13 @@
#include <uapi/asm/chsc.h> #include <uapi/asm/chsc.h>
/**
* Operation codes for CHSC PNSO:
* PNSO_OC_NET_BRIDGE_INFO - only addresses that are visible to a bridgeport
* PNSO_OC_NET_ADDR_INFO - all addresses
*/
#define PNSO_OC_NET_BRIDGE_INFO 0
#define PNSO_OC_NET_ADDR_INFO 3
/** /**
* struct chsc_pnso_naid_l2 - network address information descriptor * struct chsc_pnso_naid_l2 - network address information descriptor
* @nit: Network interface token * @nit: Network interface token
......
...@@ -36,7 +36,9 @@ struct css_general_char { ...@@ -36,7 +36,9 @@ struct css_general_char {
u64 alt_ssi : 1; /* bit 108 */ u64 alt_ssi : 1; /* bit 108 */
u64 : 1; u64 : 1;
u64 narf : 1; /* bit 110 */ u64 narf : 1; /* bit 110 */
u64 : 12; u64 : 5;
u64 enarf: 1; /* bit 116 */
u64 : 6;
u64 util_str : 1;/* bit 123 */ u64 util_str : 1;/* bit 123 */
} __packed; } __packed;
......
...@@ -65,6 +65,8 @@ int chsc_error_from_response(int response) ...@@ -65,6 +65,8 @@ int chsc_error_from_response(int response)
case 0x0100: case 0x0100:
case 0x0102: case 0x0102:
return -ENOMEM; return -ENOMEM;
case 0x0108: /* "HW limit exceeded" for the op 0x003d */
return -EUSERS;
default: default:
return -EIO; return -EIO;
} }
...@@ -1340,6 +1342,7 @@ EXPORT_SYMBOL_GPL(chsc_scm_info); ...@@ -1340,6 +1342,7 @@ EXPORT_SYMBOL_GPL(chsc_scm_info);
* chsc_pnso() - Perform Network-Subchannel Operation * chsc_pnso() - Perform Network-Subchannel Operation
* @schid: id of the subchannel on which PNSO is performed * @schid: id of the subchannel on which PNSO is performed
* @pnso_area: request and response block for the operation * @pnso_area: request and response block for the operation
* @oc: Operation Code
* @resume_token: resume token for multiblock response * @resume_token: resume token for multiblock response
* @cnc: Boolean change-notification control * @cnc: Boolean change-notification control
* *
...@@ -1347,10 +1350,8 @@ EXPORT_SYMBOL_GPL(chsc_scm_info); ...@@ -1347,10 +1350,8 @@ EXPORT_SYMBOL_GPL(chsc_scm_info);
* *
* Returns 0 on success. * Returns 0 on success.
*/ */
int chsc_pnso(struct subchannel_id schid, int chsc_pnso(struct subchannel_id schid, struct chsc_pnso_area *pnso_area,
struct chsc_pnso_area *pnso_area, u8 oc, struct chsc_pnso_resume_token resume_token, int cnc)
struct chsc_pnso_resume_token resume_token,
int cnc)
{ {
memset(pnso_area, 0, sizeof(*pnso_area)); memset(pnso_area, 0, sizeof(*pnso_area));
pnso_area->request.length = 0x0030; pnso_area->request.length = 0x0030;
...@@ -1359,7 +1360,7 @@ int chsc_pnso(struct subchannel_id schid, ...@@ -1359,7 +1360,7 @@ int chsc_pnso(struct subchannel_id schid,
pnso_area->ssid = schid.ssid; pnso_area->ssid = schid.ssid;
pnso_area->sch = schid.sch_no; pnso_area->sch = schid.sch_no;
pnso_area->cssid = schid.cssid; pnso_area->cssid = schid.cssid;
pnso_area->oc = 0; /* Store-network-bridging-information list */ pnso_area->oc = oc;
pnso_area->resume_token = resume_token; pnso_area->resume_token = resume_token;
pnso_area->n = (cnc != 0); pnso_area->n = (cnc != 0);
if (chsc(pnso_area)) if (chsc(pnso_area))
......
...@@ -205,10 +205,8 @@ struct chsc_scm_info { ...@@ -205,10 +205,8 @@ struct chsc_scm_info {
int chsc_scm_info(struct chsc_scm_info *scm_area, u64 token); int chsc_scm_info(struct chsc_scm_info *scm_area, u64 token);
int chsc_pnso(struct subchannel_id schid, int chsc_pnso(struct subchannel_id schid, struct chsc_pnso_area *pnso_area,
struct chsc_pnso_area *pnso_area, u8 oc, struct chsc_pnso_resume_token resume_token, int cnc);
struct chsc_pnso_resume_token resume_token,
int cnc);
int __init chsc_get_cssid(int idx); int __init chsc_get_cssid(int idx);
......
...@@ -714,6 +714,7 @@ EXPORT_SYMBOL_GPL(ccw_device_get_schid); ...@@ -714,6 +714,7 @@ EXPORT_SYMBOL_GPL(ccw_device_get_schid);
* ccw_device_pnso() - Perform Network-Subchannel Operation * ccw_device_pnso() - Perform Network-Subchannel Operation
* @cdev: device on which PNSO is performed * @cdev: device on which PNSO is performed
* @pnso_area: request and response block for the operation * @pnso_area: request and response block for the operation
* @oc: Operation Code
* @resume_token: resume token for multiblock response * @resume_token: resume token for multiblock response
* @cnc: Boolean change-notification control * @cnc: Boolean change-notification control
* *
...@@ -722,14 +723,13 @@ EXPORT_SYMBOL_GPL(ccw_device_get_schid); ...@@ -722,14 +723,13 @@ EXPORT_SYMBOL_GPL(ccw_device_get_schid);
* Returns 0 on success. * Returns 0 on success.
*/ */
int ccw_device_pnso(struct ccw_device *cdev, int ccw_device_pnso(struct ccw_device *cdev,
struct chsc_pnso_area *pnso_area, struct chsc_pnso_area *pnso_area, u8 oc,
struct chsc_pnso_resume_token resume_token, struct chsc_pnso_resume_token resume_token, int cnc)
int cnc)
{ {
struct subchannel_id schid; struct subchannel_id schid;
ccw_device_get_schid(cdev, &schid); ccw_device_get_schid(cdev, &schid);
return chsc_pnso(schid, pnso_area, resume_token, cnc); return chsc_pnso(schid, pnso_area, oc, resume_token, cnc);
} }
EXPORT_SYMBOL_GPL(ccw_device_pnso); EXPORT_SYMBOL_GPL(ccw_device_pnso);
......
...@@ -642,6 +642,7 @@ static void qeth_l2_set_rx_mode(struct net_device *dev) ...@@ -642,6 +642,7 @@ static void qeth_l2_set_rx_mode(struct net_device *dev)
/** /**
* qeth_l2_pnso() - perform network subchannel operation * qeth_l2_pnso() - perform network subchannel operation
* @card: qeth_card structure pointer * @card: qeth_card structure pointer
* @oc: Operation Code
* @cnc: Boolean Change-Notification Control * @cnc: Boolean Change-Notification Control
* @cb: Callback function will be executed for each element * @cb: Callback function will be executed for each element
* of the address list * of the address list
...@@ -652,7 +653,7 @@ static void qeth_l2_set_rx_mode(struct net_device *dev) ...@@ -652,7 +653,7 @@ static void qeth_l2_set_rx_mode(struct net_device *dev)
* control" is set, further changes in the address list will be reported * control" is set, further changes in the address list will be reported
* via the IPA command. * via the IPA command.
*/ */
static int qeth_l2_pnso(struct qeth_card *card, int cnc, static int qeth_l2_pnso(struct qeth_card *card, u8 oc, int cnc,
void (*cb)(void *priv, struct chsc_pnso_naid_l2 *entry), void (*cb)(void *priv, struct chsc_pnso_naid_l2 *entry),
void *priv) void *priv)
{ {
...@@ -663,13 +664,14 @@ static int qeth_l2_pnso(struct qeth_card *card, int cnc, ...@@ -663,13 +664,14 @@ static int qeth_l2_pnso(struct qeth_card *card, int cnc,
int i, size, elems; int i, size, elems;
int rc; int rc;
QETH_CARD_TEXT(card, 2, "PNSO");
rr = (struct chsc_pnso_area *)get_zeroed_page(GFP_KERNEL); rr = (struct chsc_pnso_area *)get_zeroed_page(GFP_KERNEL);
if (rr == NULL) if (rr == NULL)
return -ENOMEM; return -ENOMEM;
do { do {
QETH_CARD_TEXT(card, 2, "PNSO");
/* on the first iteration, naihdr.resume_token will be zero */ /* on the first iteration, naihdr.resume_token will be zero */
rc = ccw_device_pnso(ddev, rr, rr->naihdr.resume_token, cnc); rc = ccw_device_pnso(ddev, rr, oc, rr->naihdr.resume_token,
cnc);
if (rc) if (rc)
continue; continue;
if (cb == NULL) if (cb == NULL)
...@@ -1578,11 +1580,12 @@ int qeth_bridgeport_an_set(struct qeth_card *card, int enable) ...@@ -1578,11 +1580,12 @@ int qeth_bridgeport_an_set(struct qeth_card *card, int enable)
if (enable) { if (enable) {
qeth_bridge_emit_host_event(card, anev_reset, 0, NULL, NULL); qeth_bridge_emit_host_event(card, anev_reset, 0, NULL, NULL);
qeth_l2_set_pnso_mode(card, QETH_PNSO_BRIDGEPORT); qeth_l2_set_pnso_mode(card, QETH_PNSO_BRIDGEPORT);
rc = qeth_l2_pnso(card, 1, qeth_bridgeport_an_set_cb, card); rc = qeth_l2_pnso(card, PNSO_OC_NET_BRIDGE_INFO, 1,
qeth_bridgeport_an_set_cb, card);
if (rc) if (rc)
qeth_l2_set_pnso_mode(card, QETH_PNSO_NONE); qeth_l2_set_pnso_mode(card, QETH_PNSO_NONE);
} else { } else {
rc = qeth_l2_pnso(card, 0, NULL, NULL); rc = qeth_l2_pnso(card, PNSO_OC_NET_BRIDGE_INFO, 0, NULL, NULL);
qeth_l2_set_pnso_mode(card, QETH_PNSO_NONE); qeth_l2_set_pnso_mode(card, QETH_PNSO_NONE);
} }
return rc; return rc;
......
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