Commit c2335d67 authored by David S. Miller's avatar David S. Miller

Merge branch 's390-next'

Julian Wiedmann says:

====================
s390/net: updates 2018-04-26

please apply the following patches to net-next. There's the usual
cleanups & small improvements, and Kittipon adds HW offload support
for IPv6 checksumming.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents d8fb1648 21b1702a
...@@ -1928,6 +1928,8 @@ lcs_portno_store (struct device *dev, struct device_attribute *attr, const char ...@@ -1928,6 +1928,8 @@ lcs_portno_store (struct device *dev, struct device_attribute *attr, const char
return -EINVAL; return -EINVAL;
/* TODO: sanity checks */ /* TODO: sanity checks */
card->portno = value; card->portno = value;
if (card->dev)
card->dev->dev_port = card->portno;
return count; return count;
...@@ -2158,6 +2160,7 @@ lcs_new_device(struct ccwgroup_device *ccwgdev) ...@@ -2158,6 +2160,7 @@ lcs_new_device(struct ccwgroup_device *ccwgdev)
card->dev = dev; card->dev = dev;
card->dev->ml_priv = card; card->dev->ml_priv = card;
card->dev->netdev_ops = &lcs_netdev_ops; card->dev->netdev_ops = &lcs_netdev_ops;
card->dev->dev_port = card->portno;
memcpy(card->dev->dev_addr, card->mac, LCS_MAC_LENGTH); memcpy(card->dev->dev_addr, card->mac, LCS_MAC_LENGTH);
#ifdef CONFIG_IP_MULTICAST #ifdef CONFIG_IP_MULTICAST
if (!lcs_check_multicast_support(card)) if (!lcs_check_multicast_support(card))
......
...@@ -148,6 +148,7 @@ struct qeth_perf_stats { ...@@ -148,6 +148,7 @@ struct qeth_perf_stats {
unsigned int tx_csum; unsigned int tx_csum;
unsigned int tx_lin; unsigned int tx_lin;
unsigned int tx_linfail; unsigned int tx_linfail;
unsigned int rx_csum;
}; };
/* Routing stuff */ /* Routing stuff */
...@@ -712,9 +713,6 @@ enum qeth_discipline_id { ...@@ -712,9 +713,6 @@ enum qeth_discipline_id {
struct qeth_discipline { struct qeth_discipline {
const struct device_type *devtype; const struct device_type *devtype;
void (*start_poll)(struct ccw_device *, int, unsigned long);
qdio_handler_t *input_handler;
qdio_handler_t *output_handler;
int (*process_rx_buffer)(struct qeth_card *card, int budget, int *done); int (*process_rx_buffer)(struct qeth_card *card, int budget, int *done);
int (*recover)(void *ptr); int (*recover)(void *ptr);
int (*setup) (struct ccwgroup_device *); int (*setup) (struct ccwgroup_device *);
...@@ -780,9 +778,9 @@ struct qeth_card { ...@@ -780,9 +778,9 @@ struct qeth_card {
struct qeth_card_options options; struct qeth_card_options options;
wait_queue_head_t wait_q; wait_queue_head_t wait_q;
spinlock_t vlanlock;
spinlock_t mclock; spinlock_t mclock;
unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)]; unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
struct mutex vid_list_mutex; /* vid_list */
struct list_head vid_list; struct list_head vid_list;
DECLARE_HASHTABLE(mac_htable, 4); DECLARE_HASHTABLE(mac_htable, 4);
DECLARE_HASHTABLE(ip_htable, 4); DECLARE_HASHTABLE(ip_htable, 4);
...@@ -867,6 +865,32 @@ static inline int qeth_get_ip_version(struct sk_buff *skb) ...@@ -867,6 +865,32 @@ static inline int qeth_get_ip_version(struct sk_buff *skb)
} }
} }
static inline void qeth_rx_csum(struct qeth_card *card, struct sk_buff *skb,
u8 flags)
{
if ((card->dev->features & NETIF_F_RXCSUM) &&
(flags & QETH_HDR_EXT_CSUM_TRANSP_REQ)) {
skb->ip_summed = CHECKSUM_UNNECESSARY;
if (card->options.performance_stats)
card->perf_stats.rx_csum++;
} else {
skb->ip_summed = CHECKSUM_NONE;
}
}
static inline void qeth_tx_csum(struct sk_buff *skb, u8 *flags, int ipv)
{
*flags |= QETH_HDR_EXT_CSUM_TRANSP_REQ;
if ((ipv == 4 && ip_hdr(skb)->protocol == IPPROTO_UDP) ||
(ipv == 6 && ipv6_hdr(skb)->nexthdr == IPPROTO_UDP))
*flags |= QETH_HDR_EXT_UDP;
if (ipv == 4) {
/* some HW requires combined L3+L4 csum offload: */
*flags |= QETH_HDR_EXT_CSUM_HDR_REQ;
ip_hdr(skb)->check = 0;
}
}
static inline void qeth_put_buffer_pool_entry(struct qeth_card *card, static inline void qeth_put_buffer_pool_entry(struct qeth_card *card,
struct qeth_buffer_pool_entry *entry) struct qeth_buffer_pool_entry *entry)
{ {
...@@ -879,6 +903,27 @@ static inline int qeth_is_diagass_supported(struct qeth_card *card, ...@@ -879,6 +903,27 @@ static inline int qeth_is_diagass_supported(struct qeth_card *card,
return card->info.diagass_support & (__u32)cmd; return card->info.diagass_support & (__u32)cmd;
} }
int qeth_send_simple_setassparms_prot(struct qeth_card *card,
enum qeth_ipa_funcs ipa_func,
u16 cmd_code, long data,
enum qeth_prot_versions prot);
/* IPv4 variant */
static inline int qeth_send_simple_setassparms(struct qeth_card *card,
enum qeth_ipa_funcs ipa_func,
u16 cmd_code, long data)
{
return qeth_send_simple_setassparms_prot(card, ipa_func, cmd_code,
data, QETH_PROT_IPV4);
}
static inline int qeth_send_simple_setassparms_v6(struct qeth_card *card,
enum qeth_ipa_funcs ipa_func,
u16 cmd_code, long data)
{
return qeth_send_simple_setassparms_prot(card, ipa_func, cmd_code,
data, QETH_PROT_IPV6);
}
extern struct qeth_discipline qeth_l2_discipline; extern struct qeth_discipline qeth_l2_discipline;
extern struct qeth_discipline qeth_l3_discipline; extern struct qeth_discipline qeth_l3_discipline;
extern const struct attribute_group *qeth_generic_attr_groups[]; extern const struct attribute_group *qeth_generic_attr_groups[];
...@@ -921,13 +966,7 @@ struct sk_buff *qeth_core_get_next_skb(struct qeth_card *, ...@@ -921,13 +966,7 @@ struct sk_buff *qeth_core_get_next_skb(struct qeth_card *,
struct qeth_qdio_buffer *, struct qdio_buffer_element **, int *, struct qeth_qdio_buffer *, struct qdio_buffer_element **, int *,
struct qeth_hdr **); struct qeth_hdr **);
void qeth_schedule_recovery(struct qeth_card *); void qeth_schedule_recovery(struct qeth_card *);
void qeth_qdio_start_poll(struct ccw_device *, int, unsigned long);
int qeth_poll(struct napi_struct *napi, int budget); int qeth_poll(struct napi_struct *napi, int budget);
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 *); void qeth_clear_ipacmd_list(struct qeth_card *);
int qeth_qdio_clear_card(struct qeth_card *, int); int qeth_qdio_clear_card(struct qeth_card *, int);
void qeth_clear_working_pool_list(struct qeth_card *); void qeth_clear_working_pool_list(struct qeth_card *);
...@@ -979,8 +1018,6 @@ int qeth_hw_trap(struct qeth_card *, enum qeth_diags_trap_action); ...@@ -979,8 +1018,6 @@ int qeth_hw_trap(struct qeth_card *, enum qeth_diags_trap_action);
int qeth_query_ipassists(struct qeth_card *, enum qeth_prot_versions prot); int qeth_query_ipassists(struct qeth_card *, enum qeth_prot_versions prot);
void qeth_trace_features(struct qeth_card *); void qeth_trace_features(struct qeth_card *);
void qeth_close_dev(struct qeth_card *); void qeth_close_dev(struct qeth_card *);
int qeth_send_simple_setassparms(struct qeth_card *, enum qeth_ipa_funcs,
__u16, long);
int qeth_send_setassparms(struct qeth_card *, struct qeth_cmd_buffer *, __u16, int qeth_send_setassparms(struct qeth_card *, struct qeth_cmd_buffer *, __u16,
long, long,
int (*reply_cb)(struct qeth_card *, int (*reply_cb)(struct qeth_card *,
......
This diff is collapsed.
...@@ -246,6 +246,8 @@ enum qeth_ipa_funcs { ...@@ -246,6 +246,8 @@ enum qeth_ipa_funcs {
IPA_QUERY_ARP_ASSIST = 0x00040000L, IPA_QUERY_ARP_ASSIST = 0x00040000L,
IPA_INBOUND_TSO = 0x00080000L, IPA_INBOUND_TSO = 0x00080000L,
IPA_OUTBOUND_TSO = 0x00100000L, IPA_OUTBOUND_TSO = 0x00100000L,
IPA_INBOUND_CHECKSUM_V6 = 0x00400000L,
IPA_OUTBOUND_CHECKSUM_V6 = 0x00800000L,
}; };
/* SETIP/DELIP IPA Command: ***************************************************/ /* SETIP/DELIP IPA Command: ***************************************************/
......
...@@ -144,6 +144,8 @@ static ssize_t qeth_dev_portno_store(struct device *dev, ...@@ -144,6 +144,8 @@ static ssize_t qeth_dev_portno_store(struct device *dev,
goto out; goto out;
} }
card->info.portno = portno; card->info.portno = portno;
if (card->dev)
card->dev->dev_port = portno;
out: out:
mutex_unlock(&card->conf_mutex); mutex_unlock(&card->conf_mutex);
return rc ? rc : count; return rc ? rc : count;
......
...@@ -17,7 +17,6 @@ ...@@ -17,7 +17,6 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/etherdevice.h> #include <linux/etherdevice.h>
#include <linux/ip.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/hash.h> #include <linux/hash.h>
#include <linux/hashtable.h> #include <linux/hashtable.h>
...@@ -195,23 +194,6 @@ static int qeth_l2_get_cast_type(struct qeth_card *card, struct sk_buff *skb) ...@@ -195,23 +194,6 @@ static int qeth_l2_get_cast_type(struct qeth_card *card, struct sk_buff *skb)
return RTN_UNSPEC; return RTN_UNSPEC;
} }
static void qeth_l2_hdr_csum(struct qeth_card *card, struct qeth_hdr *hdr,
struct sk_buff *skb)
{
struct iphdr *iph = ip_hdr(skb);
/* tcph->check contains already the pseudo hdr checksum
* so just set the header flags
*/
if (iph->protocol == IPPROTO_UDP)
hdr->hdr.l2.flags[1] |= QETH_HDR_EXT_UDP;
hdr->hdr.l2.flags[1] |= QETH_HDR_EXT_CSUM_TRANSP_REQ |
QETH_HDR_EXT_CSUM_HDR_REQ;
iph->check = 0;
if (card->options.performance_stats)
card->perf_stats.tx_csum++;
}
static void qeth_l2_fill_header(struct qeth_hdr *hdr, struct sk_buff *skb, static void qeth_l2_fill_header(struct qeth_hdr *hdr, struct sk_buff *skb,
int cast_type, unsigned int data_len) int cast_type, unsigned int data_len)
{ {
...@@ -297,12 +279,13 @@ static int qeth_l2_send_setdelvlan(struct qeth_card *card, __u16 i, ...@@ -297,12 +279,13 @@ static int qeth_l2_send_setdelvlan(struct qeth_card *card, __u16 i,
static void qeth_l2_process_vlans(struct qeth_card *card) static void qeth_l2_process_vlans(struct qeth_card *card)
{ {
struct qeth_vlan_vid *id; struct qeth_vlan_vid *id;
QETH_CARD_TEXT(card, 3, "L2prcvln"); QETH_CARD_TEXT(card, 3, "L2prcvln");
spin_lock_bh(&card->vlanlock); mutex_lock(&card->vid_list_mutex);
list_for_each_entry(id, &card->vid_list, list) { list_for_each_entry(id, &card->vid_list, list) {
qeth_l2_send_setdelvlan(card, id->vid, IPA_CMD_SETVLAN); qeth_l2_send_setdelvlan(card, id->vid, IPA_CMD_SETVLAN);
} }
spin_unlock_bh(&card->vlanlock); mutex_unlock(&card->vid_list_mutex);
} }
static int qeth_l2_vlan_rx_add_vid(struct net_device *dev, static int qeth_l2_vlan_rx_add_vid(struct net_device *dev,
...@@ -319,7 +302,7 @@ static int qeth_l2_vlan_rx_add_vid(struct net_device *dev, ...@@ -319,7 +302,7 @@ static int qeth_l2_vlan_rx_add_vid(struct net_device *dev,
QETH_CARD_TEXT(card, 3, "aidREC"); QETH_CARD_TEXT(card, 3, "aidREC");
return 0; return 0;
} }
id = kmalloc(sizeof(struct qeth_vlan_vid), GFP_ATOMIC); id = kmalloc(sizeof(*id), GFP_KERNEL);
if (id) { if (id) {
id->vid = vid; id->vid = vid;
rc = qeth_l2_send_setdelvlan(card, vid, IPA_CMD_SETVLAN); rc = qeth_l2_send_setdelvlan(card, vid, IPA_CMD_SETVLAN);
...@@ -327,9 +310,9 @@ static int qeth_l2_vlan_rx_add_vid(struct net_device *dev, ...@@ -327,9 +310,9 @@ static int qeth_l2_vlan_rx_add_vid(struct net_device *dev,
kfree(id); kfree(id);
return rc; return rc;
} }
spin_lock_bh(&card->vlanlock); mutex_lock(&card->vid_list_mutex);
list_add_tail(&id->list, &card->vid_list); list_add_tail(&id->list, &card->vid_list);
spin_unlock_bh(&card->vlanlock); mutex_unlock(&card->vid_list_mutex);
} else { } else {
return -ENOMEM; return -ENOMEM;
} }
...@@ -348,7 +331,7 @@ static int qeth_l2_vlan_rx_kill_vid(struct net_device *dev, ...@@ -348,7 +331,7 @@ static int qeth_l2_vlan_rx_kill_vid(struct net_device *dev,
QETH_CARD_TEXT(card, 3, "kidREC"); QETH_CARD_TEXT(card, 3, "kidREC");
return 0; return 0;
} }
spin_lock_bh(&card->vlanlock); mutex_lock(&card->vid_list_mutex);
list_for_each_entry(id, &card->vid_list, list) { list_for_each_entry(id, &card->vid_list, list) {
if (id->vid == vid) { if (id->vid == vid) {
list_del(&id->list); list_del(&id->list);
...@@ -356,7 +339,7 @@ static int qeth_l2_vlan_rx_kill_vid(struct net_device *dev, ...@@ -356,7 +339,7 @@ static int qeth_l2_vlan_rx_kill_vid(struct net_device *dev,
break; break;
} }
} }
spin_unlock_bh(&card->vlanlock); mutex_unlock(&card->vid_list_mutex);
if (tmpid) { if (tmpid) {
rc = qeth_l2_send_setdelvlan(card, vid, IPA_CMD_DELVLAN); rc = qeth_l2_send_setdelvlan(card, vid, IPA_CMD_DELVLAN);
kfree(tmpid); kfree(tmpid);
...@@ -423,15 +406,7 @@ static int qeth_l2_process_inbound_buffer(struct qeth_card *card, ...@@ -423,15 +406,7 @@ static int qeth_l2_process_inbound_buffer(struct qeth_card *card,
switch (hdr->hdr.l2.id) { switch (hdr->hdr.l2.id) {
case QETH_HEADER_TYPE_LAYER2: case QETH_HEADER_TYPE_LAYER2:
skb->protocol = eth_type_trans(skb, skb->dev); skb->protocol = eth_type_trans(skb, skb->dev);
if ((card->dev->features & NETIF_F_RXCSUM) qeth_rx_csum(card, skb, hdr->hdr.l2.flags[1]);
&& ((hdr->hdr.l2.flags[1] &
(QETH_HDR_EXT_CSUM_HDR_REQ |
QETH_HDR_EXT_CSUM_TRANSP_REQ)) ==
(QETH_HDR_EXT_CSUM_HDR_REQ |
QETH_HDR_EXT_CSUM_TRANSP_REQ)))
skb->ip_summed = CHECKSUM_UNNECESSARY;
else
skb->ip_summed = CHECKSUM_NONE;
if (skb->protocol == htons(ETH_P_802_2)) if (skb->protocol == htons(ETH_P_802_2))
*((__u32 *)skb->cb) = ++card->seqno.pkt_seqno; *((__u32 *)skb->cb) = ++card->seqno.pkt_seqno;
len = skb->len; len = skb->len;
...@@ -464,7 +439,6 @@ static int qeth_l2_process_inbound_buffer(struct qeth_card *card, ...@@ -464,7 +439,6 @@ static int qeth_l2_process_inbound_buffer(struct qeth_card *card,
static int qeth_l2_request_initial_mac(struct qeth_card *card) static int qeth_l2_request_initial_mac(struct qeth_card *card)
{ {
int rc = 0; int rc = 0;
char vendor_pre[] = {0x02, 0x00, 0x00};
QETH_DBF_TEXT(SETUP, 2, "l2reqmac"); QETH_DBF_TEXT(SETUP, 2, "l2reqmac");
QETH_DBF_TEXT_(SETUP, 2, "doL2%s", CARD_BUS_ID(card)); QETH_DBF_TEXT_(SETUP, 2, "doL2%s", CARD_BUS_ID(card));
...@@ -484,16 +458,20 @@ static int qeth_l2_request_initial_mac(struct qeth_card *card) ...@@ -484,16 +458,20 @@ static int qeth_l2_request_initial_mac(struct qeth_card *card)
card->info.type == QETH_CARD_TYPE_OSX || card->info.type == QETH_CARD_TYPE_OSX ||
card->info.guestlan) { card->info.guestlan) {
rc = qeth_setadpparms_change_macaddr(card); rc = qeth_setadpparms_change_macaddr(card);
if (rc) { if (!rc)
QETH_DBF_MESSAGE(2, "couldn't get MAC address on " goto out;
"device %s: x%x\n", CARD_BUS_ID(card), rc); QETH_DBF_MESSAGE(2, "READ_MAC Assist failed on device %s: x%x\n",
QETH_DBF_TEXT_(SETUP, 2, "1err%04x", rc); CARD_BUS_ID(card), rc);
return rc; QETH_DBF_TEXT_(SETUP, 2, "1err%04x", rc);
} /* fall back once more: */
} else {
eth_random_addr(card->dev->dev_addr);
memcpy(card->dev->dev_addr, vendor_pre, 3);
} }
/* some devices don't support a custom MAC address: */
if (card->info.type == QETH_CARD_TYPE_OSM ||
card->info.type == QETH_CARD_TYPE_OSX)
return (rc) ? rc : -EADDRNOTAVAIL;
eth_hw_addr_random(card->dev);
out: out:
QETH_DBF_HEX(SETUP, 2, card->dev->dev_addr, card->dev->addr_len); QETH_DBF_HEX(SETUP, 2, card->dev->dev_addr, card->dev->addr_len);
return 0; return 0;
...@@ -685,7 +663,8 @@ static int qeth_l2_xmit_iqd(struct qeth_card *card, struct sk_buff *skb, ...@@ -685,7 +663,8 @@ static int qeth_l2_xmit_iqd(struct qeth_card *card, struct sk_buff *skb,
} }
static int qeth_l2_xmit_osa(struct qeth_card *card, struct sk_buff *skb, static int qeth_l2_xmit_osa(struct qeth_card *card, struct sk_buff *skb,
struct qeth_qdio_out_q *queue, int cast_type) struct qeth_qdio_out_q *queue, int cast_type,
int ipv)
{ {
int push_len = sizeof(struct qeth_hdr); int push_len = sizeof(struct qeth_hdr);
unsigned int elements, nr_frags; unsigned int elements, nr_frags;
...@@ -723,8 +702,11 @@ static int qeth_l2_xmit_osa(struct qeth_card *card, struct sk_buff *skb, ...@@ -723,8 +702,11 @@ static int qeth_l2_xmit_osa(struct qeth_card *card, struct sk_buff *skb,
hdr_elements = 1; hdr_elements = 1;
} }
qeth_l2_fill_header(hdr, skb, cast_type, skb->len - push_len); qeth_l2_fill_header(hdr, skb, cast_type, skb->len - push_len);
if (skb->ip_summed == CHECKSUM_PARTIAL) if (skb->ip_summed == CHECKSUM_PARTIAL) {
qeth_l2_hdr_csum(card, hdr, skb); qeth_tx_csum(skb, &hdr->hdr.l2.flags[1], ipv);
if (card->options.performance_stats)
card->perf_stats.tx_csum++;
}
elements = qeth_get_elements_no(card, skb, hdr_elements, 0); elements = qeth_get_elements_no(card, skb, hdr_elements, 0);
if (!elements) { if (!elements) {
...@@ -776,6 +758,7 @@ static netdev_tx_t qeth_l2_hard_start_xmit(struct sk_buff *skb, ...@@ -776,6 +758,7 @@ static netdev_tx_t qeth_l2_hard_start_xmit(struct sk_buff *skb,
{ {
struct qeth_card *card = dev->ml_priv; struct qeth_card *card = dev->ml_priv;
int cast_type = qeth_l2_get_cast_type(card, skb); int cast_type = qeth_l2_get_cast_type(card, skb);
int ipv = qeth_get_ip_version(skb);
struct qeth_qdio_out_q *queue; struct qeth_qdio_out_q *queue;
int tx_bytes = skb->len; int tx_bytes = skb->len;
int rc; int rc;
...@@ -783,7 +766,7 @@ static netdev_tx_t qeth_l2_hard_start_xmit(struct sk_buff *skb, ...@@ -783,7 +766,7 @@ static netdev_tx_t qeth_l2_hard_start_xmit(struct sk_buff *skb,
if (card->qdio.do_prio_queueing || (cast_type && if (card->qdio.do_prio_queueing || (cast_type &&
card->info.is_multicast_different)) card->info.is_multicast_different))
queue = card->qdio.out_qs[qeth_get_priority_queue(card, skb, queue = card->qdio.out_qs[qeth_get_priority_queue(card, skb,
qeth_get_ip_version(skb), cast_type)]; ipv, cast_type)];
else else
queue = card->qdio.out_qs[card->qdio.default_out_queue]; queue = card->qdio.out_qs[card->qdio.default_out_queue];
...@@ -806,7 +789,7 @@ static netdev_tx_t qeth_l2_hard_start_xmit(struct sk_buff *skb, ...@@ -806,7 +789,7 @@ static netdev_tx_t qeth_l2_hard_start_xmit(struct sk_buff *skb,
rc = qeth_l2_xmit_iqd(card, skb, queue, cast_type); rc = qeth_l2_xmit_iqd(card, skb, queue, cast_type);
break; break;
default: default:
rc = qeth_l2_xmit_osa(card, skb, queue, cast_type); rc = qeth_l2_xmit_osa(card, skb, queue, cast_type, ipv);
} }
if (!rc) { if (!rc) {
...@@ -983,6 +966,7 @@ static int qeth_l2_setup_netdev(struct qeth_card *card) ...@@ -983,6 +966,7 @@ static int qeth_l2_setup_netdev(struct qeth_card *card)
card->dev->mtu = card->info.initial_mtu; card->dev->mtu = card->info.initial_mtu;
card->dev->min_mtu = 64; card->dev->min_mtu = 64;
card->dev->max_mtu = ETH_MAX_MTU; card->dev->max_mtu = ETH_MAX_MTU;
card->dev->dev_port = card->info.portno;
card->dev->netdev_ops = &qeth_l2_netdev_ops; card->dev->netdev_ops = &qeth_l2_netdev_ops;
if (card->info.type == QETH_CARD_TYPE_OSN) { if (card->info.type == QETH_CARD_TYPE_OSN) {
card->dev->ethtool_ops = &qeth_l2_osn_ops; card->dev->ethtool_ops = &qeth_l2_osn_ops;
...@@ -1011,10 +995,15 @@ static int qeth_l2_setup_netdev(struct qeth_card *card) ...@@ -1011,10 +995,15 @@ static int qeth_l2_setup_netdev(struct qeth_card *card)
card->dev->hw_features |= NETIF_F_IP_CSUM; card->dev->hw_features |= NETIF_F_IP_CSUM;
card->dev->vlan_features |= NETIF_F_IP_CSUM; card->dev->vlan_features |= NETIF_F_IP_CSUM;
} }
if (qeth_is_supported(card, IPA_INBOUND_CHECKSUM)) { }
card->dev->hw_features |= NETIF_F_RXCSUM; if (qeth_is_supported6(card, IPA_OUTBOUND_CHECKSUM_V6)) {
card->dev->vlan_features |= NETIF_F_RXCSUM; card->dev->hw_features |= NETIF_F_IPV6_CSUM;
} card->dev->vlan_features |= NETIF_F_IPV6_CSUM;
}
if (qeth_is_supported(card, IPA_INBOUND_CHECKSUM) ||
qeth_is_supported6(card, IPA_INBOUND_CHECKSUM_V6)) {
card->dev->hw_features |= NETIF_F_RXCSUM;
card->dev->vlan_features |= NETIF_F_RXCSUM;
} }
card->info.broadcast_capable = 1; card->info.broadcast_capable = 1;
...@@ -1315,9 +1304,6 @@ static int qeth_l2_control_event(struct qeth_card *card, ...@@ -1315,9 +1304,6 @@ static int qeth_l2_control_event(struct qeth_card *card,
struct qeth_discipline qeth_l2_discipline = { struct qeth_discipline qeth_l2_discipline = {
.devtype = &qeth_l2_devtype, .devtype = &qeth_l2_devtype,
.start_poll = qeth_qdio_start_poll,
.input_handler = (qdio_handler_t *) qeth_qdio_input_handler,
.output_handler = (qdio_handler_t *) qeth_qdio_output_handler,
.process_rx_buffer = qeth_l2_process_inbound_buffer, .process_rx_buffer = qeth_l2_process_inbound_buffer,
.recover = qeth_l2_recover, .recover = qeth_l2_recover,
.setup = qeth_l2_probe_device, .setup = qeth_l2_probe_device,
......
...@@ -735,22 +735,6 @@ static int qeth_l3_setadapter_parms(struct qeth_card *card) ...@@ -735,22 +735,6 @@ static int qeth_l3_setadapter_parms(struct qeth_card *card)
return rc; return rc;
} }
static int qeth_l3_send_simple_setassparms_ipv6(struct qeth_card *card,
enum qeth_ipa_funcs ipa_func, __u16 cmd_code)
{
int rc;
struct qeth_cmd_buffer *iob;
QETH_CARD_TEXT(card, 4, "simassp6");
iob = qeth_get_setassparms_cmd(card, ipa_func, cmd_code,
0, QETH_PROT_IPV6);
if (!iob)
return -ENOMEM;
rc = qeth_send_setassparms(card, iob, 0, 0,
qeth_setassparms_cb, NULL);
return rc;
}
static int qeth_l3_start_ipa_arp_processing(struct qeth_card *card) static int qeth_l3_start_ipa_arp_processing(struct qeth_card *card)
{ {
int rc; int rc;
...@@ -851,14 +835,6 @@ static int qeth_l3_softsetup_ipv6(struct qeth_card *card) ...@@ -851,14 +835,6 @@ static int qeth_l3_softsetup_ipv6(struct qeth_card *card)
QETH_CARD_TEXT(card, 3, "softipv6"); QETH_CARD_TEXT(card, 3, "softipv6");
rc = qeth_query_ipassists(card, QETH_PROT_IPV6);
if (rc) {
dev_err(&card->gdev->dev,
"Activating IPv6 support for %s failed\n",
QETH_CARD_IFNAME(card));
return rc;
}
if (card->info.type == QETH_CARD_TYPE_IQD) if (card->info.type == QETH_CARD_TYPE_IQD)
goto out; goto out;
...@@ -870,16 +846,16 @@ static int qeth_l3_softsetup_ipv6(struct qeth_card *card) ...@@ -870,16 +846,16 @@ static int qeth_l3_softsetup_ipv6(struct qeth_card *card)
QETH_CARD_IFNAME(card)); QETH_CARD_IFNAME(card));
return rc; return rc;
} }
rc = qeth_l3_send_simple_setassparms_ipv6(card, IPA_IPV6, rc = qeth_send_simple_setassparms_v6(card, IPA_IPV6,
IPA_CMD_ASS_START); IPA_CMD_ASS_START, 0);
if (rc) { if (rc) {
dev_err(&card->gdev->dev, dev_err(&card->gdev->dev,
"Activating IPv6 support for %s failed\n", "Activating IPv6 support for %s failed\n",
QETH_CARD_IFNAME(card)); QETH_CARD_IFNAME(card));
return rc; return rc;
} }
rc = qeth_l3_send_simple_setassparms_ipv6(card, IPA_PASSTHRU, rc = qeth_send_simple_setassparms_v6(card, IPA_PASSTHRU,
IPA_CMD_ASS_START); IPA_CMD_ASS_START, 0);
if (rc) { if (rc) {
dev_warn(&card->gdev->dev, dev_warn(&card->gdev->dev,
"Enabling the passthrough mode for %s failed\n", "Enabling the passthrough mode for %s failed\n",
...@@ -1293,91 +1269,6 @@ static void qeth_l3_add_multicast_ipv6(struct qeth_card *card) ...@@ -1293,91 +1269,6 @@ static void qeth_l3_add_multicast_ipv6(struct qeth_card *card)
in6_dev_put(in6_dev); in6_dev_put(in6_dev);
} }
static void qeth_l3_free_vlan_addresses4(struct qeth_card *card,
unsigned short vid)
{
struct in_device *in_dev;
struct in_ifaddr *ifa;
struct qeth_ipaddr *addr;
struct net_device *netdev;
QETH_CARD_TEXT(card, 4, "frvaddr4");
netdev = __vlan_find_dev_deep_rcu(card->dev, htons(ETH_P_8021Q), vid);
if (!netdev)
return;
in_dev = in_dev_get(netdev);
if (!in_dev)
return;
addr = qeth_l3_get_addr_buffer(QETH_PROT_IPV4);
if (!addr)
goto out;
spin_lock_bh(&card->ip_lock);
for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next) {
addr->u.a4.addr = be32_to_cpu(ifa->ifa_address);
addr->u.a4.mask = be32_to_cpu(ifa->ifa_mask);
addr->type = QETH_IP_TYPE_NORMAL;
qeth_l3_delete_ip(card, addr);
}
spin_unlock_bh(&card->ip_lock);
kfree(addr);
out:
in_dev_put(in_dev);
}
static void qeth_l3_free_vlan_addresses6(struct qeth_card *card,
unsigned short vid)
{
struct inet6_dev *in6_dev;
struct inet6_ifaddr *ifa;
struct qeth_ipaddr *addr;
struct net_device *netdev;
QETH_CARD_TEXT(card, 4, "frvaddr6");
netdev = __vlan_find_dev_deep_rcu(card->dev, htons(ETH_P_8021Q), vid);
if (!netdev)
return;
in6_dev = in6_dev_get(netdev);
if (!in6_dev)
return;
addr = qeth_l3_get_addr_buffer(QETH_PROT_IPV6);
if (!addr)
goto out;
spin_lock_bh(&card->ip_lock);
list_for_each_entry(ifa, &in6_dev->addr_list, if_list) {
memcpy(&addr->u.a6.addr, &ifa->addr,
sizeof(struct in6_addr));
addr->u.a6.pfxlen = ifa->prefix_len;
addr->type = QETH_IP_TYPE_NORMAL;
qeth_l3_delete_ip(card, addr);
}
spin_unlock_bh(&card->ip_lock);
kfree(addr);
out:
in6_dev_put(in6_dev);
}
static void qeth_l3_free_vlan_addresses(struct qeth_card *card,
unsigned short vid)
{
rcu_read_lock();
qeth_l3_free_vlan_addresses4(card, vid);
qeth_l3_free_vlan_addresses6(card, vid);
rcu_read_unlock();
}
static int qeth_l3_vlan_rx_add_vid(struct net_device *dev, static int qeth_l3_vlan_rx_add_vid(struct net_device *dev,
__be16 proto, u16 vid) __be16 proto, u16 vid)
{ {
...@@ -1398,8 +1289,6 @@ static int qeth_l3_vlan_rx_kill_vid(struct net_device *dev, ...@@ -1398,8 +1289,6 @@ static int qeth_l3_vlan_rx_kill_vid(struct net_device *dev,
QETH_CARD_TEXT(card, 3, "kidREC"); QETH_CARD_TEXT(card, 3, "kidREC");
return 0; return 0;
} }
/* unregister IP addresses of vlan device */
qeth_l3_free_vlan_addresses(card, vid);
clear_bit(vid, card->active_vlans); clear_bit(vid, card->active_vlans);
qeth_l3_set_rx_mode(dev); qeth_l3_set_rx_mode(dev);
return 0; return 0;
...@@ -1454,17 +1343,7 @@ static void qeth_l3_rebuild_skb(struct qeth_card *card, struct sk_buff *skb, ...@@ -1454,17 +1343,7 @@ static void qeth_l3_rebuild_skb(struct qeth_card *card, struct sk_buff *skb,
__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), tag); __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), tag);
} }
if (card->dev->features & NETIF_F_RXCSUM) { qeth_rx_csum(card, skb, hdr->hdr.l3.ext_flags);
if ((hdr->hdr.l3.ext_flags &
(QETH_HDR_EXT_CSUM_HDR_REQ |
QETH_HDR_EXT_CSUM_TRANSP_REQ)) ==
(QETH_HDR_EXT_CSUM_HDR_REQ |
QETH_HDR_EXT_CSUM_TRANSP_REQ))
skb->ip_summed = CHECKSUM_UNNECESSARY;
else
skb->ip_summed = CHECKSUM_NONE;
} else
skb->ip_summed = CHECKSUM_NONE;
} }
static int qeth_l3_process_inbound_buffer(struct qeth_card *card, static int qeth_l3_process_inbound_buffer(struct qeth_card *card,
...@@ -2210,23 +2089,6 @@ static void qeth_l3_fill_header(struct qeth_card *card, struct qeth_hdr *hdr, ...@@ -2210,23 +2089,6 @@ static void qeth_l3_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
rcu_read_unlock(); rcu_read_unlock();
} }
static void qeth_l3_hdr_csum(struct qeth_card *card, struct qeth_hdr *hdr,
struct sk_buff *skb)
{
struct iphdr *iph = ip_hdr(skb);
/* tcph->check contains already the pseudo hdr checksum
* so just set the header flags
*/
if (iph->protocol == IPPROTO_UDP)
hdr->hdr.l3.ext_flags |= QETH_HDR_EXT_UDP;
hdr->hdr.l3.ext_flags |= QETH_HDR_EXT_CSUM_TRANSP_REQ |
QETH_HDR_EXT_CSUM_HDR_REQ;
iph->check = 0;
if (card->options.performance_stats)
card->perf_stats.tx_csum++;
}
static void qeth_tso_fill_header(struct qeth_card *card, static void qeth_tso_fill_header(struct qeth_card *card,
struct qeth_hdr *qhdr, struct sk_buff *skb) struct qeth_hdr *qhdr, struct sk_buff *skb)
{ {
...@@ -2418,8 +2280,11 @@ static netdev_tx_t qeth_l3_hard_start_xmit(struct sk_buff *skb, ...@@ -2418,8 +2280,11 @@ static netdev_tx_t qeth_l3_hard_start_xmit(struct sk_buff *skb,
} }
} }
if (skb->ip_summed == CHECKSUM_PARTIAL) if (new_skb->ip_summed == CHECKSUM_PARTIAL) {
qeth_l3_hdr_csum(card, hdr, new_skb); qeth_tx_csum(new_skb, &hdr->hdr.l3.ext_flags, ipv);
if (card->options.performance_stats)
card->perf_stats.tx_csum++;
}
} }
elements = use_tso ? elements = use_tso ?
...@@ -2620,28 +2485,32 @@ static int qeth_l3_setup_netdev(struct qeth_card *card) ...@@ -2620,28 +2485,32 @@ static int qeth_l3_setup_netdev(struct qeth_card *card)
(card->info.link_type == QETH_LINK_TYPE_HSTR)) { (card->info.link_type == QETH_LINK_TYPE_HSTR)) {
pr_info("qeth_l3: ignoring TR device\n"); pr_info("qeth_l3: ignoring TR device\n");
return -ENODEV; return -ENODEV;
} else { }
card->dev = alloc_etherdev(0);
if (!card->dev) card->dev = alloc_etherdev(0);
return -ENODEV; if (!card->dev)
card->dev->netdev_ops = &qeth_l3_osa_netdev_ops; return -ENODEV;
card->dev->netdev_ops = &qeth_l3_osa_netdev_ops;
/*IPv6 address autoconfiguration stuff*/
qeth_l3_get_unique_id(card); /*IPv6 address autoconfiguration stuff*/
if (!(card->info.unique_id & UNIQUE_ID_NOT_BY_CARD)) qeth_l3_get_unique_id(card);
card->dev->dev_id = card->info.unique_id & if (!(card->info.unique_id & UNIQUE_ID_NOT_BY_CARD))
0xffff; card->dev->dev_id = card->info.unique_id & 0xffff;
card->dev->hw_features |= NETIF_F_SG; card->dev->hw_features |= NETIF_F_SG;
card->dev->vlan_features |= NETIF_F_SG; card->dev->vlan_features |= NETIF_F_SG;
if (!card->info.guestlan) { if (!card->info.guestlan) {
card->dev->features |= NETIF_F_SG; card->dev->features |= NETIF_F_SG;
card->dev->hw_features |= NETIF_F_TSO | card->dev->hw_features |= NETIF_F_TSO |
NETIF_F_RXCSUM | NETIF_F_IP_CSUM; NETIF_F_RXCSUM | NETIF_F_IP_CSUM;
card->dev->vlan_features |= NETIF_F_TSO | card->dev->vlan_features |= NETIF_F_TSO |
NETIF_F_RXCSUM | NETIF_F_IP_CSUM; NETIF_F_RXCSUM | NETIF_F_IP_CSUM;
} }
if (qeth_is_supported6(card, IPA_OUTBOUND_CHECKSUM_V6)) {
card->dev->hw_features |= NETIF_F_IPV6_CSUM;
card->dev->vlan_features |= NETIF_F_IPV6_CSUM;
} }
} else if (card->info.type == QETH_CARD_TYPE_IQD) { } else if (card->info.type == QETH_CARD_TYPE_IQD) {
card->dev = alloc_netdev(0, "hsi%d", NET_NAME_UNKNOWN, card->dev = alloc_netdev(0, "hsi%d", NET_NAME_UNKNOWN,
...@@ -2663,6 +2532,7 @@ static int qeth_l3_setup_netdev(struct qeth_card *card) ...@@ -2663,6 +2532,7 @@ static int qeth_l3_setup_netdev(struct qeth_card *card)
card->dev->mtu = card->info.initial_mtu; card->dev->mtu = card->info.initial_mtu;
card->dev->min_mtu = 64; card->dev->min_mtu = 64;
card->dev->max_mtu = ETH_MAX_MTU; card->dev->max_mtu = ETH_MAX_MTU;
card->dev->dev_port = card->info.portno;
card->dev->ethtool_ops = &qeth_l3_ethtool_ops; card->dev->ethtool_ops = &qeth_l3_ethtool_ops;
card->dev->features |= NETIF_F_HW_VLAN_CTAG_TX | card->dev->features |= NETIF_F_HW_VLAN_CTAG_TX |
NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_CTAG_RX |
...@@ -2960,9 +2830,6 @@ static int qeth_l3_control_event(struct qeth_card *card, ...@@ -2960,9 +2830,6 @@ static int qeth_l3_control_event(struct qeth_card *card,
struct qeth_discipline qeth_l3_discipline = { struct qeth_discipline qeth_l3_discipline = {
.devtype = &qeth_l3_devtype, .devtype = &qeth_l3_devtype,
.start_poll = qeth_qdio_start_poll,
.input_handler = (qdio_handler_t *) qeth_qdio_input_handler,
.output_handler = (qdio_handler_t *) qeth_qdio_output_handler,
.process_rx_buffer = qeth_l3_process_inbound_buffer, .process_rx_buffer = qeth_l3_process_inbound_buffer,
.recover = qeth_l3_recover, .recover = qeth_l3_recover,
.setup = qeth_l3_probe_device, .setup = qeth_l3_probe_device,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment