blob: b7b9d5cbe4d5d1f51fcabb79c3faef8d3de12433 [file] [log] [blame]
Frank Blaschka4a71df52008-02-15 09:19:42 +01001/*
Frank Blaschkabbcfcdc2009-06-16 10:30:31 +02002 * Copyright IBM Corp. 2007, 2009
Frank Blaschka4a71df52008-02-15 09:19:42 +01003 * Author(s): Utz Bacher <utz.bacher@de.ibm.com>,
4 * Frank Pavlic <fpavlic@de.ibm.com>,
5 * Thomas Spatzier <tspat@de.ibm.com>,
6 * Frank Blaschka <frank.blaschka@de.ibm.com>
7 */
8
Frank Blaschka74eacdb2008-12-25 13:39:49 +01009#define KMSG_COMPONENT "qeth"
10#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
11
Frank Blaschka4a71df52008-02-15 09:19:42 +010012#include <linux/module.h>
13#include <linux/moduleparam.h>
14#include <linux/string.h>
15#include <linux/errno.h>
16#include <linux/kernel.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090017#include <linux/slab.h>
Frank Blaschka4a71df52008-02-15 09:19:42 +010018#include <linux/etherdevice.h>
19#include <linux/mii.h>
20#include <linux/ip.h>
Jiri Pirkoccffad252009-05-22 23:22:17 +000021#include <linux/list.h>
Frank Blaschka4a71df52008-02-15 09:19:42 +010022
Frank Blaschka4a71df52008-02-15 09:19:42 +010023#include "qeth_core.h"
Eugene Crosserb4d72c02014-01-14 15:54:11 +010024#include "qeth_l2.h"
Frank Blaschka4a71df52008-02-15 09:19:42 +010025
Frank Blaschka4a71df52008-02-15 09:19:42 +010026static int qeth_l2_set_offline(struct ccwgroup_device *);
27static int qeth_l2_stop(struct net_device *);
28static int qeth_l2_send_delmac(struct qeth_card *, __u8 *);
29static int qeth_l2_send_setdelmac(struct qeth_card *, __u8 *,
Eugene Crosserefbbc1d2015-01-21 13:39:09 +010030 enum qeth_ipa_cmds);
Frank Blaschka4a71df52008-02-15 09:19:42 +010031static void qeth_l2_set_multicast_list(struct net_device *);
32static int qeth_l2_recover(void *);
Eugene Crosserc044dc22014-01-29 09:23:48 +010033static void qeth_bridgeport_query_support(struct qeth_card *card);
34static void qeth_bridge_state_change(struct qeth_card *card,
35 struct qeth_ipa_cmd *cmd);
36static void qeth_bridge_host_event(struct qeth_card *card,
37 struct qeth_ipa_cmd *cmd);
Frank Blaschka4a71df52008-02-15 09:19:42 +010038
39static int qeth_l2_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
40{
Heiko Carstens509e2562008-07-26 02:24:10 -070041 struct qeth_card *card = dev->ml_priv;
Frank Blaschka4a71df52008-02-15 09:19:42 +010042 struct mii_ioctl_data *mii_data;
43 int rc = 0;
44
45 if (!card)
46 return -ENODEV;
47
48 if ((card->state != CARD_STATE_UP) &&
49 (card->state != CARD_STATE_SOFTSETUP))
50 return -ENODEV;
51
52 if (card->info.type == QETH_CARD_TYPE_OSN)
53 return -EPERM;
54
55 switch (cmd) {
56 case SIOC_QETH_ADP_SET_SNMP_CONTROL:
57 rc = qeth_snmp_command(card, rq->ifr_ifru.ifru_data);
58 break;
59 case SIOC_QETH_GET_CARD_TYPE:
Ursula Braun5113fec2010-05-16 21:15:14 +000060 if ((card->info.type == QETH_CARD_TYPE_OSD ||
61 card->info.type == QETH_CARD_TYPE_OSM ||
62 card->info.type == QETH_CARD_TYPE_OSX) &&
Frank Blaschka4a71df52008-02-15 09:19:42 +010063 !card->info.guestlan)
64 return 1;
65 return 0;
66 break;
67 case SIOCGMIIPHY:
68 mii_data = if_mii(rq);
69 mii_data->phy_id = 0;
70 break;
71 case SIOCGMIIREG:
72 mii_data = if_mii(rq);
73 if (mii_data->phy_id != 0)
74 rc = -EINVAL;
75 else
76 mii_data->val_out = qeth_mdio_read(dev,
77 mii_data->phy_id, mii_data->reg_num);
78 break;
Frank Blaschkac3ab96f2012-02-08 00:19:49 +000079 case SIOC_QETH_QUERY_OAT:
80 rc = qeth_query_oat_command(card, rq->ifr_ifru.ifru_data);
81 break;
Frank Blaschka4a71df52008-02-15 09:19:42 +010082 default:
83 rc = -EOPNOTSUPP;
84 }
85 if (rc)
Carsten Otte847a50f2010-06-21 22:57:05 +000086 QETH_CARD_TEXT_(card, 2, "ioce%d", rc);
Frank Blaschka4a71df52008-02-15 09:19:42 +010087 return rc;
88}
89
90static int qeth_l2_verify_dev(struct net_device *dev)
91{
92 struct qeth_card *card;
93 unsigned long flags;
94 int rc = 0;
95
96 read_lock_irqsave(&qeth_core_card_list.rwlock, flags);
97 list_for_each_entry(card, &qeth_core_card_list.list, list) {
98 if (card->dev == dev) {
99 rc = QETH_REAL_CARD;
100 break;
101 }
102 }
103 read_unlock_irqrestore(&qeth_core_card_list.rwlock, flags);
104
105 return rc;
106}
107
108static struct net_device *qeth_l2_netdev_by_devno(unsigned char *read_dev_no)
109{
110 struct qeth_card *card;
111 struct net_device *ndev;
Cornelia Huckf06f6f32008-06-06 12:37:45 +0200112 __u16 temp_dev_no;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100113 unsigned long flags;
Cornelia Huckf06f6f32008-06-06 12:37:45 +0200114 struct ccw_dev_id read_devid;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100115
116 ndev = NULL;
117 memcpy(&temp_dev_no, read_dev_no, 2);
118 read_lock_irqsave(&qeth_core_card_list.rwlock, flags);
119 list_for_each_entry(card, &qeth_core_card_list.list, list) {
Cornelia Huckf06f6f32008-06-06 12:37:45 +0200120 ccw_device_get_id(CARD_RDEV(card), &read_devid);
121 if (read_devid.devno == temp_dev_no) {
Frank Blaschka4a71df52008-02-15 09:19:42 +0100122 ndev = card->dev;
123 break;
124 }
125 }
126 read_unlock_irqrestore(&qeth_core_card_list.rwlock, flags);
127 return ndev;
128}
129
Eugene Crosserefbbc1d2015-01-21 13:39:09 +0100130static int qeth_setdel_makerc(struct qeth_card *card, int retcode)
Frank Blaschka4a71df52008-02-15 09:19:42 +0100131{
Eugene Crosserefbbc1d2015-01-21 13:39:09 +0100132 int rc;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100133
Eugene Crosserefbbc1d2015-01-21 13:39:09 +0100134 if (retcode)
135 QETH_CARD_TEXT_(card, 2, "err%d", retcode);
136 switch (retcode) {
137 case IPA_RC_SUCCESS:
138 rc = 0;
139 break;
140 case IPA_RC_L2_UNSUPPORTED_CMD:
141 rc = -ENOSYS;
142 break;
143 case IPA_RC_L2_ADDR_TABLE_FULL:
144 rc = -ENOSPC;
145 break;
146 case IPA_RC_L2_DUP_MAC:
147 case IPA_RC_L2_DUP_LAYER3_MAC:
148 rc = -EEXIST;
149 break;
150 case IPA_RC_L2_MAC_NOT_AUTH_BY_HYP:
151 case IPA_RC_L2_MAC_NOT_AUTH_BY_ADP:
152 rc = -EPERM;
153 break;
154 case IPA_RC_L2_MAC_NOT_FOUND:
155 rc = -ENOENT;
156 break;
157 default:
158 rc = -EIO;
159 break;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100160 }
Eugene Crosserefbbc1d2015-01-21 13:39:09 +0100161 return rc;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100162}
163
164static int qeth_l2_send_setgroupmac(struct qeth_card *card, __u8 *mac)
165{
Eugene Crosserefbbc1d2015-01-21 13:39:09 +0100166 int rc;
167
Carsten Otte847a50f2010-06-21 22:57:05 +0000168 QETH_CARD_TEXT(card, 2, "L2Sgmac");
Eugene Crosserefbbc1d2015-01-21 13:39:09 +0100169 rc = qeth_setdel_makerc(card, qeth_l2_send_setdelmac(card, mac,
170 IPA_CMD_SETGMAC));
171 if (rc == -EEXIST)
172 QETH_DBF_MESSAGE(2, "Group MAC %pM already existing on %s\n",
173 mac, QETH_CARD_IFNAME(card));
174 else if (rc)
175 QETH_DBF_MESSAGE(2, "Could not set group MAC %pM on %s: %d\n",
176 mac, QETH_CARD_IFNAME(card), rc);
177 return rc;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100178}
179
180static int qeth_l2_send_delgroupmac(struct qeth_card *card, __u8 *mac)
181{
Eugene Crosserefbbc1d2015-01-21 13:39:09 +0100182 int rc;
183
Carsten Otte847a50f2010-06-21 22:57:05 +0000184 QETH_CARD_TEXT(card, 2, "L2Dgmac");
Eugene Crosserefbbc1d2015-01-21 13:39:09 +0100185 rc = qeth_setdel_makerc(card, qeth_l2_send_setdelmac(card, mac,
186 IPA_CMD_DELGMAC));
187 if (rc)
188 QETH_DBF_MESSAGE(2,
189 "Could not delete group MAC %pM on %s: %d\n",
190 mac, QETH_CARD_IFNAME(card), rc);
191 return rc;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100192}
193
Frank Blaschka7db22662008-08-15 08:02:59 +0200194static void qeth_l2_add_mc(struct qeth_card *card, __u8 *mac, int vmac)
Frank Blaschka4a71df52008-02-15 09:19:42 +0100195{
196 struct qeth_mc_mac *mc;
Frank Blaschka7db22662008-08-15 08:02:59 +0200197 int rc;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100198
199 mc = kmalloc(sizeof(struct qeth_mc_mac), GFP_ATOMIC);
200
Frank Blaschka14cc21b2008-06-06 12:37:46 +0200201 if (!mc)
Frank Blaschka4a71df52008-02-15 09:19:42 +0100202 return;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100203
204 memcpy(mc->mc_addr, mac, OSA_ADDR_LEN);
205 mc->mc_addrlen = OSA_ADDR_LEN;
Frank Blaschka7db22662008-08-15 08:02:59 +0200206 mc->is_vmac = vmac;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100207
Frank Blaschka7db22662008-08-15 08:02:59 +0200208 if (vmac) {
Eugene Crosserefbbc1d2015-01-21 13:39:09 +0100209 rc = qeth_setdel_makerc(card,
210 qeth_l2_send_setdelmac(card, mac, IPA_CMD_SETVMAC));
Frank Blaschka7db22662008-08-15 08:02:59 +0200211 } else {
Eugene Crosserefbbc1d2015-01-21 13:39:09 +0100212 rc = qeth_setdel_makerc(card,
213 qeth_l2_send_setgroupmac(card, mac));
Frank Blaschka7db22662008-08-15 08:02:59 +0200214 }
215
216 if (!rc)
Frank Blaschka4a71df52008-02-15 09:19:42 +0100217 list_add_tail(&mc->list, &card->mc_list);
218 else
219 kfree(mc);
220}
221
Ursula Braun70919e22011-02-26 22:41:36 -0800222static void qeth_l2_del_all_mc(struct qeth_card *card, int del)
Frank Blaschka4a71df52008-02-15 09:19:42 +0100223{
224 struct qeth_mc_mac *mc, *tmp;
225
226 spin_lock_bh(&card->mclock);
227 list_for_each_entry_safe(mc, tmp, &card->mc_list, list) {
Ursula Braun70919e22011-02-26 22:41:36 -0800228 if (del) {
229 if (mc->is_vmac)
230 qeth_l2_send_setdelmac(card, mc->mc_addr,
Eugene Crosserefbbc1d2015-01-21 13:39:09 +0100231 IPA_CMD_DELVMAC);
Ursula Braun70919e22011-02-26 22:41:36 -0800232 else
233 qeth_l2_send_delgroupmac(card, mc->mc_addr);
234 }
Frank Blaschka4a71df52008-02-15 09:19:42 +0100235 list_del(&mc->list);
236 kfree(mc);
237 }
238 spin_unlock_bh(&card->mclock);
239}
240
Klaus-Dieter Wackerce73e102009-08-26 02:01:08 +0000241static inline int qeth_l2_get_cast_type(struct qeth_card *card,
242 struct sk_buff *skb)
Frank Blaschka4a71df52008-02-15 09:19:42 +0100243{
Klaus-Dieter Wackerce73e102009-08-26 02:01:08 +0000244 if (card->info.type == QETH_CARD_TYPE_OSN)
245 return RTN_UNSPEC;
246 if (is_broadcast_ether_addr(skb->data))
247 return RTN_BROADCAST;
248 if (is_multicast_ether_addr(skb->data))
249 return RTN_MULTICAST;
250 return RTN_UNSPEC;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100251}
252
253static void qeth_l2_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
Stefan Raspl43934072014-03-19 07:58:01 +0100254 struct sk_buff *skb, int cast_type)
Frank Blaschka4a71df52008-02-15 09:19:42 +0100255{
Frank Blaschka683d7182008-08-01 16:39:13 +0200256 struct vlan_ethhdr *veth = (struct vlan_ethhdr *)skb_mac_header(skb);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100257
258 memset(hdr, 0, sizeof(struct qeth_hdr));
259 hdr->hdr.l2.id = QETH_HEADER_TYPE_LAYER2;
260
261 /* set byte byte 3 to casting flags */
262 if (cast_type == RTN_MULTICAST)
263 hdr->hdr.l2.flags[2] |= QETH_LAYER2_FLAG_MULTICAST;
264 else if (cast_type == RTN_BROADCAST)
265 hdr->hdr.l2.flags[2] |= QETH_LAYER2_FLAG_BROADCAST;
266 else
Klaus-Dieter Wackerce73e102009-08-26 02:01:08 +0000267 hdr->hdr.l2.flags[2] |= QETH_LAYER2_FLAG_UNICAST;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100268
269 hdr->hdr.l2.pkt_length = skb->len-QETH_HEADER_SIZE;
270 /* VSWITCH relies on the VLAN
271 * information to be present in
272 * the QDIO header */
273 if (veth->h_vlan_proto == __constant_htons(ETH_P_8021Q)) {
274 hdr->hdr.l2.flags[2] |= QETH_LAYER2_FLAG_VLAN;
275 hdr->hdr.l2.vlan_id = ntohs(veth->h_vlan_TCI);
276 }
277}
278
279static int qeth_l2_send_setdelvlan_cb(struct qeth_card *card,
280 struct qeth_reply *reply, unsigned long data)
281{
282 struct qeth_ipa_cmd *cmd;
283
Carsten Otte847a50f2010-06-21 22:57:05 +0000284 QETH_CARD_TEXT(card, 2, "L2sdvcb");
Frank Blaschka4a71df52008-02-15 09:19:42 +0100285 cmd = (struct qeth_ipa_cmd *) data;
286 if (cmd->hdr.return_code) {
Frank Blaschka14cc21b2008-06-06 12:37:46 +0200287 QETH_DBF_MESSAGE(2, "Error in processing VLAN %i on %s: 0x%x. "
Frank Blaschka4a71df52008-02-15 09:19:42 +0100288 "Continuing\n", cmd->data.setdelvlan.vlan_id,
289 QETH_CARD_IFNAME(card), cmd->hdr.return_code);
Carsten Otte847a50f2010-06-21 22:57:05 +0000290 QETH_CARD_TEXT_(card, 2, "L2VL%4x", cmd->hdr.command);
291 QETH_CARD_TEXT_(card, 2, "err%d", cmd->hdr.return_code);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100292 }
293 return 0;
294}
295
296static int qeth_l2_send_setdelvlan(struct qeth_card *card, __u16 i,
297 enum qeth_ipa_cmds ipacmd)
298{
299 struct qeth_ipa_cmd *cmd;
300 struct qeth_cmd_buffer *iob;
301
Carsten Otte847a50f2010-06-21 22:57:05 +0000302 QETH_CARD_TEXT_(card, 4, "L2sdv%x", ipacmd);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100303 iob = qeth_get_ipacmd_buffer(card, ipacmd, QETH_PROT_IPV4);
304 cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
305 cmd->data.setdelvlan.vlan_id = i;
306 return qeth_send_ipa_cmd(card, iob,
307 qeth_l2_send_setdelvlan_cb, NULL);
308}
309
Ursula Braun70919e22011-02-26 22:41:36 -0800310static void qeth_l2_process_vlans(struct qeth_card *card)
Frank Blaschka4a71df52008-02-15 09:19:42 +0100311{
312 struct qeth_vlan_vid *id;
Carsten Otte847a50f2010-06-21 22:57:05 +0000313 QETH_CARD_TEXT(card, 3, "L2prcvln");
Frank Blaschka4a71df52008-02-15 09:19:42 +0100314 spin_lock_bh(&card->vlanlock);
315 list_for_each_entry(id, &card->vid_list, list) {
Ursula Braun70919e22011-02-26 22:41:36 -0800316 qeth_l2_send_setdelvlan(card, id->vid, IPA_CMD_SETVLAN);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100317 }
318 spin_unlock_bh(&card->vlanlock);
319}
320
Patrick McHardy80d5c362013-04-19 02:04:28 +0000321static int qeth_l2_vlan_rx_add_vid(struct net_device *dev,
322 __be16 proto, u16 vid)
Frank Blaschka4a71df52008-02-15 09:19:42 +0100323{
Heiko Carstens509e2562008-07-26 02:24:10 -0700324 struct qeth_card *card = dev->ml_priv;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100325 struct qeth_vlan_vid *id;
326
Carsten Otte847a50f2010-06-21 22:57:05 +0000327 QETH_CARD_TEXT_(card, 4, "aid:%d", vid);
Ursula Braun10651db2010-10-01 02:51:13 +0000328 if (!vid)
Jiri Pirko8e586132011-12-08 19:52:37 -0500329 return 0;
Ursula Braun5113fec2010-05-16 21:15:14 +0000330 if (card->info.type == QETH_CARD_TYPE_OSM) {
Carsten Otte847a50f2010-06-21 22:57:05 +0000331 QETH_CARD_TEXT(card, 3, "aidOSM");
Jiri Pirko8e586132011-12-08 19:52:37 -0500332 return 0;
Ursula Braun5113fec2010-05-16 21:15:14 +0000333 }
Ursula Braun8e98ac42009-03-24 20:57:18 +0000334 if (qeth_wait_for_threads(card, QETH_RECOVER_THREAD)) {
Carsten Otte847a50f2010-06-21 22:57:05 +0000335 QETH_CARD_TEXT(card, 3, "aidREC");
Jiri Pirko8e586132011-12-08 19:52:37 -0500336 return 0;
Ursula Braun8e98ac42009-03-24 20:57:18 +0000337 }
Frank Blaschka4a71df52008-02-15 09:19:42 +0100338 id = kmalloc(sizeof(struct qeth_vlan_vid), GFP_ATOMIC);
339 if (id) {
340 id->vid = vid;
341 qeth_l2_send_setdelvlan(card, vid, IPA_CMD_SETVLAN);
342 spin_lock_bh(&card->vlanlock);
343 list_add_tail(&id->list, &card->vid_list);
344 spin_unlock_bh(&card->vlanlock);
Jiri Pirko8e586132011-12-08 19:52:37 -0500345 } else {
346 return -ENOMEM;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100347 }
Jiri Pirko8e586132011-12-08 19:52:37 -0500348 return 0;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100349}
350
Patrick McHardy80d5c362013-04-19 02:04:28 +0000351static int qeth_l2_vlan_rx_kill_vid(struct net_device *dev,
352 __be16 proto, u16 vid)
Frank Blaschka4a71df52008-02-15 09:19:42 +0100353{
354 struct qeth_vlan_vid *id, *tmpid = NULL;
Heiko Carstens509e2562008-07-26 02:24:10 -0700355 struct qeth_card *card = dev->ml_priv;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100356
Carsten Otte847a50f2010-06-21 22:57:05 +0000357 QETH_CARD_TEXT_(card, 4, "kid:%d", vid);
Ursula Braun5113fec2010-05-16 21:15:14 +0000358 if (card->info.type == QETH_CARD_TYPE_OSM) {
Carsten Otte847a50f2010-06-21 22:57:05 +0000359 QETH_CARD_TEXT(card, 3, "kidOSM");
Jiri Pirko8e586132011-12-08 19:52:37 -0500360 return 0;
Ursula Braun5113fec2010-05-16 21:15:14 +0000361 }
Ursula Braun8e98ac42009-03-24 20:57:18 +0000362 if (qeth_wait_for_threads(card, QETH_RECOVER_THREAD)) {
Carsten Otte847a50f2010-06-21 22:57:05 +0000363 QETH_CARD_TEXT(card, 3, "kidREC");
Jiri Pirko8e586132011-12-08 19:52:37 -0500364 return 0;
Ursula Braun8e98ac42009-03-24 20:57:18 +0000365 }
Frank Blaschka4a71df52008-02-15 09:19:42 +0100366 spin_lock_bh(&card->vlanlock);
367 list_for_each_entry(id, &card->vid_list, list) {
368 if (id->vid == vid) {
369 list_del(&id->list);
370 tmpid = id;
371 break;
372 }
373 }
374 spin_unlock_bh(&card->vlanlock);
375 if (tmpid) {
376 qeth_l2_send_setdelvlan(card, vid, IPA_CMD_DELVLAN);
377 kfree(tmpid);
378 }
379 qeth_l2_set_multicast_list(card->dev);
Jiri Pirko8e586132011-12-08 19:52:37 -0500380 return 0;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100381}
382
383static int qeth_l2_stop_card(struct qeth_card *card, int recovery_mode)
384{
385 int rc = 0;
386
Peter Tiedemannd11ba0c2008-04-01 10:26:58 +0200387 QETH_DBF_TEXT(SETUP , 2, "stopcard");
388 QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *));
Frank Blaschka4a71df52008-02-15 09:19:42 +0100389
390 qeth_set_allowed_threads(card, 0, 1);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100391 if (card->read.state == CH_STATE_UP &&
392 card->write.state == CH_STATE_UP &&
393 (card->state == CARD_STATE_UP)) {
394 if (recovery_mode &&
395 card->info.type != QETH_CARD_TYPE_OSN) {
396 qeth_l2_stop(card->dev);
397 } else {
398 rtnl_lock();
399 dev_close(card->dev);
400 rtnl_unlock();
401 }
Ursula Braun70919e22011-02-26 22:41:36 -0800402 card->info.mac_bits &= ~QETH_LAYER2_MAC_REGISTERED;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100403 card->state = CARD_STATE_SOFTSETUP;
404 }
405 if (card->state == CARD_STATE_SOFTSETUP) {
Ursula Braun70919e22011-02-26 22:41:36 -0800406 qeth_l2_del_all_mc(card, 0);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100407 qeth_clear_ipacmd_list(card);
408 card->state = CARD_STATE_HARDSETUP;
409 }
410 if (card->state == CARD_STATE_HARDSETUP) {
411 qeth_qdio_clear_card(card, 0);
412 qeth_clear_qdio_buffers(card);
413 qeth_clear_working_pool_list(card);
414 card->state = CARD_STATE_DOWN;
415 }
416 if (card->state == CARD_STATE_DOWN) {
417 qeth_clear_cmd_buffers(&card->read);
418 qeth_clear_cmd_buffers(&card->write);
419 }
Frank Blaschka4a71df52008-02-15 09:19:42 +0100420 return rc;
421}
422
Frank Blaschkaa1c3ed42010-09-07 21:14:42 +0000423static int qeth_l2_process_inbound_buffer(struct qeth_card *card,
424 int budget, int *done)
Frank Blaschka4a71df52008-02-15 09:19:42 +0100425{
Frank Blaschkaa1c3ed42010-09-07 21:14:42 +0000426 int work_done = 0;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100427 struct sk_buff *skb;
428 struct qeth_hdr *hdr;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100429 unsigned int len;
430
Frank Blaschkaa1c3ed42010-09-07 21:14:42 +0000431 *done = 0;
Stefan Raspl18af5c12012-11-19 02:46:50 +0000432 WARN_ON_ONCE(!budget);
Frank Blaschkaa1c3ed42010-09-07 21:14:42 +0000433 while (budget) {
434 skb = qeth_core_get_next_skb(card,
Frank Blaschkab3332932011-08-08 01:33:59 +0000435 &card->qdio.in_q->bufs[card->rx.b_index],
Frank Blaschkaa1c3ed42010-09-07 21:14:42 +0000436 &card->rx.b_element, &card->rx.e_offset, &hdr);
437 if (!skb) {
438 *done = 1;
439 break;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100440 }
Frank Blaschkaa1c3ed42010-09-07 21:14:42 +0000441 skb->dev = card->dev;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100442 switch (hdr->hdr.l2.id) {
443 case QETH_HEADER_TYPE_LAYER2:
444 skb->pkt_type = PACKET_HOST;
445 skb->protocol = eth_type_trans(skb, skb->dev);
Frank Blaschkac5e631a2011-05-12 18:45:01 +0000446 skb->ip_summed = CHECKSUM_NONE;
Ursula Braun12883722008-04-01 10:26:56 +0200447 if (skb->protocol == htons(ETH_P_802_2))
448 *((__u32 *)skb->cb) = ++card->seqno.pkt_seqno;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100449 len = skb->len;
Frank Blaschkaa1c3ed42010-09-07 21:14:42 +0000450 netif_receive_skb(skb);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100451 break;
452 case QETH_HEADER_TYPE_OSN:
Ursula Braun2d488c22008-10-24 11:16:55 +0200453 if (card->info.type == QETH_CARD_TYPE_OSN) {
454 skb_push(skb, sizeof(struct qeth_hdr));
455 skb_copy_to_linear_data(skb, hdr,
Frank Blaschka4a71df52008-02-15 09:19:42 +0100456 sizeof(struct qeth_hdr));
Ursula Braun2d488c22008-10-24 11:16:55 +0200457 len = skb->len;
458 card->osn_info.data_cb(skb);
459 break;
460 }
461 /* else unknown */
Frank Blaschka4a71df52008-02-15 09:19:42 +0100462 default:
463 dev_kfree_skb_any(skb);
Carsten Otte847a50f2010-06-21 22:57:05 +0000464 QETH_CARD_TEXT(card, 3, "inbunkno");
Peter Tiedemannd11ba0c2008-04-01 10:26:58 +0200465 QETH_DBF_HEX(CTRL, 3, hdr, QETH_DBF_CTRL_LEN);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100466 continue;
467 }
Frank Blaschkaa1c3ed42010-09-07 21:14:42 +0000468 work_done++;
469 budget--;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100470 card->stats.rx_packets++;
471 card->stats.rx_bytes += len;
472 }
Frank Blaschkaa1c3ed42010-09-07 21:14:42 +0000473 return work_done;
474}
475
476static int qeth_l2_poll(struct napi_struct *napi, int budget)
477{
478 struct qeth_card *card = container_of(napi, struct qeth_card, napi);
479 int work_done = 0;
480 struct qeth_qdio_buffer *buffer;
481 int done;
482 int new_budget = budget;
483
484 if (card->options.performance_stats) {
485 card->perf_stats.inbound_cnt++;
486 card->perf_stats.inbound_start_time = qeth_get_micros();
487 }
488
489 while (1) {
490 if (!card->rx.b_count) {
491 card->rx.qdio_err = 0;
492 card->rx.b_count = qdio_get_next_buffers(
493 card->data.ccwdev, 0, &card->rx.b_index,
494 &card->rx.qdio_err);
495 if (card->rx.b_count <= 0) {
496 card->rx.b_count = 0;
497 break;
498 }
499 card->rx.b_element =
500 &card->qdio.in_q->bufs[card->rx.b_index]
501 .buffer->element[0];
502 card->rx.e_offset = 0;
503 }
504
505 while (card->rx.b_count) {
506 buffer = &card->qdio.in_q->bufs[card->rx.b_index];
507 if (!(card->rx.qdio_err &&
508 qeth_check_qdio_errors(card, buffer->buffer,
509 card->rx.qdio_err, "qinerr")))
510 work_done += qeth_l2_process_inbound_buffer(
511 card, new_budget, &done);
512 else
513 done = 1;
514
515 if (done) {
516 if (card->options.performance_stats)
517 card->perf_stats.bufs_rec++;
518 qeth_put_buffer_pool_entry(card,
519 buffer->pool_entry);
520 qeth_queue_input_buffer(card, card->rx.b_index);
521 card->rx.b_count--;
522 if (card->rx.b_count) {
523 card->rx.b_index =
524 (card->rx.b_index + 1) %
525 QDIO_MAX_BUFFERS_PER_Q;
526 card->rx.b_element =
527 &card->qdio.in_q
528 ->bufs[card->rx.b_index]
529 .buffer->element[0];
530 card->rx.e_offset = 0;
531 }
532 }
533
534 if (work_done >= budget)
535 goto out;
536 else
537 new_budget = budget - work_done;
538 }
539 }
540
541 napi_complete(napi);
542 if (qdio_start_irq(card->data.ccwdev, 0))
543 napi_schedule(&card->napi);
544out:
545 if (card->options.performance_stats)
546 card->perf_stats.inbound_time += qeth_get_micros() -
547 card->perf_stats.inbound_start_time;
548 return work_done;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100549}
550
551static int qeth_l2_send_setdelmac(struct qeth_card *card, __u8 *mac,
Eugene Crosserefbbc1d2015-01-21 13:39:09 +0100552 enum qeth_ipa_cmds ipacmd)
Frank Blaschka4a71df52008-02-15 09:19:42 +0100553{
554 struct qeth_ipa_cmd *cmd;
555 struct qeth_cmd_buffer *iob;
556
Carsten Otte847a50f2010-06-21 22:57:05 +0000557 QETH_CARD_TEXT(card, 2, "L2sdmac");
Frank Blaschka4a71df52008-02-15 09:19:42 +0100558 iob = qeth_get_ipacmd_buffer(card, ipacmd, QETH_PROT_IPV4);
559 cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
560 cmd->data.setdelmac.mac_length = OSA_ADDR_LEN;
561 memcpy(&cmd->data.setdelmac.mac, mac, OSA_ADDR_LEN);
Eugene Crosserefbbc1d2015-01-21 13:39:09 +0100562 return qeth_send_ipa_cmd(card, iob, NULL, NULL);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100563}
564
565static int qeth_l2_send_setmac(struct qeth_card *card, __u8 *mac)
566{
Eugene Crosserefbbc1d2015-01-21 13:39:09 +0100567 int rc;
568
Carsten Otte847a50f2010-06-21 22:57:05 +0000569 QETH_CARD_TEXT(card, 2, "L2Setmac");
Eugene Crosserefbbc1d2015-01-21 13:39:09 +0100570 rc = qeth_setdel_makerc(card, qeth_l2_send_setdelmac(card, mac,
571 IPA_CMD_SETVMAC));
572 if (rc == 0) {
573 card->info.mac_bits |= QETH_LAYER2_MAC_REGISTERED;
574 memcpy(card->dev->dev_addr, mac, OSA_ADDR_LEN);
575 dev_info(&card->gdev->dev,
576 "MAC address %pM successfully registered on device %s\n",
577 card->dev->dev_addr, card->dev->name);
578 } else {
579 card->info.mac_bits &= ~QETH_LAYER2_MAC_REGISTERED;
580 switch (rc) {
581 case -EEXIST:
582 dev_warn(&card->gdev->dev,
583 "MAC address %pM already exists\n", mac);
584 break;
585 case -EPERM:
586 dev_warn(&card->gdev->dev,
587 "MAC address %pM is not authorized\n", mac);
588 break;
589 }
Frank Blaschka4a71df52008-02-15 09:19:42 +0100590 }
Eugene Crosserefbbc1d2015-01-21 13:39:09 +0100591 return rc;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100592}
593
594static int qeth_l2_send_delmac(struct qeth_card *card, __u8 *mac)
595{
Eugene Crosserefbbc1d2015-01-21 13:39:09 +0100596 int rc;
597
Carsten Otte847a50f2010-06-21 22:57:05 +0000598 QETH_CARD_TEXT(card, 2, "L2Delmac");
Frank Blaschka4a71df52008-02-15 09:19:42 +0100599 if (!(card->info.mac_bits & QETH_LAYER2_MAC_REGISTERED))
600 return 0;
Eugene Crosserefbbc1d2015-01-21 13:39:09 +0100601 rc = qeth_setdel_makerc(card, qeth_l2_send_setdelmac(card, mac,
602 IPA_CMD_DELVMAC));
603 if (rc == 0)
604 card->info.mac_bits &= ~QETH_LAYER2_MAC_REGISTERED;
605 return rc;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100606}
607
608static int qeth_l2_request_initial_mac(struct qeth_card *card)
609{
610 int rc = 0;
611 char vendor_pre[] = {0x02, 0x00, 0x00};
612
Peter Tiedemannd11ba0c2008-04-01 10:26:58 +0200613 QETH_DBF_TEXT(SETUP, 2, "doL2init");
614 QETH_DBF_TEXT_(SETUP, 2, "doL2%s", CARD_BUS_ID(card));
Frank Blaschka4a71df52008-02-15 09:19:42 +0100615
Stefan Raspla1348842012-11-12 23:05:16 +0000616 if (qeth_is_supported(card, IPA_SETADAPTERPARMS)) {
617 rc = qeth_query_setadapterparms(card);
618 if (rc) {
619 QETH_DBF_MESSAGE(2, "could not query adapter "
620 "parameters on device %s: x%x\n",
621 CARD_BUS_ID(card), rc);
622 }
Frank Blaschka4a71df52008-02-15 09:19:42 +0100623 }
624
Ursula Braun5113fec2010-05-16 21:15:14 +0000625 if (card->info.type == QETH_CARD_TYPE_IQD ||
626 card->info.type == QETH_CARD_TYPE_OSM ||
627 card->info.type == QETH_CARD_TYPE_OSX ||
628 card->info.guestlan) {
Frank Blaschka4a71df52008-02-15 09:19:42 +0100629 rc = qeth_setadpparms_change_macaddr(card);
630 if (rc) {
Frank Blaschka14cc21b2008-06-06 12:37:46 +0200631 QETH_DBF_MESSAGE(2, "couldn't get MAC address on "
632 "device %s: x%x\n", CARD_BUS_ID(card), rc);
Peter Tiedemannd11ba0c2008-04-01 10:26:58 +0200633 QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100634 return rc;
635 }
Peter Tiedemannd11ba0c2008-04-01 10:26:58 +0200636 QETH_DBF_HEX(SETUP, 2, card->dev->dev_addr, OSA_ADDR_LEN);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100637 } else {
Joe Perches18336112012-07-12 22:33:10 -0700638 eth_random_addr(card->dev->dev_addr);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100639 memcpy(card->dev->dev_addr, vendor_pre, 3);
640 }
641 return 0;
642}
643
644static int qeth_l2_set_mac_address(struct net_device *dev, void *p)
645{
646 struct sockaddr *addr = p;
Heiko Carstens509e2562008-07-26 02:24:10 -0700647 struct qeth_card *card = dev->ml_priv;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100648 int rc = 0;
649
Carsten Otte847a50f2010-06-21 22:57:05 +0000650 QETH_CARD_TEXT(card, 3, "setmac");
Frank Blaschka4a71df52008-02-15 09:19:42 +0100651
652 if (qeth_l2_verify_dev(dev) != QETH_REAL_CARD) {
Carsten Otte847a50f2010-06-21 22:57:05 +0000653 QETH_CARD_TEXT(card, 3, "setmcINV");
Frank Blaschka4a71df52008-02-15 09:19:42 +0100654 return -EOPNOTSUPP;
655 }
656
Ursula Braun5113fec2010-05-16 21:15:14 +0000657 if (card->info.type == QETH_CARD_TYPE_OSN ||
658 card->info.type == QETH_CARD_TYPE_OSM ||
659 card->info.type == QETH_CARD_TYPE_OSX) {
Carsten Otte847a50f2010-06-21 22:57:05 +0000660 QETH_CARD_TEXT(card, 3, "setmcTYP");
Frank Blaschka4a71df52008-02-15 09:19:42 +0100661 return -EOPNOTSUPP;
662 }
Carsten Otte847a50f2010-06-21 22:57:05 +0000663 QETH_CARD_HEX(card, 3, addr->sa_data, OSA_ADDR_LEN);
Ursula Braun8e98ac42009-03-24 20:57:18 +0000664 if (qeth_wait_for_threads(card, QETH_RECOVER_THREAD)) {
Carsten Otte847a50f2010-06-21 22:57:05 +0000665 QETH_CARD_TEXT(card, 3, "setmcREC");
Ursula Braun8e98ac42009-03-24 20:57:18 +0000666 return -ERESTARTSYS;
667 }
Frank Blaschka4a71df52008-02-15 09:19:42 +0100668 rc = qeth_l2_send_delmac(card, &card->dev->dev_addr[0]);
Eugene Crosserefbbc1d2015-01-21 13:39:09 +0100669 if (!rc || (rc == -ENOENT))
Frank Blaschka4a71df52008-02-15 09:19:42 +0100670 rc = qeth_l2_send_setmac(card, addr->sa_data);
Ursula Braune0a81142012-03-07 02:06:28 +0000671 return rc ? -EINVAL : 0;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100672}
673
674static void qeth_l2_set_multicast_list(struct net_device *dev)
675{
Heiko Carstens509e2562008-07-26 02:24:10 -0700676 struct qeth_card *card = dev->ml_priv;
Jiri Pirkoccffad252009-05-22 23:22:17 +0000677 struct netdev_hw_addr *ha;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100678
679 if (card->info.type == QETH_CARD_TYPE_OSN)
680 return ;
681
Carsten Otte847a50f2010-06-21 22:57:05 +0000682 QETH_CARD_TEXT(card, 3, "setmulti");
Ursula Braun8e98ac42009-03-24 20:57:18 +0000683 if (qeth_threads_running(card, QETH_RECOVER_THREAD) &&
684 (card->state != CARD_STATE_UP))
685 return;
Ursula Braun70919e22011-02-26 22:41:36 -0800686 qeth_l2_del_all_mc(card, 1);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100687 spin_lock_bh(&card->mclock);
Jiri Pirko22bedad32010-04-01 21:22:57 +0000688 netdev_for_each_mc_addr(ha, dev)
689 qeth_l2_add_mc(card, ha->addr, 0);
Frank Blaschka7db22662008-08-15 08:02:59 +0200690
Jiri Pirko32e7bfc2010-01-25 13:36:10 -0800691 netdev_for_each_uc_addr(ha, dev)
Jiri Pirkoccffad252009-05-22 23:22:17 +0000692 qeth_l2_add_mc(card, ha->addr, 1);
Frank Blaschka7db22662008-08-15 08:02:59 +0200693
Frank Blaschka4a71df52008-02-15 09:19:42 +0100694 spin_unlock_bh(&card->mclock);
695 if (!qeth_adp_supported(card, IPA_SETADP_SET_PROMISC_MODE))
696 return;
697 qeth_setadp_promisc_mode(card);
698}
699
700static int qeth_l2_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
701{
702 int rc;
703 struct qeth_hdr *hdr = NULL;
704 int elements = 0;
Heiko Carstens509e2562008-07-26 02:24:10 -0700705 struct qeth_card *card = dev->ml_priv;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100706 struct sk_buff *new_skb = skb;
Klaus-Dieter Wackerce73e102009-08-26 02:01:08 +0000707 int cast_type = qeth_l2_get_cast_type(card, skb);
Stefan Raspl290b8342014-04-28 10:05:08 +0200708 struct qeth_qdio_out_q *queue;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100709 int tx_bytes = skb->len;
Frank Blaschka683d7182008-08-01 16:39:13 +0200710 int data_offset = -1;
711 int elements_needed = 0;
712 int hd_len = 0;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100713
Stefan Raspl290b8342014-04-28 10:05:08 +0200714 if (card->qdio.do_prio_queueing || (cast_type &&
715 card->info.is_multicast_different))
716 queue = card->qdio.out_qs[qeth_get_priority_queue(card, skb,
717 qeth_get_ip_version(skb), cast_type)];
718 else
719 queue = card->qdio.out_qs[card->qdio.default_out_queue];
720
Frank Blaschka4a71df52008-02-15 09:19:42 +0100721 if ((card->state != CARD_STATE_UP) || !card->lan_online) {
722 card->stats.tx_carrier_errors++;
723 goto tx_drop;
724 }
725
726 if ((card->info.type == QETH_CARD_TYPE_OSN) &&
727 (skb->protocol == htons(ETH_P_IPV6)))
728 goto tx_drop;
729
730 if (card->options.performance_stats) {
731 card->perf_stats.outbound_cnt++;
732 card->perf_stats.outbound_start_time = qeth_get_micros();
733 }
734 netif_stop_queue(dev);
735
Frank Blaschka4a71df52008-02-15 09:19:42 +0100736 if (card->info.type == QETH_CARD_TYPE_OSN)
737 hdr = (struct qeth_hdr *)skb->data;
738 else {
Frank Blaschka64ef8952009-03-24 20:57:16 +0000739 if (card->info.type == QETH_CARD_TYPE_IQD) {
Frank Blaschka683d7182008-08-01 16:39:13 +0200740 new_skb = skb;
741 data_offset = ETH_HLEN;
742 hd_len = ETH_HLEN;
743 hdr = kmem_cache_alloc(qeth_core_header_cache,
744 GFP_ATOMIC);
745 if (!hdr)
746 goto tx_drop;
747 elements_needed++;
748 skb_reset_mac_header(new_skb);
Stefan Raspl43934072014-03-19 07:58:01 +0100749 qeth_l2_fill_header(card, hdr, new_skb, cast_type);
Frank Blaschka683d7182008-08-01 16:39:13 +0200750 hdr->hdr.l2.pkt_length = new_skb->len;
751 memcpy(((char *)hdr) + sizeof(struct qeth_hdr),
752 skb_mac_header(new_skb), ETH_HLEN);
753 } else {
754 /* create a clone with writeable headroom */
755 new_skb = skb_realloc_headroom(skb,
Frank Blaschkaf90b7442008-04-24 10:15:24 +0200756 sizeof(struct qeth_hdr));
Frank Blaschka683d7182008-08-01 16:39:13 +0200757 if (!new_skb)
758 goto tx_drop;
759 hdr = (struct qeth_hdr *)skb_push(new_skb,
760 sizeof(struct qeth_hdr));
761 skb_set_mac_header(new_skb, sizeof(struct qeth_hdr));
Stefan Raspl43934072014-03-19 07:58:01 +0100762 qeth_l2_fill_header(card, hdr, new_skb, cast_type);
Frank Blaschka683d7182008-08-01 16:39:13 +0200763 }
Frank Blaschka4a71df52008-02-15 09:19:42 +0100764 }
765
Stefan Raspl065cc782013-04-22 01:12:28 +0000766 elements = qeth_get_elements_no(card, new_skb, elements_needed);
Frank Blaschka64ef8952009-03-24 20:57:16 +0000767 if (!elements) {
768 if (data_offset >= 0)
769 kmem_cache_free(qeth_core_header_cache, hdr);
770 goto tx_drop;
Frank Blaschkaf61a0d02009-03-24 20:57:15 +0000771 }
Frank Blaschka4a71df52008-02-15 09:19:42 +0100772
Frank Blaschka51aa1652010-06-21 22:57:10 +0000773 if (card->info.type != QETH_CARD_TYPE_IQD) {
Stefan Raspld4ae1f52013-04-22 01:12:29 +0000774 if (qeth_hdr_chk_and_bounce(new_skb, &hdr,
Frank Blaschka51aa1652010-06-21 22:57:10 +0000775 sizeof(struct qeth_hdr_layer2)))
776 goto tx_drop;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100777 rc = qeth_do_send_packet(card, queue, new_skb, hdr,
Frank Blaschka64ef8952009-03-24 20:57:16 +0000778 elements);
Frank Blaschka51aa1652010-06-21 22:57:10 +0000779 } else
Frank Blaschka4a71df52008-02-15 09:19:42 +0100780 rc = qeth_do_send_packet_fast(card, queue, new_skb, hdr,
Frank Blaschka64ef8952009-03-24 20:57:16 +0000781 elements, data_offset, hd_len);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100782 if (!rc) {
783 card->stats.tx_packets++;
784 card->stats.tx_bytes += tx_bytes;
785 if (new_skb != skb)
786 dev_kfree_skb_any(skb);
Patrick McHardyec634fe2009-07-05 19:23:38 -0700787 rc = NETDEV_TX_OK;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100788 } else {
Frank Blaschka683d7182008-08-01 16:39:13 +0200789 if (data_offset >= 0)
790 kmem_cache_free(qeth_core_header_cache, hdr);
791
Frank Blaschka4a71df52008-02-15 09:19:42 +0100792 if (rc == -EBUSY) {
793 if (new_skb != skb)
794 dev_kfree_skb_any(new_skb);
795 return NETDEV_TX_BUSY;
796 } else
797 goto tx_drop;
798 }
799
800 netif_wake_queue(dev);
801 if (card->options.performance_stats)
802 card->perf_stats.outbound_time += qeth_get_micros() -
803 card->perf_stats.outbound_start_time;
804 return rc;
805
806tx_drop:
807 card->stats.tx_dropped++;
808 card->stats.tx_errors++;
809 if ((new_skb != skb) && new_skb)
810 dev_kfree_skb_any(new_skb);
811 dev_kfree_skb_any(skb);
Frank Blaschkad0ec0f52008-06-06 12:37:48 +0200812 netif_wake_queue(dev);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100813 return NETDEV_TX_OK;
814}
815
Ursula Braun39423442011-01-12 20:42:24 +0000816static int __qeth_l2_open(struct net_device *dev)
Frank Blaschka4a71df52008-02-15 09:19:42 +0100817{
Heiko Carstens509e2562008-07-26 02:24:10 -0700818 struct qeth_card *card = dev->ml_priv;
Frank Blaschkaa1c3ed42010-09-07 21:14:42 +0000819 int rc = 0;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100820
Carsten Otte847a50f2010-06-21 22:57:05 +0000821 QETH_CARD_TEXT(card, 4, "qethopen");
Ursula Braun39423442011-01-12 20:42:24 +0000822 if (card->state == CARD_STATE_UP)
823 return rc;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100824 if (card->state != CARD_STATE_SOFTSETUP)
825 return -ENODEV;
826
827 if ((card->info.type != QETH_CARD_TYPE_OSN) &&
828 (!(card->info.mac_bits & QETH_LAYER2_MAC_REGISTERED))) {
Carsten Otte847a50f2010-06-21 22:57:05 +0000829 QETH_CARD_TEXT(card, 4, "nomacadr");
Frank Blaschka4a71df52008-02-15 09:19:42 +0100830 return -EPERM;
831 }
832 card->data.state = CH_STATE_UP;
833 card->state = CARD_STATE_UP;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100834 netif_start_queue(dev);
835
Frank Blaschkaa1c3ed42010-09-07 21:14:42 +0000836 if (qdio_stop_irq(card->data.ccwdev, 0) >= 0) {
837 napi_enable(&card->napi);
838 napi_schedule(&card->napi);
839 } else
840 rc = -EIO;
841 return rc;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100842}
843
Ursula Braun39423442011-01-12 20:42:24 +0000844static int qeth_l2_open(struct net_device *dev)
845{
846 struct qeth_card *card = dev->ml_priv;
847
848 QETH_CARD_TEXT(card, 5, "qethope_");
849 if (qeth_wait_for_threads(card, QETH_RECOVER_THREAD)) {
850 QETH_CARD_TEXT(card, 3, "openREC");
851 return -ERESTARTSYS;
852 }
853 return __qeth_l2_open(dev);
854}
855
Frank Blaschka4a71df52008-02-15 09:19:42 +0100856static int qeth_l2_stop(struct net_device *dev)
857{
Heiko Carstens509e2562008-07-26 02:24:10 -0700858 struct qeth_card *card = dev->ml_priv;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100859
Carsten Otte847a50f2010-06-21 22:57:05 +0000860 QETH_CARD_TEXT(card, 4, "qethstop");
Frank Blaschka4a71df52008-02-15 09:19:42 +0100861 netif_tx_disable(dev);
Frank Blaschkaa1c3ed42010-09-07 21:14:42 +0000862 if (card->state == CARD_STATE_UP) {
Frank Blaschka4a71df52008-02-15 09:19:42 +0100863 card->state = CARD_STATE_SOFTSETUP;
Frank Blaschkaa1c3ed42010-09-07 21:14:42 +0000864 napi_disable(&card->napi);
865 }
Frank Blaschka4a71df52008-02-15 09:19:42 +0100866 return 0;
867}
868
869static int qeth_l2_probe_device(struct ccwgroup_device *gdev)
870{
871 struct qeth_card *card = dev_get_drvdata(&gdev->dev);
872
Eugene Crosserb4d72c02014-01-14 15:54:11 +0100873 qeth_l2_create_device_attributes(&gdev->dev);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100874 INIT_LIST_HEAD(&card->vid_list);
875 INIT_LIST_HEAD(&card->mc_list);
876 card->options.layer2 = 1;
Frank Blaschka1da74b12011-05-12 18:45:02 +0000877 card->info.hwtrap = 0;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100878 return 0;
879}
880
881static void qeth_l2_remove_device(struct ccwgroup_device *cgdev)
882{
883 struct qeth_card *card = dev_get_drvdata(&cgdev->dev);
884
Eugene Crosserb4d72c02014-01-14 15:54:11 +0100885 qeth_l2_remove_device_attributes(&cgdev->dev);
Ursula Braunf2148562009-05-19 21:38:37 +0000886 qeth_set_allowed_threads(card, 0, 1);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100887 wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0);
888
Ursula Braun70919e22011-02-26 22:41:36 -0800889 if (cgdev->state == CCWGROUP_ONLINE)
Frank Blaschka4a71df52008-02-15 09:19:42 +0100890 qeth_l2_set_offline(cgdev);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100891
892 if (card->dev) {
893 unregister_netdev(card->dev);
894 card->dev = NULL;
895 }
Frank Blaschka4a71df52008-02-15 09:19:42 +0100896 return;
897}
898
Stephen Hemminger0fc0b732009-09-02 01:03:33 -0700899static const struct ethtool_ops qeth_l2_ethtool_ops = {
Frank Blaschka4a71df52008-02-15 09:19:42 +0100900 .get_link = ethtool_op_get_link,
Frank Blaschka4a71df52008-02-15 09:19:42 +0100901 .get_strings = qeth_core_get_strings,
902 .get_ethtool_stats = qeth_core_get_ethtool_stats,
Ben Hutchingsdf8b4ec2009-10-01 11:24:32 +0000903 .get_sset_count = qeth_core_get_sset_count,
Frank Blaschka4a71df52008-02-15 09:19:42 +0100904 .get_drvinfo = qeth_core_get_drvinfo,
Frank Blaschka3f9975a2008-04-24 10:15:23 +0200905 .get_settings = qeth_core_ethtool_get_settings,
Frank Blaschka4a71df52008-02-15 09:19:42 +0100906};
907
Stephen Hemminger0fc0b732009-09-02 01:03:33 -0700908static const struct ethtool_ops qeth_l2_osn_ops = {
Frank Blaschka4a71df52008-02-15 09:19:42 +0100909 .get_strings = qeth_core_get_strings,
910 .get_ethtool_stats = qeth_core_get_ethtool_stats,
Ben Hutchingsdf8b4ec2009-10-01 11:24:32 +0000911 .get_sset_count = qeth_core_get_sset_count,
Frank Blaschka4a71df52008-02-15 09:19:42 +0100912 .get_drvinfo = qeth_core_get_drvinfo,
913};
914
Frank Blaschka3d58cef2009-01-09 03:44:00 +0000915static const struct net_device_ops qeth_l2_netdev_ops = {
Frank Blaschka8403b132009-01-08 10:50:55 -0800916 .ndo_open = qeth_l2_open,
917 .ndo_stop = qeth_l2_stop,
918 .ndo_get_stats = qeth_get_stats,
919 .ndo_start_xmit = qeth_l2_hard_start_xmit,
920 .ndo_validate_addr = eth_validate_addr,
Jiri Pirkoafc4b132011-08-16 06:29:01 +0000921 .ndo_set_rx_mode = qeth_l2_set_multicast_list,
Frank Blaschka8403b132009-01-08 10:50:55 -0800922 .ndo_do_ioctl = qeth_l2_do_ioctl,
923 .ndo_set_mac_address = qeth_l2_set_mac_address,
924 .ndo_change_mtu = qeth_change_mtu,
925 .ndo_vlan_rx_add_vid = qeth_l2_vlan_rx_add_vid,
926 .ndo_vlan_rx_kill_vid = qeth_l2_vlan_rx_kill_vid,
927 .ndo_tx_timeout = qeth_tx_timeout,
928};
929
Frank Blaschka4a71df52008-02-15 09:19:42 +0100930static int qeth_l2_setup_netdev(struct qeth_card *card)
931{
932 switch (card->info.type) {
Frank Blaschka4a71df52008-02-15 09:19:42 +0100933 case QETH_CARD_TYPE_IQD:
Tom Gundersenc835a672014-07-14 16:37:24 +0200934 card->dev = alloc_netdev(0, "hsi%d", NET_NAME_UNKNOWN,
935 ether_setup);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100936 break;
937 case QETH_CARD_TYPE_OSN:
Tom Gundersenc835a672014-07-14 16:37:24 +0200938 card->dev = alloc_netdev(0, "osn%d", NET_NAME_UNKNOWN,
939 ether_setup);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100940 card->dev->flags |= IFF_NOARP;
941 break;
942 default:
943 card->dev = alloc_etherdev(0);
944 }
945
946 if (!card->dev)
947 return -ENODEV;
948
Heiko Carstens509e2562008-07-26 02:24:10 -0700949 card->dev->ml_priv = card;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100950 card->dev->watchdog_timeo = QETH_TX_TIMEOUT;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100951 card->dev->mtu = card->info.initial_mtu;
Frank Blaschka8403b132009-01-08 10:50:55 -0800952 card->dev->netdev_ops = &qeth_l2_netdev_ops;
Wilfried Klaebe7ad24ea2014-05-11 00:12:32 +0000953 card->dev->ethtool_ops =
954 (card->info.type != QETH_CARD_TYPE_OSN) ?
955 &qeth_l2_ethtool_ops : &qeth_l2_osn_ops;
Patrick McHardyf6469682013-04-19 02:04:27 +0000956 card->dev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100957 card->info.broadcast_capable = 1;
958 qeth_l2_request_initial_mac(card);
959 SET_NETDEV_DEV(card->dev, &card->gdev->dev);
Frank Blaschkaa1c3ed42010-09-07 21:14:42 +0000960 netif_napi_add(card->dev, &card->napi, qeth_l2_poll, QETH_NAPI_WEIGHT);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100961 return register_netdev(card->dev);
962}
963
964static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)
965{
966 struct qeth_card *card = dev_get_drvdata(&gdev->dev);
967 int rc = 0;
968 enum qeth_card_states recover_flag;
969
Ursula Braun9dc48cc2010-07-22 23:15:05 +0000970 mutex_lock(&card->discipline_mutex);
Frank Blaschkac4949f02010-05-11 19:34:47 +0000971 mutex_lock(&card->conf_mutex);
Peter Tiedemannd11ba0c2008-04-01 10:26:58 +0200972 QETH_DBF_TEXT(SETUP, 2, "setonlin");
973 QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *));
Frank Blaschka4a71df52008-02-15 09:19:42 +0100974
Frank Blaschka4a71df52008-02-15 09:19:42 +0100975 recover_flag = card->state;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100976 rc = qeth_core_hardsetup_card(card);
977 if (rc) {
Peter Tiedemannd11ba0c2008-04-01 10:26:58 +0200978 QETH_DBF_TEXT_(SETUP, 2, "2err%d", rc);
Ursula Braunaa909222009-11-12 00:11:43 +0000979 rc = -ENODEV;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100980 goto out_remove;
981 }
Eugene Crosserc044dc22014-01-29 09:23:48 +0100982 qeth_bridgeport_query_support(card);
983 if (card->options.sbp.supported_funcs)
984 dev_info(&card->gdev->dev,
985 "The device represents a HiperSockets Bridge Capable Port\n");
Stefan Raspl395672e02012-11-19 02:46:49 +0000986 qeth_trace_features(card);
Frank Blaschka4a71df52008-02-15 09:19:42 +0100987
Ursula Braunaa909222009-11-12 00:11:43 +0000988 if (!card->dev && qeth_l2_setup_netdev(card)) {
989 rc = -ENODEV;
Frank Blaschka4a71df52008-02-15 09:19:42 +0100990 goto out_remove;
Ursula Braunaa909222009-11-12 00:11:43 +0000991 }
Frank Blaschka4a71df52008-02-15 09:19:42 +0100992
993 if (card->info.type != QETH_CARD_TYPE_OSN)
994 qeth_l2_send_setmac(card, &card->dev->dev_addr[0]);
995
Frank Blaschka1da74b12011-05-12 18:45:02 +0000996 if (qeth_is_diagass_supported(card, QETH_DIAGS_CMD_TRAP)) {
997 if (card->info.hwtrap &&
998 qeth_hw_trap(card, QETH_DIAGS_TRAP_ARM))
999 card->info.hwtrap = 0;
1000 } else
1001 card->info.hwtrap = 0;
1002
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001003 qeth_l2_setup_bridgeport_attrs(card);
1004
Frank Blaschka4a71df52008-02-15 09:19:42 +01001005 card->state = CARD_STATE_HARDSETUP;
Frank Blaschkaa1c3ed42010-09-07 21:14:42 +00001006 memset(&card->rx, 0, sizeof(struct qeth_rx));
Frank Blaschka4a71df52008-02-15 09:19:42 +01001007 qeth_print_status_message(card);
1008
1009 /* softsetup */
Peter Tiedemannd11ba0c2008-04-01 10:26:58 +02001010 QETH_DBF_TEXT(SETUP, 2, "softsetp");
Frank Blaschka4a71df52008-02-15 09:19:42 +01001011
1012 rc = qeth_send_startlan(card);
1013 if (rc) {
Peter Tiedemannd11ba0c2008-04-01 10:26:58 +02001014 QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc);
Frank Blaschka4a71df52008-02-15 09:19:42 +01001015 if (rc == 0xe080) {
Frank Blaschka74eacdb2008-12-25 13:39:49 +01001016 dev_warn(&card->gdev->dev,
1017 "The LAN is offline\n");
Frank Blaschka4a71df52008-02-15 09:19:42 +01001018 card->lan_online = 0;
Ursula Braun2b6203b2010-11-26 02:41:19 +00001019 goto contin;
Frank Blaschka4a71df52008-02-15 09:19:42 +01001020 }
Ursula Braunaa909222009-11-12 00:11:43 +00001021 rc = -ENODEV;
Ursula Braunf2148562009-05-19 21:38:37 +00001022 goto out_remove;
Frank Blaschka4a71df52008-02-15 09:19:42 +01001023 } else
1024 card->lan_online = 1;
1025
Ursula Braun2b6203b2010-11-26 02:41:19 +00001026contin:
Ursula Braun5113fec2010-05-16 21:15:14 +00001027 if ((card->info.type == QETH_CARD_TYPE_OSD) ||
Stefan Raspl0f547612013-01-21 02:30:20 +00001028 (card->info.type == QETH_CARD_TYPE_OSX)) {
Einar Lueckd64ecc22009-11-12 00:11:41 +00001029 /* configure isolation level */
Stefan Raspl0f547612013-01-21 02:30:20 +00001030 rc = qeth_set_access_ctrl_online(card, 0);
1031 if (rc) {
1032 rc = -ENODEV;
1033 goto out_remove;
1034 }
1035 }
Ursula Braun5113fec2010-05-16 21:15:14 +00001036
1037 if (card->info.type != QETH_CARD_TYPE_OSN &&
1038 card->info.type != QETH_CARD_TYPE_OSM)
Ursula Braun70919e22011-02-26 22:41:36 -08001039 qeth_l2_process_vlans(card);
Frank Blaschka4a71df52008-02-15 09:19:42 +01001040
1041 netif_tx_disable(card->dev);
1042
1043 rc = qeth_init_qdio_queues(card);
1044 if (rc) {
Peter Tiedemannd11ba0c2008-04-01 10:26:58 +02001045 QETH_DBF_TEXT_(SETUP, 2, "6err%d", rc);
Ursula Braunaa909222009-11-12 00:11:43 +00001046 rc = -ENODEV;
Frank Blaschka4a71df52008-02-15 09:19:42 +01001047 goto out_remove;
1048 }
1049 card->state = CARD_STATE_SOFTSETUP;
Ursula Braun2b6203b2010-11-26 02:41:19 +00001050 if (card->lan_online)
1051 netif_carrier_on(card->dev);
1052 else
1053 netif_carrier_off(card->dev);
Frank Blaschka4a71df52008-02-15 09:19:42 +01001054
1055 qeth_set_allowed_threads(card, 0xffffffff, 0);
1056 if (recover_flag == CARD_STATE_RECOVER) {
1057 if (recovery_mode &&
1058 card->info.type != QETH_CARD_TYPE_OSN) {
Ursula Braun39423442011-01-12 20:42:24 +00001059 __qeth_l2_open(card->dev);
Frank Blaschka4a71df52008-02-15 09:19:42 +01001060 } else {
1061 rtnl_lock();
1062 dev_open(card->dev);
1063 rtnl_unlock();
1064 }
1065 /* this also sets saved unicast addresses */
1066 qeth_l2_set_multicast_list(card->dev);
1067 }
1068 /* let user_space know that device is online */
1069 kobject_uevent(&gdev->dev.kobj, KOBJ_CHANGE);
Frank Blaschkac4949f02010-05-11 19:34:47 +00001070 mutex_unlock(&card->conf_mutex);
Ursula Braun9dc48cc2010-07-22 23:15:05 +00001071 mutex_unlock(&card->discipline_mutex);
Frank Blaschka4a71df52008-02-15 09:19:42 +01001072 return 0;
Ursula Braunaa909222009-11-12 00:11:43 +00001073
Frank Blaschka4a71df52008-02-15 09:19:42 +01001074out_remove:
Frank Blaschka4a71df52008-02-15 09:19:42 +01001075 qeth_l2_stop_card(card, 0);
1076 ccw_device_set_offline(CARD_DDEV(card));
1077 ccw_device_set_offline(CARD_WDEV(card));
1078 ccw_device_set_offline(CARD_RDEV(card));
Ursula Braun22ae2792014-02-24 13:12:06 +01001079 qdio_free(CARD_DDEV(card));
Frank Blaschka4a71df52008-02-15 09:19:42 +01001080 if (recover_flag == CARD_STATE_RECOVER)
1081 card->state = CARD_STATE_RECOVER;
1082 else
1083 card->state = CARD_STATE_DOWN;
Frank Blaschkac4949f02010-05-11 19:34:47 +00001084 mutex_unlock(&card->conf_mutex);
Ursula Braun9dc48cc2010-07-22 23:15:05 +00001085 mutex_unlock(&card->discipline_mutex);
Ursula Braunaa909222009-11-12 00:11:43 +00001086 return rc;
Frank Blaschka4a71df52008-02-15 09:19:42 +01001087}
1088
1089static int qeth_l2_set_online(struct ccwgroup_device *gdev)
1090{
1091 return __qeth_l2_set_online(gdev, 0);
1092}
1093
1094static int __qeth_l2_set_offline(struct ccwgroup_device *cgdev,
1095 int recovery_mode)
1096{
1097 struct qeth_card *card = dev_get_drvdata(&cgdev->dev);
1098 int rc = 0, rc2 = 0, rc3 = 0;
1099 enum qeth_card_states recover_flag;
1100
Ursula Braun9dc48cc2010-07-22 23:15:05 +00001101 mutex_lock(&card->discipline_mutex);
Frank Blaschkac4949f02010-05-11 19:34:47 +00001102 mutex_lock(&card->conf_mutex);
Peter Tiedemannd11ba0c2008-04-01 10:26:58 +02001103 QETH_DBF_TEXT(SETUP, 3, "setoffl");
1104 QETH_DBF_HEX(SETUP, 3, &card, sizeof(void *));
Frank Blaschka4a71df52008-02-15 09:19:42 +01001105
1106 if (card->dev && netif_carrier_ok(card->dev))
1107 netif_carrier_off(card->dev);
1108 recover_flag = card->state;
Frank Blaschka1da74b12011-05-12 18:45:02 +00001109 if ((!recovery_mode && card->info.hwtrap) || card->info.hwtrap == 2) {
1110 qeth_hw_trap(card, QETH_DIAGS_TRAP_DISARM);
1111 card->info.hwtrap = 1;
1112 }
Ursula Braun0f5623c2008-10-24 11:16:52 +02001113 qeth_l2_stop_card(card, recovery_mode);
Frank Blaschka4a71df52008-02-15 09:19:42 +01001114 rc = ccw_device_set_offline(CARD_DDEV(card));
1115 rc2 = ccw_device_set_offline(CARD_WDEV(card));
1116 rc3 = ccw_device_set_offline(CARD_RDEV(card));
1117 if (!rc)
1118 rc = (rc2) ? rc2 : rc3;
1119 if (rc)
Peter Tiedemannd11ba0c2008-04-01 10:26:58 +02001120 QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc);
Ursula Braun22ae2792014-02-24 13:12:06 +01001121 qdio_free(CARD_DDEV(card));
Frank Blaschka4a71df52008-02-15 09:19:42 +01001122 if (recover_flag == CARD_STATE_UP)
1123 card->state = CARD_STATE_RECOVER;
1124 /* let user_space know that device is offline */
1125 kobject_uevent(&cgdev->dev.kobj, KOBJ_CHANGE);
Frank Blaschkac4949f02010-05-11 19:34:47 +00001126 mutex_unlock(&card->conf_mutex);
Ursula Braun9dc48cc2010-07-22 23:15:05 +00001127 mutex_unlock(&card->discipline_mutex);
Frank Blaschka4a71df52008-02-15 09:19:42 +01001128 return 0;
1129}
1130
1131static int qeth_l2_set_offline(struct ccwgroup_device *cgdev)
1132{
1133 return __qeth_l2_set_offline(cgdev, 0);
1134}
1135
1136static int qeth_l2_recover(void *ptr)
1137{
1138 struct qeth_card *card;
1139 int rc = 0;
1140
1141 card = (struct qeth_card *) ptr;
Carsten Otte847a50f2010-06-21 22:57:05 +00001142 QETH_CARD_TEXT(card, 2, "recover1");
Frank Blaschka4a71df52008-02-15 09:19:42 +01001143 if (!qeth_do_run_thread(card, QETH_RECOVER_THREAD))
1144 return 0;
Carsten Otte847a50f2010-06-21 22:57:05 +00001145 QETH_CARD_TEXT(card, 2, "recover2");
Frank Blaschka74eacdb2008-12-25 13:39:49 +01001146 dev_warn(&card->gdev->dev,
1147 "A recovery process has been started for the device\n");
Stefan Raspl65d80132013-04-07 22:19:27 +00001148 qeth_set_recovery_task(card);
Frank Blaschka4a71df52008-02-15 09:19:42 +01001149 __qeth_l2_set_offline(card->gdev, 1);
1150 rc = __qeth_l2_set_online(card->gdev, 1);
Frank Blaschka4a71df52008-02-15 09:19:42 +01001151 if (!rc)
Frank Blaschka74eacdb2008-12-25 13:39:49 +01001152 dev_info(&card->gdev->dev,
1153 "Device successfully recovered!\n");
Ursula Braun28a7e4c2008-09-19 12:56:03 +02001154 else {
Stefan Raspl0f547612013-01-21 02:30:20 +00001155 qeth_close_dev(card);
1156 dev_warn(&card->gdev->dev, "The qeth device driver "
Stefan Raspl2efaf5f2012-10-15 19:21:18 +00001157 "failed to recover an error on the device\n");
Ursula Braun28a7e4c2008-09-19 12:56:03 +02001158 }
Stefan Raspl65d80132013-04-07 22:19:27 +00001159 qeth_clear_recovery_task(card);
Frank Blaschkaa1c3ed42010-09-07 21:14:42 +00001160 qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD);
1161 qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD);
Frank Blaschka4a71df52008-02-15 09:19:42 +01001162 return 0;
1163}
1164
1165static int __init qeth_l2_init(void)
1166{
Frank Blaschka74eacdb2008-12-25 13:39:49 +01001167 pr_info("register layer 2 discipline\n");
Frank Blaschka4a71df52008-02-15 09:19:42 +01001168 return 0;
1169}
1170
1171static void __exit qeth_l2_exit(void)
1172{
Frank Blaschka74eacdb2008-12-25 13:39:49 +01001173 pr_info("unregister layer 2 discipline\n");
Frank Blaschka4a71df52008-02-15 09:19:42 +01001174}
1175
1176static void qeth_l2_shutdown(struct ccwgroup_device *gdev)
1177{
1178 struct qeth_card *card = dev_get_drvdata(&gdev->dev);
Ursula Braunf78ac2b2011-12-19 22:56:33 +00001179 qeth_set_allowed_threads(card, 0, 1);
Frank Blaschka1da74b12011-05-12 18:45:02 +00001180 if ((gdev->state == CCWGROUP_ONLINE) && card->info.hwtrap)
1181 qeth_hw_trap(card, QETH_DIAGS_TRAP_DISARM);
Frank Blaschka4a71df52008-02-15 09:19:42 +01001182 qeth_qdio_clear_card(card, 0);
1183 qeth_clear_qdio_buffers(card);
Ursula Braun22ae2792014-02-24 13:12:06 +01001184 qdio_free(CARD_DDEV(card));
Frank Blaschka4a71df52008-02-15 09:19:42 +01001185}
1186
Frank Blaschkabbcfcdc2009-06-16 10:30:31 +02001187static int qeth_l2_pm_suspend(struct ccwgroup_device *gdev)
1188{
1189 struct qeth_card *card = dev_get_drvdata(&gdev->dev);
1190
1191 if (card->dev)
1192 netif_device_detach(card->dev);
1193 qeth_set_allowed_threads(card, 0, 1);
1194 wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0);
1195 if (gdev->state == CCWGROUP_OFFLINE)
1196 return 0;
1197 if (card->state == CARD_STATE_UP) {
Frank Blaschka1da74b12011-05-12 18:45:02 +00001198 if (card->info.hwtrap)
1199 qeth_hw_trap(card, QETH_DIAGS_TRAP_DISARM);
Frank Blaschkabbcfcdc2009-06-16 10:30:31 +02001200 __qeth_l2_set_offline(card->gdev, 1);
1201 } else
1202 __qeth_l2_set_offline(card->gdev, 0);
1203 return 0;
1204}
1205
1206static int qeth_l2_pm_resume(struct ccwgroup_device *gdev)
1207{
1208 struct qeth_card *card = dev_get_drvdata(&gdev->dev);
1209 int rc = 0;
1210
1211 if (gdev->state == CCWGROUP_OFFLINE)
1212 goto out;
1213
1214 if (card->state == CARD_STATE_RECOVER) {
1215 rc = __qeth_l2_set_online(card->gdev, 1);
1216 if (rc) {
Ursula Braun869da902010-03-08 20:36:56 +00001217 rtnl_lock();
1218 dev_close(card->dev);
1219 rtnl_unlock();
Frank Blaschkabbcfcdc2009-06-16 10:30:31 +02001220 }
1221 } else
1222 rc = __qeth_l2_set_online(card->gdev, 0);
1223out:
1224 qeth_set_allowed_threads(card, 0xffffffff, 0);
1225 if (card->dev)
1226 netif_device_attach(card->dev);
1227 if (rc)
1228 dev_warn(&card->gdev->dev, "The qeth device driver "
1229 "failed to recover an error on the device\n");
1230 return rc;
1231}
1232
Eugene Crosserc044dc22014-01-29 09:23:48 +01001233/* Returns zero if the command is successfully "consumed" */
1234static int qeth_l2_control_event(struct qeth_card *card,
1235 struct qeth_ipa_cmd *cmd)
1236{
1237 switch (cmd->hdr.command) {
1238 case IPA_CMD_SETBRIDGEPORT:
1239 if (cmd->data.sbp.hdr.command_code ==
1240 IPA_SBP_BRIDGE_PORT_STATE_CHANGE) {
1241 qeth_bridge_state_change(card, cmd);
1242 return 0;
1243 } else
1244 return 1;
1245 case IPA_CMD_ADDRESS_CHANGE_NOTIF:
1246 qeth_bridge_host_event(card, cmd);
1247 return 0;
1248 default:
1249 return 1;
1250 }
1251}
1252
Sebastian Ottc041f2d4872012-05-15 18:02:21 +02001253struct qeth_discipline qeth_l2_discipline = {
1254 .start_poll = qeth_qdio_start_poll,
1255 .input_handler = (qdio_handler_t *) qeth_qdio_input_handler,
1256 .output_handler = (qdio_handler_t *) qeth_qdio_output_handler,
1257 .recover = qeth_l2_recover,
1258 .setup = qeth_l2_probe_device,
Frank Blaschka4a71df52008-02-15 09:19:42 +01001259 .remove = qeth_l2_remove_device,
1260 .set_online = qeth_l2_set_online,
1261 .set_offline = qeth_l2_set_offline,
1262 .shutdown = qeth_l2_shutdown,
Frank Blaschkabbcfcdc2009-06-16 10:30:31 +02001263 .freeze = qeth_l2_pm_suspend,
1264 .thaw = qeth_l2_pm_resume,
1265 .restore = qeth_l2_pm_resume,
Eugene Crosserc044dc22014-01-29 09:23:48 +01001266 .control_event_handler = qeth_l2_control_event,
Frank Blaschka4a71df52008-02-15 09:19:42 +01001267};
Sebastian Ottc041f2d4872012-05-15 18:02:21 +02001268EXPORT_SYMBOL_GPL(qeth_l2_discipline);
Frank Blaschka4a71df52008-02-15 09:19:42 +01001269
1270static int qeth_osn_send_control_data(struct qeth_card *card, int len,
1271 struct qeth_cmd_buffer *iob)
1272{
1273 unsigned long flags;
1274 int rc = 0;
1275
Carsten Otte847a50f2010-06-21 22:57:05 +00001276 QETH_CARD_TEXT(card, 5, "osndctrd");
Frank Blaschka4a71df52008-02-15 09:19:42 +01001277
1278 wait_event(card->wait_q,
1279 atomic_cmpxchg(&card->write.irq_pending, 0, 1) == 0);
1280 qeth_prepare_control_data(card, len, iob);
Carsten Otte847a50f2010-06-21 22:57:05 +00001281 QETH_CARD_TEXT(card, 6, "osnoirqp");
Frank Blaschka4a71df52008-02-15 09:19:42 +01001282 spin_lock_irqsave(get_ccwdev_lock(card->write.ccwdev), flags);
1283 rc = ccw_device_start(card->write.ccwdev, &card->write.ccw,
1284 (addr_t) iob, 0, 0);
1285 spin_unlock_irqrestore(get_ccwdev_lock(card->write.ccwdev), flags);
1286 if (rc) {
Frank Blaschka14cc21b2008-06-06 12:37:46 +02001287 QETH_DBF_MESSAGE(2, "qeth_osn_send_control_data: "
Frank Blaschka4a71df52008-02-15 09:19:42 +01001288 "ccw_device_start rc = %i\n", rc);
Carsten Otte847a50f2010-06-21 22:57:05 +00001289 QETH_CARD_TEXT_(card, 2, " err%d", rc);
Frank Blaschka4a71df52008-02-15 09:19:42 +01001290 qeth_release_buffer(iob->channel, iob);
1291 atomic_set(&card->write.irq_pending, 0);
1292 wake_up(&card->wait_q);
1293 }
1294 return rc;
1295}
1296
1297static int qeth_osn_send_ipa_cmd(struct qeth_card *card,
1298 struct qeth_cmd_buffer *iob, int data_len)
1299{
1300 u16 s1, s2;
1301
Carsten Otte847a50f2010-06-21 22:57:05 +00001302 QETH_CARD_TEXT(card, 4, "osndipa");
Frank Blaschka4a71df52008-02-15 09:19:42 +01001303
1304 qeth_prepare_ipa_cmd(card, iob, QETH_PROT_OSN2);
1305 s1 = (u16)(IPA_PDU_HEADER_SIZE + data_len);
1306 s2 = (u16)data_len;
1307 memcpy(QETH_IPA_PDU_LEN_TOTAL(iob->data), &s1, 2);
1308 memcpy(QETH_IPA_PDU_LEN_PDU1(iob->data), &s2, 2);
1309 memcpy(QETH_IPA_PDU_LEN_PDU2(iob->data), &s2, 2);
1310 memcpy(QETH_IPA_PDU_LEN_PDU3(iob->data), &s2, 2);
1311 return qeth_osn_send_control_data(card, s1, iob);
1312}
1313
1314int qeth_osn_assist(struct net_device *dev, void *data, int data_len)
1315{
1316 struct qeth_cmd_buffer *iob;
1317 struct qeth_card *card;
1318 int rc;
1319
Frank Blaschka4a71df52008-02-15 09:19:42 +01001320 if (!dev)
1321 return -ENODEV;
Heiko Carstens509e2562008-07-26 02:24:10 -07001322 card = dev->ml_priv;
Frank Blaschka4a71df52008-02-15 09:19:42 +01001323 if (!card)
1324 return -ENODEV;
Carsten Otte847a50f2010-06-21 22:57:05 +00001325 QETH_CARD_TEXT(card, 2, "osnsdmc");
Frank Blaschka4a71df52008-02-15 09:19:42 +01001326 if ((card->state != CARD_STATE_UP) &&
1327 (card->state != CARD_STATE_SOFTSETUP))
1328 return -ENODEV;
1329 iob = qeth_wait_for_buffer(&card->write);
1330 memcpy(iob->data+IPA_PDU_HEADER_SIZE, data, data_len);
1331 rc = qeth_osn_send_ipa_cmd(card, iob, data_len);
1332 return rc;
1333}
1334EXPORT_SYMBOL(qeth_osn_assist);
1335
1336int qeth_osn_register(unsigned char *read_dev_no, struct net_device **dev,
1337 int (*assist_cb)(struct net_device *, void *),
1338 int (*data_cb)(struct sk_buff *))
1339{
1340 struct qeth_card *card;
1341
Frank Blaschka4a71df52008-02-15 09:19:42 +01001342 *dev = qeth_l2_netdev_by_devno(read_dev_no);
1343 if (*dev == NULL)
1344 return -ENODEV;
Heiko Carstens509e2562008-07-26 02:24:10 -07001345 card = (*dev)->ml_priv;
Frank Blaschka4a71df52008-02-15 09:19:42 +01001346 if (!card)
1347 return -ENODEV;
Carsten Otte847a50f2010-06-21 22:57:05 +00001348 QETH_CARD_TEXT(card, 2, "osnreg");
Frank Blaschka4a71df52008-02-15 09:19:42 +01001349 if ((assist_cb == NULL) || (data_cb == NULL))
1350 return -EINVAL;
1351 card->osn_info.assist_cb = assist_cb;
1352 card->osn_info.data_cb = data_cb;
1353 return 0;
1354}
1355EXPORT_SYMBOL(qeth_osn_register);
1356
1357void qeth_osn_deregister(struct net_device *dev)
1358{
1359 struct qeth_card *card;
1360
Frank Blaschka4a71df52008-02-15 09:19:42 +01001361 if (!dev)
1362 return;
Heiko Carstens509e2562008-07-26 02:24:10 -07001363 card = dev->ml_priv;
Frank Blaschka4a71df52008-02-15 09:19:42 +01001364 if (!card)
1365 return;
Carsten Otte847a50f2010-06-21 22:57:05 +00001366 QETH_CARD_TEXT(card, 2, "osndereg");
Frank Blaschka4a71df52008-02-15 09:19:42 +01001367 card->osn_info.assist_cb = NULL;
1368 card->osn_info.data_cb = NULL;
1369 return;
1370}
1371EXPORT_SYMBOL(qeth_osn_deregister);
1372
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001373/* SETBRIDGEPORT support, async notifications */
1374
Eugene Crosser9f48b9d2014-01-14 15:54:13 +01001375enum qeth_an_event_type {anev_reg_unreg, anev_abort, anev_reset};
1376
1377/**
1378 * qeth_bridge_emit_host_event() - bridgeport address change notification
1379 * @card: qeth_card structure pointer, for udev events.
1380 * @evtype: "normal" register/unregister, or abort, or reset. For abort
1381 * and reset token and addr_lnid are unused and may be NULL.
1382 * @code: event bitmask: high order bit 0x80 value 1 means removal of an
1383 * object, 0 - addition of an object.
1384 * 0x01 - VLAN, 0x02 - MAC, 0x03 - VLAN and MAC.
1385 * @token: "network token" structure identifying physical address of the port.
1386 * @addr_lnid: pointer to structure with MAC address and VLAN ID.
1387 *
1388 * This function is called when registrations and deregistrations are
1389 * reported by the hardware, and also when notifications are enabled -
1390 * for all currently registered addresses.
1391 */
1392static void qeth_bridge_emit_host_event(struct qeth_card *card,
1393 enum qeth_an_event_type evtype,
1394 u8 code, struct net_if_token *token, struct mac_addr_lnid *addr_lnid)
1395{
1396 char str[7][32];
1397 char *env[8];
1398 int i = 0;
1399
1400 switch (evtype) {
1401 case anev_reg_unreg:
1402 snprintf(str[i], sizeof(str[i]), "BRIDGEDHOST=%s",
1403 (code & IPA_ADDR_CHANGE_CODE_REMOVAL)
1404 ? "deregister" : "register");
1405 env[i] = str[i]; i++;
1406 if (code & IPA_ADDR_CHANGE_CODE_VLANID) {
1407 snprintf(str[i], sizeof(str[i]), "VLAN=%d",
1408 addr_lnid->lnid);
1409 env[i] = str[i]; i++;
1410 }
1411 if (code & IPA_ADDR_CHANGE_CODE_MACADDR) {
1412 snprintf(str[i], sizeof(str[i]), "MAC=%pM6",
1413 &addr_lnid->mac);
1414 env[i] = str[i]; i++;
1415 }
1416 snprintf(str[i], sizeof(str[i]), "NTOK_BUSID=%x.%x.%04x",
1417 token->cssid, token->ssid, token->devnum);
1418 env[i] = str[i]; i++;
1419 snprintf(str[i], sizeof(str[i]), "NTOK_IID=%02x", token->iid);
1420 env[i] = str[i]; i++;
1421 snprintf(str[i], sizeof(str[i]), "NTOK_CHPID=%02x",
1422 token->chpid);
1423 env[i] = str[i]; i++;
1424 snprintf(str[i], sizeof(str[i]), "NTOK_CHID=%04x", token->chid);
1425 env[i] = str[i]; i++;
1426 break;
1427 case anev_abort:
1428 snprintf(str[i], sizeof(str[i]), "BRIDGEDHOST=abort");
1429 env[i] = str[i]; i++;
1430 break;
1431 case anev_reset:
1432 snprintf(str[i], sizeof(str[i]), "BRIDGEDHOST=reset");
1433 env[i] = str[i]; i++;
1434 break;
1435 }
1436 env[i] = NULL;
1437 kobject_uevent_env(&card->gdev->dev.kobj, KOBJ_CHANGE, env);
1438}
1439
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001440struct qeth_bridge_state_data {
1441 struct work_struct worker;
1442 struct qeth_card *card;
1443 struct qeth_sbp_state_change qports;
1444};
1445
1446static void qeth_bridge_state_change_worker(struct work_struct *work)
1447{
1448 struct qeth_bridge_state_data *data =
1449 container_of(work, struct qeth_bridge_state_data, worker);
1450 /* We are only interested in the first entry - local port */
1451 struct qeth_sbp_port_entry *entry = &data->qports.entry[0];
1452 char env_locrem[32];
1453 char env_role[32];
1454 char env_state[32];
1455 char *env[] = {
1456 env_locrem,
1457 env_role,
1458 env_state,
1459 NULL
1460 };
1461
1462 /* Role should not change by itself, but if it did, */
1463 /* information from the hardware is authoritative. */
1464 mutex_lock(&data->card->conf_mutex);
1465 data->card->options.sbp.role = entry->role;
1466 mutex_unlock(&data->card->conf_mutex);
1467
1468 snprintf(env_locrem, sizeof(env_locrem), "BRIDGEPORT=statechange");
1469 snprintf(env_role, sizeof(env_role), "ROLE=%s",
1470 (entry->role == QETH_SBP_ROLE_NONE) ? "none" :
1471 (entry->role == QETH_SBP_ROLE_PRIMARY) ? "primary" :
1472 (entry->role == QETH_SBP_ROLE_SECONDARY) ? "secondary" :
1473 "<INVALID>");
1474 snprintf(env_state, sizeof(env_state), "STATE=%s",
1475 (entry->state == QETH_SBP_STATE_INACTIVE) ? "inactive" :
1476 (entry->state == QETH_SBP_STATE_STANDBY) ? "standby" :
1477 (entry->state == QETH_SBP_STATE_ACTIVE) ? "active" :
1478 "<INVALID>");
1479 kobject_uevent_env(&data->card->gdev->dev.kobj,
1480 KOBJ_CHANGE, env);
1481 kfree(data);
1482}
1483
Eugene Crosserc044dc22014-01-29 09:23:48 +01001484static void qeth_bridge_state_change(struct qeth_card *card,
1485 struct qeth_ipa_cmd *cmd)
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001486{
1487 struct qeth_sbp_state_change *qports =
1488 &cmd->data.sbp.data.state_change;
1489 struct qeth_bridge_state_data *data;
1490 int extrasize;
1491
1492 QETH_CARD_TEXT(card, 2, "brstchng");
1493 if (qports->entry_length != sizeof(struct qeth_sbp_port_entry)) {
Thomas Richter8a593142014-10-22 12:18:03 +02001494 QETH_CARD_TEXT_(card, 2, "BPsz%04x", qports->entry_length);
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001495 return;
1496 }
1497 extrasize = sizeof(struct qeth_sbp_port_entry) * qports->num_entries;
1498 data = kzalloc(sizeof(struct qeth_bridge_state_data) + extrasize,
1499 GFP_ATOMIC);
1500 if (!data) {
1501 QETH_CARD_TEXT(card, 2, "BPSalloc");
1502 return;
1503 }
1504 INIT_WORK(&data->worker, qeth_bridge_state_change_worker);
1505 data->card = card;
1506 memcpy(&data->qports, qports,
1507 sizeof(struct qeth_sbp_state_change) + extrasize);
1508 queue_work(qeth_wq, &data->worker);
1509}
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001510
Eugene Crosser9f48b9d2014-01-14 15:54:13 +01001511struct qeth_bridge_host_data {
1512 struct work_struct worker;
1513 struct qeth_card *card;
1514 struct qeth_ipacmd_addr_change hostevs;
1515};
1516
1517static void qeth_bridge_host_event_worker(struct work_struct *work)
1518{
1519 struct qeth_bridge_host_data *data =
1520 container_of(work, struct qeth_bridge_host_data, worker);
1521 int i;
1522
1523 if (data->hostevs.lost_event_mask) {
1524 dev_info(&data->card->gdev->dev,
1525"Address notification from the HiperSockets Bridge Port stopped %s (%s)\n",
1526 data->card->dev->name,
1527 (data->hostevs.lost_event_mask == 0x01)
1528 ? "Overflow"
1529 : (data->hostevs.lost_event_mask == 0x02)
1530 ? "Bridge port state change"
1531 : "Unknown reason");
1532 mutex_lock(&data->card->conf_mutex);
1533 data->card->options.sbp.hostnotification = 0;
1534 mutex_unlock(&data->card->conf_mutex);
1535 qeth_bridge_emit_host_event(data->card, anev_abort,
1536 0, NULL, NULL);
1537 } else
1538 for (i = 0; i < data->hostevs.num_entries; i++) {
1539 struct qeth_ipacmd_addr_change_entry *entry =
1540 &data->hostevs.entry[i];
1541 qeth_bridge_emit_host_event(data->card,
1542 anev_reg_unreg,
1543 entry->change_code,
1544 &entry->token, &entry->addr_lnid);
1545 }
1546 kfree(data);
1547}
1548
Eugene Crosserc044dc22014-01-29 09:23:48 +01001549static void qeth_bridge_host_event(struct qeth_card *card,
1550 struct qeth_ipa_cmd *cmd)
Eugene Crosser9f48b9d2014-01-14 15:54:13 +01001551{
1552 struct qeth_ipacmd_addr_change *hostevs =
1553 &cmd->data.addrchange;
1554 struct qeth_bridge_host_data *data;
1555 int extrasize;
1556
1557 QETH_CARD_TEXT(card, 2, "brhostev");
1558 if (cmd->hdr.return_code != 0x0000) {
1559 if (cmd->hdr.return_code == 0x0010) {
1560 if (hostevs->lost_event_mask == 0x00)
1561 hostevs->lost_event_mask = 0xff;
1562 } else {
1563 QETH_CARD_TEXT_(card, 2, "BPHe%04x",
1564 cmd->hdr.return_code);
1565 return;
1566 }
1567 }
1568 extrasize = sizeof(struct qeth_ipacmd_addr_change_entry) *
1569 hostevs->num_entries;
1570 data = kzalloc(sizeof(struct qeth_bridge_host_data) + extrasize,
1571 GFP_ATOMIC);
1572 if (!data) {
1573 QETH_CARD_TEXT(card, 2, "BPHalloc");
1574 return;
1575 }
1576 INIT_WORK(&data->worker, qeth_bridge_host_event_worker);
1577 data->card = card;
1578 memcpy(&data->hostevs, hostevs,
1579 sizeof(struct qeth_ipacmd_addr_change) + extrasize);
1580 queue_work(qeth_wq, &data->worker);
1581}
Eugene Crosser9f48b9d2014-01-14 15:54:13 +01001582
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001583/* SETBRIDGEPORT support; sending commands */
1584
1585struct _qeth_sbp_cbctl {
1586 u16 ipa_rc;
1587 u16 cmd_rc;
1588 union {
1589 u32 supported;
1590 struct {
1591 enum qeth_sbp_roles *role;
1592 enum qeth_sbp_states *state;
1593 } qports;
1594 } data;
1595};
1596
1597/**
1598 * qeth_bridgeport_makerc() - derive "traditional" error from hardware codes.
1599 * @card: qeth_card structure pointer, for debug messages.
1600 * @cbctl: state structure with hardware return codes.
1601 * @setcmd: IPA command code
1602 *
1603 * Returns negative errno-compatible error indication or 0 on success.
1604 */
1605static int qeth_bridgeport_makerc(struct qeth_card *card,
1606 struct _qeth_sbp_cbctl *cbctl, enum qeth_ipa_sbp_cmd setcmd)
1607{
1608 int rc;
1609
1610 switch (cbctl->ipa_rc) {
1611 case IPA_RC_SUCCESS:
1612 switch (cbctl->cmd_rc) {
1613 case 0x0000:
1614 rc = 0;
1615 break;
1616 case 0x0004:
1617 rc = -ENOSYS;
1618 break;
1619 case 0x000C: /* Not configured as bridge Port */
1620 rc = -ENODEV; /* maybe not the best code here? */
1621 dev_err(&card->gdev->dev,
1622 "The HiperSockets device is not configured as a Bridge Port\n");
1623 break;
1624 case 0x0014: /* Another device is Primary */
1625 switch (setcmd) {
1626 case IPA_SBP_SET_PRIMARY_BRIDGE_PORT:
1627 rc = -EEXIST;
1628 dev_err(&card->gdev->dev,
1629 "The HiperSockets LAN already has a primary Bridge Port\n");
1630 break;
1631 case IPA_SBP_SET_SECONDARY_BRIDGE_PORT:
1632 rc = -EBUSY;
1633 dev_err(&card->gdev->dev,
1634 "The HiperSockets device is already a primary Bridge Port\n");
1635 break;
1636 default:
1637 rc = -EIO;
1638 }
1639 break;
1640 case 0x0018: /* This device is currently Secondary */
1641 rc = -EBUSY;
1642 dev_err(&card->gdev->dev,
1643 "The HiperSockets device is already a secondary Bridge Port\n");
1644 break;
1645 case 0x001C: /* Limit for Secondary devices reached */
1646 rc = -EEXIST;
1647 dev_err(&card->gdev->dev,
1648 "The HiperSockets LAN cannot have more secondary Bridge Ports\n");
1649 break;
1650 case 0x0024: /* This device is currently Primary */
1651 rc = -EBUSY;
1652 dev_err(&card->gdev->dev,
1653 "The HiperSockets device is already a primary Bridge Port\n");
1654 break;
1655 case 0x0020: /* Not authorized by zManager */
1656 rc = -EACCES;
1657 dev_err(&card->gdev->dev,
1658 "The HiperSockets device is not authorized to be a Bridge Port\n");
1659 break;
1660 default:
1661 rc = -EIO;
1662 }
1663 break;
1664 case IPA_RC_NOTSUPP:
1665 rc = -ENOSYS;
1666 break;
1667 case IPA_RC_UNSUPPORTED_COMMAND:
1668 rc = -ENOSYS;
1669 break;
1670 default:
1671 rc = -EIO;
1672 }
1673 if (rc) {
1674 QETH_CARD_TEXT_(card, 2, "SBPi%04x", cbctl->ipa_rc);
1675 QETH_CARD_TEXT_(card, 2, "SBPc%04x", cbctl->cmd_rc);
1676 }
1677 return rc;
1678}
1679
1680static int qeth_bridgeport_query_support_cb(struct qeth_card *card,
1681 struct qeth_reply *reply, unsigned long data)
1682{
1683 struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data;
1684 struct _qeth_sbp_cbctl *cbctl = (struct _qeth_sbp_cbctl *)reply->param;
1685 QETH_CARD_TEXT(card, 2, "brqsupcb");
1686 cbctl->ipa_rc = cmd->hdr.return_code;
1687 cbctl->cmd_rc = cmd->data.sbp.hdr.return_code;
1688 if ((cbctl->ipa_rc == 0) && (cbctl->cmd_rc == 0)) {
1689 cbctl->data.supported =
1690 cmd->data.sbp.data.query_cmds_supp.supported_cmds;
1691 } else {
1692 cbctl->data.supported = 0;
1693 }
1694 return 0;
1695}
1696
1697/**
1698 * qeth_bridgeport_query_support() - store bitmask of supported subfunctions.
1699 * @card: qeth_card structure pointer.
1700 *
1701 * Sets bitmask of supported setbridgeport subfunctions in the qeth_card
1702 * strucutre: card->options.sbp.supported_funcs.
1703 */
Eugene Crosserc044dc22014-01-29 09:23:48 +01001704static void qeth_bridgeport_query_support(struct qeth_card *card)
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001705{
1706 struct qeth_cmd_buffer *iob;
1707 struct qeth_ipa_cmd *cmd;
1708 struct _qeth_sbp_cbctl cbctl;
1709
1710 QETH_CARD_TEXT(card, 2, "brqsuppo");
1711 iob = qeth_get_ipacmd_buffer(card, IPA_CMD_SETBRIDGEPORT, 0);
1712 cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
1713 cmd->data.sbp.hdr.cmdlength =
1714 sizeof(struct qeth_ipacmd_sbp_hdr) +
1715 sizeof(struct qeth_sbp_query_cmds_supp);
1716 cmd->data.sbp.hdr.command_code =
1717 IPA_SBP_QUERY_COMMANDS_SUPPORTED;
1718 cmd->data.sbp.hdr.used_total = 1;
1719 cmd->data.sbp.hdr.seq_no = 1;
1720 if (qeth_send_ipa_cmd(card, iob, qeth_bridgeport_query_support_cb,
1721 (void *)&cbctl) ||
1722 qeth_bridgeport_makerc(card, &cbctl,
1723 IPA_SBP_QUERY_COMMANDS_SUPPORTED)) {
1724 /* non-zero makerc signifies failure, and produce messages */
1725 card->options.sbp.role = QETH_SBP_ROLE_NONE;
1726 return;
1727 }
1728 card->options.sbp.supported_funcs = cbctl.data.supported;
1729}
Eugene Crosserb4d72c02014-01-14 15:54:11 +01001730
1731static int qeth_bridgeport_query_ports_cb(struct qeth_card *card,
1732 struct qeth_reply *reply, unsigned long data)
1733{
1734 struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data;
1735 struct qeth_sbp_query_ports *qports = &cmd->data.sbp.data.query_ports;
1736 struct _qeth_sbp_cbctl *cbctl = (struct _qeth_sbp_cbctl *)reply->param;
1737
1738 QETH_CARD_TEXT(card, 2, "brqprtcb");
1739 cbctl->ipa_rc = cmd->hdr.return_code;
1740 cbctl->cmd_rc = cmd->data.sbp.hdr.return_code;
1741 if ((cbctl->ipa_rc != 0) || (cbctl->cmd_rc != 0))
1742 return 0;
1743 if (qports->entry_length != sizeof(struct qeth_sbp_port_entry)) {
1744 cbctl->cmd_rc = 0xffff;
1745 QETH_CARD_TEXT_(card, 2, "SBPs%04x", qports->entry_length);
1746 return 0;
1747 }
1748 /* first entry contains the state of the local port */
1749 if (qports->num_entries > 0) {
1750 if (cbctl->data.qports.role)
1751 *cbctl->data.qports.role = qports->entry[0].role;
1752 if (cbctl->data.qports.state)
1753 *cbctl->data.qports.state = qports->entry[0].state;
1754 }
1755 return 0;
1756}
1757
1758/**
1759 * qeth_bridgeport_query_ports() - query local bridgeport status.
1760 * @card: qeth_card structure pointer.
1761 * @role: Role of the port: 0-none, 1-primary, 2-secondary.
1762 * @state: State of the port: 0-inactive, 1-standby, 2-active.
1763 *
1764 * Returns negative errno-compatible error indication or 0 on success.
1765 *
1766 * 'role' and 'state' are not updated in case of hardware operation failure.
1767 */
1768int qeth_bridgeport_query_ports(struct qeth_card *card,
1769 enum qeth_sbp_roles *role, enum qeth_sbp_states *state)
1770{
1771 int rc = 0;
1772 struct qeth_cmd_buffer *iob;
1773 struct qeth_ipa_cmd *cmd;
1774 struct _qeth_sbp_cbctl cbctl = {
1775 .data = {
1776 .qports = {
1777 .role = role,
1778 .state = state,
1779 },
1780 },
1781 };
1782
1783 QETH_CARD_TEXT(card, 2, "brqports");
1784 if (!(card->options.sbp.supported_funcs & IPA_SBP_QUERY_BRIDGE_PORTS))
1785 return -EOPNOTSUPP;
1786 iob = qeth_get_ipacmd_buffer(card, IPA_CMD_SETBRIDGEPORT, 0);
1787 cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
1788 cmd->data.sbp.hdr.cmdlength =
1789 sizeof(struct qeth_ipacmd_sbp_hdr);
1790 cmd->data.sbp.hdr.command_code =
1791 IPA_SBP_QUERY_BRIDGE_PORTS;
1792 cmd->data.sbp.hdr.used_total = 1;
1793 cmd->data.sbp.hdr.seq_no = 1;
1794 rc = qeth_send_ipa_cmd(card, iob, qeth_bridgeport_query_ports_cb,
1795 (void *)&cbctl);
1796 if (rc)
1797 return rc;
1798 rc = qeth_bridgeport_makerc(card, &cbctl, IPA_SBP_QUERY_BRIDGE_PORTS);
1799 if (rc)
1800 return rc;
1801 return 0;
1802}
1803EXPORT_SYMBOL_GPL(qeth_bridgeport_query_ports);
1804
1805static int qeth_bridgeport_set_cb(struct qeth_card *card,
1806 struct qeth_reply *reply, unsigned long data)
1807{
1808 struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *)data;
1809 struct _qeth_sbp_cbctl *cbctl = (struct _qeth_sbp_cbctl *)reply->param;
1810 QETH_CARD_TEXT(card, 2, "brsetrcb");
1811 cbctl->ipa_rc = cmd->hdr.return_code;
1812 cbctl->cmd_rc = cmd->data.sbp.hdr.return_code;
1813 return 0;
1814}
1815
1816/**
1817 * qeth_bridgeport_setrole() - Assign primary role to the port.
1818 * @card: qeth_card structure pointer.
1819 * @role: Role to assign.
1820 *
1821 * Returns negative errno-compatible error indication or 0 on success.
1822 */
1823int qeth_bridgeport_setrole(struct qeth_card *card, enum qeth_sbp_roles role)
1824{
1825 int rc = 0;
1826 int cmdlength;
1827 struct qeth_cmd_buffer *iob;
1828 struct qeth_ipa_cmd *cmd;
1829 struct _qeth_sbp_cbctl cbctl;
1830 enum qeth_ipa_sbp_cmd setcmd;
1831
1832 QETH_CARD_TEXT(card, 2, "brsetrol");
1833 switch (role) {
1834 case QETH_SBP_ROLE_NONE:
1835 setcmd = IPA_SBP_RESET_BRIDGE_PORT_ROLE;
1836 cmdlength = sizeof(struct qeth_ipacmd_sbp_hdr) +
1837 sizeof(struct qeth_sbp_reset_role);
1838 break;
1839 case QETH_SBP_ROLE_PRIMARY:
1840 setcmd = IPA_SBP_SET_PRIMARY_BRIDGE_PORT;
1841 cmdlength = sizeof(struct qeth_ipacmd_sbp_hdr) +
1842 sizeof(struct qeth_sbp_set_primary);
1843 break;
1844 case QETH_SBP_ROLE_SECONDARY:
1845 setcmd = IPA_SBP_SET_SECONDARY_BRIDGE_PORT;
1846 cmdlength = sizeof(struct qeth_ipacmd_sbp_hdr) +
1847 sizeof(struct qeth_sbp_set_secondary);
1848 break;
1849 default:
1850 return -EINVAL;
1851 }
1852 if (!(card->options.sbp.supported_funcs & setcmd))
1853 return -EOPNOTSUPP;
1854 iob = qeth_get_ipacmd_buffer(card, IPA_CMD_SETBRIDGEPORT, 0);
1855 cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
1856 cmd->data.sbp.hdr.cmdlength = cmdlength;
1857 cmd->data.sbp.hdr.command_code = setcmd;
1858 cmd->data.sbp.hdr.used_total = 1;
1859 cmd->data.sbp.hdr.seq_no = 1;
1860 rc = qeth_send_ipa_cmd(card, iob, qeth_bridgeport_set_cb,
1861 (void *)&cbctl);
1862 if (rc)
1863 return rc;
1864 rc = qeth_bridgeport_makerc(card, &cbctl, setcmd);
1865 return rc;
1866}
1867
Eugene Crosser9f48b9d2014-01-14 15:54:13 +01001868/**
1869 * qeth_anset_makerc() - derive "traditional" error from hardware codes.
1870 * @card: qeth_card structure pointer, for debug messages.
1871 *
1872 * Returns negative errno-compatible error indication or 0 on success.
1873 */
1874static int qeth_anset_makerc(struct qeth_card *card, int pnso_rc, u16 response)
1875{
1876 int rc;
1877
1878 if (pnso_rc == 0)
1879 switch (response) {
1880 case 0x0001:
1881 rc = 0;
1882 break;
1883 case 0x0004:
1884 case 0x0100:
1885 case 0x0106:
1886 rc = -ENOSYS;
1887 dev_err(&card->gdev->dev,
1888 "Setting address notification failed\n");
1889 break;
1890 case 0x0107:
1891 rc = -EAGAIN;
1892 break;
1893 default:
1894 rc = -EIO;
1895 }
1896 else
1897 rc = -EIO;
1898
1899 if (rc) {
1900 QETH_CARD_TEXT_(card, 2, "SBPp%04x", pnso_rc);
1901 QETH_CARD_TEXT_(card, 2, "SBPr%04x", response);
1902 }
1903 return rc;
1904}
1905
1906static void qeth_bridgeport_an_set_cb(void *priv,
1907 enum qdio_brinfo_entry_type type, void *entry)
1908{
1909 struct qeth_card *card = (struct qeth_card *)priv;
1910 struct qdio_brinfo_entry_l2 *l2entry;
1911 u8 code;
1912
1913 if (type != l2_addr_lnid) {
1914 WARN_ON_ONCE(1);
1915 return;
1916 }
1917
1918 l2entry = (struct qdio_brinfo_entry_l2 *)entry;
1919 code = IPA_ADDR_CHANGE_CODE_MACADDR;
1920 if (l2entry->addr_lnid.lnid)
1921 code |= IPA_ADDR_CHANGE_CODE_VLANID;
1922 qeth_bridge_emit_host_event(card, anev_reg_unreg, code,
1923 (struct net_if_token *)&l2entry->nit,
1924 (struct mac_addr_lnid *)&l2entry->addr_lnid);
1925}
1926
1927/**
1928 * qeth_bridgeport_an_set() - Enable or disable bridgeport address notification
1929 * @card: qeth_card structure pointer.
1930 * @enable: 0 - disable, non-zero - enable notifications
1931 *
1932 * Returns negative errno-compatible error indication or 0 on success.
1933 *
1934 * On enable, emits a series of address notifications udev events for all
1935 * currently registered hosts.
1936 */
1937int qeth_bridgeport_an_set(struct qeth_card *card, int enable)
1938{
1939 int rc;
1940 u16 response;
1941 struct ccw_device *ddev;
1942 struct subchannel_id schid;
1943
1944 if (!card)
1945 return -EINVAL;
1946 if (!card->options.sbp.supported_funcs)
1947 return -EOPNOTSUPP;
1948 ddev = CARD_DDEV(card);
1949 ccw_device_get_schid(ddev, &schid);
1950
1951 if (enable) {
1952 qeth_bridge_emit_host_event(card, anev_reset, 0, NULL, NULL);
1953 rc = qdio_pnso_brinfo(schid, 1, &response,
1954 qeth_bridgeport_an_set_cb, card);
1955 } else
1956 rc = qdio_pnso_brinfo(schid, 0, &response, NULL, NULL);
1957 return qeth_anset_makerc(card, rc, response);
1958}
1959EXPORT_SYMBOL_GPL(qeth_bridgeport_an_set);
1960
Frank Blaschka4a71df52008-02-15 09:19:42 +01001961module_init(qeth_l2_init);
1962module_exit(qeth_l2_exit);
1963MODULE_AUTHOR("Frank Blaschka <frank.blaschka@de.ibm.com>");
1964MODULE_DESCRIPTION("qeth layer 2 discipline");
1965MODULE_LICENSE("GPL");