[PATCH] s390: qeth driver fixes [4/6]
[PATCH 7/9] s390: qeth driver fixes [4/6] From: Frank Pavlic <fpavlic@de.ibm.com> - fix kernel crash due to race, set card->state to SOFTSETUP after card and card->dev are initialized properly. - remove CONFIG_QETH_PERF_STATS, use sysfs attribute instead, as we want to have the ability to turn on/off the statistics at runtime. Signed-off-by: Frank Pavlic <fpavlic@de.ibm.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
This commit is contained in:
parent
f7b65d70a3
commit
09d2d38a15
6 changed files with 128 additions and 108 deletions
|
@ -92,15 +92,6 @@ config QETH_VLAN
|
||||||
If CONFIG_QETH is switched on, this option will include IEEE
|
If CONFIG_QETH is switched on, this option will include IEEE
|
||||||
802.1q VLAN support in the qeth device driver.
|
802.1q VLAN support in the qeth device driver.
|
||||||
|
|
||||||
config QETH_PERF_STATS
|
|
||||||
bool "Performance statistics in /proc"
|
|
||||||
depends on QETH
|
|
||||||
help
|
|
||||||
When switched on, this option will add a file in the proc-fs
|
|
||||||
(/proc/qeth_perf_stats) containing performance statistics. It
|
|
||||||
may slightly impact performance, so this is only recommended for
|
|
||||||
internal tuning of the device driver.
|
|
||||||
|
|
||||||
config CCWGROUP
|
config CCWGROUP
|
||||||
tristate
|
tristate
|
||||||
default (LCS || CTC || QETH)
|
default (LCS || CTC || QETH)
|
||||||
|
|
|
@ -176,7 +176,6 @@ extern struct ccwgroup_driver qeth_ccwgroup_driver;
|
||||||
/**
|
/**
|
||||||
* card stuff
|
* card stuff
|
||||||
*/
|
*/
|
||||||
#ifdef CONFIG_QETH_PERF_STATS
|
|
||||||
struct qeth_perf_stats {
|
struct qeth_perf_stats {
|
||||||
unsigned int bufs_rec;
|
unsigned int bufs_rec;
|
||||||
unsigned int bufs_sent;
|
unsigned int bufs_sent;
|
||||||
|
@ -211,8 +210,10 @@ struct qeth_perf_stats {
|
||||||
unsigned int large_send_cnt;
|
unsigned int large_send_cnt;
|
||||||
unsigned int sg_skbs_sent;
|
unsigned int sg_skbs_sent;
|
||||||
unsigned int sg_frags_sent;
|
unsigned int sg_frags_sent;
|
||||||
|
/* initial values when measuring starts */
|
||||||
|
unsigned long initial_rx_packets;
|
||||||
|
unsigned long initial_tx_packets;
|
||||||
};
|
};
|
||||||
#endif /* CONFIG_QETH_PERF_STATS */
|
|
||||||
|
|
||||||
/* Routing stuff */
|
/* Routing stuff */
|
||||||
struct qeth_routing_info {
|
struct qeth_routing_info {
|
||||||
|
@ -767,6 +768,7 @@ struct qeth_card_options {
|
||||||
int fake_ll;
|
int fake_ll;
|
||||||
int layer2;
|
int layer2;
|
||||||
enum qeth_large_send_types large_send;
|
enum qeth_large_send_types large_send;
|
||||||
|
int performance_stats;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -819,9 +821,7 @@ struct qeth_card {
|
||||||
struct list_head cmd_waiter_list;
|
struct list_head cmd_waiter_list;
|
||||||
/* QDIO buffer handling */
|
/* QDIO buffer handling */
|
||||||
struct qeth_qdio_info qdio;
|
struct qeth_qdio_info qdio;
|
||||||
#ifdef CONFIG_QETH_PERF_STATS
|
|
||||||
struct qeth_perf_stats perf_stats;
|
struct qeth_perf_stats perf_stats;
|
||||||
#endif /* CONFIG_QETH_PERF_STATS */
|
|
||||||
int use_hard_stop;
|
int use_hard_stop;
|
||||||
int (*orig_hard_header)(struct sk_buff *,struct net_device *,
|
int (*orig_hard_header)(struct sk_buff *,struct net_device *,
|
||||||
unsigned short,void *,void *,unsigned);
|
unsigned short,void *,void *,unsigned);
|
||||||
|
@ -1049,13 +1049,11 @@ qeth_get_arphdr_type(int cardtype, int linktype)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_QETH_PERF_STATS
|
|
||||||
static inline int
|
static inline int
|
||||||
qeth_get_micros(void)
|
qeth_get_micros(void)
|
||||||
{
|
{
|
||||||
return (int) (get_clock() >> 12);
|
return (int) (get_clock() >> 12);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
qeth_get_qdio_q_format(struct qeth_card *card)
|
qeth_get_qdio_q_format(struct qeth_card *card)
|
||||||
|
|
|
@ -179,9 +179,8 @@ out_check:
|
||||||
flush_cnt++;
|
flush_cnt++;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
#ifdef CONFIG_QETH_PERF_STATS
|
if (queue->card->options.performance_stats)
|
||||||
queue->card->perf_stats.skbs_sent_pack++;
|
queue->card->perf_stats.skbs_sent_pack++;
|
||||||
#endif
|
|
||||||
QETH_DBF_TEXT(trace, 6, "fillbfpa");
|
QETH_DBF_TEXT(trace, 6, "fillbfpa");
|
||||||
if (buf->next_element_to_fill >=
|
if (buf->next_element_to_fill >=
|
||||||
QETH_MAX_BUFFER_ELEMENTS(queue->card)) {
|
QETH_MAX_BUFFER_ELEMENTS(queue->card)) {
|
||||||
|
|
|
@ -1073,6 +1073,7 @@ qeth_set_intial_options(struct qeth_card *card)
|
||||||
card->options.layer2 = 1;
|
card->options.layer2 = 1;
|
||||||
else
|
else
|
||||||
card->options.layer2 = 0;
|
card->options.layer2 = 0;
|
||||||
|
card->options.performance_stats = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2564,9 +2565,8 @@ qeth_process_inbound_buffer(struct qeth_card *card,
|
||||||
/* get first element of current buffer */
|
/* get first element of current buffer */
|
||||||
element = (struct qdio_buffer_element *)&buf->buffer->element[0];
|
element = (struct qdio_buffer_element *)&buf->buffer->element[0];
|
||||||
offset = 0;
|
offset = 0;
|
||||||
#ifdef CONFIG_QETH_PERF_STATS
|
if (card->options.performance_stats)
|
||||||
card->perf_stats.bufs_rec++;
|
card->perf_stats.bufs_rec++;
|
||||||
#endif
|
|
||||||
while((skb = qeth_get_next_skb(card, buf->buffer, &element,
|
while((skb = qeth_get_next_skb(card, buf->buffer, &element,
|
||||||
&offset, &hdr))) {
|
&offset, &hdr))) {
|
||||||
skb->dev = card->dev;
|
skb->dev = card->dev;
|
||||||
|
@ -2697,17 +2697,18 @@ qeth_queue_input_buffer(struct qeth_card *card, int index)
|
||||||
* 'index') un-requeued -> this buffer is the first buffer that
|
* 'index') un-requeued -> this buffer is the first buffer that
|
||||||
* will be requeued the next time
|
* will be requeued the next time
|
||||||
*/
|
*/
|
||||||
#ifdef CONFIG_QETH_PERF_STATS
|
if (card->options.performance_stats) {
|
||||||
card->perf_stats.inbound_do_qdio_cnt++;
|
card->perf_stats.inbound_do_qdio_cnt++;
|
||||||
card->perf_stats.inbound_do_qdio_start_time = qeth_get_micros();
|
card->perf_stats.inbound_do_qdio_start_time =
|
||||||
#endif
|
qeth_get_micros();
|
||||||
|
}
|
||||||
rc = do_QDIO(CARD_DDEV(card),
|
rc = do_QDIO(CARD_DDEV(card),
|
||||||
QDIO_FLAG_SYNC_INPUT | QDIO_FLAG_UNDER_INTERRUPT,
|
QDIO_FLAG_SYNC_INPUT | QDIO_FLAG_UNDER_INTERRUPT,
|
||||||
0, queue->next_buf_to_init, count, NULL);
|
0, queue->next_buf_to_init, count, NULL);
|
||||||
#ifdef CONFIG_QETH_PERF_STATS
|
if (card->options.performance_stats)
|
||||||
card->perf_stats.inbound_do_qdio_time += qeth_get_micros() -
|
card->perf_stats.inbound_do_qdio_time +=
|
||||||
card->perf_stats.inbound_do_qdio_start_time;
|
qeth_get_micros() -
|
||||||
#endif
|
card->perf_stats.inbound_do_qdio_start_time;
|
||||||
if (rc){
|
if (rc){
|
||||||
PRINT_WARN("qeth_queue_input_buffer's do_QDIO "
|
PRINT_WARN("qeth_queue_input_buffer's do_QDIO "
|
||||||
"return %i (device %s).\n",
|
"return %i (device %s).\n",
|
||||||
|
@ -2743,10 +2744,10 @@ qeth_qdio_input_handler(struct ccw_device * ccwdev, unsigned int status,
|
||||||
QETH_DBF_TEXT(trace, 6, "qdinput");
|
QETH_DBF_TEXT(trace, 6, "qdinput");
|
||||||
card = (struct qeth_card *) card_ptr;
|
card = (struct qeth_card *) card_ptr;
|
||||||
net_dev = card->dev;
|
net_dev = card->dev;
|
||||||
#ifdef CONFIG_QETH_PERF_STATS
|
if (card->options.performance_stats) {
|
||||||
card->perf_stats.inbound_cnt++;
|
card->perf_stats.inbound_cnt++;
|
||||||
card->perf_stats.inbound_start_time = qeth_get_micros();
|
card->perf_stats.inbound_start_time = qeth_get_micros();
|
||||||
#endif
|
}
|
||||||
if (status & QDIO_STATUS_LOOK_FOR_ERROR) {
|
if (status & QDIO_STATUS_LOOK_FOR_ERROR) {
|
||||||
if (status & QDIO_STATUS_ACTIVATE_CHECK_CONDITION){
|
if (status & QDIO_STATUS_ACTIVATE_CHECK_CONDITION){
|
||||||
QETH_DBF_TEXT(trace, 1,"qdinchk");
|
QETH_DBF_TEXT(trace, 1,"qdinchk");
|
||||||
|
@ -2768,10 +2769,9 @@ qeth_qdio_input_handler(struct ccw_device * ccwdev, unsigned int status,
|
||||||
qeth_put_buffer_pool_entry(card, buffer->pool_entry);
|
qeth_put_buffer_pool_entry(card, buffer->pool_entry);
|
||||||
qeth_queue_input_buffer(card, index);
|
qeth_queue_input_buffer(card, index);
|
||||||
}
|
}
|
||||||
#ifdef CONFIG_QETH_PERF_STATS
|
if (card->options.performance_stats)
|
||||||
card->perf_stats.inbound_time += qeth_get_micros() -
|
card->perf_stats.inbound_time += qeth_get_micros() -
|
||||||
card->perf_stats.inbound_start_time;
|
card->perf_stats.inbound_start_time;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
|
@ -2861,10 +2861,11 @@ qeth_flush_buffers(struct qeth_qdio_out_q *queue, int under_int,
|
||||||
}
|
}
|
||||||
|
|
||||||
queue->card->dev->trans_start = jiffies;
|
queue->card->dev->trans_start = jiffies;
|
||||||
#ifdef CONFIG_QETH_PERF_STATS
|
if (queue->card->options.performance_stats) {
|
||||||
queue->card->perf_stats.outbound_do_qdio_cnt++;
|
queue->card->perf_stats.outbound_do_qdio_cnt++;
|
||||||
queue->card->perf_stats.outbound_do_qdio_start_time = qeth_get_micros();
|
queue->card->perf_stats.outbound_do_qdio_start_time =
|
||||||
#endif
|
qeth_get_micros();
|
||||||
|
}
|
||||||
if (under_int)
|
if (under_int)
|
||||||
rc = do_QDIO(CARD_DDEV(queue->card),
|
rc = do_QDIO(CARD_DDEV(queue->card),
|
||||||
QDIO_FLAG_SYNC_OUTPUT | QDIO_FLAG_UNDER_INTERRUPT,
|
QDIO_FLAG_SYNC_OUTPUT | QDIO_FLAG_UNDER_INTERRUPT,
|
||||||
|
@ -2872,10 +2873,10 @@ qeth_flush_buffers(struct qeth_qdio_out_q *queue, int under_int,
|
||||||
else
|
else
|
||||||
rc = do_QDIO(CARD_DDEV(queue->card), QDIO_FLAG_SYNC_OUTPUT,
|
rc = do_QDIO(CARD_DDEV(queue->card), QDIO_FLAG_SYNC_OUTPUT,
|
||||||
queue->queue_no, index, count, NULL);
|
queue->queue_no, index, count, NULL);
|
||||||
#ifdef CONFIG_QETH_PERF_STATS
|
if (queue->card->options.performance_stats)
|
||||||
queue->card->perf_stats.outbound_do_qdio_time += qeth_get_micros() -
|
queue->card->perf_stats.outbound_do_qdio_time +=
|
||||||
queue->card->perf_stats.outbound_do_qdio_start_time;
|
qeth_get_micros() -
|
||||||
#endif
|
queue->card->perf_stats.outbound_do_qdio_start_time;
|
||||||
if (rc){
|
if (rc){
|
||||||
QETH_DBF_TEXT(trace, 2, "flushbuf");
|
QETH_DBF_TEXT(trace, 2, "flushbuf");
|
||||||
QETH_DBF_TEXT_(trace, 2, " err%d", rc);
|
QETH_DBF_TEXT_(trace, 2, " err%d", rc);
|
||||||
|
@ -2887,9 +2888,8 @@ qeth_flush_buffers(struct qeth_qdio_out_q *queue, int under_int,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
atomic_add(count, &queue->used_buffers);
|
atomic_add(count, &queue->used_buffers);
|
||||||
#ifdef CONFIG_QETH_PERF_STATS
|
if (queue->card->options.performance_stats)
|
||||||
queue->card->perf_stats.bufs_sent += count;
|
queue->card->perf_stats.bufs_sent += count;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2904,9 +2904,8 @@ qeth_switch_to_packing_if_needed(struct qeth_qdio_out_q *queue)
|
||||||
>= QETH_HIGH_WATERMARK_PACK){
|
>= QETH_HIGH_WATERMARK_PACK){
|
||||||
/* switch non-PACKING -> PACKING */
|
/* switch non-PACKING -> PACKING */
|
||||||
QETH_DBF_TEXT(trace, 6, "np->pack");
|
QETH_DBF_TEXT(trace, 6, "np->pack");
|
||||||
#ifdef CONFIG_QETH_PERF_STATS
|
if (queue->card->options.performance_stats)
|
||||||
queue->card->perf_stats.sc_dp_p++;
|
queue->card->perf_stats.sc_dp_p++;
|
||||||
#endif
|
|
||||||
queue->do_pack = 1;
|
queue->do_pack = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2929,9 +2928,8 @@ qeth_switch_to_nonpacking_if_needed(struct qeth_qdio_out_q *queue)
|
||||||
<= QETH_LOW_WATERMARK_PACK) {
|
<= QETH_LOW_WATERMARK_PACK) {
|
||||||
/* switch PACKING -> non-PACKING */
|
/* switch PACKING -> non-PACKING */
|
||||||
QETH_DBF_TEXT(trace, 6, "pack->np");
|
QETH_DBF_TEXT(trace, 6, "pack->np");
|
||||||
#ifdef CONFIG_QETH_PERF_STATS
|
if (queue->card->options.performance_stats)
|
||||||
queue->card->perf_stats.sc_p_dp++;
|
queue->card->perf_stats.sc_p_dp++;
|
||||||
#endif
|
|
||||||
queue->do_pack = 0;
|
queue->do_pack = 0;
|
||||||
/* flush packing buffers */
|
/* flush packing buffers */
|
||||||
buffer = &queue->bufs[queue->next_buf_to_fill];
|
buffer = &queue->bufs[queue->next_buf_to_fill];
|
||||||
|
@ -2943,7 +2941,7 @@ qeth_switch_to_nonpacking_if_needed(struct qeth_qdio_out_q *queue)
|
||||||
queue->next_buf_to_fill =
|
queue->next_buf_to_fill =
|
||||||
(queue->next_buf_to_fill + 1) %
|
(queue->next_buf_to_fill + 1) %
|
||||||
QDIO_MAX_BUFFERS_PER_Q;
|
QDIO_MAX_BUFFERS_PER_Q;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return flush_count;
|
return flush_count;
|
||||||
|
@ -2999,11 +2997,10 @@ qeth_check_outbound_queue(struct qeth_qdio_out_q *queue)
|
||||||
!atomic_read(&queue->set_pci_flags_count))
|
!atomic_read(&queue->set_pci_flags_count))
|
||||||
flush_cnt +=
|
flush_cnt +=
|
||||||
qeth_flush_buffers_on_no_pci(queue);
|
qeth_flush_buffers_on_no_pci(queue);
|
||||||
#ifdef CONFIG_QETH_PERF_STATS
|
if (queue->card->options.performance_stats &&
|
||||||
if (q_was_packing)
|
q_was_packing)
|
||||||
queue->card->perf_stats.bufs_sent_pack +=
|
queue->card->perf_stats.bufs_sent_pack +=
|
||||||
flush_cnt;
|
flush_cnt;
|
||||||
#endif
|
|
||||||
if (flush_cnt)
|
if (flush_cnt)
|
||||||
qeth_flush_buffers(queue, 1, index, flush_cnt);
|
qeth_flush_buffers(queue, 1, index, flush_cnt);
|
||||||
atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED);
|
atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED);
|
||||||
|
@ -3033,10 +3030,11 @@ qeth_qdio_output_handler(struct ccw_device * ccwdev, unsigned int status,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#ifdef CONFIG_QETH_PERF_STATS
|
if (card->options.performance_stats) {
|
||||||
card->perf_stats.outbound_handler_cnt++;
|
card->perf_stats.outbound_handler_cnt++;
|
||||||
card->perf_stats.outbound_handler_start_time = qeth_get_micros();
|
card->perf_stats.outbound_handler_start_time =
|
||||||
#endif
|
qeth_get_micros();
|
||||||
|
}
|
||||||
for(i = first_element; i < (first_element + count); ++i){
|
for(i = first_element; i < (first_element + count); ++i){
|
||||||
buffer = &queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q];
|
buffer = &queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q];
|
||||||
/*we only handle the KICK_IT error by doing a recovery */
|
/*we only handle the KICK_IT error by doing a recovery */
|
||||||
|
@ -3055,10 +3053,9 @@ qeth_qdio_output_handler(struct ccw_device * ccwdev, unsigned int status,
|
||||||
qeth_check_outbound_queue(queue);
|
qeth_check_outbound_queue(queue);
|
||||||
|
|
||||||
netif_wake_queue(queue->card->dev);
|
netif_wake_queue(queue->card->dev);
|
||||||
#ifdef CONFIG_QETH_PERF_STATS
|
if (card->options.performance_stats)
|
||||||
card->perf_stats.outbound_handler_time += qeth_get_micros() -
|
card->perf_stats.outbound_handler_time += qeth_get_micros() -
|
||||||
card->perf_stats.outbound_handler_start_time;
|
card->perf_stats.outbound_handler_start_time;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -3684,10 +3681,10 @@ qeth_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||||
/* return OK; otherwise ksoftirqd goes to 100% */
|
/* return OK; otherwise ksoftirqd goes to 100% */
|
||||||
return NETDEV_TX_OK;
|
return NETDEV_TX_OK;
|
||||||
}
|
}
|
||||||
#ifdef CONFIG_QETH_PERF_STATS
|
if (card->options.performance_stats) {
|
||||||
card->perf_stats.outbound_cnt++;
|
card->perf_stats.outbound_cnt++;
|
||||||
card->perf_stats.outbound_start_time = qeth_get_micros();
|
card->perf_stats.outbound_start_time = qeth_get_micros();
|
||||||
#endif
|
}
|
||||||
netif_stop_queue(dev);
|
netif_stop_queue(dev);
|
||||||
if ((rc = qeth_send_packet(card, skb))) {
|
if ((rc = qeth_send_packet(card, skb))) {
|
||||||
if (rc == -EBUSY) {
|
if (rc == -EBUSY) {
|
||||||
|
@ -3701,10 +3698,9 @@ qeth_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
netif_wake_queue(dev);
|
netif_wake_queue(dev);
|
||||||
#ifdef CONFIG_QETH_PERF_STATS
|
if (card->options.performance_stats)
|
||||||
card->perf_stats.outbound_time += qeth_get_micros() -
|
card->perf_stats.outbound_time += qeth_get_micros() -
|
||||||
card->perf_stats.outbound_start_time;
|
card->perf_stats.outbound_start_time;
|
||||||
#endif
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4213,9 +4209,8 @@ qeth_fill_buffer(struct qeth_qdio_out_q *queue,
|
||||||
flush_cnt = 1;
|
flush_cnt = 1;
|
||||||
} else {
|
} else {
|
||||||
QETH_DBF_TEXT(trace, 6, "fillbfpa");
|
QETH_DBF_TEXT(trace, 6, "fillbfpa");
|
||||||
#ifdef CONFIG_QETH_PERF_STATS
|
if (queue->card->options.performance_stats)
|
||||||
queue->card->perf_stats.skbs_sent_pack++;
|
queue->card->perf_stats.skbs_sent_pack++;
|
||||||
#endif
|
|
||||||
if (buf->next_element_to_fill >=
|
if (buf->next_element_to_fill >=
|
||||||
QETH_MAX_BUFFER_ELEMENTS(queue->card)) {
|
QETH_MAX_BUFFER_ELEMENTS(queue->card)) {
|
||||||
/*
|
/*
|
||||||
|
@ -4380,10 +4375,8 @@ out:
|
||||||
qeth_flush_buffers(queue, 0, start_index, flush_count);
|
qeth_flush_buffers(queue, 0, start_index, flush_count);
|
||||||
}
|
}
|
||||||
/* at this point the queue is UNLOCKED again */
|
/* at this point the queue is UNLOCKED again */
|
||||||
#ifdef CONFIG_QETH_PERF_STATS
|
if (queue->card->options.performance_stats && do_pack)
|
||||||
if (do_pack)
|
|
||||||
queue->card->perf_stats.bufs_sent_pack += flush_count;
|
queue->card->perf_stats.bufs_sent_pack += flush_count;
|
||||||
#endif /* CONFIG_QETH_PERF_STATS */
|
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -4420,10 +4413,8 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb)
|
||||||
enum qeth_large_send_types large_send = QETH_LARGE_SEND_NO;
|
enum qeth_large_send_types large_send = QETH_LARGE_SEND_NO;
|
||||||
struct qeth_eddp_context *ctx = NULL;
|
struct qeth_eddp_context *ctx = NULL;
|
||||||
int tx_bytes = skb->len;
|
int tx_bytes = skb->len;
|
||||||
#ifdef CONFIG_QETH_PERF_STATS
|
|
||||||
unsigned short nr_frags = skb_shinfo(skb)->nr_frags;
|
unsigned short nr_frags = skb_shinfo(skb)->nr_frags;
|
||||||
unsigned short tso_size = skb_shinfo(skb)->gso_size;
|
unsigned short tso_size = skb_shinfo(skb)->gso_size;
|
||||||
#endif
|
|
||||||
struct sk_buff *new_skb, *new_skb2;
|
struct sk_buff *new_skb, *new_skb2;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
@ -4505,19 +4496,19 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb)
|
||||||
card->stats.tx_bytes += tx_bytes;
|
card->stats.tx_bytes += tx_bytes;
|
||||||
if (new_skb != skb)
|
if (new_skb != skb)
|
||||||
dev_kfree_skb_any(skb);
|
dev_kfree_skb_any(skb);
|
||||||
#ifdef CONFIG_QETH_PERF_STATS
|
if (card->options.performance_stats) {
|
||||||
if (tso_size &&
|
if (tso_size &&
|
||||||
!(large_send == QETH_LARGE_SEND_NO)) {
|
!(large_send == QETH_LARGE_SEND_NO)) {
|
||||||
card->perf_stats.large_send_bytes += tx_bytes;
|
card->perf_stats.large_send_bytes += tx_bytes;
|
||||||
card->perf_stats.large_send_cnt++;
|
card->perf_stats.large_send_cnt++;
|
||||||
|
}
|
||||||
|
if (nr_frags > 0) {
|
||||||
|
card->perf_stats.sg_skbs_sent++;
|
||||||
|
/* nr_frags + skb->data */
|
||||||
|
card->perf_stats.sg_frags_sent +=
|
||||||
|
nr_frags + 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (nr_frags > 0) {
|
|
||||||
card->perf_stats.sg_skbs_sent++;
|
|
||||||
/* nr_frags + skb->data */
|
|
||||||
card->perf_stats.sg_frags_sent +=
|
|
||||||
nr_frags + 1;
|
|
||||||
}
|
|
||||||
#endif /* CONFIG_QETH_PERF_STATS */
|
|
||||||
} else {
|
} else {
|
||||||
card->stats.tx_dropped++;
|
card->stats.tx_dropped++;
|
||||||
__qeth_free_new_skb(skb, new_skb);
|
__qeth_free_new_skb(skb, new_skb);
|
||||||
|
@ -7878,12 +7869,12 @@ __qeth_set_online(struct ccwgroup_device *gdev, int recovery_mode)
|
||||||
QETH_DBF_TEXT_(setup, 2, "5err%d", rc);
|
QETH_DBF_TEXT_(setup, 2, "5err%d", rc);
|
||||||
goto out_remove;
|
goto out_remove;
|
||||||
}
|
}
|
||||||
card->state = CARD_STATE_SOFTSETUP;
|
|
||||||
|
|
||||||
if ((rc = qeth_init_qdio_queues(card))){
|
if ((rc = qeth_init_qdio_queues(card))){
|
||||||
QETH_DBF_TEXT_(setup, 2, "6err%d", rc);
|
QETH_DBF_TEXT_(setup, 2, "6err%d", rc);
|
||||||
goto out_remove;
|
goto out_remove;
|
||||||
}
|
}
|
||||||
|
card->state = CARD_STATE_SOFTSETUP;
|
||||||
netif_carrier_on(card->dev);
|
netif_carrier_on(card->dev);
|
||||||
|
|
||||||
qeth_set_allowed_threads(card, 0xffffffff, 0);
|
qeth_set_allowed_threads(card, 0xffffffff, 0);
|
||||||
|
|
|
@ -173,7 +173,6 @@ static struct file_operations qeth_procfile_fops = {
|
||||||
#define QETH_PERF_PROCFILE_NAME "qeth_perf"
|
#define QETH_PERF_PROCFILE_NAME "qeth_perf"
|
||||||
static struct proc_dir_entry *qeth_perf_procfile;
|
static struct proc_dir_entry *qeth_perf_procfile;
|
||||||
|
|
||||||
#ifdef CONFIG_QETH_PERF_STATS
|
|
||||||
static int
|
static int
|
||||||
qeth_perf_procfile_seq_show(struct seq_file *s, void *it)
|
qeth_perf_procfile_seq_show(struct seq_file *s, void *it)
|
||||||
{
|
{
|
||||||
|
@ -192,14 +191,21 @@ qeth_perf_procfile_seq_show(struct seq_file *s, void *it)
|
||||||
CARD_DDEV_ID(card),
|
CARD_DDEV_ID(card),
|
||||||
QETH_CARD_IFNAME(card)
|
QETH_CARD_IFNAME(card)
|
||||||
);
|
);
|
||||||
|
if (!card->options.performance_stats)
|
||||||
|
seq_printf(s, "Performance statistics are deactivated.\n");
|
||||||
seq_printf(s, " Skb's/buffers received : %lu/%u\n"
|
seq_printf(s, " Skb's/buffers received : %lu/%u\n"
|
||||||
" Skb's/buffers sent : %lu/%u\n\n",
|
" Skb's/buffers sent : %lu/%u\n\n",
|
||||||
card->stats.rx_packets, card->perf_stats.bufs_rec,
|
card->stats.rx_packets -
|
||||||
card->stats.tx_packets, card->perf_stats.bufs_sent
|
card->perf_stats.initial_rx_packets,
|
||||||
|
card->perf_stats.bufs_rec,
|
||||||
|
card->stats.tx_packets -
|
||||||
|
card->perf_stats.initial_tx_packets,
|
||||||
|
card->perf_stats.bufs_sent
|
||||||
);
|
);
|
||||||
seq_printf(s, " Skb's/buffers sent without packing : %lu/%u\n"
|
seq_printf(s, " Skb's/buffers sent without packing : %lu/%u\n"
|
||||||
" Skb's/buffers sent with packing : %u/%u\n\n",
|
" Skb's/buffers sent with packing : %u/%u\n\n",
|
||||||
card->stats.tx_packets - card->perf_stats.skbs_sent_pack,
|
card->stats.tx_packets - card->perf_stats.initial_tx_packets
|
||||||
|
- card->perf_stats.skbs_sent_pack,
|
||||||
card->perf_stats.bufs_sent - card->perf_stats.bufs_sent_pack,
|
card->perf_stats.bufs_sent - card->perf_stats.bufs_sent_pack,
|
||||||
card->perf_stats.skbs_sent_pack,
|
card->perf_stats.skbs_sent_pack,
|
||||||
card->perf_stats.bufs_sent_pack
|
card->perf_stats.bufs_sent_pack
|
||||||
|
@ -275,11 +281,6 @@ static struct file_operations qeth_perf_procfile_fops = {
|
||||||
.release = seq_release,
|
.release = seq_release,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define qeth_perf_procfile_created qeth_perf_procfile
|
|
||||||
#else
|
|
||||||
#define qeth_perf_procfile_created 1
|
|
||||||
#endif /* CONFIG_QETH_PERF_STATS */
|
|
||||||
|
|
||||||
int __init
|
int __init
|
||||||
qeth_create_procfs_entries(void)
|
qeth_create_procfs_entries(void)
|
||||||
{
|
{
|
||||||
|
@ -288,15 +289,13 @@ qeth_create_procfs_entries(void)
|
||||||
if (qeth_procfile)
|
if (qeth_procfile)
|
||||||
qeth_procfile->proc_fops = &qeth_procfile_fops;
|
qeth_procfile->proc_fops = &qeth_procfile_fops;
|
||||||
|
|
||||||
#ifdef CONFIG_QETH_PERF_STATS
|
|
||||||
qeth_perf_procfile = create_proc_entry(QETH_PERF_PROCFILE_NAME,
|
qeth_perf_procfile = create_proc_entry(QETH_PERF_PROCFILE_NAME,
|
||||||
S_IFREG | 0444, NULL);
|
S_IFREG | 0444, NULL);
|
||||||
if (qeth_perf_procfile)
|
if (qeth_perf_procfile)
|
||||||
qeth_perf_procfile->proc_fops = &qeth_perf_procfile_fops;
|
qeth_perf_procfile->proc_fops = &qeth_perf_procfile_fops;
|
||||||
#endif /* CONFIG_QETH_PERF_STATS */
|
|
||||||
|
|
||||||
if (qeth_procfile &&
|
if (qeth_procfile &&
|
||||||
qeth_perf_procfile_created)
|
qeth_perf_procfile)
|
||||||
return 0;
|
return 0;
|
||||||
else
|
else
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
|
@ -742,6 +742,47 @@ qeth_dev_layer2_store(struct device *dev, struct device_attribute *attr, const c
|
||||||
static DEVICE_ATTR(layer2, 0644, qeth_dev_layer2_show,
|
static DEVICE_ATTR(layer2, 0644, qeth_dev_layer2_show,
|
||||||
qeth_dev_layer2_store);
|
qeth_dev_layer2_store);
|
||||||
|
|
||||||
|
static ssize_t
|
||||||
|
qeth_dev_performance_stats_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
struct qeth_card *card = dev->driver_data;
|
||||||
|
|
||||||
|
if (!card)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
return sprintf(buf, "%i\n", card->options.performance_stats ? 1:0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t
|
||||||
|
qeth_dev_performance_stats_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
|
||||||
|
{
|
||||||
|
struct qeth_card *card = dev->driver_data;
|
||||||
|
char *tmp;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!card)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
i = simple_strtoul(buf, &tmp, 16);
|
||||||
|
if ((i == 0) || (i == 1)) {
|
||||||
|
if (i == card->options.performance_stats)
|
||||||
|
return count;
|
||||||
|
card->options.performance_stats = i;
|
||||||
|
if (i == 0)
|
||||||
|
memset(&card->perf_stats, 0,
|
||||||
|
sizeof(struct qeth_perf_stats));
|
||||||
|
card->perf_stats.initial_rx_packets = card->stats.rx_packets;
|
||||||
|
card->perf_stats.initial_tx_packets = card->stats.tx_packets;
|
||||||
|
} else {
|
||||||
|
PRINT_WARN("performance_stats: write 0 or 1 to this file!\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static DEVICE_ATTR(performance_stats, 0644, qeth_dev_performance_stats_show,
|
||||||
|
qeth_dev_performance_stats_store);
|
||||||
|
|
||||||
static ssize_t
|
static ssize_t
|
||||||
qeth_dev_large_send_show(struct device *dev, struct device_attribute *attr, char *buf)
|
qeth_dev_large_send_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||||
{
|
{
|
||||||
|
@ -928,6 +969,7 @@ static struct device_attribute * qeth_device_attrs[] = {
|
||||||
&dev_attr_canonical_macaddr,
|
&dev_attr_canonical_macaddr,
|
||||||
&dev_attr_layer2,
|
&dev_attr_layer2,
|
||||||
&dev_attr_large_send,
|
&dev_attr_large_send,
|
||||||
|
&dev_attr_performance_stats,
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Reference in a new issue