blob: 88dd92954eec17efe4ad2004240f3c39714a5d82 [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>
Frank Blaschka4a71df52008-02-15 09:19:42 +010020#include <linux/ip.h>
Jiri Pirkoccffad252009-05-22 23:22:17 +000021#include <linux/list.h>
Lakhvich Dmitriyfe5c8022015-10-06 15:12:28 +020022#include <linux/hash.h>
23#include <linux/hashtable.h>
24#include <linux/string.h>
Julian Wiedmannec61bd22017-06-20 16:00:34 +020025#include <asm/setup.h>
Frank Blaschka4a71df52008-02-15 09:19:42 +010026#include "qeth_core.h"
Eugene Crosserb4d72c02014-01-14 15:54:11 +010027#include "qeth_l2.h"
Frank Blaschka4a71df52008-02-15 09:19:42 +010028
Frank Blaschka4a71df52008-02-15 09:19:42 +010029static int qeth_l2_set_offline(struct ccwgroup_device *);
30static int qeth_l2_stop(struct net_device *);
Lakhvich Dmitriyfe5c8022015-10-06 15:12:28 +020031static void qeth_l2_set_rx_mode(struct net_device *);
Eugene Crosserc044dc22014-01-29 09:23:48 +010032static void qeth_bridgeport_query_support(struct qeth_card *card);
33static void qeth_bridge_state_change(struct qeth_card *card,
34 struct qeth_ipa_cmd *cmd);
35static void qeth_bridge_host_event(struct qeth_card *card,
36 struct qeth_ipa_cmd *cmd);
Hans Wippelcaa1f0b2017-09-18 21:18:15 +020037static void qeth_l2_vnicc_set_defaults(struct qeth_card *card);
Hans Wippela45b3fa2017-09-18 21:18:14 +020038static void qeth_l2_vnicc_init(struct qeth_card *card);
Hans Wippel349d13d2017-09-18 21:18:16 +020039static bool qeth_l2_vnicc_recover_timeout(struct qeth_card *card, u32 vnicc,
40 u32 *timeout);
Frank Blaschka4a71df52008-02-15 09:19:42 +010041
Frank Blaschka4a71df52008-02-15 09:19:42 +010042static struct net_device *qeth_l2_netdev_by_devno(unsigned char *read_dev_no)
43{
44 struct qeth_card *card;
45 struct net_device *ndev;
Cornelia Huckf06f6f32008-06-06 12:37:45 +020046 __u16 temp_dev_no;
Frank Blaschka4a71df52008-02-15 09:19:42 +010047 unsigned long flags;
Cornelia Huckf06f6f32008-06-06 12:37:45 +020048 struct ccw_dev_id read_devid;
Frank Blaschka4a71df52008-02-15 09:19:42 +010049
50 ndev = NULL;
51 memcpy(&temp_dev_no, read_dev_no, 2);
52 read_lock_irqsave(&qeth_core_card_list.rwlock, flags);
53 list_for_each_entry(card, &qeth_core_card_list.list, list) {
Cornelia Huckf06f6f32008-06-06 12:37:45 +020054 ccw_device_get_id(CARD_RDEV(card), &read_devid);
55 if (read_devid.devno == temp_dev_no) {
Frank Blaschka4a71df52008-02-15 09:19:42 +010056 ndev = card->dev;
57 break;
58 }
59 }
60 read_unlock_irqrestore(&qeth_core_card_list.rwlock, flags);
61 return ndev;
62}
63
Julian Wiedmann2aa48672017-09-18 21:18:20 +020064static int qeth_setdelmac_makerc(struct qeth_card *card, int retcode)
Frank Blaschka4a71df52008-02-15 09:19:42 +010065{
Eugene Crosserefbbc1d2015-01-21 13:39:09 +010066 int rc;
Frank Blaschka4a71df52008-02-15 09:19:42 +010067
Eugene Crosserefbbc1d2015-01-21 13:39:09 +010068 if (retcode)
Thomas Richter1aec42b2015-01-21 13:39:10 +010069 QETH_CARD_TEXT_(card, 2, "err%04x", retcode);
Eugene Crosserefbbc1d2015-01-21 13:39:09 +010070 switch (retcode) {
71 case IPA_RC_SUCCESS:
72 rc = 0;
73 break;
74 case IPA_RC_L2_UNSUPPORTED_CMD:
Eugene Crosserffb95252015-05-18 14:27:58 +020075 rc = -EOPNOTSUPP;
Eugene Crosserefbbc1d2015-01-21 13:39:09 +010076 break;
77 case IPA_RC_L2_ADDR_TABLE_FULL:
78 rc = -ENOSPC;
79 break;
80 case IPA_RC_L2_DUP_MAC:
81 case IPA_RC_L2_DUP_LAYER3_MAC:
82 rc = -EEXIST;
83 break;
84 case IPA_RC_L2_MAC_NOT_AUTH_BY_HYP:
85 case IPA_RC_L2_MAC_NOT_AUTH_BY_ADP:
86 rc = -EPERM;
87 break;
88 case IPA_RC_L2_MAC_NOT_FOUND:
89 rc = -ENOENT;
90 break;
Thomas Richter1aec42b2015-01-21 13:39:10 +010091 case -ENOMEM:
92 rc = -ENOMEM;
93 break;
Eugene Crosserefbbc1d2015-01-21 13:39:09 +010094 default:
95 rc = -EIO;
96 break;
Frank Blaschka4a71df52008-02-15 09:19:42 +010097 }
Eugene Crosserefbbc1d2015-01-21 13:39:09 +010098 return rc;
Frank Blaschka4a71df52008-02-15 09:19:42 +010099}
100
Julian Wiedmannac988d72017-01-12 15:48:41 +0100101static int qeth_l2_send_setdelmac(struct qeth_card *card, __u8 *mac,
102 enum qeth_ipa_cmds ipacmd)
103{
104 struct qeth_ipa_cmd *cmd;
105 struct qeth_cmd_buffer *iob;
106
107 QETH_CARD_TEXT(card, 2, "L2sdmac");
108 iob = qeth_get_ipacmd_buffer(card, ipacmd, QETH_PROT_IPV4);
109 if (!iob)
110 return -ENOMEM;
111 cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
112 cmd->data.setdelmac.mac_length = OSA_ADDR_LEN;
113 memcpy(&cmd->data.setdelmac.mac, mac, OSA_ADDR_LEN);
Julian Wiedmann2aa48672017-09-18 21:18:20 +0200114 return qeth_setdelmac_makerc(card, qeth_send_ipa_cmd(card, iob,
115 NULL, NULL));
Julian Wiedmannac988d72017-01-12 15:48:41 +0100116}
117
118static int qeth_l2_send_setmac(struct qeth_card *card, __u8 *mac)
119{
120 int rc;
121
122 QETH_CARD_TEXT(card, 2, "L2Setmac");
123 rc = qeth_l2_send_setdelmac(card, mac, IPA_CMD_SETVMAC);
124 if (rc == 0) {
125 card->info.mac_bits |= QETH_LAYER2_MAC_REGISTERED;
126 memcpy(card->dev->dev_addr, mac, OSA_ADDR_LEN);
127 dev_info(&card->gdev->dev,
128 "MAC address %pM successfully registered on device %s\n",
129 card->dev->dev_addr, card->dev->name);
130 } else {
131 card->info.mac_bits &= ~QETH_LAYER2_MAC_REGISTERED;
132 switch (rc) {
133 case -EEXIST:
134 dev_warn(&card->gdev->dev,
135 "MAC address %pM already exists\n", mac);
136 break;
137 case -EPERM:
138 dev_warn(&card->gdev->dev,
139 "MAC address %pM is not authorized\n", mac);
140 break;
141 }
142 }
143 return rc;
144}
145
146static int qeth_l2_send_delmac(struct qeth_card *card, __u8 *mac)
147{
148 int rc;
149
150 QETH_CARD_TEXT(card, 2, "L2Delmac");
151 if (!(card->info.mac_bits & QETH_LAYER2_MAC_REGISTERED))
152 return 0;
153 rc = qeth_l2_send_setdelmac(card, mac, IPA_CMD_DELVMAC);
154 if (rc == 0)
155 card->info.mac_bits &= ~QETH_LAYER2_MAC_REGISTERED;
156 return rc;
157}
158
Frank Blaschka4a71df52008-02-15 09:19:42 +0100159static int qeth_l2_send_setgroupmac(struct qeth_card *card, __u8 *mac)
160{
Eugene Crosserefbbc1d2015-01-21 13:39:09 +0100161 int rc;
162
Carsten Otte847a50f2010-06-21 22:57:05 +0000163 QETH_CARD_TEXT(card, 2, "L2Sgmac");
Julian Wiedmann754e0b82017-01-12 15:48:39 +0100164 rc = qeth_l2_send_setdelmac(card, mac, IPA_CMD_SETGMAC);
Eugene Crosserefbbc1d2015-01-21 13:39:09 +0100165 if (rc == -EEXIST)
166 QETH_DBF_MESSAGE(2, "Group MAC %pM already existing on %s\n",
167 mac, QETH_CARD_IFNAME(card));
168 else if (rc)
169 QETH_DBF_MESSAGE(2, "Could not set group MAC %pM on %s: %d\n",
170 mac, QETH_CARD_IFNAME(card), rc);
171 return rc;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100172}
173
174static int qeth_l2_send_delgroupmac(struct qeth_card *card, __u8 *mac)
175{
Eugene Crosserefbbc1d2015-01-21 13:39:09 +0100176 int rc;
177
Carsten Otte847a50f2010-06-21 22:57:05 +0000178 QETH_CARD_TEXT(card, 2, "L2Dgmac");
Julian Wiedmann754e0b82017-01-12 15:48:39 +0100179 rc = qeth_l2_send_setdelmac(card, mac, IPA_CMD_DELGMAC);
Eugene Crosserefbbc1d2015-01-21 13:39:09 +0100180 if (rc)
181 QETH_DBF_MESSAGE(2,
182 "Could not delete group MAC %pM on %s: %d\n",
183 mac, QETH_CARD_IFNAME(card), rc);
184 return rc;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100185}
186
Lakhvich Dmitriyfe5c8022015-10-06 15:12:28 +0200187static int qeth_l2_write_mac(struct qeth_card *card, struct qeth_mac *mac)
Frank Blaschka4a71df52008-02-15 09:19:42 +0100188{
Julian Wiedmann4641b022017-12-20 20:10:59 +0100189 if (is_multicast_ether_addr_64bits(mac->mac_addr))
Julian Wiedmann979d7922017-01-12 15:48:40 +0100190 return qeth_l2_send_setgroupmac(card, mac->mac_addr);
Julian Wiedmann4641b022017-12-20 20:10:59 +0100191 return qeth_l2_send_setdelmac(card, mac->mac_addr, IPA_CMD_SETVMAC);
Julian Wiedmann979d7922017-01-12 15:48:40 +0100192}
193
194static int qeth_l2_remove_mac(struct qeth_card *card, struct qeth_mac *mac)
195{
Julian Wiedmann4641b022017-12-20 20:10:59 +0100196 if (is_multicast_ether_addr_64bits(mac->mac_addr))
Julian Wiedmann979d7922017-01-12 15:48:40 +0100197 return qeth_l2_send_delgroupmac(card, mac->mac_addr);
Julian Wiedmann4641b022017-12-20 20:10:59 +0100198 return qeth_l2_send_setdelmac(card, mac->mac_addr, IPA_CMD_DELVMAC);
Lakhvich Dmitriyfe5c8022015-10-06 15:12:28 +0200199}
200
Julian Wiedmannc07cbf22017-01-12 15:48:37 +0100201static void qeth_l2_del_all_macs(struct qeth_card *card)
Lakhvich Dmitriyfe5c8022015-10-06 15:12:28 +0200202{
203 struct qeth_mac *mac;
204 struct hlist_node *tmp;
205 int i;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100206
207 spin_lock_bh(&card->mclock);
Lakhvich Dmitriyfe5c8022015-10-06 15:12:28 +0200208 hash_for_each_safe(card->mac_htable, i, tmp, mac, hnode) {
Lakhvich Dmitriyfe5c8022015-10-06 15:12:28 +0200209 hash_del(&mac->hnode);
210 kfree(mac);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100211 }
212 spin_unlock_bh(&card->mclock);
213}
214
Julian Wiedmanncef6ff222017-08-15 17:02:46 +0200215static int qeth_l2_get_cast_type(struct qeth_card *card, struct sk_buff *skb)
Frank Blaschka4a71df52008-02-15 09:19:42 +0100216{
Klaus-Dieter Wackerce73e102009-08-26 02:01:08 +0000217 if (card->info.type == QETH_CARD_TYPE_OSN)
218 return RTN_UNSPEC;
219 if (is_broadcast_ether_addr(skb->data))
220 return RTN_BROADCAST;
221 if (is_multicast_ether_addr(skb->data))
222 return RTN_MULTICAST;
223 return RTN_UNSPEC;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100224}
225
Julian Wiedmanncef6ff222017-08-15 17:02:46 +0200226static void qeth_l2_hdr_csum(struct qeth_card *card, struct qeth_hdr *hdr,
227 struct sk_buff *skb)
Thomas Richter4d7def22015-09-18 16:06:51 +0200228{
229 struct iphdr *iph = ip_hdr(skb);
230
231 /* tcph->check contains already the pseudo hdr checksum
232 * so just set the header flags
233 */
234 if (iph->protocol == IPPROTO_UDP)
235 hdr->hdr.l2.flags[1] |= QETH_HDR_EXT_UDP;
236 hdr->hdr.l2.flags[1] |= QETH_HDR_EXT_CSUM_TRANSP_REQ |
237 QETH_HDR_EXT_CSUM_HDR_REQ;
238 iph->check = 0;
239 if (card->options.performance_stats)
240 card->perf_stats.tx_csum++;
241}
242
Julian Wiedmannae79fe02017-08-18 10:19:05 +0200243static void qeth_l2_fill_header(struct qeth_hdr *hdr, struct sk_buff *skb,
244 int cast_type, unsigned int data_len)
Frank Blaschka4a71df52008-02-15 09:19:42 +0100245{
Frank Blaschka683d7182008-08-01 16:39:13 +0200246 struct vlan_ethhdr *veth = (struct vlan_ethhdr *)skb_mac_header(skb);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100247
248 memset(hdr, 0, sizeof(struct qeth_hdr));
249 hdr->hdr.l2.id = QETH_HEADER_TYPE_LAYER2;
Julian Wiedmannae79fe02017-08-18 10:19:05 +0200250 hdr->hdr.l2.pkt_length = data_len;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100251
252 /* set byte byte 3 to casting flags */
253 if (cast_type == RTN_MULTICAST)
254 hdr->hdr.l2.flags[2] |= QETH_LAYER2_FLAG_MULTICAST;
255 else if (cast_type == RTN_BROADCAST)
256 hdr->hdr.l2.flags[2] |= QETH_LAYER2_FLAG_BROADCAST;
257 else
Klaus-Dieter Wackerce73e102009-08-26 02:01:08 +0000258 hdr->hdr.l2.flags[2] |= QETH_LAYER2_FLAG_UNICAST;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100259
Frank Blaschka4a71df52008-02-15 09:19:42 +0100260 /* VSWITCH relies on the VLAN
261 * information to be present in
262 * the QDIO header */
263 if (veth->h_vlan_proto == __constant_htons(ETH_P_8021Q)) {
264 hdr->hdr.l2.flags[2] |= QETH_LAYER2_FLAG_VLAN;
265 hdr->hdr.l2.vlan_id = ntohs(veth->h_vlan_TCI);
266 }
267}
268
Julian Wiedmann2aa48672017-09-18 21:18:20 +0200269static int qeth_setdelvlan_makerc(struct qeth_card *card, int retcode)
Frank Blaschka4a71df52008-02-15 09:19:42 +0100270{
Julian Wiedmann2aa48672017-09-18 21:18:20 +0200271 if (retcode)
272 QETH_CARD_TEXT_(card, 2, "err%04x", retcode);
273
274 switch (retcode) {
275 case IPA_RC_SUCCESS:
276 return 0;
277 case IPA_RC_L2_INVALID_VLAN_ID:
278 return -EINVAL;
279 case IPA_RC_L2_DUP_VLAN_ID:
280 return -EEXIST;
281 case IPA_RC_L2_VLAN_ID_NOT_FOUND:
282 return -ENOENT;
283 case IPA_RC_L2_VLAN_ID_NOT_ALLOWED:
284 return -EPERM;
285 case -ENOMEM:
286 return -ENOMEM;
287 default:
288 return -EIO;
289 }
290}
291
292static int qeth_l2_send_setdelvlan_cb(struct qeth_card *card,
293 struct qeth_reply *reply,
294 unsigned long data)
295{
296 struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100297
Carsten Otte847a50f2010-06-21 22:57:05 +0000298 QETH_CARD_TEXT(card, 2, "L2sdvcb");
Frank Blaschka4a71df52008-02-15 09:19:42 +0100299 if (cmd->hdr.return_code) {
Julian Wiedmann2aa48672017-09-18 21:18:20 +0200300 QETH_DBF_MESSAGE(2, "Error in processing VLAN %i on %s: 0x%x.\n",
301 cmd->data.setdelvlan.vlan_id,
302 QETH_CARD_IFNAME(card), cmd->hdr.return_code);
Carsten Otte847a50f2010-06-21 22:57:05 +0000303 QETH_CARD_TEXT_(card, 2, "L2VL%4x", cmd->hdr.command);
304 QETH_CARD_TEXT_(card, 2, "err%d", cmd->hdr.return_code);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100305 }
306 return 0;
307}
308
309static int qeth_l2_send_setdelvlan(struct qeth_card *card, __u16 i,
Julian Wiedmann2aa48672017-09-18 21:18:20 +0200310 enum qeth_ipa_cmds ipacmd)
Frank Blaschka4a71df52008-02-15 09:19:42 +0100311{
312 struct qeth_ipa_cmd *cmd;
313 struct qeth_cmd_buffer *iob;
314
Carsten Otte847a50f2010-06-21 22:57:05 +0000315 QETH_CARD_TEXT_(card, 4, "L2sdv%x", ipacmd);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100316 iob = qeth_get_ipacmd_buffer(card, ipacmd, QETH_PROT_IPV4);
Thomas Richter1aec42b2015-01-21 13:39:10 +0100317 if (!iob)
318 return -ENOMEM;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100319 cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
320 cmd->data.setdelvlan.vlan_id = i;
Julian Wiedmann2aa48672017-09-18 21:18:20 +0200321 return qeth_setdelvlan_makerc(card, qeth_send_ipa_cmd(card, iob,
322 qeth_l2_send_setdelvlan_cb, NULL));
Frank Blaschka4a71df52008-02-15 09:19:42 +0100323}
324
Ursula Braun70919e22011-02-26 22:41:36 -0800325static void qeth_l2_process_vlans(struct qeth_card *card)
Frank Blaschka4a71df52008-02-15 09:19:42 +0100326{
327 struct qeth_vlan_vid *id;
Carsten Otte847a50f2010-06-21 22:57:05 +0000328 QETH_CARD_TEXT(card, 3, "L2prcvln");
Frank Blaschka4a71df52008-02-15 09:19:42 +0100329 spin_lock_bh(&card->vlanlock);
330 list_for_each_entry(id, &card->vid_list, list) {
Ursula Braun70919e22011-02-26 22:41:36 -0800331 qeth_l2_send_setdelvlan(card, id->vid, IPA_CMD_SETVLAN);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100332 }
333 spin_unlock_bh(&card->vlanlock);
334}
335
Patrick McHardy80d5c362013-04-19 02:04:28 +0000336static int qeth_l2_vlan_rx_add_vid(struct net_device *dev,
337 __be16 proto, u16 vid)
Frank Blaschka4a71df52008-02-15 09:19:42 +0100338{
Heiko Carstens509e2562008-07-26 02:24:10 -0700339 struct qeth_card *card = dev->ml_priv;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100340 struct qeth_vlan_vid *id;
Thomas Richter1aec42b2015-01-21 13:39:10 +0100341 int rc;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100342
Carsten Otte847a50f2010-06-21 22:57:05 +0000343 QETH_CARD_TEXT_(card, 4, "aid:%d", vid);
Ursula Braun10651db2010-10-01 02:51:13 +0000344 if (!vid)
Jiri Pirko8e586132011-12-08 19:52:37 -0500345 return 0;
Ursula Braun8e98ac42009-03-24 20:57:18 +0000346 if (qeth_wait_for_threads(card, QETH_RECOVER_THREAD)) {
Carsten Otte847a50f2010-06-21 22:57:05 +0000347 QETH_CARD_TEXT(card, 3, "aidREC");
Jiri Pirko8e586132011-12-08 19:52:37 -0500348 return 0;
Ursula Braun8e98ac42009-03-24 20:57:18 +0000349 }
Frank Blaschka4a71df52008-02-15 09:19:42 +0100350 id = kmalloc(sizeof(struct qeth_vlan_vid), GFP_ATOMIC);
351 if (id) {
352 id->vid = vid;
Thomas Richter1aec42b2015-01-21 13:39:10 +0100353 rc = qeth_l2_send_setdelvlan(card, vid, IPA_CMD_SETVLAN);
354 if (rc) {
355 kfree(id);
356 return rc;
357 }
Frank Blaschka4a71df52008-02-15 09:19:42 +0100358 spin_lock_bh(&card->vlanlock);
359 list_add_tail(&id->list, &card->vid_list);
360 spin_unlock_bh(&card->vlanlock);
Jiri Pirko8e586132011-12-08 19:52:37 -0500361 } else {
362 return -ENOMEM;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100363 }
Jiri Pirko8e586132011-12-08 19:52:37 -0500364 return 0;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100365}
366
Patrick McHardy80d5c362013-04-19 02:04:28 +0000367static int qeth_l2_vlan_rx_kill_vid(struct net_device *dev,
368 __be16 proto, u16 vid)
Frank Blaschka4a71df52008-02-15 09:19:42 +0100369{
370 struct qeth_vlan_vid *id, *tmpid = NULL;
Heiko Carstens509e2562008-07-26 02:24:10 -0700371 struct qeth_card *card = dev->ml_priv;
Thomas Richter1aec42b2015-01-21 13:39:10 +0100372 int rc = 0;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100373
Carsten Otte847a50f2010-06-21 22:57:05 +0000374 QETH_CARD_TEXT_(card, 4, "kid:%d", vid);
Ursula Braun8e98ac42009-03-24 20:57:18 +0000375 if (qeth_wait_for_threads(card, QETH_RECOVER_THREAD)) {
Carsten Otte847a50f2010-06-21 22:57:05 +0000376 QETH_CARD_TEXT(card, 3, "kidREC");
Jiri Pirko8e586132011-12-08 19:52:37 -0500377 return 0;
Ursula Braun8e98ac42009-03-24 20:57:18 +0000378 }
Frank Blaschka4a71df52008-02-15 09:19:42 +0100379 spin_lock_bh(&card->vlanlock);
380 list_for_each_entry(id, &card->vid_list, list) {
381 if (id->vid == vid) {
382 list_del(&id->list);
383 tmpid = id;
384 break;
385 }
386 }
387 spin_unlock_bh(&card->vlanlock);
388 if (tmpid) {
Thomas Richter1aec42b2015-01-21 13:39:10 +0100389 rc = qeth_l2_send_setdelvlan(card, vid, IPA_CMD_DELVLAN);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100390 kfree(tmpid);
391 }
Lakhvich Dmitriyfe5c8022015-10-06 15:12:28 +0200392 qeth_l2_set_rx_mode(card->dev);
Thomas Richter1aec42b2015-01-21 13:39:10 +0100393 return rc;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100394}
395
Peter Senna Tschudinb2f4de82015-08-04 17:11:47 +0200396static void qeth_l2_stop_card(struct qeth_card *card, int recovery_mode)
Frank Blaschka4a71df52008-02-15 09:19:42 +0100397{
Peter Tiedemannd11ba0c2008-04-01 10:26:58 +0200398 QETH_DBF_TEXT(SETUP , 2, "stopcard");
399 QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *));
Frank Blaschka4a71df52008-02-15 09:19:42 +0100400
401 qeth_set_allowed_threads(card, 0, 1);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100402 if (card->read.state == CH_STATE_UP &&
403 card->write.state == CH_STATE_UP &&
404 (card->state == CARD_STATE_UP)) {
405 if (recovery_mode &&
406 card->info.type != QETH_CARD_TYPE_OSN) {
407 qeth_l2_stop(card->dev);
408 } else {
409 rtnl_lock();
410 dev_close(card->dev);
411 rtnl_unlock();
412 }
Ursula Braun70919e22011-02-26 22:41:36 -0800413 card->info.mac_bits &= ~QETH_LAYER2_MAC_REGISTERED;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100414 card->state = CARD_STATE_SOFTSETUP;
415 }
416 if (card->state == CARD_STATE_SOFTSETUP) {
Julian Wiedmannc07cbf22017-01-12 15:48:37 +0100417 qeth_l2_del_all_macs(card);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100418 qeth_clear_ipacmd_list(card);
419 card->state = CARD_STATE_HARDSETUP;
420 }
421 if (card->state == CARD_STATE_HARDSETUP) {
422 qeth_qdio_clear_card(card, 0);
423 qeth_clear_qdio_buffers(card);
424 qeth_clear_working_pool_list(card);
425 card->state = CARD_STATE_DOWN;
426 }
427 if (card->state == CARD_STATE_DOWN) {
428 qeth_clear_cmd_buffers(&card->read);
429 qeth_clear_cmd_buffers(&card->write);
430 }
Frank Blaschka4a71df52008-02-15 09:19:42 +0100431}
432
Frank Blaschkaa1c3ed42010-09-07 21:14:42 +0000433static int qeth_l2_process_inbound_buffer(struct qeth_card *card,
434 int budget, int *done)
Frank Blaschka4a71df52008-02-15 09:19:42 +0100435{
Frank Blaschkaa1c3ed42010-09-07 21:14:42 +0000436 int work_done = 0;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100437 struct sk_buff *skb;
438 struct qeth_hdr *hdr;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100439 unsigned int len;
440
Frank Blaschkaa1c3ed42010-09-07 21:14:42 +0000441 *done = 0;
Stefan Raspl18af5c12012-11-19 02:46:50 +0000442 WARN_ON_ONCE(!budget);
Frank Blaschkaa1c3ed42010-09-07 21:14:42 +0000443 while (budget) {
444 skb = qeth_core_get_next_skb(card,
Frank Blaschkab3332932011-08-08 01:33:59 +0000445 &card->qdio.in_q->bufs[card->rx.b_index],
Frank Blaschkaa1c3ed42010-09-07 21:14:42 +0000446 &card->rx.b_element, &card->rx.e_offset, &hdr);
447 if (!skb) {
448 *done = 1;
449 break;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100450 }
Frank Blaschkaa1c3ed42010-09-07 21:14:42 +0000451 skb->dev = card->dev;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100452 switch (hdr->hdr.l2.id) {
453 case QETH_HEADER_TYPE_LAYER2:
454 skb->pkt_type = PACKET_HOST;
455 skb->protocol = eth_type_trans(skb, skb->dev);
Thomas Richter4d7def22015-09-18 16:06:51 +0200456 if ((card->dev->features & NETIF_F_RXCSUM)
457 && ((hdr->hdr.l2.flags[1] &
458 (QETH_HDR_EXT_CSUM_HDR_REQ |
459 QETH_HDR_EXT_CSUM_TRANSP_REQ)) ==
460 (QETH_HDR_EXT_CSUM_HDR_REQ |
461 QETH_HDR_EXT_CSUM_TRANSP_REQ)))
462 skb->ip_summed = CHECKSUM_UNNECESSARY;
463 else
464 skb->ip_summed = CHECKSUM_NONE;
Ursula Braun12883722008-04-01 10:26:56 +0200465 if (skb->protocol == htons(ETH_P_802_2))
466 *((__u32 *)skb->cb) = ++card->seqno.pkt_seqno;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100467 len = skb->len;
Thomas Richter9abfa8c2015-10-06 15:12:27 +0200468 napi_gro_receive(&card->napi, skb);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100469 break;
470 case QETH_HEADER_TYPE_OSN:
Ursula Braun2d488c22008-10-24 11:16:55 +0200471 if (card->info.type == QETH_CARD_TYPE_OSN) {
472 skb_push(skb, sizeof(struct qeth_hdr));
473 skb_copy_to_linear_data(skb, hdr,
Frank Blaschka4a71df52008-02-15 09:19:42 +0100474 sizeof(struct qeth_hdr));
Ursula Braun2d488c22008-10-24 11:16:55 +0200475 len = skb->len;
476 card->osn_info.data_cb(skb);
477 break;
478 }
479 /* else unknown */
Frank Blaschka4a71df52008-02-15 09:19:42 +0100480 default:
481 dev_kfree_skb_any(skb);
Carsten Otte847a50f2010-06-21 22:57:05 +0000482 QETH_CARD_TEXT(card, 3, "inbunkno");
Peter Tiedemannd11ba0c2008-04-01 10:26:58 +0200483 QETH_DBF_HEX(CTRL, 3, hdr, QETH_DBF_CTRL_LEN);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100484 continue;
485 }
Frank Blaschkaa1c3ed42010-09-07 21:14:42 +0000486 work_done++;
487 budget--;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100488 card->stats.rx_packets++;
489 card->stats.rx_bytes += len;
490 }
Frank Blaschkaa1c3ed42010-09-07 21:14:42 +0000491 return work_done;
492}
493
Frank Blaschka4a71df52008-02-15 09:19:42 +0100494static int qeth_l2_request_initial_mac(struct qeth_card *card)
495{
496 int rc = 0;
497 char vendor_pre[] = {0x02, 0x00, 0x00};
498
Julian Wiedmannec61bd22017-06-20 16:00:34 +0200499 QETH_DBF_TEXT(SETUP, 2, "l2reqmac");
Peter Tiedemannd11ba0c2008-04-01 10:26:58 +0200500 QETH_DBF_TEXT_(SETUP, 2, "doL2%s", CARD_BUS_ID(card));
Frank Blaschka4a71df52008-02-15 09:19:42 +0100501
Julian Wiedmannec61bd22017-06-20 16:00:34 +0200502 if (MACHINE_IS_VM) {
503 rc = qeth_vm_request_mac(card);
504 if (!rc)
505 goto out;
506 QETH_DBF_MESSAGE(2, "z/VM MAC Service failed on device %s: x%x\n",
507 CARD_BUS_ID(card), rc);
508 QETH_DBF_TEXT_(SETUP, 2, "err%04x", rc);
509 /* fall back to alternative mechanism: */
510 }
511
Ursula Braun5113fec2010-05-16 21:15:14 +0000512 if (card->info.type == QETH_CARD_TYPE_IQD ||
513 card->info.type == QETH_CARD_TYPE_OSM ||
514 card->info.type == QETH_CARD_TYPE_OSX ||
515 card->info.guestlan) {
Frank Blaschka4a71df52008-02-15 09:19:42 +0100516 rc = qeth_setadpparms_change_macaddr(card);
517 if (rc) {
Frank Blaschka14cc21b2008-06-06 12:37:46 +0200518 QETH_DBF_MESSAGE(2, "couldn't get MAC address on "
519 "device %s: x%x\n", CARD_BUS_ID(card), rc);
Thomas Richter1aec42b2015-01-21 13:39:10 +0100520 QETH_DBF_TEXT_(SETUP, 2, "1err%04x", rc);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100521 return rc;
522 }
Frank Blaschka4a71df52008-02-15 09:19:42 +0100523 } else {
Joe Perches18336112012-07-12 22:33:10 -0700524 eth_random_addr(card->dev->dev_addr);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100525 memcpy(card->dev->dev_addr, vendor_pre, 3);
526 }
Julian Wiedmannec61bd22017-06-20 16:00:34 +0200527out:
528 QETH_DBF_HEX(SETUP, 2, card->dev->dev_addr, card->dev->addr_len);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100529 return 0;
530}
531
532static int qeth_l2_set_mac_address(struct net_device *dev, void *p)
533{
534 struct sockaddr *addr = p;
Heiko Carstens509e2562008-07-26 02:24:10 -0700535 struct qeth_card *card = dev->ml_priv;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100536 int rc = 0;
537
Carsten Otte847a50f2010-06-21 22:57:05 +0000538 QETH_CARD_TEXT(card, 3, "setmac");
Frank Blaschka4a71df52008-02-15 09:19:42 +0100539
Ursula Braun5113fec2010-05-16 21:15:14 +0000540 if (card->info.type == QETH_CARD_TYPE_OSN ||
541 card->info.type == QETH_CARD_TYPE_OSM ||
542 card->info.type == QETH_CARD_TYPE_OSX) {
Carsten Otte847a50f2010-06-21 22:57:05 +0000543 QETH_CARD_TEXT(card, 3, "setmcTYP");
Frank Blaschka4a71df52008-02-15 09:19:42 +0100544 return -EOPNOTSUPP;
545 }
Carsten Otte847a50f2010-06-21 22:57:05 +0000546 QETH_CARD_HEX(card, 3, addr->sa_data, OSA_ADDR_LEN);
Ursula Braun8e98ac42009-03-24 20:57:18 +0000547 if (qeth_wait_for_threads(card, QETH_RECOVER_THREAD)) {
Carsten Otte847a50f2010-06-21 22:57:05 +0000548 QETH_CARD_TEXT(card, 3, "setmcREC");
Ursula Braun8e98ac42009-03-24 20:57:18 +0000549 return -ERESTARTSYS;
550 }
Frank Blaschka4a71df52008-02-15 09:19:42 +0100551 rc = qeth_l2_send_delmac(card, &card->dev->dev_addr[0]);
Eugene Crosserefbbc1d2015-01-21 13:39:09 +0100552 if (!rc || (rc == -ENOENT))
Frank Blaschka4a71df52008-02-15 09:19:42 +0100553 rc = qeth_l2_send_setmac(card, addr->sa_data);
Ursula Braune0a81142012-03-07 02:06:28 +0000554 return rc ? -EINVAL : 0;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100555}
556
Eugene Crosser0db587b2015-05-18 14:27:55 +0200557static void qeth_promisc_to_bridge(struct qeth_card *card)
558{
559 struct net_device *dev = card->dev;
560 enum qeth_ipa_promisc_modes promisc_mode;
561 int role;
562 int rc;
563
564 QETH_CARD_TEXT(card, 3, "pmisc2br");
565
566 if (!card->options.sbp.reflect_promisc)
567 return;
568 promisc_mode = (dev->flags & IFF_PROMISC) ? SET_PROMISC_MODE_ON
569 : SET_PROMISC_MODE_OFF;
570 if (promisc_mode == card->info.promisc_mode)
571 return;
572
573 if (promisc_mode == SET_PROMISC_MODE_ON) {
574 if (card->options.sbp.reflect_promisc_primary)
575 role = QETH_SBP_ROLE_PRIMARY;
576 else
577 role = QETH_SBP_ROLE_SECONDARY;
578 } else
579 role = QETH_SBP_ROLE_NONE;
580
581 rc = qeth_bridgeport_setrole(card, role);
582 QETH_DBF_TEXT_(SETUP, 2, "bpm%c%04x",
583 (promisc_mode == SET_PROMISC_MODE_ON) ? '+' : '-', rc);
584 if (!rc) {
585 card->options.sbp.role = role;
586 card->info.promisc_mode = promisc_mode;
587 }
Lakhvich Dmitriyfe5c8022015-10-06 15:12:28 +0200588
589}
590/* New MAC address is added to the hash table and marked to be written on card
591 * only if there is not in the hash table storage already
592 *
593*/
Julian Wiedmann4641b022017-12-20 20:10:59 +0100594static void qeth_l2_add_mac(struct qeth_card *card, struct netdev_hw_addr *ha)
Lakhvich Dmitriyfe5c8022015-10-06 15:12:28 +0200595{
Julian Wiedmanncef6ff222017-08-15 17:02:46 +0200596 u32 mac_hash = get_unaligned((u32 *)(&ha->addr[2]));
Lakhvich Dmitriyfe5c8022015-10-06 15:12:28 +0200597 struct qeth_mac *mac;
598
Julian Wiedmanncef6ff222017-08-15 17:02:46 +0200599 hash_for_each_possible(card->mac_htable, mac, hnode, mac_hash) {
Julian Wiedmann4641b022017-12-20 20:10:59 +0100600 if (!memcmp(ha->addr, mac->mac_addr, OSA_ADDR_LEN)) {
Lakhvich Dmitriy5f78e292016-06-16 16:18:58 +0200601 mac->disp_flag = QETH_DISP_ADDR_DO_NOTHING;
Lakhvich Dmitriyfe5c8022015-10-06 15:12:28 +0200602 return;
603 }
604 }
605
606 mac = kzalloc(sizeof(struct qeth_mac), GFP_ATOMIC);
Lakhvich Dmitriyfe5c8022015-10-06 15:12:28 +0200607 if (!mac)
608 return;
609
610 memcpy(mac->mac_addr, ha->addr, OSA_ADDR_LEN);
Lakhvich Dmitriy5f78e292016-06-16 16:18:58 +0200611 mac->disp_flag = QETH_DISP_ADDR_ADD;
Lakhvich Dmitriyfe5c8022015-10-06 15:12:28 +0200612
Julian Wiedmanncef6ff222017-08-15 17:02:46 +0200613 hash_add(card->mac_htable, &mac->hnode, mac_hash);
Eugene Crosser0db587b2015-05-18 14:27:55 +0200614}
615
Lakhvich Dmitriyfe5c8022015-10-06 15:12:28 +0200616static void qeth_l2_set_rx_mode(struct net_device *dev)
Frank Blaschka4a71df52008-02-15 09:19:42 +0100617{
Heiko Carstens509e2562008-07-26 02:24:10 -0700618 struct qeth_card *card = dev->ml_priv;
Jiri Pirkoccffad252009-05-22 23:22:17 +0000619 struct netdev_hw_addr *ha;
Lakhvich Dmitriyfe5c8022015-10-06 15:12:28 +0200620 struct qeth_mac *mac;
621 struct hlist_node *tmp;
622 int i;
623 int rc;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100624
625 if (card->info.type == QETH_CARD_TYPE_OSN)
Lakhvich Dmitriyfe5c8022015-10-06 15:12:28 +0200626 return;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100627
Carsten Otte847a50f2010-06-21 22:57:05 +0000628 QETH_CARD_TEXT(card, 3, "setmulti");
Ursula Braun8e98ac42009-03-24 20:57:18 +0000629 if (qeth_threads_running(card, QETH_RECOVER_THREAD) &&
630 (card->state != CARD_STATE_UP))
631 return;
Lakhvich Dmitriyfe5c8022015-10-06 15:12:28 +0200632
Frank Blaschka4a71df52008-02-15 09:19:42 +0100633 spin_lock_bh(&card->mclock);
Lakhvich Dmitriyfe5c8022015-10-06 15:12:28 +0200634
Jiri Pirko22bedad32010-04-01 21:22:57 +0000635 netdev_for_each_mc_addr(ha, dev)
Julian Wiedmann4641b022017-12-20 20:10:59 +0100636 qeth_l2_add_mac(card, ha);
Jiri Pirko32e7bfc2010-01-25 13:36:10 -0800637 netdev_for_each_uc_addr(ha, dev)
Julian Wiedmann4641b022017-12-20 20:10:59 +0100638 qeth_l2_add_mac(card, ha);
Lakhvich Dmitriyfe5c8022015-10-06 15:12:28 +0200639
640 hash_for_each_safe(card->mac_htable, i, tmp, mac, hnode) {
Lakhvich Dmitriy5f78e292016-06-16 16:18:58 +0200641 if (mac->disp_flag == QETH_DISP_ADDR_DELETE) {
Julian Wiedmann979d7922017-01-12 15:48:40 +0100642 qeth_l2_remove_mac(card, mac);
Lakhvich Dmitriyfe5c8022015-10-06 15:12:28 +0200643 hash_del(&mac->hnode);
644 kfree(mac);
645
Lakhvich Dmitriy5f78e292016-06-16 16:18:58 +0200646 } else if (mac->disp_flag == QETH_DISP_ADDR_ADD) {
Lakhvich Dmitriyfe5c8022015-10-06 15:12:28 +0200647 rc = qeth_l2_write_mac(card, mac);
648 if (rc) {
649 hash_del(&mac->hnode);
650 kfree(mac);
651 } else
Lakhvich Dmitriy5f78e292016-06-16 16:18:58 +0200652 mac->disp_flag = QETH_DISP_ADDR_DELETE;
Lakhvich Dmitriyfe5c8022015-10-06 15:12:28 +0200653 } else
Lakhvich Dmitriy5f78e292016-06-16 16:18:58 +0200654 mac->disp_flag = QETH_DISP_ADDR_DELETE;
Lakhvich Dmitriyfe5c8022015-10-06 15:12:28 +0200655 }
Frank Blaschka7db22662008-08-15 08:02:59 +0200656
Frank Blaschka4a71df52008-02-15 09:19:42 +0100657 spin_unlock_bh(&card->mclock);
Lakhvich Dmitriyfe5c8022015-10-06 15:12:28 +0200658
Eugene Crosser0db587b2015-05-18 14:27:55 +0200659 if (qeth_adp_supported(card, IPA_SETADP_SET_PROMISC_MODE))
660 qeth_setadp_promisc_mode(card);
661 else
662 qeth_promisc_to_bridge(card);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100663}
664
Julian Wiedmann72863842017-08-18 10:19:04 +0200665static int qeth_l2_xmit_iqd(struct qeth_card *card, struct sk_buff *skb,
666 struct qeth_qdio_out_q *queue, int cast_type)
667{
668 unsigned int data_offset = ETH_HLEN;
669 struct qeth_hdr *hdr;
670 int rc;
671
672 hdr = kmem_cache_alloc(qeth_core_header_cache, GFP_ATOMIC);
673 if (!hdr)
674 return -ENOMEM;
Julian Wiedmannae79fe02017-08-18 10:19:05 +0200675 qeth_l2_fill_header(hdr, skb, cast_type, skb->len);
Julian Wiedmann72863842017-08-18 10:19:04 +0200676 skb_copy_from_linear_data(skb, ((char *)hdr) + sizeof(*hdr),
677 data_offset);
678
679 if (!qeth_get_elements_no(card, skb, 1, data_offset)) {
680 rc = -E2BIG;
681 goto out;
682 }
Julian Wiedmann7c2e9ba2017-09-18 21:18:18 +0200683 rc = qeth_do_send_packet_fast(queue, skb, hdr, data_offset,
Julian Wiedmannf1588172017-08-18 10:19:08 +0200684 sizeof(*hdr) + data_offset);
Julian Wiedmann72863842017-08-18 10:19:04 +0200685out:
686 if (rc)
687 kmem_cache_free(qeth_core_header_cache, hdr);
688 return rc;
689}
690
691static int qeth_l2_xmit_osa(struct qeth_card *card, struct sk_buff *skb,
692 struct qeth_qdio_out_q *queue, int cast_type)
693{
Julian Wiedmann0d6f02d2017-08-18 10:19:10 +0200694 int push_len = sizeof(struct qeth_hdr);
Julian Wiedmann72863842017-08-18 10:19:04 +0200695 unsigned int elements, nr_frags;
Julian Wiedmann0d6f02d2017-08-18 10:19:10 +0200696 unsigned int hdr_elements = 0;
697 struct qeth_hdr *hdr = NULL;
698 unsigned int hd_len = 0;
Julian Wiedmann72863842017-08-18 10:19:04 +0200699 int rc;
700
701 /* fix hardware limitation: as long as we do not have sbal
702 * chaining we can not send long frag lists
703 */
704 if (!qeth_get_elements_no(card, skb, 0, 0)) {
705 rc = skb_linearize(skb);
706
707 if (card->options.performance_stats) {
708 if (rc)
709 card->perf_stats.tx_linfail++;
710 else
711 card->perf_stats.tx_lin++;
712 }
713 if (rc)
714 return rc;
715 }
716 nr_frags = skb_shinfo(skb)->nr_frags;
717
Julian Wiedmann0d6f02d2017-08-18 10:19:10 +0200718 rc = skb_cow_head(skb, push_len);
719 if (rc)
720 return rc;
721 push_len = qeth_push_hdr(skb, &hdr, push_len);
722 if (push_len < 0)
723 return push_len;
724 if (!push_len) {
725 /* hdr was allocated from cache */
726 hd_len = sizeof(*hdr);
727 hdr_elements = 1;
728 }
729 qeth_l2_fill_header(hdr, skb, cast_type, skb->len - push_len);
730 if (skb->ip_summed == CHECKSUM_PARTIAL)
731 qeth_l2_hdr_csum(card, hdr, skb);
Julian Wiedmann72863842017-08-18 10:19:04 +0200732
Julian Wiedmann0d6f02d2017-08-18 10:19:10 +0200733 elements = qeth_get_elements_no(card, skb, hdr_elements, 0);
Julian Wiedmann72863842017-08-18 10:19:04 +0200734 if (!elements) {
735 rc = -E2BIG;
736 goto out;
737 }
Julian Wiedmann0d6f02d2017-08-18 10:19:10 +0200738 elements += hdr_elements;
739
740 /* TODO: remove the skb_orphan() once TX completion is fast enough */
741 skb_orphan(skb);
742 rc = qeth_do_send_packet(card, queue, skb, hdr, 0, hd_len, elements);
Julian Wiedmann72863842017-08-18 10:19:04 +0200743out:
744 if (!rc) {
Julian Wiedmann72863842017-08-18 10:19:04 +0200745 if (card->options.performance_stats && nr_frags) {
746 card->perf_stats.sg_skbs_sent++;
747 /* nr_frags + skb->data */
748 card->perf_stats.sg_frags_sent += nr_frags + 1;
749 }
750 } else {
Julian Wiedmann0d6f02d2017-08-18 10:19:10 +0200751 if (hd_len)
752 kmem_cache_free(qeth_core_header_cache, hdr);
753 if (rc == -EBUSY)
754 /* roll back to ETH header */
755 skb_pull(skb, push_len);
Julian Wiedmann72863842017-08-18 10:19:04 +0200756 }
757 return rc;
758}
759
760static int qeth_l2_xmit_osn(struct qeth_card *card, struct sk_buff *skb,
761 struct qeth_qdio_out_q *queue)
762{
763 unsigned int elements;
764 struct qeth_hdr *hdr;
765
766 if (skb->protocol == htons(ETH_P_IPV6))
767 return -EPROTONOSUPPORT;
768
769 hdr = (struct qeth_hdr *)skb->data;
770 elements = qeth_get_elements_no(card, skb, 0, 0);
771 if (!elements)
772 return -E2BIG;
773 if (qeth_hdr_chk_and_bounce(skb, &hdr, sizeof(*hdr)))
774 return -EINVAL;
Julian Wiedmann9c3bfda2017-08-18 10:19:07 +0200775 return qeth_do_send_packet(card, queue, skb, hdr, 0, 0, elements);
Julian Wiedmann72863842017-08-18 10:19:04 +0200776}
777
Julian Wiedmanne38db6b2017-04-11 16:11:14 +0200778static netdev_tx_t qeth_l2_hard_start_xmit(struct sk_buff *skb,
779 struct net_device *dev)
Frank Blaschka4a71df52008-02-15 09:19:42 +0100780{
Heiko Carstens509e2562008-07-26 02:24:10 -0700781 struct qeth_card *card = dev->ml_priv;
Klaus-Dieter Wackerce73e102009-08-26 02:01:08 +0000782 int cast_type = qeth_l2_get_cast_type(card, skb);
Stefan Raspl290b8342014-04-28 10:05:08 +0200783 struct qeth_qdio_out_q *queue;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100784 int tx_bytes = skb->len;
Julian Wiedmann72863842017-08-18 10:19:04 +0200785 int rc;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100786
Stefan Raspl290b8342014-04-28 10:05:08 +0200787 if (card->qdio.do_prio_queueing || (cast_type &&
788 card->info.is_multicast_different))
789 queue = card->qdio.out_qs[qeth_get_priority_queue(card, skb,
790 qeth_get_ip_version(skb), cast_type)];
791 else
792 queue = card->qdio.out_qs[card->qdio.default_out_queue];
793
Frank Blaschka4a71df52008-02-15 09:19:42 +0100794 if ((card->state != CARD_STATE_UP) || !card->lan_online) {
795 card->stats.tx_carrier_errors++;
796 goto tx_drop;
797 }
798
Frank Blaschka4a71df52008-02-15 09:19:42 +0100799 if (card->options.performance_stats) {
800 card->perf_stats.outbound_cnt++;
801 card->perf_stats.outbound_start_time = qeth_get_micros();
802 }
803 netif_stop_queue(dev);
804
Julian Wiedmann72863842017-08-18 10:19:04 +0200805 switch (card->info.type) {
806 case QETH_CARD_TYPE_OSN:
807 rc = qeth_l2_xmit_osn(card, skb, queue);
808 break;
809 case QETH_CARD_TYPE_IQD:
810 rc = qeth_l2_xmit_iqd(card, skb, queue, cast_type);
811 break;
812 default:
813 rc = qeth_l2_xmit_osa(card, skb, queue, cast_type);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100814 }
815
Frank Blaschka4a71df52008-02-15 09:19:42 +0100816 if (!rc) {
817 card->stats.tx_packets++;
818 card->stats.tx_bytes += tx_bytes;
Julian Wiedmann72863842017-08-18 10:19:04 +0200819 if (card->options.performance_stats)
820 card->perf_stats.outbound_time += qeth_get_micros() -
821 card->perf_stats.outbound_start_time;
822 netif_wake_queue(dev);
823 return NETDEV_TX_OK;
824 } else if (rc == -EBUSY) {
825 return NETDEV_TX_BUSY;
826 } /* else fall through */
Frank Blaschka4a71df52008-02-15 09:19:42 +0100827
828tx_drop:
829 card->stats.tx_dropped++;
830 card->stats.tx_errors++;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100831 dev_kfree_skb_any(skb);
Frank Blaschkad0ec0f52008-06-06 12:37:48 +0200832 netif_wake_queue(dev);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100833 return NETDEV_TX_OK;
834}
835
Ursula Braun39423442011-01-12 20:42:24 +0000836static int __qeth_l2_open(struct net_device *dev)
Frank Blaschka4a71df52008-02-15 09:19:42 +0100837{
Heiko Carstens509e2562008-07-26 02:24:10 -0700838 struct qeth_card *card = dev->ml_priv;
Frank Blaschkaa1c3ed42010-09-07 21:14:42 +0000839 int rc = 0;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100840
Carsten Otte847a50f2010-06-21 22:57:05 +0000841 QETH_CARD_TEXT(card, 4, "qethopen");
Ursula Braun39423442011-01-12 20:42:24 +0000842 if (card->state == CARD_STATE_UP)
843 return rc;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100844 if (card->state != CARD_STATE_SOFTSETUP)
845 return -ENODEV;
846
847 if ((card->info.type != QETH_CARD_TYPE_OSN) &&
848 (!(card->info.mac_bits & QETH_LAYER2_MAC_REGISTERED))) {
Carsten Otte847a50f2010-06-21 22:57:05 +0000849 QETH_CARD_TEXT(card, 4, "nomacadr");
Frank Blaschka4a71df52008-02-15 09:19:42 +0100850 return -EPERM;
851 }
852 card->data.state = CH_STATE_UP;
853 card->state = CARD_STATE_UP;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100854 netif_start_queue(dev);
855
Frank Blaschkaa1c3ed42010-09-07 21:14:42 +0000856 if (qdio_stop_irq(card->data.ccwdev, 0) >= 0) {
857 napi_enable(&card->napi);
858 napi_schedule(&card->napi);
859 } else
860 rc = -EIO;
861 return rc;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100862}
863
Ursula Braun39423442011-01-12 20:42:24 +0000864static int qeth_l2_open(struct net_device *dev)
865{
866 struct qeth_card *card = dev->ml_priv;
867
868 QETH_CARD_TEXT(card, 5, "qethope_");
869 if (qeth_wait_for_threads(card, QETH_RECOVER_THREAD)) {
870 QETH_CARD_TEXT(card, 3, "openREC");
871 return -ERESTARTSYS;
872 }
873 return __qeth_l2_open(dev);
874}
875
Frank Blaschka4a71df52008-02-15 09:19:42 +0100876static int qeth_l2_stop(struct net_device *dev)
877{
Heiko Carstens509e2562008-07-26 02:24:10 -0700878 struct qeth_card *card = dev->ml_priv;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100879
Carsten Otte847a50f2010-06-21 22:57:05 +0000880 QETH_CARD_TEXT(card, 4, "qethstop");
Frank Blaschka4a71df52008-02-15 09:19:42 +0100881 netif_tx_disable(dev);
Frank Blaschkaa1c3ed42010-09-07 21:14:42 +0000882 if (card->state == CARD_STATE_UP) {
Frank Blaschka4a71df52008-02-15 09:19:42 +0100883 card->state = CARD_STATE_SOFTSETUP;
Frank Blaschkaa1c3ed42010-09-07 21:14:42 +0000884 napi_disable(&card->napi);
885 }
Frank Blaschka4a71df52008-02-15 09:19:42 +0100886 return 0;
887}
888
Julian Wiedmann2d2ebb32017-05-10 19:07:52 +0200889static const struct device_type qeth_l2_devtype = {
890 .name = "qeth_layer2",
891 .groups = qeth_l2_attr_groups,
892};
893
Frank Blaschka4a71df52008-02-15 09:19:42 +0100894static int qeth_l2_probe_device(struct ccwgroup_device *gdev)
895{
896 struct qeth_card *card = dev_get_drvdata(&gdev->dev);
Ursula Braun9111e782017-05-10 19:07:51 +0200897 int rc;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100898
Julian Wiedmann2d2ebb32017-05-10 19:07:52 +0200899 if (gdev->dev.type == &qeth_generic_devtype) {
900 rc = qeth_l2_create_device_attributes(&gdev->dev);
901 if (rc)
902 return rc;
903 }
Frank Blaschka4a71df52008-02-15 09:19:42 +0100904 INIT_LIST_HEAD(&card->vid_list);
Lakhvich Dmitriyfe5c8022015-10-06 15:12:28 +0200905 hash_init(card->mac_htable);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100906 card->options.layer2 = 1;
Frank Blaschka1da74b12011-05-12 18:45:02 +0000907 card->info.hwtrap = 0;
Hans Wippelcaa1f0b2017-09-18 21:18:15 +0200908 qeth_l2_vnicc_set_defaults(card);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100909 return 0;
910}
911
912static void qeth_l2_remove_device(struct ccwgroup_device *cgdev)
913{
914 struct qeth_card *card = dev_get_drvdata(&cgdev->dev);
915
Julian Wiedmann2d2ebb32017-05-10 19:07:52 +0200916 if (cgdev->dev.type == &qeth_generic_devtype)
917 qeth_l2_remove_device_attributes(&cgdev->dev);
Ursula Braunf2148562009-05-19 21:38:37 +0000918 qeth_set_allowed_threads(card, 0, 1);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100919 wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0);
920
Ursula Braun70919e22011-02-26 22:41:36 -0800921 if (cgdev->state == CCWGROUP_ONLINE)
Frank Blaschka4a71df52008-02-15 09:19:42 +0100922 qeth_l2_set_offline(cgdev);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100923
924 if (card->dev) {
Ursula Braun7831b4f2016-07-04 14:07:16 +0200925 netif_napi_del(&card->napi);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100926 unregister_netdev(card->dev);
927 card->dev = NULL;
928 }
Frank Blaschka4a71df52008-02-15 09:19:42 +0100929 return;
930}
931
Stephen Hemminger0fc0b732009-09-02 01:03:33 -0700932static const struct ethtool_ops qeth_l2_ethtool_ops = {
Frank Blaschka4a71df52008-02-15 09:19:42 +0100933 .get_link = ethtool_op_get_link,
Frank Blaschka4a71df52008-02-15 09:19:42 +0100934 .get_strings = qeth_core_get_strings,
935 .get_ethtool_stats = qeth_core_get_ethtool_stats,
Ben Hutchingsdf8b4ec2009-10-01 11:24:32 +0000936 .get_sset_count = qeth_core_get_sset_count,
Frank Blaschka4a71df52008-02-15 09:19:42 +0100937 .get_drvinfo = qeth_core_get_drvinfo,
Julian Wiedmann993e19c2017-04-11 16:11:17 +0200938 .get_link_ksettings = qeth_core_ethtool_get_link_ksettings,
Frank Blaschka4a71df52008-02-15 09:19:42 +0100939};
940
Stephen Hemminger0fc0b732009-09-02 01:03:33 -0700941static const struct ethtool_ops qeth_l2_osn_ops = {
Frank Blaschka4a71df52008-02-15 09:19:42 +0100942 .get_strings = qeth_core_get_strings,
943 .get_ethtool_stats = qeth_core_get_ethtool_stats,
Ben Hutchingsdf8b4ec2009-10-01 11:24:32 +0000944 .get_sset_count = qeth_core_get_sset_count,
Frank Blaschka4a71df52008-02-15 09:19:42 +0100945 .get_drvinfo = qeth_core_get_drvinfo,
946};
947
Frank Blaschka3d58cef2009-01-09 03:44:00 +0000948static const struct net_device_ops qeth_l2_netdev_ops = {
Frank Blaschka8403b132009-01-08 10:50:55 -0800949 .ndo_open = qeth_l2_open,
950 .ndo_stop = qeth_l2_stop,
951 .ndo_get_stats = qeth_get_stats,
952 .ndo_start_xmit = qeth_l2_hard_start_xmit,
Julian Wiedmann6d69b1f2017-12-01 10:14:50 +0100953 .ndo_features_check = qeth_features_check,
Frank Blaschka8403b132009-01-08 10:50:55 -0800954 .ndo_validate_addr = eth_validate_addr,
Lakhvich Dmitriyfe5c8022015-10-06 15:12:28 +0200955 .ndo_set_rx_mode = qeth_l2_set_rx_mode,
Julian Wiedmann942d6982017-04-11 16:11:10 +0200956 .ndo_do_ioctl = qeth_do_ioctl,
Frank Blaschka8403b132009-01-08 10:50:55 -0800957 .ndo_set_mac_address = qeth_l2_set_mac_address,
958 .ndo_change_mtu = qeth_change_mtu,
959 .ndo_vlan_rx_add_vid = qeth_l2_vlan_rx_add_vid,
960 .ndo_vlan_rx_kill_vid = qeth_l2_vlan_rx_kill_vid,
961 .ndo_tx_timeout = qeth_tx_timeout,
Thomas Richter8f43fb02016-06-16 16:18:59 +0200962 .ndo_fix_features = qeth_fix_features,
963 .ndo_set_features = qeth_set_features
Frank Blaschka8403b132009-01-08 10:50:55 -0800964};
965
Frank Blaschka4a71df52008-02-15 09:19:42 +0100966static int qeth_l2_setup_netdev(struct qeth_card *card)
967{
968 switch (card->info.type) {
Frank Blaschka4a71df52008-02-15 09:19:42 +0100969 case QETH_CARD_TYPE_IQD:
Tom Gundersenc835a672014-07-14 16:37:24 +0200970 card->dev = alloc_netdev(0, "hsi%d", NET_NAME_UNKNOWN,
971 ether_setup);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100972 break;
973 case QETH_CARD_TYPE_OSN:
Tom Gundersenc835a672014-07-14 16:37:24 +0200974 card->dev = alloc_netdev(0, "osn%d", NET_NAME_UNKNOWN,
975 ether_setup);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100976 break;
977 default:
978 card->dev = alloc_etherdev(0);
979 }
980
981 if (!card->dev)
982 return -ENODEV;
983
Heiko Carstens509e2562008-07-26 02:24:10 -0700984 card->dev->ml_priv = card;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100985 card->dev->watchdog_timeo = QETH_TX_TIMEOUT;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100986 card->dev->mtu = card->info.initial_mtu;
Jarod Wilson46b3ef42016-10-20 13:55:23 -0400987 card->dev->min_mtu = 64;
988 card->dev->max_mtu = ETH_MAX_MTU;
Frank Blaschka8403b132009-01-08 10:50:55 -0800989 card->dev->netdev_ops = &qeth_l2_netdev_ops;
Julian Wiedmann25e2c342017-05-10 19:07:53 +0200990 if (card->info.type == QETH_CARD_TYPE_OSN) {
991 card->dev->ethtool_ops = &qeth_l2_osn_ops;
992 card->dev->flags |= IFF_NOARP;
993 } else {
994 card->dev->ethtool_ops = &qeth_l2_ethtool_ops;
995 }
Julian Wiedmann9400c532017-10-18 17:40:20 +0200996
997 if (card->info.type == QETH_CARD_TYPE_OSM)
998 card->dev->features |= NETIF_F_VLAN_CHALLENGED;
999 else
1000 card->dev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
Thomas Richter4d7def22015-09-18 16:06:51 +02001001 if (card->info.type == QETH_CARD_TYPE_OSD && !card->info.guestlan) {
Thomas Richter8f43fb02016-06-16 16:18:59 +02001002 card->dev->hw_features = NETIF_F_SG;
Hans Wippel9bdc4412016-06-16 16:19:00 +02001003 card->dev->vlan_features = NETIF_F_SG;
Julian Wiedmann6d69b1f2017-12-01 10:14:50 +01001004 card->dev->features |= NETIF_F_SG;
Thomas Richter8f43fb02016-06-16 16:18:59 +02001005 /* OSA 3S and earlier has no RX/TX support */
Hans Wippel9bdc4412016-06-16 16:19:00 +02001006 if (qeth_is_supported(card, IPA_OUTBOUND_CHECKSUM)) {
Thomas Richter8f43fb02016-06-16 16:18:59 +02001007 card->dev->hw_features |= NETIF_F_IP_CSUM;
Hans Wippel9bdc4412016-06-16 16:19:00 +02001008 card->dev->vlan_features |= NETIF_F_IP_CSUM;
1009 }
1010 if (qeth_is_supported(card, IPA_INBOUND_CHECKSUM)) {
Thomas Richter8f43fb02016-06-16 16:18:59 +02001011 card->dev->hw_features |= NETIF_F_RXCSUM;
Hans Wippel9bdc4412016-06-16 16:19:00 +02001012 card->dev->vlan_features |= NETIF_F_RXCSUM;
1013 }
Thomas Richter4d7def22015-09-18 16:06:51 +02001014 }
Julian Wiedmann0d6f02d2017-08-18 10:19:10 +02001015 if (card->info.type != QETH_CARD_TYPE_OSN &&
1016 card->info.type != QETH_CARD_TYPE_IQD) {
1017 card->dev->priv_flags &= ~IFF_TX_SKB_SHARING;
1018 card->dev->needed_headroom = sizeof(struct qeth_hdr);
1019 }
1020
Frank Blaschka4a71df52008-02-15 09:19:42 +01001021 card->info.broadcast_capable = 1;
1022 qeth_l2_request_initial_mac(card);
1023 SET_NETDEV_DEV(card->dev, &card->gdev->dev);
Julian Wiedmannd73ef322017-04-11 16:11:11 +02001024 netif_napi_add(card->dev, &card->napi, qeth_poll, QETH_NAPI_WEIGHT);
Ursula Braune5ebe632015-12-11 12:27:55 +01001025 netif_carrier_off(card->dev);
Frank Blaschka4a71df52008-02-15 09:19:42 +01001026 return register_netdev(card->dev);
1027}
1028
Thomas Richter4d7def22015-09-18 16:06:51 +02001029static int qeth_l2_start_ipassists(struct qeth_card *card)
1030{
1031 /* configure isolation level */
1032 if (qeth_set_access_ctrl_online(card, 0))
1033 return -ENODEV;
Thomas Richter4d7def22015-09-18 16:06:51 +02001034 return 0;
1035}
1036
Julian Wiedmann521c10e2017-06-06 14:33:45 +02001037static void qeth_l2_trace_features(struct qeth_card *card)
1038{
Hans Wippela45b3fa2017-09-18 21:18:14 +02001039 /* Set BridgePort features */
1040 QETH_CARD_TEXT(card, 2, "featuSBP");
Julian Wiedmann521c10e2017-06-06 14:33:45 +02001041 QETH_CARD_HEX(card, 2, &card->options.sbp.supported_funcs,
1042 sizeof(card->options.sbp.supported_funcs));
Hans Wippela45b3fa2017-09-18 21:18:14 +02001043 /* VNIC Characteristics features */
1044 QETH_CARD_TEXT(card, 2, "feaVNICC");
1045 QETH_CARD_HEX(card, 2, &card->options.vnicc.sup_chars,
1046 sizeof(card->options.vnicc.sup_chars));
Julian Wiedmann521c10e2017-06-06 14:33:45 +02001047}
1048
Frank Blaschka4a71df52008-02-15 09:19:42 +01001049static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)
1050{
1051 struct qeth_card *card = dev_get_drvdata(&gdev->dev);
1052 int rc = 0;
1053 enum qeth_card_states recover_flag;
1054
Ursula Braun9dc48cc2010-07-22 23:15:05 +00001055 mutex_lock(&card->discipline_mutex);
Frank Blaschkac4949f02010-05-11 19:34:47 +00001056 mutex_lock(&card->conf_mutex);
Peter Tiedemannd11ba0c2008-04-01 10:26:58 +02001057 QETH_DBF_TEXT(SETUP, 2, "setonlin");
1058 QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *));
Frank Blaschka4a71df52008-02-15 09:19:42 +01001059
Frank Blaschka4a71df52008-02-15 09:19:42 +01001060 recover_flag = card->state;
Frank Blaschka4a71df52008-02-15 09:19:42 +01001061 rc = qeth_core_hardsetup_card(card);
1062 if (rc) {
Thomas Richter1aec42b2015-01-21 13:39:10 +01001063 QETH_DBF_TEXT_(SETUP, 2, "2err%04x", rc);
Ursula Braunaa909222009-11-12 00:11:43 +00001064 rc = -ENODEV;
Frank Blaschka4a71df52008-02-15 09:19:42 +01001065 goto out_remove;
1066 }
Eugene Crosserc044dc22014-01-29 09:23:48 +01001067 qeth_bridgeport_query_support(card);
1068 if (card->options.sbp.supported_funcs)
1069 dev_info(&card->gdev->dev,
Eugene Crosser9c23f4da2015-05-18 14:27:56 +02001070 "The device represents a Bridge Capable Port\n");
Frank Blaschka4a71df52008-02-15 09:19:42 +01001071
Ursula Braunaa909222009-11-12 00:11:43 +00001072 if (!card->dev && qeth_l2_setup_netdev(card)) {
1073 rc = -ENODEV;
Frank Blaschka4a71df52008-02-15 09:19:42 +01001074 goto out_remove;
Ursula Braunaa909222009-11-12 00:11:43 +00001075 }
Frank Blaschka4a71df52008-02-15 09:19:42 +01001076
1077 if (card->info.type != QETH_CARD_TYPE_OSN)
1078 qeth_l2_send_setmac(card, &card->dev->dev_addr[0]);
1079
Frank Blaschka1da74b12011-05-12 18:45:02 +00001080 if (qeth_is_diagass_supported(card, QETH_DIAGS_CMD_TRAP)) {
1081 if (card->info.hwtrap &&
1082 qeth_hw_trap(card, QETH_DIAGS_TRAP_ARM))
1083 card->info.hwtrap = 0;
1084 } else
1085 card->info.hwtrap = 0;
1086
Hans Wippela45b3fa2017-09-18 21:18:14 +02001087 /* for the rx_bcast characteristic, init VNICC after setmac */
1088 qeth_l2_vnicc_init(card);
1089
1090 qeth_trace_features(card);
1091 qeth_l2_trace_features(card);
1092
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001093 qeth_l2_setup_bridgeport_attrs(card);
1094
Frank Blaschka4a71df52008-02-15 09:19:42 +01001095 card->state = CARD_STATE_HARDSETUP;
Frank Blaschkaa1c3ed42010-09-07 21:14:42 +00001096 memset(&card->rx, 0, sizeof(struct qeth_rx));
Frank Blaschka4a71df52008-02-15 09:19:42 +01001097 qeth_print_status_message(card);
1098
1099 /* softsetup */
Peter Tiedemannd11ba0c2008-04-01 10:26:58 +02001100 QETH_DBF_TEXT(SETUP, 2, "softsetp");
Frank Blaschka4a71df52008-02-15 09:19:42 +01001101
Ursula Braun5113fec2010-05-16 21:15:14 +00001102 if ((card->info.type == QETH_CARD_TYPE_OSD) ||
Stefan Raspl0f547612013-01-21 02:30:20 +00001103 (card->info.type == QETH_CARD_TYPE_OSX)) {
Thomas Richter8f43fb02016-06-16 16:18:59 +02001104 rc = qeth_l2_start_ipassists(card);
1105 if (rc)
Stefan Raspl0f547612013-01-21 02:30:20 +00001106 goto out_remove;
Stefan Raspl0f547612013-01-21 02:30:20 +00001107 }
Ursula Braun5113fec2010-05-16 21:15:14 +00001108
Julian Wiedmann9400c532017-10-18 17:40:20 +02001109 if (card->info.type != QETH_CARD_TYPE_OSN)
Ursula Braun70919e22011-02-26 22:41:36 -08001110 qeth_l2_process_vlans(card);
Frank Blaschka4a71df52008-02-15 09:19:42 +01001111
1112 netif_tx_disable(card->dev);
1113
1114 rc = qeth_init_qdio_queues(card);
1115 if (rc) {
Peter Tiedemannd11ba0c2008-04-01 10:26:58 +02001116 QETH_DBF_TEXT_(SETUP, 2, "6err%d", rc);
Ursula Braunaa909222009-11-12 00:11:43 +00001117 rc = -ENODEV;
Frank Blaschka4a71df52008-02-15 09:19:42 +01001118 goto out_remove;
1119 }
1120 card->state = CARD_STATE_SOFTSETUP;
Ursula Braun2b6203b2010-11-26 02:41:19 +00001121 if (card->lan_online)
1122 netif_carrier_on(card->dev);
1123 else
1124 netif_carrier_off(card->dev);
Frank Blaschka4a71df52008-02-15 09:19:42 +01001125
1126 qeth_set_allowed_threads(card, 0xffffffff, 0);
1127 if (recover_flag == CARD_STATE_RECOVER) {
1128 if (recovery_mode &&
1129 card->info.type != QETH_CARD_TYPE_OSN) {
Ursula Braun39423442011-01-12 20:42:24 +00001130 __qeth_l2_open(card->dev);
Frank Blaschka4a71df52008-02-15 09:19:42 +01001131 } else {
1132 rtnl_lock();
1133 dev_open(card->dev);
1134 rtnl_unlock();
1135 }
1136 /* this also sets saved unicast addresses */
Lakhvich Dmitriyfe5c8022015-10-06 15:12:28 +02001137 qeth_l2_set_rx_mode(card->dev);
Hans Wippele830baa2016-09-15 14:39:21 +02001138 rtnl_lock();
1139 qeth_recover_features(card->dev);
1140 rtnl_unlock();
Frank Blaschka4a71df52008-02-15 09:19:42 +01001141 }
1142 /* let user_space know that device is online */
1143 kobject_uevent(&gdev->dev.kobj, KOBJ_CHANGE);
Frank Blaschkac4949f02010-05-11 19:34:47 +00001144 mutex_unlock(&card->conf_mutex);
Ursula Braun9dc48cc2010-07-22 23:15:05 +00001145 mutex_unlock(&card->discipline_mutex);
Frank Blaschka4a71df52008-02-15 09:19:42 +01001146 return 0;
Ursula Braunaa909222009-11-12 00:11:43 +00001147
Frank Blaschka4a71df52008-02-15 09:19:42 +01001148out_remove:
Frank Blaschka4a71df52008-02-15 09:19:42 +01001149 qeth_l2_stop_card(card, 0);
1150 ccw_device_set_offline(CARD_DDEV(card));
1151 ccw_device_set_offline(CARD_WDEV(card));
1152 ccw_device_set_offline(CARD_RDEV(card));
Ursula Braun22ae2792014-02-24 13:12:06 +01001153 qdio_free(CARD_DDEV(card));
Frank Blaschka4a71df52008-02-15 09:19:42 +01001154 if (recover_flag == CARD_STATE_RECOVER)
1155 card->state = CARD_STATE_RECOVER;
1156 else
1157 card->state = CARD_STATE_DOWN;
Frank Blaschkac4949f02010-05-11 19:34:47 +00001158 mutex_unlock(&card->conf_mutex);
Ursula Braun9dc48cc2010-07-22 23:15:05 +00001159 mutex_unlock(&card->discipline_mutex);
Ursula Braunaa909222009-11-12 00:11:43 +00001160 return rc;
Frank Blaschka4a71df52008-02-15 09:19:42 +01001161}
1162
1163static int qeth_l2_set_online(struct ccwgroup_device *gdev)
1164{
1165 return __qeth_l2_set_online(gdev, 0);
1166}
1167
1168static int __qeth_l2_set_offline(struct ccwgroup_device *cgdev,
1169 int recovery_mode)
1170{
1171 struct qeth_card *card = dev_get_drvdata(&cgdev->dev);
1172 int rc = 0, rc2 = 0, rc3 = 0;
1173 enum qeth_card_states recover_flag;
1174
Ursula Braun9dc48cc2010-07-22 23:15:05 +00001175 mutex_lock(&card->discipline_mutex);
Frank Blaschkac4949f02010-05-11 19:34:47 +00001176 mutex_lock(&card->conf_mutex);
Peter Tiedemannd11ba0c2008-04-01 10:26:58 +02001177 QETH_DBF_TEXT(SETUP, 3, "setoffl");
1178 QETH_DBF_HEX(SETUP, 3, &card, sizeof(void *));
Frank Blaschka4a71df52008-02-15 09:19:42 +01001179
1180 if (card->dev && netif_carrier_ok(card->dev))
1181 netif_carrier_off(card->dev);
1182 recover_flag = card->state;
Frank Blaschka1da74b12011-05-12 18:45:02 +00001183 if ((!recovery_mode && card->info.hwtrap) || card->info.hwtrap == 2) {
1184 qeth_hw_trap(card, QETH_DIAGS_TRAP_DISARM);
1185 card->info.hwtrap = 1;
1186 }
Ursula Braun0f5623c2008-10-24 11:16:52 +02001187 qeth_l2_stop_card(card, recovery_mode);
Frank Blaschka4a71df52008-02-15 09:19:42 +01001188 rc = ccw_device_set_offline(CARD_DDEV(card));
1189 rc2 = ccw_device_set_offline(CARD_WDEV(card));
1190 rc3 = ccw_device_set_offline(CARD_RDEV(card));
1191 if (!rc)
1192 rc = (rc2) ? rc2 : rc3;
1193 if (rc)
Peter Tiedemannd11ba0c2008-04-01 10:26:58 +02001194 QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc);
Ursula Braun22ae2792014-02-24 13:12:06 +01001195 qdio_free(CARD_DDEV(card));
Frank Blaschka4a71df52008-02-15 09:19:42 +01001196 if (recover_flag == CARD_STATE_UP)
1197 card->state = CARD_STATE_RECOVER;
1198 /* let user_space know that device is offline */
1199 kobject_uevent(&cgdev->dev.kobj, KOBJ_CHANGE);
Frank Blaschkac4949f02010-05-11 19:34:47 +00001200 mutex_unlock(&card->conf_mutex);
Ursula Braun9dc48cc2010-07-22 23:15:05 +00001201 mutex_unlock(&card->discipline_mutex);
Frank Blaschka4a71df52008-02-15 09:19:42 +01001202 return 0;
1203}
1204
1205static int qeth_l2_set_offline(struct ccwgroup_device *cgdev)
1206{
1207 return __qeth_l2_set_offline(cgdev, 0);
1208}
1209
1210static int qeth_l2_recover(void *ptr)
1211{
1212 struct qeth_card *card;
1213 int rc = 0;
1214
1215 card = (struct qeth_card *) ptr;
Carsten Otte847a50f2010-06-21 22:57:05 +00001216 QETH_CARD_TEXT(card, 2, "recover1");
Frank Blaschka4a71df52008-02-15 09:19:42 +01001217 if (!qeth_do_run_thread(card, QETH_RECOVER_THREAD))
1218 return 0;
Carsten Otte847a50f2010-06-21 22:57:05 +00001219 QETH_CARD_TEXT(card, 2, "recover2");
Frank Blaschka74eacdb2008-12-25 13:39:49 +01001220 dev_warn(&card->gdev->dev,
1221 "A recovery process has been started for the device\n");
Stefan Raspl65d80132013-04-07 22:19:27 +00001222 qeth_set_recovery_task(card);
Frank Blaschka4a71df52008-02-15 09:19:42 +01001223 __qeth_l2_set_offline(card->gdev, 1);
1224 rc = __qeth_l2_set_online(card->gdev, 1);
Frank Blaschka4a71df52008-02-15 09:19:42 +01001225 if (!rc)
Frank Blaschka74eacdb2008-12-25 13:39:49 +01001226 dev_info(&card->gdev->dev,
1227 "Device successfully recovered!\n");
Ursula Braun28a7e4c2008-09-19 12:56:03 +02001228 else {
Stefan Raspl0f547612013-01-21 02:30:20 +00001229 qeth_close_dev(card);
1230 dev_warn(&card->gdev->dev, "The qeth device driver "
Stefan Raspl2efaf5f2012-10-15 19:21:18 +00001231 "failed to recover an error on the device\n");
Ursula Braun28a7e4c2008-09-19 12:56:03 +02001232 }
Stefan Raspl65d80132013-04-07 22:19:27 +00001233 qeth_clear_recovery_task(card);
Frank Blaschkaa1c3ed42010-09-07 21:14:42 +00001234 qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD);
1235 qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD);
Frank Blaschka4a71df52008-02-15 09:19:42 +01001236 return 0;
1237}
1238
1239static int __init qeth_l2_init(void)
1240{
Frank Blaschka74eacdb2008-12-25 13:39:49 +01001241 pr_info("register layer 2 discipline\n");
Frank Blaschka4a71df52008-02-15 09:19:42 +01001242 return 0;
1243}
1244
1245static void __exit qeth_l2_exit(void)
1246{
Frank Blaschka74eacdb2008-12-25 13:39:49 +01001247 pr_info("unregister layer 2 discipline\n");
Frank Blaschka4a71df52008-02-15 09:19:42 +01001248}
1249
Frank Blaschkabbcfcdc2009-06-16 10:30:31 +02001250static int qeth_l2_pm_suspend(struct ccwgroup_device *gdev)
1251{
1252 struct qeth_card *card = dev_get_drvdata(&gdev->dev);
1253
1254 if (card->dev)
1255 netif_device_detach(card->dev);
1256 qeth_set_allowed_threads(card, 0, 1);
1257 wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0);
1258 if (gdev->state == CCWGROUP_OFFLINE)
1259 return 0;
1260 if (card->state == CARD_STATE_UP) {
Frank Blaschka1da74b12011-05-12 18:45:02 +00001261 if (card->info.hwtrap)
1262 qeth_hw_trap(card, QETH_DIAGS_TRAP_DISARM);
Frank Blaschkabbcfcdc2009-06-16 10:30:31 +02001263 __qeth_l2_set_offline(card->gdev, 1);
1264 } else
1265 __qeth_l2_set_offline(card->gdev, 0);
1266 return 0;
1267}
1268
1269static int qeth_l2_pm_resume(struct ccwgroup_device *gdev)
1270{
1271 struct qeth_card *card = dev_get_drvdata(&gdev->dev);
1272 int rc = 0;
1273
1274 if (gdev->state == CCWGROUP_OFFLINE)
1275 goto out;
1276
1277 if (card->state == CARD_STATE_RECOVER) {
1278 rc = __qeth_l2_set_online(card->gdev, 1);
1279 if (rc) {
Ursula Braun869da902010-03-08 20:36:56 +00001280 rtnl_lock();
1281 dev_close(card->dev);
1282 rtnl_unlock();
Frank Blaschkabbcfcdc2009-06-16 10:30:31 +02001283 }
1284 } else
1285 rc = __qeth_l2_set_online(card->gdev, 0);
1286out:
1287 qeth_set_allowed_threads(card, 0xffffffff, 0);
1288 if (card->dev)
1289 netif_device_attach(card->dev);
1290 if (rc)
1291 dev_warn(&card->gdev->dev, "The qeth device driver "
1292 "failed to recover an error on the device\n");
1293 return rc;
1294}
1295
Eugene Crosserc044dc22014-01-29 09:23:48 +01001296/* Returns zero if the command is successfully "consumed" */
1297static int qeth_l2_control_event(struct qeth_card *card,
1298 struct qeth_ipa_cmd *cmd)
1299{
1300 switch (cmd->hdr.command) {
Eugene Crosser9c23f4da2015-05-18 14:27:56 +02001301 case IPA_CMD_SETBRIDGEPORT_OSA:
1302 case IPA_CMD_SETBRIDGEPORT_IQD:
Eugene Crosserc044dc22014-01-29 09:23:48 +01001303 if (cmd->data.sbp.hdr.command_code ==
1304 IPA_SBP_BRIDGE_PORT_STATE_CHANGE) {
1305 qeth_bridge_state_change(card, cmd);
1306 return 0;
1307 } else
1308 return 1;
1309 case IPA_CMD_ADDRESS_CHANGE_NOTIF:
1310 qeth_bridge_host_event(card, cmd);
1311 return 0;
1312 default:
1313 return 1;
1314 }
1315}
1316
Sebastian Ottc041f2d4872012-05-15 18:02:21 +02001317struct qeth_discipline qeth_l2_discipline = {
Julian Wiedmann2d2ebb32017-05-10 19:07:52 +02001318 .devtype = &qeth_l2_devtype,
Sebastian Ottc041f2d4872012-05-15 18:02:21 +02001319 .start_poll = qeth_qdio_start_poll,
1320 .input_handler = (qdio_handler_t *) qeth_qdio_input_handler,
1321 .output_handler = (qdio_handler_t *) qeth_qdio_output_handler,
Julian Wiedmannd73ef322017-04-11 16:11:11 +02001322 .process_rx_buffer = qeth_l2_process_inbound_buffer,
Sebastian Ottc041f2d4872012-05-15 18:02:21 +02001323 .recover = qeth_l2_recover,
1324 .setup = qeth_l2_probe_device,
Frank Blaschka4a71df52008-02-15 09:19:42 +01001325 .remove = qeth_l2_remove_device,
1326 .set_online = qeth_l2_set_online,
1327 .set_offline = qeth_l2_set_offline,
Frank Blaschkabbcfcdc2009-06-16 10:30:31 +02001328 .freeze = qeth_l2_pm_suspend,
1329 .thaw = qeth_l2_pm_resume,
1330 .restore = qeth_l2_pm_resume,
Julian Wiedmann942d6982017-04-11 16:11:10 +02001331 .do_ioctl = NULL,
Eugene Crosserc044dc22014-01-29 09:23:48 +01001332 .control_event_handler = qeth_l2_control_event,
Frank Blaschka4a71df52008-02-15 09:19:42 +01001333};
Sebastian Ottc041f2d4872012-05-15 18:02:21 +02001334EXPORT_SYMBOL_GPL(qeth_l2_discipline);
Frank Blaschka4a71df52008-02-15 09:19:42 +01001335
1336static int qeth_osn_send_control_data(struct qeth_card *card, int len,
1337 struct qeth_cmd_buffer *iob)
1338{
1339 unsigned long flags;
1340 int rc = 0;
1341
Carsten Otte847a50f2010-06-21 22:57:05 +00001342 QETH_CARD_TEXT(card, 5, "osndctrd");
Frank Blaschka4a71df52008-02-15 09:19:42 +01001343
1344 wait_event(card->wait_q,
1345 atomic_cmpxchg(&card->write.irq_pending, 0, 1) == 0);
1346 qeth_prepare_control_data(card, len, iob);
Carsten Otte847a50f2010-06-21 22:57:05 +00001347 QETH_CARD_TEXT(card, 6, "osnoirqp");
Frank Blaschka4a71df52008-02-15 09:19:42 +01001348 spin_lock_irqsave(get_ccwdev_lock(card->write.ccwdev), flags);
1349 rc = ccw_device_start(card->write.ccwdev, &card->write.ccw,
1350 (addr_t) iob, 0, 0);
1351 spin_unlock_irqrestore(get_ccwdev_lock(card->write.ccwdev), flags);
1352 if (rc) {
Frank Blaschka14cc21b2008-06-06 12:37:46 +02001353 QETH_DBF_MESSAGE(2, "qeth_osn_send_control_data: "
Frank Blaschka4a71df52008-02-15 09:19:42 +01001354 "ccw_device_start rc = %i\n", rc);
Carsten Otte847a50f2010-06-21 22:57:05 +00001355 QETH_CARD_TEXT_(card, 2, " err%d", rc);
Frank Blaschka4a71df52008-02-15 09:19:42 +01001356 qeth_release_buffer(iob->channel, iob);
1357 atomic_set(&card->write.irq_pending, 0);
1358 wake_up(&card->wait_q);
1359 }
1360 return rc;
1361}
1362
1363static int qeth_osn_send_ipa_cmd(struct qeth_card *card,
1364 struct qeth_cmd_buffer *iob, int data_len)
1365{
1366 u16 s1, s2;
1367
Carsten Otte847a50f2010-06-21 22:57:05 +00001368 QETH_CARD_TEXT(card, 4, "osndipa");
Frank Blaschka4a71df52008-02-15 09:19:42 +01001369
1370 qeth_prepare_ipa_cmd(card, iob, QETH_PROT_OSN2);
1371 s1 = (u16)(IPA_PDU_HEADER_SIZE + data_len);
1372 s2 = (u16)data_len;
1373 memcpy(QETH_IPA_PDU_LEN_TOTAL(iob->data), &s1, 2);
1374 memcpy(QETH_IPA_PDU_LEN_PDU1(iob->data), &s2, 2);
1375 memcpy(QETH_IPA_PDU_LEN_PDU2(iob->data), &s2, 2);
1376 memcpy(QETH_IPA_PDU_LEN_PDU3(iob->data), &s2, 2);
1377 return qeth_osn_send_control_data(card, s1, iob);
1378}
1379
1380int qeth_osn_assist(struct net_device *dev, void *data, int data_len)
1381{
1382 struct qeth_cmd_buffer *iob;
1383 struct qeth_card *card;
1384 int rc;
1385
Frank Blaschka4a71df52008-02-15 09:19:42 +01001386 if (!dev)
1387 return -ENODEV;
Heiko Carstens509e2562008-07-26 02:24:10 -07001388 card = dev->ml_priv;
Frank Blaschka4a71df52008-02-15 09:19:42 +01001389 if (!card)
1390 return -ENODEV;
Carsten Otte847a50f2010-06-21 22:57:05 +00001391 QETH_CARD_TEXT(card, 2, "osnsdmc");
Eugene Crosserc3521252015-01-16 14:05:47 +01001392 if (!qeth_card_hw_is_reachable(card))
Frank Blaschka4a71df52008-02-15 09:19:42 +01001393 return -ENODEV;
1394 iob = qeth_wait_for_buffer(&card->write);
1395 memcpy(iob->data+IPA_PDU_HEADER_SIZE, data, data_len);
1396 rc = qeth_osn_send_ipa_cmd(card, iob, data_len);
1397 return rc;
1398}
1399EXPORT_SYMBOL(qeth_osn_assist);
1400
1401int qeth_osn_register(unsigned char *read_dev_no, struct net_device **dev,
1402 int (*assist_cb)(struct net_device *, void *),
1403 int (*data_cb)(struct sk_buff *))
1404{
1405 struct qeth_card *card;
1406
Frank Blaschka4a71df52008-02-15 09:19:42 +01001407 *dev = qeth_l2_netdev_by_devno(read_dev_no);
1408 if (*dev == NULL)
1409 return -ENODEV;
Heiko Carstens509e2562008-07-26 02:24:10 -07001410 card = (*dev)->ml_priv;
Frank Blaschka4a71df52008-02-15 09:19:42 +01001411 if (!card)
1412 return -ENODEV;
Carsten Otte847a50f2010-06-21 22:57:05 +00001413 QETH_CARD_TEXT(card, 2, "osnreg");
Frank Blaschka4a71df52008-02-15 09:19:42 +01001414 if ((assist_cb == NULL) || (data_cb == NULL))
1415 return -EINVAL;
1416 card->osn_info.assist_cb = assist_cb;
1417 card->osn_info.data_cb = data_cb;
1418 return 0;
1419}
1420EXPORT_SYMBOL(qeth_osn_register);
1421
1422void qeth_osn_deregister(struct net_device *dev)
1423{
1424 struct qeth_card *card;
1425
Frank Blaschka4a71df52008-02-15 09:19:42 +01001426 if (!dev)
1427 return;
Heiko Carstens509e2562008-07-26 02:24:10 -07001428 card = dev->ml_priv;
Frank Blaschka4a71df52008-02-15 09:19:42 +01001429 if (!card)
1430 return;
Carsten Otte847a50f2010-06-21 22:57:05 +00001431 QETH_CARD_TEXT(card, 2, "osndereg");
Frank Blaschka4a71df52008-02-15 09:19:42 +01001432 card->osn_info.assist_cb = NULL;
1433 card->osn_info.data_cb = NULL;
1434 return;
1435}
1436EXPORT_SYMBOL(qeth_osn_deregister);
1437
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001438/* SETBRIDGEPORT support, async notifications */
1439
Eugene Crosser9f48b9d2014-01-14 15:54:13 +01001440enum qeth_an_event_type {anev_reg_unreg, anev_abort, anev_reset};
1441
1442/**
1443 * qeth_bridge_emit_host_event() - bridgeport address change notification
1444 * @card: qeth_card structure pointer, for udev events.
1445 * @evtype: "normal" register/unregister, or abort, or reset. For abort
1446 * and reset token and addr_lnid are unused and may be NULL.
1447 * @code: event bitmask: high order bit 0x80 value 1 means removal of an
1448 * object, 0 - addition of an object.
1449 * 0x01 - VLAN, 0x02 - MAC, 0x03 - VLAN and MAC.
1450 * @token: "network token" structure identifying physical address of the port.
1451 * @addr_lnid: pointer to structure with MAC address and VLAN ID.
1452 *
1453 * This function is called when registrations and deregistrations are
1454 * reported by the hardware, and also when notifications are enabled -
1455 * for all currently registered addresses.
1456 */
1457static void qeth_bridge_emit_host_event(struct qeth_card *card,
1458 enum qeth_an_event_type evtype,
1459 u8 code, struct net_if_token *token, struct mac_addr_lnid *addr_lnid)
1460{
1461 char str[7][32];
1462 char *env[8];
1463 int i = 0;
1464
1465 switch (evtype) {
1466 case anev_reg_unreg:
1467 snprintf(str[i], sizeof(str[i]), "BRIDGEDHOST=%s",
1468 (code & IPA_ADDR_CHANGE_CODE_REMOVAL)
1469 ? "deregister" : "register");
1470 env[i] = str[i]; i++;
1471 if (code & IPA_ADDR_CHANGE_CODE_VLANID) {
1472 snprintf(str[i], sizeof(str[i]), "VLAN=%d",
1473 addr_lnid->lnid);
1474 env[i] = str[i]; i++;
1475 }
1476 if (code & IPA_ADDR_CHANGE_CODE_MACADDR) {
Eugene Crosser9846e702015-09-18 16:06:48 +02001477 snprintf(str[i], sizeof(str[i]), "MAC=%pM",
Thomas Richter4d7def22015-09-18 16:06:51 +02001478 addr_lnid->mac);
Eugene Crosser9f48b9d2014-01-14 15:54:13 +01001479 env[i] = str[i]; i++;
1480 }
1481 snprintf(str[i], sizeof(str[i]), "NTOK_BUSID=%x.%x.%04x",
1482 token->cssid, token->ssid, token->devnum);
1483 env[i] = str[i]; i++;
1484 snprintf(str[i], sizeof(str[i]), "NTOK_IID=%02x", token->iid);
1485 env[i] = str[i]; i++;
1486 snprintf(str[i], sizeof(str[i]), "NTOK_CHPID=%02x",
1487 token->chpid);
1488 env[i] = str[i]; i++;
1489 snprintf(str[i], sizeof(str[i]), "NTOK_CHID=%04x", token->chid);
1490 env[i] = str[i]; i++;
1491 break;
1492 case anev_abort:
1493 snprintf(str[i], sizeof(str[i]), "BRIDGEDHOST=abort");
1494 env[i] = str[i]; i++;
1495 break;
1496 case anev_reset:
1497 snprintf(str[i], sizeof(str[i]), "BRIDGEDHOST=reset");
1498 env[i] = str[i]; i++;
1499 break;
1500 }
1501 env[i] = NULL;
1502 kobject_uevent_env(&card->gdev->dev.kobj, KOBJ_CHANGE, env);
1503}
1504
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001505struct qeth_bridge_state_data {
1506 struct work_struct worker;
1507 struct qeth_card *card;
1508 struct qeth_sbp_state_change qports;
1509};
1510
1511static void qeth_bridge_state_change_worker(struct work_struct *work)
1512{
1513 struct qeth_bridge_state_data *data =
1514 container_of(work, struct qeth_bridge_state_data, worker);
1515 /* We are only interested in the first entry - local port */
1516 struct qeth_sbp_port_entry *entry = &data->qports.entry[0];
1517 char env_locrem[32];
1518 char env_role[32];
1519 char env_state[32];
1520 char *env[] = {
1521 env_locrem,
1522 env_role,
1523 env_state,
1524 NULL
1525 };
1526
1527 /* Role should not change by itself, but if it did, */
1528 /* information from the hardware is authoritative. */
1529 mutex_lock(&data->card->conf_mutex);
1530 data->card->options.sbp.role = entry->role;
1531 mutex_unlock(&data->card->conf_mutex);
1532
1533 snprintf(env_locrem, sizeof(env_locrem), "BRIDGEPORT=statechange");
1534 snprintf(env_role, sizeof(env_role), "ROLE=%s",
1535 (entry->role == QETH_SBP_ROLE_NONE) ? "none" :
1536 (entry->role == QETH_SBP_ROLE_PRIMARY) ? "primary" :
1537 (entry->role == QETH_SBP_ROLE_SECONDARY) ? "secondary" :
1538 "<INVALID>");
1539 snprintf(env_state, sizeof(env_state), "STATE=%s",
1540 (entry->state == QETH_SBP_STATE_INACTIVE) ? "inactive" :
1541 (entry->state == QETH_SBP_STATE_STANDBY) ? "standby" :
1542 (entry->state == QETH_SBP_STATE_ACTIVE) ? "active" :
1543 "<INVALID>");
1544 kobject_uevent_env(&data->card->gdev->dev.kobj,
1545 KOBJ_CHANGE, env);
1546 kfree(data);
1547}
1548
Eugene Crosserc044dc22014-01-29 09:23:48 +01001549static void qeth_bridge_state_change(struct qeth_card *card,
1550 struct qeth_ipa_cmd *cmd)
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001551{
1552 struct qeth_sbp_state_change *qports =
1553 &cmd->data.sbp.data.state_change;
1554 struct qeth_bridge_state_data *data;
1555 int extrasize;
1556
1557 QETH_CARD_TEXT(card, 2, "brstchng");
1558 if (qports->entry_length != sizeof(struct qeth_sbp_port_entry)) {
Thomas Richter8a593142014-10-22 12:18:03 +02001559 QETH_CARD_TEXT_(card, 2, "BPsz%04x", qports->entry_length);
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001560 return;
1561 }
1562 extrasize = sizeof(struct qeth_sbp_port_entry) * qports->num_entries;
1563 data = kzalloc(sizeof(struct qeth_bridge_state_data) + extrasize,
1564 GFP_ATOMIC);
1565 if (!data) {
1566 QETH_CARD_TEXT(card, 2, "BPSalloc");
1567 return;
1568 }
1569 INIT_WORK(&data->worker, qeth_bridge_state_change_worker);
1570 data->card = card;
1571 memcpy(&data->qports, qports,
1572 sizeof(struct qeth_sbp_state_change) + extrasize);
1573 queue_work(qeth_wq, &data->worker);
1574}
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001575
Eugene Crosser9f48b9d2014-01-14 15:54:13 +01001576struct qeth_bridge_host_data {
1577 struct work_struct worker;
1578 struct qeth_card *card;
1579 struct qeth_ipacmd_addr_change hostevs;
1580};
1581
1582static void qeth_bridge_host_event_worker(struct work_struct *work)
1583{
1584 struct qeth_bridge_host_data *data =
1585 container_of(work, struct qeth_bridge_host_data, worker);
1586 int i;
1587
1588 if (data->hostevs.lost_event_mask) {
1589 dev_info(&data->card->gdev->dev,
Eugene Crosser9c23f4da2015-05-18 14:27:56 +02001590"Address notification from the Bridge Port stopped %s (%s)\n",
Eugene Crosser9f48b9d2014-01-14 15:54:13 +01001591 data->card->dev->name,
1592 (data->hostevs.lost_event_mask == 0x01)
1593 ? "Overflow"
1594 : (data->hostevs.lost_event_mask == 0x02)
1595 ? "Bridge port state change"
1596 : "Unknown reason");
1597 mutex_lock(&data->card->conf_mutex);
1598 data->card->options.sbp.hostnotification = 0;
1599 mutex_unlock(&data->card->conf_mutex);
1600 qeth_bridge_emit_host_event(data->card, anev_abort,
1601 0, NULL, NULL);
1602 } else
1603 for (i = 0; i < data->hostevs.num_entries; i++) {
1604 struct qeth_ipacmd_addr_change_entry *entry =
1605 &data->hostevs.entry[i];
1606 qeth_bridge_emit_host_event(data->card,
1607 anev_reg_unreg,
1608 entry->change_code,
1609 &entry->token, &entry->addr_lnid);
1610 }
1611 kfree(data);
1612}
1613
Eugene Crosserc044dc22014-01-29 09:23:48 +01001614static void qeth_bridge_host_event(struct qeth_card *card,
1615 struct qeth_ipa_cmd *cmd)
Eugene Crosser9f48b9d2014-01-14 15:54:13 +01001616{
1617 struct qeth_ipacmd_addr_change *hostevs =
1618 &cmd->data.addrchange;
1619 struct qeth_bridge_host_data *data;
1620 int extrasize;
1621
1622 QETH_CARD_TEXT(card, 2, "brhostev");
1623 if (cmd->hdr.return_code != 0x0000) {
1624 if (cmd->hdr.return_code == 0x0010) {
1625 if (hostevs->lost_event_mask == 0x00)
1626 hostevs->lost_event_mask = 0xff;
1627 } else {
1628 QETH_CARD_TEXT_(card, 2, "BPHe%04x",
1629 cmd->hdr.return_code);
1630 return;
1631 }
1632 }
1633 extrasize = sizeof(struct qeth_ipacmd_addr_change_entry) *
1634 hostevs->num_entries;
1635 data = kzalloc(sizeof(struct qeth_bridge_host_data) + extrasize,
1636 GFP_ATOMIC);
1637 if (!data) {
1638 QETH_CARD_TEXT(card, 2, "BPHalloc");
1639 return;
1640 }
1641 INIT_WORK(&data->worker, qeth_bridge_host_event_worker);
1642 data->card = card;
1643 memcpy(&data->hostevs, hostevs,
1644 sizeof(struct qeth_ipacmd_addr_change) + extrasize);
1645 queue_work(qeth_wq, &data->worker);
1646}
Eugene Crosser9f48b9d2014-01-14 15:54:13 +01001647
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001648/* SETBRIDGEPORT support; sending commands */
1649
1650struct _qeth_sbp_cbctl {
1651 u16 ipa_rc;
1652 u16 cmd_rc;
1653 union {
1654 u32 supported;
1655 struct {
1656 enum qeth_sbp_roles *role;
1657 enum qeth_sbp_states *state;
1658 } qports;
1659 } data;
1660};
1661
1662/**
1663 * qeth_bridgeport_makerc() - derive "traditional" error from hardware codes.
1664 * @card: qeth_card structure pointer, for debug messages.
1665 * @cbctl: state structure with hardware return codes.
1666 * @setcmd: IPA command code
1667 *
1668 * Returns negative errno-compatible error indication or 0 on success.
1669 */
1670static int qeth_bridgeport_makerc(struct qeth_card *card,
1671 struct _qeth_sbp_cbctl *cbctl, enum qeth_ipa_sbp_cmd setcmd)
1672{
1673 int rc;
Eugene Crosser9c23f4da2015-05-18 14:27:56 +02001674 int is_iqd = (card->info.type == QETH_CARD_TYPE_IQD);
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001675
Eugene Crosser9c23f4da2015-05-18 14:27:56 +02001676 if ((is_iqd && (cbctl->ipa_rc == IPA_RC_SUCCESS)) ||
1677 (!is_iqd && (cbctl->ipa_rc == cbctl->cmd_rc)))
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001678 switch (cbctl->cmd_rc) {
Kittipon Meesompop2063a5f2017-06-20 16:00:31 +02001679 case IPA_RC_SUCCESS:
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001680 rc = 0;
1681 break;
Kittipon Meesompop2063a5f2017-06-20 16:00:31 +02001682 case IPA_RC_L2_UNSUPPORTED_CMD:
1683 case IPA_RC_UNSUPPORTED_COMMAND:
Eugene Crosserffb95252015-05-18 14:27:58 +02001684 rc = -EOPNOTSUPP;
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001685 break;
Kittipon Meesompop2063a5f2017-06-20 16:00:31 +02001686 case IPA_RC_SBP_OSA_NOT_CONFIGURED:
1687 case IPA_RC_SBP_IQD_NOT_CONFIGURED:
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001688 rc = -ENODEV; /* maybe not the best code here? */
1689 dev_err(&card->gdev->dev,
Eugene Crosser9c23f4da2015-05-18 14:27:56 +02001690 "The device is not configured as a Bridge Port\n");
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001691 break;
Kittipon Meesompop2063a5f2017-06-20 16:00:31 +02001692 case IPA_RC_SBP_OSA_OS_MISMATCH:
1693 case IPA_RC_SBP_IQD_OS_MISMATCH:
Eugene Crosser1b05cf62016-06-16 16:18:51 +02001694 rc = -EPERM;
1695 dev_err(&card->gdev->dev,
1696 "A Bridge Port is already configured by a different operating system\n");
1697 break;
Kittipon Meesompop2063a5f2017-06-20 16:00:31 +02001698 case IPA_RC_SBP_OSA_ANO_DEV_PRIMARY:
1699 case IPA_RC_SBP_IQD_ANO_DEV_PRIMARY:
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001700 switch (setcmd) {
1701 case IPA_SBP_SET_PRIMARY_BRIDGE_PORT:
1702 rc = -EEXIST;
1703 dev_err(&card->gdev->dev,
Eugene Crosser9c23f4da2015-05-18 14:27:56 +02001704 "The LAN already has a primary Bridge Port\n");
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001705 break;
1706 case IPA_SBP_SET_SECONDARY_BRIDGE_PORT:
1707 rc = -EBUSY;
1708 dev_err(&card->gdev->dev,
Eugene Crosser9c23f4da2015-05-18 14:27:56 +02001709 "The device is already a primary Bridge Port\n");
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001710 break;
1711 default:
1712 rc = -EIO;
1713 }
1714 break;
Kittipon Meesompop2063a5f2017-06-20 16:00:31 +02001715 case IPA_RC_SBP_OSA_CURRENT_SECOND:
1716 case IPA_RC_SBP_IQD_CURRENT_SECOND:
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001717 rc = -EBUSY;
1718 dev_err(&card->gdev->dev,
Eugene Crosser9c23f4da2015-05-18 14:27:56 +02001719 "The device is already a secondary Bridge Port\n");
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001720 break;
Kittipon Meesompop2063a5f2017-06-20 16:00:31 +02001721 case IPA_RC_SBP_OSA_LIMIT_SECOND:
1722 case IPA_RC_SBP_IQD_LIMIT_SECOND:
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001723 rc = -EEXIST;
1724 dev_err(&card->gdev->dev,
Eugene Crosser9c23f4da2015-05-18 14:27:56 +02001725 "The LAN cannot have more secondary Bridge Ports\n");
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001726 break;
Kittipon Meesompop2063a5f2017-06-20 16:00:31 +02001727 case IPA_RC_SBP_OSA_CURRENT_PRIMARY:
1728 case IPA_RC_SBP_IQD_CURRENT_PRIMARY:
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001729 rc = -EBUSY;
1730 dev_err(&card->gdev->dev,
Eugene Crosser9c23f4da2015-05-18 14:27:56 +02001731 "The device is already a primary Bridge Port\n");
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001732 break;
Kittipon Meesompop2063a5f2017-06-20 16:00:31 +02001733 case IPA_RC_SBP_OSA_NOT_AUTHD_BY_ZMAN:
1734 case IPA_RC_SBP_IQD_NOT_AUTHD_BY_ZMAN:
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001735 rc = -EACCES;
1736 dev_err(&card->gdev->dev,
Eugene Crosser9c23f4da2015-05-18 14:27:56 +02001737 "The device is not authorized to be a Bridge Port\n");
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001738 break;
1739 default:
1740 rc = -EIO;
1741 }
Eugene Crosser9c23f4da2015-05-18 14:27:56 +02001742 else
1743 switch (cbctl->ipa_rc) {
1744 case IPA_RC_NOTSUPP:
Eugene Crosserffb95252015-05-18 14:27:58 +02001745 rc = -EOPNOTSUPP;
Eugene Crosser9c23f4da2015-05-18 14:27:56 +02001746 break;
1747 case IPA_RC_UNSUPPORTED_COMMAND:
Eugene Crosserffb95252015-05-18 14:27:58 +02001748 rc = -EOPNOTSUPP;
Eugene Crosser9c23f4da2015-05-18 14:27:56 +02001749 break;
1750 default:
1751 rc = -EIO;
1752 }
1753
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001754 if (rc) {
1755 QETH_CARD_TEXT_(card, 2, "SBPi%04x", cbctl->ipa_rc);
1756 QETH_CARD_TEXT_(card, 2, "SBPc%04x", cbctl->cmd_rc);
1757 }
1758 return rc;
1759}
1760
Julian Wiedmannd65626a2017-08-15 17:02:47 +02001761static struct qeth_cmd_buffer *qeth_sbp_build_cmd(struct qeth_card *card,
1762 enum qeth_ipa_sbp_cmd sbp_cmd,
1763 unsigned int cmd_length)
Eugene Crosser9c23f4da2015-05-18 14:27:56 +02001764{
Julian Wiedmannd65626a2017-08-15 17:02:47 +02001765 enum qeth_ipa_cmds ipa_cmd = (card->info.type == QETH_CARD_TYPE_IQD) ?
1766 IPA_CMD_SETBRIDGEPORT_IQD :
1767 IPA_CMD_SETBRIDGEPORT_OSA;
1768 struct qeth_cmd_buffer *iob;
1769 struct qeth_ipa_cmd *cmd;
1770
1771 iob = qeth_get_ipacmd_buffer(card, ipa_cmd, 0);
1772 if (!iob)
1773 return iob;
1774 cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
1775 cmd->data.sbp.hdr.cmdlength = sizeof(struct qeth_ipacmd_sbp_hdr) +
1776 cmd_length;
1777 cmd->data.sbp.hdr.command_code = sbp_cmd;
1778 cmd->data.sbp.hdr.used_total = 1;
1779 cmd->data.sbp.hdr.seq_no = 1;
1780 return iob;
Eugene Crosser9c23f4da2015-05-18 14:27:56 +02001781}
1782
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001783static int qeth_bridgeport_query_support_cb(struct qeth_card *card,
1784 struct qeth_reply *reply, unsigned long data)
1785{
1786 struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data;
1787 struct _qeth_sbp_cbctl *cbctl = (struct _qeth_sbp_cbctl *)reply->param;
1788 QETH_CARD_TEXT(card, 2, "brqsupcb");
1789 cbctl->ipa_rc = cmd->hdr.return_code;
1790 cbctl->cmd_rc = cmd->data.sbp.hdr.return_code;
1791 if ((cbctl->ipa_rc == 0) && (cbctl->cmd_rc == 0)) {
1792 cbctl->data.supported =
1793 cmd->data.sbp.data.query_cmds_supp.supported_cmds;
1794 } else {
1795 cbctl->data.supported = 0;
1796 }
1797 return 0;
1798}
1799
1800/**
1801 * qeth_bridgeport_query_support() - store bitmask of supported subfunctions.
1802 * @card: qeth_card structure pointer.
1803 *
1804 * Sets bitmask of supported setbridgeport subfunctions in the qeth_card
1805 * strucutre: card->options.sbp.supported_funcs.
1806 */
Eugene Crosserc044dc22014-01-29 09:23:48 +01001807static void qeth_bridgeport_query_support(struct qeth_card *card)
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001808{
1809 struct qeth_cmd_buffer *iob;
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001810 struct _qeth_sbp_cbctl cbctl;
1811
1812 QETH_CARD_TEXT(card, 2, "brqsuppo");
Julian Wiedmannd65626a2017-08-15 17:02:47 +02001813 iob = qeth_sbp_build_cmd(card, IPA_SBP_QUERY_COMMANDS_SUPPORTED,
1814 sizeof(struct qeth_sbp_query_cmds_supp));
Thomas Richter1aec42b2015-01-21 13:39:10 +01001815 if (!iob)
1816 return;
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001817 if (qeth_send_ipa_cmd(card, iob, qeth_bridgeport_query_support_cb,
1818 (void *)&cbctl) ||
1819 qeth_bridgeport_makerc(card, &cbctl,
1820 IPA_SBP_QUERY_COMMANDS_SUPPORTED)) {
1821 /* non-zero makerc signifies failure, and produce messages */
1822 card->options.sbp.role = QETH_SBP_ROLE_NONE;
1823 return;
1824 }
1825 card->options.sbp.supported_funcs = cbctl.data.supported;
1826}
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001827
1828static int qeth_bridgeport_query_ports_cb(struct qeth_card *card,
1829 struct qeth_reply *reply, unsigned long data)
1830{
1831 struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data;
1832 struct qeth_sbp_query_ports *qports = &cmd->data.sbp.data.query_ports;
1833 struct _qeth_sbp_cbctl *cbctl = (struct _qeth_sbp_cbctl *)reply->param;
1834
1835 QETH_CARD_TEXT(card, 2, "brqprtcb");
1836 cbctl->ipa_rc = cmd->hdr.return_code;
1837 cbctl->cmd_rc = cmd->data.sbp.hdr.return_code;
1838 if ((cbctl->ipa_rc != 0) || (cbctl->cmd_rc != 0))
1839 return 0;
1840 if (qports->entry_length != sizeof(struct qeth_sbp_port_entry)) {
1841 cbctl->cmd_rc = 0xffff;
1842 QETH_CARD_TEXT_(card, 2, "SBPs%04x", qports->entry_length);
1843 return 0;
1844 }
1845 /* first entry contains the state of the local port */
1846 if (qports->num_entries > 0) {
1847 if (cbctl->data.qports.role)
1848 *cbctl->data.qports.role = qports->entry[0].role;
1849 if (cbctl->data.qports.state)
1850 *cbctl->data.qports.state = qports->entry[0].state;
1851 }
1852 return 0;
1853}
1854
1855/**
1856 * qeth_bridgeport_query_ports() - query local bridgeport status.
1857 * @card: qeth_card structure pointer.
1858 * @role: Role of the port: 0-none, 1-primary, 2-secondary.
1859 * @state: State of the port: 0-inactive, 1-standby, 2-active.
1860 *
1861 * Returns negative errno-compatible error indication or 0 on success.
1862 *
1863 * 'role' and 'state' are not updated in case of hardware operation failure.
1864 */
1865int qeth_bridgeport_query_ports(struct qeth_card *card,
1866 enum qeth_sbp_roles *role, enum qeth_sbp_states *state)
1867{
1868 int rc = 0;
1869 struct qeth_cmd_buffer *iob;
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001870 struct _qeth_sbp_cbctl cbctl = {
1871 .data = {
1872 .qports = {
1873 .role = role,
1874 .state = state,
1875 },
1876 },
1877 };
1878
1879 QETH_CARD_TEXT(card, 2, "brqports");
1880 if (!(card->options.sbp.supported_funcs & IPA_SBP_QUERY_BRIDGE_PORTS))
1881 return -EOPNOTSUPP;
Julian Wiedmannd65626a2017-08-15 17:02:47 +02001882 iob = qeth_sbp_build_cmd(card, IPA_SBP_QUERY_BRIDGE_PORTS, 0);
Thomas Richter1aec42b2015-01-21 13:39:10 +01001883 if (!iob)
1884 return -ENOMEM;
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001885 rc = qeth_send_ipa_cmd(card, iob, qeth_bridgeport_query_ports_cb,
1886 (void *)&cbctl);
Eugene Crosserc88394e2015-05-18 14:27:53 +02001887 if (rc < 0)
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001888 return rc;
Eugene Crosserc88394e2015-05-18 14:27:53 +02001889 return qeth_bridgeport_makerc(card, &cbctl, IPA_SBP_QUERY_BRIDGE_PORTS);
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001890}
1891EXPORT_SYMBOL_GPL(qeth_bridgeport_query_ports);
1892
1893static int qeth_bridgeport_set_cb(struct qeth_card *card,
1894 struct qeth_reply *reply, unsigned long data)
1895{
1896 struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *)data;
1897 struct _qeth_sbp_cbctl *cbctl = (struct _qeth_sbp_cbctl *)reply->param;
1898 QETH_CARD_TEXT(card, 2, "brsetrcb");
1899 cbctl->ipa_rc = cmd->hdr.return_code;
1900 cbctl->cmd_rc = cmd->data.sbp.hdr.return_code;
1901 return 0;
1902}
1903
1904/**
1905 * qeth_bridgeport_setrole() - Assign primary role to the port.
1906 * @card: qeth_card structure pointer.
1907 * @role: Role to assign.
1908 *
1909 * Returns negative errno-compatible error indication or 0 on success.
1910 */
1911int qeth_bridgeport_setrole(struct qeth_card *card, enum qeth_sbp_roles role)
1912{
1913 int rc = 0;
1914 int cmdlength;
1915 struct qeth_cmd_buffer *iob;
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001916 struct _qeth_sbp_cbctl cbctl;
1917 enum qeth_ipa_sbp_cmd setcmd;
1918
1919 QETH_CARD_TEXT(card, 2, "brsetrol");
1920 switch (role) {
1921 case QETH_SBP_ROLE_NONE:
1922 setcmd = IPA_SBP_RESET_BRIDGE_PORT_ROLE;
Julian Wiedmannd65626a2017-08-15 17:02:47 +02001923 cmdlength = sizeof(struct qeth_sbp_reset_role);
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001924 break;
1925 case QETH_SBP_ROLE_PRIMARY:
1926 setcmd = IPA_SBP_SET_PRIMARY_BRIDGE_PORT;
Julian Wiedmannd65626a2017-08-15 17:02:47 +02001927 cmdlength = sizeof(struct qeth_sbp_set_primary);
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001928 break;
1929 case QETH_SBP_ROLE_SECONDARY:
1930 setcmd = IPA_SBP_SET_SECONDARY_BRIDGE_PORT;
Julian Wiedmannd65626a2017-08-15 17:02:47 +02001931 cmdlength = sizeof(struct qeth_sbp_set_secondary);
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001932 break;
1933 default:
1934 return -EINVAL;
1935 }
1936 if (!(card->options.sbp.supported_funcs & setcmd))
1937 return -EOPNOTSUPP;
Julian Wiedmannd65626a2017-08-15 17:02:47 +02001938 iob = qeth_sbp_build_cmd(card, setcmd, cmdlength);
Thomas Richter1aec42b2015-01-21 13:39:10 +01001939 if (!iob)
1940 return -ENOMEM;
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001941 rc = qeth_send_ipa_cmd(card, iob, qeth_bridgeport_set_cb,
1942 (void *)&cbctl);
Eugene Crosserc88394e2015-05-18 14:27:53 +02001943 if (rc < 0)
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001944 return rc;
Eugene Crosserc88394e2015-05-18 14:27:53 +02001945 return qeth_bridgeport_makerc(card, &cbctl, setcmd);
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001946}
1947
Eugene Crosser9f48b9d2014-01-14 15:54:13 +01001948/**
1949 * qeth_anset_makerc() - derive "traditional" error from hardware codes.
1950 * @card: qeth_card structure pointer, for debug messages.
1951 *
1952 * Returns negative errno-compatible error indication or 0 on success.
1953 */
1954static int qeth_anset_makerc(struct qeth_card *card, int pnso_rc, u16 response)
1955{
1956 int rc;
1957
1958 if (pnso_rc == 0)
1959 switch (response) {
1960 case 0x0001:
1961 rc = 0;
1962 break;
1963 case 0x0004:
1964 case 0x0100:
1965 case 0x0106:
Eugene Crosserffb95252015-05-18 14:27:58 +02001966 rc = -EOPNOTSUPP;
Eugene Crosser9f48b9d2014-01-14 15:54:13 +01001967 dev_err(&card->gdev->dev,
1968 "Setting address notification failed\n");
1969 break;
1970 case 0x0107:
1971 rc = -EAGAIN;
1972 break;
1973 default:
1974 rc = -EIO;
1975 }
1976 else
1977 rc = -EIO;
1978
1979 if (rc) {
1980 QETH_CARD_TEXT_(card, 2, "SBPp%04x", pnso_rc);
1981 QETH_CARD_TEXT_(card, 2, "SBPr%04x", response);
1982 }
1983 return rc;
1984}
1985
1986static void qeth_bridgeport_an_set_cb(void *priv,
1987 enum qdio_brinfo_entry_type type, void *entry)
1988{
1989 struct qeth_card *card = (struct qeth_card *)priv;
1990 struct qdio_brinfo_entry_l2 *l2entry;
1991 u8 code;
1992
1993 if (type != l2_addr_lnid) {
1994 WARN_ON_ONCE(1);
1995 return;
1996 }
1997
1998 l2entry = (struct qdio_brinfo_entry_l2 *)entry;
1999 code = IPA_ADDR_CHANGE_CODE_MACADDR;
2000 if (l2entry->addr_lnid.lnid)
2001 code |= IPA_ADDR_CHANGE_CODE_VLANID;
2002 qeth_bridge_emit_host_event(card, anev_reg_unreg, code,
2003 (struct net_if_token *)&l2entry->nit,
2004 (struct mac_addr_lnid *)&l2entry->addr_lnid);
2005}
2006
2007/**
2008 * qeth_bridgeport_an_set() - Enable or disable bridgeport address notification
2009 * @card: qeth_card structure pointer.
2010 * @enable: 0 - disable, non-zero - enable notifications
2011 *
2012 * Returns negative errno-compatible error indication or 0 on success.
2013 *
2014 * On enable, emits a series of address notifications udev events for all
2015 * currently registered hosts.
2016 */
2017int qeth_bridgeport_an_set(struct qeth_card *card, int enable)
2018{
2019 int rc;
2020 u16 response;
2021 struct ccw_device *ddev;
2022 struct subchannel_id schid;
2023
2024 if (!card)
2025 return -EINVAL;
2026 if (!card->options.sbp.supported_funcs)
2027 return -EOPNOTSUPP;
2028 ddev = CARD_DDEV(card);
2029 ccw_device_get_schid(ddev, &schid);
2030
2031 if (enable) {
2032 qeth_bridge_emit_host_event(card, anev_reset, 0, NULL, NULL);
2033 rc = qdio_pnso_brinfo(schid, 1, &response,
2034 qeth_bridgeport_an_set_cb, card);
2035 } else
2036 rc = qdio_pnso_brinfo(schid, 0, &response, NULL, NULL);
2037 return qeth_anset_makerc(card, rc, response);
2038}
2039EXPORT_SYMBOL_GPL(qeth_bridgeport_an_set);
2040
Hans Wippelcaa1f0b2017-09-18 21:18:15 +02002041static bool qeth_bridgeport_is_in_use(struct qeth_card *card)
2042{
2043 return (card->options.sbp.role || card->options.sbp.reflect_promisc ||
2044 card->options.sbp.hostnotification);
2045}
2046
Hans Wippela45b3fa2017-09-18 21:18:14 +02002047/* VNIC Characteristics support */
2048
2049/* handle VNICC IPA command return codes; convert to error codes */
2050static int qeth_l2_vnicc_makerc(struct qeth_card *card, int ipa_rc)
2051{
2052 int rc;
2053
2054 switch (ipa_rc) {
2055 case IPA_RC_SUCCESS:
2056 return ipa_rc;
2057 case IPA_RC_L2_UNSUPPORTED_CMD:
2058 case IPA_RC_NOTSUPP:
2059 rc = -EOPNOTSUPP;
2060 break;
2061 case IPA_RC_VNICC_OOSEQ:
2062 rc = -EALREADY;
2063 break;
2064 case IPA_RC_VNICC_VNICBP:
2065 rc = -EBUSY;
2066 break;
2067 case IPA_RC_L2_ADDR_TABLE_FULL:
2068 rc = -ENOSPC;
2069 break;
2070 case IPA_RC_L2_MAC_NOT_AUTH_BY_ADP:
2071 rc = -EACCES;
2072 break;
2073 default:
2074 rc = -EIO;
2075 }
2076
2077 QETH_CARD_TEXT_(card, 2, "err%04x", ipa_rc);
2078 return rc;
2079}
2080
2081/* generic VNICC request call back control */
2082struct _qeth_l2_vnicc_request_cbctl {
2083 u32 sub_cmd;
Hans Wippelcaa1f0b2017-09-18 21:18:15 +02002084 struct {
2085 u32 vnic_char;
Hans Wippel349d13d2017-09-18 21:18:16 +02002086 u32 timeout;
Hans Wippelcaa1f0b2017-09-18 21:18:15 +02002087 } param;
2088 struct {
Hans Wippel349d13d2017-09-18 21:18:16 +02002089 union{
2090 u32 *sup_cmds;
2091 u32 *timeout;
2092 };
Hans Wippelcaa1f0b2017-09-18 21:18:15 +02002093 } result;
Hans Wippela45b3fa2017-09-18 21:18:14 +02002094};
2095
2096/* generic VNICC request call back */
2097static int qeth_l2_vnicc_request_cb(struct qeth_card *card,
2098 struct qeth_reply *reply,
2099 unsigned long data)
2100{
Hans Wippelcaa1f0b2017-09-18 21:18:15 +02002101 struct _qeth_l2_vnicc_request_cbctl *cbctl =
2102 (struct _qeth_l2_vnicc_request_cbctl *) reply->param;
Hans Wippela45b3fa2017-09-18 21:18:14 +02002103 struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data;
2104 struct qeth_ipacmd_vnicc *rep = &cmd->data.vnicc;
2105
2106 QETH_CARD_TEXT(card, 2, "vniccrcb");
2107 if (cmd->hdr.return_code)
2108 return 0;
2109 /* return results to caller */
2110 card->options.vnicc.sup_chars = rep->hdr.sup;
2111 card->options.vnicc.cur_chars = rep->hdr.cur;
2112
Hans Wippelcaa1f0b2017-09-18 21:18:15 +02002113 if (cbctl->sub_cmd == IPA_VNICC_QUERY_CMDS)
2114 *cbctl->result.sup_cmds = rep->query_cmds.sup_cmds;
2115
Hans Wippel349d13d2017-09-18 21:18:16 +02002116 if (cbctl->sub_cmd == IPA_VNICC_GET_TIMEOUT)
2117 *cbctl->result.timeout = rep->getset_timeout.timeout;
2118
Hans Wippela45b3fa2017-09-18 21:18:14 +02002119 return 0;
2120}
2121
2122/* generic VNICC request */
2123static int qeth_l2_vnicc_request(struct qeth_card *card,
2124 struct _qeth_l2_vnicc_request_cbctl *cbctl)
2125{
2126 struct qeth_ipacmd_vnicc *req;
2127 struct qeth_cmd_buffer *iob;
2128 struct qeth_ipa_cmd *cmd;
2129 int rc;
2130
2131 QETH_CARD_TEXT(card, 2, "vniccreq");
2132
2133 /* get new buffer for request */
2134 iob = qeth_get_ipacmd_buffer(card, IPA_CMD_VNICC, 0);
2135 if (!iob)
2136 return -ENOMEM;
2137
2138 /* create header for request */
2139 cmd = (struct qeth_ipa_cmd *)(iob->data + IPA_PDU_HEADER_SIZE);
2140 req = &cmd->data.vnicc;
2141
2142 /* create sub command header for request */
2143 req->sub_hdr.data_length = sizeof(req->sub_hdr);
2144 req->sub_hdr.sub_command = cbctl->sub_cmd;
2145
2146 /* create sub command specific request fields */
2147 switch (cbctl->sub_cmd) {
2148 case IPA_VNICC_QUERY_CHARS:
2149 break;
Hans Wippelcaa1f0b2017-09-18 21:18:15 +02002150 case IPA_VNICC_QUERY_CMDS:
2151 req->sub_hdr.data_length += sizeof(req->query_cmds);
2152 req->query_cmds.vnic_char = cbctl->param.vnic_char;
2153 break;
2154 case IPA_VNICC_ENABLE:
2155 case IPA_VNICC_DISABLE:
2156 req->sub_hdr.data_length += sizeof(req->set_char);
2157 req->set_char.vnic_char = cbctl->param.vnic_char;
2158 break;
Hans Wippel349d13d2017-09-18 21:18:16 +02002159 case IPA_VNICC_SET_TIMEOUT:
2160 req->getset_timeout.timeout = cbctl->param.timeout;
2161 /* fallthrough */
2162 case IPA_VNICC_GET_TIMEOUT:
2163 req->sub_hdr.data_length += sizeof(req->getset_timeout);
2164 req->getset_timeout.vnic_char = cbctl->param.vnic_char;
2165 break;
Hans Wippela45b3fa2017-09-18 21:18:14 +02002166 default:
2167 qeth_release_buffer(iob->channel, iob);
2168 return -EOPNOTSUPP;
2169 }
2170
2171 /* send request */
2172 rc = qeth_send_ipa_cmd(card, iob, qeth_l2_vnicc_request_cb,
2173 (void *) cbctl);
2174
2175 return qeth_l2_vnicc_makerc(card, rc);
2176}
2177
2178/* VNICC query VNIC characteristics request */
2179static int qeth_l2_vnicc_query_chars(struct qeth_card *card)
2180{
2181 struct _qeth_l2_vnicc_request_cbctl cbctl;
2182
2183 /* prepare callback control */
2184 cbctl.sub_cmd = IPA_VNICC_QUERY_CHARS;
2185
2186 QETH_CARD_TEXT(card, 2, "vniccqch");
2187 return qeth_l2_vnicc_request(card, &cbctl);
2188}
2189
Hans Wippelcaa1f0b2017-09-18 21:18:15 +02002190/* VNICC query sub commands request */
2191static int qeth_l2_vnicc_query_cmds(struct qeth_card *card, u32 vnic_char,
2192 u32 *sup_cmds)
2193{
2194 struct _qeth_l2_vnicc_request_cbctl cbctl;
2195
2196 /* prepare callback control */
2197 cbctl.sub_cmd = IPA_VNICC_QUERY_CMDS;
2198 cbctl.param.vnic_char = vnic_char;
2199 cbctl.result.sup_cmds = sup_cmds;
2200
2201 QETH_CARD_TEXT(card, 2, "vniccqcm");
2202 return qeth_l2_vnicc_request(card, &cbctl);
2203}
2204
2205/* VNICC enable/disable characteristic request */
2206static int qeth_l2_vnicc_set_char(struct qeth_card *card, u32 vnic_char,
2207 u32 cmd)
2208{
2209 struct _qeth_l2_vnicc_request_cbctl cbctl;
2210
2211 /* prepare callback control */
2212 cbctl.sub_cmd = cmd;
2213 cbctl.param.vnic_char = vnic_char;
2214
2215 QETH_CARD_TEXT(card, 2, "vniccedc");
2216 return qeth_l2_vnicc_request(card, &cbctl);
2217}
2218
Hans Wippel349d13d2017-09-18 21:18:16 +02002219/* VNICC get/set timeout for characteristic request */
2220static int qeth_l2_vnicc_getset_timeout(struct qeth_card *card, u32 vnicc,
2221 u32 cmd, u32 *timeout)
2222{
2223 struct _qeth_l2_vnicc_request_cbctl cbctl;
2224
2225 /* prepare callback control */
2226 cbctl.sub_cmd = cmd;
2227 cbctl.param.vnic_char = vnicc;
2228 if (cmd == IPA_VNICC_SET_TIMEOUT)
2229 cbctl.param.timeout = *timeout;
2230 if (cmd == IPA_VNICC_GET_TIMEOUT)
2231 cbctl.result.timeout = timeout;
2232
2233 QETH_CARD_TEXT(card, 2, "vniccgst");
2234 return qeth_l2_vnicc_request(card, &cbctl);
2235}
2236
Hans Wippelcaa1f0b2017-09-18 21:18:15 +02002237/* set current VNICC flag state; called from sysfs store function */
2238int qeth_l2_vnicc_set_state(struct qeth_card *card, u32 vnicc, bool state)
2239{
2240 int rc = 0;
2241 u32 cmd;
2242
2243 QETH_CARD_TEXT(card, 2, "vniccsch");
2244
2245 /* do not change anything if BridgePort is enabled */
2246 if (qeth_bridgeport_is_in_use(card))
2247 return -EBUSY;
2248
2249 /* check if characteristic and enable/disable are supported */
2250 if (!(card->options.vnicc.sup_chars & vnicc) ||
2251 !(card->options.vnicc.set_char_sup & vnicc))
2252 return -EOPNOTSUPP;
2253
2254 /* set enable/disable command and store wanted characteristic */
2255 if (state) {
2256 cmd = IPA_VNICC_ENABLE;
2257 card->options.vnicc.wanted_chars |= vnicc;
2258 } else {
2259 cmd = IPA_VNICC_DISABLE;
2260 card->options.vnicc.wanted_chars &= ~vnicc;
2261 }
2262
2263 /* do we need to do anything? */
2264 if (card->options.vnicc.cur_chars == card->options.vnicc.wanted_chars)
2265 return rc;
2266
2267 /* if card is not ready, simply stop here */
2268 if (!qeth_card_hw_is_reachable(card)) {
2269 if (state)
2270 card->options.vnicc.cur_chars |= vnicc;
2271 else
2272 card->options.vnicc.cur_chars &= ~vnicc;
2273 return rc;
2274 }
2275
2276 rc = qeth_l2_vnicc_set_char(card, vnicc, cmd);
2277 if (rc)
2278 card->options.vnicc.wanted_chars =
2279 card->options.vnicc.cur_chars;
Hans Wippel349d13d2017-09-18 21:18:16 +02002280 else {
2281 /* successful online VNICC change; handle special cases */
2282 if (state && vnicc == QETH_VNICC_RX_BCAST)
2283 card->options.vnicc.rx_bcast_enabled = true;
2284 if (!state && vnicc == QETH_VNICC_LEARNING)
2285 qeth_l2_vnicc_recover_timeout(card, vnicc,
2286 &card->options.vnicc.learning_timeout);
2287 }
Hans Wippelcaa1f0b2017-09-18 21:18:15 +02002288
2289 return rc;
2290}
2291
2292/* get current VNICC flag state; called from sysfs show function */
2293int qeth_l2_vnicc_get_state(struct qeth_card *card, u32 vnicc, bool *state)
2294{
2295 int rc = 0;
2296
2297 QETH_CARD_TEXT(card, 2, "vniccgch");
2298
2299 /* do not get anything if BridgePort is enabled */
2300 if (qeth_bridgeport_is_in_use(card))
2301 return -EBUSY;
2302
2303 /* check if characteristic is supported */
2304 if (!(card->options.vnicc.sup_chars & vnicc))
2305 return -EOPNOTSUPP;
2306
2307 /* if card is ready, query current VNICC state */
2308 if (qeth_card_hw_is_reachable(card))
2309 rc = qeth_l2_vnicc_query_chars(card);
2310
2311 *state = (card->options.vnicc.cur_chars & vnicc) ? true : false;
2312 return rc;
2313}
2314
Hans Wippel349d13d2017-09-18 21:18:16 +02002315/* set VNICC timeout; called from sysfs store function. Currently, only learning
2316 * supports timeout
2317 */
2318int qeth_l2_vnicc_set_timeout(struct qeth_card *card, u32 timeout)
2319{
2320 int rc = 0;
2321
2322 QETH_CARD_TEXT(card, 2, "vniccsto");
2323
2324 /* do not change anything if BridgePort is enabled */
2325 if (qeth_bridgeport_is_in_use(card))
2326 return -EBUSY;
2327
2328 /* check if characteristic and set_timeout are supported */
2329 if (!(card->options.vnicc.sup_chars & QETH_VNICC_LEARNING) ||
2330 !(card->options.vnicc.getset_timeout_sup & QETH_VNICC_LEARNING))
2331 return -EOPNOTSUPP;
2332
2333 /* do we need to do anything? */
2334 if (card->options.vnicc.learning_timeout == timeout)
2335 return rc;
2336
2337 /* if card is not ready, simply store the value internally and return */
2338 if (!qeth_card_hw_is_reachable(card)) {
2339 card->options.vnicc.learning_timeout = timeout;
2340 return rc;
2341 }
2342
2343 /* send timeout value to card; if successful, store value internally */
2344 rc = qeth_l2_vnicc_getset_timeout(card, QETH_VNICC_LEARNING,
2345 IPA_VNICC_SET_TIMEOUT, &timeout);
2346 if (!rc)
2347 card->options.vnicc.learning_timeout = timeout;
2348
2349 return rc;
2350}
2351
2352/* get current VNICC timeout; called from sysfs show function. Currently, only
2353 * learning supports timeout
2354 */
2355int qeth_l2_vnicc_get_timeout(struct qeth_card *card, u32 *timeout)
2356{
2357 int rc = 0;
2358
2359 QETH_CARD_TEXT(card, 2, "vniccgto");
2360
2361 /* do not get anything if BridgePort is enabled */
2362 if (qeth_bridgeport_is_in_use(card))
2363 return -EBUSY;
2364
2365 /* check if characteristic and get_timeout are supported */
2366 if (!(card->options.vnicc.sup_chars & QETH_VNICC_LEARNING) ||
2367 !(card->options.vnicc.getset_timeout_sup & QETH_VNICC_LEARNING))
2368 return -EOPNOTSUPP;
2369 /* if card is ready, get timeout. Otherwise, just return stored value */
2370 *timeout = card->options.vnicc.learning_timeout;
2371 if (qeth_card_hw_is_reachable(card))
2372 rc = qeth_l2_vnicc_getset_timeout(card, QETH_VNICC_LEARNING,
2373 IPA_VNICC_GET_TIMEOUT,
2374 timeout);
2375
2376 return rc;
2377}
2378
Hans Wippelcaa1f0b2017-09-18 21:18:15 +02002379/* check if VNICC is currently enabled */
2380bool qeth_l2_vnicc_is_in_use(struct qeth_card *card)
2381{
2382 /* if everything is turned off, VNICC is not active */
2383 if (!card->options.vnicc.cur_chars)
2384 return false;
2385 /* default values are only OK if rx_bcast was not enabled by user
2386 * or the card is offline.
2387 */
2388 if (card->options.vnicc.cur_chars == QETH_VNICC_DEFAULT) {
2389 if (!card->options.vnicc.rx_bcast_enabled ||
2390 !qeth_card_hw_is_reachable(card))
2391 return false;
2392 }
2393 return true;
2394}
2395
Hans Wippel349d13d2017-09-18 21:18:16 +02002396/* recover user timeout setting */
2397static bool qeth_l2_vnicc_recover_timeout(struct qeth_card *card, u32 vnicc,
2398 u32 *timeout)
2399{
2400 if (card->options.vnicc.sup_chars & vnicc &&
2401 card->options.vnicc.getset_timeout_sup & vnicc &&
2402 !qeth_l2_vnicc_getset_timeout(card, vnicc, IPA_VNICC_SET_TIMEOUT,
2403 timeout))
2404 return false;
2405 *timeout = QETH_VNICC_DEFAULT_TIMEOUT;
2406 return true;
2407}
2408
Hans Wippelcaa1f0b2017-09-18 21:18:15 +02002409/* recover user characteristic setting */
2410static bool qeth_l2_vnicc_recover_char(struct qeth_card *card, u32 vnicc,
2411 bool enable)
2412{
2413 u32 cmd = enable ? IPA_VNICC_ENABLE : IPA_VNICC_DISABLE;
2414
2415 if (card->options.vnicc.sup_chars & vnicc &&
2416 card->options.vnicc.set_char_sup & vnicc &&
2417 !qeth_l2_vnicc_set_char(card, vnicc, cmd))
2418 return false;
2419 card->options.vnicc.wanted_chars &= ~vnicc;
2420 card->options.vnicc.wanted_chars |= QETH_VNICC_DEFAULT & vnicc;
2421 return true;
2422}
2423
Hans Wippela45b3fa2017-09-18 21:18:14 +02002424/* (re-)initialize VNICC */
2425static void qeth_l2_vnicc_init(struct qeth_card *card)
2426{
Hans Wippel349d13d2017-09-18 21:18:16 +02002427 u32 *timeout = &card->options.vnicc.learning_timeout;
Hans Wippelcaa1f0b2017-09-18 21:18:15 +02002428 unsigned int chars_len, i;
2429 unsigned long chars_tmp;
2430 u32 sup_cmds, vnicc;
2431 bool enable, error;
2432
Hans Wippela45b3fa2017-09-18 21:18:14 +02002433 QETH_CARD_TEXT(card, 2, "vniccini");
Hans Wippelcaa1f0b2017-09-18 21:18:15 +02002434 /* reset rx_bcast */
2435 card->options.vnicc.rx_bcast_enabled = 0;
Hans Wippela45b3fa2017-09-18 21:18:14 +02002436 /* initial query and storage of VNIC characteristics */
2437 if (qeth_l2_vnicc_query_chars(card)) {
Hans Wippel349d13d2017-09-18 21:18:16 +02002438 if (card->options.vnicc.wanted_chars != QETH_VNICC_DEFAULT ||
2439 *timeout != QETH_VNICC_DEFAULT_TIMEOUT)
Hans Wippelcaa1f0b2017-09-18 21:18:15 +02002440 dev_err(&card->gdev->dev, "Configuring the VNIC characteristics failed\n");
2441 /* fail quietly if user didn't change the default config */
Hans Wippela45b3fa2017-09-18 21:18:14 +02002442 card->options.vnicc.sup_chars = 0;
2443 card->options.vnicc.cur_chars = 0;
Hans Wippelcaa1f0b2017-09-18 21:18:15 +02002444 card->options.vnicc.wanted_chars = QETH_VNICC_DEFAULT;
2445 return;
Hans Wippela45b3fa2017-09-18 21:18:14 +02002446 }
Hans Wippelcaa1f0b2017-09-18 21:18:15 +02002447 /* get supported commands for each supported characteristic */
2448 chars_tmp = card->options.vnicc.sup_chars;
2449 chars_len = sizeof(card->options.vnicc.sup_chars) * BITS_PER_BYTE;
2450 for_each_set_bit(i, &chars_tmp, chars_len) {
2451 vnicc = BIT(i);
2452 qeth_l2_vnicc_query_cmds(card, vnicc, &sup_cmds);
Hans Wippel349d13d2017-09-18 21:18:16 +02002453 if (!(sup_cmds & IPA_VNICC_SET_TIMEOUT) ||
2454 !(sup_cmds & IPA_VNICC_GET_TIMEOUT))
2455 card->options.vnicc.getset_timeout_sup &= ~vnicc;
Hans Wippelcaa1f0b2017-09-18 21:18:15 +02002456 if (!(sup_cmds & IPA_VNICC_ENABLE) ||
2457 !(sup_cmds & IPA_VNICC_DISABLE))
2458 card->options.vnicc.set_char_sup &= ~vnicc;
2459 }
2460 /* enforce assumed default values and recover settings, if changed */
Hans Wippel349d13d2017-09-18 21:18:16 +02002461 error = qeth_l2_vnicc_recover_timeout(card, QETH_VNICC_LEARNING,
2462 timeout);
Hans Wippelcaa1f0b2017-09-18 21:18:15 +02002463 chars_tmp = card->options.vnicc.wanted_chars ^ QETH_VNICC_DEFAULT;
2464 chars_tmp |= QETH_VNICC_BRIDGE_INVISIBLE;
2465 chars_len = sizeof(card->options.vnicc.wanted_chars) * BITS_PER_BYTE;
2466 for_each_set_bit(i, &chars_tmp, chars_len) {
2467 vnicc = BIT(i);
2468 enable = card->options.vnicc.wanted_chars & vnicc;
2469 error |= qeth_l2_vnicc_recover_char(card, vnicc, enable);
2470 }
2471 if (error)
2472 dev_err(&card->gdev->dev, "Configuring the VNIC characteristics failed\n");
2473}
2474
2475/* configure default values of VNIC characteristics */
2476static void qeth_l2_vnicc_set_defaults(struct qeth_card *card)
2477{
2478 /* characteristics values */
2479 card->options.vnicc.sup_chars = QETH_VNICC_ALL;
2480 card->options.vnicc.cur_chars = QETH_VNICC_DEFAULT;
Hans Wippel349d13d2017-09-18 21:18:16 +02002481 card->options.vnicc.learning_timeout = QETH_VNICC_DEFAULT_TIMEOUT;
Hans Wippelcaa1f0b2017-09-18 21:18:15 +02002482 /* supported commands */
2483 card->options.vnicc.set_char_sup = QETH_VNICC_ALL;
Hans Wippel349d13d2017-09-18 21:18:16 +02002484 card->options.vnicc.getset_timeout_sup = QETH_VNICC_LEARNING;
Hans Wippelcaa1f0b2017-09-18 21:18:15 +02002485 /* settings wanted by users */
2486 card->options.vnicc.wanted_chars = QETH_VNICC_DEFAULT;
Hans Wippela45b3fa2017-09-18 21:18:14 +02002487}
2488
Frank Blaschka4a71df52008-02-15 09:19:42 +01002489module_init(qeth_l2_init);
2490module_exit(qeth_l2_exit);
2491MODULE_AUTHOR("Frank Blaschka <frank.blaschka@de.ibm.com>");
2492MODULE_DESCRIPTION("qeth layer 2 discipline");
2493MODULE_LICENSE("GPL");