blob: 810d69bd9991a4d0bd3fa3121ddb60b7cdb27f73 [file] [log] [blame]
Greg Kroah-Hartmanab9953f2017-11-14 18:38:04 +01001// SPDX-License-Identifier: GPL-2.0
Frank Blaschka4a71df52008-02-15 09:19:42 +01002/*
Frank Blaschkabbcfcdc2009-06-16 10:30:31 +02003 * Copyright IBM Corp. 2007, 2009
Frank Blaschka4a71df52008-02-15 09:19:42 +01004 * Author(s): Utz Bacher <utz.bacher@de.ibm.com>,
5 * Frank Pavlic <fpavlic@de.ibm.com>,
6 * Thomas Spatzier <tspat@de.ibm.com>,
7 * Frank Blaschka <frank.blaschka@de.ibm.com>
8 */
9
Frank Blaschka74eacdb2008-12-25 13:39:49 +010010#define KMSG_COMPONENT "qeth"
11#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
12
Frank Blaschka4a71df52008-02-15 09:19:42 +010013#include <linux/module.h>
14#include <linux/moduleparam.h>
15#include <linux/string.h>
16#include <linux/errno.h>
17#include <linux/kernel.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090018#include <linux/slab.h>
Frank Blaschka4a71df52008-02-15 09:19:42 +010019#include <linux/etherdevice.h>
Jiri Pirkoccffad252009-05-22 23:22:17 +000020#include <linux/list.h>
Lakhvich Dmitriyfe5c8022015-10-06 15:12:28 +020021#include <linux/hash.h>
22#include <linux/hashtable.h>
Julian Wiedmannec61bd22017-06-20 16:00:34 +020023#include <asm/setup.h>
Frank Blaschka4a71df52008-02-15 09:19:42 +010024#include "qeth_core.h"
Eugene Crosserb4d72c02014-01-14 15:54:11 +010025#include "qeth_l2.h"
Frank Blaschka4a71df52008-02-15 09:19:42 +010026
Frank Blaschka4a71df52008-02-15 09:19:42 +010027static int qeth_l2_set_offline(struct ccwgroup_device *);
28static int qeth_l2_stop(struct net_device *);
Lakhvich Dmitriyfe5c8022015-10-06 15:12:28 +020029static void qeth_l2_set_rx_mode(struct net_device *);
Eugene Crosserc044dc22014-01-29 09:23:48 +010030static void qeth_bridgeport_query_support(struct qeth_card *card);
31static void qeth_bridge_state_change(struct qeth_card *card,
32 struct qeth_ipa_cmd *cmd);
33static void qeth_bridge_host_event(struct qeth_card *card,
34 struct qeth_ipa_cmd *cmd);
Hans Wippelcaa1f0b2017-09-18 21:18:15 +020035static void qeth_l2_vnicc_set_defaults(struct qeth_card *card);
Hans Wippela45b3fa2017-09-18 21:18:14 +020036static void qeth_l2_vnicc_init(struct qeth_card *card);
Hans Wippel349d13d2017-09-18 21:18:16 +020037static bool qeth_l2_vnicc_recover_timeout(struct qeth_card *card, u32 vnicc,
38 u32 *timeout);
Frank Blaschka4a71df52008-02-15 09:19:42 +010039
Frank Blaschka4a71df52008-02-15 09:19:42 +010040static struct net_device *qeth_l2_netdev_by_devno(unsigned char *read_dev_no)
41{
42 struct qeth_card *card;
43 struct net_device *ndev;
Cornelia Huckf06f6f32008-06-06 12:37:45 +020044 __u16 temp_dev_no;
Frank Blaschka4a71df52008-02-15 09:19:42 +010045 unsigned long flags;
Cornelia Huckf06f6f32008-06-06 12:37:45 +020046 struct ccw_dev_id read_devid;
Frank Blaschka4a71df52008-02-15 09:19:42 +010047
48 ndev = NULL;
49 memcpy(&temp_dev_no, read_dev_no, 2);
50 read_lock_irqsave(&qeth_core_card_list.rwlock, flags);
51 list_for_each_entry(card, &qeth_core_card_list.list, list) {
Cornelia Huckf06f6f32008-06-06 12:37:45 +020052 ccw_device_get_id(CARD_RDEV(card), &read_devid);
53 if (read_devid.devno == temp_dev_no) {
Frank Blaschka4a71df52008-02-15 09:19:42 +010054 ndev = card->dev;
55 break;
56 }
57 }
58 read_unlock_irqrestore(&qeth_core_card_list.rwlock, flags);
59 return ndev;
60}
61
Julian Wiedmann2aa48672017-09-18 21:18:20 +020062static int qeth_setdelmac_makerc(struct qeth_card *card, int retcode)
Frank Blaschka4a71df52008-02-15 09:19:42 +010063{
Eugene Crosserefbbc1d2015-01-21 13:39:09 +010064 int rc;
Frank Blaschka4a71df52008-02-15 09:19:42 +010065
Eugene Crosserefbbc1d2015-01-21 13:39:09 +010066 if (retcode)
Thomas Richter1aec42b2015-01-21 13:39:10 +010067 QETH_CARD_TEXT_(card, 2, "err%04x", retcode);
Eugene Crosserefbbc1d2015-01-21 13:39:09 +010068 switch (retcode) {
69 case IPA_RC_SUCCESS:
70 rc = 0;
71 break;
72 case IPA_RC_L2_UNSUPPORTED_CMD:
Eugene Crosserffb95252015-05-18 14:27:58 +020073 rc = -EOPNOTSUPP;
Eugene Crosserefbbc1d2015-01-21 13:39:09 +010074 break;
75 case IPA_RC_L2_ADDR_TABLE_FULL:
76 rc = -ENOSPC;
77 break;
78 case IPA_RC_L2_DUP_MAC:
79 case IPA_RC_L2_DUP_LAYER3_MAC:
80 rc = -EEXIST;
81 break;
82 case IPA_RC_L2_MAC_NOT_AUTH_BY_HYP:
83 case IPA_RC_L2_MAC_NOT_AUTH_BY_ADP:
84 rc = -EPERM;
85 break;
86 case IPA_RC_L2_MAC_NOT_FOUND:
87 rc = -ENOENT;
88 break;
Thomas Richter1aec42b2015-01-21 13:39:10 +010089 case -ENOMEM:
90 rc = -ENOMEM;
91 break;
Eugene Crosserefbbc1d2015-01-21 13:39:09 +010092 default:
93 rc = -EIO;
94 break;
Frank Blaschka4a71df52008-02-15 09:19:42 +010095 }
Eugene Crosserefbbc1d2015-01-21 13:39:09 +010096 return rc;
Frank Blaschka4a71df52008-02-15 09:19:42 +010097}
98
Julian Wiedmannac988d72017-01-12 15:48:41 +010099static int qeth_l2_send_setdelmac(struct qeth_card *card, __u8 *mac,
100 enum qeth_ipa_cmds ipacmd)
101{
102 struct qeth_ipa_cmd *cmd;
103 struct qeth_cmd_buffer *iob;
104
105 QETH_CARD_TEXT(card, 2, "L2sdmac");
106 iob = qeth_get_ipacmd_buffer(card, ipacmd, QETH_PROT_IPV4);
107 if (!iob)
108 return -ENOMEM;
Julian Wiedmannff5caa72018-03-09 18:12:52 +0100109 cmd = __ipa_cmd(iob);
Julian Wiedmann99f0b852017-12-20 20:11:01 +0100110 cmd->data.setdelmac.mac_length = ETH_ALEN;
111 ether_addr_copy(cmd->data.setdelmac.mac, mac);
Julian Wiedmann2aa48672017-09-18 21:18:20 +0200112 return qeth_setdelmac_makerc(card, qeth_send_ipa_cmd(card, iob,
113 NULL, NULL));
Julian Wiedmannac988d72017-01-12 15:48:41 +0100114}
115
116static int qeth_l2_send_setmac(struct qeth_card *card, __u8 *mac)
117{
118 int rc;
119
120 QETH_CARD_TEXT(card, 2, "L2Setmac");
121 rc = qeth_l2_send_setdelmac(card, mac, IPA_CMD_SETVMAC);
122 if (rc == 0) {
Julian Wiedmannac988d72017-01-12 15:48:41 +0100123 dev_info(&card->gdev->dev,
Julian Wiedmannbcacfcb2018-04-19 12:52:09 +0200124 "MAC address %pM successfully registered on device %s\n",
125 mac, card->dev->name);
Julian Wiedmannac988d72017-01-12 15:48:41 +0100126 } else {
Julian Wiedmannac988d72017-01-12 15:48:41 +0100127 switch (rc) {
128 case -EEXIST:
129 dev_warn(&card->gdev->dev,
130 "MAC address %pM already exists\n", mac);
131 break;
132 case -EPERM:
133 dev_warn(&card->gdev->dev,
134 "MAC address %pM is not authorized\n", mac);
135 break;
136 }
137 }
138 return rc;
139}
140
Julian Wiedmann8174aa82017-12-20 20:11:00 +0100141static int qeth_l2_write_mac(struct qeth_card *card, u8 *mac)
Frank Blaschka4a71df52008-02-15 09:19:42 +0100142{
Julian Wiedmann8174aa82017-12-20 20:11:00 +0100143 enum qeth_ipa_cmds cmd = is_multicast_ether_addr_64bits(mac) ?
144 IPA_CMD_SETGMAC : IPA_CMD_SETVMAC;
Eugene Crosserefbbc1d2015-01-21 13:39:09 +0100145 int rc;
146
Julian Wiedmann8174aa82017-12-20 20:11:00 +0100147 QETH_CARD_TEXT(card, 2, "L2Wmac");
148 rc = qeth_l2_send_setdelmac(card, mac, cmd);
Eugene Crosserefbbc1d2015-01-21 13:39:09 +0100149 if (rc == -EEXIST)
Julian Wiedmann8174aa82017-12-20 20:11:00 +0100150 QETH_DBF_MESSAGE(2, "MAC %pM already registered on %s\n",
151 mac, QETH_CARD_IFNAME(card));
Eugene Crosserefbbc1d2015-01-21 13:39:09 +0100152 else if (rc)
Julian Wiedmann8174aa82017-12-20 20:11:00 +0100153 QETH_DBF_MESSAGE(2, "Failed to register MAC %pM on %s: %d\n",
154 mac, QETH_CARD_IFNAME(card), rc);
Eugene Crosserefbbc1d2015-01-21 13:39:09 +0100155 return rc;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100156}
157
Julian Wiedmann8174aa82017-12-20 20:11:00 +0100158static int qeth_l2_remove_mac(struct qeth_card *card, u8 *mac)
Frank Blaschka4a71df52008-02-15 09:19:42 +0100159{
Julian Wiedmann8174aa82017-12-20 20:11:00 +0100160 enum qeth_ipa_cmds cmd = is_multicast_ether_addr_64bits(mac) ?
161 IPA_CMD_DELGMAC : IPA_CMD_DELVMAC;
Eugene Crosserefbbc1d2015-01-21 13:39:09 +0100162 int rc;
163
Julian Wiedmann8174aa82017-12-20 20:11:00 +0100164 QETH_CARD_TEXT(card, 2, "L2Rmac");
165 rc = qeth_l2_send_setdelmac(card, mac, cmd);
Eugene Crosserefbbc1d2015-01-21 13:39:09 +0100166 if (rc)
Julian Wiedmann8174aa82017-12-20 20:11:00 +0100167 QETH_DBF_MESSAGE(2, "Failed to delete MAC %pM on %s: %d\n",
168 mac, QETH_CARD_IFNAME(card), rc);
Eugene Crosserefbbc1d2015-01-21 13:39:09 +0100169 return rc;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100170}
171
Julian Wiedmannc07cbf22017-01-12 15:48:37 +0100172static void qeth_l2_del_all_macs(struct qeth_card *card)
Lakhvich Dmitriyfe5c8022015-10-06 15:12:28 +0200173{
174 struct qeth_mac *mac;
175 struct hlist_node *tmp;
176 int i;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100177
178 spin_lock_bh(&card->mclock);
Lakhvich Dmitriyfe5c8022015-10-06 15:12:28 +0200179 hash_for_each_safe(card->mac_htable, i, tmp, mac, hnode) {
Lakhvich Dmitriyfe5c8022015-10-06 15:12:28 +0200180 hash_del(&mac->hnode);
181 kfree(mac);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100182 }
183 spin_unlock_bh(&card->mclock);
184}
185
Julian Wiedmanncef6ff222017-08-15 17:02:46 +0200186static int qeth_l2_get_cast_type(struct qeth_card *card, struct sk_buff *skb)
Frank Blaschka4a71df52008-02-15 09:19:42 +0100187{
Klaus-Dieter Wackerce73e102009-08-26 02:01:08 +0000188 if (card->info.type == QETH_CARD_TYPE_OSN)
189 return RTN_UNSPEC;
190 if (is_broadcast_ether_addr(skb->data))
191 return RTN_BROADCAST;
192 if (is_multicast_ether_addr(skb->data))
193 return RTN_MULTICAST;
194 return RTN_UNSPEC;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100195}
196
Julian Wiedmannae79fe02017-08-18 10:19:05 +0200197static void qeth_l2_fill_header(struct qeth_hdr *hdr, struct sk_buff *skb,
198 int cast_type, unsigned int data_len)
Frank Blaschka4a71df52008-02-15 09:19:42 +0100199{
Frank Blaschka683d7182008-08-01 16:39:13 +0200200 struct vlan_ethhdr *veth = (struct vlan_ethhdr *)skb_mac_header(skb);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100201
202 memset(hdr, 0, sizeof(struct qeth_hdr));
203 hdr->hdr.l2.id = QETH_HEADER_TYPE_LAYER2;
Julian Wiedmannae79fe02017-08-18 10:19:05 +0200204 hdr->hdr.l2.pkt_length = data_len;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100205
206 /* set byte byte 3 to casting flags */
207 if (cast_type == RTN_MULTICAST)
208 hdr->hdr.l2.flags[2] |= QETH_LAYER2_FLAG_MULTICAST;
209 else if (cast_type == RTN_BROADCAST)
210 hdr->hdr.l2.flags[2] |= QETH_LAYER2_FLAG_BROADCAST;
211 else
Klaus-Dieter Wackerce73e102009-08-26 02:01:08 +0000212 hdr->hdr.l2.flags[2] |= QETH_LAYER2_FLAG_UNICAST;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100213
Frank Blaschka4a71df52008-02-15 09:19:42 +0100214 /* VSWITCH relies on the VLAN
215 * information to be present in
216 * the QDIO header */
217 if (veth->h_vlan_proto == __constant_htons(ETH_P_8021Q)) {
218 hdr->hdr.l2.flags[2] |= QETH_LAYER2_FLAG_VLAN;
219 hdr->hdr.l2.vlan_id = ntohs(veth->h_vlan_TCI);
220 }
221}
222
Julian Wiedmann2aa48672017-09-18 21:18:20 +0200223static int qeth_setdelvlan_makerc(struct qeth_card *card, int retcode)
Frank Blaschka4a71df52008-02-15 09:19:42 +0100224{
Julian Wiedmann2aa48672017-09-18 21:18:20 +0200225 if (retcode)
226 QETH_CARD_TEXT_(card, 2, "err%04x", retcode);
227
228 switch (retcode) {
229 case IPA_RC_SUCCESS:
230 return 0;
231 case IPA_RC_L2_INVALID_VLAN_ID:
232 return -EINVAL;
233 case IPA_RC_L2_DUP_VLAN_ID:
234 return -EEXIST;
235 case IPA_RC_L2_VLAN_ID_NOT_FOUND:
236 return -ENOENT;
237 case IPA_RC_L2_VLAN_ID_NOT_ALLOWED:
238 return -EPERM;
239 case -ENOMEM:
240 return -ENOMEM;
241 default:
242 return -EIO;
243 }
244}
245
246static int qeth_l2_send_setdelvlan_cb(struct qeth_card *card,
247 struct qeth_reply *reply,
248 unsigned long data)
249{
250 struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100251
Carsten Otte847a50f2010-06-21 22:57:05 +0000252 QETH_CARD_TEXT(card, 2, "L2sdvcb");
Frank Blaschka4a71df52008-02-15 09:19:42 +0100253 if (cmd->hdr.return_code) {
Julian Wiedmann2aa48672017-09-18 21:18:20 +0200254 QETH_DBF_MESSAGE(2, "Error in processing VLAN %i on %s: 0x%x.\n",
255 cmd->data.setdelvlan.vlan_id,
256 QETH_CARD_IFNAME(card), cmd->hdr.return_code);
Carsten Otte847a50f2010-06-21 22:57:05 +0000257 QETH_CARD_TEXT_(card, 2, "L2VL%4x", cmd->hdr.command);
258 QETH_CARD_TEXT_(card, 2, "err%d", cmd->hdr.return_code);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100259 }
260 return 0;
261}
262
263static int qeth_l2_send_setdelvlan(struct qeth_card *card, __u16 i,
Julian Wiedmann2aa48672017-09-18 21:18:20 +0200264 enum qeth_ipa_cmds ipacmd)
Frank Blaschka4a71df52008-02-15 09:19:42 +0100265{
266 struct qeth_ipa_cmd *cmd;
267 struct qeth_cmd_buffer *iob;
268
Carsten Otte847a50f2010-06-21 22:57:05 +0000269 QETH_CARD_TEXT_(card, 4, "L2sdv%x", ipacmd);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100270 iob = qeth_get_ipacmd_buffer(card, ipacmd, QETH_PROT_IPV4);
Thomas Richter1aec42b2015-01-21 13:39:10 +0100271 if (!iob)
272 return -ENOMEM;
Julian Wiedmannff5caa72018-03-09 18:12:52 +0100273 cmd = __ipa_cmd(iob);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100274 cmd->data.setdelvlan.vlan_id = i;
Julian Wiedmann2aa48672017-09-18 21:18:20 +0200275 return qeth_setdelvlan_makerc(card, qeth_send_ipa_cmd(card, iob,
276 qeth_l2_send_setdelvlan_cb, NULL));
Frank Blaschka4a71df52008-02-15 09:19:42 +0100277}
278
Ursula Braun70919e22011-02-26 22:41:36 -0800279static void qeth_l2_process_vlans(struct qeth_card *card)
Frank Blaschka4a71df52008-02-15 09:19:42 +0100280{
281 struct qeth_vlan_vid *id;
Julian Wiedmannd4ac0242018-04-26 09:42:13 +0200282
Carsten Otte847a50f2010-06-21 22:57:05 +0000283 QETH_CARD_TEXT(card, 3, "L2prcvln");
Julian Wiedmannd4ac0242018-04-26 09:42:13 +0200284 mutex_lock(&card->vid_list_mutex);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100285 list_for_each_entry(id, &card->vid_list, list) {
Ursula Braun70919e22011-02-26 22:41:36 -0800286 qeth_l2_send_setdelvlan(card, id->vid, IPA_CMD_SETVLAN);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100287 }
Julian Wiedmannd4ac0242018-04-26 09:42:13 +0200288 mutex_unlock(&card->vid_list_mutex);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100289}
290
Patrick McHardy80d5c362013-04-19 02:04:28 +0000291static int qeth_l2_vlan_rx_add_vid(struct net_device *dev,
292 __be16 proto, u16 vid)
Frank Blaschka4a71df52008-02-15 09:19:42 +0100293{
Heiko Carstens509e2562008-07-26 02:24:10 -0700294 struct qeth_card *card = dev->ml_priv;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100295 struct qeth_vlan_vid *id;
Thomas Richter1aec42b2015-01-21 13:39:10 +0100296 int rc;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100297
Carsten Otte847a50f2010-06-21 22:57:05 +0000298 QETH_CARD_TEXT_(card, 4, "aid:%d", vid);
Ursula Braun10651db2010-10-01 02:51:13 +0000299 if (!vid)
Jiri Pirko8e586132011-12-08 19:52:37 -0500300 return 0;
Ursula Braun8e98ac42009-03-24 20:57:18 +0000301 if (qeth_wait_for_threads(card, QETH_RECOVER_THREAD)) {
Carsten Otte847a50f2010-06-21 22:57:05 +0000302 QETH_CARD_TEXT(card, 3, "aidREC");
Jiri Pirko8e586132011-12-08 19:52:37 -0500303 return 0;
Ursula Braun8e98ac42009-03-24 20:57:18 +0000304 }
Julian Wiedmannd4ac0242018-04-26 09:42:13 +0200305 id = kmalloc(sizeof(*id), GFP_KERNEL);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100306 if (id) {
307 id->vid = vid;
Thomas Richter1aec42b2015-01-21 13:39:10 +0100308 rc = qeth_l2_send_setdelvlan(card, vid, IPA_CMD_SETVLAN);
309 if (rc) {
310 kfree(id);
311 return rc;
312 }
Julian Wiedmannd4ac0242018-04-26 09:42:13 +0200313 mutex_lock(&card->vid_list_mutex);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100314 list_add_tail(&id->list, &card->vid_list);
Julian Wiedmannd4ac0242018-04-26 09:42:13 +0200315 mutex_unlock(&card->vid_list_mutex);
Jiri Pirko8e586132011-12-08 19:52:37 -0500316 } else {
317 return -ENOMEM;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100318 }
Jiri Pirko8e586132011-12-08 19:52:37 -0500319 return 0;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100320}
321
Patrick McHardy80d5c362013-04-19 02:04:28 +0000322static int qeth_l2_vlan_rx_kill_vid(struct net_device *dev,
323 __be16 proto, u16 vid)
Frank Blaschka4a71df52008-02-15 09:19:42 +0100324{
325 struct qeth_vlan_vid *id, *tmpid = NULL;
Heiko Carstens509e2562008-07-26 02:24:10 -0700326 struct qeth_card *card = dev->ml_priv;
Thomas Richter1aec42b2015-01-21 13:39:10 +0100327 int rc = 0;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100328
Carsten Otte847a50f2010-06-21 22:57:05 +0000329 QETH_CARD_TEXT_(card, 4, "kid:%d", vid);
Ursula Braun8e98ac42009-03-24 20:57:18 +0000330 if (qeth_wait_for_threads(card, QETH_RECOVER_THREAD)) {
Carsten Otte847a50f2010-06-21 22:57:05 +0000331 QETH_CARD_TEXT(card, 3, "kidREC");
Jiri Pirko8e586132011-12-08 19:52:37 -0500332 return 0;
Ursula Braun8e98ac42009-03-24 20:57:18 +0000333 }
Julian Wiedmannd4ac0242018-04-26 09:42:13 +0200334 mutex_lock(&card->vid_list_mutex);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100335 list_for_each_entry(id, &card->vid_list, list) {
336 if (id->vid == vid) {
337 list_del(&id->list);
338 tmpid = id;
339 break;
340 }
341 }
Julian Wiedmannd4ac0242018-04-26 09:42:13 +0200342 mutex_unlock(&card->vid_list_mutex);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100343 if (tmpid) {
Thomas Richter1aec42b2015-01-21 13:39:10 +0100344 rc = qeth_l2_send_setdelvlan(card, vid, IPA_CMD_DELVLAN);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100345 kfree(tmpid);
346 }
Lakhvich Dmitriyfe5c8022015-10-06 15:12:28 +0200347 qeth_l2_set_rx_mode(card->dev);
Thomas Richter1aec42b2015-01-21 13:39:10 +0100348 return rc;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100349}
350
Peter Senna Tschudinb2f4de82015-08-04 17:11:47 +0200351static void qeth_l2_stop_card(struct qeth_card *card, int recovery_mode)
Frank Blaschka4a71df52008-02-15 09:19:42 +0100352{
Peter Tiedemannd11ba0c2008-04-01 10:26:58 +0200353 QETH_DBF_TEXT(SETUP , 2, "stopcard");
354 QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *));
Frank Blaschka4a71df52008-02-15 09:19:42 +0100355
356 qeth_set_allowed_threads(card, 0, 1);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100357 if (card->read.state == CH_STATE_UP &&
358 card->write.state == CH_STATE_UP &&
359 (card->state == CARD_STATE_UP)) {
360 if (recovery_mode &&
361 card->info.type != QETH_CARD_TYPE_OSN) {
362 qeth_l2_stop(card->dev);
363 } else {
364 rtnl_lock();
365 dev_close(card->dev);
366 rtnl_unlock();
367 }
Ursula Braun70919e22011-02-26 22:41:36 -0800368 card->info.mac_bits &= ~QETH_LAYER2_MAC_REGISTERED;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100369 card->state = CARD_STATE_SOFTSETUP;
370 }
371 if (card->state == CARD_STATE_SOFTSETUP) {
Julian Wiedmannc07cbf22017-01-12 15:48:37 +0100372 qeth_l2_del_all_macs(card);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100373 qeth_clear_ipacmd_list(card);
374 card->state = CARD_STATE_HARDSETUP;
375 }
376 if (card->state == CARD_STATE_HARDSETUP) {
377 qeth_qdio_clear_card(card, 0);
378 qeth_clear_qdio_buffers(card);
379 qeth_clear_working_pool_list(card);
380 card->state = CARD_STATE_DOWN;
381 }
382 if (card->state == CARD_STATE_DOWN) {
383 qeth_clear_cmd_buffers(&card->read);
384 qeth_clear_cmd_buffers(&card->write);
385 }
Frank Blaschka4a71df52008-02-15 09:19:42 +0100386}
387
Frank Blaschkaa1c3ed42010-09-07 21:14:42 +0000388static int qeth_l2_process_inbound_buffer(struct qeth_card *card,
389 int budget, int *done)
Frank Blaschka4a71df52008-02-15 09:19:42 +0100390{
Frank Blaschkaa1c3ed42010-09-07 21:14:42 +0000391 int work_done = 0;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100392 struct sk_buff *skb;
393 struct qeth_hdr *hdr;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100394 unsigned int len;
395
Frank Blaschkaa1c3ed42010-09-07 21:14:42 +0000396 *done = 0;
Stefan Raspl18af5c12012-11-19 02:46:50 +0000397 WARN_ON_ONCE(!budget);
Frank Blaschkaa1c3ed42010-09-07 21:14:42 +0000398 while (budget) {
399 skb = qeth_core_get_next_skb(card,
Frank Blaschkab3332932011-08-08 01:33:59 +0000400 &card->qdio.in_q->bufs[card->rx.b_index],
Frank Blaschkaa1c3ed42010-09-07 21:14:42 +0000401 &card->rx.b_element, &card->rx.e_offset, &hdr);
402 if (!skb) {
403 *done = 1;
404 break;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100405 }
Frank Blaschka4a71df52008-02-15 09:19:42 +0100406 switch (hdr->hdr.l2.id) {
407 case QETH_HEADER_TYPE_LAYER2:
Frank Blaschka4a71df52008-02-15 09:19:42 +0100408 skb->protocol = eth_type_trans(skb, skb->dev);
Julian Wiedmann6195b932018-04-26 09:42:17 +0200409 qeth_rx_csum(card, skb, hdr->hdr.l2.flags[1]);
Ursula Braun12883722008-04-01 10:26:56 +0200410 if (skb->protocol == htons(ETH_P_802_2))
411 *((__u32 *)skb->cb) = ++card->seqno.pkt_seqno;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100412 len = skb->len;
Thomas Richter9abfa8c2015-10-06 15:12:27 +0200413 napi_gro_receive(&card->napi, skb);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100414 break;
415 case QETH_HEADER_TYPE_OSN:
Ursula Braun2d488c22008-10-24 11:16:55 +0200416 if (card->info.type == QETH_CARD_TYPE_OSN) {
417 skb_push(skb, sizeof(struct qeth_hdr));
418 skb_copy_to_linear_data(skb, hdr,
Frank Blaschka4a71df52008-02-15 09:19:42 +0100419 sizeof(struct qeth_hdr));
Ursula Braun2d488c22008-10-24 11:16:55 +0200420 len = skb->len;
421 card->osn_info.data_cb(skb);
422 break;
423 }
424 /* else unknown */
Frank Blaschka4a71df52008-02-15 09:19:42 +0100425 default:
426 dev_kfree_skb_any(skb);
Carsten Otte847a50f2010-06-21 22:57:05 +0000427 QETH_CARD_TEXT(card, 3, "inbunkno");
Peter Tiedemannd11ba0c2008-04-01 10:26:58 +0200428 QETH_DBF_HEX(CTRL, 3, hdr, QETH_DBF_CTRL_LEN);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100429 continue;
430 }
Frank Blaschkaa1c3ed42010-09-07 21:14:42 +0000431 work_done++;
432 budget--;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100433 card->stats.rx_packets++;
434 card->stats.rx_bytes += len;
435 }
Frank Blaschkaa1c3ed42010-09-07 21:14:42 +0000436 return work_done;
437}
438
Frank Blaschka4a71df52008-02-15 09:19:42 +0100439static int qeth_l2_request_initial_mac(struct qeth_card *card)
440{
441 int rc = 0;
442 char vendor_pre[] = {0x02, 0x00, 0x00};
443
Julian Wiedmannec61bd22017-06-20 16:00:34 +0200444 QETH_DBF_TEXT(SETUP, 2, "l2reqmac");
Peter Tiedemannd11ba0c2008-04-01 10:26:58 +0200445 QETH_DBF_TEXT_(SETUP, 2, "doL2%s", CARD_BUS_ID(card));
Frank Blaschka4a71df52008-02-15 09:19:42 +0100446
Julian Wiedmannec61bd22017-06-20 16:00:34 +0200447 if (MACHINE_IS_VM) {
448 rc = qeth_vm_request_mac(card);
449 if (!rc)
450 goto out;
451 QETH_DBF_MESSAGE(2, "z/VM MAC Service failed on device %s: x%x\n",
452 CARD_BUS_ID(card), rc);
453 QETH_DBF_TEXT_(SETUP, 2, "err%04x", rc);
454 /* fall back to alternative mechanism: */
455 }
456
Ursula Braun5113fec2010-05-16 21:15:14 +0000457 if (card->info.type == QETH_CARD_TYPE_IQD ||
458 card->info.type == QETH_CARD_TYPE_OSM ||
459 card->info.type == QETH_CARD_TYPE_OSX ||
460 card->info.guestlan) {
Frank Blaschka4a71df52008-02-15 09:19:42 +0100461 rc = qeth_setadpparms_change_macaddr(card);
462 if (rc) {
Frank Blaschka14cc21b2008-06-06 12:37:46 +0200463 QETH_DBF_MESSAGE(2, "couldn't get MAC address on "
464 "device %s: x%x\n", CARD_BUS_ID(card), rc);
Thomas Richter1aec42b2015-01-21 13:39:10 +0100465 QETH_DBF_TEXT_(SETUP, 2, "1err%04x", rc);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100466 return rc;
467 }
Frank Blaschka4a71df52008-02-15 09:19:42 +0100468 } else {
Joe Perches18336112012-07-12 22:33:10 -0700469 eth_random_addr(card->dev->dev_addr);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100470 memcpy(card->dev->dev_addr, vendor_pre, 3);
471 }
Julian Wiedmannec61bd22017-06-20 16:00:34 +0200472out:
473 QETH_DBF_HEX(SETUP, 2, card->dev->dev_addr, card->dev->addr_len);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100474 return 0;
475}
476
477static int qeth_l2_set_mac_address(struct net_device *dev, void *p)
478{
479 struct sockaddr *addr = p;
Heiko Carstens509e2562008-07-26 02:24:10 -0700480 struct qeth_card *card = dev->ml_priv;
Julian Wiedmannbcacfcb2018-04-19 12:52:09 +0200481 u8 old_addr[ETH_ALEN];
Frank Blaschka4a71df52008-02-15 09:19:42 +0100482 int rc = 0;
483
Carsten Otte847a50f2010-06-21 22:57:05 +0000484 QETH_CARD_TEXT(card, 3, "setmac");
Frank Blaschka4a71df52008-02-15 09:19:42 +0100485
Ursula Braun5113fec2010-05-16 21:15:14 +0000486 if (card->info.type == QETH_CARD_TYPE_OSN ||
487 card->info.type == QETH_CARD_TYPE_OSM ||
488 card->info.type == QETH_CARD_TYPE_OSX) {
Carsten Otte847a50f2010-06-21 22:57:05 +0000489 QETH_CARD_TEXT(card, 3, "setmcTYP");
Frank Blaschka4a71df52008-02-15 09:19:42 +0100490 return -EOPNOTSUPP;
491 }
Julian Wiedmann99f0b852017-12-20 20:11:01 +0100492 QETH_CARD_HEX(card, 3, addr->sa_data, ETH_ALEN);
Julian Wiedmannbcacfcb2018-04-19 12:52:09 +0200493 if (!is_valid_ether_addr(addr->sa_data))
494 return -EADDRNOTAVAIL;
495
Ursula Braun8e98ac42009-03-24 20:57:18 +0000496 if (qeth_wait_for_threads(card, QETH_RECOVER_THREAD)) {
Carsten Otte847a50f2010-06-21 22:57:05 +0000497 QETH_CARD_TEXT(card, 3, "setmcREC");
Ursula Braun8e98ac42009-03-24 20:57:18 +0000498 return -ERESTARTSYS;
499 }
Julian Wiedmannbcacfcb2018-04-19 12:52:09 +0200500
501 if (!qeth_card_hw_is_reachable(card)) {
502 ether_addr_copy(dev->dev_addr, addr->sa_data);
503 return 0;
504 }
505
506 /* don't register the same address twice */
507 if (ether_addr_equal_64bits(dev->dev_addr, addr->sa_data) &&
508 (card->info.mac_bits & QETH_LAYER2_MAC_REGISTERED))
509 return 0;
510
511 /* add the new address, switch over, drop the old */
512 rc = qeth_l2_send_setmac(card, addr->sa_data);
513 if (rc)
514 return rc;
515 ether_addr_copy(old_addr, dev->dev_addr);
516 ether_addr_copy(dev->dev_addr, addr->sa_data);
517
518 if (card->info.mac_bits & QETH_LAYER2_MAC_REGISTERED)
519 qeth_l2_remove_mac(card, old_addr);
520 card->info.mac_bits |= QETH_LAYER2_MAC_REGISTERED;
521 return 0;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100522}
523
Eugene Crosser0db587b2015-05-18 14:27:55 +0200524static void qeth_promisc_to_bridge(struct qeth_card *card)
525{
526 struct net_device *dev = card->dev;
527 enum qeth_ipa_promisc_modes promisc_mode;
528 int role;
529 int rc;
530
531 QETH_CARD_TEXT(card, 3, "pmisc2br");
532
533 if (!card->options.sbp.reflect_promisc)
534 return;
535 promisc_mode = (dev->flags & IFF_PROMISC) ? SET_PROMISC_MODE_ON
536 : SET_PROMISC_MODE_OFF;
537 if (promisc_mode == card->info.promisc_mode)
538 return;
539
540 if (promisc_mode == SET_PROMISC_MODE_ON) {
541 if (card->options.sbp.reflect_promisc_primary)
542 role = QETH_SBP_ROLE_PRIMARY;
543 else
544 role = QETH_SBP_ROLE_SECONDARY;
545 } else
546 role = QETH_SBP_ROLE_NONE;
547
548 rc = qeth_bridgeport_setrole(card, role);
549 QETH_DBF_TEXT_(SETUP, 2, "bpm%c%04x",
550 (promisc_mode == SET_PROMISC_MODE_ON) ? '+' : '-', rc);
551 if (!rc) {
552 card->options.sbp.role = role;
553 card->info.promisc_mode = promisc_mode;
554 }
Lakhvich Dmitriyfe5c8022015-10-06 15:12:28 +0200555
556}
557/* New MAC address is added to the hash table and marked to be written on card
558 * only if there is not in the hash table storage already
559 *
560*/
Julian Wiedmann4641b022017-12-20 20:10:59 +0100561static void qeth_l2_add_mac(struct qeth_card *card, struct netdev_hw_addr *ha)
Lakhvich Dmitriyfe5c8022015-10-06 15:12:28 +0200562{
Julian Wiedmanncef6ff222017-08-15 17:02:46 +0200563 u32 mac_hash = get_unaligned((u32 *)(&ha->addr[2]));
Lakhvich Dmitriyfe5c8022015-10-06 15:12:28 +0200564 struct qeth_mac *mac;
565
Julian Wiedmanncef6ff222017-08-15 17:02:46 +0200566 hash_for_each_possible(card->mac_htable, mac, hnode, mac_hash) {
Julian Wiedmann99f0b852017-12-20 20:11:01 +0100567 if (ether_addr_equal_64bits(ha->addr, mac->mac_addr)) {
Lakhvich Dmitriy5f78e292016-06-16 16:18:58 +0200568 mac->disp_flag = QETH_DISP_ADDR_DO_NOTHING;
Lakhvich Dmitriyfe5c8022015-10-06 15:12:28 +0200569 return;
570 }
571 }
572
573 mac = kzalloc(sizeof(struct qeth_mac), GFP_ATOMIC);
Lakhvich Dmitriyfe5c8022015-10-06 15:12:28 +0200574 if (!mac)
575 return;
576
Julian Wiedmann99f0b852017-12-20 20:11:01 +0100577 ether_addr_copy(mac->mac_addr, ha->addr);
Lakhvich Dmitriy5f78e292016-06-16 16:18:58 +0200578 mac->disp_flag = QETH_DISP_ADDR_ADD;
Lakhvich Dmitriyfe5c8022015-10-06 15:12:28 +0200579
Julian Wiedmanncef6ff222017-08-15 17:02:46 +0200580 hash_add(card->mac_htable, &mac->hnode, mac_hash);
Eugene Crosser0db587b2015-05-18 14:27:55 +0200581}
582
Lakhvich Dmitriyfe5c8022015-10-06 15:12:28 +0200583static void qeth_l2_set_rx_mode(struct net_device *dev)
Frank Blaschka4a71df52008-02-15 09:19:42 +0100584{
Heiko Carstens509e2562008-07-26 02:24:10 -0700585 struct qeth_card *card = dev->ml_priv;
Jiri Pirkoccffad252009-05-22 23:22:17 +0000586 struct netdev_hw_addr *ha;
Lakhvich Dmitriyfe5c8022015-10-06 15:12:28 +0200587 struct qeth_mac *mac;
588 struct hlist_node *tmp;
589 int i;
590 int rc;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100591
592 if (card->info.type == QETH_CARD_TYPE_OSN)
Lakhvich Dmitriyfe5c8022015-10-06 15:12:28 +0200593 return;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100594
Carsten Otte847a50f2010-06-21 22:57:05 +0000595 QETH_CARD_TEXT(card, 3, "setmulti");
Ursula Braun8e98ac42009-03-24 20:57:18 +0000596 if (qeth_threads_running(card, QETH_RECOVER_THREAD) &&
597 (card->state != CARD_STATE_UP))
598 return;
Lakhvich Dmitriyfe5c8022015-10-06 15:12:28 +0200599
Frank Blaschka4a71df52008-02-15 09:19:42 +0100600 spin_lock_bh(&card->mclock);
Lakhvich Dmitriyfe5c8022015-10-06 15:12:28 +0200601
Jiri Pirko22bedad32010-04-01 21:22:57 +0000602 netdev_for_each_mc_addr(ha, dev)
Julian Wiedmann4641b022017-12-20 20:10:59 +0100603 qeth_l2_add_mac(card, ha);
Jiri Pirko32e7bfc2010-01-25 13:36:10 -0800604 netdev_for_each_uc_addr(ha, dev)
Julian Wiedmann4641b022017-12-20 20:10:59 +0100605 qeth_l2_add_mac(card, ha);
Lakhvich Dmitriyfe5c8022015-10-06 15:12:28 +0200606
607 hash_for_each_safe(card->mac_htable, i, tmp, mac, hnode) {
Julian Wiedmann00c163f2017-12-20 20:11:02 +0100608 switch (mac->disp_flag) {
609 case QETH_DISP_ADDR_DELETE:
Julian Wiedmann8174aa82017-12-20 20:11:00 +0100610 qeth_l2_remove_mac(card, mac->mac_addr);
Lakhvich Dmitriyfe5c8022015-10-06 15:12:28 +0200611 hash_del(&mac->hnode);
612 kfree(mac);
Julian Wiedmann00c163f2017-12-20 20:11:02 +0100613 break;
614 case QETH_DISP_ADDR_ADD:
Julian Wiedmann8174aa82017-12-20 20:11:00 +0100615 rc = qeth_l2_write_mac(card, mac->mac_addr);
Lakhvich Dmitriyfe5c8022015-10-06 15:12:28 +0200616 if (rc) {
617 hash_del(&mac->hnode);
618 kfree(mac);
Julian Wiedmann00c163f2017-12-20 20:11:02 +0100619 break;
620 }
621 /* fall through */
622 default:
623 /* for next call to set_rx_mode(): */
Lakhvich Dmitriy5f78e292016-06-16 16:18:58 +0200624 mac->disp_flag = QETH_DISP_ADDR_DELETE;
Julian Wiedmann00c163f2017-12-20 20:11:02 +0100625 }
Lakhvich Dmitriyfe5c8022015-10-06 15:12:28 +0200626 }
Frank Blaschka7db22662008-08-15 08:02:59 +0200627
Frank Blaschka4a71df52008-02-15 09:19:42 +0100628 spin_unlock_bh(&card->mclock);
Lakhvich Dmitriyfe5c8022015-10-06 15:12:28 +0200629
Eugene Crosser0db587b2015-05-18 14:27:55 +0200630 if (qeth_adp_supported(card, IPA_SETADP_SET_PROMISC_MODE))
631 qeth_setadp_promisc_mode(card);
632 else
633 qeth_promisc_to_bridge(card);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100634}
635
Julian Wiedmann72863842017-08-18 10:19:04 +0200636static int qeth_l2_xmit_iqd(struct qeth_card *card, struct sk_buff *skb,
637 struct qeth_qdio_out_q *queue, int cast_type)
638{
639 unsigned int data_offset = ETH_HLEN;
640 struct qeth_hdr *hdr;
641 int rc;
642
643 hdr = kmem_cache_alloc(qeth_core_header_cache, GFP_ATOMIC);
644 if (!hdr)
645 return -ENOMEM;
Julian Wiedmannae79fe02017-08-18 10:19:05 +0200646 qeth_l2_fill_header(hdr, skb, cast_type, skb->len);
Julian Wiedmann72863842017-08-18 10:19:04 +0200647 skb_copy_from_linear_data(skb, ((char *)hdr) + sizeof(*hdr),
648 data_offset);
649
650 if (!qeth_get_elements_no(card, skb, 1, data_offset)) {
651 rc = -E2BIG;
652 goto out;
653 }
Julian Wiedmann7c2e9ba2017-09-18 21:18:18 +0200654 rc = qeth_do_send_packet_fast(queue, skb, hdr, data_offset,
Julian Wiedmannf1588172017-08-18 10:19:08 +0200655 sizeof(*hdr) + data_offset);
Julian Wiedmann72863842017-08-18 10:19:04 +0200656out:
657 if (rc)
658 kmem_cache_free(qeth_core_header_cache, hdr);
659 return rc;
660}
661
662static int qeth_l2_xmit_osa(struct qeth_card *card, struct sk_buff *skb,
Kittipon Meesompop571f9dd82018-04-26 09:42:22 +0200663 struct qeth_qdio_out_q *queue, int cast_type,
664 int ipv)
Julian Wiedmann72863842017-08-18 10:19:04 +0200665{
Julian Wiedmann0d6f02d2017-08-18 10:19:10 +0200666 int push_len = sizeof(struct qeth_hdr);
Julian Wiedmann72863842017-08-18 10:19:04 +0200667 unsigned int elements, nr_frags;
Julian Wiedmann0d6f02d2017-08-18 10:19:10 +0200668 unsigned int hdr_elements = 0;
669 struct qeth_hdr *hdr = NULL;
670 unsigned int hd_len = 0;
Julian Wiedmann72863842017-08-18 10:19:04 +0200671 int rc;
672
673 /* fix hardware limitation: as long as we do not have sbal
674 * chaining we can not send long frag lists
675 */
676 if (!qeth_get_elements_no(card, skb, 0, 0)) {
677 rc = skb_linearize(skb);
678
679 if (card->options.performance_stats) {
680 if (rc)
681 card->perf_stats.tx_linfail++;
682 else
683 card->perf_stats.tx_lin++;
684 }
685 if (rc)
686 return rc;
687 }
688 nr_frags = skb_shinfo(skb)->nr_frags;
689
Julian Wiedmann0d6f02d2017-08-18 10:19:10 +0200690 rc = skb_cow_head(skb, push_len);
691 if (rc)
692 return rc;
693 push_len = qeth_push_hdr(skb, &hdr, push_len);
694 if (push_len < 0)
695 return push_len;
696 if (!push_len) {
697 /* hdr was allocated from cache */
698 hd_len = sizeof(*hdr);
699 hdr_elements = 1;
700 }
701 qeth_l2_fill_header(hdr, skb, cast_type, skb->len - push_len);
Julian Wiedmann6195b932018-04-26 09:42:17 +0200702 if (skb->ip_summed == CHECKSUM_PARTIAL) {
Kittipon Meesompop571f9dd82018-04-26 09:42:22 +0200703 qeth_tx_csum(skb, &hdr->hdr.l2.flags[1], ipv);
Julian Wiedmann6195b932018-04-26 09:42:17 +0200704 if (card->options.performance_stats)
705 card->perf_stats.tx_csum++;
706 }
Julian Wiedmann72863842017-08-18 10:19:04 +0200707
Julian Wiedmann0d6f02d2017-08-18 10:19:10 +0200708 elements = qeth_get_elements_no(card, skb, hdr_elements, 0);
Julian Wiedmann72863842017-08-18 10:19:04 +0200709 if (!elements) {
710 rc = -E2BIG;
711 goto out;
712 }
Julian Wiedmann0d6f02d2017-08-18 10:19:10 +0200713 elements += hdr_elements;
714
715 /* TODO: remove the skb_orphan() once TX completion is fast enough */
716 skb_orphan(skb);
717 rc = qeth_do_send_packet(card, queue, skb, hdr, 0, hd_len, elements);
Julian Wiedmann72863842017-08-18 10:19:04 +0200718out:
719 if (!rc) {
Julian Wiedmann72863842017-08-18 10:19:04 +0200720 if (card->options.performance_stats && nr_frags) {
721 card->perf_stats.sg_skbs_sent++;
722 /* nr_frags + skb->data */
723 card->perf_stats.sg_frags_sent += nr_frags + 1;
724 }
725 } else {
Julian Wiedmann0d6f02d2017-08-18 10:19:10 +0200726 if (hd_len)
727 kmem_cache_free(qeth_core_header_cache, hdr);
728 if (rc == -EBUSY)
729 /* roll back to ETH header */
730 skb_pull(skb, push_len);
Julian Wiedmann72863842017-08-18 10:19:04 +0200731 }
732 return rc;
733}
734
735static int qeth_l2_xmit_osn(struct qeth_card *card, struct sk_buff *skb,
736 struct qeth_qdio_out_q *queue)
737{
738 unsigned int elements;
739 struct qeth_hdr *hdr;
740
741 if (skb->protocol == htons(ETH_P_IPV6))
742 return -EPROTONOSUPPORT;
743
744 hdr = (struct qeth_hdr *)skb->data;
745 elements = qeth_get_elements_no(card, skb, 0, 0);
746 if (!elements)
747 return -E2BIG;
748 if (qeth_hdr_chk_and_bounce(skb, &hdr, sizeof(*hdr)))
749 return -EINVAL;
Julian Wiedmann9c3bfda2017-08-18 10:19:07 +0200750 return qeth_do_send_packet(card, queue, skb, hdr, 0, 0, elements);
Julian Wiedmann72863842017-08-18 10:19:04 +0200751}
752
Julian Wiedmanne38db6b2017-04-11 16:11:14 +0200753static netdev_tx_t qeth_l2_hard_start_xmit(struct sk_buff *skb,
754 struct net_device *dev)
Frank Blaschka4a71df52008-02-15 09:19:42 +0100755{
Heiko Carstens509e2562008-07-26 02:24:10 -0700756 struct qeth_card *card = dev->ml_priv;
Klaus-Dieter Wackerce73e102009-08-26 02:01:08 +0000757 int cast_type = qeth_l2_get_cast_type(card, skb);
Kittipon Meesompop571f9dd82018-04-26 09:42:22 +0200758 int ipv = qeth_get_ip_version(skb);
Stefan Raspl290b8342014-04-28 10:05:08 +0200759 struct qeth_qdio_out_q *queue;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100760 int tx_bytes = skb->len;
Julian Wiedmann72863842017-08-18 10:19:04 +0200761 int rc;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100762
Stefan Raspl290b8342014-04-28 10:05:08 +0200763 if (card->qdio.do_prio_queueing || (cast_type &&
764 card->info.is_multicast_different))
765 queue = card->qdio.out_qs[qeth_get_priority_queue(card, skb,
Kittipon Meesompop571f9dd82018-04-26 09:42:22 +0200766 ipv, cast_type)];
Stefan Raspl290b8342014-04-28 10:05:08 +0200767 else
768 queue = card->qdio.out_qs[card->qdio.default_out_queue];
769
Frank Blaschka4a71df52008-02-15 09:19:42 +0100770 if ((card->state != CARD_STATE_UP) || !card->lan_online) {
771 card->stats.tx_carrier_errors++;
772 goto tx_drop;
773 }
774
Frank Blaschka4a71df52008-02-15 09:19:42 +0100775 if (card->options.performance_stats) {
776 card->perf_stats.outbound_cnt++;
777 card->perf_stats.outbound_start_time = qeth_get_micros();
778 }
779 netif_stop_queue(dev);
780
Julian Wiedmann72863842017-08-18 10:19:04 +0200781 switch (card->info.type) {
782 case QETH_CARD_TYPE_OSN:
783 rc = qeth_l2_xmit_osn(card, skb, queue);
784 break;
785 case QETH_CARD_TYPE_IQD:
786 rc = qeth_l2_xmit_iqd(card, skb, queue, cast_type);
787 break;
788 default:
Kittipon Meesompop571f9dd82018-04-26 09:42:22 +0200789 rc = qeth_l2_xmit_osa(card, skb, queue, cast_type, ipv);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100790 }
791
Frank Blaschka4a71df52008-02-15 09:19:42 +0100792 if (!rc) {
793 card->stats.tx_packets++;
794 card->stats.tx_bytes += tx_bytes;
Julian Wiedmann72863842017-08-18 10:19:04 +0200795 if (card->options.performance_stats)
796 card->perf_stats.outbound_time += qeth_get_micros() -
797 card->perf_stats.outbound_start_time;
798 netif_wake_queue(dev);
799 return NETDEV_TX_OK;
800 } else if (rc == -EBUSY) {
801 return NETDEV_TX_BUSY;
802 } /* else fall through */
Frank Blaschka4a71df52008-02-15 09:19:42 +0100803
804tx_drop:
805 card->stats.tx_dropped++;
806 card->stats.tx_errors++;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100807 dev_kfree_skb_any(skb);
Frank Blaschkad0ec0f52008-06-06 12:37:48 +0200808 netif_wake_queue(dev);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100809 return NETDEV_TX_OK;
810}
811
Ursula Braun39423442011-01-12 20:42:24 +0000812static int __qeth_l2_open(struct net_device *dev)
Frank Blaschka4a71df52008-02-15 09:19:42 +0100813{
Heiko Carstens509e2562008-07-26 02:24:10 -0700814 struct qeth_card *card = dev->ml_priv;
Frank Blaschkaa1c3ed42010-09-07 21:14:42 +0000815 int rc = 0;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100816
Carsten Otte847a50f2010-06-21 22:57:05 +0000817 QETH_CARD_TEXT(card, 4, "qethopen");
Ursula Braun39423442011-01-12 20:42:24 +0000818 if (card->state == CARD_STATE_UP)
819 return rc;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100820 if (card->state != CARD_STATE_SOFTSETUP)
821 return -ENODEV;
822
823 if ((card->info.type != QETH_CARD_TYPE_OSN) &&
824 (!(card->info.mac_bits & QETH_LAYER2_MAC_REGISTERED))) {
Carsten Otte847a50f2010-06-21 22:57:05 +0000825 QETH_CARD_TEXT(card, 4, "nomacadr");
Frank Blaschka4a71df52008-02-15 09:19:42 +0100826 return -EPERM;
827 }
828 card->data.state = CH_STATE_UP;
829 card->state = CARD_STATE_UP;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100830 netif_start_queue(dev);
831
Frank Blaschkaa1c3ed42010-09-07 21:14:42 +0000832 if (qdio_stop_irq(card->data.ccwdev, 0) >= 0) {
833 napi_enable(&card->napi);
834 napi_schedule(&card->napi);
835 } else
836 rc = -EIO;
837 return rc;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100838}
839
Ursula Braun39423442011-01-12 20:42:24 +0000840static int qeth_l2_open(struct net_device *dev)
841{
842 struct qeth_card *card = dev->ml_priv;
843
844 QETH_CARD_TEXT(card, 5, "qethope_");
845 if (qeth_wait_for_threads(card, QETH_RECOVER_THREAD)) {
846 QETH_CARD_TEXT(card, 3, "openREC");
847 return -ERESTARTSYS;
848 }
849 return __qeth_l2_open(dev);
850}
851
Frank Blaschka4a71df52008-02-15 09:19:42 +0100852static int qeth_l2_stop(struct net_device *dev)
853{
Heiko Carstens509e2562008-07-26 02:24:10 -0700854 struct qeth_card *card = dev->ml_priv;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100855
Carsten Otte847a50f2010-06-21 22:57:05 +0000856 QETH_CARD_TEXT(card, 4, "qethstop");
Frank Blaschka4a71df52008-02-15 09:19:42 +0100857 netif_tx_disable(dev);
Frank Blaschkaa1c3ed42010-09-07 21:14:42 +0000858 if (card->state == CARD_STATE_UP) {
Frank Blaschka4a71df52008-02-15 09:19:42 +0100859 card->state = CARD_STATE_SOFTSETUP;
Frank Blaschkaa1c3ed42010-09-07 21:14:42 +0000860 napi_disable(&card->napi);
861 }
Frank Blaschka4a71df52008-02-15 09:19:42 +0100862 return 0;
863}
864
Julian Wiedmann2d2ebb32017-05-10 19:07:52 +0200865static const struct device_type qeth_l2_devtype = {
866 .name = "qeth_layer2",
867 .groups = qeth_l2_attr_groups,
868};
869
Frank Blaschka4a71df52008-02-15 09:19:42 +0100870static int qeth_l2_probe_device(struct ccwgroup_device *gdev)
871{
872 struct qeth_card *card = dev_get_drvdata(&gdev->dev);
Ursula Braun9111e782017-05-10 19:07:51 +0200873 int rc;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100874
Julian Wiedmann2d2ebb32017-05-10 19:07:52 +0200875 if (gdev->dev.type == &qeth_generic_devtype) {
876 rc = qeth_l2_create_device_attributes(&gdev->dev);
877 if (rc)
878 return rc;
879 }
Frank Blaschka4a71df52008-02-15 09:19:42 +0100880 INIT_LIST_HEAD(&card->vid_list);
Lakhvich Dmitriyfe5c8022015-10-06 15:12:28 +0200881 hash_init(card->mac_htable);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100882 card->options.layer2 = 1;
Frank Blaschka1da74b12011-05-12 18:45:02 +0000883 card->info.hwtrap = 0;
Hans Wippelcaa1f0b2017-09-18 21:18:15 +0200884 qeth_l2_vnicc_set_defaults(card);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100885 return 0;
886}
887
888static void qeth_l2_remove_device(struct ccwgroup_device *cgdev)
889{
890 struct qeth_card *card = dev_get_drvdata(&cgdev->dev);
891
Julian Wiedmann2d2ebb32017-05-10 19:07:52 +0200892 if (cgdev->dev.type == &qeth_generic_devtype)
893 qeth_l2_remove_device_attributes(&cgdev->dev);
Ursula Braunf2148562009-05-19 21:38:37 +0000894 qeth_set_allowed_threads(card, 0, 1);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100895 wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0);
896
Ursula Braun70919e22011-02-26 22:41:36 -0800897 if (cgdev->state == CCWGROUP_ONLINE)
Frank Blaschka4a71df52008-02-15 09:19:42 +0100898 qeth_l2_set_offline(cgdev);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100899
900 if (card->dev) {
901 unregister_netdev(card->dev);
Julian Wiedmann6be68732018-03-20 07:59:12 +0100902 free_netdev(card->dev);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100903 card->dev = NULL;
904 }
Frank Blaschka4a71df52008-02-15 09:19:42 +0100905 return;
906}
907
Stephen Hemminger0fc0b732009-09-02 01:03:33 -0700908static const struct ethtool_ops qeth_l2_ethtool_ops = {
Frank Blaschka4a71df52008-02-15 09:19:42 +0100909 .get_link = ethtool_op_get_link,
Frank Blaschka4a71df52008-02-15 09:19:42 +0100910 .get_strings = qeth_core_get_strings,
911 .get_ethtool_stats = qeth_core_get_ethtool_stats,
Ben Hutchingsdf8b4ec2009-10-01 11:24:32 +0000912 .get_sset_count = qeth_core_get_sset_count,
Frank Blaschka4a71df52008-02-15 09:19:42 +0100913 .get_drvinfo = qeth_core_get_drvinfo,
Julian Wiedmann993e19c2017-04-11 16:11:17 +0200914 .get_link_ksettings = qeth_core_ethtool_get_link_ksettings,
Frank Blaschka4a71df52008-02-15 09:19:42 +0100915};
916
Stephen Hemminger0fc0b732009-09-02 01:03:33 -0700917static const struct ethtool_ops qeth_l2_osn_ops = {
Frank Blaschka4a71df52008-02-15 09:19:42 +0100918 .get_strings = qeth_core_get_strings,
919 .get_ethtool_stats = qeth_core_get_ethtool_stats,
Ben Hutchingsdf8b4ec2009-10-01 11:24:32 +0000920 .get_sset_count = qeth_core_get_sset_count,
Frank Blaschka4a71df52008-02-15 09:19:42 +0100921 .get_drvinfo = qeth_core_get_drvinfo,
922};
923
Frank Blaschka3d58cef2009-01-09 03:44:00 +0000924static const struct net_device_ops qeth_l2_netdev_ops = {
Frank Blaschka8403b132009-01-08 10:50:55 -0800925 .ndo_open = qeth_l2_open,
926 .ndo_stop = qeth_l2_stop,
927 .ndo_get_stats = qeth_get_stats,
928 .ndo_start_xmit = qeth_l2_hard_start_xmit,
Julian Wiedmann6d69b1f2017-12-01 10:14:50 +0100929 .ndo_features_check = qeth_features_check,
Frank Blaschka8403b132009-01-08 10:50:55 -0800930 .ndo_validate_addr = eth_validate_addr,
Lakhvich Dmitriyfe5c8022015-10-06 15:12:28 +0200931 .ndo_set_rx_mode = qeth_l2_set_rx_mode,
Julian Wiedmann942d6982017-04-11 16:11:10 +0200932 .ndo_do_ioctl = qeth_do_ioctl,
Frank Blaschka8403b132009-01-08 10:50:55 -0800933 .ndo_set_mac_address = qeth_l2_set_mac_address,
934 .ndo_change_mtu = qeth_change_mtu,
935 .ndo_vlan_rx_add_vid = qeth_l2_vlan_rx_add_vid,
936 .ndo_vlan_rx_kill_vid = qeth_l2_vlan_rx_kill_vid,
937 .ndo_tx_timeout = qeth_tx_timeout,
Thomas Richter8f43fb02016-06-16 16:18:59 +0200938 .ndo_fix_features = qeth_fix_features,
939 .ndo_set_features = qeth_set_features
Frank Blaschka8403b132009-01-08 10:50:55 -0800940};
941
Frank Blaschka4a71df52008-02-15 09:19:42 +0100942static int qeth_l2_setup_netdev(struct qeth_card *card)
943{
944 switch (card->info.type) {
Frank Blaschka4a71df52008-02-15 09:19:42 +0100945 case QETH_CARD_TYPE_IQD:
Tom Gundersenc835a672014-07-14 16:37:24 +0200946 card->dev = alloc_netdev(0, "hsi%d", NET_NAME_UNKNOWN,
947 ether_setup);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100948 break;
949 case QETH_CARD_TYPE_OSN:
Tom Gundersenc835a672014-07-14 16:37:24 +0200950 card->dev = alloc_netdev(0, "osn%d", NET_NAME_UNKNOWN,
951 ether_setup);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100952 break;
953 default:
954 card->dev = alloc_etherdev(0);
955 }
956
957 if (!card->dev)
958 return -ENODEV;
959
Heiko Carstens509e2562008-07-26 02:24:10 -0700960 card->dev->ml_priv = card;
Julian Wiedmannd3aacac2018-03-09 18:12:55 +0100961 card->dev->priv_flags |= IFF_UNICAST_FLT;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100962 card->dev->watchdog_timeo = QETH_TX_TIMEOUT;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100963 card->dev->mtu = card->info.initial_mtu;
Jarod Wilson46b3ef42016-10-20 13:55:23 -0400964 card->dev->min_mtu = 64;
965 card->dev->max_mtu = ETH_MAX_MTU;
Ursula Braun71c46892018-04-26 09:42:15 +0200966 card->dev->dev_port = card->info.portno;
Frank Blaschka8403b132009-01-08 10:50:55 -0800967 card->dev->netdev_ops = &qeth_l2_netdev_ops;
Julian Wiedmann25e2c342017-05-10 19:07:53 +0200968 if (card->info.type == QETH_CARD_TYPE_OSN) {
969 card->dev->ethtool_ops = &qeth_l2_osn_ops;
970 card->dev->flags |= IFF_NOARP;
971 } else {
972 card->dev->ethtool_ops = &qeth_l2_ethtool_ops;
973 }
Julian Wiedmann9400c532017-10-18 17:40:20 +0200974
975 if (card->info.type == QETH_CARD_TYPE_OSM)
976 card->dev->features |= NETIF_F_VLAN_CHALLENGED;
977 else
978 card->dev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
Julian Wiedmann0f342942018-03-09 18:12:54 +0100979
980 if (card->info.type != QETH_CARD_TYPE_OSN &&
981 card->info.type != QETH_CARD_TYPE_IQD) {
982 card->dev->priv_flags &= ~IFF_TX_SKB_SHARING;
983 card->dev->needed_headroom = sizeof(struct qeth_hdr);
984 card->dev->hw_features |= NETIF_F_SG;
985 card->dev->vlan_features |= NETIF_F_SG;
986 }
987
Thomas Richter4d7def22015-09-18 16:06:51 +0200988 if (card->info.type == QETH_CARD_TYPE_OSD && !card->info.guestlan) {
Julian Wiedmann6d69b1f2017-12-01 10:14:50 +0100989 card->dev->features |= NETIF_F_SG;
Thomas Richter8f43fb02016-06-16 16:18:59 +0200990 /* OSA 3S and earlier has no RX/TX support */
Hans Wippel9bdc4412016-06-16 16:19:00 +0200991 if (qeth_is_supported(card, IPA_OUTBOUND_CHECKSUM)) {
Thomas Richter8f43fb02016-06-16 16:18:59 +0200992 card->dev->hw_features |= NETIF_F_IP_CSUM;
Hans Wippel9bdc4412016-06-16 16:19:00 +0200993 card->dev->vlan_features |= NETIF_F_IP_CSUM;
994 }
Thomas Richter4d7def22015-09-18 16:06:51 +0200995 }
Kittipon Meesompop571f9dd82018-04-26 09:42:22 +0200996 if (qeth_is_supported6(card, IPA_OUTBOUND_CHECKSUM_V6)) {
997 card->dev->hw_features |= NETIF_F_IPV6_CSUM;
998 card->dev->vlan_features |= NETIF_F_IPV6_CSUM;
999 }
Kittipon Meesompopd7e6ed92018-04-26 09:42:23 +02001000 if (qeth_is_supported(card, IPA_INBOUND_CHECKSUM) ||
1001 qeth_is_supported6(card, IPA_INBOUND_CHECKSUM_V6)) {
1002 card->dev->hw_features |= NETIF_F_RXCSUM;
1003 card->dev->vlan_features |= NETIF_F_RXCSUM;
1004 }
Julian Wiedmann0d6f02d2017-08-18 10:19:10 +02001005
Frank Blaschka4a71df52008-02-15 09:19:42 +01001006 card->info.broadcast_capable = 1;
1007 qeth_l2_request_initial_mac(card);
1008 SET_NETDEV_DEV(card->dev, &card->gdev->dev);
Julian Wiedmannd73ef322017-04-11 16:11:11 +02001009 netif_napi_add(card->dev, &card->napi, qeth_poll, QETH_NAPI_WEIGHT);
Ursula Braune5ebe632015-12-11 12:27:55 +01001010 netif_carrier_off(card->dev);
Frank Blaschka4a71df52008-02-15 09:19:42 +01001011 return register_netdev(card->dev);
1012}
1013
Thomas Richter4d7def22015-09-18 16:06:51 +02001014static int qeth_l2_start_ipassists(struct qeth_card *card)
1015{
1016 /* configure isolation level */
1017 if (qeth_set_access_ctrl_online(card, 0))
1018 return -ENODEV;
Thomas Richter4d7def22015-09-18 16:06:51 +02001019 return 0;
1020}
1021
Julian Wiedmann521c10e2017-06-06 14:33:45 +02001022static void qeth_l2_trace_features(struct qeth_card *card)
1023{
Hans Wippela45b3fa2017-09-18 21:18:14 +02001024 /* Set BridgePort features */
1025 QETH_CARD_TEXT(card, 2, "featuSBP");
Julian Wiedmann521c10e2017-06-06 14:33:45 +02001026 QETH_CARD_HEX(card, 2, &card->options.sbp.supported_funcs,
1027 sizeof(card->options.sbp.supported_funcs));
Hans Wippela45b3fa2017-09-18 21:18:14 +02001028 /* VNIC Characteristics features */
1029 QETH_CARD_TEXT(card, 2, "feaVNICC");
1030 QETH_CARD_HEX(card, 2, &card->options.vnicc.sup_chars,
1031 sizeof(card->options.vnicc.sup_chars));
Julian Wiedmann521c10e2017-06-06 14:33:45 +02001032}
1033
Frank Blaschka4a71df52008-02-15 09:19:42 +01001034static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)
1035{
1036 struct qeth_card *card = dev_get_drvdata(&gdev->dev);
1037 int rc = 0;
1038 enum qeth_card_states recover_flag;
1039
Ursula Braun9dc48cc2010-07-22 23:15:05 +00001040 mutex_lock(&card->discipline_mutex);
Frank Blaschkac4949f02010-05-11 19:34:47 +00001041 mutex_lock(&card->conf_mutex);
Peter Tiedemannd11ba0c2008-04-01 10:26:58 +02001042 QETH_DBF_TEXT(SETUP, 2, "setonlin");
1043 QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *));
Frank Blaschka4a71df52008-02-15 09:19:42 +01001044
Frank Blaschka4a71df52008-02-15 09:19:42 +01001045 recover_flag = card->state;
Frank Blaschka4a71df52008-02-15 09:19:42 +01001046 rc = qeth_core_hardsetup_card(card);
1047 if (rc) {
Thomas Richter1aec42b2015-01-21 13:39:10 +01001048 QETH_DBF_TEXT_(SETUP, 2, "2err%04x", rc);
Ursula Braunaa909222009-11-12 00:11:43 +00001049 rc = -ENODEV;
Frank Blaschka4a71df52008-02-15 09:19:42 +01001050 goto out_remove;
1051 }
Eugene Crosserc044dc22014-01-29 09:23:48 +01001052 qeth_bridgeport_query_support(card);
1053 if (card->options.sbp.supported_funcs)
1054 dev_info(&card->gdev->dev,
Eugene Crosser9c23f4da2015-05-18 14:27:56 +02001055 "The device represents a Bridge Capable Port\n");
Frank Blaschka4a71df52008-02-15 09:19:42 +01001056
Ursula Braunaa909222009-11-12 00:11:43 +00001057 if (!card->dev && qeth_l2_setup_netdev(card)) {
1058 rc = -ENODEV;
Frank Blaschka4a71df52008-02-15 09:19:42 +01001059 goto out_remove;
Ursula Braunaa909222009-11-12 00:11:43 +00001060 }
Frank Blaschka4a71df52008-02-15 09:19:42 +01001061
Julian Wiedmannbcacfcb2018-04-19 12:52:09 +02001062 if (card->info.type != QETH_CARD_TYPE_OSN &&
1063 !qeth_l2_send_setmac(card, card->dev->dev_addr))
1064 card->info.mac_bits |= QETH_LAYER2_MAC_REGISTERED;
Frank Blaschka4a71df52008-02-15 09:19:42 +01001065
Frank Blaschka1da74b12011-05-12 18:45:02 +00001066 if (qeth_is_diagass_supported(card, QETH_DIAGS_CMD_TRAP)) {
1067 if (card->info.hwtrap &&
1068 qeth_hw_trap(card, QETH_DIAGS_TRAP_ARM))
1069 card->info.hwtrap = 0;
1070 } else
1071 card->info.hwtrap = 0;
1072
Hans Wippela45b3fa2017-09-18 21:18:14 +02001073 /* for the rx_bcast characteristic, init VNICC after setmac */
1074 qeth_l2_vnicc_init(card);
1075
1076 qeth_trace_features(card);
1077 qeth_l2_trace_features(card);
1078
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001079 qeth_l2_setup_bridgeport_attrs(card);
1080
Frank Blaschka4a71df52008-02-15 09:19:42 +01001081 card->state = CARD_STATE_HARDSETUP;
1082 qeth_print_status_message(card);
1083
1084 /* softsetup */
Peter Tiedemannd11ba0c2008-04-01 10:26:58 +02001085 QETH_DBF_TEXT(SETUP, 2, "softsetp");
Frank Blaschka4a71df52008-02-15 09:19:42 +01001086
Ursula Braun5113fec2010-05-16 21:15:14 +00001087 if ((card->info.type == QETH_CARD_TYPE_OSD) ||
Stefan Raspl0f547612013-01-21 02:30:20 +00001088 (card->info.type == QETH_CARD_TYPE_OSX)) {
Thomas Richter8f43fb02016-06-16 16:18:59 +02001089 rc = qeth_l2_start_ipassists(card);
1090 if (rc)
Stefan Raspl0f547612013-01-21 02:30:20 +00001091 goto out_remove;
Stefan Raspl0f547612013-01-21 02:30:20 +00001092 }
Ursula Braun5113fec2010-05-16 21:15:14 +00001093
Julian Wiedmann9400c532017-10-18 17:40:20 +02001094 if (card->info.type != QETH_CARD_TYPE_OSN)
Ursula Braun70919e22011-02-26 22:41:36 -08001095 qeth_l2_process_vlans(card);
Frank Blaschka4a71df52008-02-15 09:19:42 +01001096
1097 netif_tx_disable(card->dev);
1098
1099 rc = qeth_init_qdio_queues(card);
1100 if (rc) {
Peter Tiedemannd11ba0c2008-04-01 10:26:58 +02001101 QETH_DBF_TEXT_(SETUP, 2, "6err%d", rc);
Ursula Braunaa909222009-11-12 00:11:43 +00001102 rc = -ENODEV;
Frank Blaschka4a71df52008-02-15 09:19:42 +01001103 goto out_remove;
1104 }
1105 card->state = CARD_STATE_SOFTSETUP;
Ursula Braun2b6203b2010-11-26 02:41:19 +00001106 if (card->lan_online)
1107 netif_carrier_on(card->dev);
1108 else
1109 netif_carrier_off(card->dev);
Frank Blaschka4a71df52008-02-15 09:19:42 +01001110
1111 qeth_set_allowed_threads(card, 0xffffffff, 0);
1112 if (recover_flag == CARD_STATE_RECOVER) {
1113 if (recovery_mode &&
1114 card->info.type != QETH_CARD_TYPE_OSN) {
Ursula Braun39423442011-01-12 20:42:24 +00001115 __qeth_l2_open(card->dev);
Frank Blaschka4a71df52008-02-15 09:19:42 +01001116 } else {
1117 rtnl_lock();
1118 dev_open(card->dev);
1119 rtnl_unlock();
1120 }
1121 /* this also sets saved unicast addresses */
Lakhvich Dmitriyfe5c8022015-10-06 15:12:28 +02001122 qeth_l2_set_rx_mode(card->dev);
Hans Wippele830baa2016-09-15 14:39:21 +02001123 rtnl_lock();
1124 qeth_recover_features(card->dev);
1125 rtnl_unlock();
Frank Blaschka4a71df52008-02-15 09:19:42 +01001126 }
1127 /* let user_space know that device is online */
1128 kobject_uevent(&gdev->dev.kobj, KOBJ_CHANGE);
Frank Blaschkac4949f02010-05-11 19:34:47 +00001129 mutex_unlock(&card->conf_mutex);
Ursula Braun9dc48cc2010-07-22 23:15:05 +00001130 mutex_unlock(&card->discipline_mutex);
Frank Blaschka4a71df52008-02-15 09:19:42 +01001131 return 0;
Ursula Braunaa909222009-11-12 00:11:43 +00001132
Frank Blaschka4a71df52008-02-15 09:19:42 +01001133out_remove:
Frank Blaschka4a71df52008-02-15 09:19:42 +01001134 qeth_l2_stop_card(card, 0);
1135 ccw_device_set_offline(CARD_DDEV(card));
1136 ccw_device_set_offline(CARD_WDEV(card));
1137 ccw_device_set_offline(CARD_RDEV(card));
Ursula Braun22ae2792014-02-24 13:12:06 +01001138 qdio_free(CARD_DDEV(card));
Frank Blaschka4a71df52008-02-15 09:19:42 +01001139 if (recover_flag == CARD_STATE_RECOVER)
1140 card->state = CARD_STATE_RECOVER;
1141 else
1142 card->state = CARD_STATE_DOWN;
Frank Blaschkac4949f02010-05-11 19:34:47 +00001143 mutex_unlock(&card->conf_mutex);
Ursula Braun9dc48cc2010-07-22 23:15:05 +00001144 mutex_unlock(&card->discipline_mutex);
Ursula Braunaa909222009-11-12 00:11:43 +00001145 return rc;
Frank Blaschka4a71df52008-02-15 09:19:42 +01001146}
1147
1148static int qeth_l2_set_online(struct ccwgroup_device *gdev)
1149{
1150 return __qeth_l2_set_online(gdev, 0);
1151}
1152
1153static int __qeth_l2_set_offline(struct ccwgroup_device *cgdev,
1154 int recovery_mode)
1155{
1156 struct qeth_card *card = dev_get_drvdata(&cgdev->dev);
1157 int rc = 0, rc2 = 0, rc3 = 0;
1158 enum qeth_card_states recover_flag;
1159
Ursula Braun9dc48cc2010-07-22 23:15:05 +00001160 mutex_lock(&card->discipline_mutex);
Frank Blaschkac4949f02010-05-11 19:34:47 +00001161 mutex_lock(&card->conf_mutex);
Peter Tiedemannd11ba0c2008-04-01 10:26:58 +02001162 QETH_DBF_TEXT(SETUP, 3, "setoffl");
1163 QETH_DBF_HEX(SETUP, 3, &card, sizeof(void *));
Frank Blaschka4a71df52008-02-15 09:19:42 +01001164
1165 if (card->dev && netif_carrier_ok(card->dev))
1166 netif_carrier_off(card->dev);
1167 recover_flag = card->state;
Frank Blaschka1da74b12011-05-12 18:45:02 +00001168 if ((!recovery_mode && card->info.hwtrap) || card->info.hwtrap == 2) {
1169 qeth_hw_trap(card, QETH_DIAGS_TRAP_DISARM);
1170 card->info.hwtrap = 1;
1171 }
Ursula Braun0f5623c2008-10-24 11:16:52 +02001172 qeth_l2_stop_card(card, recovery_mode);
Frank Blaschka4a71df52008-02-15 09:19:42 +01001173 rc = ccw_device_set_offline(CARD_DDEV(card));
1174 rc2 = ccw_device_set_offline(CARD_WDEV(card));
1175 rc3 = ccw_device_set_offline(CARD_RDEV(card));
1176 if (!rc)
1177 rc = (rc2) ? rc2 : rc3;
1178 if (rc)
Peter Tiedemannd11ba0c2008-04-01 10:26:58 +02001179 QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc);
Ursula Braun22ae2792014-02-24 13:12:06 +01001180 qdio_free(CARD_DDEV(card));
Frank Blaschka4a71df52008-02-15 09:19:42 +01001181 if (recover_flag == CARD_STATE_UP)
1182 card->state = CARD_STATE_RECOVER;
1183 /* let user_space know that device is offline */
1184 kobject_uevent(&cgdev->dev.kobj, KOBJ_CHANGE);
Frank Blaschkac4949f02010-05-11 19:34:47 +00001185 mutex_unlock(&card->conf_mutex);
Ursula Braun9dc48cc2010-07-22 23:15:05 +00001186 mutex_unlock(&card->discipline_mutex);
Frank Blaschka4a71df52008-02-15 09:19:42 +01001187 return 0;
1188}
1189
1190static int qeth_l2_set_offline(struct ccwgroup_device *cgdev)
1191{
1192 return __qeth_l2_set_offline(cgdev, 0);
1193}
1194
1195static int qeth_l2_recover(void *ptr)
1196{
1197 struct qeth_card *card;
1198 int rc = 0;
1199
1200 card = (struct qeth_card *) ptr;
Carsten Otte847a50f2010-06-21 22:57:05 +00001201 QETH_CARD_TEXT(card, 2, "recover1");
Frank Blaschka4a71df52008-02-15 09:19:42 +01001202 if (!qeth_do_run_thread(card, QETH_RECOVER_THREAD))
1203 return 0;
Carsten Otte847a50f2010-06-21 22:57:05 +00001204 QETH_CARD_TEXT(card, 2, "recover2");
Frank Blaschka74eacdb2008-12-25 13:39:49 +01001205 dev_warn(&card->gdev->dev,
1206 "A recovery process has been started for the device\n");
Stefan Raspl65d80132013-04-07 22:19:27 +00001207 qeth_set_recovery_task(card);
Frank Blaschka4a71df52008-02-15 09:19:42 +01001208 __qeth_l2_set_offline(card->gdev, 1);
1209 rc = __qeth_l2_set_online(card->gdev, 1);
Frank Blaschka4a71df52008-02-15 09:19:42 +01001210 if (!rc)
Frank Blaschka74eacdb2008-12-25 13:39:49 +01001211 dev_info(&card->gdev->dev,
1212 "Device successfully recovered!\n");
Ursula Braun28a7e4c2008-09-19 12:56:03 +02001213 else {
Stefan Raspl0f547612013-01-21 02:30:20 +00001214 qeth_close_dev(card);
1215 dev_warn(&card->gdev->dev, "The qeth device driver "
Stefan Raspl2efaf5f2012-10-15 19:21:18 +00001216 "failed to recover an error on the device\n");
Ursula Braun28a7e4c2008-09-19 12:56:03 +02001217 }
Stefan Raspl65d80132013-04-07 22:19:27 +00001218 qeth_clear_recovery_task(card);
Frank Blaschkaa1c3ed42010-09-07 21:14:42 +00001219 qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD);
1220 qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD);
Frank Blaschka4a71df52008-02-15 09:19:42 +01001221 return 0;
1222}
1223
1224static int __init qeth_l2_init(void)
1225{
Frank Blaschka74eacdb2008-12-25 13:39:49 +01001226 pr_info("register layer 2 discipline\n");
Frank Blaschka4a71df52008-02-15 09:19:42 +01001227 return 0;
1228}
1229
1230static void __exit qeth_l2_exit(void)
1231{
Frank Blaschka74eacdb2008-12-25 13:39:49 +01001232 pr_info("unregister layer 2 discipline\n");
Frank Blaschka4a71df52008-02-15 09:19:42 +01001233}
1234
Frank Blaschkabbcfcdc2009-06-16 10:30:31 +02001235static int qeth_l2_pm_suspend(struct ccwgroup_device *gdev)
1236{
1237 struct qeth_card *card = dev_get_drvdata(&gdev->dev);
1238
1239 if (card->dev)
1240 netif_device_detach(card->dev);
1241 qeth_set_allowed_threads(card, 0, 1);
1242 wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0);
1243 if (gdev->state == CCWGROUP_OFFLINE)
1244 return 0;
1245 if (card->state == CARD_STATE_UP) {
Frank Blaschka1da74b12011-05-12 18:45:02 +00001246 if (card->info.hwtrap)
1247 qeth_hw_trap(card, QETH_DIAGS_TRAP_DISARM);
Frank Blaschkabbcfcdc2009-06-16 10:30:31 +02001248 __qeth_l2_set_offline(card->gdev, 1);
1249 } else
1250 __qeth_l2_set_offline(card->gdev, 0);
1251 return 0;
1252}
1253
1254static int qeth_l2_pm_resume(struct ccwgroup_device *gdev)
1255{
1256 struct qeth_card *card = dev_get_drvdata(&gdev->dev);
1257 int rc = 0;
1258
1259 if (gdev->state == CCWGROUP_OFFLINE)
1260 goto out;
1261
1262 if (card->state == CARD_STATE_RECOVER) {
1263 rc = __qeth_l2_set_online(card->gdev, 1);
1264 if (rc) {
Ursula Braun869da902010-03-08 20:36:56 +00001265 rtnl_lock();
1266 dev_close(card->dev);
1267 rtnl_unlock();
Frank Blaschkabbcfcdc2009-06-16 10:30:31 +02001268 }
1269 } else
1270 rc = __qeth_l2_set_online(card->gdev, 0);
1271out:
1272 qeth_set_allowed_threads(card, 0xffffffff, 0);
1273 if (card->dev)
1274 netif_device_attach(card->dev);
1275 if (rc)
1276 dev_warn(&card->gdev->dev, "The qeth device driver "
1277 "failed to recover an error on the device\n");
1278 return rc;
1279}
1280
Eugene Crosserc044dc22014-01-29 09:23:48 +01001281/* Returns zero if the command is successfully "consumed" */
1282static int qeth_l2_control_event(struct qeth_card *card,
1283 struct qeth_ipa_cmd *cmd)
1284{
1285 switch (cmd->hdr.command) {
Eugene Crosser9c23f4da2015-05-18 14:27:56 +02001286 case IPA_CMD_SETBRIDGEPORT_OSA:
1287 case IPA_CMD_SETBRIDGEPORT_IQD:
Eugene Crosserc044dc22014-01-29 09:23:48 +01001288 if (cmd->data.sbp.hdr.command_code ==
1289 IPA_SBP_BRIDGE_PORT_STATE_CHANGE) {
1290 qeth_bridge_state_change(card, cmd);
1291 return 0;
1292 } else
1293 return 1;
1294 case IPA_CMD_ADDRESS_CHANGE_NOTIF:
1295 qeth_bridge_host_event(card, cmd);
1296 return 0;
1297 default:
1298 return 1;
1299 }
1300}
1301
Sebastian Ottc041f2d4872012-05-15 18:02:21 +02001302struct qeth_discipline qeth_l2_discipline = {
Julian Wiedmann2d2ebb32017-05-10 19:07:52 +02001303 .devtype = &qeth_l2_devtype,
Julian Wiedmannd73ef322017-04-11 16:11:11 +02001304 .process_rx_buffer = qeth_l2_process_inbound_buffer,
Sebastian Ottc041f2d4872012-05-15 18:02:21 +02001305 .recover = qeth_l2_recover,
1306 .setup = qeth_l2_probe_device,
Frank Blaschka4a71df52008-02-15 09:19:42 +01001307 .remove = qeth_l2_remove_device,
1308 .set_online = qeth_l2_set_online,
1309 .set_offline = qeth_l2_set_offline,
Frank Blaschkabbcfcdc2009-06-16 10:30:31 +02001310 .freeze = qeth_l2_pm_suspend,
1311 .thaw = qeth_l2_pm_resume,
1312 .restore = qeth_l2_pm_resume,
Julian Wiedmann942d6982017-04-11 16:11:10 +02001313 .do_ioctl = NULL,
Eugene Crosserc044dc22014-01-29 09:23:48 +01001314 .control_event_handler = qeth_l2_control_event,
Frank Blaschka4a71df52008-02-15 09:19:42 +01001315};
Sebastian Ottc041f2d4872012-05-15 18:02:21 +02001316EXPORT_SYMBOL_GPL(qeth_l2_discipline);
Frank Blaschka4a71df52008-02-15 09:19:42 +01001317
1318static int qeth_osn_send_control_data(struct qeth_card *card, int len,
1319 struct qeth_cmd_buffer *iob)
1320{
1321 unsigned long flags;
1322 int rc = 0;
1323
Carsten Otte847a50f2010-06-21 22:57:05 +00001324 QETH_CARD_TEXT(card, 5, "osndctrd");
Frank Blaschka4a71df52008-02-15 09:19:42 +01001325
1326 wait_event(card->wait_q,
1327 atomic_cmpxchg(&card->write.irq_pending, 0, 1) == 0);
1328 qeth_prepare_control_data(card, len, iob);
Carsten Otte847a50f2010-06-21 22:57:05 +00001329 QETH_CARD_TEXT(card, 6, "osnoirqp");
Frank Blaschka4a71df52008-02-15 09:19:42 +01001330 spin_lock_irqsave(get_ccwdev_lock(card->write.ccwdev), flags);
Julian Wiedmanndb71bbb2018-04-19 12:52:10 +02001331 rc = ccw_device_start_timeout(CARD_WDEV(card), &card->write.ccw,
1332 (addr_t) iob, 0, 0, QETH_IPA_TIMEOUT);
Frank Blaschka4a71df52008-02-15 09:19:42 +01001333 spin_unlock_irqrestore(get_ccwdev_lock(card->write.ccwdev), flags);
1334 if (rc) {
Frank Blaschka14cc21b2008-06-06 12:37:46 +02001335 QETH_DBF_MESSAGE(2, "qeth_osn_send_control_data: "
Frank Blaschka4a71df52008-02-15 09:19:42 +01001336 "ccw_device_start rc = %i\n", rc);
Carsten Otte847a50f2010-06-21 22:57:05 +00001337 QETH_CARD_TEXT_(card, 2, " err%d", rc);
Frank Blaschka4a71df52008-02-15 09:19:42 +01001338 qeth_release_buffer(iob->channel, iob);
1339 atomic_set(&card->write.irq_pending, 0);
1340 wake_up(&card->wait_q);
1341 }
1342 return rc;
1343}
1344
1345static int qeth_osn_send_ipa_cmd(struct qeth_card *card,
1346 struct qeth_cmd_buffer *iob, int data_len)
1347{
1348 u16 s1, s2;
1349
Carsten Otte847a50f2010-06-21 22:57:05 +00001350 QETH_CARD_TEXT(card, 4, "osndipa");
Frank Blaschka4a71df52008-02-15 09:19:42 +01001351
1352 qeth_prepare_ipa_cmd(card, iob, QETH_PROT_OSN2);
1353 s1 = (u16)(IPA_PDU_HEADER_SIZE + data_len);
1354 s2 = (u16)data_len;
1355 memcpy(QETH_IPA_PDU_LEN_TOTAL(iob->data), &s1, 2);
1356 memcpy(QETH_IPA_PDU_LEN_PDU1(iob->data), &s2, 2);
1357 memcpy(QETH_IPA_PDU_LEN_PDU2(iob->data), &s2, 2);
1358 memcpy(QETH_IPA_PDU_LEN_PDU3(iob->data), &s2, 2);
1359 return qeth_osn_send_control_data(card, s1, iob);
1360}
1361
1362int qeth_osn_assist(struct net_device *dev, void *data, int data_len)
1363{
1364 struct qeth_cmd_buffer *iob;
1365 struct qeth_card *card;
Frank Blaschka4a71df52008-02-15 09:19:42 +01001366
Frank Blaschka4a71df52008-02-15 09:19:42 +01001367 if (!dev)
1368 return -ENODEV;
Heiko Carstens509e2562008-07-26 02:24:10 -07001369 card = dev->ml_priv;
Frank Blaschka4a71df52008-02-15 09:19:42 +01001370 if (!card)
1371 return -ENODEV;
Carsten Otte847a50f2010-06-21 22:57:05 +00001372 QETH_CARD_TEXT(card, 2, "osnsdmc");
Eugene Crosserc3521252015-01-16 14:05:47 +01001373 if (!qeth_card_hw_is_reachable(card))
Frank Blaschka4a71df52008-02-15 09:19:42 +01001374 return -ENODEV;
1375 iob = qeth_wait_for_buffer(&card->write);
Julian Wiedmannff5caa72018-03-09 18:12:52 +01001376 memcpy(__ipa_cmd(iob), data, data_len);
1377 return qeth_osn_send_ipa_cmd(card, iob, data_len);
Frank Blaschka4a71df52008-02-15 09:19:42 +01001378}
1379EXPORT_SYMBOL(qeth_osn_assist);
1380
1381int qeth_osn_register(unsigned char *read_dev_no, struct net_device **dev,
1382 int (*assist_cb)(struct net_device *, void *),
1383 int (*data_cb)(struct sk_buff *))
1384{
1385 struct qeth_card *card;
1386
Frank Blaschka4a71df52008-02-15 09:19:42 +01001387 *dev = qeth_l2_netdev_by_devno(read_dev_no);
1388 if (*dev == NULL)
1389 return -ENODEV;
Heiko Carstens509e2562008-07-26 02:24:10 -07001390 card = (*dev)->ml_priv;
Frank Blaschka4a71df52008-02-15 09:19:42 +01001391 if (!card)
1392 return -ENODEV;
Carsten Otte847a50f2010-06-21 22:57:05 +00001393 QETH_CARD_TEXT(card, 2, "osnreg");
Frank Blaschka4a71df52008-02-15 09:19:42 +01001394 if ((assist_cb == NULL) || (data_cb == NULL))
1395 return -EINVAL;
1396 card->osn_info.assist_cb = assist_cb;
1397 card->osn_info.data_cb = data_cb;
1398 return 0;
1399}
1400EXPORT_SYMBOL(qeth_osn_register);
1401
1402void qeth_osn_deregister(struct net_device *dev)
1403{
1404 struct qeth_card *card;
1405
Frank Blaschka4a71df52008-02-15 09:19:42 +01001406 if (!dev)
1407 return;
Heiko Carstens509e2562008-07-26 02:24:10 -07001408 card = dev->ml_priv;
Frank Blaschka4a71df52008-02-15 09:19:42 +01001409 if (!card)
1410 return;
Carsten Otte847a50f2010-06-21 22:57:05 +00001411 QETH_CARD_TEXT(card, 2, "osndereg");
Frank Blaschka4a71df52008-02-15 09:19:42 +01001412 card->osn_info.assist_cb = NULL;
1413 card->osn_info.data_cb = NULL;
1414 return;
1415}
1416EXPORT_SYMBOL(qeth_osn_deregister);
1417
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001418/* SETBRIDGEPORT support, async notifications */
1419
Eugene Crosser9f48b9d2014-01-14 15:54:13 +01001420enum qeth_an_event_type {anev_reg_unreg, anev_abort, anev_reset};
1421
1422/**
1423 * qeth_bridge_emit_host_event() - bridgeport address change notification
1424 * @card: qeth_card structure pointer, for udev events.
1425 * @evtype: "normal" register/unregister, or abort, or reset. For abort
1426 * and reset token and addr_lnid are unused and may be NULL.
1427 * @code: event bitmask: high order bit 0x80 value 1 means removal of an
1428 * object, 0 - addition of an object.
1429 * 0x01 - VLAN, 0x02 - MAC, 0x03 - VLAN and MAC.
1430 * @token: "network token" structure identifying physical address of the port.
1431 * @addr_lnid: pointer to structure with MAC address and VLAN ID.
1432 *
1433 * This function is called when registrations and deregistrations are
1434 * reported by the hardware, and also when notifications are enabled -
1435 * for all currently registered addresses.
1436 */
1437static void qeth_bridge_emit_host_event(struct qeth_card *card,
1438 enum qeth_an_event_type evtype,
1439 u8 code, struct net_if_token *token, struct mac_addr_lnid *addr_lnid)
1440{
1441 char str[7][32];
1442 char *env[8];
1443 int i = 0;
1444
1445 switch (evtype) {
1446 case anev_reg_unreg:
1447 snprintf(str[i], sizeof(str[i]), "BRIDGEDHOST=%s",
1448 (code & IPA_ADDR_CHANGE_CODE_REMOVAL)
1449 ? "deregister" : "register");
1450 env[i] = str[i]; i++;
1451 if (code & IPA_ADDR_CHANGE_CODE_VLANID) {
1452 snprintf(str[i], sizeof(str[i]), "VLAN=%d",
1453 addr_lnid->lnid);
1454 env[i] = str[i]; i++;
1455 }
1456 if (code & IPA_ADDR_CHANGE_CODE_MACADDR) {
Eugene Crosser9846e702015-09-18 16:06:48 +02001457 snprintf(str[i], sizeof(str[i]), "MAC=%pM",
Thomas Richter4d7def22015-09-18 16:06:51 +02001458 addr_lnid->mac);
Eugene Crosser9f48b9d2014-01-14 15:54:13 +01001459 env[i] = str[i]; i++;
1460 }
1461 snprintf(str[i], sizeof(str[i]), "NTOK_BUSID=%x.%x.%04x",
1462 token->cssid, token->ssid, token->devnum);
1463 env[i] = str[i]; i++;
1464 snprintf(str[i], sizeof(str[i]), "NTOK_IID=%02x", token->iid);
1465 env[i] = str[i]; i++;
1466 snprintf(str[i], sizeof(str[i]), "NTOK_CHPID=%02x",
1467 token->chpid);
1468 env[i] = str[i]; i++;
1469 snprintf(str[i], sizeof(str[i]), "NTOK_CHID=%04x", token->chid);
1470 env[i] = str[i]; i++;
1471 break;
1472 case anev_abort:
1473 snprintf(str[i], sizeof(str[i]), "BRIDGEDHOST=abort");
1474 env[i] = str[i]; i++;
1475 break;
1476 case anev_reset:
1477 snprintf(str[i], sizeof(str[i]), "BRIDGEDHOST=reset");
1478 env[i] = str[i]; i++;
1479 break;
1480 }
1481 env[i] = NULL;
1482 kobject_uevent_env(&card->gdev->dev.kobj, KOBJ_CHANGE, env);
1483}
1484
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001485struct qeth_bridge_state_data {
1486 struct work_struct worker;
1487 struct qeth_card *card;
1488 struct qeth_sbp_state_change qports;
1489};
1490
1491static void qeth_bridge_state_change_worker(struct work_struct *work)
1492{
1493 struct qeth_bridge_state_data *data =
1494 container_of(work, struct qeth_bridge_state_data, worker);
1495 /* We are only interested in the first entry - local port */
1496 struct qeth_sbp_port_entry *entry = &data->qports.entry[0];
1497 char env_locrem[32];
1498 char env_role[32];
1499 char env_state[32];
1500 char *env[] = {
1501 env_locrem,
1502 env_role,
1503 env_state,
1504 NULL
1505 };
1506
1507 /* Role should not change by itself, but if it did, */
1508 /* information from the hardware is authoritative. */
1509 mutex_lock(&data->card->conf_mutex);
1510 data->card->options.sbp.role = entry->role;
1511 mutex_unlock(&data->card->conf_mutex);
1512
1513 snprintf(env_locrem, sizeof(env_locrem), "BRIDGEPORT=statechange");
1514 snprintf(env_role, sizeof(env_role), "ROLE=%s",
1515 (entry->role == QETH_SBP_ROLE_NONE) ? "none" :
1516 (entry->role == QETH_SBP_ROLE_PRIMARY) ? "primary" :
1517 (entry->role == QETH_SBP_ROLE_SECONDARY) ? "secondary" :
1518 "<INVALID>");
1519 snprintf(env_state, sizeof(env_state), "STATE=%s",
1520 (entry->state == QETH_SBP_STATE_INACTIVE) ? "inactive" :
1521 (entry->state == QETH_SBP_STATE_STANDBY) ? "standby" :
1522 (entry->state == QETH_SBP_STATE_ACTIVE) ? "active" :
1523 "<INVALID>");
1524 kobject_uevent_env(&data->card->gdev->dev.kobj,
1525 KOBJ_CHANGE, env);
1526 kfree(data);
1527}
1528
Eugene Crosserc044dc22014-01-29 09:23:48 +01001529static void qeth_bridge_state_change(struct qeth_card *card,
1530 struct qeth_ipa_cmd *cmd)
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001531{
1532 struct qeth_sbp_state_change *qports =
1533 &cmd->data.sbp.data.state_change;
1534 struct qeth_bridge_state_data *data;
1535 int extrasize;
1536
1537 QETH_CARD_TEXT(card, 2, "brstchng");
1538 if (qports->entry_length != sizeof(struct qeth_sbp_port_entry)) {
Thomas Richter8a593142014-10-22 12:18:03 +02001539 QETH_CARD_TEXT_(card, 2, "BPsz%04x", qports->entry_length);
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001540 return;
1541 }
1542 extrasize = sizeof(struct qeth_sbp_port_entry) * qports->num_entries;
1543 data = kzalloc(sizeof(struct qeth_bridge_state_data) + extrasize,
1544 GFP_ATOMIC);
1545 if (!data) {
1546 QETH_CARD_TEXT(card, 2, "BPSalloc");
1547 return;
1548 }
1549 INIT_WORK(&data->worker, qeth_bridge_state_change_worker);
1550 data->card = card;
1551 memcpy(&data->qports, qports,
1552 sizeof(struct qeth_sbp_state_change) + extrasize);
1553 queue_work(qeth_wq, &data->worker);
1554}
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001555
Eugene Crosser9f48b9d2014-01-14 15:54:13 +01001556struct qeth_bridge_host_data {
1557 struct work_struct worker;
1558 struct qeth_card *card;
1559 struct qeth_ipacmd_addr_change hostevs;
1560};
1561
1562static void qeth_bridge_host_event_worker(struct work_struct *work)
1563{
1564 struct qeth_bridge_host_data *data =
1565 container_of(work, struct qeth_bridge_host_data, worker);
1566 int i;
1567
1568 if (data->hostevs.lost_event_mask) {
1569 dev_info(&data->card->gdev->dev,
Eugene Crosser9c23f4da2015-05-18 14:27:56 +02001570"Address notification from the Bridge Port stopped %s (%s)\n",
Eugene Crosser9f48b9d2014-01-14 15:54:13 +01001571 data->card->dev->name,
1572 (data->hostevs.lost_event_mask == 0x01)
1573 ? "Overflow"
1574 : (data->hostevs.lost_event_mask == 0x02)
1575 ? "Bridge port state change"
1576 : "Unknown reason");
1577 mutex_lock(&data->card->conf_mutex);
1578 data->card->options.sbp.hostnotification = 0;
1579 mutex_unlock(&data->card->conf_mutex);
1580 qeth_bridge_emit_host_event(data->card, anev_abort,
1581 0, NULL, NULL);
1582 } else
1583 for (i = 0; i < data->hostevs.num_entries; i++) {
1584 struct qeth_ipacmd_addr_change_entry *entry =
1585 &data->hostevs.entry[i];
1586 qeth_bridge_emit_host_event(data->card,
1587 anev_reg_unreg,
1588 entry->change_code,
1589 &entry->token, &entry->addr_lnid);
1590 }
1591 kfree(data);
1592}
1593
Eugene Crosserc044dc22014-01-29 09:23:48 +01001594static void qeth_bridge_host_event(struct qeth_card *card,
1595 struct qeth_ipa_cmd *cmd)
Eugene Crosser9f48b9d2014-01-14 15:54:13 +01001596{
1597 struct qeth_ipacmd_addr_change *hostevs =
1598 &cmd->data.addrchange;
1599 struct qeth_bridge_host_data *data;
1600 int extrasize;
1601
1602 QETH_CARD_TEXT(card, 2, "brhostev");
1603 if (cmd->hdr.return_code != 0x0000) {
1604 if (cmd->hdr.return_code == 0x0010) {
1605 if (hostevs->lost_event_mask == 0x00)
1606 hostevs->lost_event_mask = 0xff;
1607 } else {
1608 QETH_CARD_TEXT_(card, 2, "BPHe%04x",
1609 cmd->hdr.return_code);
1610 return;
1611 }
1612 }
1613 extrasize = sizeof(struct qeth_ipacmd_addr_change_entry) *
1614 hostevs->num_entries;
1615 data = kzalloc(sizeof(struct qeth_bridge_host_data) + extrasize,
1616 GFP_ATOMIC);
1617 if (!data) {
1618 QETH_CARD_TEXT(card, 2, "BPHalloc");
1619 return;
1620 }
1621 INIT_WORK(&data->worker, qeth_bridge_host_event_worker);
1622 data->card = card;
1623 memcpy(&data->hostevs, hostevs,
1624 sizeof(struct qeth_ipacmd_addr_change) + extrasize);
1625 queue_work(qeth_wq, &data->worker);
1626}
Eugene Crosser9f48b9d2014-01-14 15:54:13 +01001627
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001628/* SETBRIDGEPORT support; sending commands */
1629
1630struct _qeth_sbp_cbctl {
1631 u16 ipa_rc;
1632 u16 cmd_rc;
1633 union {
1634 u32 supported;
1635 struct {
1636 enum qeth_sbp_roles *role;
1637 enum qeth_sbp_states *state;
1638 } qports;
1639 } data;
1640};
1641
1642/**
1643 * qeth_bridgeport_makerc() - derive "traditional" error from hardware codes.
1644 * @card: qeth_card structure pointer, for debug messages.
1645 * @cbctl: state structure with hardware return codes.
1646 * @setcmd: IPA command code
1647 *
1648 * Returns negative errno-compatible error indication or 0 on success.
1649 */
1650static int qeth_bridgeport_makerc(struct qeth_card *card,
1651 struct _qeth_sbp_cbctl *cbctl, enum qeth_ipa_sbp_cmd setcmd)
1652{
1653 int rc;
Eugene Crosser9c23f4da2015-05-18 14:27:56 +02001654 int is_iqd = (card->info.type == QETH_CARD_TYPE_IQD);
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001655
Eugene Crosser9c23f4da2015-05-18 14:27:56 +02001656 if ((is_iqd && (cbctl->ipa_rc == IPA_RC_SUCCESS)) ||
1657 (!is_iqd && (cbctl->ipa_rc == cbctl->cmd_rc)))
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001658 switch (cbctl->cmd_rc) {
Kittipon Meesompop2063a5f2017-06-20 16:00:31 +02001659 case IPA_RC_SUCCESS:
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001660 rc = 0;
1661 break;
Kittipon Meesompop2063a5f2017-06-20 16:00:31 +02001662 case IPA_RC_L2_UNSUPPORTED_CMD:
1663 case IPA_RC_UNSUPPORTED_COMMAND:
Eugene Crosserffb95252015-05-18 14:27:58 +02001664 rc = -EOPNOTSUPP;
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001665 break;
Kittipon Meesompop2063a5f2017-06-20 16:00:31 +02001666 case IPA_RC_SBP_OSA_NOT_CONFIGURED:
1667 case IPA_RC_SBP_IQD_NOT_CONFIGURED:
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001668 rc = -ENODEV; /* maybe not the best code here? */
1669 dev_err(&card->gdev->dev,
Eugene Crosser9c23f4da2015-05-18 14:27:56 +02001670 "The device is not configured as a Bridge Port\n");
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001671 break;
Kittipon Meesompop2063a5f2017-06-20 16:00:31 +02001672 case IPA_RC_SBP_OSA_OS_MISMATCH:
1673 case IPA_RC_SBP_IQD_OS_MISMATCH:
Eugene Crosser1b05cf62016-06-16 16:18:51 +02001674 rc = -EPERM;
1675 dev_err(&card->gdev->dev,
1676 "A Bridge Port is already configured by a different operating system\n");
1677 break;
Kittipon Meesompop2063a5f2017-06-20 16:00:31 +02001678 case IPA_RC_SBP_OSA_ANO_DEV_PRIMARY:
1679 case IPA_RC_SBP_IQD_ANO_DEV_PRIMARY:
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001680 switch (setcmd) {
1681 case IPA_SBP_SET_PRIMARY_BRIDGE_PORT:
1682 rc = -EEXIST;
1683 dev_err(&card->gdev->dev,
Eugene Crosser9c23f4da2015-05-18 14:27:56 +02001684 "The LAN already has a primary Bridge Port\n");
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001685 break;
1686 case IPA_SBP_SET_SECONDARY_BRIDGE_PORT:
1687 rc = -EBUSY;
1688 dev_err(&card->gdev->dev,
Eugene Crosser9c23f4da2015-05-18 14:27:56 +02001689 "The device is already a primary Bridge Port\n");
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001690 break;
1691 default:
1692 rc = -EIO;
1693 }
1694 break;
Kittipon Meesompop2063a5f2017-06-20 16:00:31 +02001695 case IPA_RC_SBP_OSA_CURRENT_SECOND:
1696 case IPA_RC_SBP_IQD_CURRENT_SECOND:
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001697 rc = -EBUSY;
1698 dev_err(&card->gdev->dev,
Eugene Crosser9c23f4da2015-05-18 14:27:56 +02001699 "The device is already a secondary Bridge Port\n");
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001700 break;
Kittipon Meesompop2063a5f2017-06-20 16:00:31 +02001701 case IPA_RC_SBP_OSA_LIMIT_SECOND:
1702 case IPA_RC_SBP_IQD_LIMIT_SECOND:
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001703 rc = -EEXIST;
1704 dev_err(&card->gdev->dev,
Eugene Crosser9c23f4da2015-05-18 14:27:56 +02001705 "The LAN cannot have more secondary Bridge Ports\n");
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001706 break;
Kittipon Meesompop2063a5f2017-06-20 16:00:31 +02001707 case IPA_RC_SBP_OSA_CURRENT_PRIMARY:
1708 case IPA_RC_SBP_IQD_CURRENT_PRIMARY:
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001709 rc = -EBUSY;
1710 dev_err(&card->gdev->dev,
Eugene Crosser9c23f4da2015-05-18 14:27:56 +02001711 "The device is already a primary Bridge Port\n");
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001712 break;
Kittipon Meesompop2063a5f2017-06-20 16:00:31 +02001713 case IPA_RC_SBP_OSA_NOT_AUTHD_BY_ZMAN:
1714 case IPA_RC_SBP_IQD_NOT_AUTHD_BY_ZMAN:
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001715 rc = -EACCES;
1716 dev_err(&card->gdev->dev,
Eugene Crosser9c23f4da2015-05-18 14:27:56 +02001717 "The device is not authorized to be a Bridge Port\n");
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001718 break;
1719 default:
1720 rc = -EIO;
1721 }
Eugene Crosser9c23f4da2015-05-18 14:27:56 +02001722 else
1723 switch (cbctl->ipa_rc) {
1724 case IPA_RC_NOTSUPP:
Eugene Crosserffb95252015-05-18 14:27:58 +02001725 rc = -EOPNOTSUPP;
Eugene Crosser9c23f4da2015-05-18 14:27:56 +02001726 break;
1727 case IPA_RC_UNSUPPORTED_COMMAND:
Eugene Crosserffb95252015-05-18 14:27:58 +02001728 rc = -EOPNOTSUPP;
Eugene Crosser9c23f4da2015-05-18 14:27:56 +02001729 break;
1730 default:
1731 rc = -EIO;
1732 }
1733
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001734 if (rc) {
1735 QETH_CARD_TEXT_(card, 2, "SBPi%04x", cbctl->ipa_rc);
1736 QETH_CARD_TEXT_(card, 2, "SBPc%04x", cbctl->cmd_rc);
1737 }
1738 return rc;
1739}
1740
Julian Wiedmannd65626a2017-08-15 17:02:47 +02001741static struct qeth_cmd_buffer *qeth_sbp_build_cmd(struct qeth_card *card,
1742 enum qeth_ipa_sbp_cmd sbp_cmd,
1743 unsigned int cmd_length)
Eugene Crosser9c23f4da2015-05-18 14:27:56 +02001744{
Julian Wiedmannd65626a2017-08-15 17:02:47 +02001745 enum qeth_ipa_cmds ipa_cmd = (card->info.type == QETH_CARD_TYPE_IQD) ?
1746 IPA_CMD_SETBRIDGEPORT_IQD :
1747 IPA_CMD_SETBRIDGEPORT_OSA;
1748 struct qeth_cmd_buffer *iob;
1749 struct qeth_ipa_cmd *cmd;
1750
1751 iob = qeth_get_ipacmd_buffer(card, ipa_cmd, 0);
1752 if (!iob)
1753 return iob;
Julian Wiedmannff5caa72018-03-09 18:12:52 +01001754 cmd = __ipa_cmd(iob);
Julian Wiedmannd65626a2017-08-15 17:02:47 +02001755 cmd->data.sbp.hdr.cmdlength = sizeof(struct qeth_ipacmd_sbp_hdr) +
1756 cmd_length;
1757 cmd->data.sbp.hdr.command_code = sbp_cmd;
1758 cmd->data.sbp.hdr.used_total = 1;
1759 cmd->data.sbp.hdr.seq_no = 1;
1760 return iob;
Eugene Crosser9c23f4da2015-05-18 14:27:56 +02001761}
1762
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001763static int qeth_bridgeport_query_support_cb(struct qeth_card *card,
1764 struct qeth_reply *reply, unsigned long data)
1765{
1766 struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data;
1767 struct _qeth_sbp_cbctl *cbctl = (struct _qeth_sbp_cbctl *)reply->param;
1768 QETH_CARD_TEXT(card, 2, "brqsupcb");
1769 cbctl->ipa_rc = cmd->hdr.return_code;
1770 cbctl->cmd_rc = cmd->data.sbp.hdr.return_code;
1771 if ((cbctl->ipa_rc == 0) && (cbctl->cmd_rc == 0)) {
1772 cbctl->data.supported =
1773 cmd->data.sbp.data.query_cmds_supp.supported_cmds;
1774 } else {
1775 cbctl->data.supported = 0;
1776 }
1777 return 0;
1778}
1779
1780/**
1781 * qeth_bridgeport_query_support() - store bitmask of supported subfunctions.
1782 * @card: qeth_card structure pointer.
1783 *
1784 * Sets bitmask of supported setbridgeport subfunctions in the qeth_card
1785 * strucutre: card->options.sbp.supported_funcs.
1786 */
Eugene Crosserc044dc22014-01-29 09:23:48 +01001787static void qeth_bridgeport_query_support(struct qeth_card *card)
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001788{
1789 struct qeth_cmd_buffer *iob;
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001790 struct _qeth_sbp_cbctl cbctl;
1791
1792 QETH_CARD_TEXT(card, 2, "brqsuppo");
Julian Wiedmannd65626a2017-08-15 17:02:47 +02001793 iob = qeth_sbp_build_cmd(card, IPA_SBP_QUERY_COMMANDS_SUPPORTED,
1794 sizeof(struct qeth_sbp_query_cmds_supp));
Thomas Richter1aec42b2015-01-21 13:39:10 +01001795 if (!iob)
1796 return;
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001797 if (qeth_send_ipa_cmd(card, iob, qeth_bridgeport_query_support_cb,
1798 (void *)&cbctl) ||
1799 qeth_bridgeport_makerc(card, &cbctl,
1800 IPA_SBP_QUERY_COMMANDS_SUPPORTED)) {
1801 /* non-zero makerc signifies failure, and produce messages */
1802 card->options.sbp.role = QETH_SBP_ROLE_NONE;
1803 return;
1804 }
1805 card->options.sbp.supported_funcs = cbctl.data.supported;
1806}
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001807
1808static int qeth_bridgeport_query_ports_cb(struct qeth_card *card,
1809 struct qeth_reply *reply, unsigned long data)
1810{
1811 struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data;
1812 struct qeth_sbp_query_ports *qports = &cmd->data.sbp.data.query_ports;
1813 struct _qeth_sbp_cbctl *cbctl = (struct _qeth_sbp_cbctl *)reply->param;
1814
1815 QETH_CARD_TEXT(card, 2, "brqprtcb");
1816 cbctl->ipa_rc = cmd->hdr.return_code;
1817 cbctl->cmd_rc = cmd->data.sbp.hdr.return_code;
1818 if ((cbctl->ipa_rc != 0) || (cbctl->cmd_rc != 0))
1819 return 0;
1820 if (qports->entry_length != sizeof(struct qeth_sbp_port_entry)) {
1821 cbctl->cmd_rc = 0xffff;
1822 QETH_CARD_TEXT_(card, 2, "SBPs%04x", qports->entry_length);
1823 return 0;
1824 }
1825 /* first entry contains the state of the local port */
1826 if (qports->num_entries > 0) {
1827 if (cbctl->data.qports.role)
1828 *cbctl->data.qports.role = qports->entry[0].role;
1829 if (cbctl->data.qports.state)
1830 *cbctl->data.qports.state = qports->entry[0].state;
1831 }
1832 return 0;
1833}
1834
1835/**
1836 * qeth_bridgeport_query_ports() - query local bridgeport status.
1837 * @card: qeth_card structure pointer.
1838 * @role: Role of the port: 0-none, 1-primary, 2-secondary.
1839 * @state: State of the port: 0-inactive, 1-standby, 2-active.
1840 *
1841 * Returns negative errno-compatible error indication or 0 on success.
1842 *
1843 * 'role' and 'state' are not updated in case of hardware operation failure.
1844 */
1845int qeth_bridgeport_query_ports(struct qeth_card *card,
1846 enum qeth_sbp_roles *role, enum qeth_sbp_states *state)
1847{
1848 int rc = 0;
1849 struct qeth_cmd_buffer *iob;
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001850 struct _qeth_sbp_cbctl cbctl = {
1851 .data = {
1852 .qports = {
1853 .role = role,
1854 .state = state,
1855 },
1856 },
1857 };
1858
1859 QETH_CARD_TEXT(card, 2, "brqports");
1860 if (!(card->options.sbp.supported_funcs & IPA_SBP_QUERY_BRIDGE_PORTS))
1861 return -EOPNOTSUPP;
Julian Wiedmannd65626a2017-08-15 17:02:47 +02001862 iob = qeth_sbp_build_cmd(card, IPA_SBP_QUERY_BRIDGE_PORTS, 0);
Thomas Richter1aec42b2015-01-21 13:39:10 +01001863 if (!iob)
1864 return -ENOMEM;
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001865 rc = qeth_send_ipa_cmd(card, iob, qeth_bridgeport_query_ports_cb,
1866 (void *)&cbctl);
Eugene Crosserc88394e2015-05-18 14:27:53 +02001867 if (rc < 0)
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001868 return rc;
Eugene Crosserc88394e2015-05-18 14:27:53 +02001869 return qeth_bridgeport_makerc(card, &cbctl, IPA_SBP_QUERY_BRIDGE_PORTS);
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001870}
1871EXPORT_SYMBOL_GPL(qeth_bridgeport_query_ports);
1872
1873static int qeth_bridgeport_set_cb(struct qeth_card *card,
1874 struct qeth_reply *reply, unsigned long data)
1875{
1876 struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *)data;
1877 struct _qeth_sbp_cbctl *cbctl = (struct _qeth_sbp_cbctl *)reply->param;
1878 QETH_CARD_TEXT(card, 2, "brsetrcb");
1879 cbctl->ipa_rc = cmd->hdr.return_code;
1880 cbctl->cmd_rc = cmd->data.sbp.hdr.return_code;
1881 return 0;
1882}
1883
1884/**
1885 * qeth_bridgeport_setrole() - Assign primary role to the port.
1886 * @card: qeth_card structure pointer.
1887 * @role: Role to assign.
1888 *
1889 * Returns negative errno-compatible error indication or 0 on success.
1890 */
1891int qeth_bridgeport_setrole(struct qeth_card *card, enum qeth_sbp_roles role)
1892{
1893 int rc = 0;
1894 int cmdlength;
1895 struct qeth_cmd_buffer *iob;
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001896 struct _qeth_sbp_cbctl cbctl;
1897 enum qeth_ipa_sbp_cmd setcmd;
1898
1899 QETH_CARD_TEXT(card, 2, "brsetrol");
1900 switch (role) {
1901 case QETH_SBP_ROLE_NONE:
1902 setcmd = IPA_SBP_RESET_BRIDGE_PORT_ROLE;
Julian Wiedmannd65626a2017-08-15 17:02:47 +02001903 cmdlength = sizeof(struct qeth_sbp_reset_role);
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001904 break;
1905 case QETH_SBP_ROLE_PRIMARY:
1906 setcmd = IPA_SBP_SET_PRIMARY_BRIDGE_PORT;
Julian Wiedmannd65626a2017-08-15 17:02:47 +02001907 cmdlength = sizeof(struct qeth_sbp_set_primary);
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001908 break;
1909 case QETH_SBP_ROLE_SECONDARY:
1910 setcmd = IPA_SBP_SET_SECONDARY_BRIDGE_PORT;
Julian Wiedmannd65626a2017-08-15 17:02:47 +02001911 cmdlength = sizeof(struct qeth_sbp_set_secondary);
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001912 break;
1913 default:
1914 return -EINVAL;
1915 }
1916 if (!(card->options.sbp.supported_funcs & setcmd))
1917 return -EOPNOTSUPP;
Julian Wiedmannd65626a2017-08-15 17:02:47 +02001918 iob = qeth_sbp_build_cmd(card, setcmd, cmdlength);
Thomas Richter1aec42b2015-01-21 13:39:10 +01001919 if (!iob)
1920 return -ENOMEM;
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001921 rc = qeth_send_ipa_cmd(card, iob, qeth_bridgeport_set_cb,
1922 (void *)&cbctl);
Eugene Crosserc88394e2015-05-18 14:27:53 +02001923 if (rc < 0)
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001924 return rc;
Eugene Crosserc88394e2015-05-18 14:27:53 +02001925 return qeth_bridgeport_makerc(card, &cbctl, setcmd);
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001926}
1927
Eugene Crosser9f48b9d2014-01-14 15:54:13 +01001928/**
1929 * qeth_anset_makerc() - derive "traditional" error from hardware codes.
1930 * @card: qeth_card structure pointer, for debug messages.
1931 *
1932 * Returns negative errno-compatible error indication or 0 on success.
1933 */
1934static int qeth_anset_makerc(struct qeth_card *card, int pnso_rc, u16 response)
1935{
1936 int rc;
1937
1938 if (pnso_rc == 0)
1939 switch (response) {
1940 case 0x0001:
1941 rc = 0;
1942 break;
1943 case 0x0004:
1944 case 0x0100:
1945 case 0x0106:
Eugene Crosserffb95252015-05-18 14:27:58 +02001946 rc = -EOPNOTSUPP;
Eugene Crosser9f48b9d2014-01-14 15:54:13 +01001947 dev_err(&card->gdev->dev,
1948 "Setting address notification failed\n");
1949 break;
1950 case 0x0107:
1951 rc = -EAGAIN;
1952 break;
1953 default:
1954 rc = -EIO;
1955 }
1956 else
1957 rc = -EIO;
1958
1959 if (rc) {
1960 QETH_CARD_TEXT_(card, 2, "SBPp%04x", pnso_rc);
1961 QETH_CARD_TEXT_(card, 2, "SBPr%04x", response);
1962 }
1963 return rc;
1964}
1965
1966static void qeth_bridgeport_an_set_cb(void *priv,
1967 enum qdio_brinfo_entry_type type, void *entry)
1968{
1969 struct qeth_card *card = (struct qeth_card *)priv;
1970 struct qdio_brinfo_entry_l2 *l2entry;
1971 u8 code;
1972
1973 if (type != l2_addr_lnid) {
1974 WARN_ON_ONCE(1);
1975 return;
1976 }
1977
1978 l2entry = (struct qdio_brinfo_entry_l2 *)entry;
1979 code = IPA_ADDR_CHANGE_CODE_MACADDR;
1980 if (l2entry->addr_lnid.lnid)
1981 code |= IPA_ADDR_CHANGE_CODE_VLANID;
1982 qeth_bridge_emit_host_event(card, anev_reg_unreg, code,
1983 (struct net_if_token *)&l2entry->nit,
1984 (struct mac_addr_lnid *)&l2entry->addr_lnid);
1985}
1986
1987/**
1988 * qeth_bridgeport_an_set() - Enable or disable bridgeport address notification
1989 * @card: qeth_card structure pointer.
1990 * @enable: 0 - disable, non-zero - enable notifications
1991 *
1992 * Returns negative errno-compatible error indication or 0 on success.
1993 *
1994 * On enable, emits a series of address notifications udev events for all
1995 * currently registered hosts.
1996 */
1997int qeth_bridgeport_an_set(struct qeth_card *card, int enable)
1998{
1999 int rc;
2000 u16 response;
2001 struct ccw_device *ddev;
2002 struct subchannel_id schid;
2003
2004 if (!card)
2005 return -EINVAL;
2006 if (!card->options.sbp.supported_funcs)
2007 return -EOPNOTSUPP;
2008 ddev = CARD_DDEV(card);
2009 ccw_device_get_schid(ddev, &schid);
2010
2011 if (enable) {
2012 qeth_bridge_emit_host_event(card, anev_reset, 0, NULL, NULL);
2013 rc = qdio_pnso_brinfo(schid, 1, &response,
2014 qeth_bridgeport_an_set_cb, card);
2015 } else
2016 rc = qdio_pnso_brinfo(schid, 0, &response, NULL, NULL);
2017 return qeth_anset_makerc(card, rc, response);
2018}
2019EXPORT_SYMBOL_GPL(qeth_bridgeport_an_set);
2020
Hans Wippelcaa1f0b2017-09-18 21:18:15 +02002021static bool qeth_bridgeport_is_in_use(struct qeth_card *card)
2022{
2023 return (card->options.sbp.role || card->options.sbp.reflect_promisc ||
2024 card->options.sbp.hostnotification);
2025}
2026
Hans Wippela45b3fa2017-09-18 21:18:14 +02002027/* VNIC Characteristics support */
2028
2029/* handle VNICC IPA command return codes; convert to error codes */
2030static int qeth_l2_vnicc_makerc(struct qeth_card *card, int ipa_rc)
2031{
2032 int rc;
2033
2034 switch (ipa_rc) {
2035 case IPA_RC_SUCCESS:
2036 return ipa_rc;
2037 case IPA_RC_L2_UNSUPPORTED_CMD:
2038 case IPA_RC_NOTSUPP:
2039 rc = -EOPNOTSUPP;
2040 break;
2041 case IPA_RC_VNICC_OOSEQ:
2042 rc = -EALREADY;
2043 break;
2044 case IPA_RC_VNICC_VNICBP:
2045 rc = -EBUSY;
2046 break;
2047 case IPA_RC_L2_ADDR_TABLE_FULL:
2048 rc = -ENOSPC;
2049 break;
2050 case IPA_RC_L2_MAC_NOT_AUTH_BY_ADP:
2051 rc = -EACCES;
2052 break;
2053 default:
2054 rc = -EIO;
2055 }
2056
2057 QETH_CARD_TEXT_(card, 2, "err%04x", ipa_rc);
2058 return rc;
2059}
2060
2061/* generic VNICC request call back control */
2062struct _qeth_l2_vnicc_request_cbctl {
2063 u32 sub_cmd;
Hans Wippelcaa1f0b2017-09-18 21:18:15 +02002064 struct {
2065 u32 vnic_char;
Hans Wippel349d13d2017-09-18 21:18:16 +02002066 u32 timeout;
Hans Wippelcaa1f0b2017-09-18 21:18:15 +02002067 } param;
2068 struct {
Hans Wippel349d13d2017-09-18 21:18:16 +02002069 union{
2070 u32 *sup_cmds;
2071 u32 *timeout;
2072 };
Hans Wippelcaa1f0b2017-09-18 21:18:15 +02002073 } result;
Hans Wippela45b3fa2017-09-18 21:18:14 +02002074};
2075
2076/* generic VNICC request call back */
2077static int qeth_l2_vnicc_request_cb(struct qeth_card *card,
2078 struct qeth_reply *reply,
2079 unsigned long data)
2080{
Hans Wippelcaa1f0b2017-09-18 21:18:15 +02002081 struct _qeth_l2_vnicc_request_cbctl *cbctl =
2082 (struct _qeth_l2_vnicc_request_cbctl *) reply->param;
Hans Wippela45b3fa2017-09-18 21:18:14 +02002083 struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data;
2084 struct qeth_ipacmd_vnicc *rep = &cmd->data.vnicc;
2085
2086 QETH_CARD_TEXT(card, 2, "vniccrcb");
2087 if (cmd->hdr.return_code)
2088 return 0;
2089 /* return results to caller */
2090 card->options.vnicc.sup_chars = rep->hdr.sup;
2091 card->options.vnicc.cur_chars = rep->hdr.cur;
2092
Hans Wippelcaa1f0b2017-09-18 21:18:15 +02002093 if (cbctl->sub_cmd == IPA_VNICC_QUERY_CMDS)
2094 *cbctl->result.sup_cmds = rep->query_cmds.sup_cmds;
2095
Hans Wippel349d13d2017-09-18 21:18:16 +02002096 if (cbctl->sub_cmd == IPA_VNICC_GET_TIMEOUT)
2097 *cbctl->result.timeout = rep->getset_timeout.timeout;
2098
Hans Wippela45b3fa2017-09-18 21:18:14 +02002099 return 0;
2100}
2101
2102/* generic VNICC request */
2103static int qeth_l2_vnicc_request(struct qeth_card *card,
2104 struct _qeth_l2_vnicc_request_cbctl *cbctl)
2105{
2106 struct qeth_ipacmd_vnicc *req;
2107 struct qeth_cmd_buffer *iob;
2108 struct qeth_ipa_cmd *cmd;
2109 int rc;
2110
2111 QETH_CARD_TEXT(card, 2, "vniccreq");
2112
2113 /* get new buffer for request */
2114 iob = qeth_get_ipacmd_buffer(card, IPA_CMD_VNICC, 0);
2115 if (!iob)
2116 return -ENOMEM;
2117
2118 /* create header for request */
Julian Wiedmannff5caa72018-03-09 18:12:52 +01002119 cmd = __ipa_cmd(iob);
Hans Wippela45b3fa2017-09-18 21:18:14 +02002120 req = &cmd->data.vnicc;
2121
2122 /* create sub command header for request */
2123 req->sub_hdr.data_length = sizeof(req->sub_hdr);
2124 req->sub_hdr.sub_command = cbctl->sub_cmd;
2125
2126 /* create sub command specific request fields */
2127 switch (cbctl->sub_cmd) {
2128 case IPA_VNICC_QUERY_CHARS:
2129 break;
Hans Wippelcaa1f0b2017-09-18 21:18:15 +02002130 case IPA_VNICC_QUERY_CMDS:
2131 req->sub_hdr.data_length += sizeof(req->query_cmds);
2132 req->query_cmds.vnic_char = cbctl->param.vnic_char;
2133 break;
2134 case IPA_VNICC_ENABLE:
2135 case IPA_VNICC_DISABLE:
2136 req->sub_hdr.data_length += sizeof(req->set_char);
2137 req->set_char.vnic_char = cbctl->param.vnic_char;
2138 break;
Hans Wippel349d13d2017-09-18 21:18:16 +02002139 case IPA_VNICC_SET_TIMEOUT:
2140 req->getset_timeout.timeout = cbctl->param.timeout;
2141 /* fallthrough */
2142 case IPA_VNICC_GET_TIMEOUT:
2143 req->sub_hdr.data_length += sizeof(req->getset_timeout);
2144 req->getset_timeout.vnic_char = cbctl->param.vnic_char;
2145 break;
Hans Wippela45b3fa2017-09-18 21:18:14 +02002146 default:
2147 qeth_release_buffer(iob->channel, iob);
2148 return -EOPNOTSUPP;
2149 }
2150
2151 /* send request */
2152 rc = qeth_send_ipa_cmd(card, iob, qeth_l2_vnicc_request_cb,
2153 (void *) cbctl);
2154
2155 return qeth_l2_vnicc_makerc(card, rc);
2156}
2157
2158/* VNICC query VNIC characteristics request */
2159static int qeth_l2_vnicc_query_chars(struct qeth_card *card)
2160{
2161 struct _qeth_l2_vnicc_request_cbctl cbctl;
2162
2163 /* prepare callback control */
2164 cbctl.sub_cmd = IPA_VNICC_QUERY_CHARS;
2165
2166 QETH_CARD_TEXT(card, 2, "vniccqch");
2167 return qeth_l2_vnicc_request(card, &cbctl);
2168}
2169
Hans Wippelcaa1f0b2017-09-18 21:18:15 +02002170/* VNICC query sub commands request */
2171static int qeth_l2_vnicc_query_cmds(struct qeth_card *card, u32 vnic_char,
2172 u32 *sup_cmds)
2173{
2174 struct _qeth_l2_vnicc_request_cbctl cbctl;
2175
2176 /* prepare callback control */
2177 cbctl.sub_cmd = IPA_VNICC_QUERY_CMDS;
2178 cbctl.param.vnic_char = vnic_char;
2179 cbctl.result.sup_cmds = sup_cmds;
2180
2181 QETH_CARD_TEXT(card, 2, "vniccqcm");
2182 return qeth_l2_vnicc_request(card, &cbctl);
2183}
2184
2185/* VNICC enable/disable characteristic request */
2186static int qeth_l2_vnicc_set_char(struct qeth_card *card, u32 vnic_char,
2187 u32 cmd)
2188{
2189 struct _qeth_l2_vnicc_request_cbctl cbctl;
2190
2191 /* prepare callback control */
2192 cbctl.sub_cmd = cmd;
2193 cbctl.param.vnic_char = vnic_char;
2194
2195 QETH_CARD_TEXT(card, 2, "vniccedc");
2196 return qeth_l2_vnicc_request(card, &cbctl);
2197}
2198
Hans Wippel349d13d2017-09-18 21:18:16 +02002199/* VNICC get/set timeout for characteristic request */
2200static int qeth_l2_vnicc_getset_timeout(struct qeth_card *card, u32 vnicc,
2201 u32 cmd, u32 *timeout)
2202{
2203 struct _qeth_l2_vnicc_request_cbctl cbctl;
2204
2205 /* prepare callback control */
2206 cbctl.sub_cmd = cmd;
2207 cbctl.param.vnic_char = vnicc;
2208 if (cmd == IPA_VNICC_SET_TIMEOUT)
2209 cbctl.param.timeout = *timeout;
2210 if (cmd == IPA_VNICC_GET_TIMEOUT)
2211 cbctl.result.timeout = timeout;
2212
2213 QETH_CARD_TEXT(card, 2, "vniccgst");
2214 return qeth_l2_vnicc_request(card, &cbctl);
2215}
2216
Hans Wippelcaa1f0b2017-09-18 21:18:15 +02002217/* set current VNICC flag state; called from sysfs store function */
2218int qeth_l2_vnicc_set_state(struct qeth_card *card, u32 vnicc, bool state)
2219{
2220 int rc = 0;
2221 u32 cmd;
2222
2223 QETH_CARD_TEXT(card, 2, "vniccsch");
2224
2225 /* do not change anything if BridgePort is enabled */
2226 if (qeth_bridgeport_is_in_use(card))
2227 return -EBUSY;
2228
2229 /* check if characteristic and enable/disable are supported */
2230 if (!(card->options.vnicc.sup_chars & vnicc) ||
2231 !(card->options.vnicc.set_char_sup & vnicc))
2232 return -EOPNOTSUPP;
2233
2234 /* set enable/disable command and store wanted characteristic */
2235 if (state) {
2236 cmd = IPA_VNICC_ENABLE;
2237 card->options.vnicc.wanted_chars |= vnicc;
2238 } else {
2239 cmd = IPA_VNICC_DISABLE;
2240 card->options.vnicc.wanted_chars &= ~vnicc;
2241 }
2242
2243 /* do we need to do anything? */
2244 if (card->options.vnicc.cur_chars == card->options.vnicc.wanted_chars)
2245 return rc;
2246
2247 /* if card is not ready, simply stop here */
2248 if (!qeth_card_hw_is_reachable(card)) {
2249 if (state)
2250 card->options.vnicc.cur_chars |= vnicc;
2251 else
2252 card->options.vnicc.cur_chars &= ~vnicc;
2253 return rc;
2254 }
2255
2256 rc = qeth_l2_vnicc_set_char(card, vnicc, cmd);
2257 if (rc)
2258 card->options.vnicc.wanted_chars =
2259 card->options.vnicc.cur_chars;
Hans Wippel349d13d2017-09-18 21:18:16 +02002260 else {
2261 /* successful online VNICC change; handle special cases */
2262 if (state && vnicc == QETH_VNICC_RX_BCAST)
2263 card->options.vnicc.rx_bcast_enabled = true;
2264 if (!state && vnicc == QETH_VNICC_LEARNING)
2265 qeth_l2_vnicc_recover_timeout(card, vnicc,
2266 &card->options.vnicc.learning_timeout);
2267 }
Hans Wippelcaa1f0b2017-09-18 21:18:15 +02002268
2269 return rc;
2270}
2271
2272/* get current VNICC flag state; called from sysfs show function */
2273int qeth_l2_vnicc_get_state(struct qeth_card *card, u32 vnicc, bool *state)
2274{
2275 int rc = 0;
2276
2277 QETH_CARD_TEXT(card, 2, "vniccgch");
2278
2279 /* do not get anything if BridgePort is enabled */
2280 if (qeth_bridgeport_is_in_use(card))
2281 return -EBUSY;
2282
2283 /* check if characteristic is supported */
2284 if (!(card->options.vnicc.sup_chars & vnicc))
2285 return -EOPNOTSUPP;
2286
2287 /* if card is ready, query current VNICC state */
2288 if (qeth_card_hw_is_reachable(card))
2289 rc = qeth_l2_vnicc_query_chars(card);
2290
2291 *state = (card->options.vnicc.cur_chars & vnicc) ? true : false;
2292 return rc;
2293}
2294
Hans Wippel349d13d2017-09-18 21:18:16 +02002295/* set VNICC timeout; called from sysfs store function. Currently, only learning
2296 * supports timeout
2297 */
2298int qeth_l2_vnicc_set_timeout(struct qeth_card *card, u32 timeout)
2299{
2300 int rc = 0;
2301
2302 QETH_CARD_TEXT(card, 2, "vniccsto");
2303
2304 /* do not change anything if BridgePort is enabled */
2305 if (qeth_bridgeport_is_in_use(card))
2306 return -EBUSY;
2307
2308 /* check if characteristic and set_timeout are supported */
2309 if (!(card->options.vnicc.sup_chars & QETH_VNICC_LEARNING) ||
2310 !(card->options.vnicc.getset_timeout_sup & QETH_VNICC_LEARNING))
2311 return -EOPNOTSUPP;
2312
2313 /* do we need to do anything? */
2314 if (card->options.vnicc.learning_timeout == timeout)
2315 return rc;
2316
2317 /* if card is not ready, simply store the value internally and return */
2318 if (!qeth_card_hw_is_reachable(card)) {
2319 card->options.vnicc.learning_timeout = timeout;
2320 return rc;
2321 }
2322
2323 /* send timeout value to card; if successful, store value internally */
2324 rc = qeth_l2_vnicc_getset_timeout(card, QETH_VNICC_LEARNING,
2325 IPA_VNICC_SET_TIMEOUT, &timeout);
2326 if (!rc)
2327 card->options.vnicc.learning_timeout = timeout;
2328
2329 return rc;
2330}
2331
2332/* get current VNICC timeout; called from sysfs show function. Currently, only
2333 * learning supports timeout
2334 */
2335int qeth_l2_vnicc_get_timeout(struct qeth_card *card, u32 *timeout)
2336{
2337 int rc = 0;
2338
2339 QETH_CARD_TEXT(card, 2, "vniccgto");
2340
2341 /* do not get anything if BridgePort is enabled */
2342 if (qeth_bridgeport_is_in_use(card))
2343 return -EBUSY;
2344
2345 /* check if characteristic and get_timeout are supported */
2346 if (!(card->options.vnicc.sup_chars & QETH_VNICC_LEARNING) ||
2347 !(card->options.vnicc.getset_timeout_sup & QETH_VNICC_LEARNING))
2348 return -EOPNOTSUPP;
2349 /* if card is ready, get timeout. Otherwise, just return stored value */
2350 *timeout = card->options.vnicc.learning_timeout;
2351 if (qeth_card_hw_is_reachable(card))
2352 rc = qeth_l2_vnicc_getset_timeout(card, QETH_VNICC_LEARNING,
2353 IPA_VNICC_GET_TIMEOUT,
2354 timeout);
2355
2356 return rc;
2357}
2358
Hans Wippelcaa1f0b2017-09-18 21:18:15 +02002359/* check if VNICC is currently enabled */
2360bool qeth_l2_vnicc_is_in_use(struct qeth_card *card)
2361{
2362 /* if everything is turned off, VNICC is not active */
2363 if (!card->options.vnicc.cur_chars)
2364 return false;
2365 /* default values are only OK if rx_bcast was not enabled by user
2366 * or the card is offline.
2367 */
2368 if (card->options.vnicc.cur_chars == QETH_VNICC_DEFAULT) {
2369 if (!card->options.vnicc.rx_bcast_enabled ||
2370 !qeth_card_hw_is_reachable(card))
2371 return false;
2372 }
2373 return true;
2374}
2375
Hans Wippel349d13d2017-09-18 21:18:16 +02002376/* recover user timeout setting */
2377static bool qeth_l2_vnicc_recover_timeout(struct qeth_card *card, u32 vnicc,
2378 u32 *timeout)
2379{
2380 if (card->options.vnicc.sup_chars & vnicc &&
2381 card->options.vnicc.getset_timeout_sup & vnicc &&
2382 !qeth_l2_vnicc_getset_timeout(card, vnicc, IPA_VNICC_SET_TIMEOUT,
2383 timeout))
2384 return false;
2385 *timeout = QETH_VNICC_DEFAULT_TIMEOUT;
2386 return true;
2387}
2388
Hans Wippelcaa1f0b2017-09-18 21:18:15 +02002389/* recover user characteristic setting */
2390static bool qeth_l2_vnicc_recover_char(struct qeth_card *card, u32 vnicc,
2391 bool enable)
2392{
2393 u32 cmd = enable ? IPA_VNICC_ENABLE : IPA_VNICC_DISABLE;
2394
2395 if (card->options.vnicc.sup_chars & vnicc &&
2396 card->options.vnicc.set_char_sup & vnicc &&
2397 !qeth_l2_vnicc_set_char(card, vnicc, cmd))
2398 return false;
2399 card->options.vnicc.wanted_chars &= ~vnicc;
2400 card->options.vnicc.wanted_chars |= QETH_VNICC_DEFAULT & vnicc;
2401 return true;
2402}
2403
Hans Wippela45b3fa2017-09-18 21:18:14 +02002404/* (re-)initialize VNICC */
2405static void qeth_l2_vnicc_init(struct qeth_card *card)
2406{
Hans Wippel349d13d2017-09-18 21:18:16 +02002407 u32 *timeout = &card->options.vnicc.learning_timeout;
Hans Wippelcaa1f0b2017-09-18 21:18:15 +02002408 unsigned int chars_len, i;
2409 unsigned long chars_tmp;
2410 u32 sup_cmds, vnicc;
2411 bool enable, error;
2412
Hans Wippela45b3fa2017-09-18 21:18:14 +02002413 QETH_CARD_TEXT(card, 2, "vniccini");
Hans Wippelcaa1f0b2017-09-18 21:18:15 +02002414 /* reset rx_bcast */
2415 card->options.vnicc.rx_bcast_enabled = 0;
Hans Wippela45b3fa2017-09-18 21:18:14 +02002416 /* initial query and storage of VNIC characteristics */
2417 if (qeth_l2_vnicc_query_chars(card)) {
Hans Wippel349d13d2017-09-18 21:18:16 +02002418 if (card->options.vnicc.wanted_chars != QETH_VNICC_DEFAULT ||
2419 *timeout != QETH_VNICC_DEFAULT_TIMEOUT)
Hans Wippelcaa1f0b2017-09-18 21:18:15 +02002420 dev_err(&card->gdev->dev, "Configuring the VNIC characteristics failed\n");
2421 /* fail quietly if user didn't change the default config */
Hans Wippela45b3fa2017-09-18 21:18:14 +02002422 card->options.vnicc.sup_chars = 0;
2423 card->options.vnicc.cur_chars = 0;
Hans Wippelcaa1f0b2017-09-18 21:18:15 +02002424 card->options.vnicc.wanted_chars = QETH_VNICC_DEFAULT;
2425 return;
Hans Wippela45b3fa2017-09-18 21:18:14 +02002426 }
Hans Wippelcaa1f0b2017-09-18 21:18:15 +02002427 /* get supported commands for each supported characteristic */
2428 chars_tmp = card->options.vnicc.sup_chars;
2429 chars_len = sizeof(card->options.vnicc.sup_chars) * BITS_PER_BYTE;
2430 for_each_set_bit(i, &chars_tmp, chars_len) {
2431 vnicc = BIT(i);
2432 qeth_l2_vnicc_query_cmds(card, vnicc, &sup_cmds);
Hans Wippel349d13d2017-09-18 21:18:16 +02002433 if (!(sup_cmds & IPA_VNICC_SET_TIMEOUT) ||
2434 !(sup_cmds & IPA_VNICC_GET_TIMEOUT))
2435 card->options.vnicc.getset_timeout_sup &= ~vnicc;
Hans Wippelcaa1f0b2017-09-18 21:18:15 +02002436 if (!(sup_cmds & IPA_VNICC_ENABLE) ||
2437 !(sup_cmds & IPA_VNICC_DISABLE))
2438 card->options.vnicc.set_char_sup &= ~vnicc;
2439 }
2440 /* enforce assumed default values and recover settings, if changed */
Hans Wippel349d13d2017-09-18 21:18:16 +02002441 error = qeth_l2_vnicc_recover_timeout(card, QETH_VNICC_LEARNING,
2442 timeout);
Hans Wippelcaa1f0b2017-09-18 21:18:15 +02002443 chars_tmp = card->options.vnicc.wanted_chars ^ QETH_VNICC_DEFAULT;
2444 chars_tmp |= QETH_VNICC_BRIDGE_INVISIBLE;
2445 chars_len = sizeof(card->options.vnicc.wanted_chars) * BITS_PER_BYTE;
2446 for_each_set_bit(i, &chars_tmp, chars_len) {
2447 vnicc = BIT(i);
2448 enable = card->options.vnicc.wanted_chars & vnicc;
2449 error |= qeth_l2_vnicc_recover_char(card, vnicc, enable);
2450 }
2451 if (error)
2452 dev_err(&card->gdev->dev, "Configuring the VNIC characteristics failed\n");
2453}
2454
2455/* configure default values of VNIC characteristics */
2456static void qeth_l2_vnicc_set_defaults(struct qeth_card *card)
2457{
2458 /* characteristics values */
2459 card->options.vnicc.sup_chars = QETH_VNICC_ALL;
2460 card->options.vnicc.cur_chars = QETH_VNICC_DEFAULT;
Hans Wippel349d13d2017-09-18 21:18:16 +02002461 card->options.vnicc.learning_timeout = QETH_VNICC_DEFAULT_TIMEOUT;
Hans Wippelcaa1f0b2017-09-18 21:18:15 +02002462 /* supported commands */
2463 card->options.vnicc.set_char_sup = QETH_VNICC_ALL;
Hans Wippel349d13d2017-09-18 21:18:16 +02002464 card->options.vnicc.getset_timeout_sup = QETH_VNICC_LEARNING;
Hans Wippelcaa1f0b2017-09-18 21:18:15 +02002465 /* settings wanted by users */
2466 card->options.vnicc.wanted_chars = QETH_VNICC_DEFAULT;
Hans Wippela45b3fa2017-09-18 21:18:14 +02002467}
2468
Frank Blaschka4a71df52008-02-15 09:19:42 +01002469module_init(qeth_l2_init);
2470module_exit(qeth_l2_exit);
2471MODULE_AUTHOR("Frank Blaschka <frank.blaschka@de.ibm.com>");
2472MODULE_DESCRIPTION("qeth layer 2 discipline");
2473MODULE_LICENSE("GPL");