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 *,
......
...@@ -1467,13 +1467,13 @@ static int qeth_setup_card(struct qeth_card *card) ...@@ -1467,13 +1467,13 @@ static int qeth_setup_card(struct qeth_card *card)
card->lan_online = 0; card->lan_online = 0;
card->read_or_write_problem = 0; card->read_or_write_problem = 0;
card->dev = NULL; card->dev = NULL;
spin_lock_init(&card->vlanlock);
spin_lock_init(&card->mclock); spin_lock_init(&card->mclock);
spin_lock_init(&card->lock); spin_lock_init(&card->lock);
spin_lock_init(&card->ip_lock); spin_lock_init(&card->ip_lock);
spin_lock_init(&card->thread_mask_lock); spin_lock_init(&card->thread_mask_lock);
mutex_init(&card->conf_mutex); mutex_init(&card->conf_mutex);
mutex_init(&card->discipline_mutex); mutex_init(&card->discipline_mutex);
mutex_init(&card->vid_list_mutex);
card->thread_start_mask = 0; card->thread_start_mask = 0;
card->thread_allowed_mask = 0; card->thread_allowed_mask = 0;
card->thread_running_mask = 0; card->thread_running_mask = 0;
...@@ -3588,15 +3588,14 @@ static void qeth_check_outbound_queue(struct qeth_qdio_out_q *queue) ...@@ -3588,15 +3588,14 @@ static void qeth_check_outbound_queue(struct qeth_qdio_out_q *queue)
} }
} }
void qeth_qdio_start_poll(struct ccw_device *ccwdev, int queue, static void qeth_qdio_start_poll(struct ccw_device *ccwdev, int queue,
unsigned long card_ptr) unsigned long card_ptr)
{ {
struct qeth_card *card = (struct qeth_card *)card_ptr; struct qeth_card *card = (struct qeth_card *)card_ptr;
if (card->dev && (card->dev->flags & IFF_UP)) if (card->dev && (card->dev->flags & IFF_UP))
napi_schedule(&card->napi); napi_schedule(&card->napi);
} }
EXPORT_SYMBOL_GPL(qeth_qdio_start_poll);
int qeth_configure_cq(struct qeth_card *card, enum qeth_cq cq) int qeth_configure_cq(struct qeth_card *card, enum qeth_cq cq)
{ {
...@@ -3698,9 +3697,10 @@ static void qeth_qdio_cq_handler(struct qeth_card *card, ...@@ -3698,9 +3697,10 @@ static void qeth_qdio_cq_handler(struct qeth_card *card,
return; return;
} }
void qeth_qdio_input_handler(struct ccw_device *ccwdev, unsigned int qdio_err, static void qeth_qdio_input_handler(struct ccw_device *ccwdev,
unsigned int queue, int first_elem, int count, unsigned int qdio_err, int queue,
unsigned long card_ptr) int first_elem, int count,
unsigned long card_ptr)
{ {
struct qeth_card *card = (struct qeth_card *)card_ptr; struct qeth_card *card = (struct qeth_card *)card_ptr;
...@@ -3711,14 +3711,12 @@ void qeth_qdio_input_handler(struct ccw_device *ccwdev, unsigned int qdio_err, ...@@ -3711,14 +3711,12 @@ void qeth_qdio_input_handler(struct ccw_device *ccwdev, unsigned int qdio_err,
qeth_qdio_cq_handler(card, qdio_err, queue, first_elem, count); qeth_qdio_cq_handler(card, qdio_err, queue, first_elem, count);
else if (qdio_err) else if (qdio_err)
qeth_schedule_recovery(card); qeth_schedule_recovery(card);
} }
EXPORT_SYMBOL_GPL(qeth_qdio_input_handler);
void qeth_qdio_output_handler(struct ccw_device *ccwdev, static void qeth_qdio_output_handler(struct ccw_device *ccwdev,
unsigned int qdio_error, int __queue, int first_element, unsigned int qdio_error, int __queue,
int count, unsigned long card_ptr) int first_element, int count,
unsigned long card_ptr)
{ {
struct qeth_card *card = (struct qeth_card *) card_ptr; struct qeth_card *card = (struct qeth_card *) card_ptr;
struct qeth_qdio_out_q *queue = card->qdio.out_qs[__queue]; struct qeth_qdio_out_q *queue = card->qdio.out_qs[__queue];
...@@ -3787,7 +3785,6 @@ void qeth_qdio_output_handler(struct ccw_device *ccwdev, ...@@ -3787,7 +3785,6 @@ void qeth_qdio_output_handler(struct ccw_device *ccwdev,
card->perf_stats.outbound_handler_time += qeth_get_micros() - card->perf_stats.outbound_handler_time += qeth_get_micros() -
card->perf_stats.outbound_handler_start_time; card->perf_stats.outbound_handler_start_time;
} }
EXPORT_SYMBOL_GPL(qeth_qdio_output_handler);
/* We cannot use outbound queue 3 for unicast packets on HiperSockets */ /* We cannot use outbound queue 3 for unicast packets on HiperSockets */
static inline int qeth_cut_iqd_prio(struct qeth_card *card, int queue_num) static inline int qeth_cut_iqd_prio(struct qeth_card *card, int queue_num)
...@@ -4995,7 +4992,7 @@ static int qeth_qdio_establish(struct qeth_card *card) ...@@ -4995,7 +4992,7 @@ static int qeth_qdio_establish(struct qeth_card *card)
goto out_free_in_sbals; goto out_free_in_sbals;
} }
for (i = 0; i < card->qdio.no_in_queues; ++i) for (i = 0; i < card->qdio.no_in_queues; ++i)
queue_start_poll[i] = card->discipline->start_poll; queue_start_poll[i] = qeth_qdio_start_poll;
qeth_qdio_establish_cq(card, in_sbal_ptrs, queue_start_poll); qeth_qdio_establish_cq(card, in_sbal_ptrs, queue_start_poll);
...@@ -5019,8 +5016,8 @@ static int qeth_qdio_establish(struct qeth_card *card) ...@@ -5019,8 +5016,8 @@ static int qeth_qdio_establish(struct qeth_card *card)
init_data.qib_param_field = qib_param_field; init_data.qib_param_field = qib_param_field;
init_data.no_input_qs = card->qdio.no_in_queues; init_data.no_input_qs = card->qdio.no_in_queues;
init_data.no_output_qs = card->qdio.no_out_queues; init_data.no_output_qs = card->qdio.no_out_queues;
init_data.input_handler = card->discipline->input_handler; init_data.input_handler = qeth_qdio_input_handler;
init_data.output_handler = card->discipline->output_handler; init_data.output_handler = qeth_qdio_output_handler;
init_data.queue_start_poll_array = queue_start_poll; init_data.queue_start_poll_array = queue_start_poll;
init_data.int_parm = (unsigned long) card; init_data.int_parm = (unsigned long) card;
init_data.input_sbal_addr_array = (void **) in_sbal_ptrs; init_data.input_sbal_addr_array = (void **) in_sbal_ptrs;
...@@ -5204,6 +5201,11 @@ int qeth_core_hardsetup_card(struct qeth_card *card) ...@@ -5204,6 +5201,11 @@ int qeth_core_hardsetup_card(struct qeth_card *card)
rc = qeth_query_ipassists(card, QETH_PROT_IPV4); rc = qeth_query_ipassists(card, QETH_PROT_IPV4);
if (rc == -ENOMEM) if (rc == -ENOMEM)
goto out; goto out;
if (qeth_is_supported(card, IPA_IPV6)) {
rc = qeth_query_ipassists(card, QETH_PROT_IPV6);
if (rc == -ENOMEM)
goto out;
}
if (qeth_is_supported(card, IPA_SETADAPTERPARMS)) { if (qeth_is_supported(card, IPA_SETADAPTERPARMS)) {
rc = qeth_query_setadapterparms(card); rc = qeth_query_setadapterparms(card);
if (rc < 0) { if (rc < 0) {
...@@ -5511,26 +5513,26 @@ int qeth_send_setassparms(struct qeth_card *card, ...@@ -5511,26 +5513,26 @@ int qeth_send_setassparms(struct qeth_card *card,
} }
EXPORT_SYMBOL_GPL(qeth_send_setassparms); EXPORT_SYMBOL_GPL(qeth_send_setassparms);
int qeth_send_simple_setassparms(struct qeth_card *card, int qeth_send_simple_setassparms_prot(struct qeth_card *card,
enum qeth_ipa_funcs ipa_func, enum qeth_ipa_funcs ipa_func,
__u16 cmd_code, long data) u16 cmd_code, long data,
enum qeth_prot_versions prot)
{ {
int rc; int rc;
int length = 0; int length = 0;
struct qeth_cmd_buffer *iob; struct qeth_cmd_buffer *iob;
QETH_CARD_TEXT(card, 4, "simassp4"); QETH_CARD_TEXT_(card, 4, "simassp%i", prot);
if (data) if (data)
length = sizeof(__u32); length = sizeof(__u32);
iob = qeth_get_setassparms_cmd(card, ipa_func, cmd_code, iob = qeth_get_setassparms_cmd(card, ipa_func, cmd_code, length, prot);
length, QETH_PROT_IPV4);
if (!iob) if (!iob)
return -ENOMEM; return -ENOMEM;
rc = qeth_send_setassparms(card, iob, length, data, rc = qeth_send_setassparms(card, iob, length, data,
qeth_setassparms_cb, NULL); qeth_setassparms_cb, NULL);
return rc; return rc;
} }
EXPORT_SYMBOL_GPL(qeth_send_simple_setassparms); EXPORT_SYMBOL_GPL(qeth_send_simple_setassparms_prot);
static void qeth_unregister_dbf_views(void) static void qeth_unregister_dbf_views(void)
{ {
...@@ -6008,7 +6010,8 @@ static struct { ...@@ -6008,7 +6010,8 @@ static struct {
{"tx lin"}, {"tx lin"},
{"tx linfail"}, {"tx linfail"},
{"cq handler count"}, {"cq handler count"},
{"cq handler time"} {"cq handler time"},
{"rx csum"}
}; };
int qeth_core_get_sset_count(struct net_device *dev, int stringset) int qeth_core_get_sset_count(struct net_device *dev, int stringset)
...@@ -6070,6 +6073,7 @@ void qeth_core_get_ethtool_stats(struct net_device *dev, ...@@ -6070,6 +6073,7 @@ void qeth_core_get_ethtool_stats(struct net_device *dev,
data[35] = card->perf_stats.tx_linfail; data[35] = card->perf_stats.tx_linfail;
data[36] = card->perf_stats.cq_cnt; data[36] = card->perf_stats.cq_cnt;
data[37] = card->perf_stats.cq_time; data[37] = card->perf_stats.cq_time;
data[38] = card->perf_stats.rx_csum;
} }
EXPORT_SYMBOL_GPL(qeth_core_get_ethtool_stats); EXPORT_SYMBOL_GPL(qeth_core_get_ethtool_stats);
...@@ -6326,14 +6330,15 @@ static int qeth_ipa_checksum_run_cmd_cb(struct qeth_card *card, ...@@ -6326,14 +6330,15 @@ static int qeth_ipa_checksum_run_cmd_cb(struct qeth_card *card,
static int qeth_ipa_checksum_run_cmd(struct qeth_card *card, static int qeth_ipa_checksum_run_cmd(struct qeth_card *card,
enum qeth_ipa_funcs ipa_func, enum qeth_ipa_funcs ipa_func,
__u16 cmd_code, long data, __u16 cmd_code, long data,
struct qeth_checksum_cmd *chksum_cb) struct qeth_checksum_cmd *chksum_cb,
enum qeth_prot_versions prot)
{ {
struct qeth_cmd_buffer *iob; struct qeth_cmd_buffer *iob;
int rc = -ENOMEM; int rc = -ENOMEM;
QETH_CARD_TEXT(card, 4, "chkdocmd"); QETH_CARD_TEXT(card, 4, "chkdocmd");
iob = qeth_get_setassparms_cmd(card, ipa_func, cmd_code, iob = qeth_get_setassparms_cmd(card, ipa_func, cmd_code,
sizeof(__u32), QETH_PROT_IPV4); sizeof(__u32), prot);
if (iob) if (iob)
rc = qeth_send_setassparms(card, iob, sizeof(__u32), data, rc = qeth_send_setassparms(card, iob, sizeof(__u32), data,
qeth_ipa_checksum_run_cmd_cb, qeth_ipa_checksum_run_cmd_cb,
...@@ -6341,16 +6346,17 @@ static int qeth_ipa_checksum_run_cmd(struct qeth_card *card, ...@@ -6341,16 +6346,17 @@ static int qeth_ipa_checksum_run_cmd(struct qeth_card *card,
return rc; return rc;
} }
static int qeth_send_checksum_on(struct qeth_card *card, int cstype) static int qeth_send_checksum_on(struct qeth_card *card, int cstype,
enum qeth_prot_versions prot)
{ {
const __u32 required_features = QETH_IPA_CHECKSUM_IP_HDR | u32 required_features = QETH_IPA_CHECKSUM_UDP | QETH_IPA_CHECKSUM_TCP;
QETH_IPA_CHECKSUM_UDP |
QETH_IPA_CHECKSUM_TCP;
struct qeth_checksum_cmd chksum_cb; struct qeth_checksum_cmd chksum_cb;
int rc; int rc;
if (prot == QETH_PROT_IPV4)
required_features |= QETH_IPA_CHECKSUM_IP_HDR;
rc = qeth_ipa_checksum_run_cmd(card, cstype, IPA_CMD_ASS_START, 0, rc = qeth_ipa_checksum_run_cmd(card, cstype, IPA_CMD_ASS_START, 0,
&chksum_cb); &chksum_cb, prot);
if (!rc) { if (!rc) {
if ((required_features & chksum_cb.supported) != if ((required_features & chksum_cb.supported) !=
required_features) required_features)
...@@ -6362,37 +6368,42 @@ static int qeth_send_checksum_on(struct qeth_card *card, int cstype) ...@@ -6362,37 +6368,42 @@ static int qeth_send_checksum_on(struct qeth_card *card, int cstype)
QETH_CARD_IFNAME(card)); QETH_CARD_IFNAME(card));
} }
if (rc) { if (rc) {
qeth_send_simple_setassparms(card, cstype, IPA_CMD_ASS_STOP, 0); qeth_send_simple_setassparms_prot(card, cstype,
IPA_CMD_ASS_STOP, 0, prot);
dev_warn(&card->gdev->dev, dev_warn(&card->gdev->dev,
"Starting HW checksumming for %s failed, using SW checksumming\n", "Starting HW IPv%d checksumming for %s failed, using SW checksumming\n",
QETH_CARD_IFNAME(card)); prot, QETH_CARD_IFNAME(card));
return rc; return rc;
} }
rc = qeth_ipa_checksum_run_cmd(card, cstype, IPA_CMD_ASS_ENABLE, rc = qeth_ipa_checksum_run_cmd(card, cstype, IPA_CMD_ASS_ENABLE,
chksum_cb.supported, &chksum_cb); chksum_cb.supported, &chksum_cb,
prot);
if (!rc) { if (!rc) {
if ((required_features & chksum_cb.enabled) != if ((required_features & chksum_cb.enabled) !=
required_features) required_features)
rc = -EIO; rc = -EIO;
} }
if (rc) { if (rc) {
qeth_send_simple_setassparms(card, cstype, IPA_CMD_ASS_STOP, 0); qeth_send_simple_setassparms_prot(card, cstype,
IPA_CMD_ASS_STOP, 0, prot);
dev_warn(&card->gdev->dev, dev_warn(&card->gdev->dev,
"Enabling HW checksumming for %s failed, using SW checksumming\n", "Enabling HW IPv%d checksumming for %s failed, using SW checksumming\n",
QETH_CARD_IFNAME(card)); prot, QETH_CARD_IFNAME(card));
return rc; return rc;
} }
dev_info(&card->gdev->dev, "HW Checksumming (%sbound) enabled\n", dev_info(&card->gdev->dev, "HW Checksumming (%sbound IPv%d) enabled\n",
cstype == IPA_INBOUND_CHECKSUM ? "in" : "out"); cstype == IPA_INBOUND_CHECKSUM ? "in" : "out", prot);
return 0; return 0;
} }
static int qeth_set_ipa_csum(struct qeth_card *card, int on, int cstype) static int qeth_set_ipa_csum(struct qeth_card *card, bool on, int cstype,
enum qeth_prot_versions prot)
{ {
int rc = (on) ? qeth_send_checksum_on(card, cstype) int rc = (on) ? qeth_send_checksum_on(card, cstype, prot)
: qeth_send_simple_setassparms(card, cstype, : qeth_send_simple_setassparms_prot(card, cstype,
IPA_CMD_ASS_STOP, 0); IPA_CMD_ASS_STOP, 0,
prot);
return rc ? -EIO : 0; return rc ? -EIO : 0;
} }
...@@ -6419,8 +6430,31 @@ static int qeth_set_ipa_tso(struct qeth_card *card, int on) ...@@ -6419,8 +6430,31 @@ static int qeth_set_ipa_tso(struct qeth_card *card, int on)
return rc; return rc;
} }
#define QETH_HW_FEATURES (NETIF_F_RXCSUM | NETIF_F_IP_CSUM | NETIF_F_TSO) static int qeth_set_ipa_rx_csum(struct qeth_card *card, bool on)
{
int rc_ipv4 = (on) ? -EOPNOTSUPP : 0;
int rc_ipv6;
if (qeth_is_supported(card, IPA_INBOUND_CHECKSUM))
rc_ipv4 = qeth_set_ipa_csum(card, on, IPA_INBOUND_CHECKSUM,
QETH_PROT_IPV4);
if (!qeth_is_supported6(card, IPA_INBOUND_CHECKSUM_V6))
/* no/one Offload Assist available, so the rc is trivial */
return rc_ipv4;
rc_ipv6 = qeth_set_ipa_csum(card, on, IPA_INBOUND_CHECKSUM,
QETH_PROT_IPV6);
if (on)
/* enable: success if any Assist is active */
return (rc_ipv6) ? rc_ipv4 : 0;
/* disable: failure if any Assist is still active */
return (rc_ipv6) ? rc_ipv6 : rc_ipv4;
}
#define QETH_HW_FEATURES (NETIF_F_RXCSUM | NETIF_F_IP_CSUM | NETIF_F_TSO | \
NETIF_F_IPV6_CSUM)
/** /**
* qeth_recover_features() - Restore device features after recovery * qeth_recover_features() - Restore device features after recovery
* @dev: the recovering net_device * @dev: the recovering net_device
...@@ -6455,16 +6489,19 @@ int qeth_set_features(struct net_device *dev, netdev_features_t features) ...@@ -6455,16 +6489,19 @@ int qeth_set_features(struct net_device *dev, netdev_features_t features)
QETH_DBF_HEX(SETUP, 2, &features, sizeof(features)); QETH_DBF_HEX(SETUP, 2, &features, sizeof(features));
if ((changed & NETIF_F_IP_CSUM)) { if ((changed & NETIF_F_IP_CSUM)) {
rc = qeth_set_ipa_csum(card, rc = qeth_set_ipa_csum(card, features & NETIF_F_IP_CSUM,
features & NETIF_F_IP_CSUM ? 1 : 0, IPA_OUTBOUND_CHECKSUM, QETH_PROT_IPV4);
IPA_OUTBOUND_CHECKSUM);
if (rc) if (rc)
changed ^= NETIF_F_IP_CSUM; changed ^= NETIF_F_IP_CSUM;
} }
if ((changed & NETIF_F_RXCSUM)) { if (changed & NETIF_F_IPV6_CSUM) {
rc = qeth_set_ipa_csum(card, rc = qeth_set_ipa_csum(card, features & NETIF_F_IPV6_CSUM,
features & NETIF_F_RXCSUM ? 1 : 0, IPA_OUTBOUND_CHECKSUM, QETH_PROT_IPV6);
IPA_INBOUND_CHECKSUM); if (rc)
changed ^= NETIF_F_IPV6_CSUM;
}
if (changed & NETIF_F_RXCSUM) {
rc = qeth_set_ipa_rx_csum(card, features & NETIF_F_RXCSUM);
if (rc) if (rc)
changed ^= NETIF_F_RXCSUM; changed ^= NETIF_F_RXCSUM;
} }
...@@ -6491,7 +6528,10 @@ netdev_features_t qeth_fix_features(struct net_device *dev, ...@@ -6491,7 +6528,10 @@ netdev_features_t qeth_fix_features(struct net_device *dev,
QETH_DBF_TEXT(SETUP, 2, "fixfeat"); QETH_DBF_TEXT(SETUP, 2, "fixfeat");
if (!qeth_is_supported(card, IPA_OUTBOUND_CHECKSUM)) if (!qeth_is_supported(card, IPA_OUTBOUND_CHECKSUM))
features &= ~NETIF_F_IP_CSUM; features &= ~NETIF_F_IP_CSUM;
if (!qeth_is_supported(card, IPA_INBOUND_CHECKSUM)) if (!qeth_is_supported6(card, IPA_OUTBOUND_CHECKSUM_V6))
features &= ~NETIF_F_IPV6_CSUM;
if (!qeth_is_supported(card, IPA_INBOUND_CHECKSUM) &&
!qeth_is_supported6(card, IPA_INBOUND_CHECKSUM_V6))
features &= ~NETIF_F_RXCSUM; features &= ~NETIF_F_RXCSUM;
if (!qeth_is_supported(card, IPA_OUTBOUND_TSO)) if (!qeth_is_supported(card, IPA_OUTBOUND_TSO))
features &= ~NETIF_F_TSO; features &= ~NETIF_F_TSO;
......
...@@ -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