diff options
Diffstat (limited to 'drivers/s390/net')
-rw-r--r-- | drivers/s390/net/ctcm_main.c | 1 | ||||
-rw-r--r-- | drivers/s390/net/netiucv.c | 1 | ||||
-rw-r--r-- | drivers/s390/net/qeth_core.h | 10 | ||||
-rw-r--r-- | drivers/s390/net/qeth_core_main.c | 114 | ||||
-rw-r--r-- | drivers/s390/net/qeth_core_sys.c | 2 | ||||
-rw-r--r-- | drivers/s390/net/qeth_l2_main.c | 47 | ||||
-rw-r--r-- | drivers/s390/net/qeth_l3_main.c | 51 |
7 files changed, 126 insertions, 100 deletions
diff --git a/drivers/s390/net/ctcm_main.c b/drivers/s390/net/ctcm_main.c index 38b5079f159..c5b83874500 100644 --- a/drivers/s390/net/ctcm_main.c +++ b/drivers/s390/net/ctcm_main.c @@ -164,7 +164,6 @@ void ctcm_unpack_skb(struct channel *ch, struct sk_buff *pskb) priv->stats.rx_packets++; priv->stats.rx_bytes += skblen; netif_rx_ni(skb); - dev->last_rx = jiffies; if (len > 0) { skb_pull(pskb, header->length); if (skb_tailroom(pskb) < LL_HEADER_LENGTH) { diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c index bb1183a2ed6..271c4a82e84 100644 --- a/drivers/s390/net/netiucv.c +++ b/drivers/s390/net/netiucv.c @@ -676,7 +676,6 @@ static void netiucv_unpack_skb(struct iucv_connection *conn, * we must use netif_rx_ni() instead of netif_rx() */ netif_rx_ni(skb); - dev->last_rx = jiffies; skb_pull(pskb, header->next); skb_put(pskb, NETIUCV_HDRLEN); } diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h index 447e1d19581..31a2b4e502c 100644 --- a/drivers/s390/net/qeth_core.h +++ b/drivers/s390/net/qeth_core.h @@ -435,6 +435,7 @@ struct qeth_qdio_out_q { * index of buffer to be filled by driver; state EMPTY or PACKING */ int next_buf_to_fill; + int sync_iqdio_error; /* * number of buffers that are currently filled (PRIMED) * -> these buffers are hardware-owned @@ -685,6 +686,14 @@ struct qeth_mc_mac { int is_vmac; }; +struct qeth_skb_data { + __u32 magic; + int count; +}; + +#define QETH_SKB_MAGIC 0x71657468 +#define QETH_SIGA_CC2_RETRIES 3 + struct qeth_card { struct list_head list; enum qeth_card_states state; @@ -834,7 +843,6 @@ int qeth_default_setadapterparms_cb(struct qeth_card *, struct qeth_reply *, int qeth_send_control_data(struct qeth_card *, int, struct qeth_cmd_buffer *, int (*reply_cb)(struct qeth_card *, struct qeth_reply*, unsigned long), void *reply_param); -int qeth_get_cast_type(struct qeth_card *, struct sk_buff *); int qeth_get_priority_queue(struct qeth_card *, struct sk_buff *, int, int); int qeth_get_elements_no(struct qeth_card *, void *, struct sk_buff *, int); int qeth_do_send_packet_fast(struct qeth_card *, struct qeth_qdio_out_q *, diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index d53621c4acb..c4a42d97015 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -927,8 +927,8 @@ out: return; } -static void qeth_clear_output_buffer(struct qeth_qdio_out_q *queue, - struct qeth_qdio_out_buffer *buf) +static void __qeth_clear_output_buffer(struct qeth_qdio_out_q *queue, + struct qeth_qdio_out_buffer *buf, unsigned int qeth_skip_skb) { int i; struct sk_buff *skb; @@ -937,11 +937,13 @@ static void qeth_clear_output_buffer(struct qeth_qdio_out_q *queue, if (buf->buffer->element[0].flags & 0x40) atomic_dec(&queue->set_pci_flags_count); - skb = skb_dequeue(&buf->skb_list); - while (skb) { - atomic_dec(&skb->users); - dev_kfree_skb_any(skb); + if (!qeth_skip_skb) { skb = skb_dequeue(&buf->skb_list); + while (skb) { + atomic_dec(&skb->users); + dev_kfree_skb_any(skb); + skb = skb_dequeue(&buf->skb_list); + } } for (i = 0; i < QETH_MAX_BUFFER_ELEMENTS(queue->card); ++i) { if (buf->buffer->element[i].addr && buf->is_header[i]) @@ -957,6 +959,12 @@ static void qeth_clear_output_buffer(struct qeth_qdio_out_q *queue, atomic_set(&buf->state, QETH_QDIO_BUF_EMPTY); } +static void qeth_clear_output_buffer(struct qeth_qdio_out_q *queue, + struct qeth_qdio_out_buffer *buf) +{ + __qeth_clear_output_buffer(queue, buf, 0); +} + void qeth_clear_qdio_buffers(struct qeth_card *card) { int i, j; @@ -1152,8 +1160,9 @@ static void qeth_core_sl_print(struct seq_file *m, struct service_level *slr) { struct qeth_card *card = container_of(slr, struct qeth_card, qeth_service_level); - seq_printf(m, "qeth: %s firmware level %s\n", CARD_BUS_ID(card), - card->info.mcl_level); + if (card->info.mcl_level[0]) + seq_printf(m, "qeth: %s firmware level %s\n", + CARD_BUS_ID(card), card->info.mcl_level); } static struct qeth_card *qeth_alloc_card(void) @@ -2685,6 +2694,13 @@ static int qeth_handle_send_error(struct qeth_card *card, int sbalf15 = buffer->buffer->element[15].flags & 0xff; QETH_DBF_TEXT(TRACE, 6, "hdsnderr"); + if (card->info.type == QETH_CARD_TYPE_IQD) { + if (sbalf15 == 0) { + qdio_err = 0; + } else { + qdio_err = 1; + } + } qeth_check_qdio_errors(buffer->buffer, qdio_err, "qouterr"); if (!qdio_err) @@ -2817,6 +2833,7 @@ static void qeth_flush_buffers(struct qeth_qdio_out_q *queue, int index, } } + queue->sync_iqdio_error = 0; queue->card->dev->trans_start = jiffies; if (queue->card->options.performance_stats) { queue->card->perf_stats.outbound_do_qdio_cnt++; @@ -2832,6 +2849,10 @@ static void qeth_flush_buffers(struct qeth_qdio_out_q *queue, int index, queue->card->perf_stats.outbound_do_qdio_time += qeth_get_micros() - queue->card->perf_stats.outbound_do_qdio_start_time; + if (rc > 0) { + if (!(rc & QDIO_ERROR_SIGA_BUSY)) + queue->sync_iqdio_error = rc & 3; + } if (rc) { queue->card->stats.tx_errors += count; /* ignore temporary SIGA errors without busy condition */ @@ -2899,6 +2920,7 @@ void qeth_qdio_output_handler(struct ccw_device *ccwdev, struct qeth_qdio_out_q *queue = card->qdio.out_qs[__queue]; struct qeth_qdio_out_buffer *buffer; int i; + unsigned qeth_send_err; QETH_DBF_TEXT(TRACE, 6, "qdouhdl"); if (qdio_error & QDIO_ERROR_ACTIVATE_CHECK_CONDITION) { @@ -2915,8 +2937,9 @@ void qeth_qdio_output_handler(struct ccw_device *ccwdev, } for (i = first_element; i < (first_element + count); ++i) { buffer = &queue->bufs[i % QDIO_MAX_BUFFERS_PER_Q]; - qeth_handle_send_error(card, buffer, qdio_error); - qeth_clear_output_buffer(queue, buffer); + qeth_send_err = qeth_handle_send_error(card, buffer, qdio_error); + __qeth_clear_output_buffer(queue, buffer, + (qeth_send_err == QETH_SEND_ERROR_RETRY) ? 1 : 0); } atomic_sub(count, &queue->used_buffers); /* check if we need to do something on this outbound queue */ @@ -2930,55 +2953,6 @@ void qeth_qdio_output_handler(struct ccw_device *ccwdev, } EXPORT_SYMBOL_GPL(qeth_qdio_output_handler); -int qeth_get_cast_type(struct qeth_card *card, struct sk_buff *skb) -{ - int cast_type = RTN_UNSPEC; - - if (card->info.type == QETH_CARD_TYPE_OSN) - return cast_type; - - if (skb_dst(skb) && skb_dst(skb)->neighbour) { - cast_type = skb_dst(skb)->neighbour->type; - if ((cast_type == RTN_BROADCAST) || - (cast_type == RTN_MULTICAST) || - (cast_type == RTN_ANYCAST)) - return cast_type; - else - return RTN_UNSPEC; - } - /* try something else */ - if (skb->protocol == ETH_P_IPV6) - return (skb_network_header(skb)[24] == 0xff) ? - RTN_MULTICAST : 0; - else if (skb->protocol == ETH_P_IP) - return ((skb_network_header(skb)[16] & 0xf0) == 0xe0) ? - RTN_MULTICAST : 0; - /* ... */ - if (!memcmp(skb->data, skb->dev->broadcast, 6)) - return RTN_BROADCAST; - else { - u16 hdr_mac; - - hdr_mac = *((u16 *)skb->data); - /* tr multicast? */ - switch (card->info.link_type) { - case QETH_LINK_TYPE_HSTR: - case QETH_LINK_TYPE_LANE_TR: - if ((hdr_mac == QETH_TR_MAC_NC) || - (hdr_mac == QETH_TR_MAC_C)) - return RTN_MULTICAST; - break; - /* eth or so multicast? */ - default: - if ((hdr_mac == QETH_ETH_MAC_V4) || - (hdr_mac == QETH_ETH_MAC_V6)) - return RTN_MULTICAST; - } - } - return cast_type; -} -EXPORT_SYMBOL_GPL(qeth_get_cast_type); - int qeth_get_priority_queue(struct qeth_card *card, struct sk_buff *skb, int ipv, int cast_type) { @@ -3159,7 +3133,10 @@ int qeth_do_send_packet_fast(struct qeth_card *card, int offset, int hd_len) { struct qeth_qdio_out_buffer *buffer; + struct sk_buff *skb1; + struct qeth_skb_data *retry_ctrl; int index; + int rc; /* spin until we get the queue ... */ while (atomic_cmpxchg(&queue->state, QETH_OUT_Q_UNLOCKED, @@ -3178,6 +3155,25 @@ int qeth_do_send_packet_fast(struct qeth_card *card, atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED); qeth_fill_buffer(queue, buffer, skb, hdr, offset, hd_len); qeth_flush_buffers(queue, index, 1); + if (queue->sync_iqdio_error == 2) { + skb1 = skb_dequeue(&buffer->skb_list); + while (skb1) { + atomic_dec(&skb1->users); + skb1 = skb_dequeue(&buffer->skb_list); + } + retry_ctrl = (struct qeth_skb_data *) &skb->cb[16]; + if (retry_ctrl->magic != QETH_SKB_MAGIC) { + retry_ctrl->magic = QETH_SKB_MAGIC; + retry_ctrl->count = 0; + } + if (retry_ctrl->count < QETH_SIGA_CC2_RETRIES) { + retry_ctrl->count++; + rc = dev_queue_xmit(skb); + } else { + dev_kfree_skb_any(skb); + QETH_DBF_TEXT(QERR, 2, "qrdrop"); + } + } return 0; out: atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED); diff --git a/drivers/s390/net/qeth_core_sys.c b/drivers/s390/net/qeth_core_sys.c index 568465d7517..33505c2a0e3 100644 --- a/drivers/s390/net/qeth_core_sys.c +++ b/drivers/s390/net/qeth_core_sys.c @@ -364,7 +364,7 @@ static ssize_t qeth_dev_layer2_show(struct device *dev, if (!card) return -EINVAL; - return sprintf(buf, "%i\n", card->options.layer2 ? 1:0); + return sprintf(buf, "%i\n", card->options.layer2); } static ssize_t qeth_dev_layer2_store(struct device *dev, diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index 2cfc338c462..f4f3ca1393b 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -216,36 +216,16 @@ static void qeth_l2_del_all_mc(struct qeth_card *card) spin_unlock_bh(&card->mclock); } -static void qeth_l2_get_packet_type(struct qeth_card *card, - struct qeth_hdr *hdr, struct sk_buff *skb) +static inline int qeth_l2_get_cast_type(struct qeth_card *card, + struct sk_buff *skb) { - __u16 hdr_mac; - - if (!memcmp(skb->data + QETH_HEADER_SIZE, - skb->dev->broadcast, 6)) { - /* broadcast? */ - hdr->hdr.l2.flags[2] |= QETH_LAYER2_FLAG_BROADCAST; - return; - } - hdr_mac = *((__u16 *)skb->data); - /* tr multicast? */ - switch (card->info.link_type) { - case QETH_LINK_TYPE_HSTR: - case QETH_LINK_TYPE_LANE_TR: - if ((hdr_mac == QETH_TR_MAC_NC) || - (hdr_mac == QETH_TR_MAC_C)) - hdr->hdr.l2.flags[2] |= QETH_LAYER2_FLAG_MULTICAST; - else - hdr->hdr.l2.flags[2] |= QETH_LAYER2_FLAG_UNICAST; - break; - /* eth or so multicast? */ - default: - if ((hdr_mac == QETH_ETH_MAC_V4) || - (hdr_mac == QETH_ETH_MAC_V6)) - hdr->hdr.l2.flags[2] |= QETH_LAYER2_FLAG_MULTICAST; - else - hdr->hdr.l2.flags[2] |= QETH_LAYER2_FLAG_UNICAST; - } + if (card->info.type == QETH_CARD_TYPE_OSN) + return RTN_UNSPEC; + if (is_broadcast_ether_addr(skb->data)) + return RTN_BROADCAST; + if (is_multicast_ether_addr(skb->data)) + return RTN_MULTICAST; + return RTN_UNSPEC; } static void qeth_l2_fill_header(struct qeth_card *card, struct qeth_hdr *hdr, @@ -262,7 +242,7 @@ static void qeth_l2_fill_header(struct qeth_card *card, struct qeth_hdr *hdr, else if (cast_type == RTN_BROADCAST) hdr->hdr.l2.flags[2] |= QETH_LAYER2_FLAG_BROADCAST; else - qeth_l2_get_packet_type(card, hdr, skb); + hdr->hdr.l2.flags[2] |= QETH_LAYER2_FLAG_UNICAST; hdr->hdr.l2.pkt_length = skb->len-QETH_HEADER_SIZE; /* VSWITCH relies on the VLAN @@ -469,7 +449,6 @@ static void qeth_l2_process_inbound_buffer(struct qeth_card *card, QETH_DBF_HEX(CTRL, 3, hdr, QETH_DBF_CTRL_LEN); continue; } - card->dev->last_rx = jiffies; card->stats.rx_packets++; card->stats.rx_bytes += len; } @@ -672,7 +651,7 @@ static int qeth_l2_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) struct qeth_card *card = dev->ml_priv; struct sk_buff *new_skb = skb; int ipv = qeth_get_ip_version(skb); - int cast_type = qeth_get_cast_type(card, skb); + int cast_type = qeth_l2_get_cast_type(card, skb); struct qeth_qdio_out_q *queue = card->qdio.out_qs [qeth_get_priority_queue(card, skb, ipv, cast_type)]; int tx_bytes = skb->len; @@ -883,7 +862,7 @@ static void qeth_l2_remove_device(struct ccwgroup_device *cgdev) return; } -static struct ethtool_ops qeth_l2_ethtool_ops = { +static const struct ethtool_ops qeth_l2_ethtool_ops = { .get_link = ethtool_op_get_link, .get_strings = qeth_core_get_strings, .get_ethtool_stats = qeth_core_get_ethtool_stats, @@ -892,7 +871,7 @@ static struct ethtool_ops qeth_l2_ethtool_ops = { .get_settings = qeth_core_ethtool_get_settings, }; -static struct ethtool_ops qeth_l2_osn_ops = { +static const struct ethtool_ops qeth_l2_osn_ops = { .get_strings = qeth_core_get_strings, .get_ethtool_stats = qeth_core_get_ethtool_stats, .get_stats_count = qeth_core_get_stats_count, diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index 048defaea81..073b6d35491 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -1987,7 +1987,6 @@ static void qeth_l3_process_inbound_buffer(struct qeth_card *card, continue; } - card->dev->last_rx = jiffies; card->stats.rx_packets++; card->stats.rx_bytes += len; } @@ -2525,6 +2524,51 @@ static int qeth_l3_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) return rc; } +int inline qeth_l3_get_cast_type(struct qeth_card *card, struct sk_buff *skb) +{ + int cast_type = RTN_UNSPEC; + + if (skb_dst(skb) && skb_dst(skb)->neighbour) { + cast_type = skb_dst(skb)->neighbour->type; + if ((cast_type == RTN_BROADCAST) || + (cast_type == RTN_MULTICAST) || + (cast_type == RTN_ANYCAST)) + return cast_type; + else + return RTN_UNSPEC; + } + /* try something else */ + if (skb->protocol == ETH_P_IPV6) + return (skb_network_header(skb)[24] == 0xff) ? + RTN_MULTICAST : 0; + else if (skb->protocol == ETH_P_IP) + return ((skb_network_header(skb)[16] & 0xf0) == 0xe0) ? + RTN_MULTICAST : 0; + /* ... */ + if (!memcmp(skb->data, skb->dev->broadcast, 6)) + return RTN_BROADCAST; + else { + u16 hdr_mac; + + hdr_mac = *((u16 *)skb->data); + /* tr multicast? */ + switch (card->info.link_type) { + case QETH_LINK_TYPE_HSTR: + case QETH_LINK_TYPE_LANE_TR: + if ((hdr_mac == QETH_TR_MAC_NC) || + (hdr_mac == QETH_TR_MAC_C)) + return RTN_MULTICAST; + break; + /* eth or so multicast? */ + default: + if ((hdr_mac == QETH_ETH_MAC_V4) || + (hdr_mac == QETH_ETH_MAC_V6)) + return RTN_MULTICAST; + } + } + return cast_type; +} + static void qeth_l3_fill_header(struct qeth_card *card, struct qeth_hdr *hdr, struct sk_buff *skb, int ipv, int cast_type) { @@ -2650,7 +2694,7 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) struct qeth_card *card = dev->ml_priv; struct sk_buff *new_skb = NULL; int ipv = qeth_get_ip_version(skb); - int cast_type = qeth_get_cast_type(card, skb); + int cast_type = qeth_l3_get_cast_type(card, skb); struct qeth_qdio_out_q *queue = card->qdio.out_qs [qeth_get_priority_queue(card, skb, ipv, cast_type)]; int tx_bytes = skb->len; @@ -2901,7 +2945,7 @@ static int qeth_l3_ethtool_set_tso(struct net_device *dev, u32 data) return 0; } -static struct ethtool_ops qeth_l3_ethtool_ops = { +static const struct ethtool_ops qeth_l3_ethtool_ops = { .get_link = ethtool_op_get_link, .get_tx_csum = ethtool_op_get_tx_csum, .set_tx_csum = ethtool_op_set_tx_hw_csum, @@ -3180,6 +3224,7 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode) netif_carrier_on(card->dev); qeth_set_allowed_threads(card, 0xffffffff, 0); + qeth_l3_set_ip_addr_list(card); if (recover_flag == CARD_STATE_RECOVER) { if (recovery_mode) qeth_l3_open(card->dev); |