mirror of
https://github.com/torvalds/linux.git
synced 2026-05-31 10:33:41 +02:00
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: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
c2335d67b7
|
|
@ -1928,6 +1928,8 @@ lcs_portno_store (struct device *dev, struct device_attribute *attr, const char
|
|||
return -EINVAL;
|
||||
/* TODO: sanity checks */
|
||||
card->portno = value;
|
||||
if (card->dev)
|
||||
card->dev->dev_port = card->portno;
|
||||
|
||||
return count;
|
||||
|
||||
|
|
@ -2158,6 +2160,7 @@ lcs_new_device(struct ccwgroup_device *ccwgdev)
|
|||
card->dev = dev;
|
||||
card->dev->ml_priv = card;
|
||||
card->dev->netdev_ops = &lcs_netdev_ops;
|
||||
card->dev->dev_port = card->portno;
|
||||
memcpy(card->dev->dev_addr, card->mac, LCS_MAC_LENGTH);
|
||||
#ifdef CONFIG_IP_MULTICAST
|
||||
if (!lcs_check_multicast_support(card))
|
||||
|
|
|
|||
|
|
@ -148,6 +148,7 @@ struct qeth_perf_stats {
|
|||
unsigned int tx_csum;
|
||||
unsigned int tx_lin;
|
||||
unsigned int tx_linfail;
|
||||
unsigned int rx_csum;
|
||||
};
|
||||
|
||||
/* Routing stuff */
|
||||
|
|
@ -712,9 +713,6 @@ enum qeth_discipline_id {
|
|||
|
||||
struct qeth_discipline {
|
||||
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 (*recover)(void *ptr);
|
||||
int (*setup) (struct ccwgroup_device *);
|
||||
|
|
@ -780,9 +778,9 @@ struct qeth_card {
|
|||
struct qeth_card_options options;
|
||||
|
||||
wait_queue_head_t wait_q;
|
||||
spinlock_t vlanlock;
|
||||
spinlock_t mclock;
|
||||
unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
|
||||
struct mutex vid_list_mutex; /* vid_list */
|
||||
struct list_head vid_list;
|
||||
DECLARE_HASHTABLE(mac_htable, 4);
|
||||
DECLARE_HASHTABLE(ip_htable, 4);
|
||||
|
|
@ -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,
|
||||
struct qeth_buffer_pool_entry *entry)
|
||||
{
|
||||
|
|
@ -879,6 +903,27 @@ static inline int qeth_is_diagass_supported(struct qeth_card *card,
|
|||
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_l3_discipline;
|
||||
extern const struct attribute_group *qeth_generic_attr_groups[];
|
||||
|
|
@ -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_hdr **);
|
||||
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);
|
||||
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 *);
|
||||
int qeth_qdio_clear_card(struct qeth_card *, int);
|
||||
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);
|
|||
int qeth_query_ipassists(struct qeth_card *, enum qeth_prot_versions prot);
|
||||
void qeth_trace_features(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,
|
||||
long,
|
||||
int (*reply_cb)(struct qeth_card *,
|
||||
|
|
|
|||
|
|
@ -1467,13 +1467,13 @@ static int qeth_setup_card(struct qeth_card *card)
|
|||
card->lan_online = 0;
|
||||
card->read_or_write_problem = 0;
|
||||
card->dev = NULL;
|
||||
spin_lock_init(&card->vlanlock);
|
||||
spin_lock_init(&card->mclock);
|
||||
spin_lock_init(&card->lock);
|
||||
spin_lock_init(&card->ip_lock);
|
||||
spin_lock_init(&card->thread_mask_lock);
|
||||
mutex_init(&card->conf_mutex);
|
||||
mutex_init(&card->discipline_mutex);
|
||||
mutex_init(&card->vid_list_mutex);
|
||||
card->thread_start_mask = 0;
|
||||
card->thread_allowed_mask = 0;
|
||||
card->thread_running_mask = 0;
|
||||
|
|
@ -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,
|
||||
unsigned long card_ptr)
|
||||
static void qeth_qdio_start_poll(struct ccw_device *ccwdev, int queue,
|
||||
unsigned long card_ptr)
|
||||
{
|
||||
struct qeth_card *card = (struct qeth_card *)card_ptr;
|
||||
|
||||
if (card->dev && (card->dev->flags & IFF_UP))
|
||||
napi_schedule(&card->napi);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(qeth_qdio_start_poll);
|
||||
|
||||
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,
|
|||
return;
|
||||
}
|
||||
|
||||
void qeth_qdio_input_handler(struct ccw_device *ccwdev, unsigned int qdio_err,
|
||||
unsigned int queue, int first_elem, int count,
|
||||
unsigned long card_ptr)
|
||||
static void qeth_qdio_input_handler(struct ccw_device *ccwdev,
|
||||
unsigned int qdio_err, int queue,
|
||||
int first_elem, int count,
|
||||
unsigned long 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,
|
|||
qeth_qdio_cq_handler(card, qdio_err, queue, first_elem, count);
|
||||
else if (qdio_err)
|
||||
qeth_schedule_recovery(card);
|
||||
|
||||
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(qeth_qdio_input_handler);
|
||||
|
||||
void qeth_qdio_output_handler(struct ccw_device *ccwdev,
|
||||
unsigned int qdio_error, int __queue, int first_element,
|
||||
int count, unsigned long card_ptr)
|
||||
static void qeth_qdio_output_handler(struct ccw_device *ccwdev,
|
||||
unsigned int qdio_error, int __queue,
|
||||
int first_element, int count,
|
||||
unsigned long card_ptr)
|
||||
{
|
||||
struct qeth_card *card = (struct qeth_card *) card_ptr;
|
||||
struct qeth_qdio_out_q *queue = card->qdio.out_qs[__queue];
|
||||
|
|
@ -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_start_time;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(qeth_qdio_output_handler);
|
||||
|
||||
/* 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)
|
||||
|
|
@ -4995,7 +4992,7 @@ static int qeth_qdio_establish(struct qeth_card *card)
|
|||
goto out_free_in_sbals;
|
||||
}
|
||||
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);
|
||||
|
||||
|
|
@ -5019,8 +5016,8 @@ static int qeth_qdio_establish(struct qeth_card *card)
|
|||
init_data.qib_param_field = qib_param_field;
|
||||
init_data.no_input_qs = card->qdio.no_in_queues;
|
||||
init_data.no_output_qs = card->qdio.no_out_queues;
|
||||
init_data.input_handler = card->discipline->input_handler;
|
||||
init_data.output_handler = card->discipline->output_handler;
|
||||
init_data.input_handler = qeth_qdio_input_handler;
|
||||
init_data.output_handler = qeth_qdio_output_handler;
|
||||
init_data.queue_start_poll_array = queue_start_poll;
|
||||
init_data.int_parm = (unsigned long) card;
|
||||
init_data.input_sbal_addr_array = (void **) in_sbal_ptrs;
|
||||
|
|
@ -5204,6 +5201,11 @@ int qeth_core_hardsetup_card(struct qeth_card *card)
|
|||
rc = qeth_query_ipassists(card, QETH_PROT_IPV4);
|
||||
if (rc == -ENOMEM)
|
||||
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)) {
|
||||
rc = qeth_query_setadapterparms(card);
|
||||
if (rc < 0) {
|
||||
|
|
@ -5511,26 +5513,26 @@ int qeth_send_setassparms(struct qeth_card *card,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(qeth_send_setassparms);
|
||||
|
||||
int qeth_send_simple_setassparms(struct qeth_card *card,
|
||||
enum qeth_ipa_funcs ipa_func,
|
||||
__u16 cmd_code, long data)
|
||||
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)
|
||||
{
|
||||
int rc;
|
||||
int length = 0;
|
||||
struct qeth_cmd_buffer *iob;
|
||||
|
||||
QETH_CARD_TEXT(card, 4, "simassp4");
|
||||
QETH_CARD_TEXT_(card, 4, "simassp%i", prot);
|
||||
if (data)
|
||||
length = sizeof(__u32);
|
||||
iob = qeth_get_setassparms_cmd(card, ipa_func, cmd_code,
|
||||
length, QETH_PROT_IPV4);
|
||||
iob = qeth_get_setassparms_cmd(card, ipa_func, cmd_code, length, prot);
|
||||
if (!iob)
|
||||
return -ENOMEM;
|
||||
rc = qeth_send_setassparms(card, iob, length, data,
|
||||
qeth_setassparms_cb, NULL);
|
||||
return rc;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(qeth_send_simple_setassparms);
|
||||
EXPORT_SYMBOL_GPL(qeth_send_simple_setassparms_prot);
|
||||
|
||||
static void qeth_unregister_dbf_views(void)
|
||||
{
|
||||
|
|
@ -6008,7 +6010,8 @@ static struct {
|
|||
{"tx lin"},
|
||||
{"tx linfail"},
|
||||
{"cq handler count"},
|
||||
{"cq handler time"}
|
||||
{"cq handler time"},
|
||||
{"rx csum"}
|
||||
};
|
||||
|
||||
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,
|
|||
data[35] = card->perf_stats.tx_linfail;
|
||||
data[36] = card->perf_stats.cq_cnt;
|
||||
data[37] = card->perf_stats.cq_time;
|
||||
data[38] = card->perf_stats.rx_csum;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(qeth_core_get_ethtool_stats);
|
||||
|
||||
|
|
@ -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,
|
||||
enum qeth_ipa_funcs ipa_func,
|
||||
__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;
|
||||
int rc = -ENOMEM;
|
||||
|
||||
QETH_CARD_TEXT(card, 4, "chkdocmd");
|
||||
iob = qeth_get_setassparms_cmd(card, ipa_func, cmd_code,
|
||||
sizeof(__u32), QETH_PROT_IPV4);
|
||||
sizeof(__u32), prot);
|
||||
if (iob)
|
||||
rc = qeth_send_setassparms(card, iob, sizeof(__u32), data,
|
||||
qeth_ipa_checksum_run_cmd_cb,
|
||||
|
|
@ -6341,16 +6346,17 @@ static int qeth_ipa_checksum_run_cmd(struct qeth_card *card,
|
|||
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 |
|
||||
QETH_IPA_CHECKSUM_UDP |
|
||||
QETH_IPA_CHECKSUM_TCP;
|
||||
u32 required_features = QETH_IPA_CHECKSUM_UDP | QETH_IPA_CHECKSUM_TCP;
|
||||
struct qeth_checksum_cmd chksum_cb;
|
||||
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,
|
||||
&chksum_cb);
|
||||
&chksum_cb, prot);
|
||||
if (!rc) {
|
||||
if ((required_features & chksum_cb.supported) !=
|
||||
required_features)
|
||||
|
|
@ -6362,37 +6368,42 @@ static int qeth_send_checksum_on(struct qeth_card *card, int cstype)
|
|||
QETH_CARD_IFNAME(card));
|
||||
}
|
||||
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,
|
||||
"Starting HW checksumming for %s failed, using SW checksumming\n",
|
||||
QETH_CARD_IFNAME(card));
|
||||
"Starting HW IPv%d checksumming for %s failed, using SW checksumming\n",
|
||||
prot, QETH_CARD_IFNAME(card));
|
||||
return rc;
|
||||
}
|
||||
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 ((required_features & chksum_cb.enabled) !=
|
||||
required_features)
|
||||
rc = -EIO;
|
||||
}
|
||||
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,
|
||||
"Enabling HW checksumming for %s failed, using SW checksumming\n",
|
||||
QETH_CARD_IFNAME(card));
|
||||
"Enabling HW IPv%d checksumming for %s failed, using SW checksumming\n",
|
||||
prot, QETH_CARD_IFNAME(card));
|
||||
return rc;
|
||||
}
|
||||
|
||||
dev_info(&card->gdev->dev, "HW Checksumming (%sbound) enabled\n",
|
||||
cstype == IPA_INBOUND_CHECKSUM ? "in" : "out");
|
||||
dev_info(&card->gdev->dev, "HW Checksumming (%sbound IPv%d) enabled\n",
|
||||
cstype == IPA_INBOUND_CHECKSUM ? "in" : "out", prot);
|
||||
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)
|
||||
: qeth_send_simple_setassparms(card, cstype,
|
||||
IPA_CMD_ASS_STOP, 0);
|
||||
int rc = (on) ? qeth_send_checksum_on(card, cstype, prot)
|
||||
: qeth_send_simple_setassparms_prot(card, cstype,
|
||||
IPA_CMD_ASS_STOP, 0,
|
||||
prot);
|
||||
return rc ? -EIO : 0;
|
||||
}
|
||||
|
||||
|
|
@ -6419,8 +6430,31 @@ static int qeth_set_ipa_tso(struct qeth_card *card, int on)
|
|||
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
|
||||
* @dev: the recovering net_device
|
||||
|
|
@ -6455,16 +6489,19 @@ int qeth_set_features(struct net_device *dev, netdev_features_t features)
|
|||
QETH_DBF_HEX(SETUP, 2, &features, sizeof(features));
|
||||
|
||||
if ((changed & NETIF_F_IP_CSUM)) {
|
||||
rc = qeth_set_ipa_csum(card,
|
||||
features & NETIF_F_IP_CSUM ? 1 : 0,
|
||||
IPA_OUTBOUND_CHECKSUM);
|
||||
rc = qeth_set_ipa_csum(card, features & NETIF_F_IP_CSUM,
|
||||
IPA_OUTBOUND_CHECKSUM, QETH_PROT_IPV4);
|
||||
if (rc)
|
||||
changed ^= NETIF_F_IP_CSUM;
|
||||
}
|
||||
if ((changed & NETIF_F_RXCSUM)) {
|
||||
rc = qeth_set_ipa_csum(card,
|
||||
features & NETIF_F_RXCSUM ? 1 : 0,
|
||||
IPA_INBOUND_CHECKSUM);
|
||||
if (changed & NETIF_F_IPV6_CSUM) {
|
||||
rc = qeth_set_ipa_csum(card, features & NETIF_F_IPV6_CSUM,
|
||||
IPA_OUTBOUND_CHECKSUM, QETH_PROT_IPV6);
|
||||
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)
|
||||
changed ^= NETIF_F_RXCSUM;
|
||||
}
|
||||
|
|
@ -6491,7 +6528,10 @@ netdev_features_t qeth_fix_features(struct net_device *dev,
|
|||
QETH_DBF_TEXT(SETUP, 2, "fixfeat");
|
||||
if (!qeth_is_supported(card, IPA_OUTBOUND_CHECKSUM))
|
||||
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;
|
||||
if (!qeth_is_supported(card, IPA_OUTBOUND_TSO))
|
||||
features &= ~NETIF_F_TSO;
|
||||
|
|
|
|||
|
|
@ -246,6 +246,8 @@ enum qeth_ipa_funcs {
|
|||
IPA_QUERY_ARP_ASSIST = 0x00040000L,
|
||||
IPA_INBOUND_TSO = 0x00080000L,
|
||||
IPA_OUTBOUND_TSO = 0x00100000L,
|
||||
IPA_INBOUND_CHECKSUM_V6 = 0x00400000L,
|
||||
IPA_OUTBOUND_CHECKSUM_V6 = 0x00800000L,
|
||||
};
|
||||
|
||||
/* SETIP/DELIP IPA Command: ***************************************************/
|
||||
|
|
|
|||
|
|
@ -144,6 +144,8 @@ static ssize_t qeth_dev_portno_store(struct device *dev,
|
|||
goto out;
|
||||
}
|
||||
card->info.portno = portno;
|
||||
if (card->dev)
|
||||
card->dev->dev_port = portno;
|
||||
out:
|
||||
mutex_unlock(&card->conf_mutex);
|
||||
return rc ? rc : count;
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/hash.h>
|
||||
#include <linux/hashtable.h>
|
||||
|
|
@ -195,23 +194,6 @@ static int qeth_l2_get_cast_type(struct qeth_card *card, struct sk_buff *skb)
|
|||
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,
|
||||
int cast_type, unsigned int data_len)
|
||||
{
|
||||
|
|
@ -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)
|
||||
{
|
||||
struct qeth_vlan_vid *id;
|
||||
|
||||
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) {
|
||||
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,
|
||||
|
|
@ -319,7 +302,7 @@ static int qeth_l2_vlan_rx_add_vid(struct net_device *dev,
|
|||
QETH_CARD_TEXT(card, 3, "aidREC");
|
||||
return 0;
|
||||
}
|
||||
id = kmalloc(sizeof(struct qeth_vlan_vid), GFP_ATOMIC);
|
||||
id = kmalloc(sizeof(*id), GFP_KERNEL);
|
||||
if (id) {
|
||||
id->vid = vid;
|
||||
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,
|
|||
kfree(id);
|
||||
return rc;
|
||||
}
|
||||
spin_lock_bh(&card->vlanlock);
|
||||
mutex_lock(&card->vid_list_mutex);
|
||||
list_add_tail(&id->list, &card->vid_list);
|
||||
spin_unlock_bh(&card->vlanlock);
|
||||
mutex_unlock(&card->vid_list_mutex);
|
||||
} else {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
|
@ -348,7 +331,7 @@ static int qeth_l2_vlan_rx_kill_vid(struct net_device *dev,
|
|||
QETH_CARD_TEXT(card, 3, "kidREC");
|
||||
return 0;
|
||||
}
|
||||
spin_lock_bh(&card->vlanlock);
|
||||
mutex_lock(&card->vid_list_mutex);
|
||||
list_for_each_entry(id, &card->vid_list, list) {
|
||||
if (id->vid == vid) {
|
||||
list_del(&id->list);
|
||||
|
|
@ -356,7 +339,7 @@ static int qeth_l2_vlan_rx_kill_vid(struct net_device *dev,
|
|||
break;
|
||||
}
|
||||
}
|
||||
spin_unlock_bh(&card->vlanlock);
|
||||
mutex_unlock(&card->vid_list_mutex);
|
||||
if (tmpid) {
|
||||
rc = qeth_l2_send_setdelvlan(card, vid, IPA_CMD_DELVLAN);
|
||||
kfree(tmpid);
|
||||
|
|
@ -423,15 +406,7 @@ static int qeth_l2_process_inbound_buffer(struct qeth_card *card,
|
|||
switch (hdr->hdr.l2.id) {
|
||||
case QETH_HEADER_TYPE_LAYER2:
|
||||
skb->protocol = eth_type_trans(skb, skb->dev);
|
||||
if ((card->dev->features & NETIF_F_RXCSUM)
|
||||
&& ((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;
|
||||
qeth_rx_csum(card, skb, hdr->hdr.l2.flags[1]);
|
||||
if (skb->protocol == htons(ETH_P_802_2))
|
||||
*((__u32 *)skb->cb) = ++card->seqno.pkt_seqno;
|
||||
len = skb->len;
|
||||
|
|
@ -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)
|
||||
{
|
||||
int rc = 0;
|
||||
char vendor_pre[] = {0x02, 0x00, 0x00};
|
||||
|
||||
QETH_DBF_TEXT(SETUP, 2, "l2reqmac");
|
||||
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)
|
|||
card->info.type == QETH_CARD_TYPE_OSX ||
|
||||
card->info.guestlan) {
|
||||
rc = qeth_setadpparms_change_macaddr(card);
|
||||
if (rc) {
|
||||
QETH_DBF_MESSAGE(2, "couldn't get MAC address on "
|
||||
"device %s: x%x\n", CARD_BUS_ID(card), rc);
|
||||
QETH_DBF_TEXT_(SETUP, 2, "1err%04x", rc);
|
||||
return rc;
|
||||
}
|
||||
} else {
|
||||
eth_random_addr(card->dev->dev_addr);
|
||||
memcpy(card->dev->dev_addr, vendor_pre, 3);
|
||||
if (!rc)
|
||||
goto out;
|
||||
QETH_DBF_MESSAGE(2, "READ_MAC Assist failed on device %s: x%x\n",
|
||||
CARD_BUS_ID(card), rc);
|
||||
QETH_DBF_TEXT_(SETUP, 2, "1err%04x", rc);
|
||||
/* fall back once more: */
|
||||
}
|
||||
|
||||
/* 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:
|
||||
QETH_DBF_HEX(SETUP, 2, card->dev->dev_addr, card->dev->addr_len);
|
||||
return 0;
|
||||
|
|
@ -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,
|
||||
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);
|
||||
unsigned int elements, nr_frags;
|
||||
|
|
@ -723,8 +702,11 @@ static int qeth_l2_xmit_osa(struct qeth_card *card, struct sk_buff *skb,
|
|||
hdr_elements = 1;
|
||||
}
|
||||
qeth_l2_fill_header(hdr, skb, cast_type, skb->len - push_len);
|
||||
if (skb->ip_summed == CHECKSUM_PARTIAL)
|
||||
qeth_l2_hdr_csum(card, hdr, skb);
|
||||
if (skb->ip_summed == CHECKSUM_PARTIAL) {
|
||||
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);
|
||||
if (!elements) {
|
||||
|
|
@ -776,6 +758,7 @@ static netdev_tx_t qeth_l2_hard_start_xmit(struct sk_buff *skb,
|
|||
{
|
||||
struct qeth_card *card = dev->ml_priv;
|
||||
int cast_type = qeth_l2_get_cast_type(card, skb);
|
||||
int ipv = qeth_get_ip_version(skb);
|
||||
struct qeth_qdio_out_q *queue;
|
||||
int tx_bytes = skb->len;
|
||||
int rc;
|
||||
|
|
@ -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 &&
|
||||
card->info.is_multicast_different))
|
||||
queue = card->qdio.out_qs[qeth_get_priority_queue(card, skb,
|
||||
qeth_get_ip_version(skb), cast_type)];
|
||||
ipv, cast_type)];
|
||||
else
|
||||
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,
|
|||
rc = qeth_l2_xmit_iqd(card, skb, queue, cast_type);
|
||||
break;
|
||||
default:
|
||||
rc = qeth_l2_xmit_osa(card, skb, queue, cast_type);
|
||||
rc = qeth_l2_xmit_osa(card, skb, queue, cast_type, ipv);
|
||||
}
|
||||
|
||||
if (!rc) {
|
||||
|
|
@ -983,6 +966,7 @@ static int qeth_l2_setup_netdev(struct qeth_card *card)
|
|||
card->dev->mtu = card->info.initial_mtu;
|
||||
card->dev->min_mtu = 64;
|
||||
card->dev->max_mtu = ETH_MAX_MTU;
|
||||
card->dev->dev_port = card->info.portno;
|
||||
card->dev->netdev_ops = &qeth_l2_netdev_ops;
|
||||
if (card->info.type == QETH_CARD_TYPE_OSN) {
|
||||
card->dev->ethtool_ops = &qeth_l2_osn_ops;
|
||||
|
|
@ -1011,10 +995,15 @@ static int qeth_l2_setup_netdev(struct qeth_card *card)
|
|||
card->dev->hw_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;
|
||||
card->dev->vlan_features |= NETIF_F_RXCSUM;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
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;
|
||||
|
|
@ -1315,9 +1304,6 @@ static int qeth_l2_control_event(struct qeth_card *card,
|
|||
|
||||
struct qeth_discipline qeth_l2_discipline = {
|
||||
.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,
|
||||
.recover = qeth_l2_recover,
|
||||
.setup = qeth_l2_probe_device,
|
||||
|
|
|
|||
|
|
@ -735,22 +735,6 @@ static int qeth_l3_setadapter_parms(struct qeth_card *card)
|
|||
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)
|
||||
{
|
||||
int rc;
|
||||
|
|
@ -851,14 +835,6 @@ static int qeth_l3_softsetup_ipv6(struct qeth_card *card)
|
|||
|
||||
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)
|
||||
goto out;
|
||||
|
||||
|
|
@ -870,16 +846,16 @@ static int qeth_l3_softsetup_ipv6(struct qeth_card *card)
|
|||
QETH_CARD_IFNAME(card));
|
||||
return rc;
|
||||
}
|
||||
rc = qeth_l3_send_simple_setassparms_ipv6(card, IPA_IPV6,
|
||||
IPA_CMD_ASS_START);
|
||||
rc = qeth_send_simple_setassparms_v6(card, IPA_IPV6,
|
||||
IPA_CMD_ASS_START, 0);
|
||||
if (rc) {
|
||||
dev_err(&card->gdev->dev,
|
||||
"Activating IPv6 support for %s failed\n",
|
||||
QETH_CARD_IFNAME(card));
|
||||
return rc;
|
||||
}
|
||||
rc = qeth_l3_send_simple_setassparms_ipv6(card, IPA_PASSTHRU,
|
||||
IPA_CMD_ASS_START);
|
||||
rc = qeth_send_simple_setassparms_v6(card, IPA_PASSTHRU,
|
||||
IPA_CMD_ASS_START, 0);
|
||||
if (rc) {
|
||||
dev_warn(&card->gdev->dev,
|
||||
"Enabling the passthrough mode for %s failed\n",
|
||||
|
|
@ -1293,91 +1269,6 @@ static void qeth_l3_add_multicast_ipv6(struct qeth_card *card)
|
|||
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,
|
||||
__be16 proto, u16 vid)
|
||||
{
|
||||
|
|
@ -1398,8 +1289,6 @@ static int qeth_l3_vlan_rx_kill_vid(struct net_device *dev,
|
|||
QETH_CARD_TEXT(card, 3, "kidREC");
|
||||
return 0;
|
||||
}
|
||||
/* unregister IP addresses of vlan device */
|
||||
qeth_l3_free_vlan_addresses(card, vid);
|
||||
clear_bit(vid, card->active_vlans);
|
||||
qeth_l3_set_rx_mode(dev);
|
||||
return 0;
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
||||
if (card->dev->features & NETIF_F_RXCSUM) {
|
||||
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;
|
||||
qeth_rx_csum(card, skb, hdr->hdr.l3.ext_flags);
|
||||
}
|
||||
|
||||
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,
|
|||
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,
|
||||
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,
|
|||
}
|
||||
}
|
||||
|
||||
if (skb->ip_summed == CHECKSUM_PARTIAL)
|
||||
qeth_l3_hdr_csum(card, hdr, new_skb);
|
||||
if (new_skb->ip_summed == CHECKSUM_PARTIAL) {
|
||||
qeth_tx_csum(new_skb, &hdr->hdr.l3.ext_flags, ipv);
|
||||
if (card->options.performance_stats)
|
||||
card->perf_stats.tx_csum++;
|
||||
}
|
||||
}
|
||||
|
||||
elements = use_tso ?
|
||||
|
|
@ -2620,28 +2485,32 @@ static int qeth_l3_setup_netdev(struct qeth_card *card)
|
|||
(card->info.link_type == QETH_LINK_TYPE_HSTR)) {
|
||||
pr_info("qeth_l3: ignoring TR device\n");
|
||||
return -ENODEV;
|
||||
} else {
|
||||
card->dev = alloc_etherdev(0);
|
||||
if (!card->dev)
|
||||
return -ENODEV;
|
||||
card->dev->netdev_ops = &qeth_l3_osa_netdev_ops;
|
||||
}
|
||||
|
||||
/*IPv6 address autoconfiguration stuff*/
|
||||
qeth_l3_get_unique_id(card);
|
||||
if (!(card->info.unique_id & UNIQUE_ID_NOT_BY_CARD))
|
||||
card->dev->dev_id = card->info.unique_id &
|
||||
0xffff;
|
||||
card->dev = alloc_etherdev(0);
|
||||
if (!card->dev)
|
||||
return -ENODEV;
|
||||
card->dev->netdev_ops = &qeth_l3_osa_netdev_ops;
|
||||
|
||||
card->dev->hw_features |= NETIF_F_SG;
|
||||
card->dev->vlan_features |= NETIF_F_SG;
|
||||
/*IPv6 address autoconfiguration stuff*/
|
||||
qeth_l3_get_unique_id(card);
|
||||
if (!(card->info.unique_id & UNIQUE_ID_NOT_BY_CARD))
|
||||
card->dev->dev_id = card->info.unique_id & 0xffff;
|
||||
|
||||
if (!card->info.guestlan) {
|
||||
card->dev->features |= NETIF_F_SG;
|
||||
card->dev->hw_features |= NETIF_F_TSO |
|
||||
NETIF_F_RXCSUM | NETIF_F_IP_CSUM;
|
||||
card->dev->vlan_features |= NETIF_F_TSO |
|
||||
NETIF_F_RXCSUM | NETIF_F_IP_CSUM;
|
||||
}
|
||||
card->dev->hw_features |= NETIF_F_SG;
|
||||
card->dev->vlan_features |= NETIF_F_SG;
|
||||
|
||||
if (!card->info.guestlan) {
|
||||
card->dev->features |= NETIF_F_SG;
|
||||
card->dev->hw_features |= NETIF_F_TSO |
|
||||
NETIF_F_RXCSUM | NETIF_F_IP_CSUM;
|
||||
card->dev->vlan_features |= NETIF_F_TSO |
|
||||
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) {
|
||||
card->dev = alloc_netdev(0, "hsi%d", NET_NAME_UNKNOWN,
|
||||
|
|
@ -2663,6 +2532,7 @@ static int qeth_l3_setup_netdev(struct qeth_card *card)
|
|||
card->dev->mtu = card->info.initial_mtu;
|
||||
card->dev->min_mtu = 64;
|
||||
card->dev->max_mtu = ETH_MAX_MTU;
|
||||
card->dev->dev_port = card->info.portno;
|
||||
card->dev->ethtool_ops = &qeth_l3_ethtool_ops;
|
||||
card->dev->features |= NETIF_F_HW_VLAN_CTAG_TX |
|
||||
NETIF_F_HW_VLAN_CTAG_RX |
|
||||
|
|
@ -2960,9 +2830,6 @@ static int qeth_l3_control_event(struct qeth_card *card,
|
|||
|
||||
struct qeth_discipline qeth_l3_discipline = {
|
||||
.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,
|
||||
.recover = qeth_l3_recover,
|
||||
.setup = qeth_l3_probe_device,
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user