Skip to content

Commit

Permalink
qeth: bridgeport support - basic control
Browse files Browse the repository at this point in the history
Introduce functions to assign roles and check state of bridgeport-capable
HiperSocket devices, and sysfs attributes providing access to these
functions from userspace. Introduce udev events emitted when the state
of a bridgeport device changes.

Signed-off-by: Eugene Crosser <eugene.crosser@ru.ibm.com>
Signed-off-by: Frank Blaschka <frank.blaschka@de.ibm.com>
Reviewed-by: Ursula Braun <ursula.braun@de.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Eugene Crosser authored and David S. Miller committed Jan 15, 2014
1 parent 3977458 commit b4d72c0
Show file tree
Hide file tree
Showing 9 changed files with 685 additions and 2 deletions.
21 changes: 21 additions & 0 deletions Documentation/s390/qeth.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
IBM s390 QDIO Ethernet Driver

HiperSockets Bridge Port Support

Uevents

To generate the events the device must be assigned a role of either
a primary or a secondary Bridge Port. For more information, see
"z/VM Connectivity, SC24-6174".

When run on HiperSockets Bridge Capable Port hardware, and the state
of some configured Bridge Port device on the channel changes, a udev
event with ACTION=CHANGE is emitted on behalf of the corresponding
ccwgroup device. The event has the following attributes:

BRIDGEPORT=statechange - indicates that the Bridge Port device changed
its state.

ROLE={primary|secondary|none} - the role assigned to the port.

STATE={active|standby|inactive} - the newly assumed state of the port.
2 changes: 1 addition & 1 deletion drivers/s390/net/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ obj-$(CONFIG_LCS) += lcs.o
obj-$(CONFIG_CLAW) += claw.o
qeth-y += qeth_core_sys.o qeth_core_main.o qeth_core_mpc.o
obj-$(CONFIG_QETH) += qeth.o
qeth_l2-y += qeth_l2_main.o
qeth_l2-y += qeth_l2_main.o qeth_l2_sys.o
obj-$(CONFIG_QETH_L2) += qeth_l2.o
qeth_l3-y += qeth_l3_main.o qeth_l3_sys.o
obj-$(CONFIG_QETH_L3) += qeth_l3.o
25 changes: 25 additions & 0 deletions drivers/s390/net/qeth_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,24 @@ struct qeth_ipa_info {
__u32 enabled_funcs;
};

/* SETBRIDGEPORT stuff */
enum qeth_sbp_roles {
QETH_SBP_ROLE_NONE = 0,
QETH_SBP_ROLE_PRIMARY = 1,
QETH_SBP_ROLE_SECONDARY = 2,
};

enum qeth_sbp_states {
QETH_SBP_STATE_INACTIVE = 0,
QETH_SBP_STATE_STANDBY = 1,
QETH_SBP_STATE_ACTIVE = 2,
};

struct qeth_sbp_info {
__u32 supported_funcs;
enum qeth_sbp_roles role;
};

static inline int qeth_is_ipa_supported(struct qeth_ipa_info *ipa,
enum qeth_ipa_funcs func)
{
Expand Down Expand Up @@ -672,6 +690,7 @@ struct qeth_card_options {
struct qeth_ipa_info adp; /*Adapter parameters*/
struct qeth_routing_info route6;
struct qeth_ipa_info ipa6;
struct qeth_sbp_info sbp; /* SETBRIDGEPORT options */
int fake_broadcast;
int add_hhlen;
int layer2;
Expand Down Expand Up @@ -857,6 +876,7 @@ extern struct qeth_discipline qeth_l2_discipline;
extern struct qeth_discipline qeth_l3_discipline;
extern const struct attribute_group *qeth_generic_attr_groups[];
extern const struct attribute_group *qeth_osn_attr_groups[];
extern struct workqueue_struct *qeth_wq;

const char *qeth_get_cardname_short(struct qeth_card *);
int qeth_realloc_buffer_pool(struct qeth_card *, int);
Expand Down Expand Up @@ -925,6 +945,11 @@ int qeth_query_card_info(struct qeth_card *card,
int qeth_send_control_data(struct qeth_card *, int, struct qeth_cmd_buffer *,
int (*reply_cb)(struct qeth_card *, struct qeth_reply*, unsigned long),
void *reply_param);
void qeth_bridge_state_change(struct qeth_card *card, struct qeth_ipa_cmd *cmd);
void qeth_bridgeport_query_support(struct qeth_card *card);
int qeth_bridgeport_query_ports(struct qeth_card *card,
enum qeth_sbp_roles *role, enum qeth_sbp_states *state);
int qeth_bridgeport_setrole(struct qeth_card *card, enum qeth_sbp_roles role);
int qeth_get_priority_queue(struct qeth_card *, struct sk_buff *, int, int);
int qeth_get_elements_no(struct qeth_card *, struct sk_buff *, int);
int qeth_get_elements_for_frags(struct sk_buff *);
Expand Down
14 changes: 13 additions & 1 deletion drivers/s390/net/qeth_core_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ static void qeth_clear_output_buffer(struct qeth_qdio_out_q *queue,
enum qeth_qdio_buffer_states newbufstate);
static int qeth_init_qdio_out_buf(struct qeth_qdio_out_q *, int);

static struct workqueue_struct *qeth_wq;
struct workqueue_struct *qeth_wq;

static void qeth_close_dev_handler(struct work_struct *work)
{
Expand Down Expand Up @@ -615,6 +615,13 @@ static struct qeth_ipa_cmd *qeth_check_ipa_data(struct qeth_card *card,
card->info.hwtrap = 2;
qeth_schedule_recovery(card);
return NULL;
case IPA_CMD_SETBRIDGEPORT:
if (cmd->data.sbp.hdr.command_code ==
IPA_SBP_BRIDGE_PORT_STATE_CHANGE) {
qeth_bridge_state_change(card, cmd);
return NULL;
} else
return cmd;
case IPA_CMD_MODCCID:
return cmd;
case IPA_CMD_REGISTER_LOCAL_ADDR:
Expand Down Expand Up @@ -4956,12 +4963,17 @@ int qeth_core_hardsetup_card(struct qeth_card *card)

card->options.ipa4.supported_funcs = 0;
card->options.adp.supported_funcs = 0;
card->options.sbp.supported_funcs = 0;
card->info.diagass_support = 0;
qeth_query_ipassists(card, QETH_PROT_IPV4);
if (qeth_is_supported(card, IPA_SETADAPTERPARMS))
qeth_query_setadapterparms(card);
if (qeth_adp_supported(card, IPA_SETADP_SET_DIAG_ASSIST))
qeth_query_setdiagass(card);
qeth_bridgeport_query_support(card);
if (card->options.sbp.supported_funcs)
dev_info(&card->gdev->dev,
"The device represents a HiperSockets Bridge Capable Port\n");
return 0;
out:
dev_warn(&card->gdev->dev, "The qeth device driver failed to recover "
Expand Down
1 change: 1 addition & 0 deletions drivers/s390/net/qeth_core_mpc.c
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,7 @@ static struct ipa_cmd_names qeth_ipa_cmd_names[] = {
{IPA_CMD_DELIP, "delip"},
{IPA_CMD_SETADAPTERPARMS, "setadapterparms"},
{IPA_CMD_SET_DIAG_ASS, "set_diag_ass"},
{IPA_CMD_SETBRIDGEPORT, "set_bridge_port"},
{IPA_CMD_CREATE_ADDR, "create_addr"},
{IPA_CMD_DESTROY_ADDR, "destroy_addr"},
{IPA_CMD_REGISTER_LOCAL_ADDR, "register_local_addr"},
Expand Down
84 changes: 84 additions & 0 deletions drivers/s390/net/qeth_core_mpc.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ enum qeth_ipa_cmds {
IPA_CMD_DELIP = 0xb7,
IPA_CMD_SETADAPTERPARMS = 0xb8,
IPA_CMD_SET_DIAG_ASS = 0xb9,
IPA_CMD_SETBRIDGEPORT = 0xbe,
IPA_CMD_CREATE_ADDR = 0xc3,
IPA_CMD_DESTROY_ADDR = 0xc4,
IPA_CMD_REGISTER_LOCAL_ADDR = 0xd1,
Expand Down Expand Up @@ -500,6 +501,88 @@ struct qeth_ipacmd_diagass {
__u8 cdata[64];
} __attribute__ ((packed));

/* SETBRIDGEPORT IPA Command: *********************************************/
enum qeth_ipa_sbp_cmd {
IPA_SBP_QUERY_COMMANDS_SUPPORTED = 0x00000000L,
IPA_SBP_RESET_BRIDGE_PORT_ROLE = 0x00000001L,
IPA_SBP_SET_PRIMARY_BRIDGE_PORT = 0x00000002L,
IPA_SBP_SET_SECONDARY_BRIDGE_PORT = 0x00000004L,
IPA_SBP_QUERY_BRIDGE_PORTS = 0x00000008L,
IPA_SBP_BRIDGE_PORT_STATE_CHANGE = 0x00000010L,
};

struct net_if_token {
__u16 devnum;
__u8 cssid;
__u8 iid;
__u8 ssid;
__u8 chpid;
__u16 chid;
} __packed;

struct qeth_ipacmd_sbp_hdr {
__u32 supported_sbp_cmds;
__u32 enabled_sbp_cmds;
__u16 cmdlength;
__u16 reserved1;
__u32 command_code;
__u16 return_code;
__u8 used_total;
__u8 seq_no;
__u32 reserved2;
} __packed;

struct qeth_sbp_query_cmds_supp {
__u32 supported_cmds;
__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;
__u8 reserved1;
__u8 reserved2;
struct net_if_token token;
} __packed;

struct qeth_sbp_query_ports {
__u8 primary_bp_supported;
__u8 secondary_bp_supported;
__u8 num_entries;
__u8 entry_length;
struct qeth_sbp_port_entry entry[];
} __packed;

struct qeth_sbp_state_change {
__u8 primary_bp_supported;
__u8 secondary_bp_supported;
__u8 num_entries;
__u8 entry_length;
struct qeth_sbp_port_entry entry[];
} __packed;

struct qeth_ipacmd_setbridgeport {
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;

/* Header for each IPA command */
struct qeth_ipacmd_hdr {
__u8 command;
Expand Down Expand Up @@ -529,6 +612,7 @@ struct qeth_ipa_cmd {
struct qeth_ipacmd_setadpparms setadapterparms;
struct qeth_set_routing setrtg;
struct qeth_ipacmd_diagass diagass;
struct qeth_ipacmd_setbridgeport sbp;
} data;
} __attribute__ ((packed));

Expand Down
15 changes: 15 additions & 0 deletions drivers/s390/net/qeth_l2.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/*
* Copyright IBM Corp. 2013
* Author(s): Eugene Crosser <eugene.crosser@ru.ibm.com>
*/

#ifndef __QETH_L2_H__
#define __QETH_L2_H__

#include "qeth_core.h"

int qeth_l2_create_device_attributes(struct device *);
void qeth_l2_remove_device_attributes(struct device *);
void qeth_l2_setup_bridgeport_attrs(struct qeth_card *card);

#endif /* __QETH_L2_H__ */
Loading

0 comments on commit b4d72c0

Please sign in to comment.