linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] s390: qeth network driver.
@ 2004-08-24 13:28 Martin Schwidefsky
  0 siblings, 0 replies; 4+ messages in thread
From: Martin Schwidefsky @ 2004-08-24 13:28 UTC (permalink / raw)
  To: akpm, linux-kernel

[PATCH] s390: qeth network driver.

From: Steffen Thoss <thoss@de.ibm.com>

qeth network driver change:
 - Make qeth devices which are present but not up addressable by
   snmp ioctls.

Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>

diffstat:
 drivers/s390/net/qeth_main.c |    9 +++++----
 1 files changed, 5 insertions(+), 4 deletions(-)

diff -urN linux-2.6/drivers/s390/net/qeth_main.c linux-2.6-s390/drivers/s390/net/qeth_main.c
--- linux-2.6/drivers/s390/net/qeth_main.c	Tue Aug 24 15:12:22 2004
+++ linux-2.6-s390/drivers/s390/net/qeth_main.c	Tue Aug 24 15:12:44 2004
@@ -1,6 +1,6 @@
 /*
  *
- * linux/drivers/s390/net/qeth_main.c ($Revision: 1.130 $)
+ * linux/drivers/s390/net/qeth_main.c ($Revision: 1.132 $)
  *
  * Linux on zSeries OSA Express and HiperSockets support
  *
@@ -12,7 +12,7 @@
  *			  Frank Pavlic (pavlic@de.ibm.com) and
  *		 	  Thomas Spatzier <tspat@de.ibm.com>
  *
- *    $Revision: 1.130 $	 $Date: 2004/08/05 11:21:50 $
+ *    $Revision: 1.132 $	 $Date: 2004/08/19 12:39:43 $
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -79,7 +79,7 @@
 #include "qeth_mpc.h"
 #include "qeth_fs.h"
 
-#define VERSION_QETH_C "$Revision: 1.130 $"
+#define VERSION_QETH_C "$Revision: 1.132 $"
 static const char *version = "qeth S/390 OSA-Express driver";
 
 /**
@@ -4547,7 +4547,8 @@
 	if (!card)
 		return -ENODEV;
 
-	if (card->state != CARD_STATE_UP)
+	if ((card->state != CARD_STATE_UP) &&
+            (card->state != CARD_STATE_SOFTSETUP))
 		return -ENODEV;
 
 	switch (cmd){

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] s390: qeth network driver
       [not found] <200502040211.j142BI35023854@hera.kernel.org>
@ 2005-02-04  3:05 ` Jeff Garzik
  0 siblings, 0 replies; 4+ messages in thread
From: Jeff Garzik @ 2005-02-04  3:05 UTC (permalink / raw)
  To: Linux Kernel Mailing List; +Cc: schwidefsky, akpm, Netdev

Linux Kernel Mailing List wrote:
> ChangeSet 1.2072, 2005/02/03 17:04:37-08:00, schwidefsky@de.ibm.com
> 
> 	[PATCH] s390: qeth network driver
> 	
> 	From: Steffen Thoss <thoss@de.ibm.com>
> 	From: Frank Pavlic <pavlic@de.ibm.com>
> 	
> 	qeth network driver changes:
> 	 - Improve performance by omitting svs.
> 	 - Use function callback mechanism to set layer 2 parameters when getting
> 	   a reply for a Layer 2 command.
> 	 - dev->hard_header must not be NULL when fake_ll is no set since
> 	   IPv6 and Layer2 needs the default function set by network stack.
> 	 - ping6 works now when running in layer 2 mode.
> 	 - Save original dev->hard_header to restore it when the user doesn't
> 	   want to use fake_ll anymore.
> 	 - Fake ethernet header in outgoing packets. This currently works
> 	   only if qeth is compiled without ipv6 support.
> 	 - Add more debug information in case of failures in qeth_set_offline.
> 	 - Using fake_ll with HiperSockets devices results in misaligned
> 	   ip packets and thus no traffic over HiperSockets.
> 	 - Start qeth_remove_device only after the qeth recovery completed.
> 	
> 	Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
> 	Signed-off-by: Andrew Morton <akpm@osdl.org>
> 	Signed-off-by: Linus Torvalds <torvalds@osdl.org>


It would be nice if this stuff was CC'd to the network, and network 
driver maintainers.

Two immediate concerns I have are,

* saving and restoring dev->hard_header is more than a little bit of a hack

* overall, I'm not so sure IPv6 support should be conditionalized on 
anything but CONFIG_IPV6.  Though S/390 and qeth are certainly unusual 
cases, none of the other net drivers in the kernel require a special 
config option to enable IPv6 support.

	Jeff



^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH] s390: qeth network driver.
@ 2004-09-20 16:38 Martin Schwidefsky
  0 siblings, 0 replies; 4+ messages in thread
From: Martin Schwidefsky @ 2004-09-20 16:38 UTC (permalink / raw)
  To: akpm, linux-kernel

[PATCH] s390: qeth network driver.

From: Steffen Thoss <thoss@de.ibm.com>
From: Ursula Braun-Krahl <braunu@de.ibm.com>

qeth network driver change:
 - Change misleading message about hardware ip fragmentation.
 - Include qeth_snmp_ureq_hdr structure in user copy in qeth_snmp_command.

Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>

diffstat:
 drivers/s390/net/qeth_main.c |   17 +++++++++--------
 1 files changed, 9 insertions(+), 8 deletions(-)

diff -urN linux-2.6/drivers/s390/net/qeth_main.c linux-2.6-patched/drivers/s390/net/qeth_main.c
--- linux-2.6/drivers/s390/net/qeth_main.c	2004-09-20 18:00:49.000000000 +0200
+++ linux-2.6-patched/drivers/s390/net/qeth_main.c	2004-09-20 18:01:04.000000000 +0200
@@ -1,6 +1,6 @@
 /*
  *
- * linux/drivers/s390/net/qeth_main.c ($Revision: 1.132 $)
+ * linux/drivers/s390/net/qeth_main.c ($Revision: 1.138 $)
  *
  * Linux on zSeries OSA Express and HiperSockets support
  *
@@ -12,7 +12,7 @@
  *			  Frank Pavlic (pavlic@de.ibm.com) and
  *		 	  Thomas Spatzier <tspat@de.ibm.com>
  *
- *    $Revision: 1.132 $	 $Date: 2004/08/19 12:39:43 $
+ *    $Revision: 1.138 $	 $Date: 2004/09/17 10:40:53 $
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -79,7 +79,7 @@
 #include "qeth_mpc.h"
 #include "qeth_fs.h"
 
-#define VERSION_QETH_C "$Revision: 1.132 $"
+#define VERSION_QETH_C "$Revision: 1.138 $"
 static const char *version = "qeth S/390 OSA-Express driver";
 
 /**
@@ -4373,12 +4373,13 @@
 	/* skip 4 bytes (data_len struct member) to get req_len */
 	if (copy_from_user(&req_len, udata + sizeof(int), sizeof(int)))
 		return -EFAULT;
-	ureq = kmalloc(req_len, GFP_KERNEL);
+	ureq = kmalloc(req_len+sizeof(struct qeth_snmp_ureq_hdr), GFP_KERNEL);
 	if (!ureq) {
 		QETH_DBF_TEXT(trace, 2, "snmpnome");
 		return -ENOMEM;
 	}
-	if (copy_from_user(ureq, udata, req_len)){
+	if (copy_from_user(ureq, udata,
+			req_len+sizeof(struct qeth_snmp_ureq_hdr))){
 		kfree(ureq);
 		return -EFAULT;
 	}
@@ -5743,7 +5744,7 @@
 	QETH_DBF_TEXT(trace,3,"ipaipfrg");
 
 	if (!qeth_is_supported(card, IPA_IP_FRAGMENTATION)) {
-		PRINT_INFO("IP fragmentation not supported on %s\n",
+		PRINT_INFO("Hardware IP fragmentation not supported on %s\n",
 			   card->info.if_name);
 		return  -EOPNOTSUPP;
 	}
@@ -5751,11 +5752,11 @@
 	rc = qeth_send_simple_setassparms(card, IPA_IP_FRAGMENTATION,
 					  IPA_CMD_ASS_START, 0);
 	if (rc) {
-		PRINT_WARN("Could not start IP fragmentation "
+		PRINT_WARN("Could not start Hardware IP fragmentation "
 			   "assist on %s: 0x%x\n",
 			   card->info.if_name, rc);
 	} else
-		PRINT_INFO("IP fragmentation enabled \n");
+		PRINT_INFO("Hardware IP fragmentation enabled \n");
 	return rc;
 }
 

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH] s390: qeth network driver.
@ 2004-06-11 17:37 Martin Schwidefsky
  0 siblings, 0 replies; 4+ messages in thread
From: Martin Schwidefsky @ 2004-06-11 17:37 UTC (permalink / raw)
  To: akpm, linux-kernel

[PATCH] s390: qeth network driver.

From: Frank Pavlic <pavlic@de.ibm.com>
From: Thomas Spatzier <tspat@de.ibm.com>

qeth network driver changes:
 - Use correct request length in arp/snmp requests.
 - Simplify handling of empty vs. primed buffers.

Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>

diffstat:
 drivers/s390/net/qeth.h      |    9 -
 drivers/s390/net/qeth_main.c |  209 +++++++++++++++++++++++++------------------
 2 files changed, 128 insertions(+), 90 deletions(-)

diff -urN linux-2.6/drivers/s390/net/qeth.h linux-2.6-s390/drivers/s390/net/qeth.h
--- linux-2.6/drivers/s390/net/qeth.h	Fri Jun 11 19:09:24 2004
+++ linux-2.6-s390/drivers/s390/net/qeth.h	Fri Jun 11 19:09:59 2004
@@ -23,7 +23,7 @@
 
 #include "qeth_mpc.h"
 
-#define VERSION_QETH_H 		"$Revision: 1.109 $"
+#define VERSION_QETH_H 		"$Revision: 1.110 $"
 
 #ifdef CONFIG_QETH_IPV6
 #define QETH_VERSION_IPV6 	":IPv6"
@@ -380,11 +380,6 @@
 	 * outbound: filled by driver; owned by hardware in order to be sent
 	 */
 	QETH_QDIO_BUF_PRIMED,
-	/*
-	 * inbound only: an error condition has been detected for a buffer
-	 *     the buffer will be discarded (not read out)
-	 */
-	QETH_QDIO_BUF_ERROR,
 };
 
 enum qeth_qdio_info_states {
@@ -423,7 +418,7 @@
 
 struct qeth_qdio_out_buffer {
 	struct qdio_buffer *buffer;
-	volatile enum qeth_qdio_buffer_states state;
+	atomic_t state;
 	volatile int next_element_to_fill;
 	struct sk_buff_head skb_list;
 };
diff -urN linux-2.6/drivers/s390/net/qeth_main.c linux-2.6-s390/drivers/s390/net/qeth_main.c
--- linux-2.6/drivers/s390/net/qeth_main.c	Fri Jun 11 19:09:24 2004
+++ linux-2.6-s390/drivers/s390/net/qeth_main.c	Fri Jun 11 19:09:59 2004
@@ -1,6 +1,6 @@
 /*
  *
- * linux/drivers/s390/net/qeth_main.c ($Revision: 1.118 $)
+ * linux/drivers/s390/net/qeth_main.c ($Revision: 1.121 $)
  *
  * Linux on zSeries OSA Express and HiperSockets support
  *
@@ -12,7 +12,7 @@
  *			  Frank Pavlic (pavlic@de.ibm.com) and
  *		 	  Thomas Spatzier <tspat@de.ibm.com>
  *
- *    $Revision: 1.118 $	 $Date: 2004/06/02 06:34:52 $
+ *    $Revision: 1.121 $	 $Date: 2004/06/11 16:32:15 $
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -78,7 +78,7 @@
 #include "qeth_mpc.h"
 #include "qeth_fs.h"
 
-#define VERSION_QETH_C "$Revision: 1.118 $"
+#define VERSION_QETH_C "$Revision: 1.121 $"
 static const char *version = "qeth S/390 OSA-Express driver";
 
 /**
@@ -2345,13 +2345,17 @@
 }
 
 static inline void
-qeth_clear_output_buffer(struct qeth_card *card,
+qeth_clear_output_buffer(struct qeth_qdio_out_q *queue,
 			 struct qeth_qdio_out_buffer *buf)
 {
 	int i;
 	struct sk_buff *skb;
 
-	for(i = 0; i < QETH_MAX_BUFFER_ELEMENTS(card); ++i){
+	/* is PCI flag set on buffer? */
+	if (buf->buffer->element[0].flags & 0x40)
+		atomic_dec(&queue->set_pci_flags_count);
+
+	for(i = 0; i < QETH_MAX_BUFFER_ELEMENTS(queue->card); ++i){
 		buf->buffer->element[i].length = 0;
 		buf->buffer->element[i].addr = NULL;
 		buf->buffer->element[i].flags = 0;
@@ -2361,7 +2365,7 @@
 		}
 	}
 	buf->next_element_to_fill = 0;
-	buf->state = QETH_QDIO_BUF_EMPTY;
+	atomic_set(&buf->state, QETH_QDIO_BUF_EMPTY);
 }
 
 static inline void
@@ -2578,8 +2582,17 @@
 		QETH_DBF_TEXT(trace, 2, "flushbuf");
 		QETH_DBF_TEXT_(trace, 2, " err%d", rc);
 		queue->card->stats.tx_errors += count;
+		/* ok, since do_QDIO went wrong the buffers have not been given
+		 * to the hardware. they still belong to us, so we can clear
+		 * them and reuse then, i.e. set back next_buf_to_fill*/
+		for (i = index; i < index + count; ++i) {
+			buf = &queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q];
+			qeth_clear_output_buffer(queue, buf);
+		}
+		queue->next_buf_to_fill = index;
 		return;
 	}
+	atomic_add(count, &queue->used_buffers);
 #ifdef CONFIG_QETH_PERF_STATS
 	queue->card->perf_stats.bufs_sent += count;
 #endif
@@ -2617,11 +2630,11 @@
 			queue->do_pack = 0;
 			/* flush packing buffers */
 			buffer = &queue->bufs[queue->next_buf_to_fill];
-			BUG_ON(buffer->state == QETH_QDIO_BUF_PRIMED);
-			if (buffer->next_element_to_fill > 0) {
-				buffer->state = QETH_QDIO_BUF_PRIMED;
+			if ((atomic_read(&buffer->state) ==
+						QETH_QDIO_BUF_EMPTY) &&
+			    (buffer->next_element_to_fill > 0)) {
+				atomic_set(&buffer->state,QETH_QDIO_BUF_PRIMED);
 				flush_count++;
-				atomic_inc(&queue->used_buffers);
 				queue->next_buf_to_fill =
 					(queue->next_buf_to_fill + 1) %
 					QDIO_MAX_BUFFERS_PER_Q;
@@ -2635,17 +2648,17 @@
 qeth_flush_buffers_on_no_pci(struct qeth_qdio_out_q *queue, int under_int)
 {
 	struct qeth_qdio_out_buffer *buffer;
+	int index;
 
-	buffer = &queue->bufs[queue->next_buf_to_fill];
-	BUG_ON(buffer->state == QETH_QDIO_BUF_PRIMED);
-	if (buffer->next_element_to_fill > 0){
+	index = queue->next_buf_to_fill;
+	buffer = &queue->bufs[index];
+	if((atomic_read(&buffer->state) == QETH_QDIO_BUF_EMPTY) &&
+	   (buffer->next_element_to_fill > 0)){
 		/* it's a packing buffer */
-		buffer->state = QETH_QDIO_BUF_PRIMED;
-		atomic_inc(&queue->used_buffers);
-		qeth_flush_buffers(queue, under_int, queue->next_buf_to_fill,
-				   1);
+		atomic_set(&buffer->state, QETH_QDIO_BUF_PRIMED);
 		queue->next_buf_to_fill =
 			(queue->next_buf_to_fill + 1) % QDIO_MAX_BUFFERS_PER_Q;
+		qeth_flush_buffers(queue, under_int, index, 1);
 	}
 }
 
@@ -2688,13 +2701,9 @@
 			qeth_schedule_recovery(card);
 			return;
 		}
-		/* is PCI flag set on buffer? */
-		if (buffer->buffer->element[0].flags & 0x40)
-			atomic_dec(&queue->set_pci_flags_count);
-
-		qeth_clear_output_buffer(card, buffer);
-		atomic_dec(&queue->used_buffers);
+		qeth_clear_output_buffer(queue, buffer);
 	}
+	atomic_sub(count, &queue->used_buffers);
 
 	netif_wake_queue(card->dev);
 #ifdef CONFIG_QETH_PERF_STATS
@@ -2887,8 +2896,8 @@
 	/* free outbound qdio_qs */
 	for (i = 0; i < card->qdio.no_out_queues; ++i){
 		for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j)
-			qeth_clear_output_buffer(card, &card->qdio.
-						out_qs[i]->bufs[j]);
+			qeth_clear_output_buffer(card->qdio.out_qs[i],
+					&card->qdio.out_qs[i]->bufs[j]);
 		kfree(card->qdio.out_qs[i]);
 	}
 	kfree(card->qdio.out_qs);
@@ -2905,8 +2914,8 @@
 	for (i = 0; i < card->qdio.no_out_queues; ++i)
 		if (card->qdio.out_qs[i]){
 			for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j)
-				qeth_clear_output_buffer(card, &card->qdio.
-						out_qs[i]->bufs[j]);
+				qeth_clear_output_buffer(card->qdio.out_qs[i],
+						&card->qdio.out_qs[i]->bufs[j]);
 		}
 }
 
@@ -2958,8 +2967,8 @@
 		memset(card->qdio.out_qs[i]->qdio_bufs, 0,
 		       QDIO_MAX_BUFFERS_PER_Q * sizeof(struct qdio_buffer));
 		for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j){
-			qeth_clear_output_buffer(card, &card->qdio.
-						 out_qs[i]->bufs[j]);
+			qeth_clear_output_buffer(card->qdio.out_qs[i],
+					&card->qdio.out_qs[i]->bufs[j]);
 		}
 		card->qdio.out_qs[i]->card = card;
 		card->qdio.out_qs[i]->next_buf_to_fill = 0;
@@ -3671,7 +3680,7 @@
 	if (!queue->do_pack) {
 		QETH_DBF_TEXT(trace, 6, "fillbfnp");
 		/* set state to PRIMED -> will be flushed */
-		buf->state = QETH_QDIO_BUF_PRIMED;
+		atomic_set(&buf->state, QETH_QDIO_BUF_PRIMED);
 	} else {
 		QETH_DBF_TEXT(trace, 6, "fillbfpa");
 #ifdef CONFIG_QETH_PERF_STATS
@@ -3683,7 +3692,7 @@
 			 * packed buffer if full -> set state PRIMED
 			 * -> will be flushed
 			 */
-			buf->state = QETH_QDIO_BUF_PRIMED;
+			atomic_set(&buf->state, QETH_QDIO_BUF_PRIMED);
 		}
 	}
 	return 0;
@@ -3696,32 +3705,27 @@
 {
 	struct qeth_qdio_out_buffer *buffer;
 	int index;
-	int rc = 0;
 
 	QETH_DBF_TEXT(trace, 6, "dosndpfa");
 
 	spin_lock(&queue->lock);
-	/* do we have empty buffers? */
-	if (atomic_read(&queue->used_buffers) >= (QDIO_MAX_BUFFERS_PER_Q - 1)){
+	index = queue->next_buf_to_fill;
+	buffer = &queue->bufs[queue->next_buf_to_fill];
+	/*
+	 * check if buffer is empty to make sure that we do not 'overtake'
+	 * ourselves and try to fill a buffer that is already primed
+	 */
+	if (atomic_read(&buffer->state) != QETH_QDIO_BUF_EMPTY) {
 		card->stats.tx_dropped++;
-		rc = -EBUSY;
 		spin_unlock(&queue->lock);
-		goto out;
+		return -EBUSY;
 	}
-	index = queue->next_buf_to_fill;
-	buffer = &queue->bufs[queue->next_buf_to_fill];
-	BUG_ON(buffer->state == QETH_QDIO_BUF_PRIMED);
 	queue->next_buf_to_fill = (queue->next_buf_to_fill + 1) %
 				  QDIO_MAX_BUFFERS_PER_Q;
-	atomic_inc(&queue->used_buffers);
-	spin_unlock(&queue->lock);
-
-	/* go on sending ... */
-	netif_wake_queue(skb->dev);
 	qeth_fill_buffer(queue, buffer, (char *)hdr, skb);
 	qeth_flush_buffers(queue, 0, index, 1);
-out:
-	return rc;
+	spin_unlock(&queue->lock);
+	return 0;
 }
 
 static inline int
@@ -3737,35 +3741,43 @@
 	QETH_DBF_TEXT(trace, 6, "dosndpkt");
 
 	spin_lock(&queue->lock);
-	/* do we have empty buffers? */
-	if (atomic_read(&queue->used_buffers) >= (QDIO_MAX_BUFFERS_PER_Q - 2)){
-		card->stats.tx_dropped++;
-		rc = -EBUSY;
-		goto out;
-	}
 	start_index = queue->next_buf_to_fill;
 	buffer = &queue->bufs[queue->next_buf_to_fill];
-	BUG_ON(buffer->state == QETH_QDIO_BUF_PRIMED);
+	/*
+	 * check if buffer is empty to make sure that we do not 'overtake'
+	 * ourselves and try to fill a buffer that is already primed
+	 */
+	if (atomic_read(&buffer->state) != QETH_QDIO_BUF_EMPTY){
+		card->stats.tx_dropped++;
+		spin_unlock(&queue->lock);
+		return -EBUSY;
+	}
 	if (queue->do_pack){
 		/* does packet fit in current buffer? */
-		if((QETH_MAX_BUFFER_ELEMENTS(card) - buffer->next_element_to_fill)
-				< elements_needed){
+		if((QETH_MAX_BUFFER_ELEMENTS(card) -
+		    buffer->next_element_to_fill) < elements_needed){
 			/* ... no -> set state PRIMED */
-			buffer->state = QETH_QDIO_BUF_PRIMED;
+			atomic_set(&buffer->state, QETH_QDIO_BUF_PRIMED);
 			flush_count++;
-			atomic_inc(&queue->used_buffers);
 			queue->next_buf_to_fill =
 				(queue->next_buf_to_fill + 1) %
 				QDIO_MAX_BUFFERS_PER_Q;
 			buffer = &queue->bufs[queue->next_buf_to_fill];
+			/* we did a step forward, so check buffer state again */
+			if (atomic_read(&buffer->state) != QETH_QDIO_BUF_EMPTY){
+				card->stats.tx_dropped++;
+				qeth_flush_buffers(queue, 0, start_index, 1);
+				spin_unlock(&queue->lock);
+				/* return EBUSY because we sent old packet, not
+				 * the current one */
+				return -EBUSY;
+			}
 		}
 	}
-
 	qeth_fill_buffer(queue, buffer, (char *)hdr, skb);
-	if (buffer->state == QETH_QDIO_BUF_PRIMED){
+	if (atomic_read(&buffer->state) == QETH_QDIO_BUF_PRIMED){
 		/* next time fill the next buffer */
 		flush_count++;
-		atomic_inc(&queue->used_buffers);
 		queue->next_buf_to_fill = (queue->next_buf_to_fill + 1) %
 			QDIO_MAX_BUFFERS_PER_Q;
 	}
@@ -3777,9 +3789,8 @@
 
 	if (!atomic_read(&queue->set_pci_flags_count))
 		qeth_flush_buffers_on_no_pci(queue, 0);
-out:
-	spin_unlock(&queue->lock);
 
+	spin_unlock(&queue->lock);
 	return rc;
 }
 
@@ -4079,21 +4090,43 @@
 
 static int
 qeth_send_ipa_arp_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob,
-		      int len, int (*reply_cb)
-			      		(struct qeth_card *,
-					 struct qeth_reply*, unsigned long),
+		      int len, int (*reply_cb)(struct qeth_card *,
+					       struct qeth_reply *,
+					       unsigned long),
 		      void *reply_param)
 {
-	int rc;
-
 	QETH_DBF_TEXT(trace,4,"sendarp");
 
 	memcpy(iob->data, IPA_PDU_HEADER, IPA_PDU_HEADER_SIZE);
 	memcpy(QETH_IPA_CMD_DEST_ADDR(iob->data),
 	       &card->token.ulp_connection_r, QETH_MPC_TOKEN_LENGTH);
-	rc = qeth_send_control_data(card, IPA_PDU_HEADER_SIZE + len, iob,
-				    reply_cb, reply_param);
-	return rc;
+	return qeth_send_control_data(card, IPA_PDU_HEADER_SIZE + len, iob,
+				      reply_cb, reply_param);
+}
+
+static int
+qeth_send_ipa_snmp_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob,
+		      int len, int (*reply_cb)(struct qeth_card *,
+					       struct qeth_reply *,
+					       unsigned long),
+		      void *reply_param)
+{
+	u16 s1, s2;
+
+	QETH_DBF_TEXT(trace,4,"sendsnmp");
+
+	memcpy(iob->data, IPA_PDU_HEADER, IPA_PDU_HEADER_SIZE);
+	memcpy(QETH_IPA_CMD_DEST_ADDR(iob->data),
+	       &card->token.ulp_connection_r, QETH_MPC_TOKEN_LENGTH);
+	/* adjust PDU length fields in IPA_PDU_HEADER */
+	s1 = (u32) IPA_PDU_HEADER_SIZE + len;
+	s2 = (u32) len;
+	memcpy(QETH_IPA_PDU_LEN_TOTAL(iob->data), &s1, 2);
+	memcpy(QETH_IPA_PDU_LEN_PDU1(iob->data), &s2, 2);
+	memcpy(QETH_IPA_PDU_LEN_PDU2(iob->data), &s2, 2);
+	memcpy(QETH_IPA_PDU_LEN_PDU3(iob->data), &s2, 2);
+	return qeth_send_control_data(card, IPA_PDU_HEADER_SIZE + len, iob,
+				      reply_cb, reply_param);
 }
 
 static struct qeth_cmd_buffer *
@@ -4136,8 +4169,7 @@
 
 	rc = qeth_send_ipa_arp_cmd(card, iob,
 				   QETH_SETASS_BASE_LEN+QETH_ARP_CMD_LEN,
-				   qeth_arp_query_cb,
-				   (void *)&qinfo);
+				   qeth_arp_query_cb, (void *)&qinfo);
 	if (rc) {
 		tmp = rc;
 		PRINT_WARN("Error while querying ARP cache on %s: %s "
@@ -4247,7 +4279,8 @@
 {
 	struct qeth_cmd_buffer *iob;
 	struct qeth_ipa_cmd *cmd;
-	struct qeth_snmp_ureq ureq;
+	struct qeth_snmp_ureq *ureq;
+	int req_len;
 	struct qeth_arp_query_info qinfo = {0, };
 	int rc = 0;
 
@@ -4260,29 +4293,39 @@
 			   "on %s!\n", card->info.if_name);
 		return -EOPNOTSUPP;
 	}
-	if (copy_from_user(&ureq, udata, sizeof(struct qeth_snmp_ureq)))
+	/* skip 4 bytes (data_len struct member) to get req_len */
+	if (copy_from_user(&req_len, udata + sizeof(int), sizeof(int)))
 		return -EFAULT;
-	qinfo.udata_len = ureq.hdr.data_len;
-	if (!(qinfo.udata = kmalloc(qinfo.udata_len, GFP_KERNEL)))
+	ureq = kmalloc(req_len, GFP_KERNEL);
+	if (!ureq) {
+		QETH_DBF_TEXT(trace, 2, "snmpnome");
 		return -ENOMEM;
+	}
+	if (copy_from_user(ureq, udata, req_len)){
+		kfree(ureq);
+		return -EFAULT;
+	}
+	qinfo.udata_len = ureq->hdr.data_len;
+	if (!(qinfo.udata = kmalloc(qinfo.udata_len, GFP_KERNEL))){
+		kfree(ureq);
+		return -ENOMEM;
+	}
 	memset(qinfo.udata, 0, qinfo.udata_len);
 	qinfo.udata_offset = sizeof(struct qeth_snmp_ureq_hdr);
 
 	iob = qeth_get_adapter_cmd(card, IPA_SETADP_SET_SNMP_CONTROL,
-				   QETH_SNMP_SETADP_CMDLENGTH+ureq.hdr.req_len);
+				   QETH_SNMP_SETADP_CMDLENGTH + req_len);
 	cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
-	memcpy(&cmd->data.setadapterparms.data.snmp, &ureq.cmd,
-	       sizeof(struct qeth_snmp_cmd));
-	rc = qeth_send_ipa_arp_cmd(card, iob,
-				   QETH_SETADP_BASE_LEN + QETH_ARP_DATA_SIZE +
-				   ureq.hdr.req_len, qeth_snmp_command_cb,
-				   (void *)&qinfo);
+	memcpy(&cmd->data.setadapterparms.data.snmp, &ureq->cmd, req_len);
+	rc = qeth_send_ipa_snmp_cmd(card, iob, QETH_SETADP_BASE_LEN + req_len,
+				    qeth_snmp_command_cb, (void *)&qinfo);
 	if (rc)
 		PRINT_WARN("SNMP command failed on %s: (0x%x)\n",
 			   card->info.if_name, rc);
 	 else
 		copy_to_user(udata, qinfo.udata, qinfo.udata_len);
 
+	kfree(ureq);
 	kfree(qinfo.udata);
 	return rc;
 }

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2005-02-04  3:19 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-08-24 13:28 [PATCH] s390: qeth network driver Martin Schwidefsky
     [not found] <200502040211.j142BI35023854@hera.kernel.org>
2005-02-04  3:05 ` Jeff Garzik
  -- strict thread matches above, loose matches on Subject: below --
2004-09-20 16:38 Martin Schwidefsky
2004-06-11 17:37 Martin Schwidefsky

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).