aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-01-25 14:17:34 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2014-01-25 14:17:34 -0500
commit4ba9920e5e9c0e16b5ed24292d45322907bb9035 (patch)
tree7d023baea59ed0886ded1f0b6d1c6385690b88f7 /drivers/s390
parent82c477669a4665eb4e52030792051e0559ee2a36 (diff)
parent8b662fe70c68282f78482dc272df0c4f355e49f5 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next
Pull networking updates from David Miller: 1) BPF debugger and asm tool by Daniel Borkmann. 2) Speed up create/bind in AF_PACKET, also from Daniel Borkmann. 3) Correct reciprocal_divide and update users, from Hannes Frederic Sowa and Daniel Borkmann. 4) Currently we only have a "set" operation for the hw timestamp socket ioctl, add a "get" operation to match. From Ben Hutchings. 5) Add better trace events for debugging driver datapath problems, also from Ben Hutchings. 6) Implement auto corking in TCP, from Eric Dumazet. Basically, if we have a small send and a previous packet is already in the qdisc or device queue, defer until TX completion or we get more data. 7) Allow userspace to manage ipv6 temporary addresses, from Jiri Pirko. 8) Add a qdisc bypass option for AF_PACKET sockets, from Daniel Borkmann. 9) Share IP header compression code between Bluetooth and IEEE802154 layers, from Jukka Rissanen. 10) Fix ipv6 router reachability probing, from Jiri Benc. 11) Allow packets to be captured on macvtap devices, from Vlad Yasevich. 12) Support tunneling in GRO layer, from Jerry Chu. 13) Allow bonding to be configured fully using netlink, from Scott Feldman. 14) Allow AF_PACKET users to obtain the VLAN TPID, just like they can already get the TCI. From Atzm Watanabe. 15) New "Heavy Hitter" qdisc, from Terry Lam. 16) Significantly improve the IPSEC support in pktgen, from Fan Du. 17) Allow ipv4 tunnels to cache routes, just like sockets. From Tom Herbert. 18) Add Proportional Integral Enhanced packet scheduler, from Vijay Subramanian. 19) Allow openvswitch to mmap'd netlink, from Thomas Graf. 20) Key TCP metrics blobs also by source address, not just destination address. From Christoph Paasch. 21) Support 10G in generic phylib. From Andy Fleming. 22) Try to short-circuit GRO flow compares using device provided RX hash, if provided. From Tom Herbert. The wireless and netfilter folks have been busy little bees too. * git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next: (2064 commits) net/cxgb4: Fix referencing freed adapter ipv6: reallocate addrconf router for ipv6 address when lo device up fib_frontend: fix possible NULL pointer dereference rtnetlink: remove IFLA_BOND_SLAVE definition rtnetlink: remove check for fill_slave_info in rtnl_have_link_slave_info qlcnic: update version to 5.3.55 qlcnic: Enhance logic to calculate msix vectors. qlcnic: Refactor interrupt coalescing code for all adapters. qlcnic: Update poll controller code path qlcnic: Interrupt code cleanup qlcnic: Enhance Tx timeout debugging. qlcnic: Use bool for rx_mac_learn. bonding: fix u64 division rtnetlink: add missing IFLA_BOND_AD_INFO_UNSPEC sfc: Use the correct maximum TX DMA ring size for SFC9100 Add Shradha Shah as the sfc driver maintainer. net/vxlan: Share RX skb de-marking and checksum checks with ovs tulip: cleanup by using ARRAY_SIZE() ip_tunnel: clear IPCB in ip_tunnel_xmit() in case dst_link_failure() is called net/cxgb4: Don't retrieve stats during recovery ...
Diffstat (limited to 'drivers/s390')
-rw-r--r--drivers/s390/net/Makefile2
-rw-r--r--drivers/s390/net/netiucv.c8
-rw-r--r--drivers/s390/net/qeth_core.h38
-rw-r--r--drivers/s390/net/qeth_core_main.c215
-rw-r--r--drivers/s390/net/qeth_core_mpc.c2
-rw-r--r--drivers/s390/net/qeth_core_mpc.h150
-rw-r--r--drivers/s390/net/qeth_l2.h15
-rw-r--r--drivers/s390/net/qeth_l2_main.c594
-rw-r--r--drivers/s390/net/qeth_l2_sys.c223
9 files changed, 1194 insertions, 53 deletions
diff --git a/drivers/s390/net/Makefile b/drivers/s390/net/Makefile
index 4dfe8c1092da..d28f05d0c75a 100644
--- a/drivers/s390/net/Makefile
+++ b/drivers/s390/net/Makefile
@@ -11,7 +11,7 @@ obj-$(CONFIG_LCS) += lcs.o
11obj-$(CONFIG_CLAW) += claw.o 11obj-$(CONFIG_CLAW) += claw.o
12qeth-y += qeth_core_sys.o qeth_core_main.o qeth_core_mpc.o 12qeth-y += qeth_core_sys.o qeth_core_main.o qeth_core_mpc.o
13obj-$(CONFIG_QETH) += qeth.o 13obj-$(CONFIG_QETH) += qeth.o
14qeth_l2-y += qeth_l2_main.o 14qeth_l2-y += qeth_l2_main.o qeth_l2_sys.o
15obj-$(CONFIG_QETH_L2) += qeth_l2.o 15obj-$(CONFIG_QETH_L2) += qeth_l2.o
16qeth_l3-y += qeth_l3_main.o qeth_l3_sys.o 16qeth_l3-y += qeth_l3_main.o qeth_l3_sys.o
17obj-$(CONFIG_QETH_L3) += qeth_l3.o 17obj-$(CONFIG_QETH_L3) += qeth_l3.o
diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c
index 9b333fcf1a4c..ce16d1bdb20a 100644
--- a/drivers/s390/net/netiucv.c
+++ b/drivers/s390/net/netiucv.c
@@ -739,8 +739,12 @@ static void conn_action_txdone(fsm_instance *fi, int event, void *arg)
739 739
740 IUCV_DBF_TEXT(trace, 4, __func__); 740 IUCV_DBF_TEXT(trace, 4, __func__);
741 741
742 if (conn && conn->netdev) 742 if (!conn || !conn->netdev) {
743 privptr = netdev_priv(conn->netdev); 743 IUCV_DBF_TEXT(data, 2,
744 "Send confirmation for unlinked connection\n");
745 return;
746 }
747 privptr = netdev_priv(conn->netdev);
744 conn->prof.tx_pending--; 748 conn->prof.tx_pending--;
745 if (single_flag) { 749 if (single_flag) {
746 if ((skb = skb_dequeue(&conn->commit_queue))) { 750 if ((skb = skb_dequeue(&conn->commit_queue))) {
diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h
index 41ef94320ee8..ac0bdded060f 100644
--- a/drivers/s390/net/qeth_core.h
+++ b/drivers/s390/net/qeth_core.h
@@ -156,6 +156,27 @@ struct qeth_ipa_info {
156 __u32 enabled_funcs; 156 __u32 enabled_funcs;
157}; 157};
158 158
159/* SETBRIDGEPORT stuff */
160enum qeth_sbp_roles {
161 QETH_SBP_ROLE_NONE = 0,
162 QETH_SBP_ROLE_PRIMARY = 1,
163 QETH_SBP_ROLE_SECONDARY = 2,
164};
165
166enum qeth_sbp_states {
167 QETH_SBP_STATE_INACTIVE = 0,
168 QETH_SBP_STATE_STANDBY = 1,
169 QETH_SBP_STATE_ACTIVE = 2,
170};
171
172#define QETH_SBP_HOST_NOTIFICATION 1
173
174struct qeth_sbp_info {
175 __u32 supported_funcs;
176 enum qeth_sbp_roles role;
177 __u32 hostnotification:1;
178};
179
159static inline int qeth_is_ipa_supported(struct qeth_ipa_info *ipa, 180static inline int qeth_is_ipa_supported(struct qeth_ipa_info *ipa,
160 enum qeth_ipa_funcs func) 181 enum qeth_ipa_funcs func)
161{ 182{
@@ -672,6 +693,7 @@ struct qeth_card_options {
672 struct qeth_ipa_info adp; /*Adapter parameters*/ 693 struct qeth_ipa_info adp; /*Adapter parameters*/
673 struct qeth_routing_info route6; 694 struct qeth_routing_info route6;
674 struct qeth_ipa_info ipa6; 695 struct qeth_ipa_info ipa6;
696 struct qeth_sbp_info sbp; /* SETBRIDGEPORT options */
675 int fake_broadcast; 697 int fake_broadcast;
676 int add_hhlen; 698 int add_hhlen;
677 int layer2; 699 int layer2;
@@ -738,6 +760,12 @@ struct qeth_rx {
738 int qdio_err; 760 int qdio_err;
739}; 761};
740 762
763struct carrier_info {
764 __u8 card_type;
765 __u16 port_mode;
766 __u32 port_speed;
767};
768
741#define QETH_NAPI_WEIGHT NAPI_POLL_WEIGHT 769#define QETH_NAPI_WEIGHT NAPI_POLL_WEIGHT
742 770
743struct qeth_card { 771struct qeth_card {
@@ -851,6 +879,7 @@ extern struct qeth_discipline qeth_l2_discipline;
851extern struct qeth_discipline qeth_l3_discipline; 879extern struct qeth_discipline qeth_l3_discipline;
852extern const struct attribute_group *qeth_generic_attr_groups[]; 880extern const struct attribute_group *qeth_generic_attr_groups[];
853extern const struct attribute_group *qeth_osn_attr_groups[]; 881extern const struct attribute_group *qeth_osn_attr_groups[];
882extern struct workqueue_struct *qeth_wq;
854 883
855const char *qeth_get_cardname_short(struct qeth_card *); 884const char *qeth_get_cardname_short(struct qeth_card *);
856int qeth_realloc_buffer_pool(struct qeth_card *, int); 885int qeth_realloc_buffer_pool(struct qeth_card *, int);
@@ -914,9 +943,18 @@ struct qeth_cmd_buffer *qeth_wait_for_buffer(struct qeth_channel *);
914int qeth_mdio_read(struct net_device *, int, int); 943int qeth_mdio_read(struct net_device *, int, int);
915int qeth_snmp_command(struct qeth_card *, char __user *); 944int qeth_snmp_command(struct qeth_card *, char __user *);
916int qeth_query_oat_command(struct qeth_card *, char __user *); 945int qeth_query_oat_command(struct qeth_card *, char __user *);
946int qeth_query_card_info(struct qeth_card *card,
947 struct carrier_info *carrier_info);
917int qeth_send_control_data(struct qeth_card *, int, struct qeth_cmd_buffer *, 948int qeth_send_control_data(struct qeth_card *, int, struct qeth_cmd_buffer *,
918 int (*reply_cb)(struct qeth_card *, struct qeth_reply*, unsigned long), 949 int (*reply_cb)(struct qeth_card *, struct qeth_reply*, unsigned long),
919 void *reply_param); 950 void *reply_param);
951void qeth_bridge_state_change(struct qeth_card *card, struct qeth_ipa_cmd *cmd);
952void qeth_bridgeport_query_support(struct qeth_card *card);
953int qeth_bridgeport_query_ports(struct qeth_card *card,
954 enum qeth_sbp_roles *role, enum qeth_sbp_states *state);
955int qeth_bridgeport_setrole(struct qeth_card *card, enum qeth_sbp_roles role);
956int qeth_bridgeport_an_set(struct qeth_card *card, int enable);
957void qeth_bridge_host_event(struct qeth_card *card, struct qeth_ipa_cmd *cmd);
920int qeth_get_priority_queue(struct qeth_card *, struct sk_buff *, int, int); 958int qeth_get_priority_queue(struct qeth_card *, struct sk_buff *, int, int);
921int qeth_get_elements_no(struct qeth_card *, struct sk_buff *, int); 959int qeth_get_elements_no(struct qeth_card *, struct sk_buff *, int);
922int qeth_get_elements_for_frags(struct sk_buff *); 960int qeth_get_elements_for_frags(struct sk_buff *);
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index eb4e1f809feb..c05dacbf4e23 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -68,7 +68,7 @@ static void qeth_clear_output_buffer(struct qeth_qdio_out_q *queue,
68 enum qeth_qdio_buffer_states newbufstate); 68 enum qeth_qdio_buffer_states newbufstate);
69static int qeth_init_qdio_out_buf(struct qeth_qdio_out_q *, int); 69static int qeth_init_qdio_out_buf(struct qeth_qdio_out_q *, int);
70 70
71static struct workqueue_struct *qeth_wq; 71struct workqueue_struct *qeth_wq;
72 72
73static void qeth_close_dev_handler(struct work_struct *work) 73static void qeth_close_dev_handler(struct work_struct *work)
74{ 74{
@@ -615,6 +615,16 @@ static struct qeth_ipa_cmd *qeth_check_ipa_data(struct qeth_card *card,
615 card->info.hwtrap = 2; 615 card->info.hwtrap = 2;
616 qeth_schedule_recovery(card); 616 qeth_schedule_recovery(card);
617 return NULL; 617 return NULL;
618 case IPA_CMD_SETBRIDGEPORT:
619 if (cmd->data.sbp.hdr.command_code ==
620 IPA_SBP_BRIDGE_PORT_STATE_CHANGE) {
621 qeth_bridge_state_change(card, cmd);
622 return NULL;
623 } else
624 return cmd;
625 case IPA_CMD_ADDRESS_CHANGE_NOTIF:
626 qeth_bridge_host_event(card, cmd);
627 return NULL;
618 case IPA_CMD_MODCCID: 628 case IPA_CMD_MODCCID:
619 return cmd; 629 return cmd;
620 case IPA_CMD_REGISTER_LOCAL_ADDR: 630 case IPA_CMD_REGISTER_LOCAL_ADDR:
@@ -4602,6 +4612,42 @@ out:
4602} 4612}
4603EXPORT_SYMBOL_GPL(qeth_query_oat_command); 4613EXPORT_SYMBOL_GPL(qeth_query_oat_command);
4604 4614
4615int qeth_query_card_info_cb(struct qeth_card *card,
4616 struct qeth_reply *reply, unsigned long data)
4617{
4618 struct qeth_ipa_cmd *cmd;
4619 struct qeth_query_card_info *card_info;
4620 struct carrier_info *carrier_info;
4621
4622 QETH_CARD_TEXT(card, 2, "qcrdincb");
4623 carrier_info = (struct carrier_info *)reply->param;
4624 cmd = (struct qeth_ipa_cmd *)data;
4625 card_info = &cmd->data.setadapterparms.data.card_info;
4626 if (cmd->data.setadapterparms.hdr.return_code == 0) {
4627 carrier_info->card_type = card_info->card_type;
4628 carrier_info->port_mode = card_info->port_mode;
4629 carrier_info->port_speed = card_info->port_speed;
4630 }
4631
4632 qeth_default_setadapterparms_cb(card, reply, (unsigned long) cmd);
4633 return 0;
4634}
4635
4636int qeth_query_card_info(struct qeth_card *card,
4637 struct carrier_info *carrier_info)
4638{
4639 struct qeth_cmd_buffer *iob;
4640
4641 QETH_CARD_TEXT(card, 2, "qcrdinfo");
4642 if (!qeth_adp_supported(card, IPA_SETADP_QUERY_CARD_INFO))
4643 return -EOPNOTSUPP;
4644 iob = qeth_get_adapter_cmd(card, IPA_SETADP_QUERY_CARD_INFO,
4645 sizeof(struct qeth_ipacmd_setadpparms_hdr));
4646 return qeth_send_ipa_cmd(card, iob, qeth_query_card_info_cb,
4647 (void *)carrier_info);
4648}
4649EXPORT_SYMBOL_GPL(qeth_query_card_info);
4650
4605static inline int qeth_get_qdio_q_format(struct qeth_card *card) 4651static inline int qeth_get_qdio_q_format(struct qeth_card *card)
4606{ 4652{
4607 switch (card->info.type) { 4653 switch (card->info.type) {
@@ -4920,12 +4966,17 @@ retriable:
4920 4966
4921 card->options.ipa4.supported_funcs = 0; 4967 card->options.ipa4.supported_funcs = 0;
4922 card->options.adp.supported_funcs = 0; 4968 card->options.adp.supported_funcs = 0;
4969 card->options.sbp.supported_funcs = 0;
4923 card->info.diagass_support = 0; 4970 card->info.diagass_support = 0;
4924 qeth_query_ipassists(card, QETH_PROT_IPV4); 4971 qeth_query_ipassists(card, QETH_PROT_IPV4);
4925 if (qeth_is_supported(card, IPA_SETADAPTERPARMS)) 4972 if (qeth_is_supported(card, IPA_SETADAPTERPARMS))
4926 qeth_query_setadapterparms(card); 4973 qeth_query_setadapterparms(card);
4927 if (qeth_adp_supported(card, IPA_SETADP_SET_DIAG_ASSIST)) 4974 if (qeth_adp_supported(card, IPA_SETADP_SET_DIAG_ASSIST))
4928 qeth_query_setdiagass(card); 4975 qeth_query_setdiagass(card);
4976 qeth_bridgeport_query_support(card);
4977 if (card->options.sbp.supported_funcs)
4978 dev_info(&card->gdev->dev,
4979 "The device represents a HiperSockets Bridge Capable Port\n");
4929 return 0; 4980 return 0;
4930out: 4981out:
4931 dev_warn(&card->gdev->dev, "The qeth device driver failed to recover " 4982 dev_warn(&card->gdev->dev, "The qeth device driver failed to recover "
@@ -5606,11 +5657,65 @@ void qeth_core_get_drvinfo(struct net_device *dev,
5606} 5657}
5607EXPORT_SYMBOL_GPL(qeth_core_get_drvinfo); 5658EXPORT_SYMBOL_GPL(qeth_core_get_drvinfo);
5608 5659
5660/* Helper function to fill 'advertizing' and 'supported' which are the same. */
5661/* Autoneg and full-duplex are supported and advertized uncondionally. */
5662/* Always advertize and support all speeds up to specified, and only one */
5663/* specified port type. */
5664static void qeth_set_ecmd_adv_sup(struct ethtool_cmd *ecmd,
5665 int maxspeed, int porttype)
5666{
5667 int port_sup, port_adv, spd_sup, spd_adv;
5668
5669 switch (porttype) {
5670 case PORT_TP:
5671 port_sup = SUPPORTED_TP;
5672 port_adv = ADVERTISED_TP;
5673 break;
5674 case PORT_FIBRE:
5675 port_sup = SUPPORTED_FIBRE;
5676 port_adv = ADVERTISED_FIBRE;
5677 break;
5678 default:
5679 port_sup = SUPPORTED_TP;
5680 port_adv = ADVERTISED_TP;
5681 WARN_ON_ONCE(1);
5682 }
5683
5684 /* "Fallthrough" case'es ordered from high to low result in setting */
5685 /* flags cumulatively, starting from the specified speed and down to */
5686 /* the lowest possible. */
5687 spd_sup = 0;
5688 spd_adv = 0;
5689 switch (maxspeed) {
5690 case SPEED_10000:
5691 spd_sup |= SUPPORTED_10000baseT_Full;
5692 spd_adv |= ADVERTISED_10000baseT_Full;
5693 case SPEED_1000:
5694 spd_sup |= SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full;
5695 spd_adv |= ADVERTISED_1000baseT_Half |
5696 ADVERTISED_1000baseT_Full;
5697 case SPEED_100:
5698 spd_sup |= SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full;
5699 spd_adv |= ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full;
5700 case SPEED_10:
5701 spd_sup |= SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full;
5702 spd_adv |= ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full;
5703 break;
5704 default:
5705 spd_sup = SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full;
5706 spd_adv = ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full;
5707 WARN_ON_ONCE(1);
5708 }
5709 ecmd->advertising = ADVERTISED_Autoneg | port_adv | spd_adv;
5710 ecmd->supported = SUPPORTED_Autoneg | port_sup | spd_sup;
5711}
5712
5609int qeth_core_ethtool_get_settings(struct net_device *netdev, 5713int qeth_core_ethtool_get_settings(struct net_device *netdev,
5610 struct ethtool_cmd *ecmd) 5714 struct ethtool_cmd *ecmd)
5611{ 5715{
5612 struct qeth_card *card = netdev->ml_priv; 5716 struct qeth_card *card = netdev->ml_priv;
5613 enum qeth_link_types link_type; 5717 enum qeth_link_types link_type;
5718 struct carrier_info carrier_info;
5614 5719
5615 if ((card->info.type == QETH_CARD_TYPE_IQD) || (card->info.guestlan)) 5720 if ((card->info.type == QETH_CARD_TYPE_IQD) || (card->info.guestlan))
5616 link_type = QETH_LINK_TYPE_10GBIT_ETH; 5721 link_type = QETH_LINK_TYPE_10GBIT_ETH;
@@ -5618,80 +5723,92 @@ int qeth_core_ethtool_get_settings(struct net_device *netdev,
5618 link_type = card->info.link_type; 5723 link_type = card->info.link_type;
5619 5724
5620 ecmd->transceiver = XCVR_INTERNAL; 5725 ecmd->transceiver = XCVR_INTERNAL;
5621 ecmd->supported = SUPPORTED_Autoneg;
5622 ecmd->advertising = ADVERTISED_Autoneg;
5623 ecmd->duplex = DUPLEX_FULL; 5726 ecmd->duplex = DUPLEX_FULL;
5624 ecmd->autoneg = AUTONEG_ENABLE; 5727 ecmd->autoneg = AUTONEG_ENABLE;
5625 5728
5626 switch (link_type) { 5729 switch (link_type) {
5627 case QETH_LINK_TYPE_FAST_ETH: 5730 case QETH_LINK_TYPE_FAST_ETH:
5628 case QETH_LINK_TYPE_LANE_ETH100: 5731 case QETH_LINK_TYPE_LANE_ETH100:
5629 ecmd->supported |= SUPPORTED_10baseT_Half | 5732 qeth_set_ecmd_adv_sup(ecmd, SPEED_100, PORT_TP);
5630 SUPPORTED_10baseT_Full |
5631 SUPPORTED_100baseT_Half |
5632 SUPPORTED_100baseT_Full |
5633 SUPPORTED_TP;
5634 ecmd->advertising |= ADVERTISED_10baseT_Half |
5635 ADVERTISED_10baseT_Full |
5636 ADVERTISED_100baseT_Half |
5637 ADVERTISED_100baseT_Full |
5638 ADVERTISED_TP;
5639 ecmd->speed = SPEED_100; 5733 ecmd->speed = SPEED_100;
5640 ecmd->port = PORT_TP; 5734 ecmd->port = PORT_TP;
5641 break; 5735 break;
5642 5736
5643 case QETH_LINK_TYPE_GBIT_ETH: 5737 case QETH_LINK_TYPE_GBIT_ETH:
5644 case QETH_LINK_TYPE_LANE_ETH1000: 5738 case QETH_LINK_TYPE_LANE_ETH1000:
5645 ecmd->supported |= SUPPORTED_10baseT_Half | 5739 qeth_set_ecmd_adv_sup(ecmd, SPEED_1000, PORT_FIBRE);
5646 SUPPORTED_10baseT_Full |
5647 SUPPORTED_100baseT_Half |
5648 SUPPORTED_100baseT_Full |
5649 SUPPORTED_1000baseT_Half |
5650 SUPPORTED_1000baseT_Full |
5651 SUPPORTED_FIBRE;
5652 ecmd->advertising |= ADVERTISED_10baseT_Half |
5653 ADVERTISED_10baseT_Full |
5654 ADVERTISED_100baseT_Half |
5655 ADVERTISED_100baseT_Full |
5656 ADVERTISED_1000baseT_Half |
5657 ADVERTISED_1000baseT_Full |
5658 ADVERTISED_FIBRE;
5659 ecmd->speed = SPEED_1000; 5740 ecmd->speed = SPEED_1000;
5660 ecmd->port = PORT_FIBRE; 5741 ecmd->port = PORT_FIBRE;
5661 break; 5742 break;
5662 5743
5663 case QETH_LINK_TYPE_10GBIT_ETH: 5744 case QETH_LINK_TYPE_10GBIT_ETH:
5664 ecmd->supported |= SUPPORTED_10baseT_Half | 5745 qeth_set_ecmd_adv_sup(ecmd, SPEED_10000, PORT_FIBRE);
5665 SUPPORTED_10baseT_Full |
5666 SUPPORTED_100baseT_Half |
5667 SUPPORTED_100baseT_Full |
5668 SUPPORTED_1000baseT_Half |
5669 SUPPORTED_1000baseT_Full |
5670 SUPPORTED_10000baseT_Full |
5671 SUPPORTED_FIBRE;
5672 ecmd->advertising |= ADVERTISED_10baseT_Half |
5673 ADVERTISED_10baseT_Full |
5674 ADVERTISED_100baseT_Half |
5675 ADVERTISED_100baseT_Full |
5676 ADVERTISED_1000baseT_Half |
5677 ADVERTISED_1000baseT_Full |
5678 ADVERTISED_10000baseT_Full |
5679 ADVERTISED_FIBRE;
5680 ecmd->speed = SPEED_10000; 5746 ecmd->speed = SPEED_10000;
5681 ecmd->port = PORT_FIBRE; 5747 ecmd->port = PORT_FIBRE;
5682 break; 5748 break;
5683 5749
5684 default: 5750 default:
5685 ecmd->supported |= SUPPORTED_10baseT_Half | 5751 qeth_set_ecmd_adv_sup(ecmd, SPEED_10, PORT_TP);
5686 SUPPORTED_10baseT_Full |
5687 SUPPORTED_TP;
5688 ecmd->advertising |= ADVERTISED_10baseT_Half |
5689 ADVERTISED_10baseT_Full |
5690 ADVERTISED_TP;
5691 ecmd->speed = SPEED_10; 5752 ecmd->speed = SPEED_10;
5692 ecmd->port = PORT_TP; 5753 ecmd->port = PORT_TP;
5693 } 5754 }
5694 5755
5756 /* Check if we can obtain more accurate information. */
5757 /* If QUERY_CARD_INFO command is not supported or fails, */
5758 /* just return the heuristics that was filled above. */
5759 if (qeth_query_card_info(card, &carrier_info) != 0)
5760 return 0;
5761
5762 netdev_dbg(netdev,
5763 "card info: card_type=0x%02x, port_mode=0x%04x, port_speed=0x%08x\n",
5764 carrier_info.card_type,
5765 carrier_info.port_mode,
5766 carrier_info.port_speed);
5767
5768 /* Update attributes for which we've obtained more authoritative */
5769 /* information, leave the rest the way they where filled above. */
5770 switch (carrier_info.card_type) {
5771 case CARD_INFO_TYPE_1G_COPPER_A:
5772 case CARD_INFO_TYPE_1G_COPPER_B:
5773 qeth_set_ecmd_adv_sup(ecmd, SPEED_1000, PORT_TP);
5774 ecmd->port = PORT_TP;
5775 break;
5776 case CARD_INFO_TYPE_1G_FIBRE_A:
5777 case CARD_INFO_TYPE_1G_FIBRE_B:
5778 qeth_set_ecmd_adv_sup(ecmd, SPEED_1000, PORT_FIBRE);
5779 ecmd->port = PORT_FIBRE;
5780 break;
5781 case CARD_INFO_TYPE_10G_FIBRE_A:
5782 case CARD_INFO_TYPE_10G_FIBRE_B:
5783 qeth_set_ecmd_adv_sup(ecmd, SPEED_10000, PORT_FIBRE);
5784 ecmd->port = PORT_FIBRE;
5785 break;
5786 }
5787
5788 switch (carrier_info.port_mode) {
5789 case CARD_INFO_PORTM_FULLDUPLEX:
5790 ecmd->duplex = DUPLEX_FULL;
5791 break;
5792 case CARD_INFO_PORTM_HALFDUPLEX:
5793 ecmd->duplex = DUPLEX_HALF;
5794 break;
5795 }
5796
5797 switch (carrier_info.port_speed) {
5798 case CARD_INFO_PORTS_10M:
5799 ecmd->speed = SPEED_10;
5800 break;
5801 case CARD_INFO_PORTS_100M:
5802 ecmd->speed = SPEED_100;
5803 break;
5804 case CARD_INFO_PORTS_1G:
5805 ecmd->speed = SPEED_1000;
5806 break;
5807 case CARD_INFO_PORTS_10G:
5808 ecmd->speed = SPEED_10000;
5809 break;
5810 }
5811
5695 return 0; 5812 return 0;
5696} 5813}
5697EXPORT_SYMBOL_GPL(qeth_core_ethtool_get_settings); 5814EXPORT_SYMBOL_GPL(qeth_core_ethtool_get_settings);
diff --git a/drivers/s390/net/qeth_core_mpc.c b/drivers/s390/net/qeth_core_mpc.c
index 06c55780005e..7b55768a9592 100644
--- a/drivers/s390/net/qeth_core_mpc.c
+++ b/drivers/s390/net/qeth_core_mpc.c
@@ -249,10 +249,12 @@ static struct ipa_cmd_names qeth_ipa_cmd_names[] = {
249 {IPA_CMD_DELIP, "delip"}, 249 {IPA_CMD_DELIP, "delip"},
250 {IPA_CMD_SETADAPTERPARMS, "setadapterparms"}, 250 {IPA_CMD_SETADAPTERPARMS, "setadapterparms"},
251 {IPA_CMD_SET_DIAG_ASS, "set_diag_ass"}, 251 {IPA_CMD_SET_DIAG_ASS, "set_diag_ass"},
252 {IPA_CMD_SETBRIDGEPORT, "set_bridge_port"},
252 {IPA_CMD_CREATE_ADDR, "create_addr"}, 253 {IPA_CMD_CREATE_ADDR, "create_addr"},
253 {IPA_CMD_DESTROY_ADDR, "destroy_addr"}, 254 {IPA_CMD_DESTROY_ADDR, "destroy_addr"},
254 {IPA_CMD_REGISTER_LOCAL_ADDR, "register_local_addr"}, 255 {IPA_CMD_REGISTER_LOCAL_ADDR, "register_local_addr"},
255 {IPA_CMD_UNREGISTER_LOCAL_ADDR, "unregister_local_addr"}, 256 {IPA_CMD_UNREGISTER_LOCAL_ADDR, "unregister_local_addr"},
257 {IPA_CMD_ADDRESS_CHANGE_NOTIF, "address_change_notification"},
256 {IPA_CMD_UNKNOWN, "unknown"}, 258 {IPA_CMD_UNKNOWN, "unknown"},
257}; 259};
258 260
diff --git a/drivers/s390/net/qeth_core_mpc.h b/drivers/s390/net/qeth_core_mpc.h
index 07085d55f9a1..cf6a90ed42ae 100644
--- a/drivers/s390/net/qeth_core_mpc.h
+++ b/drivers/s390/net/qeth_core_mpc.h
@@ -104,10 +104,12 @@ enum qeth_ipa_cmds {
104 IPA_CMD_DELIP = 0xb7, 104 IPA_CMD_DELIP = 0xb7,
105 IPA_CMD_SETADAPTERPARMS = 0xb8, 105 IPA_CMD_SETADAPTERPARMS = 0xb8,
106 IPA_CMD_SET_DIAG_ASS = 0xb9, 106 IPA_CMD_SET_DIAG_ASS = 0xb9,
107 IPA_CMD_SETBRIDGEPORT = 0xbe,
107 IPA_CMD_CREATE_ADDR = 0xc3, 108 IPA_CMD_CREATE_ADDR = 0xc3,
108 IPA_CMD_DESTROY_ADDR = 0xc4, 109 IPA_CMD_DESTROY_ADDR = 0xc4,
109 IPA_CMD_REGISTER_LOCAL_ADDR = 0xd1, 110 IPA_CMD_REGISTER_LOCAL_ADDR = 0xd1,
110 IPA_CMD_UNREGISTER_LOCAL_ADDR = 0xd2, 111 IPA_CMD_UNREGISTER_LOCAL_ADDR = 0xd2,
112 IPA_CMD_ADDRESS_CHANGE_NOTIF = 0xd3,
111 IPA_CMD_UNKNOWN = 0x00 113 IPA_CMD_UNKNOWN = 0x00
112}; 114};
113 115
@@ -274,7 +276,24 @@ enum qeth_ipa_set_access_mode_rc {
274 SET_ACCESS_CTRL_RC_REFLREL_FAILED = 0x0024, 276 SET_ACCESS_CTRL_RC_REFLREL_FAILED = 0x0024,
275 SET_ACCESS_CTRL_RC_REFLREL_DEACT_FAILED = 0x0028, 277 SET_ACCESS_CTRL_RC_REFLREL_DEACT_FAILED = 0x0028,
276}; 278};
277 279enum qeth_card_info_card_type {
280 CARD_INFO_TYPE_1G_COPPER_A = 0x61,
281 CARD_INFO_TYPE_1G_FIBRE_A = 0x71,
282 CARD_INFO_TYPE_10G_FIBRE_A = 0x91,
283 CARD_INFO_TYPE_1G_COPPER_B = 0xb1,
284 CARD_INFO_TYPE_1G_FIBRE_B = 0xa1,
285 CARD_INFO_TYPE_10G_FIBRE_B = 0xc1,
286};
287enum qeth_card_info_port_mode {
288 CARD_INFO_PORTM_HALFDUPLEX = 0x0002,
289 CARD_INFO_PORTM_FULLDUPLEX = 0x0003,
290};
291enum qeth_card_info_port_speed {
292 CARD_INFO_PORTS_10M = 0x00000005,
293 CARD_INFO_PORTS_100M = 0x00000006,
294 CARD_INFO_PORTS_1G = 0x00000007,
295 CARD_INFO_PORTS_10G = 0x00000008,
296};
278 297
279/* (SET)DELIP(M) IPA stuff ***************************************************/ 298/* (SET)DELIP(M) IPA stuff ***************************************************/
280struct qeth_ipacmd_setdelip4 { 299struct qeth_ipacmd_setdelip4 {
@@ -404,6 +423,14 @@ struct qeth_qoat_priv {
404 char *buffer; 423 char *buffer;
405}; 424};
406 425
426struct qeth_query_card_info {
427 __u8 card_type;
428 __u8 reserved1;
429 __u16 port_mode;
430 __u32 port_speed;
431 __u32 reserved2;
432};
433
407struct qeth_ipacmd_setadpparms_hdr { 434struct qeth_ipacmd_setadpparms_hdr {
408 __u32 supp_hw_cmds; 435 __u32 supp_hw_cmds;
409 __u32 reserved1; 436 __u32 reserved1;
@@ -424,6 +451,7 @@ struct qeth_ipacmd_setadpparms {
424 struct qeth_snmp_cmd snmp; 451 struct qeth_snmp_cmd snmp;
425 struct qeth_set_access_ctrl set_access_ctrl; 452 struct qeth_set_access_ctrl set_access_ctrl;
426 struct qeth_query_oat query_oat; 453 struct qeth_query_oat query_oat;
454 struct qeth_query_card_info card_info;
427 __u32 mode; 455 __u32 mode;
428 } data; 456 } data;
429} __attribute__ ((packed)); 457} __attribute__ ((packed));
@@ -474,6 +502,124 @@ struct qeth_ipacmd_diagass {
474 __u8 cdata[64]; 502 __u8 cdata[64];
475} __attribute__ ((packed)); 503} __attribute__ ((packed));
476 504
505/* SETBRIDGEPORT IPA Command: *********************************************/
506enum qeth_ipa_sbp_cmd {
507 IPA_SBP_QUERY_COMMANDS_SUPPORTED = 0x00000000L,
508 IPA_SBP_RESET_BRIDGE_PORT_ROLE = 0x00000001L,
509 IPA_SBP_SET_PRIMARY_BRIDGE_PORT = 0x00000002L,
510 IPA_SBP_SET_SECONDARY_BRIDGE_PORT = 0x00000004L,
511 IPA_SBP_QUERY_BRIDGE_PORTS = 0x00000008L,
512 IPA_SBP_BRIDGE_PORT_STATE_CHANGE = 0x00000010L,
513};
514
515struct net_if_token {
516 __u16 devnum;
517 __u8 cssid;
518 __u8 iid;
519 __u8 ssid;
520 __u8 chpid;
521 __u16 chid;
522} __packed;
523
524struct mac_addr_lnid {
525 __u8 mac[6];
526 __u16 lnid;
527} __packed;
528
529struct qeth_ipacmd_sbp_hdr {
530 __u32 supported_sbp_cmds;
531 __u32 enabled_sbp_cmds;
532 __u16 cmdlength;
533 __u16 reserved1;
534 __u32 command_code;
535 __u16 return_code;
536 __u8 used_total;
537 __u8 seq_no;
538 __u32 reserved2;
539} __packed;
540
541struct qeth_sbp_query_cmds_supp {
542 __u32 supported_cmds;
543 __u32 reserved;
544} __packed;
545
546struct qeth_sbp_reset_role {
547} __packed;
548
549struct qeth_sbp_set_primary {
550 struct net_if_token token;
551} __packed;
552
553struct qeth_sbp_set_secondary {
554} __packed;
555
556struct qeth_sbp_port_entry {
557 __u8 role;
558 __u8 state;
559 __u8 reserved1;
560 __u8 reserved2;
561 struct net_if_token token;
562} __packed;
563
564struct qeth_sbp_query_ports {
565 __u8 primary_bp_supported;
566 __u8 secondary_bp_supported;
567 __u8 num_entries;
568 __u8 entry_length;
569 struct qeth_sbp_port_entry entry[];
570} __packed;
571
572struct qeth_sbp_state_change {
573 __u8 primary_bp_supported;
574 __u8 secondary_bp_supported;
575 __u8 num_entries;
576 __u8 entry_length;
577 struct qeth_sbp_port_entry entry[];
578} __packed;
579
580struct qeth_ipacmd_setbridgeport {
581 struct qeth_ipacmd_sbp_hdr hdr;
582 union {
583 struct qeth_sbp_query_cmds_supp query_cmds_supp;
584 struct qeth_sbp_reset_role reset_role;
585 struct qeth_sbp_set_primary set_primary;
586 struct qeth_sbp_set_secondary set_secondary;
587 struct qeth_sbp_query_ports query_ports;
588 struct qeth_sbp_state_change state_change;
589 } data;
590} __packed;
591
592/* ADDRESS_CHANGE_NOTIFICATION adapter-initiated "command" *******************/
593/* Bitmask for entry->change_code. Both bits may be raised. */
594enum qeth_ipa_addr_change_code {
595 IPA_ADDR_CHANGE_CODE_VLANID = 0x01,
596 IPA_ADDR_CHANGE_CODE_MACADDR = 0x02,
597 IPA_ADDR_CHANGE_CODE_REMOVAL = 0x80, /* else addition */
598};
599enum qeth_ipa_addr_change_retcode {
600 IPA_ADDR_CHANGE_RETCODE_OK = 0x0000,
601 IPA_ADDR_CHANGE_RETCODE_LOSTEVENTS = 0x0010,
602};
603enum qeth_ipa_addr_change_lostmask {
604 IPA_ADDR_CHANGE_MASK_OVERFLOW = 0x01,
605 IPA_ADDR_CHANGE_MASK_STATECHANGE = 0x02,
606};
607
608struct qeth_ipacmd_addr_change_entry {
609 struct net_if_token token;
610 struct mac_addr_lnid addr_lnid;
611 __u8 change_code;
612 __u8 reserved1;
613 __u16 reserved2;
614} __packed;
615
616struct qeth_ipacmd_addr_change {
617 __u8 lost_event_mask;
618 __u8 reserved;
619 __u16 num_entries;
620 struct qeth_ipacmd_addr_change_entry entry[];
621} __packed;
622
477/* Header for each IPA command */ 623/* Header for each IPA command */
478struct qeth_ipacmd_hdr { 624struct qeth_ipacmd_hdr {
479 __u8 command; 625 __u8 command;
@@ -503,6 +649,8 @@ struct qeth_ipa_cmd {
503 struct qeth_ipacmd_setadpparms setadapterparms; 649 struct qeth_ipacmd_setadpparms setadapterparms;
504 struct qeth_set_routing setrtg; 650 struct qeth_set_routing setrtg;
505 struct qeth_ipacmd_diagass diagass; 651 struct qeth_ipacmd_diagass diagass;
652 struct qeth_ipacmd_setbridgeport sbp;
653 struct qeth_ipacmd_addr_change addrchange;
506 } data; 654 } data;
507} __attribute__ ((packed)); 655} __attribute__ ((packed));
508 656
diff --git a/drivers/s390/net/qeth_l2.h b/drivers/s390/net/qeth_l2.h
new file mode 100644
index 000000000000..0767556404bd
--- /dev/null
+++ b/drivers/s390/net/qeth_l2.h
@@ -0,0 +1,15 @@
1/*
2 * Copyright IBM Corp. 2013
3 * Author(s): Eugene Crosser <eugene.crosser@ru.ibm.com>
4 */
5
6#ifndef __QETH_L2_H__
7#define __QETH_L2_H__
8
9#include "qeth_core.h"
10
11int qeth_l2_create_device_attributes(struct device *);
12void qeth_l2_remove_device_attributes(struct device *);
13void qeth_l2_setup_bridgeport_attrs(struct qeth_card *card);
14
15#endif /* __QETH_L2_H__ */
diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c
index ec8ccdae7aba..914d2c121fd8 100644
--- a/drivers/s390/net/qeth_l2_main.c
+++ b/drivers/s390/net/qeth_l2_main.c
@@ -21,6 +21,7 @@
21#include <linux/list.h> 21#include <linux/list.h>
22 22
23#include "qeth_core.h" 23#include "qeth_core.h"
24#include "qeth_l2.h"
24 25
25static int qeth_l2_set_offline(struct ccwgroup_device *); 26static int qeth_l2_set_offline(struct ccwgroup_device *);
26static int qeth_l2_stop(struct net_device *); 27static int qeth_l2_stop(struct net_device *);
@@ -880,6 +881,7 @@ static int qeth_l2_probe_device(struct ccwgroup_device *gdev)
880{ 881{
881 struct qeth_card *card = dev_get_drvdata(&gdev->dev); 882 struct qeth_card *card = dev_get_drvdata(&gdev->dev);
882 883
884 qeth_l2_create_device_attributes(&gdev->dev);
883 INIT_LIST_HEAD(&card->vid_list); 885 INIT_LIST_HEAD(&card->vid_list);
884 INIT_LIST_HEAD(&card->mc_list); 886 INIT_LIST_HEAD(&card->mc_list);
885 card->options.layer2 = 1; 887 card->options.layer2 = 1;
@@ -891,6 +893,7 @@ static void qeth_l2_remove_device(struct ccwgroup_device *cgdev)
891{ 893{
892 struct qeth_card *card = dev_get_drvdata(&cgdev->dev); 894 struct qeth_card *card = dev_get_drvdata(&cgdev->dev);
893 895
896 qeth_l2_remove_device_attributes(&cgdev->dev);
894 qeth_set_allowed_threads(card, 0, 1); 897 qeth_set_allowed_threads(card, 0, 1);
895 wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0); 898 wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0);
896 899
@@ -1003,6 +1006,8 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)
1003 } else 1006 } else
1004 card->info.hwtrap = 0; 1007 card->info.hwtrap = 0;
1005 1008
1009 qeth_l2_setup_bridgeport_attrs(card);
1010
1006 card->state = CARD_STATE_HARDSETUP; 1011 card->state = CARD_STATE_HARDSETUP;
1007 memset(&card->rx, 0, sizeof(struct qeth_rx)); 1012 memset(&card->rx, 0, sizeof(struct qeth_rx));
1008 qeth_print_status_message(card); 1013 qeth_print_status_message(card);
@@ -1347,6 +1352,595 @@ void qeth_osn_deregister(struct net_device *dev)
1347} 1352}
1348EXPORT_SYMBOL(qeth_osn_deregister); 1353EXPORT_SYMBOL(qeth_osn_deregister);
1349 1354
1355/* SETBRIDGEPORT support, async notifications */
1356
1357enum qeth_an_event_type {anev_reg_unreg, anev_abort, anev_reset};
1358
1359/**
1360 * qeth_bridge_emit_host_event() - bridgeport address change notification
1361 * @card: qeth_card structure pointer, for udev events.
1362 * @evtype: "normal" register/unregister, or abort, or reset. For abort
1363 * and reset token and addr_lnid are unused and may be NULL.
1364 * @code: event bitmask: high order bit 0x80 value 1 means removal of an
1365 * object, 0 - addition of an object.
1366 * 0x01 - VLAN, 0x02 - MAC, 0x03 - VLAN and MAC.
1367 * @token: "network token" structure identifying physical address of the port.
1368 * @addr_lnid: pointer to structure with MAC address and VLAN ID.
1369 *
1370 * This function is called when registrations and deregistrations are
1371 * reported by the hardware, and also when notifications are enabled -
1372 * for all currently registered addresses.
1373 */
1374static void qeth_bridge_emit_host_event(struct qeth_card *card,
1375 enum qeth_an_event_type evtype,
1376 u8 code, struct net_if_token *token, struct mac_addr_lnid *addr_lnid)
1377{
1378 char str[7][32];
1379 char *env[8];
1380 int i = 0;
1381
1382 switch (evtype) {
1383 case anev_reg_unreg:
1384 snprintf(str[i], sizeof(str[i]), "BRIDGEDHOST=%s",
1385 (code & IPA_ADDR_CHANGE_CODE_REMOVAL)
1386 ? "deregister" : "register");
1387 env[i] = str[i]; i++;
1388 if (code & IPA_ADDR_CHANGE_CODE_VLANID) {
1389 snprintf(str[i], sizeof(str[i]), "VLAN=%d",
1390 addr_lnid->lnid);
1391 env[i] = str[i]; i++;
1392 }
1393 if (code & IPA_ADDR_CHANGE_CODE_MACADDR) {
1394 snprintf(str[i], sizeof(str[i]), "MAC=%pM6",
1395 &addr_lnid->mac);
1396 env[i] = str[i]; i++;
1397 }
1398 snprintf(str[i], sizeof(str[i]), "NTOK_BUSID=%x.%x.%04x",
1399 token->cssid, token->ssid, token->devnum);
1400 env[i] = str[i]; i++;
1401 snprintf(str[i], sizeof(str[i]), "NTOK_IID=%02x", token->iid);
1402 env[i] = str[i]; i++;
1403 snprintf(str[i], sizeof(str[i]), "NTOK_CHPID=%02x",
1404 token->chpid);
1405 env[i] = str[i]; i++;
1406 snprintf(str[i], sizeof(str[i]), "NTOK_CHID=%04x", token->chid);
1407 env[i] = str[i]; i++;
1408 break;
1409 case anev_abort:
1410 snprintf(str[i], sizeof(str[i]), "BRIDGEDHOST=abort");
1411 env[i] = str[i]; i++;
1412 break;
1413 case anev_reset:
1414 snprintf(str[i], sizeof(str[i]), "BRIDGEDHOST=reset");
1415 env[i] = str[i]; i++;
1416 break;
1417 }
1418 env[i] = NULL;
1419 kobject_uevent_env(&card->gdev->dev.kobj, KOBJ_CHANGE, env);
1420}
1421
1422struct qeth_bridge_state_data {
1423 struct work_struct worker;
1424 struct qeth_card *card;
1425 struct qeth_sbp_state_change qports;
1426};
1427
1428static void qeth_bridge_state_change_worker(struct work_struct *work)
1429{
1430 struct qeth_bridge_state_data *data =
1431 container_of(work, struct qeth_bridge_state_data, worker);
1432 /* We are only interested in the first entry - local port */
1433 struct qeth_sbp_port_entry *entry = &data->qports.entry[0];
1434 char env_locrem[32];
1435 char env_role[32];
1436 char env_state[32];
1437 char *env[] = {
1438 env_locrem,
1439 env_role,
1440 env_state,
1441 NULL
1442 };
1443
1444 /* Role should not change by itself, but if it did, */
1445 /* information from the hardware is authoritative. */
1446 mutex_lock(&data->card->conf_mutex);
1447 data->card->options.sbp.role = entry->role;
1448 mutex_unlock(&data->card->conf_mutex);
1449
1450 snprintf(env_locrem, sizeof(env_locrem), "BRIDGEPORT=statechange");
1451 snprintf(env_role, sizeof(env_role), "ROLE=%s",
1452 (entry->role == QETH_SBP_ROLE_NONE) ? "none" :
1453 (entry->role == QETH_SBP_ROLE_PRIMARY) ? "primary" :
1454 (entry->role == QETH_SBP_ROLE_SECONDARY) ? "secondary" :
1455 "<INVALID>");
1456 snprintf(env_state, sizeof(env_state), "STATE=%s",
1457 (entry->state == QETH_SBP_STATE_INACTIVE) ? "inactive" :
1458 (entry->state == QETH_SBP_STATE_STANDBY) ? "standby" :
1459 (entry->state == QETH_SBP_STATE_ACTIVE) ? "active" :
1460 "<INVALID>");
1461 kobject_uevent_env(&data->card->gdev->dev.kobj,
1462 KOBJ_CHANGE, env);
1463 kfree(data);
1464}
1465
1466void qeth_bridge_state_change(struct qeth_card *card, struct qeth_ipa_cmd *cmd)
1467{
1468 struct qeth_sbp_state_change *qports =
1469 &cmd->data.sbp.data.state_change;
1470 struct qeth_bridge_state_data *data;
1471 int extrasize;
1472
1473 QETH_CARD_TEXT(card, 2, "brstchng");
1474 if (qports->entry_length != sizeof(struct qeth_sbp_port_entry)) {
1475 QETH_CARD_TEXT_(card, 2, "BPsz%.8d", qports->entry_length);
1476 return;
1477 }
1478 extrasize = sizeof(struct qeth_sbp_port_entry) * qports->num_entries;
1479 data = kzalloc(sizeof(struct qeth_bridge_state_data) + extrasize,
1480 GFP_ATOMIC);
1481 if (!data) {
1482 QETH_CARD_TEXT(card, 2, "BPSalloc");
1483 return;
1484 }
1485 INIT_WORK(&data->worker, qeth_bridge_state_change_worker);
1486 data->card = card;
1487 memcpy(&data->qports, qports,
1488 sizeof(struct qeth_sbp_state_change) + extrasize);
1489 queue_work(qeth_wq, &data->worker);
1490}
1491EXPORT_SYMBOL(qeth_bridge_state_change);
1492
1493struct qeth_bridge_host_data {
1494 struct work_struct worker;
1495 struct qeth_card *card;
1496 struct qeth_ipacmd_addr_change hostevs;
1497};
1498
1499static void qeth_bridge_host_event_worker(struct work_struct *work)
1500{
1501 struct qeth_bridge_host_data *data =
1502 container_of(work, struct qeth_bridge_host_data, worker);
1503 int i;
1504
1505 if (data->hostevs.lost_event_mask) {
1506 dev_info(&data->card->gdev->dev,
1507"Address notification from the HiperSockets Bridge Port stopped %s (%s)\n",
1508 data->card->dev->name,
1509 (data->hostevs.lost_event_mask == 0x01)
1510 ? "Overflow"
1511 : (data->hostevs.lost_event_mask == 0x02)
1512 ? "Bridge port state change"
1513 : "Unknown reason");
1514 mutex_lock(&data->card->conf_mutex);
1515 data->card->options.sbp.hostnotification = 0;
1516 mutex_unlock(&data->card->conf_mutex);
1517 qeth_bridge_emit_host_event(data->card, anev_abort,
1518 0, NULL, NULL);
1519 } else
1520 for (i = 0; i < data->hostevs.num_entries; i++) {
1521 struct qeth_ipacmd_addr_change_entry *entry =
1522 &data->hostevs.entry[i];
1523 qeth_bridge_emit_host_event(data->card,
1524 anev_reg_unreg,
1525 entry->change_code,
1526 &entry->token, &entry->addr_lnid);
1527 }
1528 kfree(data);
1529}
1530
1531void qeth_bridge_host_event(struct qeth_card *card, struct qeth_ipa_cmd *cmd)
1532{
1533 struct qeth_ipacmd_addr_change *hostevs =
1534 &cmd->data.addrchange;
1535 struct qeth_bridge_host_data *data;
1536 int extrasize;
1537
1538 QETH_CARD_TEXT(card, 2, "brhostev");
1539 if (cmd->hdr.return_code != 0x0000) {
1540 if (cmd->hdr.return_code == 0x0010) {
1541 if (hostevs->lost_event_mask == 0x00)
1542 hostevs->lost_event_mask = 0xff;
1543 } else {
1544 QETH_CARD_TEXT_(card, 2, "BPHe%04x",
1545 cmd->hdr.return_code);
1546 return;
1547 }
1548 }
1549 extrasize = sizeof(struct qeth_ipacmd_addr_change_entry) *
1550 hostevs->num_entries;
1551 data = kzalloc(sizeof(struct qeth_bridge_host_data) + extrasize,
1552 GFP_ATOMIC);
1553 if (!data) {
1554 QETH_CARD_TEXT(card, 2, "BPHalloc");
1555 return;
1556 }
1557 INIT_WORK(&data->worker, qeth_bridge_host_event_worker);
1558 data->card = card;
1559 memcpy(&data->hostevs, hostevs,
1560 sizeof(struct qeth_ipacmd_addr_change) + extrasize);
1561 queue_work(qeth_wq, &data->worker);
1562}
1563EXPORT_SYMBOL(qeth_bridge_host_event);
1564
1565/* SETBRIDGEPORT support; sending commands */
1566
1567struct _qeth_sbp_cbctl {
1568 u16 ipa_rc;
1569 u16 cmd_rc;
1570 union {
1571 u32 supported;
1572 struct {
1573 enum qeth_sbp_roles *role;
1574 enum qeth_sbp_states *state;
1575 } qports;
1576 } data;
1577};
1578
1579/**
1580 * qeth_bridgeport_makerc() - derive "traditional" error from hardware codes.
1581 * @card: qeth_card structure pointer, for debug messages.
1582 * @cbctl: state structure with hardware return codes.
1583 * @setcmd: IPA command code
1584 *
1585 * Returns negative errno-compatible error indication or 0 on success.
1586 */
1587static int qeth_bridgeport_makerc(struct qeth_card *card,
1588 struct _qeth_sbp_cbctl *cbctl, enum qeth_ipa_sbp_cmd setcmd)
1589{
1590 int rc;
1591
1592 switch (cbctl->ipa_rc) {
1593 case IPA_RC_SUCCESS:
1594 switch (cbctl->cmd_rc) {
1595 case 0x0000:
1596 rc = 0;
1597 break;
1598 case 0x0004:
1599 rc = -ENOSYS;
1600 break;
1601 case 0x000C: /* Not configured as bridge Port */
1602 rc = -ENODEV; /* maybe not the best code here? */
1603 dev_err(&card->gdev->dev,
1604 "The HiperSockets device is not configured as a Bridge Port\n");
1605 break;
1606 case 0x0014: /* Another device is Primary */
1607 switch (setcmd) {
1608 case IPA_SBP_SET_PRIMARY_BRIDGE_PORT:
1609 rc = -EEXIST;
1610 dev_err(&card->gdev->dev,
1611 "The HiperSockets LAN already has a primary Bridge Port\n");
1612 break;
1613 case IPA_SBP_SET_SECONDARY_BRIDGE_PORT:
1614 rc = -EBUSY;
1615 dev_err(&card->gdev->dev,
1616 "The HiperSockets device is already a primary Bridge Port\n");
1617 break;
1618 default:
1619 rc = -EIO;
1620 }
1621 break;
1622 case 0x0018: /* This device is currently Secondary */
1623 rc = -EBUSY;
1624 dev_err(&card->gdev->dev,
1625 "The HiperSockets device is already a secondary Bridge Port\n");
1626 break;
1627 case 0x001C: /* Limit for Secondary devices reached */
1628 rc = -EEXIST;
1629 dev_err(&card->gdev->dev,
1630 "The HiperSockets LAN cannot have more secondary Bridge Ports\n");
1631 break;
1632 case 0x0024: /* This device is currently Primary */
1633 rc = -EBUSY;
1634 dev_err(&card->gdev->dev,
1635 "The HiperSockets device is already a primary Bridge Port\n");
1636 break;
1637 case 0x0020: /* Not authorized by zManager */
1638 rc = -EACCES;
1639 dev_err(&card->gdev->dev,
1640 "The HiperSockets device is not authorized to be a Bridge Port\n");
1641 break;
1642 default:
1643 rc = -EIO;
1644 }
1645 break;
1646 case IPA_RC_NOTSUPP:
1647 rc = -ENOSYS;
1648 break;
1649 case IPA_RC_UNSUPPORTED_COMMAND:
1650 rc = -ENOSYS;
1651 break;
1652 default:
1653 rc = -EIO;
1654 }
1655 if (rc) {
1656 QETH_CARD_TEXT_(card, 2, "SBPi%04x", cbctl->ipa_rc);
1657 QETH_CARD_TEXT_(card, 2, "SBPc%04x", cbctl->cmd_rc);
1658 }
1659 return rc;
1660}
1661
1662static int qeth_bridgeport_query_support_cb(struct qeth_card *card,
1663 struct qeth_reply *reply, unsigned long data)
1664{
1665 struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data;
1666 struct _qeth_sbp_cbctl *cbctl = (struct _qeth_sbp_cbctl *)reply->param;
1667 QETH_CARD_TEXT(card, 2, "brqsupcb");
1668 cbctl->ipa_rc = cmd->hdr.return_code;
1669 cbctl->cmd_rc = cmd->data.sbp.hdr.return_code;
1670 if ((cbctl->ipa_rc == 0) && (cbctl->cmd_rc == 0)) {
1671 cbctl->data.supported =
1672 cmd->data.sbp.data.query_cmds_supp.supported_cmds;
1673 } else {
1674 cbctl->data.supported = 0;
1675 }
1676 return 0;
1677}
1678
1679/**
1680 * qeth_bridgeport_query_support() - store bitmask of supported subfunctions.
1681 * @card: qeth_card structure pointer.
1682 *
1683 * Sets bitmask of supported setbridgeport subfunctions in the qeth_card
1684 * strucutre: card->options.sbp.supported_funcs.
1685 */
1686void qeth_bridgeport_query_support(struct qeth_card *card)
1687{
1688 struct qeth_cmd_buffer *iob;
1689 struct qeth_ipa_cmd *cmd;
1690 struct _qeth_sbp_cbctl cbctl;
1691
1692 QETH_CARD_TEXT(card, 2, "brqsuppo");
1693 iob = qeth_get_ipacmd_buffer(card, IPA_CMD_SETBRIDGEPORT, 0);
1694 cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
1695 cmd->data.sbp.hdr.cmdlength =
1696 sizeof(struct qeth_ipacmd_sbp_hdr) +
1697 sizeof(struct qeth_sbp_query_cmds_supp);
1698 cmd->data.sbp.hdr.command_code =
1699 IPA_SBP_QUERY_COMMANDS_SUPPORTED;
1700 cmd->data.sbp.hdr.used_total = 1;
1701 cmd->data.sbp.hdr.seq_no = 1;
1702 if (qeth_send_ipa_cmd(card, iob, qeth_bridgeport_query_support_cb,
1703 (void *)&cbctl) ||
1704 qeth_bridgeport_makerc(card, &cbctl,
1705 IPA_SBP_QUERY_COMMANDS_SUPPORTED)) {
1706 /* non-zero makerc signifies failure, and produce messages */
1707 card->options.sbp.role = QETH_SBP_ROLE_NONE;
1708 return;
1709 }
1710 card->options.sbp.supported_funcs = cbctl.data.supported;
1711}
1712EXPORT_SYMBOL_GPL(qeth_bridgeport_query_support);
1713
1714static int qeth_bridgeport_query_ports_cb(struct qeth_card *card,
1715 struct qeth_reply *reply, unsigned long data)
1716{
1717 struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data;
1718 struct qeth_sbp_query_ports *qports = &cmd->data.sbp.data.query_ports;
1719 struct _qeth_sbp_cbctl *cbctl = (struct _qeth_sbp_cbctl *)reply->param;
1720
1721 QETH_CARD_TEXT(card, 2, "brqprtcb");
1722 cbctl->ipa_rc = cmd->hdr.return_code;
1723 cbctl->cmd_rc = cmd->data.sbp.hdr.return_code;
1724 if ((cbctl->ipa_rc != 0) || (cbctl->cmd_rc != 0))
1725 return 0;
1726 if (qports->entry_length != sizeof(struct qeth_sbp_port_entry)) {
1727 cbctl->cmd_rc = 0xffff;
1728 QETH_CARD_TEXT_(card, 2, "SBPs%04x", qports->entry_length);
1729 return 0;
1730 }
1731 /* first entry contains the state of the local port */
1732 if (qports->num_entries > 0) {
1733 if (cbctl->data.qports.role)
1734 *cbctl->data.qports.role = qports->entry[0].role;
1735 if (cbctl->data.qports.state)
1736 *cbctl->data.qports.state = qports->entry[0].state;
1737 }
1738 return 0;
1739}
1740
1741/**
1742 * qeth_bridgeport_query_ports() - query local bridgeport status.
1743 * @card: qeth_card structure pointer.
1744 * @role: Role of the port: 0-none, 1-primary, 2-secondary.
1745 * @state: State of the port: 0-inactive, 1-standby, 2-active.
1746 *
1747 * Returns negative errno-compatible error indication or 0 on success.
1748 *
1749 * 'role' and 'state' are not updated in case of hardware operation failure.
1750 */
1751int qeth_bridgeport_query_ports(struct qeth_card *card,
1752 enum qeth_sbp_roles *role, enum qeth_sbp_states *state)
1753{
1754 int rc = 0;
1755 struct qeth_cmd_buffer *iob;
1756 struct qeth_ipa_cmd *cmd;
1757 struct _qeth_sbp_cbctl cbctl = {
1758 .data = {
1759 .qports = {
1760 .role = role,
1761 .state = state,
1762 },
1763 },
1764 };
1765
1766 QETH_CARD_TEXT(card, 2, "brqports");
1767 if (!(card->options.sbp.supported_funcs & IPA_SBP_QUERY_BRIDGE_PORTS))
1768 return -EOPNOTSUPP;
1769 iob = qeth_get_ipacmd_buffer(card, IPA_CMD_SETBRIDGEPORT, 0);
1770 cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
1771 cmd->data.sbp.hdr.cmdlength =
1772 sizeof(struct qeth_ipacmd_sbp_hdr);
1773 cmd->data.sbp.hdr.command_code =
1774 IPA_SBP_QUERY_BRIDGE_PORTS;
1775 cmd->data.sbp.hdr.used_total = 1;
1776 cmd->data.sbp.hdr.seq_no = 1;
1777 rc = qeth_send_ipa_cmd(card, iob, qeth_bridgeport_query_ports_cb,
1778 (void *)&cbctl);
1779 if (rc)
1780 return rc;
1781 rc = qeth_bridgeport_makerc(card, &cbctl, IPA_SBP_QUERY_BRIDGE_PORTS);
1782 if (rc)
1783 return rc;
1784 return 0;
1785}
1786EXPORT_SYMBOL_GPL(qeth_bridgeport_query_ports);
1787
1788static int qeth_bridgeport_set_cb(struct qeth_card *card,
1789 struct qeth_reply *reply, unsigned long data)
1790{
1791 struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *)data;
1792 struct _qeth_sbp_cbctl *cbctl = (struct _qeth_sbp_cbctl *)reply->param;
1793 QETH_CARD_TEXT(card, 2, "brsetrcb");
1794 cbctl->ipa_rc = cmd->hdr.return_code;
1795 cbctl->cmd_rc = cmd->data.sbp.hdr.return_code;
1796 return 0;
1797}
1798
1799/**
1800 * qeth_bridgeport_setrole() - Assign primary role to the port.
1801 * @card: qeth_card structure pointer.
1802 * @role: Role to assign.
1803 *
1804 * Returns negative errno-compatible error indication or 0 on success.
1805 */
1806int qeth_bridgeport_setrole(struct qeth_card *card, enum qeth_sbp_roles role)
1807{
1808 int rc = 0;
1809 int cmdlength;
1810 struct qeth_cmd_buffer *iob;
1811 struct qeth_ipa_cmd *cmd;
1812 struct _qeth_sbp_cbctl cbctl;
1813 enum qeth_ipa_sbp_cmd setcmd;
1814
1815 QETH_CARD_TEXT(card, 2, "brsetrol");
1816 switch (role) {
1817 case QETH_SBP_ROLE_NONE:
1818 setcmd = IPA_SBP_RESET_BRIDGE_PORT_ROLE;
1819 cmdlength = sizeof(struct qeth_ipacmd_sbp_hdr) +
1820 sizeof(struct qeth_sbp_reset_role);
1821 break;
1822 case QETH_SBP_ROLE_PRIMARY:
1823 setcmd = IPA_SBP_SET_PRIMARY_BRIDGE_PORT;
1824 cmdlength = sizeof(struct qeth_ipacmd_sbp_hdr) +
1825 sizeof(struct qeth_sbp_set_primary);
1826 break;
1827 case QETH_SBP_ROLE_SECONDARY:
1828 setcmd = IPA_SBP_SET_SECONDARY_BRIDGE_PORT;
1829 cmdlength = sizeof(struct qeth_ipacmd_sbp_hdr) +
1830 sizeof(struct qeth_sbp_set_secondary);
1831 break;
1832 default:
1833 return -EINVAL;
1834 }
1835 if (!(card->options.sbp.supported_funcs & setcmd))
1836 return -EOPNOTSUPP;
1837 iob = qeth_get_ipacmd_buffer(card, IPA_CMD_SETBRIDGEPORT, 0);
1838 cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
1839 cmd->data.sbp.hdr.cmdlength = cmdlength;
1840 cmd->data.sbp.hdr.command_code = setcmd;
1841 cmd->data.sbp.hdr.used_total = 1;
1842 cmd->data.sbp.hdr.seq_no = 1;
1843 rc = qeth_send_ipa_cmd(card, iob, qeth_bridgeport_set_cb,
1844 (void *)&cbctl);
1845 if (rc)
1846 return rc;
1847 rc = qeth_bridgeport_makerc(card, &cbctl, setcmd);
1848 return rc;
1849}
1850
1851/**
1852 * qeth_anset_makerc() - derive "traditional" error from hardware codes.
1853 * @card: qeth_card structure pointer, for debug messages.
1854 *
1855 * Returns negative errno-compatible error indication or 0 on success.
1856 */
1857static int qeth_anset_makerc(struct qeth_card *card, int pnso_rc, u16 response)
1858{
1859 int rc;
1860
1861 if (pnso_rc == 0)
1862 switch (response) {
1863 case 0x0001:
1864 rc = 0;
1865 break;
1866 case 0x0004:
1867 case 0x0100:
1868 case 0x0106:
1869 rc = -ENOSYS;
1870 dev_err(&card->gdev->dev,
1871 "Setting address notification failed\n");
1872 break;
1873 case 0x0107:
1874 rc = -EAGAIN;
1875 break;
1876 default:
1877 rc = -EIO;
1878 }
1879 else
1880 rc = -EIO;
1881
1882 if (rc) {
1883 QETH_CARD_TEXT_(card, 2, "SBPp%04x", pnso_rc);
1884 QETH_CARD_TEXT_(card, 2, "SBPr%04x", response);
1885 }
1886 return rc;
1887}
1888
1889static void qeth_bridgeport_an_set_cb(void *priv,
1890 enum qdio_brinfo_entry_type type, void *entry)
1891{
1892 struct qeth_card *card = (struct qeth_card *)priv;
1893 struct qdio_brinfo_entry_l2 *l2entry;
1894 u8 code;
1895
1896 if (type != l2_addr_lnid) {
1897 WARN_ON_ONCE(1);
1898 return;
1899 }
1900
1901 l2entry = (struct qdio_brinfo_entry_l2 *)entry;
1902 code = IPA_ADDR_CHANGE_CODE_MACADDR;
1903 if (l2entry->addr_lnid.lnid)
1904 code |= IPA_ADDR_CHANGE_CODE_VLANID;
1905 qeth_bridge_emit_host_event(card, anev_reg_unreg, code,
1906 (struct net_if_token *)&l2entry->nit,
1907 (struct mac_addr_lnid *)&l2entry->addr_lnid);
1908}
1909
1910/**
1911 * qeth_bridgeport_an_set() - Enable or disable bridgeport address notification
1912 * @card: qeth_card structure pointer.
1913 * @enable: 0 - disable, non-zero - enable notifications
1914 *
1915 * Returns negative errno-compatible error indication or 0 on success.
1916 *
1917 * On enable, emits a series of address notifications udev events for all
1918 * currently registered hosts.
1919 */
1920int qeth_bridgeport_an_set(struct qeth_card *card, int enable)
1921{
1922 int rc;
1923 u16 response;
1924 struct ccw_device *ddev;
1925 struct subchannel_id schid;
1926
1927 if (!card)
1928 return -EINVAL;
1929 if (!card->options.sbp.supported_funcs)
1930 return -EOPNOTSUPP;
1931 ddev = CARD_DDEV(card);
1932 ccw_device_get_schid(ddev, &schid);
1933
1934 if (enable) {
1935 qeth_bridge_emit_host_event(card, anev_reset, 0, NULL, NULL);
1936 rc = qdio_pnso_brinfo(schid, 1, &response,
1937 qeth_bridgeport_an_set_cb, card);
1938 } else
1939 rc = qdio_pnso_brinfo(schid, 0, &response, NULL, NULL);
1940 return qeth_anset_makerc(card, rc, response);
1941}
1942EXPORT_SYMBOL_GPL(qeth_bridgeport_an_set);
1943
1350module_init(qeth_l2_init); 1944module_init(qeth_l2_init);
1351module_exit(qeth_l2_exit); 1945module_exit(qeth_l2_exit);
1352MODULE_AUTHOR("Frank Blaschka <frank.blaschka@de.ibm.com>"); 1946MODULE_AUTHOR("Frank Blaschka <frank.blaschka@de.ibm.com>");
diff --git a/drivers/s390/net/qeth_l2_sys.c b/drivers/s390/net/qeth_l2_sys.c
new file mode 100644
index 000000000000..ae1bc04b8653
--- /dev/null
+++ b/drivers/s390/net/qeth_l2_sys.c
@@ -0,0 +1,223 @@
1/*
2 * Copyright IBM Corp. 2013
3 * Author(s): Eugene Crosser <eugene.crosser@ru.ibm.com>
4 */
5
6#include <linux/slab.h>
7#include <asm/ebcdic.h>
8#include "qeth_l2.h"
9
10#define QETH_DEVICE_ATTR(_id, _name, _mode, _show, _store) \
11struct device_attribute dev_attr_##_id = __ATTR(_name, _mode, _show, _store)
12
13static int qeth_card_hw_is_reachable(struct qeth_card *card)
14{
15 return (card->state == CARD_STATE_SOFTSETUP) ||
16 (card->state == CARD_STATE_UP);
17}
18
19static ssize_t qeth_bridge_port_role_state_show(struct device *dev,
20 struct device_attribute *attr, char *buf,
21 int show_state)
22{
23 struct qeth_card *card = dev_get_drvdata(dev);
24 enum qeth_sbp_states state = QETH_SBP_STATE_INACTIVE;
25 int rc = 0;
26 char *word;
27
28 if (!card)
29 return -EINVAL;
30
31 mutex_lock(&card->conf_mutex);
32
33 if (qeth_card_hw_is_reachable(card) &&
34 card->options.sbp.supported_funcs)
35 rc = qeth_bridgeport_query_ports(card,
36 &card->options.sbp.role, &state);
37 if (!rc) {
38 if (show_state)
39 switch (state) {
40 case QETH_SBP_STATE_INACTIVE:
41 word = "inactive"; break;
42 case QETH_SBP_STATE_STANDBY:
43 word = "standby"; break;
44 case QETH_SBP_STATE_ACTIVE:
45 word = "active"; break;
46 default:
47 rc = -EIO;
48 }
49 else
50 switch (card->options.sbp.role) {
51 case QETH_SBP_ROLE_NONE:
52 word = "none"; break;
53 case QETH_SBP_ROLE_PRIMARY:
54 word = "primary"; break;
55 case QETH_SBP_ROLE_SECONDARY:
56 word = "secondary"; break;
57 default:
58 rc = -EIO;
59 }
60 if (rc)
61 QETH_CARD_TEXT_(card, 2, "SBP%02x:%02x",
62 card->options.sbp.role, state);
63 else
64 rc = sprintf(buf, "%s\n", word);
65 }
66
67 mutex_unlock(&card->conf_mutex);
68
69 return rc;
70}
71
72static ssize_t qeth_bridge_port_role_show(struct device *dev,
73 struct device_attribute *attr, char *buf)
74{
75 return qeth_bridge_port_role_state_show(dev, attr, buf, 0);
76}
77
78static ssize_t qeth_bridge_port_role_store(struct device *dev,
79 struct device_attribute *attr, const char *buf, size_t count)
80{
81 struct qeth_card *card = dev_get_drvdata(dev);
82 int rc = 0;
83 enum qeth_sbp_roles role;
84
85 if (!card)
86 return -EINVAL;
87 if (sysfs_streq(buf, "primary"))
88 role = QETH_SBP_ROLE_PRIMARY;
89 else if (sysfs_streq(buf, "secondary"))
90 role = QETH_SBP_ROLE_SECONDARY;
91 else if (sysfs_streq(buf, "none"))
92 role = QETH_SBP_ROLE_NONE;
93 else
94 return -EINVAL;
95
96 mutex_lock(&card->conf_mutex);
97
98 if (qeth_card_hw_is_reachable(card)) {
99 rc = qeth_bridgeport_setrole(card, role);
100 if (!rc)
101 card->options.sbp.role = role;
102 } else
103 card->options.sbp.role = role;
104
105 mutex_unlock(&card->conf_mutex);
106
107 return rc ? rc : count;
108}
109
110static DEVICE_ATTR(bridge_role, 0644, qeth_bridge_port_role_show,
111 qeth_bridge_port_role_store);
112
113static ssize_t qeth_bridge_port_state_show(struct device *dev,
114 struct device_attribute *attr, char *buf)
115{
116 return qeth_bridge_port_role_state_show(dev, attr, buf, 1);
117}
118
119static DEVICE_ATTR(bridge_state, 0644, qeth_bridge_port_state_show,
120 NULL);
121
122static ssize_t qeth_bridgeport_hostnotification_show(struct device *dev,
123 struct device_attribute *attr, char *buf)
124{
125 struct qeth_card *card = dev_get_drvdata(dev);
126 int enabled;
127
128 if (!card)
129 return -EINVAL;
130
131 mutex_lock(&card->conf_mutex);
132
133 enabled = card->options.sbp.hostnotification;
134
135 mutex_unlock(&card->conf_mutex);
136
137 return sprintf(buf, "%d\n", enabled);
138}
139
140static ssize_t qeth_bridgeport_hostnotification_store(struct device *dev,
141 struct device_attribute *attr, const char *buf, size_t count)
142{
143 struct qeth_card *card = dev_get_drvdata(dev);
144 int rc = 0;
145 int enable;
146
147 if (!card)
148 return -EINVAL;
149
150 if (sysfs_streq(buf, "0"))
151 enable = 0;
152 else if (sysfs_streq(buf, "1"))
153 enable = 1;
154 else
155 return -EINVAL;
156
157 mutex_lock(&card->conf_mutex);
158
159 if (qeth_card_hw_is_reachable(card)) {
160 rc = qeth_bridgeport_an_set(card, enable);
161 if (!rc)
162 card->options.sbp.hostnotification = enable;
163 } else
164 card->options.sbp.hostnotification = enable;
165
166 mutex_unlock(&card->conf_mutex);
167
168 return rc ? rc : count;
169}
170
171static DEVICE_ATTR(bridge_hostnotify, 0644,
172 qeth_bridgeport_hostnotification_show,
173 qeth_bridgeport_hostnotification_store);
174
175static struct attribute *qeth_l2_bridgeport_attrs[] = {
176 &dev_attr_bridge_role.attr,
177 &dev_attr_bridge_state.attr,
178 &dev_attr_bridge_hostnotify.attr,
179 NULL,
180};
181
182static struct attribute_group qeth_l2_bridgeport_attr_group = {
183 .attrs = qeth_l2_bridgeport_attrs,
184};
185
186int qeth_l2_create_device_attributes(struct device *dev)
187{
188 return sysfs_create_group(&dev->kobj, &qeth_l2_bridgeport_attr_group);
189}
190
191void qeth_l2_remove_device_attributes(struct device *dev)
192{
193 sysfs_remove_group(&dev->kobj, &qeth_l2_bridgeport_attr_group);
194}
195
196/**
197 * qeth_l2_setup_bridgeport_attrs() - set/restore attrs when turning online.
198 * @card: qeth_card structure pointer
199 *
200 * Note: this function is called with conf_mutex held by the caller
201 */
202void qeth_l2_setup_bridgeport_attrs(struct qeth_card *card)
203{
204 int rc;
205
206 if (!card)
207 return;
208 if (!card->options.sbp.supported_funcs)
209 return;
210 if (card->options.sbp.role != QETH_SBP_ROLE_NONE) {
211 /* Conditional to avoid spurious error messages */
212 qeth_bridgeport_setrole(card, card->options.sbp.role);
213 /* Let the callback function refresh the stored role value. */
214 qeth_bridgeport_query_ports(card,
215 &card->options.sbp.role, NULL);
216 }
217 if (card->options.sbp.hostnotification) {
218 rc = qeth_bridgeport_an_set(card, 1);
219 if (rc)
220 card->options.sbp.hostnotification = 0;
221 } else
222 qeth_bridgeport_an_set(card, 0);
223}