From 963a9fd22d7e5b50806f619ef8d047fd9398f105 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 7 Sep 2010 21:14:40 +0000 Subject: qeth: Use %pI6 Format an ipv6 address using vsprintf extensions. Signed-off-by: Joe Perches Signed-off-by: Frank Blaschka Signed-off-by: David S. Miller --- drivers/s390/net/qeth_l3_main.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'drivers/s390/net/qeth_l3_main.c') diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index e22ae248f61..561bdc881e9 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -103,12 +103,7 @@ int qeth_l3_string_to_ipaddr4(const char *buf, __u8 *addr) void qeth_l3_ipaddr6_to_string(const __u8 *addr, char *buf) { - sprintf(buf, "%02x%02x:%02x%02x:%02x%02x:%02x%02x" - ":%02x%02x:%02x%02x:%02x%02x:%02x%02x", - addr[0], addr[1], addr[2], addr[3], - addr[4], addr[5], addr[6], addr[7], - addr[8], addr[9], addr[10], addr[11], - addr[12], addr[13], addr[14], addr[15]); + sprintf(buf, "%pI6", addr); } int qeth_l3_string_to_ipaddr6(const char *buf, __u8 *addr) -- cgit v1.2.3-70-g09d2 From a1c3ed4c9ca01dded8d511a1d1daf271fbae8d89 Mon Sep 17 00:00:00 2001 From: Frank Blaschka Date: Tue, 7 Sep 2010 21:14:42 +0000 Subject: qeth: NAPI support for l2 and l3 discipline This patch adds NAPI support to the qeth layer 2 and layer 3 discipline. It is important to understand that we can not enable/disable IRQs as usual, we have to use the corresponding new QDIO interface. Also to not overdraw the budget we have to stop and restart buffer processing at any point during processing a bulk of QDIO buffers. Having the driver NAPI enabled it is possible to turn on GRO for the layer 3 discipline. Signed-off-by: Frank Blaschka Signed-off-by: David S. Miller --- drivers/s390/net/qeth_core.h | 17 ++++ drivers/s390/net/qeth_core_main.c | 26 +++++- drivers/s390/net/qeth_l2_main.c | 173 ++++++++++++++++++++++-------------- drivers/s390/net/qeth_l3_main.c | 182 +++++++++++++++++++++++--------------- 4 files changed, 260 insertions(+), 138 deletions(-) (limited to 'drivers/s390/net/qeth_l3_main.c') diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h index d1257768be9..6be43eb126b 100644 --- a/drivers/s390/net/qeth_core.h +++ b/drivers/s390/net/qeth_core.h @@ -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); @@ -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; @@ -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 { @@ -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 *); diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 3a5a18a0fc2..76426706260 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -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) @@ -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; @@ -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"}, diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index 830d63524d6..01c3c1f7787 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -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; @@ -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) { @@ -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, @@ -755,49 +829,10 @@ tx_drop: 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) @@ -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; } @@ -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; @@ -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); } @@ -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 */ @@ -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"); @@ -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; } diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index 561bdc881e9..5b79f573bd9 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -2107,51 +2107,44 @@ static inline __u16 qeth_l3_rebuild_skb(struct qeth_card *card, return vlan_id; } -static void qeth_l3_process_inbound_buffer(struct qeth_card *card, - struct qeth_qdio_buffer *buf, int index) +static int qeth_l3_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; __u16 vlan_tag = 0; 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.l3.id) { case QETH_HEADER_TYPE_LAYER3: vlan_tag = qeth_l3_rebuild_skb(card, skb, hdr); len = skb->len; if (vlan_tag && !card->options.sniffer) if (card->vlangrp) - vlan_hwaccel_rx(skb, card->vlangrp, - vlan_tag); + vlan_gro_receive(&card->napi, + card->vlangrp, vlan_tag, skb); else { dev_kfree_skb_any(skb); continue; } else - netif_rx(skb); + napi_gro_receive(&card->napi, skb); break; case QETH_HEADER_TYPE_LAYER2: /* for HiperSockets sniffer */ skb->pkt_type = PACKET_HOST; skb->protocol = eth_type_trans(skb, skb->dev); - if (card->options.checksum_type == NO_CHECKSUMMING) - skb->ip_summed = CHECKSUM_UNNECESSARY; - else - skb->ip_summed = CHECKSUM_NONE; len = skb->len; netif_receive_skb(skb); break; @@ -2161,10 +2154,87 @@ static void qeth_l3_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_l3_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_l3_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_l3_verify_vlan_dev(struct net_device *dev, @@ -3098,6 +3168,7 @@ tx_drop: static int qeth_l3_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) @@ -3108,7 +3179,12 @@ static int qeth_l3_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_l3_stop(struct net_device *dev) @@ -3117,8 +3193,10 @@ static int qeth_l3_stop(struct net_device *dev) 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; } @@ -3288,57 +3366,19 @@ static int qeth_l3_setup_netdev(struct qeth_card *card) card->dev->gso_max_size = 15 * PAGE_SIZE; SET_NETDEV_DEV(card->dev, &card->gdev->dev); + netif_napi_add(card->dev, &card->napi, qeth_l3_poll, QETH_NAPI_WEIGHT); return register_netdev(card->dev); } -static void qeth_l3_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_l3_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_l3_probe_device(struct ccwgroup_device *gdev) { struct qeth_card *card = dev_get_drvdata(&gdev->dev); qeth_l3_create_device_attributes(&gdev->dev); card->options.layer2 = 0; + card->discipline.start_poll = qeth_qdio_start_poll; card->discipline.input_handler = (qdio_handler_t *) - qeth_l3_qdio_input_handler; + qeth_qdio_input_handler; card->discipline.output_handler = (qdio_handler_t *) qeth_qdio_output_handler; card->discipline.recover = qeth_l3_recover; @@ -3397,6 +3437,7 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode) } card->state = CARD_STATE_HARDSETUP; + memset(&card->rx, 0, sizeof(struct qeth_rx)); qeth_print_status_message(card); /* softsetup */ @@ -3533,9 +3574,6 @@ static int qeth_l3_recover(void *ptr) card->use_hard_stop = 1; __qeth_l3_set_offline(card->gdev, 1); rc = __qeth_l3_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"); @@ -3546,6 +3584,8 @@ static int qeth_l3_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; } -- cgit v1.2.3-70-g09d2 From 10651db75a94c54a34bbf85fbee334d1114da3fb Mon Sep 17 00:00:00 2001 From: Ursula Braun Date: Fri, 1 Oct 2010 02:51:13 +0000 Subject: qeth: tagging with VLAN-ID 0 This patch adapts qeth to handle tagged frames with VLAN-ID 0 and with or without priority information in the tag. It enables qeth to receive priority-tagged frames on a base interface, for example from z/OS, without configuring an additional VLAN interface. Signed-off-by: Ursula Braun Signed-off-by: Frank Blaschka Signed-off-by: David S. Miller --- drivers/s390/net/qeth_l2_main.c | 2 ++ drivers/s390/net/qeth_l3_main.c | 27 +++++++++++++-------------- 2 files changed, 15 insertions(+), 14 deletions(-) (limited to 'drivers/s390/net/qeth_l3_main.c') diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index 01c3c1f7787..847e8797073 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -310,6 +310,8 @@ static void qeth_l2_vlan_rx_add_vid(struct net_device *dev, unsigned short vid) struct qeth_vlan_vid *id; QETH_CARD_TEXT_(card, 4, "aid:%d", vid); + if (!vid) + return; if (card->info.type == QETH_CARD_TYPE_OSM) { QETH_CARD_TEXT(card, 3, "aidOSM"); return; diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index 5b79f573bd9..c094707fcbf 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -2013,13 +2013,14 @@ static void qeth_l3_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) qeth_l3_set_multicast_list(card->dev); } -static inline __u16 qeth_l3_rebuild_skb(struct qeth_card *card, - struct sk_buff *skb, struct qeth_hdr *hdr) +static inline int qeth_l3_rebuild_skb(struct qeth_card *card, + struct sk_buff *skb, struct qeth_hdr *hdr, + unsigned short *vlan_id) { - unsigned short vlan_id = 0; __be16 prot; struct iphdr *ip_hdr; unsigned char tg_addr[MAX_ADDR_LEN]; + int is_vlan = 0; if (!(hdr->hdr.l3.flags & QETH_HDR_PASSTHRU)) { prot = htons((hdr->hdr.l3.flags & QETH_HDR_IPV6)? ETH_P_IPV6 : @@ -2082,8 +2083,9 @@ static inline __u16 qeth_l3_rebuild_skb(struct qeth_card *card, if (hdr->hdr.l3.ext_flags & (QETH_HDR_EXT_VLAN_FRAME | QETH_HDR_EXT_INCLUDE_VLAN_TAG)) { - vlan_id = (hdr->hdr.l3.ext_flags & QETH_HDR_EXT_VLAN_FRAME)? + *vlan_id = (hdr->hdr.l3.ext_flags & QETH_HDR_EXT_VLAN_FRAME) ? hdr->hdr.l3.vlan_id : *((u16 *)&hdr->hdr.l3.dest_addr[12]); + is_vlan = 1; } switch (card->options.checksum_type) { @@ -2104,7 +2106,7 @@ static inline __u16 qeth_l3_rebuild_skb(struct qeth_card *card, skb->ip_summed = CHECKSUM_NONE; } - return vlan_id; + return is_vlan; } static int qeth_l3_process_inbound_buffer(struct qeth_card *card, @@ -2114,6 +2116,7 @@ static int qeth_l3_process_inbound_buffer(struct qeth_card *card, struct sk_buff *skb; struct qeth_hdr *hdr; __u16 vlan_tag = 0; + int is_vlan; unsigned int len; *done = 0; @@ -2129,16 +2132,12 @@ static int qeth_l3_process_inbound_buffer(struct qeth_card *card, skb->dev = card->dev; switch (hdr->hdr.l3.id) { case QETH_HEADER_TYPE_LAYER3: - vlan_tag = qeth_l3_rebuild_skb(card, skb, hdr); + is_vlan = qeth_l3_rebuild_skb(card, skb, hdr, + &vlan_tag); len = skb->len; - if (vlan_tag && !card->options.sniffer) - if (card->vlangrp) - vlan_gro_receive(&card->napi, - card->vlangrp, vlan_tag, skb); - else { - dev_kfree_skb_any(skb); - continue; - } + if (is_vlan && !card->options.sniffer) + vlan_gro_receive(&card->napi, card->vlangrp, + vlan_tag, skb); else napi_gro_receive(&card->napi, skb); break; -- cgit v1.2.3-70-g09d2 From b738127dfb469bb9f595cdace30e7f881e8146b2 Mon Sep 17 00:00:00 2001 From: Jesse Gross Date: Wed, 20 Oct 2010 13:56:02 +0000 Subject: vlan: Rename VLAN_GROUP_ARRAY_LEN to VLAN_N_VID. VLAN_GROUP_ARRAY_LEN is simply the number of possible vlan VIDs. Since vlan groups will soon be more of an implementation detail for vlan devices, rename the constant to be descriptive of its actual purpose. Signed-off-by: Jesse Gross Signed-off-by: David S. Miller --- drivers/net/benet/be.h | 2 +- drivers/net/benet/be_main.c | 2 +- drivers/net/e1000/e1000_main.c | 2 +- drivers/net/e1000e/netdev.c | 2 +- drivers/net/igb/igb_main.c | 2 +- drivers/net/igbvf/netdev.c | 2 +- drivers/net/ixgb/ixgb_main.c | 2 +- drivers/net/ixgbe/ixgbe_main.c | 2 +- drivers/net/ixgbevf/ixgbevf_main.c | 2 +- drivers/net/qlcnic/qlcnic_main.c | 2 +- drivers/net/vmxnet3/vmxnet3_drv.c | 2 +- drivers/net/vxge/vxge-main.c | 2 +- drivers/s390/net/qeth_l3_main.c | 6 +++--- include/linux/if_vlan.h | 4 ++-- net/8021q/vlan.c | 16 ++++++++-------- net/bridge/netfilter/ebt_vlan.c | 4 ++-- 16 files changed, 27 insertions(+), 27 deletions(-) (limited to 'drivers/s390/net/qeth_l3_main.c') diff --git a/drivers/net/benet/be.h b/drivers/net/benet/be.h index 1afabb1e662..59a17b569b7 100644 --- a/drivers/net/benet/be.h +++ b/drivers/net/benet/be.h @@ -263,7 +263,7 @@ struct be_adapter { struct vlan_group *vlan_grp; u16 vlans_added; u16 max_vlans; /* Number of vlans supported */ - u8 vlan_tag[VLAN_GROUP_ARRAY_LEN]; + u8 vlan_tag[VLAN_N_VID]; struct be_dma_mem mc_cmd_mem; struct be_dma_mem stats_cmd; diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 9a1cd28b426..4b59e53890b 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -626,7 +626,7 @@ static int be_vid_config(struct be_adapter *adapter, bool vf, u32 vf_num) if (adapter->vlans_added <= adapter->max_vlans) { /* Construct VLAN Table to give to HW */ - for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { + for (i = 0; i < VLAN_N_VID; i++) { if (adapter->vlan_tag[i]) { vtag[ntags] = cpu_to_le16(i); ntags++; diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index cb3f84b8179..232ac2dcb49 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -4541,7 +4541,7 @@ static void e1000_restore_vlan(struct e1000_adapter *adapter) if (adapter->vlgrp) { u16 vid; - for (vid = 0; vid < VLAN_GROUP_ARRAY_LEN; vid++) { + for (vid = 0; vid < VLAN_N_VID; vid++) { if (!vlan_group_get_device(adapter->vlgrp, vid)) continue; e1000_vlan_rx_add_vid(adapter->netdev, vid); diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index 992b622fe20..5d6cdea0eb1 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -2545,7 +2545,7 @@ static void e1000_restore_vlan(struct e1000_adapter *adapter) if (!adapter->vlgrp) return; - for (vid = 0; vid < VLAN_GROUP_ARRAY_LEN; vid++) { + for (vid = 0; vid < VLAN_N_VID; vid++) { if (!vlan_group_get_device(adapter->vlgrp, vid)) continue; e1000_vlan_rx_add_vid(adapter->netdev, vid); diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index b8dccc0ac08..0f0939caf09 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -6153,7 +6153,7 @@ static void igb_restore_vlan(struct igb_adapter *adapter) if (adapter->vlgrp) { u16 vid; - for (vid = 0; vid < VLAN_GROUP_ARRAY_LEN; vid++) { + for (vid = 0; vid < VLAN_N_VID; vid++) { if (!vlan_group_get_device(adapter->vlgrp, vid)) continue; igb_vlan_rx_add_vid(adapter->netdev, vid); diff --git a/drivers/net/igbvf/netdev.c b/drivers/net/igbvf/netdev.c index 6693323a6cf..ebfaa68ee63 100644 --- a/drivers/net/igbvf/netdev.c +++ b/drivers/net/igbvf/netdev.c @@ -1254,7 +1254,7 @@ static void igbvf_restore_vlan(struct igbvf_adapter *adapter) if (!adapter->vlgrp) return; - for (vid = 0; vid < VLAN_GROUP_ARRAY_LEN; vid++) { + for (vid = 0; vid < VLAN_N_VID; vid++) { if (!vlan_group_get_device(adapter->vlgrp, vid)) continue; igbvf_vlan_rx_add_vid(adapter->netdev, vid); diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c index 80e62578ffa..666207a9c03 100644 --- a/drivers/net/ixgb/ixgb_main.c +++ b/drivers/net/ixgb/ixgb_main.c @@ -2223,7 +2223,7 @@ ixgb_restore_vlan(struct ixgb_adapter *adapter) if (adapter->vlgrp) { u16 vid; - for (vid = 0; vid < VLAN_GROUP_ARRAY_LEN; vid++) { + for (vid = 0; vid < VLAN_N_VID; vid++) { if (!vlan_group_get_device(adapter->vlgrp, vid)) continue; ixgb_vlan_rx_add_vid(adapter->netdev, vid); diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 790a0dae124..1d424428079 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -3185,7 +3185,7 @@ static void ixgbe_restore_vlan(struct ixgbe_adapter *adapter) if (adapter->vlgrp) { u16 vid; - for (vid = 0; vid < VLAN_GROUP_ARRAY_LEN; vid++) { + for (vid = 0; vid < VLAN_N_VID; vid++) { if (!vlan_group_get_device(adapter->vlgrp, vid)) continue; ixgbe_vlan_rx_add_vid(adapter->netdev, vid); diff --git a/drivers/net/ixgbevf/ixgbevf_main.c b/drivers/net/ixgbevf/ixgbevf_main.c index 0866a1cf4d7..78bfbe42ca9 100644 --- a/drivers/net/ixgbevf/ixgbevf_main.c +++ b/drivers/net/ixgbevf/ixgbevf_main.c @@ -1495,7 +1495,7 @@ static void ixgbevf_restore_vlan(struct ixgbevf_adapter *adapter) if (adapter->vlgrp) { u16 vid; - for (vid = 0; vid < VLAN_GROUP_ARRAY_LEN; vid++) { + for (vid = 0; vid < VLAN_N_VID; vid++) { if (!vlan_group_get_device(adapter->vlgrp, vid)) continue; ixgbevf_vlan_rx_add_vid(adapter->netdev, vid); diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c index 4aada0b8ceb..f047c7c4831 100644 --- a/drivers/net/qlcnic/qlcnic_main.c +++ b/drivers/net/qlcnic/qlcnic_main.c @@ -4093,7 +4093,7 @@ qlcnic_restore_indev_addr(struct net_device *netdev, unsigned long event) if (!adapter->vlgrp) return; - for (vid = 0; vid < VLAN_GROUP_ARRAY_LEN; vid++) { + for (vid = 0; vid < VLAN_N_VID; vid++) { dev = vlan_group_get_device(adapter->vlgrp, vid); if (!dev) continue; diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c index 198ce92af0c..b1de73b1bf1 100644 --- a/drivers/net/vmxnet3/vmxnet3_drv.c +++ b/drivers/net/vmxnet3/vmxnet3_drv.c @@ -1634,7 +1634,7 @@ vmxnet3_restore_vlan(struct vmxnet3_adapter *adapter) u32 *vfTable = adapter->shared->devRead.rxFilterConf.vfTable; bool activeVlan = false; - for (vid = 0; vid < VLAN_GROUP_ARRAY_LEN; vid++) { + for (vid = 0; vid < VLAN_N_VID; vid++) { if (vlan_group_get_device(adapter->vlan_grp, vid)) { VMXNET3_SET_VFTABLE_ENTRY(vfTable, vid); activeVlan = true; diff --git a/drivers/net/vxge/vxge-main.c b/drivers/net/vxge/vxge-main.c index 5378b849f54..0bda7fe05d4 100644 --- a/drivers/net/vxge/vxge-main.c +++ b/drivers/net/vxge/vxge-main.c @@ -1862,7 +1862,7 @@ enum vxge_hw_status vxge_restore_vpath_vid_table(struct vxge_vpath *vpath) if (vdev->vlgrp && vpath->is_open) { - for (vid = 0; vid < VLAN_GROUP_ARRAY_LEN; vid++) { + for (vid = 0; vid < VLAN_N_VID; vid++) { if (!vlan_group_get_device(vdev->vlgrp, vid)) continue; /* Add these vlan to the vid table */ diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index c094707fcbf..74d1401a5d5 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -1820,7 +1820,7 @@ static void qeth_l3_add_vlan_mc(struct qeth_card *card) return; vg = card->vlangrp; - for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { + for (i = 0; i < VLAN_N_VID; i++) { struct net_device *netdev = vlan_group_get_device(vg, i); if (netdev == NULL || !(netdev->flags & IFF_UP)) @@ -1883,7 +1883,7 @@ static void qeth_l3_add_vlan_mc6(struct qeth_card *card) return; vg = card->vlangrp; - for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { + for (i = 0; i < VLAN_N_VID; i++) { struct net_device *netdev = vlan_group_get_device(vg, i); if (netdev == NULL || !(netdev->flags & IFF_UP)) @@ -2247,7 +2247,7 @@ static int qeth_l3_verify_vlan_dev(struct net_device *dev, if (!vg) return rc; - for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { + for (i = 0; i < VLAN_N_VID; i++) { if (vlan_group_get_device(vg, i) == dev) { rc = QETH_VLAN_CARD; break; diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h index a52320751bf..494cce86656 100644 --- a/include/linux/if_vlan.h +++ b/include/linux/if_vlan.h @@ -68,6 +68,7 @@ static inline struct vlan_ethhdr *vlan_eth_hdr(const struct sk_buff *skb) #define VLAN_CFI_MASK 0x1000 /* Canonical Format Indicator */ #define VLAN_TAG_PRESENT VLAN_CFI_MASK #define VLAN_VID_MASK 0x0fff /* VLAN Identifier */ +#define VLAN_N_VID 4096 /* found in socket.c */ extern void vlan_ioctl_set(int (*hook)(struct net *, void __user *)); @@ -76,9 +77,8 @@ extern void vlan_ioctl_set(int (*hook)(struct net *, void __user *)); * depends on completely exhausting the VLAN identifier space. Thus * it gives constant time look-up, but in many cases it wastes memory. */ -#define VLAN_GROUP_ARRAY_LEN 4096 #define VLAN_GROUP_ARRAY_SPLIT_PARTS 8 -#define VLAN_GROUP_ARRAY_PART_LEN (VLAN_GROUP_ARRAY_LEN/VLAN_GROUP_ARRAY_SPLIT_PARTS) +#define VLAN_GROUP_ARRAY_PART_LEN (VLAN_N_VID/VLAN_GROUP_ARRAY_SPLIT_PARTS) struct vlan_group { struct net_device *real_dev; /* The ethernet(like) device diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c index 25c21332e9c..54f22d820ef 100644 --- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c @@ -439,7 +439,7 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event, switch (event) { case NETDEV_CHANGE: /* Propagate real device state to vlan devices */ - for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { + for (i = 0; i < VLAN_N_VID; i++) { vlandev = vlan_group_get_device(grp, i); if (!vlandev) continue; @@ -450,7 +450,7 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event, case NETDEV_CHANGEADDR: /* Adjust unicast filters on underlying device */ - for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { + for (i = 0; i < VLAN_N_VID; i++) { vlandev = vlan_group_get_device(grp, i); if (!vlandev) continue; @@ -464,7 +464,7 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event, break; case NETDEV_CHANGEMTU: - for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { + for (i = 0; i < VLAN_N_VID; i++) { vlandev = vlan_group_get_device(grp, i); if (!vlandev) continue; @@ -478,7 +478,7 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event, case NETDEV_FEAT_CHANGE: /* Propagate device features to underlying device */ - for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { + for (i = 0; i < VLAN_N_VID; i++) { vlandev = vlan_group_get_device(grp, i); if (!vlandev) continue; @@ -490,7 +490,7 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event, case NETDEV_DOWN: /* Put all VLANs for this dev in the down state too. */ - for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { + for (i = 0; i < VLAN_N_VID; i++) { vlandev = vlan_group_get_device(grp, i); if (!vlandev) continue; @@ -508,7 +508,7 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event, case NETDEV_UP: /* Put all VLANs for this dev in the up state too. */ - for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { + for (i = 0; i < VLAN_N_VID; i++) { vlandev = vlan_group_get_device(grp, i); if (!vlandev) continue; @@ -532,7 +532,7 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event, /* Delete all VLANs for this dev. */ grp->killall = 1; - for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { + for (i = 0; i < VLAN_N_VID; i++) { vlandev = vlan_group_get_device(grp, i); if (!vlandev) continue; @@ -540,7 +540,7 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event, /* unregistration of last vlan destroys group, abort * afterwards */ if (grp->nr_vlans == 1) - i = VLAN_GROUP_ARRAY_LEN; + i = VLAN_N_VID; unregister_vlan_dev(vlandev, &list); } diff --git a/net/bridge/netfilter/ebt_vlan.c b/net/bridge/netfilter/ebt_vlan.c index cc11d6b8e50..eae67bf0446 100644 --- a/net/bridge/netfilter/ebt_vlan.c +++ b/net/bridge/netfilter/ebt_vlan.c @@ -118,10 +118,10 @@ static int ebt_vlan_mt_check(const struct xt_mtchk_param *par) * 0 - The null VLAN ID. * 1 - The default Port VID (PVID) * 0x0FFF - Reserved for implementation use. - * if_vlan.h: VLAN_GROUP_ARRAY_LEN 4096. */ + * if_vlan.h: VLAN_N_VID 4096. */ if (GET_BITMASK(EBT_VLAN_ID)) { if (!!info->id) { /* if id!=0 => check vid range */ - if (info->id > VLAN_GROUP_ARRAY_LEN) { + if (info->id > VLAN_N_VID) { pr_debug("id %d is out of range (1-4096)\n", info->id); return -EINVAL; -- cgit v1.2.3-70-g09d2