summaryrefslogtreecommitdiffstats
path: root/drivers/s390/cio
diff options
context:
space:
mode:
authorAlexandra Winter <wintera@linux.ibm.com>2020-04-16 15:08:41 +0200
committerVasily Gorbik <gor@linux.ibm.com>2020-05-28 12:21:55 +0200
commita0138f59265aff4a21356ba9319171f421575b52 (patch)
treec0fa1a104a00676a0f76a16a29ef0b6d05df04d8 /drivers/s390/cio
parentcafebf8653b3d689b3411daa0d3d7b67fc4f2edb (diff)
s390/cio, s390/qeth: cleanup PNSO CHSC
CHSC3D (PNSO - perform network subchannel operation) is used for OC0 (Store-network-bridging-information) as well as for OC3 (Store-network-address-information). So common fields are renamed from *brinfo* to *pnso*. Also *_bridge_host_* is changed into *_addr_change_*, e.g. qeth_bridge_host_event to qeth_addr_change_event, for the same reasons. The keywords in the card traces are changed accordingly. Remove unused L3 types, as PNSO will only return Layer2 entries. Make PNSO CHSC implementation more consistent with existing API usage: Add new function ccw_device_pnso() to drivers/s390/cio/device_ops.c and the function declaration to arch/s390/include/asm/ccwdev.h, which takes a struct ccw_device * as parameter instead of schid and calls chsc_pnso(). PNSO CHSC has no strict relationship to qdio. So move the calling function from qdio to qeth_l2 and move the necessary structures to a new file arch/s390/include/asm/chsc.h. Do response code evaluation only in chsc_error_from_response() and use return code in all other places. qeth_anset_makerc() was meant to evaluate the PNSO response code, but never did, because pnso_rc was already non-zero. Indentation was corrected in some places. Signed-off-by: Alexandra Winter <wintera@linux.ibm.com> Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com> Reviewed-by: Vineeth Vijayan <vneethv@linux.ibm.com> Reviewed-by: Julian Wiedmann <jwi@linux.ibm.com> Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
Diffstat (limited to 'drivers/s390/cio')
-rw-r--r--drivers/s390/cio/chsc.c40
-rw-r--r--drivers/s390/cio/chsc.h50
-rw-r--r--drivers/s390/cio/device_ops.c23
-rw-r--r--drivers/s390/cio/qdio_main.c88
4 files changed, 47 insertions, 154 deletions
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c
index 1ca73c2e5a8f..c314e9495c1b 100644
--- a/drivers/s390/cio/chsc.c
+++ b/drivers/s390/cio/chsc.c
@@ -57,6 +57,7 @@ int chsc_error_from_response(int response)
case 0x0104:
return -EINVAL;
case 0x0004:
+ case 0x0106: /* "Wrong Channel Parm" for the op 0x003d */
return -EOPNOTSUPP;
case 0x000b:
case 0x0107: /* "Channel busy" for the op 0x003d */
@@ -1336,36 +1337,35 @@ out:
EXPORT_SYMBOL_GPL(chsc_scm_info);
/**
- * chsc_pnso_brinfo() - Perform Network-Subchannel Operation, Bridge Info.
+ * chsc_pnso() - Perform Network-Subchannel Operation
* @schid: id of the subchannel on which PNSO is performed
- * @brinfo_area: request and response block for the operation
+ * @pnso_area: request and response block for the operation
* @resume_token: resume token for multiblock response
* @cnc: Boolean change-notification control
*
- * brinfo_area must be allocated by the caller with get_zeroed_page(GFP_KERNEL)
+ * pnso_area must be allocated by the caller with get_zeroed_page(GFP_KERNEL)
*
* Returns 0 on success.
*/
-int chsc_pnso_brinfo(struct subchannel_id schid,
- struct chsc_pnso_area *brinfo_area,
- struct chsc_brinfo_resume_token resume_token,
- int cnc)
+int chsc_pnso(struct subchannel_id schid,
+ struct chsc_pnso_area *pnso_area,
+ struct chsc_pnso_resume_token resume_token,
+ int cnc)
{
- memset(brinfo_area, 0, sizeof(*brinfo_area));
- brinfo_area->request.length = 0x0030;
- brinfo_area->request.code = 0x003d; /* network-subchannel operation */
- brinfo_area->m = schid.m;
- brinfo_area->ssid = schid.ssid;
- brinfo_area->sch = schid.sch_no;
- brinfo_area->cssid = schid.cssid;
- brinfo_area->oc = 0; /* Store-network-bridging-information list */
- brinfo_area->resume_token = resume_token;
- brinfo_area->n = (cnc != 0);
- if (chsc(brinfo_area))
+ memset(pnso_area, 0, sizeof(*pnso_area));
+ pnso_area->request.length = 0x0030;
+ pnso_area->request.code = 0x003d; /* network-subchannel operation */
+ pnso_area->m = schid.m;
+ 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->resume_token = resume_token;
+ pnso_area->n = (cnc != 0);
+ if (chsc(pnso_area))
return -EIO;
- return chsc_error_from_response(brinfo_area->response.code);
+ return chsc_error_from_response(pnso_area->response.code);
}
-EXPORT_SYMBOL_GPL(chsc_pnso_brinfo);
int chsc_sgib(u32 origin)
{
diff --git a/drivers/s390/cio/chsc.h b/drivers/s390/cio/chsc.h
index 34de6d77442c..7ecf7e4c402e 100644
--- a/drivers/s390/cio/chsc.h
+++ b/drivers/s390/cio/chsc.h
@@ -205,52 +205,10 @@ struct chsc_scm_info {
int chsc_scm_info(struct chsc_scm_info *scm_area, u64 token);
-struct chsc_brinfo_resume_token {
- u64 t1;
- u64 t2;
-} __packed;
-
-struct chsc_brinfo_naihdr {
- struct chsc_brinfo_resume_token resume_token;
- u32:32;
- u32 instance;
- u32:24;
- u8 naids;
- u32 reserved[3];
-} __packed;
-
-struct chsc_pnso_area {
- struct chsc_header request;
- u8:2;
- u8 m:1;
- u8:5;
- u8:2;
- u8 ssid:2;
- u8 fmt:4;
- u16 sch;
- u8:8;
- u8 cssid;
- u16:16;
- u8 oc;
- u32:24;
- struct chsc_brinfo_resume_token resume_token;
- u32 n:1;
- u32:31;
- u32 reserved[3];
- struct chsc_header response;
- u32:32;
- struct chsc_brinfo_naihdr naihdr;
- union {
- struct qdio_brinfo_entry_l3_ipv6 l3_ipv6[0];
- struct qdio_brinfo_entry_l3_ipv4 l3_ipv4[0];
- struct qdio_brinfo_entry_l2 l2[0];
- } entries;
-} __packed __aligned(PAGE_SIZE);
-
-int chsc_pnso_brinfo(struct subchannel_id schid,
- struct chsc_pnso_area *brinfo_area,
- struct chsc_brinfo_resume_token resume_token,
- int cnc);
+int chsc_pnso(struct subchannel_id schid,
+ struct chsc_pnso_area *pnso_area,
+ struct chsc_pnso_resume_token resume_token,
+ int cnc);
int __init chsc_get_cssid(int idx);
diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c
index ccecf6b9504e..963fcc9054c6 100644
--- a/drivers/s390/cio/device_ops.c
+++ b/drivers/s390/cio/device_ops.c
@@ -710,6 +710,29 @@ void ccw_device_get_schid(struct ccw_device *cdev, struct subchannel_id *schid)
}
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
+ * @resume_token: resume token for multiblock response
+ * @cnc: Boolean change-notification control
+ *
+ * pnso_area must be allocated by the caller with get_zeroed_page(GFP_KERNEL)
+ *
+ * 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 subchannel_id schid;
+
+ ccw_device_get_schid(cdev, &schid);
+ return chsc_pnso(schid, pnso_area, resume_token, cnc);
+}
+EXPORT_SYMBOL_GPL(ccw_device_pnso);
+
/*
* Allocate zeroed dma coherent 31 bit addressable memory using
* the subchannels dma pool. Maximal size of allocation supported
diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c
index b0e84fba54dd..610c05f59589 100644
--- a/drivers/s390/cio/qdio_main.c
+++ b/drivers/s390/cio/qdio_main.c
@@ -1705,94 +1705,6 @@ int qdio_stop_irq(struct ccw_device *cdev)
}
EXPORT_SYMBOL(qdio_stop_irq);
-/**
- * qdio_pnso_brinfo() - perform network subchannel op #0 - bridge info.
- * @schid: Subchannel ID.
- * @cnc: Boolean Change-Notification Control
- * @response: Response code will be stored at this address
- * @cb: Callback function will be executed for each element
- * of the address list
- * @priv: Pointer to pass to the callback function.
- *
- * Performs "Store-network-bridging-information list" operation and calls
- * the callback function for every entry in the list. If "change-
- * notification-control" is set, further changes in the address list
- * will be reported via the IPA command.
- */
-int qdio_pnso_brinfo(struct subchannel_id schid,
- int cnc, u16 *response,
- void (*cb)(void *priv, enum qdio_brinfo_entry_type type,
- void *entry),
- void *priv)
-{
- struct chsc_pnso_area *rr;
- int rc;
- u32 prev_instance = 0;
- int isfirstblock = 1;
- int i, size, elems;
-
- rr = (struct chsc_pnso_area *)get_zeroed_page(GFP_KERNEL);
- if (rr == NULL)
- return -ENOMEM;
- do {
- /* on the first iteration, naihdr.resume_token will be zero */
- rc = chsc_pnso_brinfo(schid, rr, rr->naihdr.resume_token, cnc);
- if (rc != 0 && rc != -EBUSY)
- goto out;
- if (rr->response.code != 1) {
- rc = -EIO;
- continue;
- } else
- rc = 0;
-
- if (cb == NULL)
- continue;
-
- size = rr->naihdr.naids;
- elems = (rr->response.length -
- sizeof(struct chsc_header) -
- sizeof(struct chsc_brinfo_naihdr)) /
- size;
-
- if (!isfirstblock && (rr->naihdr.instance != prev_instance)) {
- /* Inform the caller that they need to scrap */
- /* the data that was already reported via cb */
- rc = -EAGAIN;
- break;
- }
- isfirstblock = 0;
- prev_instance = rr->naihdr.instance;
- for (i = 0; i < elems; i++)
- switch (size) {
- case sizeof(struct qdio_brinfo_entry_l3_ipv6):
- (*cb)(priv, l3_ipv6_addr,
- &rr->entries.l3_ipv6[i]);
- break;
- case sizeof(struct qdio_brinfo_entry_l3_ipv4):
- (*cb)(priv, l3_ipv4_addr,
- &rr->entries.l3_ipv4[i]);
- break;
- case sizeof(struct qdio_brinfo_entry_l2):
- (*cb)(priv, l2_addr_lnid,
- &rr->entries.l2[i]);
- break;
- default:
- WARN_ON_ONCE(1);
- rc = -EIO;
- goto out;
- }
- } while (rr->response.code == 0x0107 || /* channel busy */
- (rr->response.code == 1 && /* list stored */
- /* resume token is non-zero => list incomplete */
- (rr->naihdr.resume_token.t1 || rr->naihdr.resume_token.t2)));
- (*response) = rr->response.code;
-
-out:
- free_page((unsigned long)rr);
- return rc;
-}
-EXPORT_SYMBOL_GPL(qdio_pnso_brinfo);
-
static int __init init_QDIO(void)
{
int rc;