s390/cio: Add new Operation Code OC3 to PNSO
authorAlexandra Winter <wintera@linux.ibm.com>
Thu, 10 Sep 2020 17:23:44 +0000 (19:23 +0200)
committerDavid S. Miller <davem@davemloft.net>
Tue, 15 Sep 2020 20:21:46 +0000 (13:21 -0700)
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: Alexandra Winter <wintera@linux.ibm.com>
Reviewed-by: Julian Wiedmann <jwi@linux.ibm.com>
Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Reviewed-by: Vineeth Vijayan <vneethv@linux.ibm.com>
Signed-off-by: Julian Wiedmann <jwi@linux.ibm.com>
Acked-by: Heiko Carstens <hca@linux.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
arch/s390/include/asm/ccwdev.h
arch/s390/include/asm/chsc.h
arch/s390/include/asm/css_chars.h
drivers/s390/cio/chsc.c
drivers/s390/cio/chsc.h
drivers/s390/cio/device_ops.c
drivers/s390/net/qeth_l2_main.c

index 3cfe1eb..9739a00 100644 (file)
@@ -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);
 u8 *ccw_device_get_util_str(struct ccw_device *cdev, int chp_idx);
 int ccw_device_pnso(struct ccw_device *cdev,
-                   struct chsc_pnso_area *pnso_area,
-                   struct chsc_pnso_resume_token resume_token,
-                   int cnc);
+                   struct chsc_pnso_area *pnso_area, u8 oc,
+                   struct chsc_pnso_resume_token resume_token, int cnc);
 #endif /* _S390_CCWDEV_H_ */
index 36ce2d2..ae4d254 100644 (file)
 
 #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
  * @nit:  Network interface token
index 480bb02..638137d 100644 (file)
@@ -36,7 +36,9 @@ struct css_general_char {
        u64 alt_ssi : 1; /* bit 108 */
        u64 : 1;
        u64 narf : 1;    /* bit 110 */
-       u64 : 12;
+       u64 : 5;
+       u64 enarf: 1;    /* bit 116 */
+       u64 : 6;
        u64 util_str : 1;/* bit 123 */
 } __packed;
 
index c314e94..8f764a2 100644 (file)
@@ -65,6 +65,8 @@ int chsc_error_from_response(int response)
        case 0x0100:
        case 0x0102:
                return -ENOMEM;
+       case 0x0108:            /* "HW limit exceeded" for the op 0x003d */
+               return -EUSERS;
        default:
                return -EIO;
        }
@@ -1340,6 +1342,7 @@ EXPORT_SYMBOL_GPL(chsc_scm_info);
  * chsc_pnso() - Perform Network-Subchannel Operation
  * @schid:             id of the subchannel on which PNSO is performed
  * @pnso_area:         request and response block for the operation
+ * @oc:                        Operation Code
  * @resume_token:      resume token for multiblock response
  * @cnc:               Boolean change-notification control
  *
@@ -1347,10 +1350,8 @@ EXPORT_SYMBOL_GPL(chsc_scm_info);
  *
  * Returns 0 on success.
  */
-int chsc_pnso(struct subchannel_id schid,
-             struct chsc_pnso_area *pnso_area,
-             struct chsc_pnso_resume_token resume_token,
-             int cnc)
+int chsc_pnso(struct subchannel_id schid, struct chsc_pnso_area *pnso_area,
+             u8 oc, struct chsc_pnso_resume_token resume_token, int cnc)
 {
        memset(pnso_area, 0, sizeof(*pnso_area));
        pnso_area->request.length = 0x0030;
@@ -1359,7 +1360,7 @@ int chsc_pnso(struct subchannel_id schid,
        pnso_area->ssid  = schid.ssid;
        pnso_area->sch   = schid.sch_no;
        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->n       = (cnc != 0);
        if (chsc(pnso_area))
index 7ecf7e4..7416957 100644 (file)
@@ -205,10 +205,8 @@ struct chsc_scm_info {
 
 int chsc_scm_info(struct chsc_scm_info *scm_area, u64 token);
 
-int chsc_pnso(struct subchannel_id schid,
-             struct chsc_pnso_area *pnso_area,
-             struct chsc_pnso_resume_token resume_token,
-             int cnc);
+int chsc_pnso(struct subchannel_id schid, struct chsc_pnso_area *pnso_area,
+             u8 oc, struct chsc_pnso_resume_token resume_token, int cnc);
 
 int __init chsc_get_cssid(int idx);
 
index 963fcc9..cdf44f3 100644 (file)
@@ -714,6 +714,7 @@ EXPORT_SYMBOL_GPL(ccw_device_get_schid);
  * ccw_device_pnso() - Perform Network-Subchannel Operation
  * @cdev:              device on which PNSO is performed
  * @pnso_area:         request and response block for the operation
+ * @oc:                        Operation Code
  * @resume_token:      resume token for multiblock response
  * @cnc:               Boolean change-notification control
  *
@@ -722,14 +723,13 @@ EXPORT_SYMBOL_GPL(ccw_device_get_schid);
  * Returns 0 on success.
  */
 int ccw_device_pnso(struct ccw_device *cdev,
-                   struct chsc_pnso_area *pnso_area,
-                   struct chsc_pnso_resume_token resume_token,
-                   int cnc)
+                   struct chsc_pnso_area *pnso_area, u8 oc,
+                   struct chsc_pnso_resume_token resume_token, int cnc)
 {
        struct subchannel_id 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);
 
index 4915780..2ab130d 100644 (file)
@@ -642,6 +642,7 @@ static void qeth_l2_set_rx_mode(struct net_device *dev)
 /**
  *     qeth_l2_pnso() - perform network subchannel operation
  *     @card: qeth_card structure pointer
+ *     @oc: Operation Code
  *     @cnc: Boolean Change-Notification Control
  *     @cb: Callback function will be executed for each element
  *             of the address list
@@ -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
  *     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 *priv)
 {
@@ -663,13 +664,14 @@ static int qeth_l2_pnso(struct qeth_card *card, int cnc,
        int i, size, elems;
        int rc;
 
-       QETH_CARD_TEXT(card, 2, "PNSO");
        rr = (struct chsc_pnso_area *)get_zeroed_page(GFP_KERNEL);
        if (rr == NULL)
                return -ENOMEM;
        do {
+               QETH_CARD_TEXT(card, 2, "PNSO");
                /* 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)
                        continue;
                if (cb == NULL)
@@ -1578,11 +1580,12 @@ int qeth_bridgeport_an_set(struct qeth_card *card, int enable)
        if (enable) {
                qeth_bridge_emit_host_event(card, anev_reset, 0, NULL, NULL);
                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)
                        qeth_l2_set_pnso_mode(card, QETH_PNSO_NONE);
        } 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);
        }
        return rc;