blob: 5ebd545ab04ef29375065b45d0cfe84f8c2ff4e5 [file] [log] [blame]
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001/*
2 * linux/drivers/net/ehea/ehea_main.c
3 *
4 * eHEA ethernet device driver for IBM eServer System p
5 *
6 * (C) Copyright IBM Corp. 2006
7 *
8 * Authors:
9 * Christoph Raisch <raisch@de.ibm.com>
10 * Jan-Bernd Themann <themann@de.ibm.com>
11 * Thomas Klein <tklein@de.ibm.com>
12 *
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2, or (at your option)
17 * any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 */
28
29#include <linux/in.h>
30#include <linux/ip.h>
31#include <linux/tcp.h>
32#include <linux/udp.h>
33#include <linux/if.h>
34#include <linux/list.h>
35#include <linux/if_ether.h>
36#include <net/ip.h>
37
38#include "ehea.h"
39#include "ehea_qmr.h"
40#include "ehea_phyp.h"
41
42
43MODULE_LICENSE("GPL");
44MODULE_AUTHOR("Christoph Raisch <raisch@de.ibm.com>");
45MODULE_DESCRIPTION("IBM eServer HEA Driver");
46MODULE_VERSION(DRV_VERSION);
47
48
49static int msg_level = -1;
50static int rq1_entries = EHEA_DEF_ENTRIES_RQ1;
51static int rq2_entries = EHEA_DEF_ENTRIES_RQ2;
52static int rq3_entries = EHEA_DEF_ENTRIES_RQ3;
53static int sq_entries = EHEA_DEF_ENTRIES_SQ;
Jan-Bernd Themann18604c52007-02-28 18:34:10 +010054static int use_mcs = 0;
55static int num_tx_qps = EHEA_NUM_TX_QP;
Jan-Bernd Themann8759cf72007-09-07 12:30:17 +020056static int prop_carrier_state = 0;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +020057
58module_param(msg_level, int, 0);
59module_param(rq1_entries, int, 0);
60module_param(rq2_entries, int, 0);
61module_param(rq3_entries, int, 0);
62module_param(sq_entries, int, 0);
Jan-Bernd Themann8759cf72007-09-07 12:30:17 +020063module_param(prop_carrier_state, int, 0);
Jan-Bernd Themann18604c52007-02-28 18:34:10 +010064module_param(use_mcs, int, 0);
65module_param(num_tx_qps, int, 0);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +020066
Jan-Bernd Themann18604c52007-02-28 18:34:10 +010067MODULE_PARM_DESC(num_tx_qps, "Number of TX-QPS");
Jan-Bernd Themann7a291082006-09-13 17:44:31 +020068MODULE_PARM_DESC(msg_level, "msg_level");
Jan-Bernd Themann8759cf72007-09-07 12:30:17 +020069MODULE_PARM_DESC(prop_carrier_state, "Propagate carrier state of physical "
70 "port to stack. 1:yes, 0:no. Default = 0 ");
Jan-Bernd Themann7a291082006-09-13 17:44:31 +020071MODULE_PARM_DESC(rq3_entries, "Number of entries for Receive Queue 3 "
72 "[2^x - 1], x = [6..14]. Default = "
73 __MODULE_STRING(EHEA_DEF_ENTRIES_RQ3) ")");
74MODULE_PARM_DESC(rq2_entries, "Number of entries for Receive Queue 2 "
75 "[2^x - 1], x = [6..14]. Default = "
76 __MODULE_STRING(EHEA_DEF_ENTRIES_RQ2) ")");
77MODULE_PARM_DESC(rq1_entries, "Number of entries for Receive Queue 1 "
78 "[2^x - 1], x = [6..14]. Default = "
79 __MODULE_STRING(EHEA_DEF_ENTRIES_RQ1) ")");
80MODULE_PARM_DESC(sq_entries, " Number of entries for the Send Queue "
81 "[2^x - 1], x = [6..14]. Default = "
82 __MODULE_STRING(EHEA_DEF_ENTRIES_SQ) ")");
Jan-Bernd Themann18072a52007-08-22 16:21:24 +020083MODULE_PARM_DESC(use_mcs, " 0:NAPI, 1:Multiple receive queues, Default = 0 ");
Jan-Bernd Themann7a291082006-09-13 17:44:31 +020084
Thomas Kleind1dea382007-04-26 11:56:13 +020085static int port_name_cnt = 0;
Thomas Klein44c82152007-07-11 16:32:00 +020086static LIST_HEAD(adapter_list);
87u64 ehea_driver_flags = 0;
88struct workqueue_struct *ehea_driver_wq;
89struct work_struct ehea_rereg_mr_task;
90
Thomas Kleind1dea382007-04-26 11:56:13 +020091
92static int __devinit ehea_probe_adapter(struct ibmebus_dev *dev,
Jan-Bernd Themannd1d25aa2007-07-02 13:00:46 +020093 const struct of_device_id *id);
Thomas Kleind1dea382007-04-26 11:56:13 +020094
95static int __devexit ehea_remove(struct ibmebus_dev *dev);
96
97static struct of_device_id ehea_device_table[] = {
98 {
99 .name = "lhea",
100 .compatible = "IBM,lhea",
101 },
102 {},
103};
104
105static struct ibmebus_driver ehea_driver = {
106 .name = "ehea",
107 .id_table = ehea_device_table,
108 .probe = ehea_probe_adapter,
109 .remove = ehea_remove,
110};
111
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200112void ehea_dump(void *adr, int len, char *msg) {
113 int x;
114 unsigned char *deb = adr;
115 for (x = 0; x < len; x += 16) {
Jan-Bernd Themannd2db9ee2007-02-09 09:10:51 +0100116 printk(DRV_NAME " %s adr=%p ofs=%04x %016lx %016lx\n", msg,
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200117 deb, x, *((u64*)&deb[0]), *((u64*)&deb[8]));
118 deb += 16;
119 }
120}
121
122static struct net_device_stats *ehea_get_stats(struct net_device *dev)
123{
124 struct ehea_port *port = netdev_priv(dev);
125 struct net_device_stats *stats = &port->stats;
126 struct hcp_ehea_port_cb2 *cb2;
127 u64 hret, rx_packets;
128 int i;
129
130 memset(stats, 0, sizeof(*stats));
131
Thomas Kleina1d261c2006-11-03 17:48:23 +0100132 cb2 = kzalloc(PAGE_SIZE, GFP_KERNEL);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200133 if (!cb2) {
134 ehea_error("no mem for cb2");
135 goto out;
136 }
137
138 hret = ehea_h_query_ehea_port(port->adapter->handle,
139 port->logical_port_id,
140 H_PORT_CB2, H_PORT_CB2_ALL, cb2);
141 if (hret != H_SUCCESS) {
142 ehea_error("query_ehea_port failed");
143 goto out_herr;
144 }
145
146 if (netif_msg_hw(port))
147 ehea_dump(cb2, sizeof(*cb2), "net_device_stats");
148
149 rx_packets = 0;
150 for (i = 0; i < port->num_def_qps; i++)
151 rx_packets += port->port_res[i].rx_packets;
152
153 stats->tx_packets = cb2->txucp + cb2->txmcp + cb2->txbcp;
154 stats->multicast = cb2->rxmcp;
155 stats->rx_errors = cb2->rxuerr;
156 stats->rx_bytes = cb2->rxo;
157 stats->tx_bytes = cb2->txo;
158 stats->rx_packets = rx_packets;
159
160out_herr:
161 kfree(cb2);
162out:
163 return stats;
164}
165
166static void ehea_refill_rq1(struct ehea_port_res *pr, int index, int nr_of_wqes)
167{
168 struct sk_buff **skb_arr_rq1 = pr->rq1_skba.arr;
169 struct net_device *dev = pr->port->netdev;
170 int max_index_mask = pr->rq1_skba.len - 1;
171 int i;
172
173 if (!nr_of_wqes)
174 return;
175
176 for (i = 0; i < nr_of_wqes; i++) {
177 if (!skb_arr_rq1[index]) {
178 skb_arr_rq1[index] = netdev_alloc_skb(dev,
179 EHEA_L_PKT_SIZE);
180 if (!skb_arr_rq1[index]) {
181 ehea_error("%s: no mem for skb/%d wqes filled",
182 dev->name, i);
183 break;
184 }
185 }
186 index--;
187 index &= max_index_mask;
188 }
189 /* Ring doorbell */
190 ehea_update_rq1a(pr->qp, i);
191}
192
193static int ehea_init_fill_rq1(struct ehea_port_res *pr, int nr_rq1a)
194{
195 int ret = 0;
196 struct sk_buff **skb_arr_rq1 = pr->rq1_skba.arr;
197 struct net_device *dev = pr->port->netdev;
198 int i;
199
200 for (i = 0; i < pr->rq1_skba.len; i++) {
201 skb_arr_rq1[i] = netdev_alloc_skb(dev, EHEA_L_PKT_SIZE);
202 if (!skb_arr_rq1[i]) {
203 ehea_error("%s: no mem for skb/%d wqes filled",
204 dev->name, i);
205 ret = -ENOMEM;
206 goto out;
207 }
208 }
209 /* Ring doorbell */
210 ehea_update_rq1a(pr->qp, nr_rq1a);
211out:
212 return ret;
213}
214
215static int ehea_refill_rq_def(struct ehea_port_res *pr,
216 struct ehea_q_skb_arr *q_skba, int rq_nr,
217 int num_wqes, int wqe_type, int packet_size)
218{
219 struct net_device *dev = pr->port->netdev;
220 struct ehea_qp *qp = pr->qp;
221 struct sk_buff **skb_arr = q_skba->arr;
222 struct ehea_rwqe *rwqe;
223 int i, index, max_index_mask, fill_wqes;
224 int ret = 0;
225
226 fill_wqes = q_skba->os_skbs + num_wqes;
227
228 if (!fill_wqes)
229 return ret;
230
231 index = q_skba->index;
232 max_index_mask = q_skba->len - 1;
233 for (i = 0; i < fill_wqes; i++) {
234 struct sk_buff *skb = netdev_alloc_skb(dev, packet_size);
235 if (!skb) {
236 ehea_error("%s: no mem for skb/%d wqes filled",
Jan-Bernd Themann18604c52007-02-28 18:34:10 +0100237 pr->port->netdev->name, i);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200238 q_skba->os_skbs = fill_wqes - i;
239 ret = -ENOMEM;
240 break;
241 }
242 skb_reserve(skb, NET_IP_ALIGN);
243
244 skb_arr[index] = skb;
245
246 rwqe = ehea_get_next_rwqe(qp, rq_nr);
247 rwqe->wr_id = EHEA_BMASK_SET(EHEA_WR_ID_TYPE, wqe_type)
Jan-Bernd Themannd1d25aa2007-07-02 13:00:46 +0200248 | EHEA_BMASK_SET(EHEA_WR_ID_INDEX, index);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200249 rwqe->sg_list[0].l_key = pr->recv_mr.lkey;
Thomas Klein44c82152007-07-11 16:32:00 +0200250 rwqe->sg_list[0].vaddr = ehea_map_vaddr(skb->data);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200251 rwqe->sg_list[0].len = packet_size;
252 rwqe->data_segments = 1;
253
254 index++;
255 index &= max_index_mask;
Thomas Klein44c82152007-07-11 16:32:00 +0200256
257 if (unlikely(test_bit(__EHEA_STOP_XFER, &ehea_driver_flags)))
258 goto out;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200259 }
Thomas Klein44c82152007-07-11 16:32:00 +0200260
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200261 q_skba->index = index;
262
263 /* Ring doorbell */
264 iosync();
265 if (rq_nr == 2)
266 ehea_update_rq2a(pr->qp, i);
267 else
268 ehea_update_rq3a(pr->qp, i);
Thomas Klein44c82152007-07-11 16:32:00 +0200269out:
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200270 return ret;
271}
272
273
274static int ehea_refill_rq2(struct ehea_port_res *pr, int nr_of_wqes)
275{
276 return ehea_refill_rq_def(pr, &pr->rq2_skba, 2,
277 nr_of_wqes, EHEA_RWQE2_TYPE,
278 EHEA_RQ2_PKT_SIZE + NET_IP_ALIGN);
279}
280
281
282static int ehea_refill_rq3(struct ehea_port_res *pr, int nr_of_wqes)
283{
284 return ehea_refill_rq_def(pr, &pr->rq3_skba, 3,
285 nr_of_wqes, EHEA_RWQE3_TYPE,
286 EHEA_MAX_PACKET_SIZE + NET_IP_ALIGN);
287}
288
289static inline int ehea_check_cqe(struct ehea_cqe *cqe, int *rq_num)
290{
291 *rq_num = (cqe->type & EHEA_CQE_TYPE_RQ) >> 5;
292 if ((cqe->status & EHEA_CQE_STAT_ERR_MASK) == 0)
293 return 0;
294 if (((cqe->status & EHEA_CQE_STAT_ERR_TCP) != 0) &&
295 (cqe->header_length == 0))
296 return 0;
297 return -EINVAL;
298}
299
300static inline void ehea_fill_skb(struct net_device *dev,
301 struct sk_buff *skb, struct ehea_cqe *cqe)
302{
303 int length = cqe->num_bytes_transfered - 4; /*remove CRC */
304
305 skb_put(skb, length);
306 skb->ip_summed = CHECKSUM_UNNECESSARY;
307 skb->protocol = eth_type_trans(skb, dev);
308}
309
310static inline struct sk_buff *get_skb_by_index(struct sk_buff **skb_array,
311 int arr_len,
312 struct ehea_cqe *cqe)
313{
314 int skb_index = EHEA_BMASK_GET(EHEA_WR_ID_INDEX, cqe->wr_id);
315 struct sk_buff *skb;
316 void *pref;
317 int x;
318
319 x = skb_index + 1;
320 x &= (arr_len - 1);
321
322 pref = skb_array[x];
323 prefetchw(pref);
324 prefetchw(pref + EHEA_CACHE_LINE);
325
326 pref = (skb_array[x]->data);
327 prefetch(pref);
328 prefetch(pref + EHEA_CACHE_LINE);
329 prefetch(pref + EHEA_CACHE_LINE * 2);
330 prefetch(pref + EHEA_CACHE_LINE * 3);
331 skb = skb_array[skb_index];
332 skb_array[skb_index] = NULL;
333 return skb;
334}
335
336static inline struct sk_buff *get_skb_by_index_ll(struct sk_buff **skb_array,
337 int arr_len, int wqe_index)
338{
339 struct sk_buff *skb;
340 void *pref;
341 int x;
342
343 x = wqe_index + 1;
344 x &= (arr_len - 1);
345
346 pref = skb_array[x];
347 prefetchw(pref);
348 prefetchw(pref + EHEA_CACHE_LINE);
349
350 pref = (skb_array[x]->data);
351 prefetchw(pref);
352 prefetchw(pref + EHEA_CACHE_LINE);
353
354 skb = skb_array[wqe_index];
355 skb_array[wqe_index] = NULL;
356 return skb;
357}
358
359static int ehea_treat_poll_error(struct ehea_port_res *pr, int rq,
360 struct ehea_cqe *cqe, int *processed_rq2,
361 int *processed_rq3)
362{
363 struct sk_buff *skb;
364
Jan-Bernd Themannacbddb52007-03-23 17:18:53 +0100365 if (cqe->status & EHEA_CQE_STAT_ERR_TCP)
366 pr->p_stats.err_tcp_cksum++;
367 if (cqe->status & EHEA_CQE_STAT_ERR_IP)
368 pr->p_stats.err_ip_cksum++;
369 if (cqe->status & EHEA_CQE_STAT_ERR_CRC)
370 pr->p_stats.err_frame_crc++;
371
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200372 if (netif_msg_rx_err(pr->port)) {
373 ehea_error("CQE Error for QP %d", pr->qp->init_attr.qp_nr);
374 ehea_dump(cqe, sizeof(*cqe), "CQE");
375 }
376
377 if (rq == 2) {
378 *processed_rq2 += 1;
379 skb = get_skb_by_index(pr->rq2_skba.arr, pr->rq2_skba.len, cqe);
380 dev_kfree_skb(skb);
381 } else if (rq == 3) {
382 *processed_rq3 += 1;
383 skb = get_skb_by_index(pr->rq3_skba.arr, pr->rq3_skba.len, cqe);
384 dev_kfree_skb(skb);
385 }
386
387 if (cqe->status & EHEA_CQE_STAT_FAT_ERR_MASK) {
388 ehea_error("Critical receive error. Resetting port.");
389 queue_work(pr->port->adapter->ehea_wq, &pr->port->reset_task);
390 return 1;
391 }
392
393 return 0;
394}
395
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700396static int ehea_proc_rwqes(struct net_device *dev,
397 struct ehea_port_res *pr,
398 int budget)
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200399{
Jan-Bernd Themann18604c52007-02-28 18:34:10 +0100400 struct ehea_port *port = pr->port;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200401 struct ehea_qp *qp = pr->qp;
402 struct ehea_cqe *cqe;
403 struct sk_buff *skb;
404 struct sk_buff **skb_arr_rq1 = pr->rq1_skba.arr;
405 struct sk_buff **skb_arr_rq2 = pr->rq2_skba.arr;
406 struct sk_buff **skb_arr_rq3 = pr->rq3_skba.arr;
407 int skb_arr_rq1_len = pr->rq1_skba.len;
408 int skb_arr_rq2_len = pr->rq2_skba.len;
409 int skb_arr_rq3_len = pr->rq3_skba.len;
410 int processed, processed_rq1, processed_rq2, processed_rq3;
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700411 int wqe_index, last_wqe_index, rq, port_reset;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200412
413 processed = processed_rq1 = processed_rq2 = processed_rq3 = 0;
414 last_wqe_index = 0;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200415
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200416 cqe = ehea_poll_rq1(qp, &wqe_index);
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700417 while ((processed < budget) && cqe) {
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200418 ehea_inc_rq1(qp);
419 processed_rq1++;
420 processed++;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200421 if (netif_msg_rx_status(port))
422 ehea_dump(cqe, sizeof(*cqe), "CQE");
423
424 last_wqe_index = wqe_index;
425 rmb();
426 if (!ehea_check_cqe(cqe, &rq)) {
427 if (rq == 1) { /* LL RQ1 */
428 skb = get_skb_by_index_ll(skb_arr_rq1,
429 skb_arr_rq1_len,
430 wqe_index);
431 if (unlikely(!skb)) {
432 if (netif_msg_rx_err(port))
433 ehea_error("LL rq1: skb=NULL");
Jan-Bernd Themann18604c52007-02-28 18:34:10 +0100434
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700435 skb = netdev_alloc_skb(dev,
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200436 EHEA_L_PKT_SIZE);
437 if (!skb)
438 break;
439 }
Arnaldo Carvalho de Melo27d7ff42007-03-31 11:55:19 -0300440 skb_copy_to_linear_data(skb, ((char*)cqe) + 64,
Jan-Bernd Themannd1d25aa2007-07-02 13:00:46 +0200441 cqe->num_bytes_transfered - 4);
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700442 ehea_fill_skb(dev, skb, cqe);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200443 } else if (rq == 2) { /* RQ2 */
444 skb = get_skb_by_index(skb_arr_rq2,
445 skb_arr_rq2_len, cqe);
446 if (unlikely(!skb)) {
447 if (netif_msg_rx_err(port))
448 ehea_error("rq2: skb=NULL");
449 break;
450 }
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700451 ehea_fill_skb(dev, skb, cqe);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200452 processed_rq2++;
453 } else { /* RQ3 */
454 skb = get_skb_by_index(skb_arr_rq3,
455 skb_arr_rq3_len, cqe);
456 if (unlikely(!skb)) {
457 if (netif_msg_rx_err(port))
458 ehea_error("rq3: skb=NULL");
459 break;
460 }
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700461 ehea_fill_skb(dev, skb, cqe);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200462 processed_rq3++;
463 }
464
Thomas Kleindec590c2007-06-06 20:53:16 +0200465 if ((cqe->status & EHEA_CQE_VLAN_TAG_XTRACT)
466 && port->vgrp)
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200467 vlan_hwaccel_receive_skb(skb, port->vgrp,
468 cqe->vlan_tag);
469 else
470 netif_receive_skb(skb);
Thomas Kleinf9e29222007-07-18 17:34:09 +0200471
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700472 dev->last_rx = jiffies;
Jan-Bernd Themann18604c52007-02-28 18:34:10 +0100473 } else {
Jan-Bernd Themannacbddb52007-03-23 17:18:53 +0100474 pr->p_stats.poll_receive_errors++;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200475 port_reset = ehea_treat_poll_error(pr, rq, cqe,
476 &processed_rq2,
477 &processed_rq3);
478 if (port_reset)
479 break;
480 }
481 cqe = ehea_poll_rq1(qp, &wqe_index);
482 }
483
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200484 pr->rx_packets += processed;
485
486 ehea_refill_rq1(pr, last_wqe_index, processed_rq1);
487 ehea_refill_rq2(pr, processed_rq2);
488 ehea_refill_rq3(pr, processed_rq3);
489
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700490 return processed;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200491}
492
Jan-Bernd Themann18604c52007-02-28 18:34:10 +0100493static struct ehea_cqe *ehea_proc_cqes(struct ehea_port_res *pr, int my_quota)
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200494{
Jan-Bernd Themannacbddb52007-03-23 17:18:53 +0100495 struct sk_buff *skb;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200496 struct ehea_cq *send_cq = pr->send_cq;
497 struct ehea_cqe *cqe;
Jan-Bernd Themann18604c52007-02-28 18:34:10 +0100498 int quota = my_quota;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200499 int cqe_counter = 0;
500 int swqe_av = 0;
Jan-Bernd Themannacbddb52007-03-23 17:18:53 +0100501 int index;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200502 unsigned long flags;
503
Jan-Bernd Themann18604c52007-02-28 18:34:10 +0100504 cqe = ehea_poll_cq(send_cq);
505 while(cqe && (quota > 0)) {
506 ehea_inc_cq(send_cq);
507
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200508 cqe_counter++;
509 rmb();
510 if (cqe->status & EHEA_CQE_STAT_ERR_MASK) {
511 ehea_error("Send Completion Error: Resetting port");
512 if (netif_msg_tx_err(pr->port))
513 ehea_dump(cqe, sizeof(*cqe), "Send CQE");
514 queue_work(pr->port->adapter->ehea_wq,
515 &pr->port->reset_task);
516 break;
517 }
518
519 if (netif_msg_tx_done(pr->port))
520 ehea_dump(cqe, sizeof(*cqe), "CQE");
521
522 if (likely(EHEA_BMASK_GET(EHEA_WR_ID_TYPE, cqe->wr_id)
Jan-Bernd Themannacbddb52007-03-23 17:18:53 +0100523 == EHEA_SWQE2_TYPE)) {
524
525 index = EHEA_BMASK_GET(EHEA_WR_ID_INDEX, cqe->wr_id);
526 skb = pr->sq_skba.arr[index];
527 dev_kfree_skb(skb);
528 pr->sq_skba.arr[index] = NULL;
529 }
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200530
531 swqe_av += EHEA_BMASK_GET(EHEA_WR_ID_REFILL, cqe->wr_id);
532 quota--;
Jan-Bernd Themann18604c52007-02-28 18:34:10 +0100533
534 cqe = ehea_poll_cq(send_cq);
535 };
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200536
537 ehea_update_feca(send_cq, cqe_counter);
538 atomic_add(swqe_av, &pr->swqe_avail);
539
540 spin_lock_irqsave(&pr->netif_queue, flags);
Jan-Bernd Themann18604c52007-02-28 18:34:10 +0100541
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200542 if (pr->queue_stopped && (atomic_read(&pr->swqe_avail)
543 >= pr->swqe_refill_th)) {
544 netif_wake_queue(pr->port->netdev);
545 pr->queue_stopped = 0;
546 }
547 spin_unlock_irqrestore(&pr->netif_queue, flags);
548
Jan-Bernd Themann18604c52007-02-28 18:34:10 +0100549 return cqe;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200550}
551
Jan-Bernd Themann18604c52007-02-28 18:34:10 +0100552#define EHEA_NAPI_POLL_NUM_BEFORE_IRQ 16
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700553#define EHEA_POLL_MAX_CQES 65535
Jan-Bernd Themann18604c52007-02-28 18:34:10 +0100554
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700555static int ehea_poll(struct napi_struct *napi, int budget)
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200556{
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700557 struct ehea_port_res *pr = container_of(napi, struct ehea_port_res, napi);
558 struct net_device *dev = pr->port->netdev;
Jan-Bernd Themann18604c52007-02-28 18:34:10 +0100559 struct ehea_cqe *cqe;
560 struct ehea_cqe *cqe_skb = NULL;
561 int force_irq, wqe_index;
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700562 int rx = 0;
Jan-Bernd Themann18604c52007-02-28 18:34:10 +0100563
564 force_irq = (pr->poll_counter > EHEA_NAPI_POLL_NUM_BEFORE_IRQ);
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700565 cqe_skb = ehea_proc_cqes(pr, EHEA_POLL_MAX_CQES);
Jan-Bernd Themann18604c52007-02-28 18:34:10 +0100566
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700567 if (!force_irq)
568 rx += ehea_proc_rwqes(dev, pr, budget - rx);
569
570 while ((rx != budget) || force_irq) {
Jan-Bernd Themann18604c52007-02-28 18:34:10 +0100571 pr->poll_counter = 0;
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700572 force_irq = 0;
573 netif_rx_complete(dev, napi);
Jan-Bernd Themann18604c52007-02-28 18:34:10 +0100574 ehea_reset_cq_ep(pr->recv_cq);
575 ehea_reset_cq_ep(pr->send_cq);
576 ehea_reset_cq_n1(pr->recv_cq);
577 ehea_reset_cq_n1(pr->send_cq);
578 cqe = ehea_poll_rq1(pr->qp, &wqe_index);
579 cqe_skb = ehea_poll_cq(pr->send_cq);
580
Jan-Bernd Themanne542aa62007-03-22 17:50:24 +0100581 if (!cqe && !cqe_skb)
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700582 return rx;
Jan-Bernd Themann18604c52007-02-28 18:34:10 +0100583
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700584 if (!netif_rx_reschedule(dev, napi))
585 return rx;
586
587 cqe_skb = ehea_proc_cqes(pr, EHEA_POLL_MAX_CQES);
588 rx += ehea_proc_rwqes(dev, pr, budget - rx);
Jan-Bernd Themann18604c52007-02-28 18:34:10 +0100589 }
Jan-Bernd Themanne542aa62007-03-22 17:50:24 +0100590
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700591 pr->poll_counter++;
592 return rx;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200593}
594
Jan-Bernd Themann8d22c972007-07-23 16:05:03 +0200595#ifdef CONFIG_NET_POLL_CONTROLLER
596static void ehea_netpoll(struct net_device *dev)
597{
598 struct ehea_port *port = netdev_priv(dev);
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700599 int i;
Jan-Bernd Themann8d22c972007-07-23 16:05:03 +0200600
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700601 for (i = 0; i < port->num_def_qps; i++)
602 netif_rx_schedule(dev, &port->port_res[i].napi);
Jan-Bernd Themann8d22c972007-07-23 16:05:03 +0200603}
604#endif
605
David Howells7d12e782006-10-05 14:55:46 +0100606static irqreturn_t ehea_recv_irq_handler(int irq, void *param)
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200607{
608 struct ehea_port_res *pr = param;
Jan-Bernd Themann18604c52007-02-28 18:34:10 +0100609
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700610 netif_rx_schedule(pr->port->netdev, &pr->napi);
Jan-Bernd Themann18604c52007-02-28 18:34:10 +0100611
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200612 return IRQ_HANDLED;
613}
614
David Howells7d12e782006-10-05 14:55:46 +0100615static irqreturn_t ehea_qp_aff_irq_handler(int irq, void *param)
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200616{
617 struct ehea_port *port = param;
618 struct ehea_eqe *eqe;
Jan-Bernd Themannd2db9ee2007-02-09 09:10:51 +0100619 struct ehea_qp *qp;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200620 u32 qp_token;
621
622 eqe = ehea_poll_eq(port->qp_eq);
Thomas Kleinbb3a6442007-01-22 12:54:50 +0100623
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200624 while (eqe) {
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200625 qp_token = EHEA_BMASK_GET(EHEA_EQE_QP_TOKEN, eqe->entry);
Thomas Kleinbb3a6442007-01-22 12:54:50 +0100626 ehea_error("QP aff_err: entry=0x%lx, token=0x%x",
627 eqe->entry, qp_token);
Jan-Bernd Themannd2db9ee2007-02-09 09:10:51 +0100628
629 qp = port->port_res[qp_token].qp;
630 ehea_error_data(port->adapter, qp->fw_handle);
Thomas Kleinbb3a6442007-01-22 12:54:50 +0100631 eqe = ehea_poll_eq(port->qp_eq);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200632 }
633
Jan-Bernd Themannd2db9ee2007-02-09 09:10:51 +0100634 queue_work(port->adapter->ehea_wq, &port->reset_task);
635
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200636 return IRQ_HANDLED;
637}
638
639static struct ehea_port *ehea_get_port(struct ehea_adapter *adapter,
640 int logical_port)
641{
642 int i;
643
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +0100644 for (i = 0; i < EHEA_MAX_PORTS; i++)
Thomas Klein41b69c72007-01-22 12:55:20 +0100645 if (adapter->port[i])
Jan-Bernd Themannd1d25aa2007-07-02 13:00:46 +0200646 if (adapter->port[i]->logical_port_id == logical_port)
Thomas Klein41b69c72007-01-22 12:55:20 +0100647 return adapter->port[i];
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200648 return NULL;
649}
650
651int ehea_sense_port_attr(struct ehea_port *port)
652{
653 int ret;
654 u64 hret;
655 struct hcp_ehea_port_cb0 *cb0;
656
Thomas Kleina1d261c2006-11-03 17:48:23 +0100657 cb0 = kzalloc(PAGE_SIZE, GFP_ATOMIC); /* May be called via */
658 if (!cb0) { /* ehea_neq_tasklet() */
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200659 ehea_error("no mem for cb0");
660 ret = -ENOMEM;
661 goto out;
662 }
663
664 hret = ehea_h_query_ehea_port(port->adapter->handle,
665 port->logical_port_id, H_PORT_CB0,
666 EHEA_BMASK_SET(H_PORT_CB0_ALL, 0xFFFF),
667 cb0);
668 if (hret != H_SUCCESS) {
669 ret = -EIO;
670 goto out_free;
671 }
672
673 /* MAC address */
674 port->mac_addr = cb0->port_mac_addr << 16;
675
676 if (!is_valid_ether_addr((u8*)&port->mac_addr)) {
677 ret = -EADDRNOTAVAIL;
678 goto out_free;
679 }
680
681 /* Port speed */
682 switch (cb0->port_speed) {
683 case H_SPEED_10M_H:
684 port->port_speed = EHEA_SPEED_10M;
685 port->full_duplex = 0;
686 break;
687 case H_SPEED_10M_F:
688 port->port_speed = EHEA_SPEED_10M;
689 port->full_duplex = 1;
690 break;
691 case H_SPEED_100M_H:
692 port->port_speed = EHEA_SPEED_100M;
693 port->full_duplex = 0;
694 break;
695 case H_SPEED_100M_F:
696 port->port_speed = EHEA_SPEED_100M;
697 port->full_duplex = 1;
698 break;
699 case H_SPEED_1G_F:
700 port->port_speed = EHEA_SPEED_1G;
701 port->full_duplex = 1;
702 break;
703 case H_SPEED_10G_F:
704 port->port_speed = EHEA_SPEED_10G;
705 port->full_duplex = 1;
706 break;
707 default:
708 port->port_speed = 0;
709 port->full_duplex = 0;
710 break;
711 }
712
Thomas Kleine919b592007-01-22 12:53:20 +0100713 port->autoneg = 1;
Jan-Bernd Themann18604c52007-02-28 18:34:10 +0100714 port->num_mcs = cb0->num_default_qps;
Thomas Kleine919b592007-01-22 12:53:20 +0100715
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200716 /* Number of default QPs */
Jan-Bernd Themann18604c52007-02-28 18:34:10 +0100717 if (use_mcs)
718 port->num_def_qps = cb0->num_default_qps;
719 else
720 port->num_def_qps = 1;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200721
722 if (!port->num_def_qps) {
723 ret = -EINVAL;
724 goto out_free;
725 }
726
Jan-Bernd Themann18604c52007-02-28 18:34:10 +0100727 port->num_tx_qps = num_tx_qps;
728
729 if (port->num_def_qps >= port->num_tx_qps)
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200730 port->num_add_tx_qps = 0;
731 else
Jan-Bernd Themann18604c52007-02-28 18:34:10 +0100732 port->num_add_tx_qps = port->num_tx_qps - port->num_def_qps;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200733
734 ret = 0;
735out_free:
736 if (ret || netif_msg_probe(port))
737 ehea_dump(cb0, sizeof(*cb0), "ehea_sense_port_attr");
738 kfree(cb0);
739out:
740 return ret;
741}
742
743int ehea_set_portspeed(struct ehea_port *port, u32 port_speed)
744{
745 struct hcp_ehea_port_cb4 *cb4;
746 u64 hret;
747 int ret = 0;
748
Thomas Kleina1d261c2006-11-03 17:48:23 +0100749 cb4 = kzalloc(PAGE_SIZE, GFP_KERNEL);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200750 if (!cb4) {
751 ehea_error("no mem for cb4");
752 ret = -ENOMEM;
753 goto out;
754 }
755
756 cb4->port_speed = port_speed;
757
758 netif_carrier_off(port->netdev);
759
760 hret = ehea_h_modify_ehea_port(port->adapter->handle,
761 port->logical_port_id,
762 H_PORT_CB4, H_PORT_CB4_SPEED, cb4);
763 if (hret == H_SUCCESS) {
764 port->autoneg = port_speed == EHEA_SPEED_AUTONEG ? 1 : 0;
765
766 hret = ehea_h_query_ehea_port(port->adapter->handle,
767 port->logical_port_id,
768 H_PORT_CB4, H_PORT_CB4_SPEED,
769 cb4);
770 if (hret == H_SUCCESS) {
771 switch (cb4->port_speed) {
772 case H_SPEED_10M_H:
773 port->port_speed = EHEA_SPEED_10M;
774 port->full_duplex = 0;
775 break;
776 case H_SPEED_10M_F:
777 port->port_speed = EHEA_SPEED_10M;
778 port->full_duplex = 1;
779 break;
780 case H_SPEED_100M_H:
781 port->port_speed = EHEA_SPEED_100M;
782 port->full_duplex = 0;
783 break;
784 case H_SPEED_100M_F:
785 port->port_speed = EHEA_SPEED_100M;
786 port->full_duplex = 1;
787 break;
788 case H_SPEED_1G_F:
789 port->port_speed = EHEA_SPEED_1G;
790 port->full_duplex = 1;
791 break;
792 case H_SPEED_10G_F:
793 port->port_speed = EHEA_SPEED_10G;
794 port->full_duplex = 1;
795 break;
796 default:
797 port->port_speed = 0;
798 port->full_duplex = 0;
799 break;
800 }
801 } else {
802 ehea_error("Failed sensing port speed");
803 ret = -EIO;
804 }
805 } else {
806 if (hret == H_AUTHORITY) {
Thomas Klein7674a582007-01-22 12:54:20 +0100807 ehea_info("Hypervisor denied setting port speed");
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200808 ret = -EPERM;
809 } else {
810 ret = -EIO;
811 ehea_error("Failed setting port speed");
812 }
813 }
Jan-Bernd Themann8759cf72007-09-07 12:30:17 +0200814 if (!prop_carrier_state || (port->phy_link == EHEA_PHY_LINK_UP))
815 netif_carrier_on(port->netdev);
816
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200817 kfree(cb4);
818out:
819 return ret;
820}
821
822static void ehea_parse_eqe(struct ehea_adapter *adapter, u64 eqe)
823{
824 int ret;
825 u8 ec;
826 u8 portnum;
827 struct ehea_port *port;
828
829 ec = EHEA_BMASK_GET(NEQE_EVENT_CODE, eqe);
830 portnum = EHEA_BMASK_GET(NEQE_PORTNUM, eqe);
831 port = ehea_get_port(adapter, portnum);
832
833 switch (ec) {
834 case EHEA_EC_PORTSTATE_CHG: /* port state change */
835
836 if (!port) {
837 ehea_error("unknown portnum %x", portnum);
838 break;
839 }
840
841 if (EHEA_BMASK_GET(NEQE_PORT_UP, eqe)) {
842 if (!netif_carrier_ok(port->netdev)) {
Jan-Bernd Themann1e1675c2006-10-25 13:11:42 +0200843 ret = ehea_sense_port_attr(port);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200844 if (ret) {
845 ehea_error("failed resensing port "
846 "attributes");
847 break;
848 }
849
850 if (netif_msg_link(port))
851 ehea_info("%s: Logical port up: %dMbps "
852 "%s Duplex",
853 port->netdev->name,
854 port->port_speed,
855 port->full_duplex ==
856 1 ? "Full" : "Half");
857
858 netif_carrier_on(port->netdev);
859 netif_wake_queue(port->netdev);
860 }
861 } else
862 if (netif_carrier_ok(port->netdev)) {
863 if (netif_msg_link(port))
864 ehea_info("%s: Logical port down",
865 port->netdev->name);
866 netif_carrier_off(port->netdev);
867 netif_stop_queue(port->netdev);
868 }
869
870 if (EHEA_BMASK_GET(NEQE_EXTSWITCH_PORT_UP, eqe)) {
Jan-Bernd Themann8759cf72007-09-07 12:30:17 +0200871 port->phy_link = EHEA_PHY_LINK_UP;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200872 if (netif_msg_link(port))
873 ehea_info("%s: Physical port up",
874 port->netdev->name);
Jan-Bernd Themann8759cf72007-09-07 12:30:17 +0200875 if (prop_carrier_state)
876 netif_carrier_on(port->netdev);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200877 } else {
Jan-Bernd Themann8759cf72007-09-07 12:30:17 +0200878 port->phy_link = EHEA_PHY_LINK_DOWN;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200879 if (netif_msg_link(port))
880 ehea_info("%s: Physical port down",
881 port->netdev->name);
Jan-Bernd Themann8759cf72007-09-07 12:30:17 +0200882 if (prop_carrier_state)
883 netif_carrier_off(port->netdev);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200884 }
885
886 if (EHEA_BMASK_GET(NEQE_EXTSWITCH_PRIMARY, eqe))
887 ehea_info("External switch port is primary port");
888 else
889 ehea_info("External switch port is backup port");
890
891 break;
892 case EHEA_EC_ADAPTER_MALFUNC:
893 ehea_error("Adapter malfunction");
894 break;
895 case EHEA_EC_PORT_MALFUNC:
896 ehea_info("Port malfunction: Device: %s", port->netdev->name);
897 netif_carrier_off(port->netdev);
898 netif_stop_queue(port->netdev);
899 break;
900 default:
Jan-Bernd Themannbff0a552006-10-05 16:53:14 +0200901 ehea_error("unknown event code %x, eqe=0x%lX", ec, eqe);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200902 break;
903 }
904}
905
906static void ehea_neq_tasklet(unsigned long data)
907{
908 struct ehea_adapter *adapter = (struct ehea_adapter*)data;
909 struct ehea_eqe *eqe;
910 u64 event_mask;
911
912 eqe = ehea_poll_eq(adapter->neq);
913 ehea_debug("eqe=%p", eqe);
914
915 while (eqe) {
916 ehea_debug("*eqe=%lx", eqe->entry);
917 ehea_parse_eqe(adapter, eqe->entry);
918 eqe = ehea_poll_eq(adapter->neq);
919 ehea_debug("next eqe=%p", eqe);
920 }
921
922 event_mask = EHEA_BMASK_SET(NELR_PORTSTATE_CHG, 1)
923 | EHEA_BMASK_SET(NELR_ADAPTER_MALFUNC, 1)
924 | EHEA_BMASK_SET(NELR_PORT_MALFUNC, 1);
925
926 ehea_h_reset_events(adapter->handle,
927 adapter->neq->fw_handle, event_mask);
928}
929
David Howells7d12e782006-10-05 14:55:46 +0100930static irqreturn_t ehea_interrupt_neq(int irq, void *param)
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200931{
932 struct ehea_adapter *adapter = param;
933 tasklet_hi_schedule(&adapter->neq_tasklet);
934 return IRQ_HANDLED;
935}
936
937
938static int ehea_fill_port_res(struct ehea_port_res *pr)
939{
940 int ret;
941 struct ehea_qp_init_attr *init_attr = &pr->qp->init_attr;
942
943 ret = ehea_init_fill_rq1(pr, init_attr->act_nr_rwqes_rq1
944 - init_attr->act_nr_rwqes_rq2
945 - init_attr->act_nr_rwqes_rq3 - 1);
946
947 ret |= ehea_refill_rq2(pr, init_attr->act_nr_rwqes_rq2 - 1);
948
949 ret |= ehea_refill_rq3(pr, init_attr->act_nr_rwqes_rq3 - 1);
950
951 return ret;
952}
953
954static int ehea_reg_interrupts(struct net_device *dev)
955{
956 struct ehea_port *port = netdev_priv(dev);
957 struct ehea_port_res *pr;
958 int i, ret;
959
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200960
961 snprintf(port->int_aff_name, EHEA_IRQ_NAME_SIZE - 1, "%s-aff",
962 dev->name);
963
964 ret = ibmebus_request_irq(NULL, port->qp_eq->attr.ist1,
965 ehea_qp_aff_irq_handler,
Thomas Gleixner38515e92007-02-14 00:33:16 -0800966 IRQF_DISABLED, port->int_aff_name, port);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200967 if (ret) {
968 ehea_error("failed registering irq for qp_aff_irq_handler:"
969 "ist=%X", port->qp_eq->attr.ist1);
970 goto out_free_qpeq;
971 }
972
973 if (netif_msg_ifup(port))
974 ehea_info("irq_handle 0x%X for function qp_aff_irq_handler "
975 "registered", port->qp_eq->attr.ist1);
976
Jan-Bernd Themann18604c52007-02-28 18:34:10 +0100977
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200978 for (i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++) {
979 pr = &port->port_res[i];
980 snprintf(pr->int_send_name, EHEA_IRQ_NAME_SIZE - 1,
Jan-Bernd Themann18604c52007-02-28 18:34:10 +0100981 "%s-queue%d", dev->name, i);
982 ret = ibmebus_request_irq(NULL, pr->eq->attr.ist1,
983 ehea_recv_irq_handler,
Thomas Gleixner38515e92007-02-14 00:33:16 -0800984 IRQF_DISABLED, pr->int_send_name,
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200985 pr);
986 if (ret) {
Jan-Bernd Themann18604c52007-02-28 18:34:10 +0100987 ehea_error("failed registering irq for ehea_queue "
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200988 "port_res_nr:%d, ist=%X", i,
Jan-Bernd Themann18604c52007-02-28 18:34:10 +0100989 pr->eq->attr.ist1);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200990 goto out_free_req;
991 }
992 if (netif_msg_ifup(port))
Jan-Bernd Themann18604c52007-02-28 18:34:10 +0100993 ehea_info("irq_handle 0x%X for function ehea_queue_int "
994 "%d registered", pr->eq->attr.ist1, i);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200995 }
996out:
997 return ret;
998
Jan-Bernd Themann18604c52007-02-28 18:34:10 +0100999
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001000out_free_req:
1001 while (--i >= 0) {
Jan-Bernd Themann18604c52007-02-28 18:34:10 +01001002 u32 ist = port->port_res[i].eq->attr.ist1;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001003 ibmebus_free_irq(NULL, ist, &port->port_res[i]);
1004 }
Jan-Bernd Themann18604c52007-02-28 18:34:10 +01001005
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001006out_free_qpeq:
1007 ibmebus_free_irq(NULL, port->qp_eq->attr.ist1, port);
1008 i = port->num_def_qps;
Jan-Bernd Themann18604c52007-02-28 18:34:10 +01001009
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001010 goto out;
Jan-Bernd Themann18604c52007-02-28 18:34:10 +01001011
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001012}
1013
1014static void ehea_free_interrupts(struct net_device *dev)
1015{
1016 struct ehea_port *port = netdev_priv(dev);
1017 struct ehea_port_res *pr;
1018 int i;
1019
1020 /* send */
Jan-Bernd Themann18604c52007-02-28 18:34:10 +01001021
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001022 for (i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++) {
1023 pr = &port->port_res[i];
Jan-Bernd Themann18604c52007-02-28 18:34:10 +01001024 ibmebus_free_irq(NULL, pr->eq->attr.ist1, pr);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001025 if (netif_msg_intr(port))
1026 ehea_info("free send irq for res %d with handle 0x%X",
Jan-Bernd Themann18604c52007-02-28 18:34:10 +01001027 i, pr->eq->attr.ist1);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001028 }
1029
1030 /* associated events */
1031 ibmebus_free_irq(NULL, port->qp_eq->attr.ist1, port);
1032 if (netif_msg_intr(port))
1033 ehea_info("associated event interrupt for handle 0x%X freed",
1034 port->qp_eq->attr.ist1);
1035}
1036
1037static int ehea_configure_port(struct ehea_port *port)
1038{
1039 int ret, i;
1040 u64 hret, mask;
1041 struct hcp_ehea_port_cb0 *cb0;
1042
1043 ret = -ENOMEM;
Thomas Kleina1d261c2006-11-03 17:48:23 +01001044 cb0 = kzalloc(PAGE_SIZE, GFP_KERNEL);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001045 if (!cb0)
1046 goto out;
1047
1048 cb0->port_rc = EHEA_BMASK_SET(PXLY_RC_VALID, 1)
1049 | EHEA_BMASK_SET(PXLY_RC_IP_CHKSUM, 1)
1050 | EHEA_BMASK_SET(PXLY_RC_TCP_UDP_CHKSUM, 1)
1051 | EHEA_BMASK_SET(PXLY_RC_VLAN_XTRACT, 1)
1052 | EHEA_BMASK_SET(PXLY_RC_VLAN_TAG_FILTER,
1053 PXLY_RC_VLAN_FILTER)
1054 | EHEA_BMASK_SET(PXLY_RC_JUMBO_FRAME, 1);
1055
Jan-Bernd Themann18604c52007-02-28 18:34:10 +01001056 for (i = 0; i < port->num_mcs; i++)
1057 if (use_mcs)
1058 cb0->default_qpn_arr[i] =
1059 port->port_res[i].qp->init_attr.qp_nr;
1060 else
1061 cb0->default_qpn_arr[i] =
1062 port->port_res[0].qp->init_attr.qp_nr;
Jan-Bernd Themanne542aa62007-03-22 17:50:24 +01001063
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001064 if (netif_msg_ifup(port))
1065 ehea_dump(cb0, sizeof(*cb0), "ehea_configure_port");
1066
1067 mask = EHEA_BMASK_SET(H_PORT_CB0_PRC, 1)
1068 | EHEA_BMASK_SET(H_PORT_CB0_DEFQPNARRAY, 1);
1069
1070 hret = ehea_h_modify_ehea_port(port->adapter->handle,
1071 port->logical_port_id,
1072 H_PORT_CB0, mask, cb0);
1073 ret = -EIO;
1074 if (hret != H_SUCCESS)
1075 goto out_free;
1076
1077 ret = 0;
1078
1079out_free:
1080 kfree(cb0);
1081out:
1082 return ret;
1083}
1084
Jan-Bernd Themanne542aa62007-03-22 17:50:24 +01001085int ehea_gen_smrs(struct ehea_port_res *pr)
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001086{
Jan-Bernd Themanne542aa62007-03-22 17:50:24 +01001087 int ret;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001088 struct ehea_adapter *adapter = pr->port->adapter;
1089
Jan-Bernd Themanne542aa62007-03-22 17:50:24 +01001090 ret = ehea_gen_smr(adapter, &adapter->mr, &pr->send_mr);
1091 if (ret)
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001092 goto out;
1093
Jan-Bernd Themanne542aa62007-03-22 17:50:24 +01001094 ret = ehea_gen_smr(adapter, &adapter->mr, &pr->recv_mr);
1095 if (ret)
1096 goto out_free;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001097
1098 return 0;
1099
Jan-Bernd Themanne542aa62007-03-22 17:50:24 +01001100out_free:
1101 ehea_rem_mr(&pr->send_mr);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001102out:
Jan-Bernd Themanne542aa62007-03-22 17:50:24 +01001103 ehea_error("Generating SMRS failed\n");
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001104 return -EIO;
1105}
1106
Jan-Bernd Themanne542aa62007-03-22 17:50:24 +01001107int ehea_rem_smrs(struct ehea_port_res *pr)
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001108{
Jan-Bernd Themanne542aa62007-03-22 17:50:24 +01001109 if ((ehea_rem_mr(&pr->send_mr))
1110 || (ehea_rem_mr(&pr->recv_mr)))
1111 return -EIO;
1112 else
1113 return 0;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001114}
1115
1116static int ehea_init_q_skba(struct ehea_q_skb_arr *q_skba, int max_q_entries)
1117{
1118 int arr_size = sizeof(void*) * max_q_entries;
1119
1120 q_skba->arr = vmalloc(arr_size);
1121 if (!q_skba->arr)
1122 return -ENOMEM;
1123
1124 memset(q_skba->arr, 0, arr_size);
1125
1126 q_skba->len = max_q_entries;
1127 q_skba->index = 0;
1128 q_skba->os_skbs = 0;
1129
1130 return 0;
1131}
1132
1133static int ehea_init_port_res(struct ehea_port *port, struct ehea_port_res *pr,
1134 struct port_res_cfg *pr_cfg, int queue_token)
1135{
1136 struct ehea_adapter *adapter = port->adapter;
1137 enum ehea_eq_type eq_type = EHEA_EQ;
1138 struct ehea_qp_init_attr *init_attr = NULL;
1139 int ret = -EIO;
1140
1141 memset(pr, 0, sizeof(struct ehea_port_res));
1142
1143 pr->port = port;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001144 spin_lock_init(&pr->xmit_lock);
1145 spin_lock_init(&pr->netif_queue);
1146
Jan-Bernd Themann18604c52007-02-28 18:34:10 +01001147 pr->eq = ehea_create_eq(adapter, eq_type, EHEA_MAX_ENTRIES_EQ, 0);
1148 if (!pr->eq) {
1149 ehea_error("create_eq failed (eq)");
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001150 goto out_free;
1151 }
1152
1153 pr->recv_cq = ehea_create_cq(adapter, pr_cfg->max_entries_rcq,
Jan-Bernd Themann18604c52007-02-28 18:34:10 +01001154 pr->eq->fw_handle,
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001155 port->logical_port_id);
1156 if (!pr->recv_cq) {
1157 ehea_error("create_cq failed (cq_recv)");
1158 goto out_free;
1159 }
1160
1161 pr->send_cq = ehea_create_cq(adapter, pr_cfg->max_entries_scq,
Jan-Bernd Themann18604c52007-02-28 18:34:10 +01001162 pr->eq->fw_handle,
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001163 port->logical_port_id);
1164 if (!pr->send_cq) {
1165 ehea_error("create_cq failed (cq_send)");
1166 goto out_free;
1167 }
1168
1169 if (netif_msg_ifup(port))
1170 ehea_info("Send CQ: act_nr_cqes=%d, Recv CQ: act_nr_cqes=%d",
1171 pr->send_cq->attr.act_nr_of_cqes,
1172 pr->recv_cq->attr.act_nr_of_cqes);
1173
1174 init_attr = kzalloc(sizeof(*init_attr), GFP_KERNEL);
1175 if (!init_attr) {
1176 ret = -ENOMEM;
1177 ehea_error("no mem for ehea_qp_init_attr");
1178 goto out_free;
1179 }
1180
1181 init_attr->low_lat_rq1 = 1;
1182 init_attr->signalingtype = 1; /* generate CQE if specified in WQE */
1183 init_attr->rq_count = 3;
1184 init_attr->qp_token = queue_token;
1185 init_attr->max_nr_send_wqes = pr_cfg->max_entries_sq;
1186 init_attr->max_nr_rwqes_rq1 = pr_cfg->max_entries_rq1;
1187 init_attr->max_nr_rwqes_rq2 = pr_cfg->max_entries_rq2;
1188 init_attr->max_nr_rwqes_rq3 = pr_cfg->max_entries_rq3;
1189 init_attr->wqe_size_enc_sq = EHEA_SG_SQ;
1190 init_attr->wqe_size_enc_rq1 = EHEA_SG_RQ1;
1191 init_attr->wqe_size_enc_rq2 = EHEA_SG_RQ2;
1192 init_attr->wqe_size_enc_rq3 = EHEA_SG_RQ3;
1193 init_attr->rq2_threshold = EHEA_RQ2_THRESHOLD;
1194 init_attr->rq3_threshold = EHEA_RQ3_THRESHOLD;
1195 init_attr->port_nr = port->logical_port_id;
1196 init_attr->send_cq_handle = pr->send_cq->fw_handle;
1197 init_attr->recv_cq_handle = pr->recv_cq->fw_handle;
1198 init_attr->aff_eq_handle = port->qp_eq->fw_handle;
1199
1200 pr->qp = ehea_create_qp(adapter, adapter->pd, init_attr);
1201 if (!pr->qp) {
1202 ehea_error("create_qp failed");
1203 ret = -EIO;
1204 goto out_free;
1205 }
1206
1207 if (netif_msg_ifup(port))
1208 ehea_info("QP: qp_nr=%d\n act_nr_snd_wqe=%d\n nr_rwqe_rq1=%d\n "
1209 "nr_rwqe_rq2=%d\n nr_rwqe_rq3=%d", init_attr->qp_nr,
1210 init_attr->act_nr_send_wqes,
1211 init_attr->act_nr_rwqes_rq1,
1212 init_attr->act_nr_rwqes_rq2,
1213 init_attr->act_nr_rwqes_rq3);
1214
1215 ret = ehea_init_q_skba(&pr->sq_skba, init_attr->act_nr_send_wqes + 1);
1216 ret |= ehea_init_q_skba(&pr->rq1_skba, init_attr->act_nr_rwqes_rq1 + 1);
1217 ret |= ehea_init_q_skba(&pr->rq2_skba, init_attr->act_nr_rwqes_rq2 + 1);
1218 ret |= ehea_init_q_skba(&pr->rq3_skba, init_attr->act_nr_rwqes_rq3 + 1);
1219 if (ret)
1220 goto out_free;
1221
1222 pr->swqe_refill_th = init_attr->act_nr_send_wqes / 10;
1223 if (ehea_gen_smrs(pr) != 0) {
1224 ret = -EIO;
1225 goto out_free;
1226 }
Jan-Bernd Themann18604c52007-02-28 18:34:10 +01001227
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001228 atomic_set(&pr->swqe_avail, init_attr->act_nr_send_wqes - 1);
1229
1230 kfree(init_attr);
Jan-Bernd Themann18604c52007-02-28 18:34:10 +01001231
Stephen Hemmingerbea33482007-10-03 16:41:36 -07001232 netif_napi_add(pr->port->netdev, &pr->napi, ehea_poll, 64);
Jan-Bernd Themann18604c52007-02-28 18:34:10 +01001233
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001234 ret = 0;
1235 goto out;
1236
1237out_free:
1238 kfree(init_attr);
1239 vfree(pr->sq_skba.arr);
1240 vfree(pr->rq1_skba.arr);
1241 vfree(pr->rq2_skba.arr);
1242 vfree(pr->rq3_skba.arr);
1243 ehea_destroy_qp(pr->qp);
1244 ehea_destroy_cq(pr->send_cq);
1245 ehea_destroy_cq(pr->recv_cq);
Jan-Bernd Themann18604c52007-02-28 18:34:10 +01001246 ehea_destroy_eq(pr->eq);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001247out:
1248 return ret;
1249}
1250
1251static int ehea_clean_portres(struct ehea_port *port, struct ehea_port_res *pr)
1252{
1253 int ret, i;
1254
1255 ret = ehea_destroy_qp(pr->qp);
1256
1257 if (!ret) {
1258 ehea_destroy_cq(pr->send_cq);
1259 ehea_destroy_cq(pr->recv_cq);
Jan-Bernd Themann18604c52007-02-28 18:34:10 +01001260 ehea_destroy_eq(pr->eq);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001261
1262 for (i = 0; i < pr->rq1_skba.len; i++)
1263 if (pr->rq1_skba.arr[i])
1264 dev_kfree_skb(pr->rq1_skba.arr[i]);
1265
1266 for (i = 0; i < pr->rq2_skba.len; i++)
1267 if (pr->rq2_skba.arr[i])
1268 dev_kfree_skb(pr->rq2_skba.arr[i]);
1269
1270 for (i = 0; i < pr->rq3_skba.len; i++)
1271 if (pr->rq3_skba.arr[i])
1272 dev_kfree_skb(pr->rq3_skba.arr[i]);
1273
1274 for (i = 0; i < pr->sq_skba.len; i++)
1275 if (pr->sq_skba.arr[i])
1276 dev_kfree_skb(pr->sq_skba.arr[i]);
1277
1278 vfree(pr->rq1_skba.arr);
1279 vfree(pr->rq2_skba.arr);
1280 vfree(pr->rq3_skba.arr);
1281 vfree(pr->sq_skba.arr);
1282 ret = ehea_rem_smrs(pr);
1283 }
1284 return ret;
1285}
1286
1287/*
1288 * The write_* functions store information in swqe which is used by
1289 * the hardware to calculate the ip/tcp/udp checksum
1290 */
1291
1292static inline void write_ip_start_end(struct ehea_swqe *swqe,
1293 const struct sk_buff *skb)
1294{
Arnaldo Carvalho de Meloeddc9ec2007-04-20 22:47:35 -07001295 swqe->ip_start = skb_network_offset(skb);
Arnaldo Carvalho de Meloc9bdd4b2007-03-12 20:09:15 -03001296 swqe->ip_end = (u8)(swqe->ip_start + ip_hdrlen(skb) - 1);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001297}
1298
1299static inline void write_tcp_offset_end(struct ehea_swqe *swqe,
1300 const struct sk_buff *skb)
1301{
1302 swqe->tcp_offset =
1303 (u8)(swqe->ip_end + 1 + offsetof(struct tcphdr, check));
1304
1305 swqe->tcp_end = (u16)skb->len - 1;
1306}
1307
1308static inline void write_udp_offset_end(struct ehea_swqe *swqe,
1309 const struct sk_buff *skb)
1310{
1311 swqe->tcp_offset =
1312 (u8)(swqe->ip_end + 1 + offsetof(struct udphdr, check));
1313
1314 swqe->tcp_end = (u16)skb->len - 1;
1315}
1316
1317
1318static void write_swqe2_TSO(struct sk_buff *skb,
1319 struct ehea_swqe *swqe, u32 lkey)
1320{
1321 struct ehea_vsgentry *sg1entry = &swqe->u.immdata_desc.sg_entry;
1322 u8 *imm_data = &swqe->u.immdata_desc.immediate_data[0];
1323 int skb_data_size = skb->len - skb->data_len;
1324 int headersize;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001325
1326 /* Packet is TCP with TSO enabled */
1327 swqe->tx_control |= EHEA_SWQE_TSO;
1328 swqe->mss = skb_shinfo(skb)->gso_size;
1329 /* copy only eth/ip/tcp headers to immediate data and
1330 * the rest of skb->data to sg1entry
1331 */
Arnaldo Carvalho de Meloab6a5bb2007-03-18 17:43:48 -07001332 headersize = ETH_HLEN + ip_hdrlen(skb) + tcp_hdrlen(skb);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001333
1334 skb_data_size = skb->len - skb->data_len;
1335
1336 if (skb_data_size >= headersize) {
1337 /* copy immediate data */
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03001338 skb_copy_from_linear_data(skb, imm_data, headersize);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001339 swqe->immediate_data_length = headersize;
1340
1341 if (skb_data_size > headersize) {
1342 /* set sg1entry data */
1343 sg1entry->l_key = lkey;
1344 sg1entry->len = skb_data_size - headersize;
Thomas Klein44a5b3d2007-08-06 13:55:44 +02001345 sg1entry->vaddr =
1346 ehea_map_vaddr(skb->data + headersize);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001347 swqe->descriptors++;
1348 }
1349 } else
1350 ehea_error("cannot handle fragmented headers");
1351}
1352
1353static void write_swqe2_nonTSO(struct sk_buff *skb,
1354 struct ehea_swqe *swqe, u32 lkey)
1355{
1356 int skb_data_size = skb->len - skb->data_len;
1357 u8 *imm_data = &swqe->u.immdata_desc.immediate_data[0];
1358 struct ehea_vsgentry *sg1entry = &swqe->u.immdata_desc.sg_entry;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001359
1360 /* Packet is any nonTSO type
1361 *
1362 * Copy as much as possible skb->data to immediate data and
1363 * the rest to sg1entry
1364 */
1365 if (skb_data_size >= SWQE2_MAX_IMM) {
1366 /* copy immediate data */
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03001367 skb_copy_from_linear_data(skb, imm_data, SWQE2_MAX_IMM);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001368
1369 swqe->immediate_data_length = SWQE2_MAX_IMM;
1370
1371 if (skb_data_size > SWQE2_MAX_IMM) {
1372 /* copy sg1entry data */
1373 sg1entry->l_key = lkey;
1374 sg1entry->len = skb_data_size - SWQE2_MAX_IMM;
Thomas Klein44a5b3d2007-08-06 13:55:44 +02001375 sg1entry->vaddr =
1376 ehea_map_vaddr(skb->data + SWQE2_MAX_IMM);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001377 swqe->descriptors++;
1378 }
1379 } else {
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03001380 skb_copy_from_linear_data(skb, imm_data, skb_data_size);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001381 swqe->immediate_data_length = skb_data_size;
1382 }
1383}
1384
1385static inline void write_swqe2_data(struct sk_buff *skb, struct net_device *dev,
1386 struct ehea_swqe *swqe, u32 lkey)
1387{
1388 struct ehea_vsgentry *sg_list, *sg1entry, *sgentry;
1389 skb_frag_t *frag;
1390 int nfrags, sg1entry_contains_frag_data, i;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001391
1392 nfrags = skb_shinfo(skb)->nr_frags;
1393 sg1entry = &swqe->u.immdata_desc.sg_entry;
1394 sg_list = (struct ehea_vsgentry*)&swqe->u.immdata_desc.sg_list;
1395 swqe->descriptors = 0;
1396 sg1entry_contains_frag_data = 0;
1397
1398 if ((dev->features & NETIF_F_TSO) && skb_shinfo(skb)->gso_size)
1399 write_swqe2_TSO(skb, swqe, lkey);
1400 else
1401 write_swqe2_nonTSO(skb, swqe, lkey);
1402
1403 /* write descriptors */
1404 if (nfrags > 0) {
1405 if (swqe->descriptors == 0) {
1406 /* sg1entry not yet used */
1407 frag = &skb_shinfo(skb)->frags[0];
1408
1409 /* copy sg1entry data */
1410 sg1entry->l_key = lkey;
1411 sg1entry->len = frag->size;
Thomas Klein44a5b3d2007-08-06 13:55:44 +02001412 sg1entry->vaddr =
1413 ehea_map_vaddr(page_address(frag->page)
1414 + frag->page_offset);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001415 swqe->descriptors++;
1416 sg1entry_contains_frag_data = 1;
1417 }
1418
1419 for (i = sg1entry_contains_frag_data; i < nfrags; i++) {
1420
1421 frag = &skb_shinfo(skb)->frags[i];
1422 sgentry = &sg_list[i - sg1entry_contains_frag_data];
1423
1424 sgentry->l_key = lkey;
1425 sgentry->len = frag->size;
Thomas Klein44a5b3d2007-08-06 13:55:44 +02001426 sgentry->vaddr =
1427 ehea_map_vaddr(page_address(frag->page)
1428 + frag->page_offset);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001429 swqe->descriptors++;
1430 }
1431 }
1432}
1433
1434static int ehea_broadcast_reg_helper(struct ehea_port *port, u32 hcallid)
1435{
1436 int ret = 0;
1437 u64 hret;
1438 u8 reg_type;
1439
1440 /* De/Register untagged packets */
1441 reg_type = EHEA_BCMC_BROADCAST | EHEA_BCMC_UNTAGGED;
1442 hret = ehea_h_reg_dereg_bcmc(port->adapter->handle,
1443 port->logical_port_id,
1444 reg_type, port->mac_addr, 0, hcallid);
1445 if (hret != H_SUCCESS) {
Thomas Kleinf9e29222007-07-18 17:34:09 +02001446 ehea_error("%sregistering bc address failed (tagged)",
1447 hcallid == H_REG_BCMC ? "" : "de");
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001448 ret = -EIO;
1449 goto out_herr;
1450 }
1451
1452 /* De/Register VLAN packets */
1453 reg_type = EHEA_BCMC_BROADCAST | EHEA_BCMC_VLANID_ALL;
1454 hret = ehea_h_reg_dereg_bcmc(port->adapter->handle,
1455 port->logical_port_id,
1456 reg_type, port->mac_addr, 0, hcallid);
1457 if (hret != H_SUCCESS) {
Thomas Kleinf9e29222007-07-18 17:34:09 +02001458 ehea_error("%sregistering bc address failed (vlan)",
1459 hcallid == H_REG_BCMC ? "" : "de");
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001460 ret = -EIO;
1461 }
1462out_herr:
1463 return ret;
1464}
1465
1466static int ehea_set_mac_addr(struct net_device *dev, void *sa)
1467{
1468 struct ehea_port *port = netdev_priv(dev);
1469 struct sockaddr *mac_addr = sa;
1470 struct hcp_ehea_port_cb0 *cb0;
1471 int ret;
1472 u64 hret;
1473
1474 if (!is_valid_ether_addr(mac_addr->sa_data)) {
1475 ret = -EADDRNOTAVAIL;
1476 goto out;
1477 }
1478
Thomas Kleina1d261c2006-11-03 17:48:23 +01001479 cb0 = kzalloc(PAGE_SIZE, GFP_KERNEL);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001480 if (!cb0) {
1481 ehea_error("no mem for cb0");
1482 ret = -ENOMEM;
1483 goto out;
1484 }
1485
1486 memcpy(&(cb0->port_mac_addr), &(mac_addr->sa_data[0]), ETH_ALEN);
1487
1488 cb0->port_mac_addr = cb0->port_mac_addr >> 16;
1489
1490 hret = ehea_h_modify_ehea_port(port->adapter->handle,
1491 port->logical_port_id, H_PORT_CB0,
1492 EHEA_BMASK_SET(H_PORT_CB0_MAC, 1), cb0);
1493 if (hret != H_SUCCESS) {
1494 ret = -EIO;
1495 goto out_free;
1496 }
1497
1498 memcpy(dev->dev_addr, mac_addr->sa_data, dev->addr_len);
1499
1500 /* Deregister old MAC in pHYP */
1501 ret = ehea_broadcast_reg_helper(port, H_DEREG_BCMC);
1502 if (ret)
1503 goto out_free;
1504
1505 port->mac_addr = cb0->port_mac_addr << 16;
1506
1507 /* Register new MAC in pHYP */
1508 ret = ehea_broadcast_reg_helper(port, H_REG_BCMC);
1509 if (ret)
1510 goto out_free;
1511
1512 ret = 0;
1513out_free:
1514 kfree(cb0);
1515out:
1516 return ret;
1517}
1518
1519static void ehea_promiscuous_error(u64 hret, int enable)
1520{
Thomas Klein7674a582007-01-22 12:54:20 +01001521 if (hret == H_AUTHORITY)
1522 ehea_info("Hypervisor denied %sabling promiscuous mode",
1523 enable == 1 ? "en" : "dis");
1524 else
1525 ehea_error("failed %sabling promiscuous mode",
1526 enable == 1 ? "en" : "dis");
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001527}
1528
1529static void ehea_promiscuous(struct net_device *dev, int enable)
1530{
1531 struct ehea_port *port = netdev_priv(dev);
1532 struct hcp_ehea_port_cb7 *cb7;
1533 u64 hret;
1534
1535 if ((enable && port->promisc) || (!enable && !port->promisc))
1536 return;
1537
Thomas Kleina1d261c2006-11-03 17:48:23 +01001538 cb7 = kzalloc(PAGE_SIZE, GFP_ATOMIC);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001539 if (!cb7) {
1540 ehea_error("no mem for cb7");
1541 goto out;
1542 }
1543
1544 /* Modify Pxs_DUCQPN in CB7 */
1545 cb7->def_uc_qpn = enable == 1 ? port->port_res[0].qp->fw_handle : 0;
1546
1547 hret = ehea_h_modify_ehea_port(port->adapter->handle,
1548 port->logical_port_id,
1549 H_PORT_CB7, H_PORT_CB7_DUCQPN, cb7);
1550 if (hret) {
1551 ehea_promiscuous_error(hret, enable);
1552 goto out;
1553 }
1554
1555 port->promisc = enable;
1556out:
1557 kfree(cb7);
1558 return;
1559}
1560
1561static u64 ehea_multicast_reg_helper(struct ehea_port *port, u64 mc_mac_addr,
1562 u32 hcallid)
1563{
1564 u64 hret;
1565 u8 reg_type;
1566
1567 reg_type = EHEA_BCMC_SCOPE_ALL | EHEA_BCMC_MULTICAST
1568 | EHEA_BCMC_UNTAGGED;
1569
1570 hret = ehea_h_reg_dereg_bcmc(port->adapter->handle,
1571 port->logical_port_id,
1572 reg_type, mc_mac_addr, 0, hcallid);
1573 if (hret)
1574 goto out;
1575
1576 reg_type = EHEA_BCMC_SCOPE_ALL | EHEA_BCMC_MULTICAST
1577 | EHEA_BCMC_VLANID_ALL;
1578
1579 hret = ehea_h_reg_dereg_bcmc(port->adapter->handle,
1580 port->logical_port_id,
1581 reg_type, mc_mac_addr, 0, hcallid);
1582out:
1583 return hret;
1584}
1585
1586static int ehea_drop_multicast_list(struct net_device *dev)
1587{
1588 struct ehea_port *port = netdev_priv(dev);
1589 struct ehea_mc_list *mc_entry = port->mc_list;
1590 struct list_head *pos;
1591 struct list_head *temp;
1592 int ret = 0;
1593 u64 hret;
1594
1595 list_for_each_safe(pos, temp, &(port->mc_list->list)) {
1596 mc_entry = list_entry(pos, struct ehea_mc_list, list);
1597
1598 hret = ehea_multicast_reg_helper(port, mc_entry->macaddr,
1599 H_DEREG_BCMC);
1600 if (hret) {
1601 ehea_error("failed deregistering mcast MAC");
1602 ret = -EIO;
1603 }
1604
1605 list_del(pos);
1606 kfree(mc_entry);
1607 }
1608 return ret;
1609}
1610
1611static void ehea_allmulti(struct net_device *dev, int enable)
1612{
1613 struct ehea_port *port = netdev_priv(dev);
1614 u64 hret;
1615
1616 if (!port->allmulti) {
1617 if (enable) {
1618 /* Enable ALLMULTI */
1619 ehea_drop_multicast_list(dev);
1620 hret = ehea_multicast_reg_helper(port, 0, H_REG_BCMC);
1621 if (!hret)
1622 port->allmulti = 1;
1623 else
1624 ehea_error("failed enabling IFF_ALLMULTI");
1625 }
1626 } else
1627 if (!enable) {
1628 /* Disable ALLMULTI */
1629 hret = ehea_multicast_reg_helper(port, 0, H_DEREG_BCMC);
1630 if (!hret)
1631 port->allmulti = 0;
1632 else
1633 ehea_error("failed disabling IFF_ALLMULTI");
1634 }
1635}
1636
1637static void ehea_add_multicast_entry(struct ehea_port* port, u8* mc_mac_addr)
1638{
1639 struct ehea_mc_list *ehea_mcl_entry;
1640 u64 hret;
1641
Jan-Bernd Themann1e1675c2006-10-25 13:11:42 +02001642 ehea_mcl_entry = kzalloc(sizeof(*ehea_mcl_entry), GFP_ATOMIC);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001643 if (!ehea_mcl_entry) {
1644 ehea_error("no mem for mcl_entry");
1645 return;
1646 }
1647
1648 INIT_LIST_HEAD(&ehea_mcl_entry->list);
1649
1650 memcpy(&ehea_mcl_entry->macaddr, mc_mac_addr, ETH_ALEN);
1651
1652 hret = ehea_multicast_reg_helper(port, ehea_mcl_entry->macaddr,
1653 H_REG_BCMC);
1654 if (!hret)
1655 list_add(&ehea_mcl_entry->list, &port->mc_list->list);
1656 else {
1657 ehea_error("failed registering mcast MAC");
1658 kfree(ehea_mcl_entry);
1659 }
1660}
1661
1662static void ehea_set_multicast_list(struct net_device *dev)
1663{
1664 struct ehea_port *port = netdev_priv(dev);
1665 struct dev_mc_list *k_mcl_entry;
1666 int ret, i;
1667
1668 if (dev->flags & IFF_PROMISC) {
1669 ehea_promiscuous(dev, 1);
1670 return;
1671 }
1672 ehea_promiscuous(dev, 0);
1673
1674 if (dev->flags & IFF_ALLMULTI) {
1675 ehea_allmulti(dev, 1);
1676 return;
1677 }
1678 ehea_allmulti(dev, 0);
1679
1680 if (dev->mc_count) {
1681 ret = ehea_drop_multicast_list(dev);
1682 if (ret) {
1683 /* Dropping the current multicast list failed.
1684 * Enabling ALL_MULTI is the best we can do.
1685 */
1686 ehea_allmulti(dev, 1);
1687 }
1688
1689 if (dev->mc_count > port->adapter->max_mc_mac) {
1690 ehea_info("Mcast registration limit reached (0x%lx). "
1691 "Use ALLMULTI!",
1692 port->adapter->max_mc_mac);
1693 goto out;
1694 }
1695
1696 for (i = 0, k_mcl_entry = dev->mc_list;
1697 i < dev->mc_count;
1698 i++, k_mcl_entry = k_mcl_entry->next) {
1699 ehea_add_multicast_entry(port, k_mcl_entry->dmi_addr);
1700 }
1701 }
1702out:
1703 return;
1704}
1705
1706static int ehea_change_mtu(struct net_device *dev, int new_mtu)
1707{
1708 if ((new_mtu < 68) || (new_mtu > EHEA_MAX_PACKET_SIZE))
1709 return -EINVAL;
1710 dev->mtu = new_mtu;
1711 return 0;
1712}
1713
1714static void ehea_xmit2(struct sk_buff *skb, struct net_device *dev,
1715 struct ehea_swqe *swqe, u32 lkey)
1716{
1717 if (skb->protocol == htons(ETH_P_IP)) {
Arnaldo Carvalho de Meloeddc9ec2007-04-20 22:47:35 -07001718 const struct iphdr *iph = ip_hdr(skb);
Jan-Bernd Themannd1d25aa2007-07-02 13:00:46 +02001719
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001720 /* IPv4 */
1721 swqe->tx_control |= EHEA_SWQE_CRC
1722 | EHEA_SWQE_IP_CHECKSUM
1723 | EHEA_SWQE_TCP_CHECKSUM
1724 | EHEA_SWQE_IMM_DATA_PRESENT
1725 | EHEA_SWQE_DESCRIPTORS_PRESENT;
1726
1727 write_ip_start_end(swqe, skb);
1728
Arnaldo Carvalho de Meloeddc9ec2007-04-20 22:47:35 -07001729 if (iph->protocol == IPPROTO_UDP) {
Jan-Bernd Themannd1d25aa2007-07-02 13:00:46 +02001730 if ((iph->frag_off & IP_MF)
1731 || (iph->frag_off & IP_OFFSET))
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001732 /* IP fragment, so don't change cs */
1733 swqe->tx_control &= ~EHEA_SWQE_TCP_CHECKSUM;
1734 else
1735 write_udp_offset_end(swqe, skb);
Arnaldo Carvalho de Meloeddc9ec2007-04-20 22:47:35 -07001736 } else if (iph->protocol == IPPROTO_TCP) {
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001737 write_tcp_offset_end(swqe, skb);
1738 }
1739
1740 /* icmp (big data) and ip segmentation packets (all other ip
1741 packets) do not require any special handling */
1742
1743 } else {
1744 /* Other Ethernet Protocol */
1745 swqe->tx_control |= EHEA_SWQE_CRC
1746 | EHEA_SWQE_IMM_DATA_PRESENT
1747 | EHEA_SWQE_DESCRIPTORS_PRESENT;
1748 }
1749
1750 write_swqe2_data(skb, dev, swqe, lkey);
1751}
1752
1753static void ehea_xmit3(struct sk_buff *skb, struct net_device *dev,
1754 struct ehea_swqe *swqe)
1755{
1756 int nfrags = skb_shinfo(skb)->nr_frags;
1757 u8 *imm_data = &swqe->u.immdata_nodesc.immediate_data[0];
1758 skb_frag_t *frag;
1759 int i;
1760
1761 if (skb->protocol == htons(ETH_P_IP)) {
Arnaldo Carvalho de Meloeddc9ec2007-04-20 22:47:35 -07001762 const struct iphdr *iph = ip_hdr(skb);
Jan-Bernd Themannd1d25aa2007-07-02 13:00:46 +02001763
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001764 /* IPv4 */
1765 write_ip_start_end(swqe, skb);
1766
Arnaldo Carvalho de Meloeddc9ec2007-04-20 22:47:35 -07001767 if (iph->protocol == IPPROTO_TCP) {
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001768 swqe->tx_control |= EHEA_SWQE_CRC
1769 | EHEA_SWQE_IP_CHECKSUM
1770 | EHEA_SWQE_TCP_CHECKSUM
1771 | EHEA_SWQE_IMM_DATA_PRESENT;
1772
1773 write_tcp_offset_end(swqe, skb);
1774
Arnaldo Carvalho de Meloeddc9ec2007-04-20 22:47:35 -07001775 } else if (iph->protocol == IPPROTO_UDP) {
Jan-Bernd Themannd1d25aa2007-07-02 13:00:46 +02001776 if ((iph->frag_off & IP_MF)
1777 || (iph->frag_off & IP_OFFSET))
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001778 /* IP fragment, so don't change cs */
1779 swqe->tx_control |= EHEA_SWQE_CRC
1780 | EHEA_SWQE_IMM_DATA_PRESENT;
1781 else {
1782 swqe->tx_control |= EHEA_SWQE_CRC
1783 | EHEA_SWQE_IP_CHECKSUM
1784 | EHEA_SWQE_TCP_CHECKSUM
1785 | EHEA_SWQE_IMM_DATA_PRESENT;
1786
1787 write_udp_offset_end(swqe, skb);
1788 }
1789 } else {
1790 /* icmp (big data) and
1791 ip segmentation packets (all other ip packets) */
1792 swqe->tx_control |= EHEA_SWQE_CRC
1793 | EHEA_SWQE_IP_CHECKSUM
1794 | EHEA_SWQE_IMM_DATA_PRESENT;
1795 }
1796 } else {
1797 /* Other Ethernet Protocol */
1798 swqe->tx_control |= EHEA_SWQE_CRC | EHEA_SWQE_IMM_DATA_PRESENT;
1799 }
1800 /* copy (immediate) data */
1801 if (nfrags == 0) {
1802 /* data is in a single piece */
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03001803 skb_copy_from_linear_data(skb, imm_data, skb->len);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001804 } else {
1805 /* first copy data from the skb->data buffer ... */
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03001806 skb_copy_from_linear_data(skb, imm_data,
1807 skb->len - skb->data_len);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001808 imm_data += skb->len - skb->data_len;
1809
1810 /* ... then copy data from the fragments */
1811 for (i = 0; i < nfrags; i++) {
1812 frag = &skb_shinfo(skb)->frags[i];
1813 memcpy(imm_data,
1814 page_address(frag->page) + frag->page_offset,
1815 frag->size);
1816 imm_data += frag->size;
1817 }
1818 }
1819 swqe->immediate_data_length = skb->len;
1820 dev_kfree_skb(skb);
1821}
1822
Jan-Bernd Themann18604c52007-02-28 18:34:10 +01001823static inline int ehea_hash_skb(struct sk_buff *skb, int num_qps)
1824{
1825 struct tcphdr *tcp;
1826 u32 tmp;
1827
1828 if ((skb->protocol == htons(ETH_P_IP)) &&
Thomas Klein88ca2d02007-05-02 16:07:05 +02001829 (ip_hdr(skb)->protocol == IPPROTO_TCP)) {
1830 tcp = (struct tcphdr*)(skb_network_header(skb) + (ip_hdr(skb)->ihl * 4));
Jan-Bernd Themann18604c52007-02-28 18:34:10 +01001831 tmp = (tcp->source + (tcp->dest << 16)) % 31;
Thomas Klein88ca2d02007-05-02 16:07:05 +02001832 tmp += ip_hdr(skb)->daddr % 31;
Jan-Bernd Themann18604c52007-02-28 18:34:10 +01001833 return tmp % num_qps;
1834 }
1835 else
1836 return 0;
1837}
1838
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001839static int ehea_start_xmit(struct sk_buff *skb, struct net_device *dev)
1840{
1841 struct ehea_port *port = netdev_priv(dev);
1842 struct ehea_swqe *swqe;
1843 unsigned long flags;
1844 u32 lkey;
1845 int swqe_index;
Jan-Bernd Themann18604c52007-02-28 18:34:10 +01001846 struct ehea_port_res *pr;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001847
Jan-Bernd Themann18604c52007-02-28 18:34:10 +01001848 pr = &port->port_res[ehea_hash_skb(skb, port->num_tx_qps)];
1849
Jan-Bernd Themann18604c52007-02-28 18:34:10 +01001850 if (!spin_trylock(&pr->xmit_lock))
1851 return NETDEV_TX_BUSY;
1852
1853 if (pr->queue_stopped) {
1854 spin_unlock(&pr->xmit_lock);
1855 return NETDEV_TX_BUSY;
1856 }
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001857
1858 swqe = ehea_get_swqe(pr->qp, &swqe_index);
1859 memset(swqe, 0, SWQE_HEADER_SIZE);
1860 atomic_dec(&pr->swqe_avail);
1861
1862 if (skb->len <= SWQE3_MAX_IMM) {
1863 u32 sig_iv = port->sig_comp_iv;
1864 u32 swqe_num = pr->swqe_id_counter;
1865 ehea_xmit3(skb, dev, swqe);
1866 swqe->wr_id = EHEA_BMASK_SET(EHEA_WR_ID_TYPE, EHEA_SWQE3_TYPE)
1867 | EHEA_BMASK_SET(EHEA_WR_ID_COUNT, swqe_num);
1868 if (pr->swqe_ll_count >= (sig_iv - 1)) {
1869 swqe->wr_id |= EHEA_BMASK_SET(EHEA_WR_ID_REFILL,
1870 sig_iv);
1871 swqe->tx_control |= EHEA_SWQE_SIGNALLED_COMPLETION;
1872 pr->swqe_ll_count = 0;
1873 } else
1874 pr->swqe_ll_count += 1;
1875 } else {
1876 swqe->wr_id =
1877 EHEA_BMASK_SET(EHEA_WR_ID_TYPE, EHEA_SWQE2_TYPE)
1878 | EHEA_BMASK_SET(EHEA_WR_ID_COUNT, pr->swqe_id_counter)
Jan-Bernd Themannacbddb52007-03-23 17:18:53 +01001879 | EHEA_BMASK_SET(EHEA_WR_ID_REFILL, 1)
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001880 | EHEA_BMASK_SET(EHEA_WR_ID_INDEX, pr->sq_skba.index);
1881 pr->sq_skba.arr[pr->sq_skba.index] = skb;
1882
1883 pr->sq_skba.index++;
1884 pr->sq_skba.index &= (pr->sq_skba.len - 1);
1885
1886 lkey = pr->send_mr.lkey;
1887 ehea_xmit2(skb, dev, swqe, lkey);
Jan-Bernd Themannacbddb52007-03-23 17:18:53 +01001888 swqe->tx_control |= EHEA_SWQE_SIGNALLED_COMPLETION;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001889 }
1890 pr->swqe_id_counter += 1;
1891
1892 if (port->vgrp && vlan_tx_tag_present(skb)) {
1893 swqe->tx_control |= EHEA_SWQE_VLAN_INSERT;
1894 swqe->vlan_tag = vlan_tx_tag_get(skb);
1895 }
1896
1897 if (netif_msg_tx_queued(port)) {
1898 ehea_info("post swqe on QP %d", pr->qp->init_attr.qp_nr);
Jan-Bernd Themannbff0a552006-10-05 16:53:14 +02001899 ehea_dump(swqe, 512, "swqe");
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001900 }
1901
Thomas Klein44c82152007-07-11 16:32:00 +02001902 if (unlikely(test_bit(__EHEA_STOP_XFER, &ehea_driver_flags)))
1903 goto out;
1904
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001905 ehea_post_swqe(pr->qp, swqe);
1906 pr->tx_packets++;
1907
1908 if (unlikely(atomic_read(&pr->swqe_avail) <= 1)) {
1909 spin_lock_irqsave(&pr->netif_queue, flags);
1910 if (unlikely(atomic_read(&pr->swqe_avail) <= 1)) {
Jan-Bernd Themannacbddb52007-03-23 17:18:53 +01001911 pr->p_stats.queue_stopped++;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001912 netif_stop_queue(dev);
1913 pr->queue_stopped = 1;
1914 }
1915 spin_unlock_irqrestore(&pr->netif_queue, flags);
1916 }
1917 dev->trans_start = jiffies;
1918 spin_unlock(&pr->xmit_lock);
Thomas Klein44c82152007-07-11 16:32:00 +02001919out:
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001920 return NETDEV_TX_OK;
1921}
1922
1923static void ehea_vlan_rx_register(struct net_device *dev,
1924 struct vlan_group *grp)
1925{
1926 struct ehea_port *port = netdev_priv(dev);
1927 struct ehea_adapter *adapter = port->adapter;
1928 struct hcp_ehea_port_cb1 *cb1;
1929 u64 hret;
1930
1931 port->vgrp = grp;
1932
Thomas Kleina1d261c2006-11-03 17:48:23 +01001933 cb1 = kzalloc(PAGE_SIZE, GFP_KERNEL);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001934 if (!cb1) {
1935 ehea_error("no mem for cb1");
1936 goto out;
1937 }
1938
Thomas Kleindec590c2007-06-06 20:53:16 +02001939 memset(cb1->vlan_filter, 0, sizeof(cb1->vlan_filter));
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001940
1941 hret = ehea_h_modify_ehea_port(adapter->handle, port->logical_port_id,
1942 H_PORT_CB1, H_PORT_CB1_ALL, cb1);
1943 if (hret != H_SUCCESS)
1944 ehea_error("modify_ehea_port failed");
1945
1946 kfree(cb1);
1947out:
1948 return;
1949}
1950
1951static void ehea_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
1952{
1953 struct ehea_port *port = netdev_priv(dev);
1954 struct ehea_adapter *adapter = port->adapter;
1955 struct hcp_ehea_port_cb1 *cb1;
1956 int index;
1957 u64 hret;
1958
Thomas Kleina1d261c2006-11-03 17:48:23 +01001959 cb1 = kzalloc(PAGE_SIZE, GFP_KERNEL);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001960 if (!cb1) {
1961 ehea_error("no mem for cb1");
1962 goto out;
1963 }
1964
1965 hret = ehea_h_query_ehea_port(adapter->handle, port->logical_port_id,
1966 H_PORT_CB1, H_PORT_CB1_ALL, cb1);
1967 if (hret != H_SUCCESS) {
1968 ehea_error("query_ehea_port failed");
1969 goto out;
1970 }
1971
1972 index = (vid / 64);
Thomas Kleindec590c2007-06-06 20:53:16 +02001973 cb1->vlan_filter[index] |= ((u64)(0x8000000000000000 >> (vid & 0x3F)));
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001974
1975 hret = ehea_h_modify_ehea_port(adapter->handle, port->logical_port_id,
1976 H_PORT_CB1, H_PORT_CB1_ALL, cb1);
1977 if (hret != H_SUCCESS)
1978 ehea_error("modify_ehea_port failed");
1979out:
1980 kfree(cb1);
1981 return;
1982}
1983
1984static void ehea_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
1985{
1986 struct ehea_port *port = netdev_priv(dev);
1987 struct ehea_adapter *adapter = port->adapter;
1988 struct hcp_ehea_port_cb1 *cb1;
1989 int index;
1990 u64 hret;
1991
Dan Aloni5c15bde2007-03-02 20:44:51 -08001992 vlan_group_set_device(port->vgrp, vid, NULL);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001993
Thomas Kleina1d261c2006-11-03 17:48:23 +01001994 cb1 = kzalloc(PAGE_SIZE, GFP_KERNEL);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001995 if (!cb1) {
1996 ehea_error("no mem for cb1");
1997 goto out;
1998 }
1999
2000 hret = ehea_h_query_ehea_port(adapter->handle, port->logical_port_id,
2001 H_PORT_CB1, H_PORT_CB1_ALL, cb1);
2002 if (hret != H_SUCCESS) {
2003 ehea_error("query_ehea_port failed");
2004 goto out;
2005 }
2006
2007 index = (vid / 64);
Thomas Kleindec590c2007-06-06 20:53:16 +02002008 cb1->vlan_filter[index] &= ~((u64)(0x8000000000000000 >> (vid & 0x3F)));
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002009
2010 hret = ehea_h_modify_ehea_port(adapter->handle, port->logical_port_id,
2011 H_PORT_CB1, H_PORT_CB1_ALL, cb1);
2012 if (hret != H_SUCCESS)
2013 ehea_error("modify_ehea_port failed");
2014out:
2015 kfree(cb1);
2016 return;
2017}
2018
2019int ehea_activate_qp(struct ehea_adapter *adapter, struct ehea_qp *qp)
2020{
2021 int ret = -EIO;
2022 u64 hret;
2023 u16 dummy16 = 0;
2024 u64 dummy64 = 0;
2025 struct hcp_modify_qp_cb0* cb0;
2026
Thomas Kleina1d261c2006-11-03 17:48:23 +01002027 cb0 = kzalloc(PAGE_SIZE, GFP_KERNEL);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002028 if (!cb0) {
2029 ret = -ENOMEM;
2030 goto out;
2031 }
2032
2033 hret = ehea_h_query_ehea_qp(adapter->handle, 0, qp->fw_handle,
2034 EHEA_BMASK_SET(H_QPCB0_ALL, 0xFFFF), cb0);
2035 if (hret != H_SUCCESS) {
2036 ehea_error("query_ehea_qp failed (1)");
2037 goto out;
2038 }
2039
2040 cb0->qp_ctl_reg = H_QP_CR_STATE_INITIALIZED;
2041 hret = ehea_h_modify_ehea_qp(adapter->handle, 0, qp->fw_handle,
2042 EHEA_BMASK_SET(H_QPCB0_QP_CTL_REG, 1), cb0,
2043 &dummy64, &dummy64, &dummy16, &dummy16);
2044 if (hret != H_SUCCESS) {
2045 ehea_error("modify_ehea_qp failed (1)");
2046 goto out;
2047 }
2048
2049 hret = ehea_h_query_ehea_qp(adapter->handle, 0, qp->fw_handle,
2050 EHEA_BMASK_SET(H_QPCB0_ALL, 0xFFFF), cb0);
2051 if (hret != H_SUCCESS) {
2052 ehea_error("query_ehea_qp failed (2)");
2053 goto out;
2054 }
2055
2056 cb0->qp_ctl_reg = H_QP_CR_ENABLED | H_QP_CR_STATE_INITIALIZED;
2057 hret = ehea_h_modify_ehea_qp(adapter->handle, 0, qp->fw_handle,
2058 EHEA_BMASK_SET(H_QPCB0_QP_CTL_REG, 1), cb0,
2059 &dummy64, &dummy64, &dummy16, &dummy16);
2060 if (hret != H_SUCCESS) {
2061 ehea_error("modify_ehea_qp failed (2)");
2062 goto out;
2063 }
2064
2065 hret = ehea_h_query_ehea_qp(adapter->handle, 0, qp->fw_handle,
2066 EHEA_BMASK_SET(H_QPCB0_ALL, 0xFFFF), cb0);
2067 if (hret != H_SUCCESS) {
2068 ehea_error("query_ehea_qp failed (3)");
2069 goto out;
2070 }
2071
2072 cb0->qp_ctl_reg = H_QP_CR_ENABLED | H_QP_CR_STATE_RDY2SND;
2073 hret = ehea_h_modify_ehea_qp(adapter->handle, 0, qp->fw_handle,
2074 EHEA_BMASK_SET(H_QPCB0_QP_CTL_REG, 1), cb0,
2075 &dummy64, &dummy64, &dummy16, &dummy16);
2076 if (hret != H_SUCCESS) {
2077 ehea_error("modify_ehea_qp failed (3)");
2078 goto out;
2079 }
2080
2081 hret = ehea_h_query_ehea_qp(adapter->handle, 0, qp->fw_handle,
2082 EHEA_BMASK_SET(H_QPCB0_ALL, 0xFFFF), cb0);
2083 if (hret != H_SUCCESS) {
2084 ehea_error("query_ehea_qp failed (4)");
2085 goto out;
2086 }
2087
2088 ret = 0;
2089out:
2090 kfree(cb0);
2091 return ret;
2092}
2093
2094static int ehea_port_res_setup(struct ehea_port *port, int def_qps,
2095 int add_tx_qps)
2096{
2097 int ret, i;
2098 struct port_res_cfg pr_cfg, pr_cfg_small_rx;
2099 enum ehea_eq_type eq_type = EHEA_EQ;
2100
2101 port->qp_eq = ehea_create_eq(port->adapter, eq_type,
2102 EHEA_MAX_ENTRIES_EQ, 1);
2103 if (!port->qp_eq) {
2104 ret = -EINVAL;
2105 ehea_error("ehea_create_eq failed (qp_eq)");
2106 goto out_kill_eq;
2107 }
2108
2109 pr_cfg.max_entries_rcq = rq1_entries + rq2_entries + rq3_entries;
Jan-Bernd Themann18604c52007-02-28 18:34:10 +01002110 pr_cfg.max_entries_scq = sq_entries * 2;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002111 pr_cfg.max_entries_sq = sq_entries;
2112 pr_cfg.max_entries_rq1 = rq1_entries;
2113 pr_cfg.max_entries_rq2 = rq2_entries;
2114 pr_cfg.max_entries_rq3 = rq3_entries;
2115
2116 pr_cfg_small_rx.max_entries_rcq = 1;
2117 pr_cfg_small_rx.max_entries_scq = sq_entries;
2118 pr_cfg_small_rx.max_entries_sq = sq_entries;
2119 pr_cfg_small_rx.max_entries_rq1 = 1;
2120 pr_cfg_small_rx.max_entries_rq2 = 1;
2121 pr_cfg_small_rx.max_entries_rq3 = 1;
2122
2123 for (i = 0; i < def_qps; i++) {
2124 ret = ehea_init_port_res(port, &port->port_res[i], &pr_cfg, i);
2125 if (ret)
2126 goto out_clean_pr;
2127 }
2128 for (i = def_qps; i < def_qps + add_tx_qps; i++) {
2129 ret = ehea_init_port_res(port, &port->port_res[i],
2130 &pr_cfg_small_rx, i);
2131 if (ret)
2132 goto out_clean_pr;
2133 }
2134
2135 return 0;
2136
2137out_clean_pr:
2138 while (--i >= 0)
2139 ehea_clean_portres(port, &port->port_res[i]);
2140
2141out_kill_eq:
2142 ehea_destroy_eq(port->qp_eq);
2143 return ret;
2144}
2145
2146static int ehea_clean_all_portres(struct ehea_port *port)
2147{
2148 int ret = 0;
2149 int i;
2150
2151 for(i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++)
2152 ret |= ehea_clean_portres(port, &port->port_res[i]);
2153
2154 ret |= ehea_destroy_eq(port->qp_eq);
2155
2156 return ret;
2157}
2158
Thomas Klein35cf2e22007-08-06 13:55:14 +02002159static void ehea_remove_adapter_mr(struct ehea_adapter *adapter)
Thomas Klein1211bb62007-04-26 11:56:43 +02002160{
Thomas Klein35cf2e22007-08-06 13:55:14 +02002161 if (adapter->active_ports)
2162 return;
Thomas Klein1211bb62007-04-26 11:56:43 +02002163
2164 ehea_rem_mr(&adapter->mr);
2165}
2166
Thomas Klein35cf2e22007-08-06 13:55:14 +02002167static int ehea_add_adapter_mr(struct ehea_adapter *adapter)
Thomas Klein1211bb62007-04-26 11:56:43 +02002168{
Thomas Klein35cf2e22007-08-06 13:55:14 +02002169 if (adapter->active_ports)
2170 return 0;
Thomas Klein1211bb62007-04-26 11:56:43 +02002171
2172 return ehea_reg_kernel_mr(adapter, &adapter->mr);
2173}
2174
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002175static int ehea_up(struct net_device *dev)
2176{
2177 int ret, i;
2178 struct ehea_port *port = netdev_priv(dev);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002179
2180 if (port->state == EHEA_PORT_UP)
2181 return 0;
2182
2183 ret = ehea_port_res_setup(port, port->num_def_qps,
2184 port->num_add_tx_qps);
2185 if (ret) {
2186 ehea_error("port_res_failed");
2187 goto out;
2188 }
2189
2190 /* Set default QP for this port */
2191 ret = ehea_configure_port(port);
2192 if (ret) {
2193 ehea_error("ehea_configure_port failed. ret:%d", ret);
2194 goto out_clean_pr;
2195 }
2196
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002197 ret = ehea_reg_interrupts(dev);
2198 if (ret) {
Thomas Kleinf9e29222007-07-18 17:34:09 +02002199 ehea_error("reg_interrupts failed. ret:%d", ret);
2200 goto out_clean_pr;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002201 }
2202
2203 for(i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++) {
2204 ret = ehea_activate_qp(port->adapter, port->port_res[i].qp);
2205 if (ret) {
2206 ehea_error("activate_qp failed");
2207 goto out_free_irqs;
2208 }
2209 }
2210
2211 for(i = 0; i < port->num_def_qps; i++) {
2212 ret = ehea_fill_port_res(&port->port_res[i]);
2213 if (ret) {
2214 ehea_error("out_free_irqs");
2215 goto out_free_irqs;
2216 }
2217 }
2218
2219 ret = 0;
2220 port->state = EHEA_PORT_UP;
2221 goto out;
2222
2223out_free_irqs:
2224 ehea_free_interrupts(dev);
2225
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002226out_clean_pr:
2227 ehea_clean_all_portres(port);
2228out:
Thomas Klein44c82152007-07-11 16:32:00 +02002229 if (ret)
2230 ehea_info("Failed starting %s. ret=%i", dev->name, ret);
2231
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002232 return ret;
2233}
2234
Stephen Hemmingerbea33482007-10-03 16:41:36 -07002235static void port_napi_disable(struct ehea_port *port)
2236{
2237 int i;
2238
2239 for (i = 0; i < port->num_def_qps; i++)
2240 napi_disable(&port->port_res[i].napi);
2241}
2242
2243static void port_napi_enable(struct ehea_port *port)
2244{
2245 int i;
2246
2247 for (i = 0; i < port->num_def_qps; i++)
2248 napi_enable(&port->port_res[i].napi);
2249}
2250
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002251static int ehea_open(struct net_device *dev)
2252{
2253 int ret;
2254 struct ehea_port *port = netdev_priv(dev);
2255
2256 down(&port->port_lock);
2257
2258 if (netif_msg_ifup(port))
2259 ehea_info("enabling port %s", dev->name);
2260
2261 ret = ehea_up(dev);
Stephen Hemmingerbea33482007-10-03 16:41:36 -07002262 if (!ret) {
2263 port_napi_enable(port);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002264 netif_start_queue(dev);
Stephen Hemmingerbea33482007-10-03 16:41:36 -07002265 }
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002266
2267 up(&port->port_lock);
2268
2269 return ret;
2270}
2271
2272static int ehea_down(struct net_device *dev)
2273{
Stephen Hemmingerbea33482007-10-03 16:41:36 -07002274 int ret;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002275 struct ehea_port *port = netdev_priv(dev);
2276
2277 if (port->state == EHEA_PORT_DOWN)
2278 return 0;
2279
2280 ehea_drop_multicast_list(dev);
2281 ehea_free_interrupts(dev);
2282
Stephen Hemmingerbea33482007-10-03 16:41:36 -07002283 port_napi_disable(port);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002284
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002285 port->state = EHEA_PORT_DOWN;
Thomas Klein44c82152007-07-11 16:32:00 +02002286
2287 ret = ehea_clean_all_portres(port);
2288 if (ret)
2289 ehea_info("Failed freeing resources for %s. ret=%i",
2290 dev->name, ret);
2291
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002292 return ret;
2293}
2294
2295static int ehea_stop(struct net_device *dev)
2296{
2297 int ret;
2298 struct ehea_port *port = netdev_priv(dev);
2299
2300 if (netif_msg_ifdown(port))
2301 ehea_info("disabling port %s", dev->name);
2302
2303 flush_workqueue(port->adapter->ehea_wq);
2304 down(&port->port_lock);
2305 netif_stop_queue(dev);
2306 ret = ehea_down(dev);
2307 up(&port->port_lock);
2308 return ret;
2309}
2310
David Howellsc4028952006-11-22 14:57:56 +00002311static void ehea_reset_port(struct work_struct *work)
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002312{
2313 int ret;
David Howellsc4028952006-11-22 14:57:56 +00002314 struct ehea_port *port =
2315 container_of(work, struct ehea_port, reset_task);
2316 struct net_device *dev = port->netdev;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002317
2318 port->resets++;
2319 down(&port->port_lock);
2320 netif_stop_queue(dev);
Stephen Hemmingerbea33482007-10-03 16:41:36 -07002321
2322 port_napi_disable(port);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002323
Thomas Klein44c82152007-07-11 16:32:00 +02002324 ehea_down(dev);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002325
2326 ret = ehea_up(dev);
Thomas Klein44c82152007-07-11 16:32:00 +02002327 if (ret)
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002328 goto out;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002329
2330 if (netif_msg_timer(port))
2331 ehea_info("Device %s resetted successfully", dev->name);
2332
Stephen Hemmingerbea33482007-10-03 16:41:36 -07002333 port_napi_enable(port);
2334
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002335 netif_wake_queue(dev);
2336out:
2337 up(&port->port_lock);
2338 return;
2339}
2340
Thomas Klein44c82152007-07-11 16:32:00 +02002341static void ehea_rereg_mrs(struct work_struct *work)
2342{
2343 int ret, i;
2344 struct ehea_adapter *adapter;
2345
2346 ehea_info("LPAR memory enlarged - re-initializing driver");
2347
2348 list_for_each_entry(adapter, &adapter_list, list)
2349 if (adapter->active_ports) {
2350 /* Shutdown all ports */
2351 for (i = 0; i < EHEA_MAX_PORTS; i++) {
2352 struct ehea_port *port = adapter->port[i];
2353
2354 if (port) {
2355 struct net_device *dev = port->netdev;
2356
2357 if (dev->flags & IFF_UP) {
2358 ehea_info("stopping %s",
2359 dev->name);
2360 down(&port->port_lock);
2361 netif_stop_queue(dev);
Stephen Hemmingerbea33482007-10-03 16:41:36 -07002362
2363 port_napi_disable(port);
2364
Thomas Klein44c82152007-07-11 16:32:00 +02002365 ehea_down(dev);
2366 up(&port->port_lock);
2367 }
2368 }
2369 }
2370
2371 /* Unregister old memory region */
2372 ret = ehea_rem_mr(&adapter->mr);
2373 if (ret) {
2374 ehea_error("unregister MR failed - driver"
2375 " inoperable!");
2376 goto out;
2377 }
2378 }
2379
2380 ehea_destroy_busmap();
2381
2382 ret = ehea_create_busmap();
2383 if (ret)
2384 goto out;
2385
2386 clear_bit(__EHEA_STOP_XFER, &ehea_driver_flags);
2387
2388 list_for_each_entry(adapter, &adapter_list, list)
2389 if (adapter->active_ports) {
2390 /* Register new memory region */
2391 ret = ehea_reg_kernel_mr(adapter, &adapter->mr);
2392 if (ret) {
2393 ehea_error("register MR failed - driver"
2394 " inoperable!");
2395 goto out;
2396 }
2397
2398 /* Restart all ports */
2399 for (i = 0; i < EHEA_MAX_PORTS; i++) {
2400 struct ehea_port *port = adapter->port[i];
2401
2402 if (port) {
2403 struct net_device *dev = port->netdev;
2404
2405 if (dev->flags & IFF_UP) {
2406 ehea_info("restarting %s",
2407 dev->name);
2408 down(&port->port_lock);
2409
2410 ret = ehea_up(dev);
2411 if (!ret) {
Stephen Hemmingerbea33482007-10-03 16:41:36 -07002412 port_napi_enable(port);
Thomas Klein44c82152007-07-11 16:32:00 +02002413 netif_wake_queue(dev);
2414 }
2415
2416 up(&port->port_lock);
2417 }
2418 }
2419 }
2420 }
2421out:
2422 return;
2423}
2424
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002425static void ehea_tx_watchdog(struct net_device *dev)
2426{
2427 struct ehea_port *port = netdev_priv(dev);
2428
2429 if (netif_carrier_ok(dev))
2430 queue_work(port->adapter->ehea_wq, &port->reset_task);
2431}
2432
2433int ehea_sense_adapter_attr(struct ehea_adapter *adapter)
2434{
2435 struct hcp_query_ehea *cb;
2436 u64 hret;
2437 int ret;
2438
Thomas Kleina1d261c2006-11-03 17:48:23 +01002439 cb = kzalloc(PAGE_SIZE, GFP_KERNEL);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002440 if (!cb) {
2441 ret = -ENOMEM;
2442 goto out;
2443 }
2444
2445 hret = ehea_h_query_ehea(adapter->handle, cb);
2446
2447 if (hret != H_SUCCESS) {
2448 ret = -EIO;
2449 goto out_herr;
2450 }
2451
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002452 adapter->max_mc_mac = cb->max_mc_mac - 1;
2453 ret = 0;
2454
2455out_herr:
2456 kfree(cb);
2457out:
2458 return ret;
2459}
2460
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01002461int ehea_get_jumboframe_status(struct ehea_port *port, int *jumbo)
2462{
2463 struct hcp_ehea_port_cb4 *cb4;
2464 u64 hret;
2465 int ret = 0;
2466
2467 *jumbo = 0;
2468
2469 /* (Try to) enable *jumbo frames */
2470 cb4 = kzalloc(PAGE_SIZE, GFP_KERNEL);
2471 if (!cb4) {
2472 ehea_error("no mem for cb4");
2473 ret = -ENOMEM;
2474 goto out;
2475 } else {
2476 hret = ehea_h_query_ehea_port(port->adapter->handle,
2477 port->logical_port_id,
2478 H_PORT_CB4,
2479 H_PORT_CB4_JUMBO, cb4);
2480 if (hret == H_SUCCESS) {
2481 if (cb4->jumbo_frame)
2482 *jumbo = 1;
2483 else {
2484 cb4->jumbo_frame = 1;
2485 hret = ehea_h_modify_ehea_port(port->adapter->
2486 handle,
2487 port->
2488 logical_port_id,
2489 H_PORT_CB4,
2490 H_PORT_CB4_JUMBO,
2491 cb4);
2492 if (hret == H_SUCCESS)
2493 *jumbo = 1;
2494 }
2495 } else
2496 ret = -EINVAL;
2497
2498 kfree(cb4);
2499 }
2500out:
2501 return ret;
2502}
2503
2504static ssize_t ehea_show_port_id(struct device *dev,
2505 struct device_attribute *attr, char *buf)
2506{
2507 struct ehea_port *port = container_of(dev, struct ehea_port, ofdev.dev);
Jan-Bernd Themanna8e34fd2007-08-22 16:20:58 +02002508 return sprintf(buf, "%d", port->logical_port_id);
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01002509}
2510
2511static DEVICE_ATTR(log_port_id, S_IRUSR | S_IRGRP | S_IROTH, ehea_show_port_id,
2512 NULL);
2513
2514static void __devinit logical_port_release(struct device *dev)
2515{
2516 struct ehea_port *port = container_of(dev, struct ehea_port, ofdev.dev);
2517 of_node_put(port->ofdev.node);
2518}
2519
Thomas Kleind1dea382007-04-26 11:56:13 +02002520static int ehea_driver_sysfs_add(struct device *dev,
Jan-Bernd Themannd1d25aa2007-07-02 13:00:46 +02002521 struct device_driver *driver)
Thomas Kleind1dea382007-04-26 11:56:13 +02002522{
2523 int ret;
2524
2525 ret = sysfs_create_link(&driver->kobj, &dev->kobj,
2526 kobject_name(&dev->kobj));
2527 if (ret == 0) {
2528 ret = sysfs_create_link(&dev->kobj, &driver->kobj,
2529 "driver");
2530 if (ret)
2531 sysfs_remove_link(&driver->kobj,
2532 kobject_name(&dev->kobj));
2533 }
2534 return ret;
2535}
2536
2537static void ehea_driver_sysfs_remove(struct device *dev,
Jan-Bernd Themannd1d25aa2007-07-02 13:00:46 +02002538 struct device_driver *driver)
Thomas Kleind1dea382007-04-26 11:56:13 +02002539{
2540 struct device_driver *drv = driver;
2541
2542 if (drv) {
2543 sysfs_remove_link(&drv->kobj, kobject_name(&dev->kobj));
2544 sysfs_remove_link(&dev->kobj, "driver");
2545 }
2546}
2547
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01002548static struct device *ehea_register_port(struct ehea_port *port,
2549 struct device_node *dn)
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002550{
2551 int ret;
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01002552
2553 port->ofdev.node = of_node_get(dn);
2554 port->ofdev.dev.parent = &port->adapter->ebus_dev->ofdev.dev;
Thomas Kleind1dea382007-04-26 11:56:13 +02002555 port->ofdev.dev.bus = &ibmebus_bus_type;
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01002556
Thomas Kleind1dea382007-04-26 11:56:13 +02002557 sprintf(port->ofdev.dev.bus_id, "port%d", port_name_cnt++);
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01002558 port->ofdev.dev.release = logical_port_release;
2559
2560 ret = of_device_register(&port->ofdev);
2561 if (ret) {
2562 ehea_error("failed to register device. ret=%d", ret);
2563 goto out;
2564 }
2565
2566 ret = device_create_file(&port->ofdev.dev, &dev_attr_log_port_id);
Jan-Bernd Themannd1d25aa2007-07-02 13:00:46 +02002567 if (ret) {
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01002568 ehea_error("failed to register attributes, ret=%d", ret);
2569 goto out_unreg_of_dev;
2570 }
Jan-Bernd Themanne542aa62007-03-22 17:50:24 +01002571
Thomas Kleind1dea382007-04-26 11:56:13 +02002572 ret = ehea_driver_sysfs_add(&port->ofdev.dev, &ehea_driver.driver);
2573 if (ret) {
2574 ehea_error("failed to register sysfs driver link");
2575 goto out_rem_dev_file;
2576 }
2577
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01002578 return &port->ofdev.dev;
2579
Thomas Kleind1dea382007-04-26 11:56:13 +02002580out_rem_dev_file:
2581 device_remove_file(&port->ofdev.dev, &dev_attr_log_port_id);
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01002582out_unreg_of_dev:
2583 of_device_unregister(&port->ofdev);
2584out:
2585 return NULL;
2586}
2587
2588static void ehea_unregister_port(struct ehea_port *port)
2589{
Thomas Kleind1dea382007-04-26 11:56:13 +02002590 ehea_driver_sysfs_remove(&port->ofdev.dev, &ehea_driver.driver);
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01002591 device_remove_file(&port->ofdev.dev, &dev_attr_log_port_id);
2592 of_device_unregister(&port->ofdev);
2593}
2594
2595struct ehea_port *ehea_setup_single_port(struct ehea_adapter *adapter,
2596 u32 logical_port_id,
2597 struct device_node *dn)
2598{
2599 int ret;
2600 struct net_device *dev;
2601 struct ehea_port *port;
2602 struct device *port_dev;
2603 int jumbo;
2604
2605 /* allocate memory for the port structures */
2606 dev = alloc_etherdev(sizeof(struct ehea_port));
2607
2608 if (!dev) {
2609 ehea_error("no mem for net_device");
2610 ret = -ENOMEM;
2611 goto out_err;
2612 }
2613
2614 port = netdev_priv(dev);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002615
2616 sema_init(&port->port_lock, 1);
2617 port->state = EHEA_PORT_DOWN;
2618 port->sig_comp_iv = sq_entries / 10;
2619
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01002620 port->adapter = adapter;
2621 port->netdev = dev;
2622 port->logical_port_id = logical_port_id;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002623
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01002624 port->msg_enable = netif_msg_init(msg_level, EHEA_MSG_DEFAULT);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002625
2626 port->mc_list = kzalloc(sizeof(struct ehea_mc_list), GFP_KERNEL);
2627 if (!port->mc_list) {
2628 ret = -ENOMEM;
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01002629 goto out_free_ethdev;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002630 }
2631
2632 INIT_LIST_HEAD(&port->mc_list->list);
2633
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002634 ret = ehea_sense_port_attr(port);
2635 if (ret)
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01002636 goto out_free_mc_list;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002637
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01002638 port_dev = ehea_register_port(port, dn);
2639 if (!port_dev)
2640 goto out_free_mc_list;
Thomas Klein9c750b72007-01-29 18:44:01 +01002641
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01002642 SET_NETDEV_DEV(dev, port_dev);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002643
2644 /* initialize net_device structure */
2645 SET_MODULE_OWNER(dev);
2646
2647 memcpy(dev->dev_addr, &port->mac_addr, ETH_ALEN);
2648
2649 dev->open = ehea_open;
Jan-Bernd Themann8d22c972007-07-23 16:05:03 +02002650#ifdef CONFIG_NET_POLL_CONTROLLER
2651 dev->poll_controller = ehea_netpoll;
2652#endif
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002653 dev->stop = ehea_stop;
2654 dev->hard_start_xmit = ehea_start_xmit;
2655 dev->get_stats = ehea_get_stats;
2656 dev->set_multicast_list = ehea_set_multicast_list;
2657 dev->set_mac_address = ehea_set_mac_addr;
2658 dev->change_mtu = ehea_change_mtu;
2659 dev->vlan_rx_register = ehea_vlan_rx_register;
2660 dev->vlan_rx_add_vid = ehea_vlan_rx_add_vid;
2661 dev->vlan_rx_kill_vid = ehea_vlan_rx_kill_vid;
2662 dev->features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_TSO
2663 | NETIF_F_HIGHDMA | NETIF_F_HW_CSUM | NETIF_F_HW_VLAN_TX
2664 | NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER
2665 | NETIF_F_LLTX;
2666 dev->tx_timeout = &ehea_tx_watchdog;
2667 dev->watchdog_timeo = EHEA_WATCH_DOG_TIMEOUT;
2668
David Howellsc4028952006-11-22 14:57:56 +00002669 INIT_WORK(&port->reset_task, ehea_reset_port);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002670
Thomas Kleinf9e29222007-07-18 17:34:09 +02002671 ret = ehea_broadcast_reg_helper(port, H_REG_BCMC);
2672 if (ret) {
2673 ret = -EIO;
2674 goto out_unreg_port;
2675 }
2676
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002677 ehea_set_ethtool_ops(dev);
2678
2679 ret = register_netdev(dev);
2680 if (ret) {
2681 ehea_error("register_netdev failed. ret=%d", ret);
Thomas Kleinf9e29222007-07-18 17:34:09 +02002682 goto out_dereg_bc;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002683 }
2684
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01002685 ret = ehea_get_jumboframe_status(port, &jumbo);
Jan-Bernd Themanne542aa62007-03-22 17:50:24 +01002686 if (ret)
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01002687 ehea_error("failed determining jumbo frame status for %s",
2688 port->netdev->name);
2689
Thomas Klein9c750b72007-01-29 18:44:01 +01002690 ehea_info("%s: Jumbo frames are %sabled", dev->name,
2691 jumbo == 1 ? "en" : "dis");
2692
Thomas Klein44c82152007-07-11 16:32:00 +02002693 adapter->active_ports++;
2694
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01002695 return port;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002696
Thomas Kleinf9e29222007-07-18 17:34:09 +02002697out_dereg_bc:
2698 ehea_broadcast_reg_helper(port, H_DEREG_BCMC);
2699
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01002700out_unreg_port:
2701 ehea_unregister_port(port);
2702
2703out_free_mc_list:
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002704 kfree(port->mc_list);
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01002705
2706out_free_ethdev:
2707 free_netdev(dev);
2708
2709out_err:
2710 ehea_error("setting up logical port with id=%d failed, ret=%d",
2711 logical_port_id, ret);
2712 return NULL;
2713}
2714
2715static void ehea_shutdown_single_port(struct ehea_port *port)
2716{
2717 unregister_netdev(port->netdev);
2718 ehea_unregister_port(port);
Thomas Kleinf9e29222007-07-18 17:34:09 +02002719 ehea_broadcast_reg_helper(port, H_DEREG_BCMC);
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01002720 kfree(port->mc_list);
2721 free_netdev(port->netdev);
Thomas Klein44c82152007-07-11 16:32:00 +02002722 port->adapter->active_ports--;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002723}
2724
2725static int ehea_setup_ports(struct ehea_adapter *adapter)
2726{
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01002727 struct device_node *lhea_dn;
2728 struct device_node *eth_dn = NULL;
Jan-Bernd Themannd1d25aa2007-07-02 13:00:46 +02002729
Stephen Rothwell9f9a3b82007-05-01 13:51:32 +10002730 const u32 *dn_log_port_id;
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01002731 int i = 0;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002732
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01002733 lhea_dn = adapter->ebus_dev->ofdev.node;
Jan-Bernd Themann1eef4e02007-03-22 17:49:42 +01002734 while ((eth_dn = of_get_next_child(lhea_dn, eth_dn))) {
Jan-Bernd Themanne542aa62007-03-22 17:50:24 +01002735
Stephen Rothwell40cd3a42007-05-01 13:54:02 +10002736 dn_log_port_id = of_get_property(eth_dn, "ibm,hea-port-no",
Jan-Bernd Themannd1d25aa2007-07-02 13:00:46 +02002737 NULL);
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01002738 if (!dn_log_port_id) {
2739 ehea_error("bad device node: eth_dn name=%s",
2740 eth_dn->full_name);
2741 continue;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002742 }
2743
Thomas Klein1211bb62007-04-26 11:56:43 +02002744 if (ehea_add_adapter_mr(adapter)) {
2745 ehea_error("creating MR failed");
2746 of_node_put(eth_dn);
2747 return -EIO;
2748 }
2749
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01002750 adapter->port[i] = ehea_setup_single_port(adapter,
2751 *dn_log_port_id,
2752 eth_dn);
2753 if (adapter->port[i])
2754 ehea_info("%s -> logical port id #%d",
Jan-Bernd Themanne542aa62007-03-22 17:50:24 +01002755 adapter->port[i]->netdev->name,
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01002756 *dn_log_port_id);
Thomas Klein1211bb62007-04-26 11:56:43 +02002757 else
2758 ehea_remove_adapter_mr(adapter);
2759
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01002760 i++;
Jan-Bernd Themann1eef4e02007-03-22 17:49:42 +01002761 };
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002762
Thomas Klein1211bb62007-04-26 11:56:43 +02002763 return 0;
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01002764}
2765
Jan-Bernd Themanne542aa62007-03-22 17:50:24 +01002766static struct device_node *ehea_get_eth_dn(struct ehea_adapter *adapter,
2767 u32 logical_port_id)
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01002768{
2769 struct device_node *lhea_dn;
2770 struct device_node *eth_dn = NULL;
Stephen Rothwell9f9a3b82007-05-01 13:51:32 +10002771 const u32 *dn_log_port_id;
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01002772
2773 lhea_dn = adapter->ebus_dev->ofdev.node;
Jan-Bernd Themann1eef4e02007-03-22 17:49:42 +01002774 while ((eth_dn = of_get_next_child(lhea_dn, eth_dn))) {
Jan-Bernd Themanne542aa62007-03-22 17:50:24 +01002775
Stephen Rothwell40cd3a42007-05-01 13:54:02 +10002776 dn_log_port_id = of_get_property(eth_dn, "ibm,hea-port-no",
Jan-Bernd Themannd1d25aa2007-07-02 13:00:46 +02002777 NULL);
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01002778 if (dn_log_port_id)
2779 if (*dn_log_port_id == logical_port_id)
2780 return eth_dn;
Jan-Bernd Themann1eef4e02007-03-22 17:49:42 +01002781 };
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01002782
2783 return NULL;
2784}
2785
2786static ssize_t ehea_probe_port(struct device *dev,
2787 struct device_attribute *attr,
2788 const char *buf, size_t count)
2789{
2790 struct ehea_adapter *adapter = dev->driver_data;
2791 struct ehea_port *port;
2792 struct device_node *eth_dn = NULL;
2793 int i;
2794
2795 u32 logical_port_id;
2796
Jan-Bernd Themanna8e34fd2007-08-22 16:20:58 +02002797 sscanf(buf, "%d", &logical_port_id);
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01002798
2799 port = ehea_get_port(adapter, logical_port_id);
2800
2801 if (port) {
2802 ehea_info("adding port with logical port id=%d failed. port "
2803 "already configured as %s.", logical_port_id,
2804 port->netdev->name);
2805 return -EINVAL;
2806 }
Jan-Bernd Themanne542aa62007-03-22 17:50:24 +01002807
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01002808 eth_dn = ehea_get_eth_dn(adapter, logical_port_id);
2809
2810 if (!eth_dn) {
2811 ehea_info("no logical port with id %d found", logical_port_id);
2812 return -EINVAL;
2813 }
Jan-Bernd Themanne542aa62007-03-22 17:50:24 +01002814
Thomas Klein1211bb62007-04-26 11:56:43 +02002815 if (ehea_add_adapter_mr(adapter)) {
2816 ehea_error("creating MR failed");
2817 return -EIO;
2818 }
2819
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01002820 port = ehea_setup_single_port(adapter, logical_port_id, eth_dn);
2821
Jan-Bernd Themann1eef4e02007-03-22 17:49:42 +01002822 of_node_put(eth_dn);
2823
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01002824 if (port) {
2825 for (i=0; i < EHEA_MAX_PORTS; i++)
2826 if (!adapter->port[i]) {
2827 adapter->port[i] = port;
2828 break;
2829 }
2830
2831 ehea_info("added %s (logical port id=%d)", port->netdev->name,
2832 logical_port_id);
Thomas Klein1211bb62007-04-26 11:56:43 +02002833 } else {
2834 ehea_remove_adapter_mr(adapter);
Jan-Bernd Themanne542aa62007-03-22 17:50:24 +01002835 return -EIO;
Thomas Klein1211bb62007-04-26 11:56:43 +02002836 }
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01002837
2838 return (ssize_t) count;
2839}
2840
2841static ssize_t ehea_remove_port(struct device *dev,
2842 struct device_attribute *attr,
2843 const char *buf, size_t count)
2844{
2845 struct ehea_adapter *adapter = dev->driver_data;
2846 struct ehea_port *port;
2847 int i;
2848 u32 logical_port_id;
2849
Jan-Bernd Themanna8e34fd2007-08-22 16:20:58 +02002850 sscanf(buf, "%d", &logical_port_id);
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01002851
2852 port = ehea_get_port(adapter, logical_port_id);
2853
2854 if (port) {
2855 ehea_info("removed %s (logical port id=%d)", port->netdev->name,
2856 logical_port_id);
2857
2858 ehea_shutdown_single_port(port);
2859
2860 for (i=0; i < EHEA_MAX_PORTS; i++)
2861 if (adapter->port[i] == port) {
2862 adapter->port[i] = NULL;
2863 break;
2864 }
2865 } else {
2866 ehea_error("removing port with logical port id=%d failed. port "
2867 "not configured.", logical_port_id);
2868 return -EINVAL;
2869 }
2870
Thomas Klein1211bb62007-04-26 11:56:43 +02002871 ehea_remove_adapter_mr(adapter);
2872
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01002873 return (ssize_t) count;
2874}
2875
2876static DEVICE_ATTR(probe_port, S_IWUSR, NULL, ehea_probe_port);
2877static DEVICE_ATTR(remove_port, S_IWUSR, NULL, ehea_remove_port);
2878
2879int ehea_create_device_sysfs(struct ibmebus_dev *dev)
2880{
2881 int ret = device_create_file(&dev->ofdev.dev, &dev_attr_probe_port);
2882 if (ret)
2883 goto out;
2884
2885 ret = device_create_file(&dev->ofdev.dev, &dev_attr_remove_port);
2886out:
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002887 return ret;
2888}
2889
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01002890void ehea_remove_device_sysfs(struct ibmebus_dev *dev)
2891{
2892 device_remove_file(&dev->ofdev.dev, &dev_attr_probe_port);
2893 device_remove_file(&dev->ofdev.dev, &dev_attr_remove_port);
2894}
2895
2896static int __devinit ehea_probe_adapter(struct ibmebus_dev *dev,
2897 const struct of_device_id *id)
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002898{
2899 struct ehea_adapter *adapter;
Stephen Rothwell9f9a3b82007-05-01 13:51:32 +10002900 const u64 *adapter_handle;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002901 int ret;
2902
Jan-Bernd Themann1eef4e02007-03-22 17:49:42 +01002903 if (!dev || !dev->ofdev.node) {
2904 ehea_error("Invalid ibmebus device probed");
2905 return -EINVAL;
2906 }
2907
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002908 adapter = kzalloc(sizeof(*adapter), GFP_KERNEL);
2909 if (!adapter) {
2910 ret = -ENOMEM;
2911 dev_err(&dev->ofdev.dev, "no mem for ehea_adapter\n");
2912 goto out;
2913 }
2914
Thomas Klein44c82152007-07-11 16:32:00 +02002915 list_add(&adapter->list, &adapter_list);
2916
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01002917 adapter->ebus_dev = dev;
2918
Stephen Rothwell40cd3a42007-05-01 13:54:02 +10002919 adapter_handle = of_get_property(dev->ofdev.node, "ibm,hea-handle",
Jan-Bernd Themannd1d25aa2007-07-02 13:00:46 +02002920 NULL);
Thomas Klein061bf3c2007-01-22 12:52:20 +01002921 if (adapter_handle)
2922 adapter->handle = *adapter_handle;
2923
2924 if (!adapter->handle) {
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002925 dev_err(&dev->ofdev.dev, "failed getting handle for adapter"
2926 " '%s'\n", dev->ofdev.node->full_name);
2927 ret = -ENODEV;
2928 goto out_free_ad;
2929 }
2930
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002931 adapter->pd = EHEA_PD_ID;
2932
2933 dev->ofdev.dev.driver_data = adapter;
2934
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002935
2936 /* initialize adapter and ports */
2937 /* get adapter properties */
2938 ret = ehea_sense_adapter_attr(adapter);
2939 if (ret) {
2940 dev_err(&dev->ofdev.dev, "sense_adapter_attr failed: %d", ret);
Thomas Klein1211bb62007-04-26 11:56:43 +02002941 goto out_free_ad;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002942 }
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002943
2944 adapter->neq = ehea_create_eq(adapter,
2945 EHEA_NEQ, EHEA_MAX_ENTRIES_EQ, 1);
2946 if (!adapter->neq) {
Jan-Bernd Themann1eef4e02007-03-22 17:49:42 +01002947 ret = -EIO;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002948 dev_err(&dev->ofdev.dev, "NEQ creation failed");
Thomas Klein1211bb62007-04-26 11:56:43 +02002949 goto out_free_ad;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002950 }
2951
2952 tasklet_init(&adapter->neq_tasklet, ehea_neq_tasklet,
2953 (unsigned long)adapter);
2954
2955 ret = ibmebus_request_irq(NULL, adapter->neq->attr.ist1,
Thomas Gleixner38515e92007-02-14 00:33:16 -08002956 ehea_interrupt_neq, IRQF_DISABLED,
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002957 "ehea_neq", adapter);
2958 if (ret) {
2959 dev_err(&dev->ofdev.dev, "requesting NEQ IRQ failed");
2960 goto out_kill_eq;
2961 }
2962
2963 adapter->ehea_wq = create_workqueue("ehea_wq");
Jan-Bernd Themann1eef4e02007-03-22 17:49:42 +01002964 if (!adapter->ehea_wq) {
2965 ret = -EIO;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002966 goto out_free_irq;
Jan-Bernd Themann1eef4e02007-03-22 17:49:42 +01002967 }
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002968
Jan-Bernd Themann1eef4e02007-03-22 17:49:42 +01002969 ret = ehea_create_device_sysfs(dev);
2970 if (ret)
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01002971 goto out_kill_wq;
2972
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002973 ret = ehea_setup_ports(adapter);
2974 if (ret) {
2975 dev_err(&dev->ofdev.dev, "setup_ports failed");
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01002976 goto out_rem_dev_sysfs;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002977 }
2978
2979 ret = 0;
2980 goto out;
2981
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01002982out_rem_dev_sysfs:
2983 ehea_remove_device_sysfs(dev);
2984
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002985out_kill_wq:
2986 destroy_workqueue(adapter->ehea_wq);
2987
2988out_free_irq:
2989 ibmebus_free_irq(NULL, adapter->neq->attr.ist1, adapter);
2990
2991out_kill_eq:
2992 ehea_destroy_eq(adapter->neq);
2993
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002994out_free_ad:
2995 kfree(adapter);
2996out:
2997 return ret;
2998}
2999
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02003000static int __devexit ehea_remove(struct ibmebus_dev *dev)
3001{
3002 struct ehea_adapter *adapter = dev->ofdev.dev.driver_data;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02003003 int i;
3004
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01003005 for (i = 0; i < EHEA_MAX_PORTS; i++)
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02003006 if (adapter->port[i]) {
3007 ehea_shutdown_single_port(adapter->port[i]);
3008 adapter->port[i] = NULL;
3009 }
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01003010
3011 ehea_remove_device_sysfs(dev);
3012
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02003013 destroy_workqueue(adapter->ehea_wq);
3014
3015 ibmebus_free_irq(NULL, adapter->neq->attr.ist1, adapter);
Thomas Kleind4150a22007-01-29 18:44:41 +01003016 tasklet_kill(&adapter->neq_tasklet);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02003017
3018 ehea_destroy_eq(adapter->neq);
Thomas Klein1211bb62007-04-26 11:56:43 +02003019 ehea_remove_adapter_mr(adapter);
Thomas Klein44c82152007-07-11 16:32:00 +02003020 list_del(&adapter->list);
3021
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02003022 kfree(adapter);
Thomas Klein44c82152007-07-11 16:32:00 +02003023
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02003024 return 0;
3025}
3026
3027static int check_module_parm(void)
3028{
3029 int ret = 0;
3030
3031 if ((rq1_entries < EHEA_MIN_ENTRIES_QP) ||
3032 (rq1_entries > EHEA_MAX_ENTRIES_RQ1)) {
3033 ehea_info("Bad parameter: rq1_entries");
3034 ret = -EINVAL;
3035 }
3036 if ((rq2_entries < EHEA_MIN_ENTRIES_QP) ||
3037 (rq2_entries > EHEA_MAX_ENTRIES_RQ2)) {
3038 ehea_info("Bad parameter: rq2_entries");
3039 ret = -EINVAL;
3040 }
3041 if ((rq3_entries < EHEA_MIN_ENTRIES_QP) ||
3042 (rq3_entries > EHEA_MAX_ENTRIES_RQ3)) {
3043 ehea_info("Bad parameter: rq3_entries");
3044 ret = -EINVAL;
3045 }
3046 if ((sq_entries < EHEA_MIN_ENTRIES_QP) ||
3047 (sq_entries > EHEA_MAX_ENTRIES_SQ)) {
3048 ehea_info("Bad parameter: sq_entries");
3049 ret = -EINVAL;
3050 }
3051
3052 return ret;
3053}
3054
Jan-Bernd Themann4c3ca4d2007-07-05 09:26:25 +02003055static ssize_t ehea_show_capabilities(struct device_driver *drv,
3056 char *buf)
3057{
3058 return sprintf(buf, "%d", EHEA_CAPABILITIES);
3059}
3060
3061static DRIVER_ATTR(capabilities, S_IRUSR | S_IRGRP | S_IROTH,
3062 ehea_show_capabilities, NULL);
3063
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02003064int __init ehea_module_init(void)
3065{
3066 int ret;
3067
3068 printk(KERN_INFO "IBM eHEA ethernet device driver (Release %s)\n",
3069 DRV_VERSION);
3070
Thomas Klein44c82152007-07-11 16:32:00 +02003071 ehea_driver_wq = create_workqueue("ehea_driver_wq");
3072
3073 INIT_WORK(&ehea_rereg_mr_task, ehea_rereg_mrs);
3074
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02003075 ret = check_module_parm();
3076 if (ret)
3077 goto out;
Thomas Klein44c82152007-07-11 16:32:00 +02003078
3079 ret = ehea_create_busmap();
3080 if (ret)
3081 goto out;
3082
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02003083 ret = ibmebus_register_driver(&ehea_driver);
Jan-Bernd Themann4c3ca4d2007-07-05 09:26:25 +02003084 if (ret) {
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02003085 ehea_error("failed registering eHEA device driver on ebus");
Jan-Bernd Themann4c3ca4d2007-07-05 09:26:25 +02003086 goto out;
3087 }
3088
3089 ret = driver_create_file(&ehea_driver.driver,
3090 &driver_attr_capabilities);
3091 if (ret) {
3092 ehea_error("failed to register capabilities attribute, ret=%d",
3093 ret);
3094 ibmebus_unregister_driver(&ehea_driver);
3095 goto out;
3096 }
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02003097
3098out:
3099 return ret;
3100}
3101
3102static void __exit ehea_module_exit(void)
3103{
Thomas Kleinf46f6ba2007-08-06 13:54:29 +02003104 destroy_workqueue(ehea_driver_wq);
Jan-Bernd Themann4c3ca4d2007-07-05 09:26:25 +02003105 driver_remove_file(&ehea_driver.driver, &driver_attr_capabilities);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02003106 ibmebus_unregister_driver(&ehea_driver);
Thomas Klein44c82152007-07-11 16:32:00 +02003107 ehea_destroy_busmap();
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02003108}
3109
3110module_init(ehea_module_init);
3111module_exit(ehea_module_exit);