mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-02 19:15:03 -04:00
Merge branch 's390-qeth-next'
Julian Wiedmann says: ==================== s390/qeth: updates 2019-06-27 please apply another round of qeth updates for net-next. This completes the conversion of the control path to use dynamically allocated cmd buffers, along with some fine-tuning for the route validation fix that recently went into -net. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
@@ -25,6 +25,8 @@
|
||||
#include <linux/wait.h>
|
||||
#include <linux/workqueue.h>
|
||||
|
||||
#include <net/dst.h>
|
||||
#include <net/ip6_fib.h>
|
||||
#include <net/ipv6.h>
|
||||
#include <net/if_inet6.h>
|
||||
#include <net/addrconf.h>
|
||||
@@ -60,7 +62,7 @@ struct qeth_dbf_info {
|
||||
debug_info_t *id;
|
||||
};
|
||||
|
||||
#define QETH_DBF_CTRL_LEN 256
|
||||
#define QETH_DBF_CTRL_LEN 256U
|
||||
|
||||
#define QETH_DBF_TEXT(name, level, text) \
|
||||
debug_text_event(qeth_dbf[QETH_DBF_##name].id, level, text)
|
||||
@@ -524,11 +526,6 @@ struct qeth_qdio_info {
|
||||
int default_out_queue;
|
||||
};
|
||||
|
||||
/**
|
||||
* buffer stuff for read channel
|
||||
*/
|
||||
#define QETH_CMD_BUFFER_NO 8
|
||||
|
||||
/**
|
||||
* channel state machine
|
||||
*/
|
||||
@@ -551,16 +548,11 @@ enum qeth_card_states {
|
||||
* Protocol versions
|
||||
*/
|
||||
enum qeth_prot_versions {
|
||||
QETH_PROT_NONE = 0x0000,
|
||||
QETH_PROT_IPV4 = 0x0004,
|
||||
QETH_PROT_IPV6 = 0x0006,
|
||||
};
|
||||
|
||||
enum qeth_cmd_buffer_state {
|
||||
BUF_STATE_FREE,
|
||||
BUF_STATE_LOCKED,
|
||||
BUF_STATE_MALLOC,
|
||||
};
|
||||
|
||||
enum qeth_cq {
|
||||
QETH_CQ_DISABLED = 0,
|
||||
QETH_CQ_ENABLED = 1,
|
||||
@@ -574,18 +566,20 @@ struct qeth_ipato {
|
||||
struct list_head entries;
|
||||
};
|
||||
|
||||
struct qeth_channel;
|
||||
struct qeth_channel {
|
||||
struct ccw_device *ccwdev;
|
||||
enum qeth_channel_states state;
|
||||
atomic_t irq_pending;
|
||||
};
|
||||
|
||||
struct qeth_cmd_buffer {
|
||||
enum qeth_cmd_buffer_state state;
|
||||
unsigned int length;
|
||||
refcount_t ref_count;
|
||||
struct qeth_channel *channel;
|
||||
struct qeth_reply *reply;
|
||||
long timeout;
|
||||
unsigned char *data;
|
||||
void (*finalize)(struct qeth_card *card, struct qeth_cmd_buffer *iob,
|
||||
unsigned int length);
|
||||
void (*finalize)(struct qeth_card *card, struct qeth_cmd_buffer *iob);
|
||||
void (*callback)(struct qeth_card *card, struct qeth_cmd_buffer *iob);
|
||||
};
|
||||
|
||||
@@ -599,25 +593,8 @@ static inline struct qeth_ipa_cmd *__ipa_cmd(struct qeth_cmd_buffer *iob)
|
||||
return (struct qeth_ipa_cmd *)(iob->data + IPA_PDU_HEADER_SIZE);
|
||||
}
|
||||
|
||||
/**
|
||||
* definition of a qeth channel, used for read and write
|
||||
*/
|
||||
struct qeth_channel {
|
||||
enum qeth_channel_states state;
|
||||
struct ccw1 *ccw;
|
||||
spinlock_t iob_lock;
|
||||
wait_queue_head_t wait_q;
|
||||
struct ccw_device *ccwdev;
|
||||
/*command buffer for control data*/
|
||||
struct qeth_cmd_buffer iob[QETH_CMD_BUFFER_NO];
|
||||
atomic_t irq_pending;
|
||||
int io_buf_no;
|
||||
};
|
||||
|
||||
static inline struct ccw1 *__ccw_from_cmd(struct qeth_cmd_buffer *iob)
|
||||
{
|
||||
if (iob->state != BUF_STATE_MALLOC)
|
||||
return iob->channel->ccw;
|
||||
return (struct ccw1 *)(iob->data + ALIGN(iob->length, 8));
|
||||
}
|
||||
|
||||
@@ -738,9 +715,6 @@ struct qeth_discipline {
|
||||
void (*remove) (struct ccwgroup_device *);
|
||||
int (*set_online) (struct ccwgroup_device *);
|
||||
int (*set_offline) (struct ccwgroup_device *);
|
||||
int (*freeze)(struct ccwgroup_device *);
|
||||
int (*thaw) (struct ccwgroup_device *);
|
||||
int (*restore)(struct ccwgroup_device *);
|
||||
int (*do_ioctl)(struct net_device *dev, struct ifreq *rq, int cmd);
|
||||
int (*control_event_handler)(struct qeth_card *card,
|
||||
struct qeth_ipa_cmd *cmd);
|
||||
@@ -905,6 +879,17 @@ static inline int qeth_get_ether_cast_type(struct sk_buff *skb)
|
||||
return RTN_UNICAST;
|
||||
}
|
||||
|
||||
static inline struct dst_entry *qeth_dst_check_rcu(struct sk_buff *skb, int ipv)
|
||||
{
|
||||
struct dst_entry *dst = skb_dst(skb);
|
||||
struct rt6_info *rt;
|
||||
|
||||
rt = (struct rt6_info *) dst;
|
||||
if (dst)
|
||||
dst = dst_check(dst, (ipv == 6) ? rt6_get_cookie(rt) : 0);
|
||||
return dst;
|
||||
}
|
||||
|
||||
static inline void qeth_rx_csum(struct qeth_card *card, struct sk_buff *skb,
|
||||
u8 flags)
|
||||
{
|
||||
@@ -939,12 +924,12 @@ static inline int qeth_is_diagass_supported(struct qeth_card *card,
|
||||
|
||||
int qeth_send_simple_setassparms_prot(struct qeth_card *card,
|
||||
enum qeth_ipa_funcs ipa_func,
|
||||
u16 cmd_code, long data,
|
||||
u16 cmd_code, u32 *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)
|
||||
u16 cmd_code, u32 *data)
|
||||
{
|
||||
return qeth_send_simple_setassparms_prot(card, ipa_func, cmd_code,
|
||||
data, QETH_PROT_IPV4);
|
||||
@@ -952,7 +937,7 @@ static inline int qeth_send_simple_setassparms(struct qeth_card *card,
|
||||
|
||||
static inline int qeth_send_simple_setassparms_v6(struct qeth_card *card,
|
||||
enum qeth_ipa_funcs ipa_func,
|
||||
u16 cmd_code, long data)
|
||||
u16 cmd_code, u32 *data)
|
||||
{
|
||||
return qeth_send_simple_setassparms_prot(card, ipa_func, cmd_code,
|
||||
data, QETH_PROT_IPV6);
|
||||
@@ -993,8 +978,23 @@ int qeth_send_ipa_cmd(struct qeth_card *, struct qeth_cmd_buffer *,
|
||||
int (*reply_cb)
|
||||
(struct qeth_card *, struct qeth_reply *, unsigned long),
|
||||
void *);
|
||||
struct qeth_cmd_buffer *qeth_get_ipacmd_buffer(struct qeth_card *,
|
||||
enum qeth_ipa_cmds, enum qeth_prot_versions);
|
||||
struct qeth_cmd_buffer *qeth_ipa_alloc_cmd(struct qeth_card *card,
|
||||
enum qeth_ipa_cmds cmd_code,
|
||||
enum qeth_prot_versions prot,
|
||||
unsigned int data_length);
|
||||
struct qeth_cmd_buffer *qeth_alloc_cmd(struct qeth_channel *channel,
|
||||
unsigned int length, unsigned int ccws,
|
||||
long timeout);
|
||||
struct qeth_cmd_buffer *qeth_get_setassparms_cmd(struct qeth_card *card,
|
||||
enum qeth_ipa_funcs ipa_func,
|
||||
u16 cmd_code,
|
||||
unsigned int data_length,
|
||||
enum qeth_prot_versions prot);
|
||||
struct qeth_cmd_buffer *qeth_get_diag_cmd(struct qeth_card *card,
|
||||
enum qeth_diags_cmds sub_cmd,
|
||||
unsigned int data_length);
|
||||
void qeth_put_cmd(struct qeth_cmd_buffer *iob);
|
||||
|
||||
struct sk_buff *qeth_core_get_next_skb(struct qeth_card *,
|
||||
struct qeth_qdio_buffer *, struct qdio_buffer_element **, int *,
|
||||
struct qeth_hdr **);
|
||||
@@ -1003,16 +1003,13 @@ int qeth_poll(struct napi_struct *napi, int budget);
|
||||
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 *);
|
||||
void qeth_clear_cmd_buffers(struct qeth_channel *);
|
||||
void qeth_drain_output_queues(struct qeth_card *card);
|
||||
void qeth_setadp_promisc_mode(struct qeth_card *);
|
||||
int qeth_setadpparms_change_macaddr(struct qeth_card *);
|
||||
void qeth_tx_timeout(struct net_device *);
|
||||
void qeth_release_buffer(struct qeth_cmd_buffer *iob);
|
||||
void qeth_notify_reply(struct qeth_reply *reply, int reason);
|
||||
void qeth_prepare_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob,
|
||||
u16 cmd_length);
|
||||
struct qeth_cmd_buffer *qeth_get_buffer(struct qeth_channel *channel);
|
||||
int qeth_query_switch_attributes(struct qeth_card *card,
|
||||
struct qeth_switch_info *sw_info);
|
||||
int qeth_query_card_info(struct qeth_card *card,
|
||||
@@ -1029,10 +1026,6 @@ int qeth_configure_cq(struct qeth_card *, enum qeth_cq);
|
||||
int qeth_hw_trap(struct qeth_card *, enum qeth_diags_trap_action);
|
||||
void qeth_trace_features(struct qeth_card *);
|
||||
int qeth_setassparms_cb(struct qeth_card *, struct qeth_reply *, unsigned long);
|
||||
struct qeth_cmd_buffer *qeth_get_setassparms_cmd(struct qeth_card *,
|
||||
enum qeth_ipa_funcs,
|
||||
__u16, __u16,
|
||||
enum qeth_prot_versions);
|
||||
int qeth_set_features(struct net_device *, netdev_features_t);
|
||||
void qeth_enable_hw_features(struct net_device *dev);
|
||||
netdev_features_t qeth_fix_features(struct net_device *, netdev_features_t);
|
||||
@@ -1047,11 +1040,10 @@ int qeth_stop(struct net_device *dev);
|
||||
|
||||
int qeth_vm_request_mac(struct qeth_card *card);
|
||||
int qeth_xmit(struct qeth_card *card, struct sk_buff *skb,
|
||||
struct qeth_qdio_out_q *queue, int ipv, int cast_type,
|
||||
struct qeth_qdio_out_q *queue, int ipv,
|
||||
void (*fill_header)(struct qeth_qdio_out_q *queue,
|
||||
struct qeth_hdr *hdr, struct sk_buff *skb,
|
||||
int ipv, int cast_type,
|
||||
unsigned int data_len));
|
||||
int ipv, unsigned int data_len));
|
||||
|
||||
/* exports for OSN */
|
||||
int qeth_osn_assist(struct net_device *, void *, int);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -379,9 +379,7 @@ struct qeth_ipacmd_layer2setdelvlan {
|
||||
__u16 vlan_id;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
|
||||
struct qeth_ipacmd_setassparms_hdr {
|
||||
__u32 assist_no;
|
||||
__u16 length;
|
||||
__u16 command_code;
|
||||
__u16 return_code;
|
||||
@@ -426,6 +424,7 @@ struct qeth_tso_start_data {
|
||||
|
||||
/* SETASSPARMS IPA Command: */
|
||||
struct qeth_ipacmd_setassparms {
|
||||
u32 assist_no;
|
||||
struct qeth_ipacmd_setassparms_hdr hdr;
|
||||
union {
|
||||
__u32 flags_32bit;
|
||||
@@ -437,6 +436,8 @@ struct qeth_ipacmd_setassparms {
|
||||
} data;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
#define SETASS_DATA_SIZEOF(field) FIELD_SIZEOF(struct qeth_ipacmd_setassparms,\
|
||||
data.field)
|
||||
|
||||
/* SETRTG IPA Command: ****************************************************/
|
||||
struct qeth_set_routing {
|
||||
@@ -524,8 +525,6 @@ struct qeth_query_switch_attributes {
|
||||
#define QETH_SETADP_FLAGS_VIRTUAL_MAC 0x80 /* for CHANGE_ADDR_READ_MAC */
|
||||
|
||||
struct qeth_ipacmd_setadpparms_hdr {
|
||||
u32 supp_hw_cmds;
|
||||
u32 reserved1;
|
||||
u16 cmdlength;
|
||||
u16 reserved2;
|
||||
u32 command_code;
|
||||
@@ -537,6 +536,7 @@ struct qeth_ipacmd_setadpparms_hdr {
|
||||
};
|
||||
|
||||
struct qeth_ipacmd_setadpparms {
|
||||
struct qeth_ipa_caps hw_cmds;
|
||||
struct qeth_ipacmd_setadpparms_hdr hdr;
|
||||
union {
|
||||
struct qeth_query_cmds_supp query_cmds_supp;
|
||||
@@ -550,6 +550,9 @@ struct qeth_ipacmd_setadpparms {
|
||||
} data;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
#define SETADP_DATA_SIZEOF(field) FIELD_SIZEOF(struct qeth_ipacmd_setadpparms,\
|
||||
data.field)
|
||||
|
||||
/* CREATE_ADDR IPA Command: ***********************************************/
|
||||
struct qeth_create_destroy_address {
|
||||
__u8 unique_id[8];
|
||||
@@ -596,6 +599,11 @@ struct qeth_ipacmd_diagass {
|
||||
__u8 cdata[64];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
#define DIAG_HDR_LEN offsetofend(struct qeth_ipacmd_diagass, ext)
|
||||
#define DIAG_SUB_HDR_LEN (offsetofend(struct qeth_ipacmd_diagass, ext) -\
|
||||
offsetof(struct qeth_ipacmd_diagass, \
|
||||
subcmd_len))
|
||||
|
||||
/* VNIC Characteristics IPA Command: *****************************************/
|
||||
/* IPA commands/sub commands for VNICC */
|
||||
#define IPA_VNICC_QUERY_CHARS 0x00000000L
|
||||
@@ -622,12 +630,6 @@ struct qeth_ipacmd_diagass {
|
||||
|
||||
/* VNICC header */
|
||||
struct qeth_ipacmd_vnicc_hdr {
|
||||
u32 sup;
|
||||
u32 cur;
|
||||
};
|
||||
|
||||
/* VNICC sub command header */
|
||||
struct qeth_vnicc_sub_hdr {
|
||||
u16 data_length;
|
||||
u16 reserved;
|
||||
u32 sub_command;
|
||||
@@ -652,15 +654,18 @@ struct qeth_vnicc_getset_timeout {
|
||||
|
||||
/* complete VNICC IPA command message */
|
||||
struct qeth_ipacmd_vnicc {
|
||||
struct qeth_ipa_caps vnicc_cmds;
|
||||
struct qeth_ipacmd_vnicc_hdr hdr;
|
||||
struct qeth_vnicc_sub_hdr sub_hdr;
|
||||
union {
|
||||
struct qeth_vnicc_query_cmds query_cmds;
|
||||
struct qeth_vnicc_set_char set_char;
|
||||
struct qeth_vnicc_getset_timeout getset_timeout;
|
||||
};
|
||||
} data;
|
||||
};
|
||||
|
||||
#define VNICC_DATA_SIZEOF(field) FIELD_SIZEOF(struct qeth_ipacmd_vnicc,\
|
||||
data.field)
|
||||
|
||||
/* SETBRIDGEPORT IPA Command: *********************************************/
|
||||
enum qeth_ipa_sbp_cmd {
|
||||
IPA_SBP_QUERY_COMMANDS_SUPPORTED = 0x00000000L,
|
||||
@@ -686,8 +691,6 @@ struct mac_addr_lnid {
|
||||
} __packed;
|
||||
|
||||
struct qeth_ipacmd_sbp_hdr {
|
||||
__u32 supported_sbp_cmds;
|
||||
__u32 enabled_sbp_cmds;
|
||||
__u16 cmdlength;
|
||||
__u16 reserved1;
|
||||
__u32 command_code;
|
||||
@@ -702,16 +705,10 @@ struct qeth_sbp_query_cmds_supp {
|
||||
__u32 reserved;
|
||||
} __packed;
|
||||
|
||||
struct qeth_sbp_reset_role {
|
||||
} __packed;
|
||||
|
||||
struct qeth_sbp_set_primary {
|
||||
struct net_if_token token;
|
||||
} __packed;
|
||||
|
||||
struct qeth_sbp_set_secondary {
|
||||
} __packed;
|
||||
|
||||
struct qeth_sbp_port_entry {
|
||||
__u8 role;
|
||||
__u8 state;
|
||||
@@ -737,17 +734,19 @@ struct qeth_sbp_state_change {
|
||||
} __packed;
|
||||
|
||||
struct qeth_ipacmd_setbridgeport {
|
||||
struct qeth_ipa_caps sbp_cmds;
|
||||
struct qeth_ipacmd_sbp_hdr hdr;
|
||||
union {
|
||||
struct qeth_sbp_query_cmds_supp query_cmds_supp;
|
||||
struct qeth_sbp_reset_role reset_role;
|
||||
struct qeth_sbp_set_primary set_primary;
|
||||
struct qeth_sbp_set_secondary set_secondary;
|
||||
struct qeth_sbp_query_ports query_ports;
|
||||
struct qeth_sbp_state_change state_change;
|
||||
} data;
|
||||
} __packed;
|
||||
|
||||
#define SBP_DATA_SIZEOF(field) FIELD_SIZEOF(struct qeth_ipacmd_setbridgeport,\
|
||||
data.field)
|
||||
|
||||
/* ADDRESS_CHANGE_NOTIFICATION adapter-initiated "command" *******************/
|
||||
/* Bitmask for entry->change_code. Both bits may be raised. */
|
||||
enum qeth_ipa_addr_change_code {
|
||||
@@ -806,6 +805,8 @@ struct qeth_ipa_cmd {
|
||||
} data;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
#define IPA_DATA_SIZEOF(field) FIELD_SIZEOF(struct qeth_ipa_cmd, data.field)
|
||||
|
||||
/*
|
||||
* special command for ARP processing.
|
||||
* this is not included in setassparms command before, because we get
|
||||
@@ -823,10 +824,6 @@ enum qeth_ipa_arp_return_codes {
|
||||
extern const char *qeth_get_ipa_msg(enum qeth_ipa_return_codes rc);
|
||||
extern const char *qeth_get_ipa_cmd_name(enum qeth_ipa_cmds cmd);
|
||||
|
||||
#define QETH_SETADP_BASE_LEN (sizeof(struct qeth_ipacmd_hdr) + \
|
||||
sizeof(struct qeth_ipacmd_setadpparms_hdr))
|
||||
#define QETH_SNMP_SETADP_CMDLENGTH 16
|
||||
|
||||
/* Helper functions */
|
||||
#define IS_IPA_REPLY(cmd) ((cmd->hdr.initiator == IPA_CMD_INITIATOR_HOST) || \
|
||||
(cmd->hdr.initiator == IPA_CMD_INITIATOR_OSA_REPLY))
|
||||
|
||||
@@ -85,7 +85,8 @@ static int qeth_l2_send_setdelmac(struct qeth_card *card, __u8 *mac,
|
||||
struct qeth_cmd_buffer *iob;
|
||||
|
||||
QETH_CARD_TEXT(card, 2, "L2sdmac");
|
||||
iob = qeth_get_ipacmd_buffer(card, ipacmd, QETH_PROT_IPV4);
|
||||
iob = qeth_ipa_alloc_cmd(card, ipacmd, QETH_PROT_IPV4,
|
||||
IPA_DATA_SIZEOF(setdelmac));
|
||||
if (!iob)
|
||||
return -ENOMEM;
|
||||
cmd = __ipa_cmd(iob);
|
||||
@@ -163,8 +164,9 @@ static void qeth_l2_drain_rx_mode_cache(struct qeth_card *card)
|
||||
|
||||
static void qeth_l2_fill_header(struct qeth_qdio_out_q *queue,
|
||||
struct qeth_hdr *hdr, struct sk_buff *skb,
|
||||
int ipv, int cast_type, unsigned int data_len)
|
||||
int ipv, unsigned int data_len)
|
||||
{
|
||||
int cast_type = qeth_get_ether_cast_type(skb);
|
||||
struct vlan_ethhdr *veth = vlan_eth_hdr(skb);
|
||||
|
||||
hdr->hdr.l2.pkt_length = data_len;
|
||||
@@ -240,7 +242,8 @@ static int qeth_l2_send_setdelvlan(struct qeth_card *card, __u16 i,
|
||||
struct qeth_cmd_buffer *iob;
|
||||
|
||||
QETH_CARD_TEXT_(card, 4, "L2sdv%x", ipacmd);
|
||||
iob = qeth_get_ipacmd_buffer(card, ipacmd, QETH_PROT_IPV4);
|
||||
iob = qeth_ipa_alloc_cmd(card, ipacmd, QETH_PROT_IPV4,
|
||||
IPA_DATA_SIZEOF(setdelvlan));
|
||||
if (!iob)
|
||||
return -ENOMEM;
|
||||
cmd = __ipa_cmd(iob);
|
||||
@@ -292,7 +295,6 @@ static void qeth_l2_stop_card(struct qeth_card *card)
|
||||
card->state = CARD_STATE_DOWN;
|
||||
}
|
||||
|
||||
qeth_clear_cmd_buffers(&card->write);
|
||||
flush_workqueue(card->event_wq);
|
||||
card->info.mac_bits &= ~QETH_LAYER2_MAC_REGISTERED;
|
||||
}
|
||||
@@ -597,7 +599,6 @@ static netdev_tx_t qeth_l2_hard_start_xmit(struct sk_buff *skb,
|
||||
rc = qeth_l2_xmit_osn(card, skb, queue);
|
||||
else
|
||||
rc = qeth_xmit(card, skb, queue, qeth_get_ip_version(skb),
|
||||
qeth_get_ether_cast_type(skb),
|
||||
qeth_l2_fill_header);
|
||||
|
||||
if (!rc) {
|
||||
@@ -964,33 +965,6 @@ static void __exit qeth_l2_exit(void)
|
||||
pr_info("unregister layer 2 discipline\n");
|
||||
}
|
||||
|
||||
static int qeth_l2_pm_suspend(struct ccwgroup_device *gdev)
|
||||
{
|
||||
struct qeth_card *card = dev_get_drvdata(&gdev->dev);
|
||||
|
||||
qeth_set_allowed_threads(card, 0, 1);
|
||||
wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0);
|
||||
if (gdev->state == CCWGROUP_OFFLINE)
|
||||
return 0;
|
||||
|
||||
qeth_l2_set_offline(gdev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qeth_l2_pm_resume(struct ccwgroup_device *gdev)
|
||||
{
|
||||
struct qeth_card *card = dev_get_drvdata(&gdev->dev);
|
||||
int rc;
|
||||
|
||||
rc = qeth_l2_set_online(gdev);
|
||||
|
||||
qeth_set_allowed_threads(card, 0xffffffff, 0);
|
||||
if (rc)
|
||||
dev_warn(&card->gdev->dev, "The qeth device driver "
|
||||
"failed to recover an error on the device\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Returns zero if the command is successfully "consumed" */
|
||||
static int qeth_l2_control_event(struct qeth_card *card,
|
||||
struct qeth_ipa_cmd *cmd)
|
||||
@@ -1020,9 +994,6 @@ struct qeth_discipline qeth_l2_discipline = {
|
||||
.remove = qeth_l2_remove_device,
|
||||
.set_online = qeth_l2_set_online,
|
||||
.set_offline = qeth_l2_set_offline,
|
||||
.freeze = qeth_l2_pm_suspend,
|
||||
.thaw = qeth_l2_pm_resume,
|
||||
.restore = qeth_l2_pm_resume,
|
||||
.do_ioctl = NULL,
|
||||
.control_event_handler = qeth_l2_control_event,
|
||||
};
|
||||
@@ -1032,7 +1003,7 @@ static void qeth_osn_assist_cb(struct qeth_card *card,
|
||||
struct qeth_cmd_buffer *iob)
|
||||
{
|
||||
qeth_notify_reply(iob->reply, 0);
|
||||
qeth_release_buffer(iob);
|
||||
qeth_put_cmd(iob);
|
||||
}
|
||||
|
||||
int qeth_osn_assist(struct net_device *dev, void *data, int data_len)
|
||||
@@ -1040,6 +1011,8 @@ int qeth_osn_assist(struct net_device *dev, void *data, int data_len)
|
||||
struct qeth_cmd_buffer *iob;
|
||||
struct qeth_card *card;
|
||||
|
||||
if (data_len < 0)
|
||||
return -EINVAL;
|
||||
if (!dev)
|
||||
return -ENODEV;
|
||||
card = dev->ml_priv;
|
||||
@@ -1048,7 +1021,9 @@ int qeth_osn_assist(struct net_device *dev, void *data, int data_len)
|
||||
QETH_CARD_TEXT(card, 2, "osnsdmc");
|
||||
if (!qeth_card_hw_is_reachable(card))
|
||||
return -ENODEV;
|
||||
iob = qeth_get_buffer(&card->write);
|
||||
|
||||
iob = qeth_alloc_cmd(&card->write, IPA_PDU_HEADER_SIZE + data_len, 1,
|
||||
QETH_IPA_TIMEOUT);
|
||||
if (!iob)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -1421,22 +1396,25 @@ static int qeth_bridgeport_makerc(struct qeth_card *card,
|
||||
|
||||
static struct qeth_cmd_buffer *qeth_sbp_build_cmd(struct qeth_card *card,
|
||||
enum qeth_ipa_sbp_cmd sbp_cmd,
|
||||
unsigned int cmd_length)
|
||||
unsigned int data_length)
|
||||
{
|
||||
enum qeth_ipa_cmds ipa_cmd = IS_IQD(card) ? IPA_CMD_SETBRIDGEPORT_IQD :
|
||||
IPA_CMD_SETBRIDGEPORT_OSA;
|
||||
struct qeth_ipacmd_sbp_hdr *hdr;
|
||||
struct qeth_cmd_buffer *iob;
|
||||
struct qeth_ipa_cmd *cmd;
|
||||
|
||||
iob = qeth_get_ipacmd_buffer(card, ipa_cmd, 0);
|
||||
iob = qeth_ipa_alloc_cmd(card, ipa_cmd, QETH_PROT_NONE,
|
||||
data_length +
|
||||
offsetof(struct qeth_ipacmd_setbridgeport,
|
||||
data));
|
||||
if (!iob)
|
||||
return iob;
|
||||
cmd = __ipa_cmd(iob);
|
||||
cmd->data.sbp.hdr.cmdlength = sizeof(struct qeth_ipacmd_sbp_hdr) +
|
||||
cmd_length;
|
||||
cmd->data.sbp.hdr.command_code = sbp_cmd;
|
||||
cmd->data.sbp.hdr.used_total = 1;
|
||||
cmd->data.sbp.hdr.seq_no = 1;
|
||||
|
||||
hdr = &__ipa_cmd(iob)->data.sbp.hdr;
|
||||
hdr->cmdlength = sizeof(*hdr) + data_length;
|
||||
hdr->command_code = sbp_cmd;
|
||||
hdr->used_total = 1;
|
||||
hdr->seq_no = 1;
|
||||
return iob;
|
||||
}
|
||||
|
||||
@@ -1471,7 +1449,7 @@ static void qeth_bridgeport_query_support(struct qeth_card *card)
|
||||
|
||||
QETH_CARD_TEXT(card, 2, "brqsuppo");
|
||||
iob = qeth_sbp_build_cmd(card, IPA_SBP_QUERY_COMMANDS_SUPPORTED,
|
||||
sizeof(struct qeth_sbp_query_cmds_supp));
|
||||
SBP_DATA_SIZEOF(query_cmds_supp));
|
||||
if (!iob)
|
||||
return;
|
||||
|
||||
@@ -1563,23 +1541,21 @@ static int qeth_bridgeport_set_cb(struct qeth_card *card,
|
||||
*/
|
||||
int qeth_bridgeport_setrole(struct qeth_card *card, enum qeth_sbp_roles role)
|
||||
{
|
||||
int cmdlength;
|
||||
struct qeth_cmd_buffer *iob;
|
||||
enum qeth_ipa_sbp_cmd setcmd;
|
||||
unsigned int cmdlength = 0;
|
||||
|
||||
QETH_CARD_TEXT(card, 2, "brsetrol");
|
||||
switch (role) {
|
||||
case QETH_SBP_ROLE_NONE:
|
||||
setcmd = IPA_SBP_RESET_BRIDGE_PORT_ROLE;
|
||||
cmdlength = sizeof(struct qeth_sbp_reset_role);
|
||||
break;
|
||||
case QETH_SBP_ROLE_PRIMARY:
|
||||
setcmd = IPA_SBP_SET_PRIMARY_BRIDGE_PORT;
|
||||
cmdlength = sizeof(struct qeth_sbp_set_primary);
|
||||
cmdlength = SBP_DATA_SIZEOF(set_primary);
|
||||
break;
|
||||
case QETH_SBP_ROLE_SECONDARY:
|
||||
setcmd = IPA_SBP_SET_SECONDARY_BRIDGE_PORT;
|
||||
cmdlength = sizeof(struct qeth_sbp_set_secondary);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
@@ -1728,10 +1704,6 @@ static int qeth_l2_vnicc_makerc(struct qeth_card *card, u16 ipa_rc)
|
||||
/* generic VNICC request call back control */
|
||||
struct _qeth_l2_vnicc_request_cbctl {
|
||||
u32 sub_cmd;
|
||||
struct {
|
||||
u32 vnic_char;
|
||||
u32 timeout;
|
||||
} param;
|
||||
struct {
|
||||
union{
|
||||
u32 *sup_cmds;
|
||||
@@ -1754,80 +1726,52 @@ static int qeth_l2_vnicc_request_cb(struct qeth_card *card,
|
||||
if (cmd->hdr.return_code)
|
||||
return qeth_l2_vnicc_makerc(card, cmd->hdr.return_code);
|
||||
/* return results to caller */
|
||||
card->options.vnicc.sup_chars = rep->hdr.sup;
|
||||
card->options.vnicc.cur_chars = rep->hdr.cur;
|
||||
card->options.vnicc.sup_chars = rep->vnicc_cmds.supported;
|
||||
card->options.vnicc.cur_chars = rep->vnicc_cmds.enabled;
|
||||
|
||||
if (cbctl->sub_cmd == IPA_VNICC_QUERY_CMDS)
|
||||
*cbctl->result.sup_cmds = rep->query_cmds.sup_cmds;
|
||||
*cbctl->result.sup_cmds = rep->data.query_cmds.sup_cmds;
|
||||
|
||||
if (cbctl->sub_cmd == IPA_VNICC_GET_TIMEOUT)
|
||||
*cbctl->result.timeout = rep->getset_timeout.timeout;
|
||||
*cbctl->result.timeout = rep->data.getset_timeout.timeout;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* generic VNICC request */
|
||||
static int qeth_l2_vnicc_request(struct qeth_card *card,
|
||||
struct _qeth_l2_vnicc_request_cbctl *cbctl)
|
||||
static struct qeth_cmd_buffer *qeth_l2_vnicc_build_cmd(struct qeth_card *card,
|
||||
u32 vnicc_cmd,
|
||||
unsigned int data_length)
|
||||
{
|
||||
struct qeth_ipacmd_vnicc *req;
|
||||
struct qeth_ipacmd_vnicc_hdr *hdr;
|
||||
struct qeth_cmd_buffer *iob;
|
||||
struct qeth_ipa_cmd *cmd;
|
||||
|
||||
QETH_CARD_TEXT(card, 2, "vniccreq");
|
||||
|
||||
/* get new buffer for request */
|
||||
iob = qeth_get_ipacmd_buffer(card, IPA_CMD_VNICC, 0);
|
||||
iob = qeth_ipa_alloc_cmd(card, IPA_CMD_VNICC, QETH_PROT_NONE,
|
||||
data_length +
|
||||
offsetof(struct qeth_ipacmd_vnicc, data));
|
||||
if (!iob)
|
||||
return -ENOMEM;
|
||||
return NULL;
|
||||
|
||||
/* create header for request */
|
||||
cmd = __ipa_cmd(iob);
|
||||
req = &cmd->data.vnicc;
|
||||
|
||||
/* create sub command header for request */
|
||||
req->sub_hdr.data_length = sizeof(req->sub_hdr);
|
||||
req->sub_hdr.sub_command = cbctl->sub_cmd;
|
||||
|
||||
/* create sub command specific request fields */
|
||||
switch (cbctl->sub_cmd) {
|
||||
case IPA_VNICC_QUERY_CHARS:
|
||||
break;
|
||||
case IPA_VNICC_QUERY_CMDS:
|
||||
req->sub_hdr.data_length += sizeof(req->query_cmds);
|
||||
req->query_cmds.vnic_char = cbctl->param.vnic_char;
|
||||
break;
|
||||
case IPA_VNICC_ENABLE:
|
||||
case IPA_VNICC_DISABLE:
|
||||
req->sub_hdr.data_length += sizeof(req->set_char);
|
||||
req->set_char.vnic_char = cbctl->param.vnic_char;
|
||||
break;
|
||||
case IPA_VNICC_SET_TIMEOUT:
|
||||
req->getset_timeout.timeout = cbctl->param.timeout;
|
||||
/* fallthrough */
|
||||
case IPA_VNICC_GET_TIMEOUT:
|
||||
req->sub_hdr.data_length += sizeof(req->getset_timeout);
|
||||
req->getset_timeout.vnic_char = cbctl->param.vnic_char;
|
||||
break;
|
||||
default:
|
||||
qeth_release_buffer(iob);
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
/* send request */
|
||||
return qeth_send_ipa_cmd(card, iob, qeth_l2_vnicc_request_cb, cbctl);
|
||||
hdr = &__ipa_cmd(iob)->data.vnicc.hdr;
|
||||
hdr->data_length = sizeof(*hdr) + data_length;
|
||||
hdr->sub_command = vnicc_cmd;
|
||||
return iob;
|
||||
}
|
||||
|
||||
/* VNICC query VNIC characteristics request */
|
||||
static int qeth_l2_vnicc_query_chars(struct qeth_card *card)
|
||||
{
|
||||
struct _qeth_l2_vnicc_request_cbctl cbctl;
|
||||
struct qeth_cmd_buffer *iob;
|
||||
|
||||
QETH_CARD_TEXT(card, 2, "vniccqch");
|
||||
iob = qeth_l2_vnicc_build_cmd(card, IPA_VNICC_QUERY_CHARS, 0);
|
||||
if (!iob)
|
||||
return -ENOMEM;
|
||||
|
||||
/* prepare callback control */
|
||||
cbctl.sub_cmd = IPA_VNICC_QUERY_CHARS;
|
||||
|
||||
QETH_CARD_TEXT(card, 2, "vniccqch");
|
||||
return qeth_l2_vnicc_request(card, &cbctl);
|
||||
return qeth_send_ipa_cmd(card, iob, qeth_l2_vnicc_request_cb, &cbctl);
|
||||
}
|
||||
|
||||
/* VNICC query sub commands request */
|
||||
@@ -1835,14 +1779,21 @@ static int qeth_l2_vnicc_query_cmds(struct qeth_card *card, u32 vnic_char,
|
||||
u32 *sup_cmds)
|
||||
{
|
||||
struct _qeth_l2_vnicc_request_cbctl cbctl;
|
||||
struct qeth_cmd_buffer *iob;
|
||||
|
||||
QETH_CARD_TEXT(card, 2, "vniccqcm");
|
||||
iob = qeth_l2_vnicc_build_cmd(card, IPA_VNICC_QUERY_CMDS,
|
||||
VNICC_DATA_SIZEOF(query_cmds));
|
||||
if (!iob)
|
||||
return -ENOMEM;
|
||||
|
||||
__ipa_cmd(iob)->data.vnicc.data.query_cmds.vnic_char = vnic_char;
|
||||
|
||||
/* prepare callback control */
|
||||
cbctl.sub_cmd = IPA_VNICC_QUERY_CMDS;
|
||||
cbctl.param.vnic_char = vnic_char;
|
||||
cbctl.result.sup_cmds = sup_cmds;
|
||||
|
||||
QETH_CARD_TEXT(card, 2, "vniccqcm");
|
||||
return qeth_l2_vnicc_request(card, &cbctl);
|
||||
return qeth_send_ipa_cmd(card, iob, qeth_l2_vnicc_request_cb, &cbctl);
|
||||
}
|
||||
|
||||
/* VNICC enable/disable characteristic request */
|
||||
@@ -1850,31 +1801,47 @@ static int qeth_l2_vnicc_set_char(struct qeth_card *card, u32 vnic_char,
|
||||
u32 cmd)
|
||||
{
|
||||
struct _qeth_l2_vnicc_request_cbctl cbctl;
|
||||
struct qeth_cmd_buffer *iob;
|
||||
|
||||
QETH_CARD_TEXT(card, 2, "vniccedc");
|
||||
iob = qeth_l2_vnicc_build_cmd(card, cmd, VNICC_DATA_SIZEOF(set_char));
|
||||
if (!iob)
|
||||
return -ENOMEM;
|
||||
|
||||
__ipa_cmd(iob)->data.vnicc.data.set_char.vnic_char = vnic_char;
|
||||
|
||||
/* prepare callback control */
|
||||
cbctl.sub_cmd = cmd;
|
||||
cbctl.param.vnic_char = vnic_char;
|
||||
|
||||
QETH_CARD_TEXT(card, 2, "vniccedc");
|
||||
return qeth_l2_vnicc_request(card, &cbctl);
|
||||
return qeth_send_ipa_cmd(card, iob, qeth_l2_vnicc_request_cb, &cbctl);
|
||||
}
|
||||
|
||||
/* VNICC get/set timeout for characteristic request */
|
||||
static int qeth_l2_vnicc_getset_timeout(struct qeth_card *card, u32 vnicc,
|
||||
u32 cmd, u32 *timeout)
|
||||
{
|
||||
struct qeth_vnicc_getset_timeout *getset_timeout;
|
||||
struct _qeth_l2_vnicc_request_cbctl cbctl;
|
||||
struct qeth_cmd_buffer *iob;
|
||||
|
||||
QETH_CARD_TEXT(card, 2, "vniccgst");
|
||||
iob = qeth_l2_vnicc_build_cmd(card, cmd,
|
||||
VNICC_DATA_SIZEOF(getset_timeout));
|
||||
if (!iob)
|
||||
return -ENOMEM;
|
||||
|
||||
getset_timeout = &__ipa_cmd(iob)->data.vnicc.data.getset_timeout;
|
||||
getset_timeout->vnic_char = vnicc;
|
||||
|
||||
if (cmd == IPA_VNICC_SET_TIMEOUT)
|
||||
getset_timeout->timeout = *timeout;
|
||||
|
||||
/* prepare callback control */
|
||||
cbctl.sub_cmd = cmd;
|
||||
cbctl.param.vnic_char = vnicc;
|
||||
if (cmd == IPA_VNICC_SET_TIMEOUT)
|
||||
cbctl.param.timeout = *timeout;
|
||||
if (cmd == IPA_VNICC_GET_TIMEOUT)
|
||||
cbctl.result.timeout = timeout;
|
||||
|
||||
QETH_CARD_TEXT(card, 2, "vniccgst");
|
||||
return qeth_l2_vnicc_request(card, &cbctl);
|
||||
return qeth_send_ipa_cmd(card, iob, qeth_l2_vnicc_request_cb, &cbctl);
|
||||
}
|
||||
|
||||
/* set current VNICC flag state; called from sysfs store function */
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
#include <net/route.h>
|
||||
#include <net/ipv6.h>
|
||||
#include <net/ip6_route.h>
|
||||
#include <net/ip6_fib.h>
|
||||
#include <net/iucv/af_iucv.h>
|
||||
#include <linux/hashtable.h>
|
||||
|
||||
@@ -377,7 +376,8 @@ static int qeth_l3_send_setdelmc(struct qeth_card *card,
|
||||
|
||||
QETH_CARD_TEXT(card, 4, "setdelmc");
|
||||
|
||||
iob = qeth_get_ipacmd_buffer(card, ipacmd, addr->proto);
|
||||
iob = qeth_ipa_alloc_cmd(card, ipacmd, addr->proto,
|
||||
IPA_DATA_SIZEOF(setdelipm));
|
||||
if (!iob)
|
||||
return -ENOMEM;
|
||||
cmd = __ipa_cmd(iob);
|
||||
@@ -429,7 +429,8 @@ static int qeth_l3_send_setdelip(struct qeth_card *card,
|
||||
|
||||
QETH_CARD_TEXT(card, 4, "setdelip");
|
||||
|
||||
iob = qeth_get_ipacmd_buffer(card, ipacmd, addr->proto);
|
||||
iob = qeth_ipa_alloc_cmd(card, ipacmd, addr->proto,
|
||||
IPA_DATA_SIZEOF(setdelip6));
|
||||
if (!iob)
|
||||
return -ENOMEM;
|
||||
cmd = __ipa_cmd(iob);
|
||||
@@ -461,7 +462,8 @@ static int qeth_l3_send_setrouting(struct qeth_card *card,
|
||||
struct qeth_cmd_buffer *iob;
|
||||
|
||||
QETH_CARD_TEXT(card, 4, "setroutg");
|
||||
iob = qeth_get_ipacmd_buffer(card, IPA_CMD_SETRTG, prot);
|
||||
iob = qeth_ipa_alloc_cmd(card, IPA_CMD_SETRTG, prot,
|
||||
IPA_DATA_SIZEOF(setrtg));
|
||||
if (!iob)
|
||||
return -ENOMEM;
|
||||
cmd = __ipa_cmd(iob);
|
||||
@@ -767,7 +769,7 @@ static int qeth_l3_start_ipa_arp_processing(struct qeth_card *card)
|
||||
return 0;
|
||||
}
|
||||
rc = qeth_send_simple_setassparms(card, IPA_ARP_PROCESSING,
|
||||
IPA_CMD_ASS_START, 0);
|
||||
IPA_CMD_ASS_START, NULL);
|
||||
if (rc) {
|
||||
dev_warn(&card->gdev->dev,
|
||||
"Starting ARP processing support for %s failed\n",
|
||||
@@ -790,7 +792,7 @@ static int qeth_l3_start_ipa_source_mac(struct qeth_card *card)
|
||||
}
|
||||
|
||||
rc = qeth_send_simple_setassparms(card, IPA_SOURCE_MAC,
|
||||
IPA_CMD_ASS_START, 0);
|
||||
IPA_CMD_ASS_START, NULL);
|
||||
if (rc)
|
||||
dev_warn(&card->gdev->dev,
|
||||
"Starting source MAC-address support for %s failed\n",
|
||||
@@ -811,7 +813,7 @@ static int qeth_l3_start_ipa_vlan(struct qeth_card *card)
|
||||
}
|
||||
|
||||
rc = qeth_send_simple_setassparms(card, IPA_VLAN_PRIO,
|
||||
IPA_CMD_ASS_START, 0);
|
||||
IPA_CMD_ASS_START, NULL);
|
||||
if (rc) {
|
||||
dev_warn(&card->gdev->dev,
|
||||
"Starting VLAN support for %s failed\n",
|
||||
@@ -836,7 +838,7 @@ static int qeth_l3_start_ipa_multicast(struct qeth_card *card)
|
||||
}
|
||||
|
||||
rc = qeth_send_simple_setassparms(card, IPA_MULTICASTING,
|
||||
IPA_CMD_ASS_START, 0);
|
||||
IPA_CMD_ASS_START, NULL);
|
||||
if (rc) {
|
||||
dev_warn(&card->gdev->dev,
|
||||
"Starting multicast support for %s failed\n",
|
||||
@@ -850,6 +852,7 @@ static int qeth_l3_start_ipa_multicast(struct qeth_card *card)
|
||||
|
||||
static int qeth_l3_softsetup_ipv6(struct qeth_card *card)
|
||||
{
|
||||
u32 ipv6_data = 3;
|
||||
int rc;
|
||||
|
||||
QETH_CARD_TEXT(card, 3, "softipv6");
|
||||
@@ -857,16 +860,16 @@ static int qeth_l3_softsetup_ipv6(struct qeth_card *card)
|
||||
if (IS_IQD(card))
|
||||
goto out;
|
||||
|
||||
rc = qeth_send_simple_setassparms(card, IPA_IPV6,
|
||||
IPA_CMD_ASS_START, 3);
|
||||
rc = qeth_send_simple_setassparms(card, IPA_IPV6, IPA_CMD_ASS_START,
|
||||
&ipv6_data);
|
||||
if (rc) {
|
||||
dev_err(&card->gdev->dev,
|
||||
"Activating IPv6 support for %s failed\n",
|
||||
QETH_CARD_IFNAME(card));
|
||||
return rc;
|
||||
}
|
||||
rc = qeth_send_simple_setassparms_v6(card, IPA_IPV6,
|
||||
IPA_CMD_ASS_START, 0);
|
||||
rc = qeth_send_simple_setassparms_v6(card, IPA_IPV6, IPA_CMD_ASS_START,
|
||||
NULL);
|
||||
if (rc) {
|
||||
dev_err(&card->gdev->dev,
|
||||
"Activating IPv6 support for %s failed\n",
|
||||
@@ -874,7 +877,7 @@ static int qeth_l3_softsetup_ipv6(struct qeth_card *card)
|
||||
return rc;
|
||||
}
|
||||
rc = qeth_send_simple_setassparms_v6(card, IPA_PASSTHRU,
|
||||
IPA_CMD_ASS_START, 0);
|
||||
IPA_CMD_ASS_START, NULL);
|
||||
if (rc) {
|
||||
dev_warn(&card->gdev->dev,
|
||||
"Enabling the passthrough mode for %s failed\n",
|
||||
@@ -900,6 +903,7 @@ static int qeth_l3_start_ipa_ipv6(struct qeth_card *card)
|
||||
|
||||
static int qeth_l3_start_ipa_broadcast(struct qeth_card *card)
|
||||
{
|
||||
u32 filter_data = 1;
|
||||
int rc;
|
||||
|
||||
QETH_CARD_TEXT(card, 3, "stbrdcst");
|
||||
@@ -912,7 +916,7 @@ static int qeth_l3_start_ipa_broadcast(struct qeth_card *card)
|
||||
goto out;
|
||||
}
|
||||
rc = qeth_send_simple_setassparms(card, IPA_FILTERING,
|
||||
IPA_CMD_ASS_START, 0);
|
||||
IPA_CMD_ASS_START, NULL);
|
||||
if (rc) {
|
||||
dev_warn(&card->gdev->dev, "Enabling broadcast filtering for "
|
||||
"%s failed\n", QETH_CARD_IFNAME(card));
|
||||
@@ -920,7 +924,7 @@ static int qeth_l3_start_ipa_broadcast(struct qeth_card *card)
|
||||
}
|
||||
|
||||
rc = qeth_send_simple_setassparms(card, IPA_FILTERING,
|
||||
IPA_CMD_ASS_CONFIGURE, 1);
|
||||
IPA_CMD_ASS_CONFIGURE, &filter_data);
|
||||
if (rc) {
|
||||
dev_warn(&card->gdev->dev,
|
||||
"Setting up broadcast filtering for %s failed\n",
|
||||
@@ -930,7 +934,7 @@ static int qeth_l3_start_ipa_broadcast(struct qeth_card *card)
|
||||
card->info.broadcast_capable = QETH_BROADCAST_WITH_ECHO;
|
||||
dev_info(&card->gdev->dev, "Broadcast enabled\n");
|
||||
rc = qeth_send_simple_setassparms(card, IPA_FILTERING,
|
||||
IPA_CMD_ASS_ENABLE, 1);
|
||||
IPA_CMD_ASS_ENABLE, &filter_data);
|
||||
if (rc) {
|
||||
dev_warn(&card->gdev->dev, "Setting up broadcast echo "
|
||||
"filtering for %s failed\n", QETH_CARD_IFNAME(card));
|
||||
@@ -981,8 +985,8 @@ static int qeth_l3_iqd_read_initial_mac(struct qeth_card *card)
|
||||
|
||||
QETH_CARD_TEXT(card, 2, "hsrmac");
|
||||
|
||||
iob = qeth_get_ipacmd_buffer(card, IPA_CMD_CREATE_ADDR,
|
||||
QETH_PROT_IPV6);
|
||||
iob = qeth_ipa_alloc_cmd(card, IPA_CMD_CREATE_ADDR, QETH_PROT_IPV6,
|
||||
IPA_DATA_SIZEOF(create_destroy_addr));
|
||||
if (!iob)
|
||||
return -ENOMEM;
|
||||
cmd = __ipa_cmd(iob);
|
||||
@@ -1025,8 +1029,8 @@ static int qeth_l3_get_unique_id(struct qeth_card *card)
|
||||
return 0;
|
||||
}
|
||||
|
||||
iob = qeth_get_ipacmd_buffer(card, IPA_CMD_CREATE_ADDR,
|
||||
QETH_PROT_IPV6);
|
||||
iob = qeth_ipa_alloc_cmd(card, IPA_CMD_CREATE_ADDR, QETH_PROT_IPV6,
|
||||
IPA_DATA_SIZEOF(create_destroy_addr));
|
||||
if (!iob)
|
||||
return -ENOMEM;
|
||||
cmd = __ipa_cmd(iob);
|
||||
@@ -1102,12 +1106,10 @@ qeth_diags_trace(struct qeth_card *card, enum qeth_diags_trace_cmds diags_cmd)
|
||||
|
||||
QETH_CARD_TEXT(card, 2, "diagtrac");
|
||||
|
||||
iob = qeth_get_ipacmd_buffer(card, IPA_CMD_SET_DIAG_ASS, 0);
|
||||
iob = qeth_get_diag_cmd(card, QETH_DIAGS_CMD_TRACE, 0);
|
||||
if (!iob)
|
||||
return -ENOMEM;
|
||||
cmd = __ipa_cmd(iob);
|
||||
cmd->data.diagass.subcmd_len = 16;
|
||||
cmd->data.diagass.subcmd = QETH_DIAGS_CMD_TRACE;
|
||||
cmd->data.diagass.type = QETH_DIAGS_TYPE_HIPERSOCKET;
|
||||
cmd->data.diagass.action = diags_cmd;
|
||||
return qeth_send_ipa_cmd(card, iob, qeth_diags_trace_cb, NULL);
|
||||
@@ -1309,6 +1311,15 @@ static int qeth_l3_vlan_rx_kill_vid(struct net_device *dev,
|
||||
static void qeth_l3_rebuild_skb(struct qeth_card *card, struct sk_buff *skb,
|
||||
struct qeth_hdr *hdr)
|
||||
{
|
||||
struct af_iucv_trans_hdr *iucv = (struct af_iucv_trans_hdr *) skb->data;
|
||||
struct net_device *dev = skb->dev;
|
||||
|
||||
if (IS_IQD(card) && iucv->magic == ETH_P_AF_IUCV) {
|
||||
dev_hard_header(skb, dev, ETH_P_AF_IUCV, dev->dev_addr,
|
||||
"FAKELL", skb->len);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(hdr->hdr.l3.flags & QETH_HDR_PASSTHRU)) {
|
||||
u16 prot = (hdr->hdr.l3.flags & QETH_HDR_IPV6) ? ETH_P_IPV6 :
|
||||
ETH_P_IP;
|
||||
@@ -1342,8 +1353,6 @@ static void qeth_l3_rebuild_skb(struct qeth_card *card, struct sk_buff *skb,
|
||||
tg_addr, "FAKELL", skb->len);
|
||||
}
|
||||
|
||||
skb->protocol = eth_type_trans(skb, card->dev);
|
||||
|
||||
/* copy VLAN tag from hdr into skb */
|
||||
if (!card->options.sniffer &&
|
||||
(hdr->hdr.l3.ext_flags & (QETH_HDR_EXT_VLAN_FRAME |
|
||||
@@ -1360,12 +1369,10 @@ static void qeth_l3_rebuild_skb(struct qeth_card *card, struct sk_buff *skb,
|
||||
static int qeth_l3_process_inbound_buffer(struct qeth_card *card,
|
||||
int budget, int *done)
|
||||
{
|
||||
struct net_device *dev = card->dev;
|
||||
int work_done = 0;
|
||||
struct sk_buff *skb;
|
||||
struct qeth_hdr *hdr;
|
||||
unsigned int len;
|
||||
__u16 magic;
|
||||
|
||||
*done = 0;
|
||||
WARN_ON_ONCE(!budget);
|
||||
@@ -1379,23 +1386,12 @@ static int qeth_l3_process_inbound_buffer(struct qeth_card *card,
|
||||
}
|
||||
switch (hdr->hdr.l3.id) {
|
||||
case QETH_HEADER_TYPE_LAYER3:
|
||||
magic = *(__u16 *)skb->data;
|
||||
if (IS_IQD(card) && magic == ETH_P_AF_IUCV) {
|
||||
len = skb->len;
|
||||
dev_hard_header(skb, dev, ETH_P_AF_IUCV,
|
||||
dev->dev_addr, "FAKELL", len);
|
||||
skb->protocol = eth_type_trans(skb, dev);
|
||||
netif_receive_skb(skb);
|
||||
} else {
|
||||
qeth_l3_rebuild_skb(card, skb, hdr);
|
||||
len = skb->len;
|
||||
napi_gro_receive(&card->napi, skb);
|
||||
}
|
||||
break;
|
||||
qeth_l3_rebuild_skb(card, skb, hdr);
|
||||
/* fall through */
|
||||
case QETH_HEADER_TYPE_LAYER2: /* for HiperSockets sniffer */
|
||||
skb->protocol = eth_type_trans(skb, skb->dev);
|
||||
len = skb->len;
|
||||
netif_receive_skb(skb);
|
||||
napi_gro_receive(&card->napi, skb);
|
||||
break;
|
||||
default:
|
||||
dev_kfree_skb_any(skb);
|
||||
@@ -1436,7 +1432,6 @@ static void qeth_l3_stop_card(struct qeth_card *card)
|
||||
card->state = CARD_STATE_DOWN;
|
||||
}
|
||||
|
||||
qeth_clear_cmd_buffers(&card->write);
|
||||
flush_workqueue(card->event_wq);
|
||||
}
|
||||
|
||||
@@ -1559,7 +1554,8 @@ static int qeth_l3_arp_set_no_entries(struct qeth_card *card, int no_entries)
|
||||
}
|
||||
|
||||
iob = qeth_get_setassparms_cmd(card, IPA_ARP_PROCESSING,
|
||||
IPA_CMD_ASS_ARP_SET_NO_ENTRIES, 4,
|
||||
IPA_CMD_ASS_ARP_SET_NO_ENTRIES,
|
||||
SETASS_DATA_SIZEOF(flags_32bit),
|
||||
QETH_PROT_IPV4);
|
||||
if (!iob)
|
||||
return -ENOMEM;
|
||||
@@ -1705,9 +1701,7 @@ static int qeth_l3_query_arp_cache_info(struct qeth_card *card,
|
||||
|
||||
iob = qeth_get_setassparms_cmd(card, IPA_ARP_PROCESSING,
|
||||
IPA_CMD_ASS_ARP_QUERY_INFO,
|
||||
sizeof(struct qeth_arp_query_data)
|
||||
- sizeof(char),
|
||||
prot);
|
||||
SETASS_DATA_SIZEOF(query_arp), prot);
|
||||
if (!iob)
|
||||
return -ENOMEM;
|
||||
cmd = __ipa_cmd(iob);
|
||||
@@ -1791,7 +1785,8 @@ static int qeth_l3_arp_modify_entry(struct qeth_card *card,
|
||||
}
|
||||
|
||||
iob = qeth_get_setassparms_cmd(card, IPA_ARP_PROCESSING, arp_cmd,
|
||||
sizeof(*cmd_entry), QETH_PROT_IPV4);
|
||||
SETASS_DATA_SIZEOF(arp_entry),
|
||||
QETH_PROT_IPV4);
|
||||
if (!iob)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -1882,26 +1877,17 @@ static int qeth_l3_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int qeth_l3_get_cast_type(struct sk_buff *skb)
|
||||
static int qeth_l3_get_cast_type_rcu(struct sk_buff *skb, struct dst_entry *dst,
|
||||
int ipv)
|
||||
{
|
||||
int ipv = qeth_get_ip_version(skb);
|
||||
struct neighbour *n = NULL;
|
||||
struct dst_entry *dst;
|
||||
|
||||
rcu_read_lock();
|
||||
dst = skb_dst(skb);
|
||||
if (dst) {
|
||||
struct rt6_info *rt = (struct rt6_info *) dst;
|
||||
|
||||
dst = dst_check(dst, (ipv == 6) ? rt6_get_cookie(rt) : 0);
|
||||
if (dst)
|
||||
n = dst_neigh_lookup_skb(dst, skb);
|
||||
}
|
||||
if (dst)
|
||||
n = dst_neigh_lookup_skb(dst, skb);
|
||||
|
||||
if (n) {
|
||||
int cast_type = n->type;
|
||||
|
||||
rcu_read_unlock();
|
||||
neigh_release(n);
|
||||
if ((cast_type == RTN_BROADCAST) ||
|
||||
(cast_type == RTN_MULTICAST) ||
|
||||
@@ -1909,7 +1895,6 @@ static int qeth_l3_get_cast_type(struct sk_buff *skb)
|
||||
return cast_type;
|
||||
return RTN_UNICAST;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
/* no neighbour (eg AF_PACKET), fall back to target's IP address ... */
|
||||
switch (ipv) {
|
||||
@@ -1927,6 +1912,20 @@ static int qeth_l3_get_cast_type(struct sk_buff *skb)
|
||||
}
|
||||
}
|
||||
|
||||
static int qeth_l3_get_cast_type(struct sk_buff *skb)
|
||||
{
|
||||
int ipv = qeth_get_ip_version(skb);
|
||||
struct dst_entry *dst;
|
||||
int cast_type;
|
||||
|
||||
rcu_read_lock();
|
||||
dst = qeth_dst_check_rcu(skb, ipv);
|
||||
cast_type = qeth_l3_get_cast_type_rcu(skb, dst, ipv);
|
||||
rcu_read_unlock();
|
||||
|
||||
return cast_type;
|
||||
}
|
||||
|
||||
static u8 qeth_l3_cast_type_to_flag(int cast_type)
|
||||
{
|
||||
if (cast_type == RTN_MULTICAST)
|
||||
@@ -1940,12 +1939,13 @@ static u8 qeth_l3_cast_type_to_flag(int cast_type)
|
||||
|
||||
static void qeth_l3_fill_header(struct qeth_qdio_out_q *queue,
|
||||
struct qeth_hdr *hdr, struct sk_buff *skb,
|
||||
int ipv, int cast_type, unsigned int data_len)
|
||||
int ipv, unsigned int data_len)
|
||||
{
|
||||
struct qeth_hdr_layer3 *l3_hdr = &hdr->hdr.l3;
|
||||
struct vlan_ethhdr *veth = vlan_eth_hdr(skb);
|
||||
struct qeth_card *card = queue->card;
|
||||
struct dst_entry *dst;
|
||||
int cast_type;
|
||||
|
||||
hdr->hdr.l3.length = data_len;
|
||||
|
||||
@@ -1982,36 +1982,23 @@ static void qeth_l3_fill_header(struct qeth_qdio_out_q *queue,
|
||||
hdr->hdr.l3.vlan_id = ntohs(veth->h_vlan_TCI);
|
||||
}
|
||||
|
||||
l3_hdr->flags = qeth_l3_cast_type_to_flag(cast_type);
|
||||
|
||||
/* OSA only: */
|
||||
if (!ipv) {
|
||||
l3_hdr->flags |= QETH_HDR_PASSTHRU;
|
||||
return;
|
||||
}
|
||||
|
||||
rcu_read_lock();
|
||||
dst = skb_dst(skb);
|
||||
dst = qeth_dst_check_rcu(skb, ipv);
|
||||
|
||||
if (IS_IQD(card) && skb_get_queue_mapping(skb) != QETH_IQD_MCAST_TXQ)
|
||||
cast_type = RTN_UNICAST;
|
||||
else
|
||||
cast_type = qeth_l3_get_cast_type_rcu(skb, dst, ipv);
|
||||
l3_hdr->flags |= qeth_l3_cast_type_to_flag(cast_type);
|
||||
|
||||
if (ipv == 4) {
|
||||
struct rtable *rt;
|
||||
|
||||
if (dst)
|
||||
dst = dst_check(dst, 0);
|
||||
rt = (struct rtable *) dst;
|
||||
struct rtable *rt = (struct rtable *) dst;
|
||||
|
||||
*((__be32 *) &hdr->hdr.l3.next_hop.ipv4.addr) = (rt) ?
|
||||
rt_nexthop(rt, ip_hdr(skb)->daddr) :
|
||||
ip_hdr(skb)->daddr;
|
||||
} else {
|
||||
/* IPv6 */
|
||||
struct rt6_info *rt;
|
||||
|
||||
if (dst) {
|
||||
rt = (struct rt6_info *) dst;
|
||||
dst = dst_check(dst, rt6_get_cookie(rt));
|
||||
}
|
||||
rt = (struct rt6_info *) dst;
|
||||
} else if (ipv == 6) {
|
||||
struct rt6_info *rt = (struct rt6_info *) dst;
|
||||
|
||||
if (rt && !ipv6_addr_any(&rt->rt6i_gateway))
|
||||
l3_hdr->next_hop.ipv6_addr = rt->rt6i_gateway;
|
||||
@@ -2021,6 +2008,9 @@ static void qeth_l3_fill_header(struct qeth_qdio_out_q *queue,
|
||||
hdr->hdr.l3.flags |= QETH_HDR_IPV6;
|
||||
if (!IS_IQD(card))
|
||||
hdr->hdr.l3.flags |= QETH_HDR_PASSTHRU;
|
||||
} else {
|
||||
/* OSA only: */
|
||||
l3_hdr->flags |= QETH_HDR_PASSTHRU;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
}
|
||||
@@ -2040,7 +2030,7 @@ static void qeth_l3_fixup_headers(struct sk_buff *skb)
|
||||
}
|
||||
|
||||
static int qeth_l3_xmit(struct qeth_card *card, struct sk_buff *skb,
|
||||
struct qeth_qdio_out_q *queue, int ipv, int cast_type)
|
||||
struct qeth_qdio_out_q *queue, int ipv)
|
||||
{
|
||||
unsigned int hw_hdr_len;
|
||||
int rc;
|
||||
@@ -2054,7 +2044,7 @@ static int qeth_l3_xmit(struct qeth_card *card, struct sk_buff *skb,
|
||||
skb_pull(skb, ETH_HLEN);
|
||||
|
||||
qeth_l3_fixup_headers(skb);
|
||||
return qeth_xmit(card, skb, queue, ipv, cast_type, qeth_l3_fill_header);
|
||||
return qeth_xmit(card, skb, queue, ipv, qeth_l3_fill_header);
|
||||
}
|
||||
|
||||
static netdev_tx_t qeth_l3_hard_start_xmit(struct sk_buff *skb,
|
||||
@@ -2065,7 +2055,7 @@ static netdev_tx_t qeth_l3_hard_start_xmit(struct sk_buff *skb,
|
||||
int ipv = qeth_get_ip_version(skb);
|
||||
struct qeth_qdio_out_q *queue;
|
||||
int tx_bytes = skb->len;
|
||||
int cast_type, rc;
|
||||
int rc;
|
||||
|
||||
if (IS_IQD(card)) {
|
||||
queue = card->qdio.out_qs[qeth_iqd_translate_txq(dev, txq)];
|
||||
@@ -2076,24 +2066,18 @@ static netdev_tx_t qeth_l3_hard_start_xmit(struct sk_buff *skb,
|
||||
(card->options.cq == QETH_CQ_ENABLED &&
|
||||
skb->protocol != htons(ETH_P_AF_IUCV)))
|
||||
goto tx_drop;
|
||||
|
||||
if (txq == QETH_IQD_MCAST_TXQ)
|
||||
cast_type = qeth_l3_get_cast_type(skb);
|
||||
else
|
||||
cast_type = RTN_UNICAST;
|
||||
} else {
|
||||
queue = card->qdio.out_qs[txq];
|
||||
cast_type = qeth_l3_get_cast_type(skb);
|
||||
}
|
||||
|
||||
if (cast_type == RTN_BROADCAST && !card->info.broadcast_capable)
|
||||
if (!(dev->flags & IFF_BROADCAST) &&
|
||||
qeth_l3_get_cast_type(skb) == RTN_BROADCAST)
|
||||
goto tx_drop;
|
||||
|
||||
if (ipv == 4 || IS_IQD(card))
|
||||
rc = qeth_l3_xmit(card, skb, queue, ipv, cast_type);
|
||||
rc = qeth_l3_xmit(card, skb, queue, ipv);
|
||||
else
|
||||
rc = qeth_xmit(card, skb, queue, ipv, cast_type,
|
||||
qeth_l3_fill_header);
|
||||
rc = qeth_xmit(card, skb, queue, ipv, qeth_l3_fill_header);
|
||||
|
||||
if (!rc) {
|
||||
QETH_TXQ_STAT_INC(queue, tx_packets);
|
||||
@@ -2498,33 +2482,6 @@ static int qeth_l3_recover(void *ptr)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qeth_l3_pm_suspend(struct ccwgroup_device *gdev)
|
||||
{
|
||||
struct qeth_card *card = dev_get_drvdata(&gdev->dev);
|
||||
|
||||
qeth_set_allowed_threads(card, 0, 1);
|
||||
wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0);
|
||||
if (gdev->state == CCWGROUP_OFFLINE)
|
||||
return 0;
|
||||
|
||||
qeth_l3_set_offline(gdev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qeth_l3_pm_resume(struct ccwgroup_device *gdev)
|
||||
{
|
||||
struct qeth_card *card = dev_get_drvdata(&gdev->dev);
|
||||
int rc;
|
||||
|
||||
rc = qeth_l3_set_online(gdev);
|
||||
|
||||
qeth_set_allowed_threads(card, 0xffffffff, 0);
|
||||
if (rc)
|
||||
dev_warn(&card->gdev->dev, "The qeth device driver "
|
||||
"failed to recover an error on the device\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Returns zero if the command is successfully "consumed" */
|
||||
static int qeth_l3_control_event(struct qeth_card *card,
|
||||
struct qeth_ipa_cmd *cmd)
|
||||
@@ -2540,9 +2497,6 @@ struct qeth_discipline qeth_l3_discipline = {
|
||||
.remove = qeth_l3_remove_device,
|
||||
.set_online = qeth_l3_set_online,
|
||||
.set_offline = qeth_l3_set_offline,
|
||||
.freeze = qeth_l3_pm_suspend,
|
||||
.thaw = qeth_l3_pm_resume,
|
||||
.restore = qeth_l3_pm_resume,
|
||||
.do_ioctl = qeth_l3_do_ioctl,
|
||||
.control_event_handler = qeth_l3_control_event,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user