Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 214359
b: refs/heads/master
c: a1c3ed4
h: refs/heads/master
i:
  214357: 659fe17
  214355: 8f6a50d
  214351: 72da90e
v: v3
  • Loading branch information
Frank Blaschka authored and David S. Miller committed Sep 8, 2010
1 parent 9d82b23 commit 6eac897
Show file tree
Hide file tree
Showing 5 changed files with 261 additions and 139 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 81d53749416995538f830c8e4d3fbaf1769b9375
refs/heads/master: a1c3ed4c9ca01dded8d511a1d1daf271fbae8d89
17 changes: 17 additions & 0 deletions trunk/drivers/s390/net/qeth_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -676,6 +676,7 @@ enum qeth_discipline_id {
};

struct qeth_discipline {
void (*start_poll)(struct ccw_device *, int, unsigned long);
qdio_handler_t *input_handler;
qdio_handler_t *output_handler;
int (*recover)(void *ptr);
Expand All @@ -702,6 +703,16 @@ struct qeth_skb_data {
#define QETH_SKB_MAGIC 0x71657468
#define QETH_SIGA_CC2_RETRIES 3

struct qeth_rx {
int b_count;
int b_index;
struct qdio_buffer_element *b_element;
int e_offset;
int qdio_err;
};

#define QETH_NAPI_WEIGHT 128

struct qeth_card {
struct list_head list;
enum qeth_card_states state;
Expand Down Expand Up @@ -749,6 +760,8 @@ struct qeth_card {
debug_info_t *debug;
struct mutex conf_mutex;
struct mutex discipline_mutex;
struct napi_struct napi;
struct qeth_rx rx;
};

struct qeth_card_list_struct {
Expand Down Expand Up @@ -831,6 +844,10 @@ struct sk_buff *qeth_core_get_next_skb(struct qeth_card *,
struct qdio_buffer *, struct qdio_buffer_element **, int *,
struct qeth_hdr **);
void qeth_schedule_recovery(struct qeth_card *);
void qeth_qdio_start_poll(struct ccw_device *, int, unsigned long);
void qeth_qdio_input_handler(struct ccw_device *,
unsigned int, unsigned int, int,
int, unsigned long);
void qeth_qdio_output_handler(struct ccw_device *, unsigned int,
int, int, int, unsigned long);
void qeth_clear_ipacmd_list(struct qeth_card *);
Expand Down
26 changes: 24 additions & 2 deletions trunk/drivers/s390/net/qeth_core_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -2911,6 +2911,27 @@ static void qeth_check_outbound_queue(struct qeth_qdio_out_q *queue)
}
}

void qeth_qdio_start_poll(struct ccw_device *ccwdev, int queue,
unsigned long card_ptr)
{
struct qeth_card *card = (struct qeth_card *)card_ptr;

if (card->dev)
napi_schedule(&card->napi);
}
EXPORT_SYMBOL_GPL(qeth_qdio_start_poll);

void qeth_qdio_input_handler(struct ccw_device *ccwdev, unsigned int qdio_err,
unsigned int queue, int first_element, int count,
unsigned long card_ptr)
{
struct qeth_card *card = (struct qeth_card *)card_ptr;

if (qdio_err)
qeth_schedule_recovery(card);
}
EXPORT_SYMBOL_GPL(qeth_qdio_input_handler);

void qeth_qdio_output_handler(struct ccw_device *ccwdev,
unsigned int qdio_error, int __queue, int first_element,
int count, unsigned long card_ptr)
Expand Down Expand Up @@ -3843,6 +3864,7 @@ static int qeth_qdio_establish(struct qeth_card *card)
init_data.no_output_qs = card->qdio.no_out_queues;
init_data.input_handler = card->discipline.input_handler;
init_data.output_handler = card->discipline.output_handler;
init_data.queue_start_poll = card->discipline.start_poll;
init_data.int_parm = (unsigned long) card;
init_data.input_sbal_addr_array = (void **) in_sbal_ptrs;
init_data.output_sbal_addr_array = (void **) out_sbal_ptrs;
Expand Down Expand Up @@ -4513,8 +4535,8 @@ static struct {
/* 20 */{"queue 1 buffer usage"},
{"queue 2 buffer usage"},
{"queue 3 buffer usage"},
{"rx handler time"},
{"rx handler count"},
{"rx poll time"},
{"rx poll count"},
{"rx do_QDIO time"},
{"rx do_QDIO count"},
{"tx handler time"},
Expand Down
173 changes: 108 additions & 65 deletions trunk/drivers/s390/net/qeth_l2_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -407,29 +407,25 @@ static int qeth_l2_stop_card(struct qeth_card *card, int recovery_mode)
return rc;
}

static void qeth_l2_process_inbound_buffer(struct qeth_card *card,
struct qeth_qdio_buffer *buf, int index)
static int qeth_l2_process_inbound_buffer(struct qeth_card *card,
int budget, int *done)
{
struct qdio_buffer_element *element;
int work_done = 0;
struct sk_buff *skb;
struct qeth_hdr *hdr;
int offset;
unsigned int len;

/* get first element of current buffer */
element = (struct qdio_buffer_element *)&buf->buffer->element[0];
offset = 0;
if (card->options.performance_stats)
card->perf_stats.bufs_rec++;
while ((skb = qeth_core_get_next_skb(card, buf->buffer, &element,
&offset, &hdr))) {
skb->dev = card->dev;
/* is device UP ? */
if (!(card->dev->flags & IFF_UP)) {
dev_kfree_skb_any(skb);
continue;
*done = 0;
BUG_ON(!budget);
while (budget) {
skb = qeth_core_get_next_skb(card,
card->qdio.in_q->bufs[card->rx.b_index].buffer,
&card->rx.b_element, &card->rx.e_offset, &hdr);
if (!skb) {
*done = 1;
break;
}

skb->dev = card->dev;
switch (hdr->hdr.l2.id) {
case QETH_HEADER_TYPE_LAYER2:
skb->pkt_type = PACKET_HOST;
Expand All @@ -441,7 +437,7 @@ static void qeth_l2_process_inbound_buffer(struct qeth_card *card,
if (skb->protocol == htons(ETH_P_802_2))
*((__u32 *)skb->cb) = ++card->seqno.pkt_seqno;
len = skb->len;
netif_rx(skb);
netif_receive_skb(skb);
break;
case QETH_HEADER_TYPE_OSN:
if (card->info.type == QETH_CARD_TYPE_OSN) {
Expand All @@ -459,9 +455,87 @@ static void qeth_l2_process_inbound_buffer(struct qeth_card *card,
QETH_DBF_HEX(CTRL, 3, hdr, QETH_DBF_CTRL_LEN);
continue;
}
work_done++;
budget--;
card->stats.rx_packets++;
card->stats.rx_bytes += len;
}
return work_done;
}

static int qeth_l2_poll(struct napi_struct *napi, int budget)
{
struct qeth_card *card = container_of(napi, struct qeth_card, napi);
int work_done = 0;
struct qeth_qdio_buffer *buffer;
int done;
int new_budget = budget;

if (card->options.performance_stats) {
card->perf_stats.inbound_cnt++;
card->perf_stats.inbound_start_time = qeth_get_micros();
}

while (1) {
if (!card->rx.b_count) {
card->rx.qdio_err = 0;
card->rx.b_count = qdio_get_next_buffers(
card->data.ccwdev, 0, &card->rx.b_index,
&card->rx.qdio_err);
if (card->rx.b_count <= 0) {
card->rx.b_count = 0;
break;
}
card->rx.b_element =
&card->qdio.in_q->bufs[card->rx.b_index]
.buffer->element[0];
card->rx.e_offset = 0;
}

while (card->rx.b_count) {
buffer = &card->qdio.in_q->bufs[card->rx.b_index];
if (!(card->rx.qdio_err &&
qeth_check_qdio_errors(card, buffer->buffer,
card->rx.qdio_err, "qinerr")))
work_done += qeth_l2_process_inbound_buffer(
card, new_budget, &done);
else
done = 1;

if (done) {
if (card->options.performance_stats)
card->perf_stats.bufs_rec++;
qeth_put_buffer_pool_entry(card,
buffer->pool_entry);
qeth_queue_input_buffer(card, card->rx.b_index);
card->rx.b_count--;
if (card->rx.b_count) {
card->rx.b_index =
(card->rx.b_index + 1) %
QDIO_MAX_BUFFERS_PER_Q;
card->rx.b_element =
&card->qdio.in_q
->bufs[card->rx.b_index]
.buffer->element[0];
card->rx.e_offset = 0;
}
}

if (work_done >= budget)
goto out;
else
new_budget = budget - work_done;
}
}

napi_complete(napi);
if (qdio_start_irq(card->data.ccwdev, 0))
napi_schedule(&card->napi);
out:
if (card->options.performance_stats)
card->perf_stats.inbound_time += qeth_get_micros() -
card->perf_stats.inbound_start_time;
return work_done;
}

static int qeth_l2_send_setdelmac(struct qeth_card *card, __u8 *mac,
Expand Down Expand Up @@ -755,49 +829,10 @@ static int qeth_l2_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
return NETDEV_TX_OK;
}

static void qeth_l2_qdio_input_handler(struct ccw_device *ccwdev,
unsigned int qdio_err, unsigned int queue,
int first_element, int count, unsigned long card_ptr)
{
struct net_device *net_dev;
struct qeth_card *card;
struct qeth_qdio_buffer *buffer;
int index;
int i;

card = (struct qeth_card *) card_ptr;
net_dev = card->dev;
if (card->options.performance_stats) {
card->perf_stats.inbound_cnt++;
card->perf_stats.inbound_start_time = qeth_get_micros();
}
if (qdio_err & QDIO_ERROR_ACTIVATE_CHECK_CONDITION) {
QETH_CARD_TEXT(card, 1, "qdinchk");
QETH_CARD_TEXT_(card, 1, "%04X%04X", first_element,
count);
QETH_CARD_TEXT_(card, 1, "%04X", queue);
qeth_schedule_recovery(card);
return;
}
for (i = first_element; i < (first_element + count); ++i) {
index = i % QDIO_MAX_BUFFERS_PER_Q;
buffer = &card->qdio.in_q->bufs[index];
if (!(qdio_err &&
qeth_check_qdio_errors(card, buffer->buffer, qdio_err,
"qinerr")))
qeth_l2_process_inbound_buffer(card, buffer, index);
/* clear buffer and give back to hardware */
qeth_put_buffer_pool_entry(card, buffer->pool_entry);
qeth_queue_input_buffer(card, index);
}
if (card->options.performance_stats)
card->perf_stats.inbound_time += qeth_get_micros() -
card->perf_stats.inbound_start_time;
}

static int qeth_l2_open(struct net_device *dev)
{
struct qeth_card *card = dev->ml_priv;
int rc = 0;

QETH_CARD_TEXT(card, 4, "qethopen");
if (card->state != CARD_STATE_SOFTSETUP)
Expand All @@ -814,18 +849,24 @@ static int qeth_l2_open(struct net_device *dev)

if (!card->lan_online && netif_carrier_ok(dev))
netif_carrier_off(dev);
return 0;
if (qdio_stop_irq(card->data.ccwdev, 0) >= 0) {
napi_enable(&card->napi);
napi_schedule(&card->napi);
} else
rc = -EIO;
return rc;
}


static int qeth_l2_stop(struct net_device *dev)
{
struct qeth_card *card = dev->ml_priv;

QETH_CARD_TEXT(card, 4, "qethstop");
netif_tx_disable(dev);
if (card->state == CARD_STATE_UP)
if (card->state == CARD_STATE_UP) {
card->state = CARD_STATE_SOFTSETUP;
napi_disable(&card->napi);
}
return 0;
}

Expand All @@ -836,8 +877,9 @@ static int qeth_l2_probe_device(struct ccwgroup_device *gdev)
INIT_LIST_HEAD(&card->vid_list);
INIT_LIST_HEAD(&card->mc_list);
card->options.layer2 = 1;
card->discipline.start_poll = qeth_qdio_start_poll;
card->discipline.input_handler = (qdio_handler_t *)
qeth_l2_qdio_input_handler;
qeth_qdio_input_handler;
card->discipline.output_handler = (qdio_handler_t *)
qeth_qdio_output_handler;
card->discipline.recover = qeth_l2_recover;
Expand Down Expand Up @@ -923,6 +965,7 @@ static int qeth_l2_setup_netdev(struct qeth_card *card)
card->info.broadcast_capable = 1;
qeth_l2_request_initial_mac(card);
SET_NETDEV_DEV(card->dev, &card->gdev->dev);
netif_napi_add(card->dev, &card->napi, qeth_l2_poll, QETH_NAPI_WEIGHT);
return register_netdev(card->dev);
}

Expand Down Expand Up @@ -955,6 +998,7 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)
qeth_l2_send_setmac(card, &card->dev->dev_addr[0]);

card->state = CARD_STATE_HARDSETUP;
memset(&card->rx, 0, sizeof(struct qeth_rx));
qeth_print_status_message(card);

/* softsetup */
Expand Down Expand Up @@ -1086,9 +1130,6 @@ static int qeth_l2_recover(void *ptr)
card->use_hard_stop = 1;
__qeth_l2_set_offline(card->gdev, 1);
rc = __qeth_l2_set_online(card->gdev, 1);
/* don't run another scheduled recovery */
qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD);
qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD);
if (!rc)
dev_info(&card->gdev->dev,
"Device successfully recovered!\n");
Expand All @@ -1099,6 +1140,8 @@ static int qeth_l2_recover(void *ptr)
dev_warn(&card->gdev->dev, "The qeth device driver "
"failed to recover an error on the device\n");
}
qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD);
qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD);
return 0;
}

Expand Down
Loading

0 comments on commit 6eac897

Please sign in to comment.