aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/net/qeth_core.h
diff options
context:
space:
mode:
authorJulian Wiedmann <jwi@linux.ibm.com>2018-06-29 19:45:53 +0200
committerDavid S. Miller <davem@davemloft.net>2018-06-30 21:19:48 +0900
commitce28867fd20c23cd769e78b4d619c4755bf71a1c (patch)
treed0adb3b90977c45f998bcd940996cc1462a1906b /drivers/s390/net/qeth_core.h
parents390/qeth: avoid using is_multicast_ether_addr_64bits on (u8 *)[6] (diff)
downloadlinux-dev-ce28867fd20c23cd769e78b4d619c4755bf71a1c.tar.xz
linux-dev-ce28867fd20c23cd769e78b4d619c4755bf71a1c.zip
s390/qeth: don't clobber buffer on async TX completion
If qeth_qdio_output_handler() detects that a transmit requires async completion, it replaces the pending buffer's metadata object (qeth_qdio_out_buffer) so that this queue buffer can be re-used while the data is pending completion. Later when the CQ indicates async completion of such a metadata object, qeth_qdio_cq_handler() tries to free any data associated with this object (since HW has now completed the transfer). By calling qeth_clear_output_buffer(), it erronously operates on the queue buffer that _previously_ belonged to this transfer ... but which has been potentially re-used several times by now. This results in double-free's of the buffer's data, and failing transmits as the buffer descriptor is scrubbed in mid-air. The correct way of handling this situation is to 1. scrub the queue buffer when it is prepared for re-use, and 2. later obtain the data addresses from the async-completion notifier (ie. the AOB), instead of the queue buffer. All this only affects qeth devices used for af_iucv HiperTransport. Fixes: 0da9581ddb0f ("qeth: exploit asynchronous delivery of storage blocks") Signed-off-by: Julian Wiedmann <jwi@linux.ibm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/s390/net/qeth_core.h')
-rw-r--r--drivers/s390/net/qeth_core.h11
1 files changed, 11 insertions, 0 deletions
diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h
index 2a5fec55bf60..940fd7b558d3 100644
--- a/drivers/s390/net/qeth_core.h
+++ b/drivers/s390/net/qeth_core.h
@@ -829,6 +829,17 @@ struct qeth_trap_id {
/*some helper functions*/
#define QETH_CARD_IFNAME(card) (((card)->dev)? (card)->dev->name : "")
+static inline void qeth_scrub_qdio_buffer(struct qdio_buffer *buf,
+ unsigned int elements)
+{
+ unsigned int i;
+
+ for (i = 0; i < elements; i++)
+ memset(&buf->element[i], 0, sizeof(struct qdio_buffer_element));
+ buf->element[14].sflags = 0;
+ buf->element[15].sflags = 0;
+}
+
/**
* qeth_get_elements_for_range() - find number of SBALEs to cover range.
* @start: Start of the address range.