blob: d2f715d80077e2436f7cc09cdbbbe47e697685c7 [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>
Jan-Bernd Themann2a6f4e42007-10-26 14:37:28 +020036#include <linux/notifier.h>
37#include <linux/reboot.h>
38
Jan-Bernd Themann7a291082006-09-13 17:44:31 +020039#include <net/ip.h>
40
41#include "ehea.h"
42#include "ehea_qmr.h"
43#include "ehea_phyp.h"
44
45
46MODULE_LICENSE("GPL");
47MODULE_AUTHOR("Christoph Raisch <raisch@de.ibm.com>");
48MODULE_DESCRIPTION("IBM eServer HEA Driver");
49MODULE_VERSION(DRV_VERSION);
50
51
52static int msg_level = -1;
53static int rq1_entries = EHEA_DEF_ENTRIES_RQ1;
54static int rq2_entries = EHEA_DEF_ENTRIES_RQ2;
55static int rq3_entries = EHEA_DEF_ENTRIES_RQ3;
56static int sq_entries = EHEA_DEF_ENTRIES_SQ;
Jan-Bernd Themann18604c52007-02-28 18:34:10 +010057static int use_mcs = 0;
Jan-Bernd Themannd4dc4ec2007-09-25 16:16:34 -070058static int use_lro = 0;
59static int lro_max_aggr = EHEA_LRO_MAX_AGGR;
Jan-Bernd Themann18604c52007-02-28 18:34:10 +010060static int num_tx_qps = EHEA_NUM_TX_QP;
Jan-Bernd Themann8759cf72007-09-07 12:30:17 +020061static int prop_carrier_state = 0;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +020062
63module_param(msg_level, int, 0);
64module_param(rq1_entries, int, 0);
65module_param(rq2_entries, int, 0);
66module_param(rq3_entries, int, 0);
67module_param(sq_entries, int, 0);
Jan-Bernd Themann8759cf72007-09-07 12:30:17 +020068module_param(prop_carrier_state, int, 0);
Jan-Bernd Themann18604c52007-02-28 18:34:10 +010069module_param(use_mcs, int, 0);
Jan-Bernd Themannd4dc4ec2007-09-25 16:16:34 -070070module_param(use_lro, int, 0);
71module_param(lro_max_aggr, int, 0);
Jan-Bernd Themann18604c52007-02-28 18:34:10 +010072module_param(num_tx_qps, int, 0);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +020073
Jan-Bernd Themann18604c52007-02-28 18:34:10 +010074MODULE_PARM_DESC(num_tx_qps, "Number of TX-QPS");
Jan-Bernd Themann7a291082006-09-13 17:44:31 +020075MODULE_PARM_DESC(msg_level, "msg_level");
Jan-Bernd Themann8759cf72007-09-07 12:30:17 +020076MODULE_PARM_DESC(prop_carrier_state, "Propagate carrier state of physical "
77 "port to stack. 1:yes, 0:no. Default = 0 ");
Jan-Bernd Themann7a291082006-09-13 17:44:31 +020078MODULE_PARM_DESC(rq3_entries, "Number of entries for Receive Queue 3 "
79 "[2^x - 1], x = [6..14]. Default = "
80 __MODULE_STRING(EHEA_DEF_ENTRIES_RQ3) ")");
81MODULE_PARM_DESC(rq2_entries, "Number of entries for Receive Queue 2 "
82 "[2^x - 1], x = [6..14]. Default = "
83 __MODULE_STRING(EHEA_DEF_ENTRIES_RQ2) ")");
84MODULE_PARM_DESC(rq1_entries, "Number of entries for Receive Queue 1 "
85 "[2^x - 1], x = [6..14]. Default = "
86 __MODULE_STRING(EHEA_DEF_ENTRIES_RQ1) ")");
87MODULE_PARM_DESC(sq_entries, " Number of entries for the Send Queue "
88 "[2^x - 1], x = [6..14]. Default = "
89 __MODULE_STRING(EHEA_DEF_ENTRIES_SQ) ")");
Jan-Bernd Themann18072a52007-08-22 16:21:24 +020090MODULE_PARM_DESC(use_mcs, " 0:NAPI, 1:Multiple receive queues, Default = 0 ");
Jan-Bernd Themann7a291082006-09-13 17:44:31 +020091
Jan-Bernd Themannd4dc4ec2007-09-25 16:16:34 -070092MODULE_PARM_DESC(lro_max_aggr, " LRO: Max packets to be aggregated. Default = "
93 __MODULE_STRING(EHEA_LRO_MAX_AGGR));
94MODULE_PARM_DESC(use_lro, " Large Receive Offload, 1: enable, 0: disable, "
95 "Default = 0");
96
Thomas Kleind1dea382007-04-26 11:56:13 +020097static int port_name_cnt = 0;
Thomas Klein44c82152007-07-11 16:32:00 +020098static LIST_HEAD(adapter_list);
99u64 ehea_driver_flags = 0;
Thomas Klein44c82152007-07-11 16:32:00 +0200100struct work_struct ehea_rereg_mr_task;
101
Jan-Bernd Themann2c694482007-10-01 16:33:18 +0200102struct semaphore dlpar_mem_lock;
Thomas Kleind1dea382007-04-26 11:56:13 +0200103
Joachim Fenkes6b08f3a2007-09-26 19:45:51 +1000104static int __devinit ehea_probe_adapter(struct of_device *dev,
Jan-Bernd Themannd1d25aa2007-07-02 13:00:46 +0200105 const struct of_device_id *id);
Thomas Kleind1dea382007-04-26 11:56:13 +0200106
Joachim Fenkes6b08f3a2007-09-26 19:45:51 +1000107static int __devexit ehea_remove(struct of_device *dev);
Thomas Kleind1dea382007-04-26 11:56:13 +0200108
109static struct of_device_id ehea_device_table[] = {
110 {
111 .name = "lhea",
112 .compatible = "IBM,lhea",
113 },
114 {},
115};
116
Joachim Fenkes6b08f3a2007-09-26 19:45:51 +1000117static struct of_platform_driver ehea_driver = {
Thomas Kleind1dea382007-04-26 11:56:13 +0200118 .name = "ehea",
Joachim Fenkes6b08f3a2007-09-26 19:45:51 +1000119 .match_table = ehea_device_table,
Thomas Kleind1dea382007-04-26 11:56:13 +0200120 .probe = ehea_probe_adapter,
121 .remove = ehea_remove,
122};
123
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200124void ehea_dump(void *adr, int len, char *msg) {
125 int x;
126 unsigned char *deb = adr;
127 for (x = 0; x < len; x += 16) {
Jan-Bernd Themannd2db9ee2007-02-09 09:10:51 +0100128 printk(DRV_NAME " %s adr=%p ofs=%04x %016lx %016lx\n", msg,
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200129 deb, x, *((u64*)&deb[0]), *((u64*)&deb[8]));
130 deb += 16;
131 }
132}
133
134static struct net_device_stats *ehea_get_stats(struct net_device *dev)
135{
136 struct ehea_port *port = netdev_priv(dev);
137 struct net_device_stats *stats = &port->stats;
138 struct hcp_ehea_port_cb2 *cb2;
Thomas Klein7393b872007-11-21 17:37:58 +0100139 u64 hret, rx_packets, tx_packets;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200140 int i;
141
142 memset(stats, 0, sizeof(*stats));
143
Thomas Kleina1d261c2006-11-03 17:48:23 +0100144 cb2 = kzalloc(PAGE_SIZE, GFP_KERNEL);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200145 if (!cb2) {
146 ehea_error("no mem for cb2");
147 goto out;
148 }
149
150 hret = ehea_h_query_ehea_port(port->adapter->handle,
151 port->logical_port_id,
152 H_PORT_CB2, H_PORT_CB2_ALL, cb2);
153 if (hret != H_SUCCESS) {
154 ehea_error("query_ehea_port failed");
155 goto out_herr;
156 }
157
158 if (netif_msg_hw(port))
159 ehea_dump(cb2, sizeof(*cb2), "net_device_stats");
160
161 rx_packets = 0;
162 for (i = 0; i < port->num_def_qps; i++)
163 rx_packets += port->port_res[i].rx_packets;
164
Thomas Klein7393b872007-11-21 17:37:58 +0100165 tx_packets = 0;
166 for (i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++)
167 tx_packets += port->port_res[i].tx_packets;
168
169 stats->tx_packets = tx_packets;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200170 stats->multicast = cb2->rxmcp;
171 stats->rx_errors = cb2->rxuerr;
172 stats->rx_bytes = cb2->rxo;
173 stats->tx_bytes = cb2->txo;
174 stats->rx_packets = rx_packets;
175
176out_herr:
177 kfree(cb2);
178out:
179 return stats;
180}
181
182static void ehea_refill_rq1(struct ehea_port_res *pr, int index, int nr_of_wqes)
183{
184 struct sk_buff **skb_arr_rq1 = pr->rq1_skba.arr;
185 struct net_device *dev = pr->port->netdev;
186 int max_index_mask = pr->rq1_skba.len - 1;
Jan-Bernd Themann2c694482007-10-01 16:33:18 +0200187 int fill_wqes = pr->rq1_skba.os_skbs + nr_of_wqes;
188 int adder = 0;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200189 int i;
190
Jan-Bernd Themann2c694482007-10-01 16:33:18 +0200191 pr->rq1_skba.os_skbs = 0;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200192
Jan-Bernd Themann2c694482007-10-01 16:33:18 +0200193 if (unlikely(test_bit(__EHEA_STOP_XFER, &ehea_driver_flags))) {
194 pr->rq1_skba.index = index;
195 pr->rq1_skba.os_skbs = fill_wqes;
196 return;
197 }
198
199 for (i = 0; i < fill_wqes; i++) {
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200200 if (!skb_arr_rq1[index]) {
201 skb_arr_rq1[index] = netdev_alloc_skb(dev,
202 EHEA_L_PKT_SIZE);
203 if (!skb_arr_rq1[index]) {
Jan-Bernd Themann2c694482007-10-01 16:33:18 +0200204 pr->rq1_skba.os_skbs = fill_wqes - i;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200205 ehea_error("%s: no mem for skb/%d wqes filled",
206 dev->name, i);
207 break;
208 }
209 }
210 index--;
211 index &= max_index_mask;
Jan-Bernd Themann2c694482007-10-01 16:33:18 +0200212 adder++;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200213 }
Jan-Bernd Themann2c694482007-10-01 16:33:18 +0200214
215 if (adder == 0)
216 return;
217
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200218 /* Ring doorbell */
Jan-Bernd Themann2c694482007-10-01 16:33:18 +0200219 ehea_update_rq1a(pr->qp, adder);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200220}
221
222static int ehea_init_fill_rq1(struct ehea_port_res *pr, int nr_rq1a)
223{
224 int ret = 0;
225 struct sk_buff **skb_arr_rq1 = pr->rq1_skba.arr;
226 struct net_device *dev = pr->port->netdev;
227 int i;
228
229 for (i = 0; i < pr->rq1_skba.len; i++) {
230 skb_arr_rq1[i] = netdev_alloc_skb(dev, EHEA_L_PKT_SIZE);
231 if (!skb_arr_rq1[i]) {
232 ehea_error("%s: no mem for skb/%d wqes filled",
233 dev->name, i);
234 ret = -ENOMEM;
235 goto out;
236 }
237 }
238 /* Ring doorbell */
239 ehea_update_rq1a(pr->qp, nr_rq1a);
240out:
241 return ret;
242}
243
244static int ehea_refill_rq_def(struct ehea_port_res *pr,
245 struct ehea_q_skb_arr *q_skba, int rq_nr,
246 int num_wqes, int wqe_type, int packet_size)
247{
248 struct net_device *dev = pr->port->netdev;
249 struct ehea_qp *qp = pr->qp;
250 struct sk_buff **skb_arr = q_skba->arr;
251 struct ehea_rwqe *rwqe;
252 int i, index, max_index_mask, fill_wqes;
Jan-Bernd Themann2c694482007-10-01 16:33:18 +0200253 int adder = 0;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200254 int ret = 0;
255
256 fill_wqes = q_skba->os_skbs + num_wqes;
Jan-Bernd Themann2c694482007-10-01 16:33:18 +0200257 q_skba->os_skbs = 0;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200258
Jan-Bernd Themann2c694482007-10-01 16:33:18 +0200259 if (unlikely(test_bit(__EHEA_STOP_XFER, &ehea_driver_flags))) {
260 q_skba->os_skbs = fill_wqes;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200261 return ret;
Jan-Bernd Themann2c694482007-10-01 16:33:18 +0200262 }
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200263
264 index = q_skba->index;
265 max_index_mask = q_skba->len - 1;
266 for (i = 0; i < fill_wqes; i++) {
Jan-Bernd Themann2c694482007-10-01 16:33:18 +0200267 u64 tmp_addr;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200268 struct sk_buff *skb = netdev_alloc_skb(dev, packet_size);
269 if (!skb) {
270 ehea_error("%s: no mem for skb/%d wqes filled",
Jan-Bernd Themann18604c52007-02-28 18:34:10 +0100271 pr->port->netdev->name, i);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200272 q_skba->os_skbs = fill_wqes - i;
273 ret = -ENOMEM;
274 break;
275 }
276 skb_reserve(skb, NET_IP_ALIGN);
277
278 skb_arr[index] = skb;
Jan-Bernd Themann2c694482007-10-01 16:33:18 +0200279 tmp_addr = ehea_map_vaddr(skb->data);
280 if (tmp_addr == -1) {
281 dev_kfree_skb(skb);
282 q_skba->os_skbs = fill_wqes - i;
283 ret = 0;
284 break;
285 }
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200286
287 rwqe = ehea_get_next_rwqe(qp, rq_nr);
288 rwqe->wr_id = EHEA_BMASK_SET(EHEA_WR_ID_TYPE, wqe_type)
Jan-Bernd Themannd1d25aa2007-07-02 13:00:46 +0200289 | EHEA_BMASK_SET(EHEA_WR_ID_INDEX, index);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200290 rwqe->sg_list[0].l_key = pr->recv_mr.lkey;
Jan-Bernd Themann2c694482007-10-01 16:33:18 +0200291 rwqe->sg_list[0].vaddr = tmp_addr;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200292 rwqe->sg_list[0].len = packet_size;
293 rwqe->data_segments = 1;
294
295 index++;
296 index &= max_index_mask;
Jan-Bernd Themann2c694482007-10-01 16:33:18 +0200297 adder++;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200298 }
Thomas Klein44c82152007-07-11 16:32:00 +0200299
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200300 q_skba->index = index;
Jan-Bernd Themann2c694482007-10-01 16:33:18 +0200301 if (adder == 0)
302 goto out;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200303
304 /* Ring doorbell */
305 iosync();
306 if (rq_nr == 2)
Jan-Bernd Themann2c694482007-10-01 16:33:18 +0200307 ehea_update_rq2a(pr->qp, adder);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200308 else
Jan-Bernd Themann2c694482007-10-01 16:33:18 +0200309 ehea_update_rq3a(pr->qp, adder);
Thomas Klein44c82152007-07-11 16:32:00 +0200310out:
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200311 return ret;
312}
313
314
315static int ehea_refill_rq2(struct ehea_port_res *pr, int nr_of_wqes)
316{
317 return ehea_refill_rq_def(pr, &pr->rq2_skba, 2,
318 nr_of_wqes, EHEA_RWQE2_TYPE,
319 EHEA_RQ2_PKT_SIZE + NET_IP_ALIGN);
320}
321
322
323static int ehea_refill_rq3(struct ehea_port_res *pr, int nr_of_wqes)
324{
325 return ehea_refill_rq_def(pr, &pr->rq3_skba, 3,
326 nr_of_wqes, EHEA_RWQE3_TYPE,
327 EHEA_MAX_PACKET_SIZE + NET_IP_ALIGN);
328}
329
330static inline int ehea_check_cqe(struct ehea_cqe *cqe, int *rq_num)
331{
332 *rq_num = (cqe->type & EHEA_CQE_TYPE_RQ) >> 5;
333 if ((cqe->status & EHEA_CQE_STAT_ERR_MASK) == 0)
334 return 0;
335 if (((cqe->status & EHEA_CQE_STAT_ERR_TCP) != 0) &&
336 (cqe->header_length == 0))
337 return 0;
338 return -EINVAL;
339}
340
341static inline void ehea_fill_skb(struct net_device *dev,
342 struct sk_buff *skb, struct ehea_cqe *cqe)
343{
344 int length = cqe->num_bytes_transfered - 4; /*remove CRC */
345
346 skb_put(skb, length);
347 skb->ip_summed = CHECKSUM_UNNECESSARY;
348 skb->protocol = eth_type_trans(skb, dev);
349}
350
351static inline struct sk_buff *get_skb_by_index(struct sk_buff **skb_array,
352 int arr_len,
353 struct ehea_cqe *cqe)
354{
355 int skb_index = EHEA_BMASK_GET(EHEA_WR_ID_INDEX, cqe->wr_id);
356 struct sk_buff *skb;
357 void *pref;
358 int x;
359
360 x = skb_index + 1;
361 x &= (arr_len - 1);
362
363 pref = skb_array[x];
364 prefetchw(pref);
365 prefetchw(pref + EHEA_CACHE_LINE);
366
367 pref = (skb_array[x]->data);
368 prefetch(pref);
369 prefetch(pref + EHEA_CACHE_LINE);
370 prefetch(pref + EHEA_CACHE_LINE * 2);
371 prefetch(pref + EHEA_CACHE_LINE * 3);
372 skb = skb_array[skb_index];
373 skb_array[skb_index] = NULL;
374 return skb;
375}
376
377static inline struct sk_buff *get_skb_by_index_ll(struct sk_buff **skb_array,
378 int arr_len, int wqe_index)
379{
380 struct sk_buff *skb;
381 void *pref;
382 int x;
383
384 x = wqe_index + 1;
385 x &= (arr_len - 1);
386
387 pref = skb_array[x];
388 prefetchw(pref);
389 prefetchw(pref + EHEA_CACHE_LINE);
390
391 pref = (skb_array[x]->data);
392 prefetchw(pref);
393 prefetchw(pref + EHEA_CACHE_LINE);
394
395 skb = skb_array[wqe_index];
396 skb_array[wqe_index] = NULL;
397 return skb;
398}
399
400static int ehea_treat_poll_error(struct ehea_port_res *pr, int rq,
401 struct ehea_cqe *cqe, int *processed_rq2,
402 int *processed_rq3)
403{
404 struct sk_buff *skb;
405
Jan-Bernd Themannacbddb52007-03-23 17:18:53 +0100406 if (cqe->status & EHEA_CQE_STAT_ERR_TCP)
407 pr->p_stats.err_tcp_cksum++;
408 if (cqe->status & EHEA_CQE_STAT_ERR_IP)
409 pr->p_stats.err_ip_cksum++;
410 if (cqe->status & EHEA_CQE_STAT_ERR_CRC)
411 pr->p_stats.err_frame_crc++;
412
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200413 if (netif_msg_rx_err(pr->port)) {
414 ehea_error("CQE Error for QP %d", pr->qp->init_attr.qp_nr);
415 ehea_dump(cqe, sizeof(*cqe), "CQE");
416 }
417
418 if (rq == 2) {
419 *processed_rq2 += 1;
420 skb = get_skb_by_index(pr->rq2_skba.arr, pr->rq2_skba.len, cqe);
421 dev_kfree_skb(skb);
422 } else if (rq == 3) {
423 *processed_rq3 += 1;
424 skb = get_skb_by_index(pr->rq3_skba.arr, pr->rq3_skba.len, cqe);
425 dev_kfree_skb(skb);
426 }
427
428 if (cqe->status & EHEA_CQE_STAT_FAT_ERR_MASK) {
429 ehea_error("Critical receive error. Resetting port.");
Jan-Bernd Themann3bf76b82007-10-08 16:01:33 +0200430 schedule_work(&pr->port->reset_task);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200431 return 1;
432 }
433
434 return 0;
435}
436
Jan-Bernd Themannd4dc4ec2007-09-25 16:16:34 -0700437static int get_skb_hdr(struct sk_buff *skb, void **iphdr,
438 void **tcph, u64 *hdr_flags, void *priv)
439{
440 struct ehea_cqe *cqe = priv;
441 unsigned int ip_len;
442 struct iphdr *iph;
443
444 /* non tcp/udp packets */
445 if (!cqe->header_length)
446 return -1;
447
448 /* non tcp packet */
449 skb_reset_network_header(skb);
450 iph = ip_hdr(skb);
451 if (iph->protocol != IPPROTO_TCP)
452 return -1;
453
454 ip_len = ip_hdrlen(skb);
455 skb_set_transport_header(skb, ip_len);
456 *tcph = tcp_hdr(skb);
457
458 /* check if ip header and tcp header are complete */
459 if (iph->tot_len < ip_len + tcp_hdrlen(skb))
460 return -1;
461
462 *hdr_flags = LRO_IPV4 | LRO_TCP;
463 *iphdr = iph;
464
465 return 0;
466}
467
468static void ehea_proc_skb(struct ehea_port_res *pr, struct ehea_cqe *cqe,
469 struct sk_buff *skb)
470{
471 int vlan_extracted = (cqe->status & EHEA_CQE_VLAN_TAG_XTRACT)
472 && pr->port->vgrp;
473
474 if (use_lro) {
475 if (vlan_extracted)
476 lro_vlan_hwaccel_receive_skb(&pr->lro_mgr, skb,
477 pr->port->vgrp,
478 cqe->vlan_tag,
479 cqe);
480 else
481 lro_receive_skb(&pr->lro_mgr, skb, cqe);
482 } else {
483 if (vlan_extracted)
484 vlan_hwaccel_receive_skb(skb, pr->port->vgrp,
485 cqe->vlan_tag);
486 else
487 netif_receive_skb(skb);
488 }
489}
490
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700491static int ehea_proc_rwqes(struct net_device *dev,
492 struct ehea_port_res *pr,
493 int budget)
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200494{
Jan-Bernd Themann18604c52007-02-28 18:34:10 +0100495 struct ehea_port *port = pr->port;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200496 struct ehea_qp *qp = pr->qp;
497 struct ehea_cqe *cqe;
498 struct sk_buff *skb;
499 struct sk_buff **skb_arr_rq1 = pr->rq1_skba.arr;
500 struct sk_buff **skb_arr_rq2 = pr->rq2_skba.arr;
501 struct sk_buff **skb_arr_rq3 = pr->rq3_skba.arr;
502 int skb_arr_rq1_len = pr->rq1_skba.len;
503 int skb_arr_rq2_len = pr->rq2_skba.len;
504 int skb_arr_rq3_len = pr->rq3_skba.len;
505 int processed, processed_rq1, processed_rq2, processed_rq3;
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700506 int wqe_index, last_wqe_index, rq, port_reset;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200507
508 processed = processed_rq1 = processed_rq2 = processed_rq3 = 0;
509 last_wqe_index = 0;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200510
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200511 cqe = ehea_poll_rq1(qp, &wqe_index);
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700512 while ((processed < budget) && cqe) {
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200513 ehea_inc_rq1(qp);
514 processed_rq1++;
515 processed++;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200516 if (netif_msg_rx_status(port))
517 ehea_dump(cqe, sizeof(*cqe), "CQE");
518
519 last_wqe_index = wqe_index;
520 rmb();
521 if (!ehea_check_cqe(cqe, &rq)) {
522 if (rq == 1) { /* LL RQ1 */
523 skb = get_skb_by_index_ll(skb_arr_rq1,
524 skb_arr_rq1_len,
525 wqe_index);
526 if (unlikely(!skb)) {
527 if (netif_msg_rx_err(port))
528 ehea_error("LL rq1: skb=NULL");
Jan-Bernd Themann18604c52007-02-28 18:34:10 +0100529
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700530 skb = netdev_alloc_skb(dev,
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200531 EHEA_L_PKT_SIZE);
532 if (!skb)
533 break;
534 }
Arnaldo Carvalho de Melo27d7ff42007-03-31 11:55:19 -0300535 skb_copy_to_linear_data(skb, ((char*)cqe) + 64,
Jan-Bernd Themannd1d25aa2007-07-02 13:00:46 +0200536 cqe->num_bytes_transfered - 4);
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700537 ehea_fill_skb(dev, skb, cqe);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200538 } else if (rq == 2) { /* RQ2 */
539 skb = get_skb_by_index(skb_arr_rq2,
540 skb_arr_rq2_len, cqe);
541 if (unlikely(!skb)) {
542 if (netif_msg_rx_err(port))
543 ehea_error("rq2: skb=NULL");
544 break;
545 }
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700546 ehea_fill_skb(dev, skb, cqe);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200547 processed_rq2++;
548 } else { /* RQ3 */
549 skb = get_skb_by_index(skb_arr_rq3,
550 skb_arr_rq3_len, cqe);
551 if (unlikely(!skb)) {
552 if (netif_msg_rx_err(port))
553 ehea_error("rq3: skb=NULL");
554 break;
555 }
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700556 ehea_fill_skb(dev, skb, cqe);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200557 processed_rq3++;
558 }
559
Jan-Bernd Themannd4dc4ec2007-09-25 16:16:34 -0700560 ehea_proc_skb(pr, cqe, skb);
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700561 dev->last_rx = jiffies;
Jan-Bernd Themann18604c52007-02-28 18:34:10 +0100562 } else {
Jan-Bernd Themannacbddb52007-03-23 17:18:53 +0100563 pr->p_stats.poll_receive_errors++;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200564 port_reset = ehea_treat_poll_error(pr, rq, cqe,
565 &processed_rq2,
566 &processed_rq3);
567 if (port_reset)
568 break;
569 }
570 cqe = ehea_poll_rq1(qp, &wqe_index);
571 }
Jan-Bernd Themannd4dc4ec2007-09-25 16:16:34 -0700572 if (use_lro)
573 lro_flush_all(&pr->lro_mgr);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200574
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200575 pr->rx_packets += processed;
576
577 ehea_refill_rq1(pr, last_wqe_index, processed_rq1);
578 ehea_refill_rq2(pr, processed_rq2);
579 ehea_refill_rq3(pr, processed_rq3);
580
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700581 return processed;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200582}
583
Jan-Bernd Themann18604c52007-02-28 18:34:10 +0100584static struct ehea_cqe *ehea_proc_cqes(struct ehea_port_res *pr, int my_quota)
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200585{
Jan-Bernd Themannacbddb52007-03-23 17:18:53 +0100586 struct sk_buff *skb;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200587 struct ehea_cq *send_cq = pr->send_cq;
588 struct ehea_cqe *cqe;
Jan-Bernd Themann18604c52007-02-28 18:34:10 +0100589 int quota = my_quota;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200590 int cqe_counter = 0;
591 int swqe_av = 0;
Jan-Bernd Themannacbddb52007-03-23 17:18:53 +0100592 int index;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200593 unsigned long flags;
594
Jan-Bernd Themann18604c52007-02-28 18:34:10 +0100595 cqe = ehea_poll_cq(send_cq);
596 while(cqe && (quota > 0)) {
597 ehea_inc_cq(send_cq);
598
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200599 cqe_counter++;
600 rmb();
601 if (cqe->status & EHEA_CQE_STAT_ERR_MASK) {
602 ehea_error("Send Completion Error: Resetting port");
603 if (netif_msg_tx_err(pr->port))
604 ehea_dump(cqe, sizeof(*cqe), "Send CQE");
Jan-Bernd Themann3bf76b82007-10-08 16:01:33 +0200605 schedule_work(&pr->port->reset_task);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200606 break;
607 }
608
609 if (netif_msg_tx_done(pr->port))
610 ehea_dump(cqe, sizeof(*cqe), "CQE");
611
612 if (likely(EHEA_BMASK_GET(EHEA_WR_ID_TYPE, cqe->wr_id)
Jan-Bernd Themannacbddb52007-03-23 17:18:53 +0100613 == EHEA_SWQE2_TYPE)) {
614
615 index = EHEA_BMASK_GET(EHEA_WR_ID_INDEX, cqe->wr_id);
616 skb = pr->sq_skba.arr[index];
617 dev_kfree_skb(skb);
618 pr->sq_skba.arr[index] = NULL;
619 }
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200620
621 swqe_av += EHEA_BMASK_GET(EHEA_WR_ID_REFILL, cqe->wr_id);
622 quota--;
Jan-Bernd Themann18604c52007-02-28 18:34:10 +0100623
624 cqe = ehea_poll_cq(send_cq);
625 };
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200626
627 ehea_update_feca(send_cq, cqe_counter);
628 atomic_add(swqe_av, &pr->swqe_avail);
629
630 spin_lock_irqsave(&pr->netif_queue, flags);
Jan-Bernd Themann18604c52007-02-28 18:34:10 +0100631
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200632 if (pr->queue_stopped && (atomic_read(&pr->swqe_avail)
633 >= pr->swqe_refill_th)) {
634 netif_wake_queue(pr->port->netdev);
635 pr->queue_stopped = 0;
636 }
637 spin_unlock_irqrestore(&pr->netif_queue, flags);
638
Jan-Bernd Themann18604c52007-02-28 18:34:10 +0100639 return cqe;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200640}
641
Jan-Bernd Themann18604c52007-02-28 18:34:10 +0100642#define EHEA_NAPI_POLL_NUM_BEFORE_IRQ 16
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700643#define EHEA_POLL_MAX_CQES 65535
Jan-Bernd Themann18604c52007-02-28 18:34:10 +0100644
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700645static int ehea_poll(struct napi_struct *napi, int budget)
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200646{
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700647 struct ehea_port_res *pr = container_of(napi, struct ehea_port_res, napi);
648 struct net_device *dev = pr->port->netdev;
Jan-Bernd Themann18604c52007-02-28 18:34:10 +0100649 struct ehea_cqe *cqe;
650 struct ehea_cqe *cqe_skb = NULL;
651 int force_irq, wqe_index;
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700652 int rx = 0;
Jan-Bernd Themann18604c52007-02-28 18:34:10 +0100653
654 force_irq = (pr->poll_counter > EHEA_NAPI_POLL_NUM_BEFORE_IRQ);
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700655 cqe_skb = ehea_proc_cqes(pr, EHEA_POLL_MAX_CQES);
Jan-Bernd Themann18604c52007-02-28 18:34:10 +0100656
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700657 if (!force_irq)
658 rx += ehea_proc_rwqes(dev, pr, budget - rx);
659
660 while ((rx != budget) || force_irq) {
Jan-Bernd Themann18604c52007-02-28 18:34:10 +0100661 pr->poll_counter = 0;
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700662 force_irq = 0;
663 netif_rx_complete(dev, napi);
Jan-Bernd Themann18604c52007-02-28 18:34:10 +0100664 ehea_reset_cq_ep(pr->recv_cq);
665 ehea_reset_cq_ep(pr->send_cq);
666 ehea_reset_cq_n1(pr->recv_cq);
667 ehea_reset_cq_n1(pr->send_cq);
668 cqe = ehea_poll_rq1(pr->qp, &wqe_index);
669 cqe_skb = ehea_poll_cq(pr->send_cq);
670
Jan-Bernd Themanne542aa62007-03-22 17:50:24 +0100671 if (!cqe && !cqe_skb)
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700672 return rx;
Jan-Bernd Themann18604c52007-02-28 18:34:10 +0100673
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700674 if (!netif_rx_reschedule(dev, napi))
675 return rx;
676
677 cqe_skb = ehea_proc_cqes(pr, EHEA_POLL_MAX_CQES);
678 rx += ehea_proc_rwqes(dev, pr, budget - rx);
Jan-Bernd Themann18604c52007-02-28 18:34:10 +0100679 }
Jan-Bernd Themanne542aa62007-03-22 17:50:24 +0100680
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700681 pr->poll_counter++;
682 return rx;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200683}
684
Jan-Bernd Themann8d22c972007-07-23 16:05:03 +0200685#ifdef CONFIG_NET_POLL_CONTROLLER
686static void ehea_netpoll(struct net_device *dev)
687{
688 struct ehea_port *port = netdev_priv(dev);
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700689 int i;
Jan-Bernd Themann8d22c972007-07-23 16:05:03 +0200690
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700691 for (i = 0; i < port->num_def_qps; i++)
692 netif_rx_schedule(dev, &port->port_res[i].napi);
Jan-Bernd Themann8d22c972007-07-23 16:05:03 +0200693}
694#endif
695
David Howells7d12e782006-10-05 14:55:46 +0100696static irqreturn_t ehea_recv_irq_handler(int irq, void *param)
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200697{
698 struct ehea_port_res *pr = param;
Jan-Bernd Themann18604c52007-02-28 18:34:10 +0100699
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700700 netif_rx_schedule(pr->port->netdev, &pr->napi);
Jan-Bernd Themann18604c52007-02-28 18:34:10 +0100701
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200702 return IRQ_HANDLED;
703}
704
David Howells7d12e782006-10-05 14:55:46 +0100705static irqreturn_t ehea_qp_aff_irq_handler(int irq, void *param)
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200706{
707 struct ehea_port *port = param;
708 struct ehea_eqe *eqe;
Jan-Bernd Themannd2db9ee2007-02-09 09:10:51 +0100709 struct ehea_qp *qp;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200710 u32 qp_token;
711
712 eqe = ehea_poll_eq(port->qp_eq);
Thomas Kleinbb3a6442007-01-22 12:54:50 +0100713
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200714 while (eqe) {
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200715 qp_token = EHEA_BMASK_GET(EHEA_EQE_QP_TOKEN, eqe->entry);
Thomas Kleinbb3a6442007-01-22 12:54:50 +0100716 ehea_error("QP aff_err: entry=0x%lx, token=0x%x",
717 eqe->entry, qp_token);
Jan-Bernd Themannd2db9ee2007-02-09 09:10:51 +0100718
719 qp = port->port_res[qp_token].qp;
720 ehea_error_data(port->adapter, qp->fw_handle);
Thomas Kleinbb3a6442007-01-22 12:54:50 +0100721 eqe = ehea_poll_eq(port->qp_eq);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200722 }
723
Jan-Bernd Themann3bf76b82007-10-08 16:01:33 +0200724 schedule_work(&port->reset_task);
Jan-Bernd Themannd2db9ee2007-02-09 09:10:51 +0100725
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200726 return IRQ_HANDLED;
727}
728
729static struct ehea_port *ehea_get_port(struct ehea_adapter *adapter,
730 int logical_port)
731{
732 int i;
733
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +0100734 for (i = 0; i < EHEA_MAX_PORTS; i++)
Thomas Klein41b69c72007-01-22 12:55:20 +0100735 if (adapter->port[i])
Jan-Bernd Themannd1d25aa2007-07-02 13:00:46 +0200736 if (adapter->port[i]->logical_port_id == logical_port)
Thomas Klein41b69c72007-01-22 12:55:20 +0100737 return adapter->port[i];
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200738 return NULL;
739}
740
741int ehea_sense_port_attr(struct ehea_port *port)
742{
743 int ret;
744 u64 hret;
745 struct hcp_ehea_port_cb0 *cb0;
746
Thomas Kleina1d261c2006-11-03 17:48:23 +0100747 cb0 = kzalloc(PAGE_SIZE, GFP_ATOMIC); /* May be called via */
748 if (!cb0) { /* ehea_neq_tasklet() */
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200749 ehea_error("no mem for cb0");
750 ret = -ENOMEM;
751 goto out;
752 }
753
754 hret = ehea_h_query_ehea_port(port->adapter->handle,
755 port->logical_port_id, H_PORT_CB0,
756 EHEA_BMASK_SET(H_PORT_CB0_ALL, 0xFFFF),
757 cb0);
758 if (hret != H_SUCCESS) {
759 ret = -EIO;
760 goto out_free;
761 }
762
763 /* MAC address */
764 port->mac_addr = cb0->port_mac_addr << 16;
765
766 if (!is_valid_ether_addr((u8*)&port->mac_addr)) {
767 ret = -EADDRNOTAVAIL;
768 goto out_free;
769 }
770
771 /* Port speed */
772 switch (cb0->port_speed) {
773 case H_SPEED_10M_H:
774 port->port_speed = EHEA_SPEED_10M;
775 port->full_duplex = 0;
776 break;
777 case H_SPEED_10M_F:
778 port->port_speed = EHEA_SPEED_10M;
779 port->full_duplex = 1;
780 break;
781 case H_SPEED_100M_H:
782 port->port_speed = EHEA_SPEED_100M;
783 port->full_duplex = 0;
784 break;
785 case H_SPEED_100M_F:
786 port->port_speed = EHEA_SPEED_100M;
787 port->full_duplex = 1;
788 break;
789 case H_SPEED_1G_F:
790 port->port_speed = EHEA_SPEED_1G;
791 port->full_duplex = 1;
792 break;
793 case H_SPEED_10G_F:
794 port->port_speed = EHEA_SPEED_10G;
795 port->full_duplex = 1;
796 break;
797 default:
798 port->port_speed = 0;
799 port->full_duplex = 0;
800 break;
801 }
802
Thomas Kleine919b592007-01-22 12:53:20 +0100803 port->autoneg = 1;
Jan-Bernd Themann18604c52007-02-28 18:34:10 +0100804 port->num_mcs = cb0->num_default_qps;
Thomas Kleine919b592007-01-22 12:53:20 +0100805
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200806 /* Number of default QPs */
Jan-Bernd Themann18604c52007-02-28 18:34:10 +0100807 if (use_mcs)
808 port->num_def_qps = cb0->num_default_qps;
809 else
810 port->num_def_qps = 1;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200811
812 if (!port->num_def_qps) {
813 ret = -EINVAL;
814 goto out_free;
815 }
816
Jan-Bernd Themann18604c52007-02-28 18:34:10 +0100817 port->num_tx_qps = num_tx_qps;
818
819 if (port->num_def_qps >= port->num_tx_qps)
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200820 port->num_add_tx_qps = 0;
821 else
Jan-Bernd Themann18604c52007-02-28 18:34:10 +0100822 port->num_add_tx_qps = port->num_tx_qps - port->num_def_qps;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200823
824 ret = 0;
825out_free:
826 if (ret || netif_msg_probe(port))
827 ehea_dump(cb0, sizeof(*cb0), "ehea_sense_port_attr");
828 kfree(cb0);
829out:
830 return ret;
831}
832
833int ehea_set_portspeed(struct ehea_port *port, u32 port_speed)
834{
835 struct hcp_ehea_port_cb4 *cb4;
836 u64 hret;
837 int ret = 0;
838
Thomas Kleina1d261c2006-11-03 17:48:23 +0100839 cb4 = kzalloc(PAGE_SIZE, GFP_KERNEL);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200840 if (!cb4) {
841 ehea_error("no mem for cb4");
842 ret = -ENOMEM;
843 goto out;
844 }
845
846 cb4->port_speed = port_speed;
847
848 netif_carrier_off(port->netdev);
849
850 hret = ehea_h_modify_ehea_port(port->adapter->handle,
851 port->logical_port_id,
852 H_PORT_CB4, H_PORT_CB4_SPEED, cb4);
853 if (hret == H_SUCCESS) {
854 port->autoneg = port_speed == EHEA_SPEED_AUTONEG ? 1 : 0;
855
856 hret = ehea_h_query_ehea_port(port->adapter->handle,
857 port->logical_port_id,
858 H_PORT_CB4, H_PORT_CB4_SPEED,
859 cb4);
860 if (hret == H_SUCCESS) {
861 switch (cb4->port_speed) {
862 case H_SPEED_10M_H:
863 port->port_speed = EHEA_SPEED_10M;
864 port->full_duplex = 0;
865 break;
866 case H_SPEED_10M_F:
867 port->port_speed = EHEA_SPEED_10M;
868 port->full_duplex = 1;
869 break;
870 case H_SPEED_100M_H:
871 port->port_speed = EHEA_SPEED_100M;
872 port->full_duplex = 0;
873 break;
874 case H_SPEED_100M_F:
875 port->port_speed = EHEA_SPEED_100M;
876 port->full_duplex = 1;
877 break;
878 case H_SPEED_1G_F:
879 port->port_speed = EHEA_SPEED_1G;
880 port->full_duplex = 1;
881 break;
882 case H_SPEED_10G_F:
883 port->port_speed = EHEA_SPEED_10G;
884 port->full_duplex = 1;
885 break;
886 default:
887 port->port_speed = 0;
888 port->full_duplex = 0;
889 break;
890 }
891 } else {
892 ehea_error("Failed sensing port speed");
893 ret = -EIO;
894 }
895 } else {
896 if (hret == H_AUTHORITY) {
Thomas Klein7674a582007-01-22 12:54:20 +0100897 ehea_info("Hypervisor denied setting port speed");
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200898 ret = -EPERM;
899 } else {
900 ret = -EIO;
901 ehea_error("Failed setting port speed");
902 }
903 }
Jan-Bernd Themann8759cf72007-09-07 12:30:17 +0200904 if (!prop_carrier_state || (port->phy_link == EHEA_PHY_LINK_UP))
905 netif_carrier_on(port->netdev);
906
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200907 kfree(cb4);
908out:
909 return ret;
910}
911
912static void ehea_parse_eqe(struct ehea_adapter *adapter, u64 eqe)
913{
914 int ret;
915 u8 ec;
916 u8 portnum;
917 struct ehea_port *port;
918
919 ec = EHEA_BMASK_GET(NEQE_EVENT_CODE, eqe);
920 portnum = EHEA_BMASK_GET(NEQE_PORTNUM, eqe);
921 port = ehea_get_port(adapter, portnum);
922
923 switch (ec) {
924 case EHEA_EC_PORTSTATE_CHG: /* port state change */
925
926 if (!port) {
927 ehea_error("unknown portnum %x", portnum);
928 break;
929 }
930
931 if (EHEA_BMASK_GET(NEQE_PORT_UP, eqe)) {
932 if (!netif_carrier_ok(port->netdev)) {
Jan-Bernd Themann1e1675c2006-10-25 13:11:42 +0200933 ret = ehea_sense_port_attr(port);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200934 if (ret) {
935 ehea_error("failed resensing port "
936 "attributes");
937 break;
938 }
939
940 if (netif_msg_link(port))
941 ehea_info("%s: Logical port up: %dMbps "
942 "%s Duplex",
943 port->netdev->name,
944 port->port_speed,
945 port->full_duplex ==
946 1 ? "Full" : "Half");
947
948 netif_carrier_on(port->netdev);
949 netif_wake_queue(port->netdev);
950 }
951 } else
952 if (netif_carrier_ok(port->netdev)) {
953 if (netif_msg_link(port))
954 ehea_info("%s: Logical port down",
955 port->netdev->name);
956 netif_carrier_off(port->netdev);
957 netif_stop_queue(port->netdev);
958 }
959
960 if (EHEA_BMASK_GET(NEQE_EXTSWITCH_PORT_UP, eqe)) {
Jan-Bernd Themann8759cf72007-09-07 12:30:17 +0200961 port->phy_link = EHEA_PHY_LINK_UP;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200962 if (netif_msg_link(port))
963 ehea_info("%s: Physical port up",
964 port->netdev->name);
Jan-Bernd Themann8759cf72007-09-07 12:30:17 +0200965 if (prop_carrier_state)
966 netif_carrier_on(port->netdev);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200967 } else {
Jan-Bernd Themann8759cf72007-09-07 12:30:17 +0200968 port->phy_link = EHEA_PHY_LINK_DOWN;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200969 if (netif_msg_link(port))
970 ehea_info("%s: Physical port down",
971 port->netdev->name);
Jan-Bernd Themann8759cf72007-09-07 12:30:17 +0200972 if (prop_carrier_state)
973 netif_carrier_off(port->netdev);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200974 }
975
976 if (EHEA_BMASK_GET(NEQE_EXTSWITCH_PRIMARY, eqe))
977 ehea_info("External switch port is primary port");
978 else
979 ehea_info("External switch port is backup port");
980
981 break;
982 case EHEA_EC_ADAPTER_MALFUNC:
983 ehea_error("Adapter malfunction");
984 break;
985 case EHEA_EC_PORT_MALFUNC:
986 ehea_info("Port malfunction: Device: %s", port->netdev->name);
987 netif_carrier_off(port->netdev);
988 netif_stop_queue(port->netdev);
989 break;
990 default:
Jan-Bernd Themannbff0a552006-10-05 16:53:14 +0200991 ehea_error("unknown event code %x, eqe=0x%lX", ec, eqe);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +0200992 break;
993 }
994}
995
996static void ehea_neq_tasklet(unsigned long data)
997{
998 struct ehea_adapter *adapter = (struct ehea_adapter*)data;
999 struct ehea_eqe *eqe;
1000 u64 event_mask;
1001
1002 eqe = ehea_poll_eq(adapter->neq);
1003 ehea_debug("eqe=%p", eqe);
1004
1005 while (eqe) {
1006 ehea_debug("*eqe=%lx", eqe->entry);
1007 ehea_parse_eqe(adapter, eqe->entry);
1008 eqe = ehea_poll_eq(adapter->neq);
1009 ehea_debug("next eqe=%p", eqe);
1010 }
1011
1012 event_mask = EHEA_BMASK_SET(NELR_PORTSTATE_CHG, 1)
1013 | EHEA_BMASK_SET(NELR_ADAPTER_MALFUNC, 1)
1014 | EHEA_BMASK_SET(NELR_PORT_MALFUNC, 1);
1015
1016 ehea_h_reset_events(adapter->handle,
1017 adapter->neq->fw_handle, event_mask);
1018}
1019
David Howells7d12e782006-10-05 14:55:46 +01001020static irqreturn_t ehea_interrupt_neq(int irq, void *param)
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001021{
1022 struct ehea_adapter *adapter = param;
1023 tasklet_hi_schedule(&adapter->neq_tasklet);
1024 return IRQ_HANDLED;
1025}
1026
1027
1028static int ehea_fill_port_res(struct ehea_port_res *pr)
1029{
1030 int ret;
1031 struct ehea_qp_init_attr *init_attr = &pr->qp->init_attr;
1032
1033 ret = ehea_init_fill_rq1(pr, init_attr->act_nr_rwqes_rq1
1034 - init_attr->act_nr_rwqes_rq2
1035 - init_attr->act_nr_rwqes_rq3 - 1);
1036
1037 ret |= ehea_refill_rq2(pr, init_attr->act_nr_rwqes_rq2 - 1);
1038
1039 ret |= ehea_refill_rq3(pr, init_attr->act_nr_rwqes_rq3 - 1);
1040
1041 return ret;
1042}
1043
1044static int ehea_reg_interrupts(struct net_device *dev)
1045{
1046 struct ehea_port *port = netdev_priv(dev);
1047 struct ehea_port_res *pr;
1048 int i, ret;
1049
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001050
1051 snprintf(port->int_aff_name, EHEA_IRQ_NAME_SIZE - 1, "%s-aff",
1052 dev->name);
1053
Joachim Fenkes6b08f3a2007-09-26 19:45:51 +10001054 ret = ibmebus_request_irq(port->qp_eq->attr.ist1,
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001055 ehea_qp_aff_irq_handler,
Thomas Gleixner38515e92007-02-14 00:33:16 -08001056 IRQF_DISABLED, port->int_aff_name, port);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001057 if (ret) {
1058 ehea_error("failed registering irq for qp_aff_irq_handler:"
1059 "ist=%X", port->qp_eq->attr.ist1);
1060 goto out_free_qpeq;
1061 }
1062
1063 if (netif_msg_ifup(port))
1064 ehea_info("irq_handle 0x%X for function qp_aff_irq_handler "
1065 "registered", port->qp_eq->attr.ist1);
1066
Jan-Bernd Themann18604c52007-02-28 18:34:10 +01001067
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001068 for (i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++) {
1069 pr = &port->port_res[i];
1070 snprintf(pr->int_send_name, EHEA_IRQ_NAME_SIZE - 1,
Jan-Bernd Themann18604c52007-02-28 18:34:10 +01001071 "%s-queue%d", dev->name, i);
Joachim Fenkes6b08f3a2007-09-26 19:45:51 +10001072 ret = ibmebus_request_irq(pr->eq->attr.ist1,
Jan-Bernd Themann18604c52007-02-28 18:34:10 +01001073 ehea_recv_irq_handler,
Thomas Gleixner38515e92007-02-14 00:33:16 -08001074 IRQF_DISABLED, pr->int_send_name,
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001075 pr);
1076 if (ret) {
Jan-Bernd Themann18604c52007-02-28 18:34:10 +01001077 ehea_error("failed registering irq for ehea_queue "
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001078 "port_res_nr:%d, ist=%X", i,
Jan-Bernd Themann18604c52007-02-28 18:34:10 +01001079 pr->eq->attr.ist1);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001080 goto out_free_req;
1081 }
1082 if (netif_msg_ifup(port))
Jan-Bernd Themann18604c52007-02-28 18:34:10 +01001083 ehea_info("irq_handle 0x%X for function ehea_queue_int "
1084 "%d registered", pr->eq->attr.ist1, i);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001085 }
1086out:
1087 return ret;
1088
Jan-Bernd Themann18604c52007-02-28 18:34:10 +01001089
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001090out_free_req:
1091 while (--i >= 0) {
Jan-Bernd Themann18604c52007-02-28 18:34:10 +01001092 u32 ist = port->port_res[i].eq->attr.ist1;
Joachim Fenkes6b08f3a2007-09-26 19:45:51 +10001093 ibmebus_free_irq(ist, &port->port_res[i]);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001094 }
Jan-Bernd Themann18604c52007-02-28 18:34:10 +01001095
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001096out_free_qpeq:
Joachim Fenkes6b08f3a2007-09-26 19:45:51 +10001097 ibmebus_free_irq(port->qp_eq->attr.ist1, port);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001098 i = port->num_def_qps;
Jan-Bernd Themann18604c52007-02-28 18:34:10 +01001099
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001100 goto out;
Jan-Bernd Themann18604c52007-02-28 18:34:10 +01001101
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001102}
1103
1104static void ehea_free_interrupts(struct net_device *dev)
1105{
1106 struct ehea_port *port = netdev_priv(dev);
1107 struct ehea_port_res *pr;
1108 int i;
1109
1110 /* send */
Jan-Bernd Themann18604c52007-02-28 18:34:10 +01001111
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001112 for (i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++) {
1113 pr = &port->port_res[i];
Joachim Fenkes6b08f3a2007-09-26 19:45:51 +10001114 ibmebus_free_irq(pr->eq->attr.ist1, pr);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001115 if (netif_msg_intr(port))
1116 ehea_info("free send irq for res %d with handle 0x%X",
Jan-Bernd Themann18604c52007-02-28 18:34:10 +01001117 i, pr->eq->attr.ist1);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001118 }
1119
1120 /* associated events */
Joachim Fenkes6b08f3a2007-09-26 19:45:51 +10001121 ibmebus_free_irq(port->qp_eq->attr.ist1, port);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001122 if (netif_msg_intr(port))
1123 ehea_info("associated event interrupt for handle 0x%X freed",
1124 port->qp_eq->attr.ist1);
1125}
1126
1127static int ehea_configure_port(struct ehea_port *port)
1128{
1129 int ret, i;
1130 u64 hret, mask;
1131 struct hcp_ehea_port_cb0 *cb0;
1132
1133 ret = -ENOMEM;
Thomas Kleina1d261c2006-11-03 17:48:23 +01001134 cb0 = kzalloc(PAGE_SIZE, GFP_KERNEL);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001135 if (!cb0)
1136 goto out;
1137
1138 cb0->port_rc = EHEA_BMASK_SET(PXLY_RC_VALID, 1)
1139 | EHEA_BMASK_SET(PXLY_RC_IP_CHKSUM, 1)
1140 | EHEA_BMASK_SET(PXLY_RC_TCP_UDP_CHKSUM, 1)
1141 | EHEA_BMASK_SET(PXLY_RC_VLAN_XTRACT, 1)
1142 | EHEA_BMASK_SET(PXLY_RC_VLAN_TAG_FILTER,
1143 PXLY_RC_VLAN_FILTER)
1144 | EHEA_BMASK_SET(PXLY_RC_JUMBO_FRAME, 1);
1145
Jan-Bernd Themann18604c52007-02-28 18:34:10 +01001146 for (i = 0; i < port->num_mcs; i++)
1147 if (use_mcs)
1148 cb0->default_qpn_arr[i] =
1149 port->port_res[i].qp->init_attr.qp_nr;
1150 else
1151 cb0->default_qpn_arr[i] =
1152 port->port_res[0].qp->init_attr.qp_nr;
Jan-Bernd Themanne542aa62007-03-22 17:50:24 +01001153
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001154 if (netif_msg_ifup(port))
1155 ehea_dump(cb0, sizeof(*cb0), "ehea_configure_port");
1156
1157 mask = EHEA_BMASK_SET(H_PORT_CB0_PRC, 1)
1158 | EHEA_BMASK_SET(H_PORT_CB0_DEFQPNARRAY, 1);
1159
1160 hret = ehea_h_modify_ehea_port(port->adapter->handle,
1161 port->logical_port_id,
1162 H_PORT_CB0, mask, cb0);
1163 ret = -EIO;
1164 if (hret != H_SUCCESS)
1165 goto out_free;
1166
1167 ret = 0;
1168
1169out_free:
1170 kfree(cb0);
1171out:
1172 return ret;
1173}
1174
Jan-Bernd Themanne542aa62007-03-22 17:50:24 +01001175int ehea_gen_smrs(struct ehea_port_res *pr)
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001176{
Jan-Bernd Themanne542aa62007-03-22 17:50:24 +01001177 int ret;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001178 struct ehea_adapter *adapter = pr->port->adapter;
1179
Jan-Bernd Themanne542aa62007-03-22 17:50:24 +01001180 ret = ehea_gen_smr(adapter, &adapter->mr, &pr->send_mr);
1181 if (ret)
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001182 goto out;
1183
Jan-Bernd Themanne542aa62007-03-22 17:50:24 +01001184 ret = ehea_gen_smr(adapter, &adapter->mr, &pr->recv_mr);
1185 if (ret)
1186 goto out_free;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001187
1188 return 0;
1189
Jan-Bernd Themanne542aa62007-03-22 17:50:24 +01001190out_free:
1191 ehea_rem_mr(&pr->send_mr);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001192out:
Jan-Bernd Themanne542aa62007-03-22 17:50:24 +01001193 ehea_error("Generating SMRS failed\n");
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001194 return -EIO;
1195}
1196
Jan-Bernd Themanne542aa62007-03-22 17:50:24 +01001197int ehea_rem_smrs(struct ehea_port_res *pr)
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001198{
Jan-Bernd Themanne542aa62007-03-22 17:50:24 +01001199 if ((ehea_rem_mr(&pr->send_mr))
1200 || (ehea_rem_mr(&pr->recv_mr)))
1201 return -EIO;
1202 else
1203 return 0;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001204}
1205
1206static int ehea_init_q_skba(struct ehea_q_skb_arr *q_skba, int max_q_entries)
1207{
1208 int arr_size = sizeof(void*) * max_q_entries;
1209
1210 q_skba->arr = vmalloc(arr_size);
1211 if (!q_skba->arr)
1212 return -ENOMEM;
1213
1214 memset(q_skba->arr, 0, arr_size);
1215
1216 q_skba->len = max_q_entries;
1217 q_skba->index = 0;
1218 q_skba->os_skbs = 0;
1219
1220 return 0;
1221}
1222
1223static int ehea_init_port_res(struct ehea_port *port, struct ehea_port_res *pr,
1224 struct port_res_cfg *pr_cfg, int queue_token)
1225{
1226 struct ehea_adapter *adapter = port->adapter;
1227 enum ehea_eq_type eq_type = EHEA_EQ;
1228 struct ehea_qp_init_attr *init_attr = NULL;
1229 int ret = -EIO;
1230
1231 memset(pr, 0, sizeof(struct ehea_port_res));
1232
1233 pr->port = port;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001234 spin_lock_init(&pr->xmit_lock);
1235 spin_lock_init(&pr->netif_queue);
1236
Jan-Bernd Themann18604c52007-02-28 18:34:10 +01001237 pr->eq = ehea_create_eq(adapter, eq_type, EHEA_MAX_ENTRIES_EQ, 0);
1238 if (!pr->eq) {
1239 ehea_error("create_eq failed (eq)");
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001240 goto out_free;
1241 }
1242
1243 pr->recv_cq = ehea_create_cq(adapter, pr_cfg->max_entries_rcq,
Jan-Bernd Themann18604c52007-02-28 18:34:10 +01001244 pr->eq->fw_handle,
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001245 port->logical_port_id);
1246 if (!pr->recv_cq) {
1247 ehea_error("create_cq failed (cq_recv)");
1248 goto out_free;
1249 }
1250
1251 pr->send_cq = ehea_create_cq(adapter, pr_cfg->max_entries_scq,
Jan-Bernd Themann18604c52007-02-28 18:34:10 +01001252 pr->eq->fw_handle,
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001253 port->logical_port_id);
1254 if (!pr->send_cq) {
1255 ehea_error("create_cq failed (cq_send)");
1256 goto out_free;
1257 }
1258
1259 if (netif_msg_ifup(port))
1260 ehea_info("Send CQ: act_nr_cqes=%d, Recv CQ: act_nr_cqes=%d",
1261 pr->send_cq->attr.act_nr_of_cqes,
1262 pr->recv_cq->attr.act_nr_of_cqes);
1263
1264 init_attr = kzalloc(sizeof(*init_attr), GFP_KERNEL);
1265 if (!init_attr) {
1266 ret = -ENOMEM;
1267 ehea_error("no mem for ehea_qp_init_attr");
1268 goto out_free;
1269 }
1270
1271 init_attr->low_lat_rq1 = 1;
1272 init_attr->signalingtype = 1; /* generate CQE if specified in WQE */
1273 init_attr->rq_count = 3;
1274 init_attr->qp_token = queue_token;
1275 init_attr->max_nr_send_wqes = pr_cfg->max_entries_sq;
1276 init_attr->max_nr_rwqes_rq1 = pr_cfg->max_entries_rq1;
1277 init_attr->max_nr_rwqes_rq2 = pr_cfg->max_entries_rq2;
1278 init_attr->max_nr_rwqes_rq3 = pr_cfg->max_entries_rq3;
1279 init_attr->wqe_size_enc_sq = EHEA_SG_SQ;
1280 init_attr->wqe_size_enc_rq1 = EHEA_SG_RQ1;
1281 init_attr->wqe_size_enc_rq2 = EHEA_SG_RQ2;
1282 init_attr->wqe_size_enc_rq3 = EHEA_SG_RQ3;
1283 init_attr->rq2_threshold = EHEA_RQ2_THRESHOLD;
1284 init_attr->rq3_threshold = EHEA_RQ3_THRESHOLD;
1285 init_attr->port_nr = port->logical_port_id;
1286 init_attr->send_cq_handle = pr->send_cq->fw_handle;
1287 init_attr->recv_cq_handle = pr->recv_cq->fw_handle;
1288 init_attr->aff_eq_handle = port->qp_eq->fw_handle;
1289
1290 pr->qp = ehea_create_qp(adapter, adapter->pd, init_attr);
1291 if (!pr->qp) {
1292 ehea_error("create_qp failed");
1293 ret = -EIO;
1294 goto out_free;
1295 }
1296
1297 if (netif_msg_ifup(port))
1298 ehea_info("QP: qp_nr=%d\n act_nr_snd_wqe=%d\n nr_rwqe_rq1=%d\n "
1299 "nr_rwqe_rq2=%d\n nr_rwqe_rq3=%d", init_attr->qp_nr,
1300 init_attr->act_nr_send_wqes,
1301 init_attr->act_nr_rwqes_rq1,
1302 init_attr->act_nr_rwqes_rq2,
1303 init_attr->act_nr_rwqes_rq3);
1304
1305 ret = ehea_init_q_skba(&pr->sq_skba, init_attr->act_nr_send_wqes + 1);
1306 ret |= ehea_init_q_skba(&pr->rq1_skba, init_attr->act_nr_rwqes_rq1 + 1);
1307 ret |= ehea_init_q_skba(&pr->rq2_skba, init_attr->act_nr_rwqes_rq2 + 1);
1308 ret |= ehea_init_q_skba(&pr->rq3_skba, init_attr->act_nr_rwqes_rq3 + 1);
1309 if (ret)
1310 goto out_free;
1311
1312 pr->swqe_refill_th = init_attr->act_nr_send_wqes / 10;
1313 if (ehea_gen_smrs(pr) != 0) {
1314 ret = -EIO;
1315 goto out_free;
1316 }
Jan-Bernd Themann18604c52007-02-28 18:34:10 +01001317
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001318 atomic_set(&pr->swqe_avail, init_attr->act_nr_send_wqes - 1);
1319
1320 kfree(init_attr);
Jan-Bernd Themann18604c52007-02-28 18:34:10 +01001321
Stephen Hemmingerbea33482007-10-03 16:41:36 -07001322 netif_napi_add(pr->port->netdev, &pr->napi, ehea_poll, 64);
Jan-Bernd Themann18604c52007-02-28 18:34:10 +01001323
Jan-Bernd Themannd4dc4ec2007-09-25 16:16:34 -07001324 pr->lro_mgr.max_aggr = pr->port->lro_max_aggr;
1325 pr->lro_mgr.max_desc = MAX_LRO_DESCRIPTORS;
1326 pr->lro_mgr.lro_arr = pr->lro_desc;
1327 pr->lro_mgr.get_skb_header = get_skb_hdr;
1328 pr->lro_mgr.features = LRO_F_NAPI | LRO_F_EXTRACT_VLAN_ID;
1329 pr->lro_mgr.dev = port->netdev;
1330 pr->lro_mgr.ip_summed = CHECKSUM_UNNECESSARY;
1331 pr->lro_mgr.ip_summed_aggr = CHECKSUM_UNNECESSARY;
1332
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001333 ret = 0;
1334 goto out;
1335
1336out_free:
1337 kfree(init_attr);
1338 vfree(pr->sq_skba.arr);
1339 vfree(pr->rq1_skba.arr);
1340 vfree(pr->rq2_skba.arr);
1341 vfree(pr->rq3_skba.arr);
1342 ehea_destroy_qp(pr->qp);
1343 ehea_destroy_cq(pr->send_cq);
1344 ehea_destroy_cq(pr->recv_cq);
Jan-Bernd Themann18604c52007-02-28 18:34:10 +01001345 ehea_destroy_eq(pr->eq);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001346out:
1347 return ret;
1348}
1349
1350static int ehea_clean_portres(struct ehea_port *port, struct ehea_port_res *pr)
1351{
1352 int ret, i;
1353
1354 ret = ehea_destroy_qp(pr->qp);
1355
1356 if (!ret) {
1357 ehea_destroy_cq(pr->send_cq);
1358 ehea_destroy_cq(pr->recv_cq);
Jan-Bernd Themann18604c52007-02-28 18:34:10 +01001359 ehea_destroy_eq(pr->eq);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001360
1361 for (i = 0; i < pr->rq1_skba.len; i++)
1362 if (pr->rq1_skba.arr[i])
1363 dev_kfree_skb(pr->rq1_skba.arr[i]);
1364
1365 for (i = 0; i < pr->rq2_skba.len; i++)
1366 if (pr->rq2_skba.arr[i])
1367 dev_kfree_skb(pr->rq2_skba.arr[i]);
1368
1369 for (i = 0; i < pr->rq3_skba.len; i++)
1370 if (pr->rq3_skba.arr[i])
1371 dev_kfree_skb(pr->rq3_skba.arr[i]);
1372
1373 for (i = 0; i < pr->sq_skba.len; i++)
1374 if (pr->sq_skba.arr[i])
1375 dev_kfree_skb(pr->sq_skba.arr[i]);
1376
1377 vfree(pr->rq1_skba.arr);
1378 vfree(pr->rq2_skba.arr);
1379 vfree(pr->rq3_skba.arr);
1380 vfree(pr->sq_skba.arr);
1381 ret = ehea_rem_smrs(pr);
1382 }
1383 return ret;
1384}
1385
1386/*
1387 * The write_* functions store information in swqe which is used by
1388 * the hardware to calculate the ip/tcp/udp checksum
1389 */
1390
1391static inline void write_ip_start_end(struct ehea_swqe *swqe,
1392 const struct sk_buff *skb)
1393{
Arnaldo Carvalho de Meloeddc9ec2007-04-20 22:47:35 -07001394 swqe->ip_start = skb_network_offset(skb);
Arnaldo Carvalho de Meloc9bdd4b2007-03-12 20:09:15 -03001395 swqe->ip_end = (u8)(swqe->ip_start + ip_hdrlen(skb) - 1);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001396}
1397
1398static inline void write_tcp_offset_end(struct ehea_swqe *swqe,
1399 const struct sk_buff *skb)
1400{
1401 swqe->tcp_offset =
1402 (u8)(swqe->ip_end + 1 + offsetof(struct tcphdr, check));
1403
1404 swqe->tcp_end = (u16)skb->len - 1;
1405}
1406
1407static inline void write_udp_offset_end(struct ehea_swqe *swqe,
1408 const struct sk_buff *skb)
1409{
1410 swqe->tcp_offset =
1411 (u8)(swqe->ip_end + 1 + offsetof(struct udphdr, check));
1412
1413 swqe->tcp_end = (u16)skb->len - 1;
1414}
1415
1416
1417static void write_swqe2_TSO(struct sk_buff *skb,
1418 struct ehea_swqe *swqe, u32 lkey)
1419{
1420 struct ehea_vsgentry *sg1entry = &swqe->u.immdata_desc.sg_entry;
1421 u8 *imm_data = &swqe->u.immdata_desc.immediate_data[0];
1422 int skb_data_size = skb->len - skb->data_len;
1423 int headersize;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001424
1425 /* Packet is TCP with TSO enabled */
1426 swqe->tx_control |= EHEA_SWQE_TSO;
1427 swqe->mss = skb_shinfo(skb)->gso_size;
1428 /* copy only eth/ip/tcp headers to immediate data and
1429 * the rest of skb->data to sg1entry
1430 */
Arnaldo Carvalho de Meloab6a5bb2007-03-18 17:43:48 -07001431 headersize = ETH_HLEN + ip_hdrlen(skb) + tcp_hdrlen(skb);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001432
1433 skb_data_size = skb->len - skb->data_len;
1434
1435 if (skb_data_size >= headersize) {
1436 /* copy immediate data */
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03001437 skb_copy_from_linear_data(skb, imm_data, headersize);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001438 swqe->immediate_data_length = headersize;
1439
1440 if (skb_data_size > headersize) {
1441 /* set sg1entry data */
1442 sg1entry->l_key = lkey;
1443 sg1entry->len = skb_data_size - headersize;
Thomas Klein44a5b3d2007-08-06 13:55:44 +02001444 sg1entry->vaddr =
1445 ehea_map_vaddr(skb->data + headersize);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001446 swqe->descriptors++;
1447 }
1448 } else
1449 ehea_error("cannot handle fragmented headers");
1450}
1451
1452static void write_swqe2_nonTSO(struct sk_buff *skb,
1453 struct ehea_swqe *swqe, u32 lkey)
1454{
1455 int skb_data_size = skb->len - skb->data_len;
1456 u8 *imm_data = &swqe->u.immdata_desc.immediate_data[0];
1457 struct ehea_vsgentry *sg1entry = &swqe->u.immdata_desc.sg_entry;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001458
1459 /* Packet is any nonTSO type
1460 *
1461 * Copy as much as possible skb->data to immediate data and
1462 * the rest to sg1entry
1463 */
1464 if (skb_data_size >= SWQE2_MAX_IMM) {
1465 /* copy immediate data */
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03001466 skb_copy_from_linear_data(skb, imm_data, SWQE2_MAX_IMM);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001467
1468 swqe->immediate_data_length = SWQE2_MAX_IMM;
1469
1470 if (skb_data_size > SWQE2_MAX_IMM) {
1471 /* copy sg1entry data */
1472 sg1entry->l_key = lkey;
1473 sg1entry->len = skb_data_size - SWQE2_MAX_IMM;
Thomas Klein44a5b3d2007-08-06 13:55:44 +02001474 sg1entry->vaddr =
1475 ehea_map_vaddr(skb->data + SWQE2_MAX_IMM);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001476 swqe->descriptors++;
1477 }
1478 } else {
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03001479 skb_copy_from_linear_data(skb, imm_data, skb_data_size);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001480 swqe->immediate_data_length = skb_data_size;
1481 }
1482}
1483
1484static inline void write_swqe2_data(struct sk_buff *skb, struct net_device *dev,
1485 struct ehea_swqe *swqe, u32 lkey)
1486{
1487 struct ehea_vsgentry *sg_list, *sg1entry, *sgentry;
1488 skb_frag_t *frag;
1489 int nfrags, sg1entry_contains_frag_data, i;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001490
1491 nfrags = skb_shinfo(skb)->nr_frags;
1492 sg1entry = &swqe->u.immdata_desc.sg_entry;
1493 sg_list = (struct ehea_vsgentry*)&swqe->u.immdata_desc.sg_list;
1494 swqe->descriptors = 0;
1495 sg1entry_contains_frag_data = 0;
1496
1497 if ((dev->features & NETIF_F_TSO) && skb_shinfo(skb)->gso_size)
1498 write_swqe2_TSO(skb, swqe, lkey);
1499 else
1500 write_swqe2_nonTSO(skb, swqe, lkey);
1501
1502 /* write descriptors */
1503 if (nfrags > 0) {
1504 if (swqe->descriptors == 0) {
1505 /* sg1entry not yet used */
1506 frag = &skb_shinfo(skb)->frags[0];
1507
1508 /* copy sg1entry data */
1509 sg1entry->l_key = lkey;
1510 sg1entry->len = frag->size;
Thomas Klein44a5b3d2007-08-06 13:55:44 +02001511 sg1entry->vaddr =
1512 ehea_map_vaddr(page_address(frag->page)
1513 + frag->page_offset);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001514 swqe->descriptors++;
1515 sg1entry_contains_frag_data = 1;
1516 }
1517
1518 for (i = sg1entry_contains_frag_data; i < nfrags; i++) {
1519
1520 frag = &skb_shinfo(skb)->frags[i];
1521 sgentry = &sg_list[i - sg1entry_contains_frag_data];
1522
1523 sgentry->l_key = lkey;
1524 sgentry->len = frag->size;
Thomas Klein44a5b3d2007-08-06 13:55:44 +02001525 sgentry->vaddr =
1526 ehea_map_vaddr(page_address(frag->page)
1527 + frag->page_offset);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001528 swqe->descriptors++;
1529 }
1530 }
1531}
1532
1533static int ehea_broadcast_reg_helper(struct ehea_port *port, u32 hcallid)
1534{
1535 int ret = 0;
1536 u64 hret;
1537 u8 reg_type;
1538
1539 /* De/Register untagged packets */
1540 reg_type = EHEA_BCMC_BROADCAST | EHEA_BCMC_UNTAGGED;
1541 hret = ehea_h_reg_dereg_bcmc(port->adapter->handle,
1542 port->logical_port_id,
1543 reg_type, port->mac_addr, 0, hcallid);
1544 if (hret != H_SUCCESS) {
Thomas Kleinf9e29222007-07-18 17:34:09 +02001545 ehea_error("%sregistering bc address failed (tagged)",
1546 hcallid == H_REG_BCMC ? "" : "de");
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001547 ret = -EIO;
1548 goto out_herr;
1549 }
1550
1551 /* De/Register VLAN packets */
1552 reg_type = EHEA_BCMC_BROADCAST | EHEA_BCMC_VLANID_ALL;
1553 hret = ehea_h_reg_dereg_bcmc(port->adapter->handle,
1554 port->logical_port_id,
1555 reg_type, port->mac_addr, 0, hcallid);
1556 if (hret != H_SUCCESS) {
Thomas Kleinf9e29222007-07-18 17:34:09 +02001557 ehea_error("%sregistering bc address failed (vlan)",
1558 hcallid == H_REG_BCMC ? "" : "de");
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001559 ret = -EIO;
1560 }
1561out_herr:
1562 return ret;
1563}
1564
1565static int ehea_set_mac_addr(struct net_device *dev, void *sa)
1566{
1567 struct ehea_port *port = netdev_priv(dev);
1568 struct sockaddr *mac_addr = sa;
1569 struct hcp_ehea_port_cb0 *cb0;
1570 int ret;
1571 u64 hret;
1572
1573 if (!is_valid_ether_addr(mac_addr->sa_data)) {
1574 ret = -EADDRNOTAVAIL;
1575 goto out;
1576 }
1577
Thomas Kleina1d261c2006-11-03 17:48:23 +01001578 cb0 = kzalloc(PAGE_SIZE, GFP_KERNEL);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001579 if (!cb0) {
1580 ehea_error("no mem for cb0");
1581 ret = -ENOMEM;
1582 goto out;
1583 }
1584
1585 memcpy(&(cb0->port_mac_addr), &(mac_addr->sa_data[0]), ETH_ALEN);
1586
1587 cb0->port_mac_addr = cb0->port_mac_addr >> 16;
1588
1589 hret = ehea_h_modify_ehea_port(port->adapter->handle,
1590 port->logical_port_id, H_PORT_CB0,
1591 EHEA_BMASK_SET(H_PORT_CB0_MAC, 1), cb0);
1592 if (hret != H_SUCCESS) {
1593 ret = -EIO;
1594 goto out_free;
1595 }
1596
1597 memcpy(dev->dev_addr, mac_addr->sa_data, dev->addr_len);
1598
1599 /* Deregister old MAC in pHYP */
1600 ret = ehea_broadcast_reg_helper(port, H_DEREG_BCMC);
1601 if (ret)
1602 goto out_free;
1603
1604 port->mac_addr = cb0->port_mac_addr << 16;
1605
1606 /* Register new MAC in pHYP */
1607 ret = ehea_broadcast_reg_helper(port, H_REG_BCMC);
1608 if (ret)
1609 goto out_free;
1610
1611 ret = 0;
1612out_free:
1613 kfree(cb0);
1614out:
1615 return ret;
1616}
1617
1618static void ehea_promiscuous_error(u64 hret, int enable)
1619{
Thomas Klein7674a582007-01-22 12:54:20 +01001620 if (hret == H_AUTHORITY)
1621 ehea_info("Hypervisor denied %sabling promiscuous mode",
1622 enable == 1 ? "en" : "dis");
1623 else
1624 ehea_error("failed %sabling promiscuous mode",
1625 enable == 1 ? "en" : "dis");
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001626}
1627
1628static void ehea_promiscuous(struct net_device *dev, int enable)
1629{
1630 struct ehea_port *port = netdev_priv(dev);
1631 struct hcp_ehea_port_cb7 *cb7;
1632 u64 hret;
1633
1634 if ((enable && port->promisc) || (!enable && !port->promisc))
1635 return;
1636
Thomas Kleina1d261c2006-11-03 17:48:23 +01001637 cb7 = kzalloc(PAGE_SIZE, GFP_ATOMIC);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001638 if (!cb7) {
1639 ehea_error("no mem for cb7");
1640 goto out;
1641 }
1642
1643 /* Modify Pxs_DUCQPN in CB7 */
1644 cb7->def_uc_qpn = enable == 1 ? port->port_res[0].qp->fw_handle : 0;
1645
1646 hret = ehea_h_modify_ehea_port(port->adapter->handle,
1647 port->logical_port_id,
1648 H_PORT_CB7, H_PORT_CB7_DUCQPN, cb7);
1649 if (hret) {
1650 ehea_promiscuous_error(hret, enable);
1651 goto out;
1652 }
1653
1654 port->promisc = enable;
1655out:
1656 kfree(cb7);
1657 return;
1658}
1659
1660static u64 ehea_multicast_reg_helper(struct ehea_port *port, u64 mc_mac_addr,
1661 u32 hcallid)
1662{
1663 u64 hret;
1664 u8 reg_type;
1665
1666 reg_type = EHEA_BCMC_SCOPE_ALL | EHEA_BCMC_MULTICAST
1667 | EHEA_BCMC_UNTAGGED;
1668
1669 hret = ehea_h_reg_dereg_bcmc(port->adapter->handle,
1670 port->logical_port_id,
1671 reg_type, mc_mac_addr, 0, hcallid);
1672 if (hret)
1673 goto out;
1674
1675 reg_type = EHEA_BCMC_SCOPE_ALL | EHEA_BCMC_MULTICAST
1676 | EHEA_BCMC_VLANID_ALL;
1677
1678 hret = ehea_h_reg_dereg_bcmc(port->adapter->handle,
1679 port->logical_port_id,
1680 reg_type, mc_mac_addr, 0, hcallid);
1681out:
1682 return hret;
1683}
1684
1685static int ehea_drop_multicast_list(struct net_device *dev)
1686{
1687 struct ehea_port *port = netdev_priv(dev);
1688 struct ehea_mc_list *mc_entry = port->mc_list;
1689 struct list_head *pos;
1690 struct list_head *temp;
1691 int ret = 0;
1692 u64 hret;
1693
1694 list_for_each_safe(pos, temp, &(port->mc_list->list)) {
1695 mc_entry = list_entry(pos, struct ehea_mc_list, list);
1696
1697 hret = ehea_multicast_reg_helper(port, mc_entry->macaddr,
1698 H_DEREG_BCMC);
1699 if (hret) {
1700 ehea_error("failed deregistering mcast MAC");
1701 ret = -EIO;
1702 }
1703
1704 list_del(pos);
1705 kfree(mc_entry);
1706 }
1707 return ret;
1708}
1709
1710static void ehea_allmulti(struct net_device *dev, int enable)
1711{
1712 struct ehea_port *port = netdev_priv(dev);
1713 u64 hret;
1714
1715 if (!port->allmulti) {
1716 if (enable) {
1717 /* Enable ALLMULTI */
1718 ehea_drop_multicast_list(dev);
1719 hret = ehea_multicast_reg_helper(port, 0, H_REG_BCMC);
1720 if (!hret)
1721 port->allmulti = 1;
1722 else
1723 ehea_error("failed enabling IFF_ALLMULTI");
1724 }
1725 } else
1726 if (!enable) {
1727 /* Disable ALLMULTI */
1728 hret = ehea_multicast_reg_helper(port, 0, H_DEREG_BCMC);
1729 if (!hret)
1730 port->allmulti = 0;
1731 else
1732 ehea_error("failed disabling IFF_ALLMULTI");
1733 }
1734}
1735
1736static void ehea_add_multicast_entry(struct ehea_port* port, u8* mc_mac_addr)
1737{
1738 struct ehea_mc_list *ehea_mcl_entry;
1739 u64 hret;
1740
Jan-Bernd Themann1e1675c2006-10-25 13:11:42 +02001741 ehea_mcl_entry = kzalloc(sizeof(*ehea_mcl_entry), GFP_ATOMIC);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001742 if (!ehea_mcl_entry) {
1743 ehea_error("no mem for mcl_entry");
1744 return;
1745 }
1746
1747 INIT_LIST_HEAD(&ehea_mcl_entry->list);
1748
1749 memcpy(&ehea_mcl_entry->macaddr, mc_mac_addr, ETH_ALEN);
1750
1751 hret = ehea_multicast_reg_helper(port, ehea_mcl_entry->macaddr,
1752 H_REG_BCMC);
1753 if (!hret)
1754 list_add(&ehea_mcl_entry->list, &port->mc_list->list);
1755 else {
1756 ehea_error("failed registering mcast MAC");
1757 kfree(ehea_mcl_entry);
1758 }
1759}
1760
1761static void ehea_set_multicast_list(struct net_device *dev)
1762{
1763 struct ehea_port *port = netdev_priv(dev);
1764 struct dev_mc_list *k_mcl_entry;
1765 int ret, i;
1766
1767 if (dev->flags & IFF_PROMISC) {
1768 ehea_promiscuous(dev, 1);
1769 return;
1770 }
1771 ehea_promiscuous(dev, 0);
1772
1773 if (dev->flags & IFF_ALLMULTI) {
1774 ehea_allmulti(dev, 1);
1775 return;
1776 }
1777 ehea_allmulti(dev, 0);
1778
1779 if (dev->mc_count) {
1780 ret = ehea_drop_multicast_list(dev);
1781 if (ret) {
1782 /* Dropping the current multicast list failed.
1783 * Enabling ALL_MULTI is the best we can do.
1784 */
1785 ehea_allmulti(dev, 1);
1786 }
1787
1788 if (dev->mc_count > port->adapter->max_mc_mac) {
1789 ehea_info("Mcast registration limit reached (0x%lx). "
1790 "Use ALLMULTI!",
1791 port->adapter->max_mc_mac);
1792 goto out;
1793 }
1794
1795 for (i = 0, k_mcl_entry = dev->mc_list;
1796 i < dev->mc_count;
1797 i++, k_mcl_entry = k_mcl_entry->next) {
1798 ehea_add_multicast_entry(port, k_mcl_entry->dmi_addr);
1799 }
1800 }
1801out:
1802 return;
1803}
1804
1805static int ehea_change_mtu(struct net_device *dev, int new_mtu)
1806{
1807 if ((new_mtu < 68) || (new_mtu > EHEA_MAX_PACKET_SIZE))
1808 return -EINVAL;
1809 dev->mtu = new_mtu;
1810 return 0;
1811}
1812
1813static void ehea_xmit2(struct sk_buff *skb, struct net_device *dev,
1814 struct ehea_swqe *swqe, u32 lkey)
1815{
1816 if (skb->protocol == htons(ETH_P_IP)) {
Arnaldo Carvalho de Meloeddc9ec2007-04-20 22:47:35 -07001817 const struct iphdr *iph = ip_hdr(skb);
Jan-Bernd Themannd1d25aa2007-07-02 13:00:46 +02001818
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001819 /* IPv4 */
1820 swqe->tx_control |= EHEA_SWQE_CRC
1821 | EHEA_SWQE_IP_CHECKSUM
1822 | EHEA_SWQE_TCP_CHECKSUM
1823 | EHEA_SWQE_IMM_DATA_PRESENT
1824 | EHEA_SWQE_DESCRIPTORS_PRESENT;
1825
1826 write_ip_start_end(swqe, skb);
1827
Arnaldo Carvalho de Meloeddc9ec2007-04-20 22:47:35 -07001828 if (iph->protocol == IPPROTO_UDP) {
Jan-Bernd Themannd1d25aa2007-07-02 13:00:46 +02001829 if ((iph->frag_off & IP_MF)
1830 || (iph->frag_off & IP_OFFSET))
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001831 /* IP fragment, so don't change cs */
1832 swqe->tx_control &= ~EHEA_SWQE_TCP_CHECKSUM;
1833 else
1834 write_udp_offset_end(swqe, skb);
Arnaldo Carvalho de Meloeddc9ec2007-04-20 22:47:35 -07001835 } else if (iph->protocol == IPPROTO_TCP) {
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001836 write_tcp_offset_end(swqe, skb);
1837 }
1838
1839 /* icmp (big data) and ip segmentation packets (all other ip
1840 packets) do not require any special handling */
1841
1842 } else {
1843 /* Other Ethernet Protocol */
1844 swqe->tx_control |= EHEA_SWQE_CRC
1845 | EHEA_SWQE_IMM_DATA_PRESENT
1846 | EHEA_SWQE_DESCRIPTORS_PRESENT;
1847 }
1848
1849 write_swqe2_data(skb, dev, swqe, lkey);
1850}
1851
1852static void ehea_xmit3(struct sk_buff *skb, struct net_device *dev,
1853 struct ehea_swqe *swqe)
1854{
1855 int nfrags = skb_shinfo(skb)->nr_frags;
1856 u8 *imm_data = &swqe->u.immdata_nodesc.immediate_data[0];
1857 skb_frag_t *frag;
1858 int i;
1859
1860 if (skb->protocol == htons(ETH_P_IP)) {
Arnaldo Carvalho de Meloeddc9ec2007-04-20 22:47:35 -07001861 const struct iphdr *iph = ip_hdr(skb);
Jan-Bernd Themannd1d25aa2007-07-02 13:00:46 +02001862
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001863 /* IPv4 */
1864 write_ip_start_end(swqe, skb);
1865
Arnaldo Carvalho de Meloeddc9ec2007-04-20 22:47:35 -07001866 if (iph->protocol == IPPROTO_TCP) {
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001867 swqe->tx_control |= EHEA_SWQE_CRC
1868 | EHEA_SWQE_IP_CHECKSUM
1869 | EHEA_SWQE_TCP_CHECKSUM
1870 | EHEA_SWQE_IMM_DATA_PRESENT;
1871
1872 write_tcp_offset_end(swqe, skb);
1873
Arnaldo Carvalho de Meloeddc9ec2007-04-20 22:47:35 -07001874 } else if (iph->protocol == IPPROTO_UDP) {
Jan-Bernd Themannd1d25aa2007-07-02 13:00:46 +02001875 if ((iph->frag_off & IP_MF)
1876 || (iph->frag_off & IP_OFFSET))
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001877 /* IP fragment, so don't change cs */
1878 swqe->tx_control |= EHEA_SWQE_CRC
1879 | EHEA_SWQE_IMM_DATA_PRESENT;
1880 else {
1881 swqe->tx_control |= EHEA_SWQE_CRC
1882 | EHEA_SWQE_IP_CHECKSUM
1883 | EHEA_SWQE_TCP_CHECKSUM
1884 | EHEA_SWQE_IMM_DATA_PRESENT;
1885
1886 write_udp_offset_end(swqe, skb);
1887 }
1888 } else {
1889 /* icmp (big data) and
1890 ip segmentation packets (all other ip packets) */
1891 swqe->tx_control |= EHEA_SWQE_CRC
1892 | EHEA_SWQE_IP_CHECKSUM
1893 | EHEA_SWQE_IMM_DATA_PRESENT;
1894 }
1895 } else {
1896 /* Other Ethernet Protocol */
1897 swqe->tx_control |= EHEA_SWQE_CRC | EHEA_SWQE_IMM_DATA_PRESENT;
1898 }
1899 /* copy (immediate) data */
1900 if (nfrags == 0) {
1901 /* data is in a single piece */
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03001902 skb_copy_from_linear_data(skb, imm_data, skb->len);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001903 } else {
1904 /* first copy data from the skb->data buffer ... */
Arnaldo Carvalho de Melod626f622007-03-27 18:55:52 -03001905 skb_copy_from_linear_data(skb, imm_data,
1906 skb->len - skb->data_len);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001907 imm_data += skb->len - skb->data_len;
1908
1909 /* ... then copy data from the fragments */
1910 for (i = 0; i < nfrags; i++) {
1911 frag = &skb_shinfo(skb)->frags[i];
1912 memcpy(imm_data,
1913 page_address(frag->page) + frag->page_offset,
1914 frag->size);
1915 imm_data += frag->size;
1916 }
1917 }
1918 swqe->immediate_data_length = skb->len;
1919 dev_kfree_skb(skb);
1920}
1921
Jan-Bernd Themann18604c52007-02-28 18:34:10 +01001922static inline int ehea_hash_skb(struct sk_buff *skb, int num_qps)
1923{
1924 struct tcphdr *tcp;
1925 u32 tmp;
1926
1927 if ((skb->protocol == htons(ETH_P_IP)) &&
Thomas Klein88ca2d02007-05-02 16:07:05 +02001928 (ip_hdr(skb)->protocol == IPPROTO_TCP)) {
1929 tcp = (struct tcphdr*)(skb_network_header(skb) + (ip_hdr(skb)->ihl * 4));
Jan-Bernd Themann18604c52007-02-28 18:34:10 +01001930 tmp = (tcp->source + (tcp->dest << 16)) % 31;
Thomas Klein88ca2d02007-05-02 16:07:05 +02001931 tmp += ip_hdr(skb)->daddr % 31;
Jan-Bernd Themann18604c52007-02-28 18:34:10 +01001932 return tmp % num_qps;
1933 }
1934 else
1935 return 0;
1936}
1937
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001938static int ehea_start_xmit(struct sk_buff *skb, struct net_device *dev)
1939{
1940 struct ehea_port *port = netdev_priv(dev);
1941 struct ehea_swqe *swqe;
1942 unsigned long flags;
1943 u32 lkey;
1944 int swqe_index;
Jan-Bernd Themann18604c52007-02-28 18:34:10 +01001945 struct ehea_port_res *pr;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001946
Jan-Bernd Themann18604c52007-02-28 18:34:10 +01001947 pr = &port->port_res[ehea_hash_skb(skb, port->num_tx_qps)];
1948
Jan-Bernd Themann18604c52007-02-28 18:34:10 +01001949 if (!spin_trylock(&pr->xmit_lock))
1950 return NETDEV_TX_BUSY;
1951
1952 if (pr->queue_stopped) {
1953 spin_unlock(&pr->xmit_lock);
1954 return NETDEV_TX_BUSY;
1955 }
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001956
1957 swqe = ehea_get_swqe(pr->qp, &swqe_index);
1958 memset(swqe, 0, SWQE_HEADER_SIZE);
1959 atomic_dec(&pr->swqe_avail);
1960
1961 if (skb->len <= SWQE3_MAX_IMM) {
1962 u32 sig_iv = port->sig_comp_iv;
1963 u32 swqe_num = pr->swqe_id_counter;
1964 ehea_xmit3(skb, dev, swqe);
1965 swqe->wr_id = EHEA_BMASK_SET(EHEA_WR_ID_TYPE, EHEA_SWQE3_TYPE)
1966 | EHEA_BMASK_SET(EHEA_WR_ID_COUNT, swqe_num);
1967 if (pr->swqe_ll_count >= (sig_iv - 1)) {
1968 swqe->wr_id |= EHEA_BMASK_SET(EHEA_WR_ID_REFILL,
1969 sig_iv);
1970 swqe->tx_control |= EHEA_SWQE_SIGNALLED_COMPLETION;
1971 pr->swqe_ll_count = 0;
1972 } else
1973 pr->swqe_ll_count += 1;
1974 } else {
1975 swqe->wr_id =
1976 EHEA_BMASK_SET(EHEA_WR_ID_TYPE, EHEA_SWQE2_TYPE)
1977 | EHEA_BMASK_SET(EHEA_WR_ID_COUNT, pr->swqe_id_counter)
Jan-Bernd Themannacbddb52007-03-23 17:18:53 +01001978 | EHEA_BMASK_SET(EHEA_WR_ID_REFILL, 1)
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001979 | EHEA_BMASK_SET(EHEA_WR_ID_INDEX, pr->sq_skba.index);
1980 pr->sq_skba.arr[pr->sq_skba.index] = skb;
1981
1982 pr->sq_skba.index++;
1983 pr->sq_skba.index &= (pr->sq_skba.len - 1);
1984
1985 lkey = pr->send_mr.lkey;
1986 ehea_xmit2(skb, dev, swqe, lkey);
Jan-Bernd Themannacbddb52007-03-23 17:18:53 +01001987 swqe->tx_control |= EHEA_SWQE_SIGNALLED_COMPLETION;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001988 }
1989 pr->swqe_id_counter += 1;
1990
1991 if (port->vgrp && vlan_tx_tag_present(skb)) {
1992 swqe->tx_control |= EHEA_SWQE_VLAN_INSERT;
1993 swqe->vlan_tag = vlan_tx_tag_get(skb);
1994 }
1995
1996 if (netif_msg_tx_queued(port)) {
1997 ehea_info("post swqe on QP %d", pr->qp->init_attr.qp_nr);
Jan-Bernd Themannbff0a552006-10-05 16:53:14 +02001998 ehea_dump(swqe, 512, "swqe");
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02001999 }
2000
Jan-Bernd Themann2c694482007-10-01 16:33:18 +02002001 if (unlikely(test_bit(__EHEA_STOP_XFER, &ehea_driver_flags))) {
2002 netif_stop_queue(dev);
2003 swqe->tx_control |= EHEA_SWQE_PURGE;
2004 }
Thomas Klein44c82152007-07-11 16:32:00 +02002005
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002006 ehea_post_swqe(pr->qp, swqe);
Thomas Klein7393b872007-11-21 17:37:58 +01002007 pr->tx_packets++;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002008
2009 if (unlikely(atomic_read(&pr->swqe_avail) <= 1)) {
2010 spin_lock_irqsave(&pr->netif_queue, flags);
2011 if (unlikely(atomic_read(&pr->swqe_avail) <= 1)) {
Jan-Bernd Themannacbddb52007-03-23 17:18:53 +01002012 pr->p_stats.queue_stopped++;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002013 netif_stop_queue(dev);
2014 pr->queue_stopped = 1;
2015 }
2016 spin_unlock_irqrestore(&pr->netif_queue, flags);
2017 }
2018 dev->trans_start = jiffies;
2019 spin_unlock(&pr->xmit_lock);
Jan-Bernd Themann2c694482007-10-01 16:33:18 +02002020
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002021 return NETDEV_TX_OK;
2022}
2023
2024static void ehea_vlan_rx_register(struct net_device *dev,
2025 struct vlan_group *grp)
2026{
2027 struct ehea_port *port = netdev_priv(dev);
2028 struct ehea_adapter *adapter = port->adapter;
2029 struct hcp_ehea_port_cb1 *cb1;
2030 u64 hret;
2031
2032 port->vgrp = grp;
2033
Thomas Kleina1d261c2006-11-03 17:48:23 +01002034 cb1 = kzalloc(PAGE_SIZE, GFP_KERNEL);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002035 if (!cb1) {
2036 ehea_error("no mem for cb1");
2037 goto out;
2038 }
2039
Thomas Kleindec590c2007-06-06 20:53:16 +02002040 memset(cb1->vlan_filter, 0, sizeof(cb1->vlan_filter));
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002041
2042 hret = ehea_h_modify_ehea_port(adapter->handle, port->logical_port_id,
2043 H_PORT_CB1, H_PORT_CB1_ALL, cb1);
2044 if (hret != H_SUCCESS)
2045 ehea_error("modify_ehea_port failed");
2046
2047 kfree(cb1);
2048out:
2049 return;
2050}
2051
2052static void ehea_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
2053{
2054 struct ehea_port *port = netdev_priv(dev);
2055 struct ehea_adapter *adapter = port->adapter;
2056 struct hcp_ehea_port_cb1 *cb1;
2057 int index;
2058 u64 hret;
2059
Thomas Kleina1d261c2006-11-03 17:48:23 +01002060 cb1 = kzalloc(PAGE_SIZE, GFP_KERNEL);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002061 if (!cb1) {
2062 ehea_error("no mem for cb1");
2063 goto out;
2064 }
2065
2066 hret = ehea_h_query_ehea_port(adapter->handle, port->logical_port_id,
2067 H_PORT_CB1, H_PORT_CB1_ALL, cb1);
2068 if (hret != H_SUCCESS) {
2069 ehea_error("query_ehea_port failed");
2070 goto out;
2071 }
2072
2073 index = (vid / 64);
Thomas Kleindec590c2007-06-06 20:53:16 +02002074 cb1->vlan_filter[index] |= ((u64)(0x8000000000000000 >> (vid & 0x3F)));
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002075
2076 hret = ehea_h_modify_ehea_port(adapter->handle, port->logical_port_id,
2077 H_PORT_CB1, H_PORT_CB1_ALL, cb1);
2078 if (hret != H_SUCCESS)
2079 ehea_error("modify_ehea_port failed");
2080out:
2081 kfree(cb1);
2082 return;
2083}
2084
2085static void ehea_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
2086{
2087 struct ehea_port *port = netdev_priv(dev);
2088 struct ehea_adapter *adapter = port->adapter;
2089 struct hcp_ehea_port_cb1 *cb1;
2090 int index;
2091 u64 hret;
2092
Dan Aloni5c15bde2007-03-02 20:44:51 -08002093 vlan_group_set_device(port->vgrp, vid, NULL);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002094
Thomas Kleina1d261c2006-11-03 17:48:23 +01002095 cb1 = kzalloc(PAGE_SIZE, GFP_KERNEL);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002096 if (!cb1) {
2097 ehea_error("no mem for cb1");
2098 goto out;
2099 }
2100
2101 hret = ehea_h_query_ehea_port(adapter->handle, port->logical_port_id,
2102 H_PORT_CB1, H_PORT_CB1_ALL, cb1);
2103 if (hret != H_SUCCESS) {
2104 ehea_error("query_ehea_port failed");
2105 goto out;
2106 }
2107
2108 index = (vid / 64);
Thomas Kleindec590c2007-06-06 20:53:16 +02002109 cb1->vlan_filter[index] &= ~((u64)(0x8000000000000000 >> (vid & 0x3F)));
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002110
2111 hret = ehea_h_modify_ehea_port(adapter->handle, port->logical_port_id,
2112 H_PORT_CB1, H_PORT_CB1_ALL, cb1);
2113 if (hret != H_SUCCESS)
2114 ehea_error("modify_ehea_port failed");
2115out:
2116 kfree(cb1);
2117 return;
2118}
2119
2120int ehea_activate_qp(struct ehea_adapter *adapter, struct ehea_qp *qp)
2121{
2122 int ret = -EIO;
2123 u64 hret;
2124 u16 dummy16 = 0;
2125 u64 dummy64 = 0;
2126 struct hcp_modify_qp_cb0* cb0;
2127
Thomas Kleina1d261c2006-11-03 17:48:23 +01002128 cb0 = kzalloc(PAGE_SIZE, GFP_KERNEL);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002129 if (!cb0) {
2130 ret = -ENOMEM;
2131 goto out;
2132 }
2133
2134 hret = ehea_h_query_ehea_qp(adapter->handle, 0, qp->fw_handle,
2135 EHEA_BMASK_SET(H_QPCB0_ALL, 0xFFFF), cb0);
2136 if (hret != H_SUCCESS) {
2137 ehea_error("query_ehea_qp failed (1)");
2138 goto out;
2139 }
2140
2141 cb0->qp_ctl_reg = H_QP_CR_STATE_INITIALIZED;
2142 hret = ehea_h_modify_ehea_qp(adapter->handle, 0, qp->fw_handle,
2143 EHEA_BMASK_SET(H_QPCB0_QP_CTL_REG, 1), cb0,
2144 &dummy64, &dummy64, &dummy16, &dummy16);
2145 if (hret != H_SUCCESS) {
2146 ehea_error("modify_ehea_qp failed (1)");
2147 goto out;
2148 }
2149
2150 hret = ehea_h_query_ehea_qp(adapter->handle, 0, qp->fw_handle,
2151 EHEA_BMASK_SET(H_QPCB0_ALL, 0xFFFF), cb0);
2152 if (hret != H_SUCCESS) {
2153 ehea_error("query_ehea_qp failed (2)");
2154 goto out;
2155 }
2156
2157 cb0->qp_ctl_reg = H_QP_CR_ENABLED | H_QP_CR_STATE_INITIALIZED;
2158 hret = ehea_h_modify_ehea_qp(adapter->handle, 0, qp->fw_handle,
2159 EHEA_BMASK_SET(H_QPCB0_QP_CTL_REG, 1), cb0,
2160 &dummy64, &dummy64, &dummy16, &dummy16);
2161 if (hret != H_SUCCESS) {
2162 ehea_error("modify_ehea_qp failed (2)");
2163 goto out;
2164 }
2165
2166 hret = ehea_h_query_ehea_qp(adapter->handle, 0, qp->fw_handle,
2167 EHEA_BMASK_SET(H_QPCB0_ALL, 0xFFFF), cb0);
2168 if (hret != H_SUCCESS) {
2169 ehea_error("query_ehea_qp failed (3)");
2170 goto out;
2171 }
2172
2173 cb0->qp_ctl_reg = H_QP_CR_ENABLED | H_QP_CR_STATE_RDY2SND;
2174 hret = ehea_h_modify_ehea_qp(adapter->handle, 0, qp->fw_handle,
2175 EHEA_BMASK_SET(H_QPCB0_QP_CTL_REG, 1), cb0,
2176 &dummy64, &dummy64, &dummy16, &dummy16);
2177 if (hret != H_SUCCESS) {
2178 ehea_error("modify_ehea_qp failed (3)");
2179 goto out;
2180 }
2181
2182 hret = ehea_h_query_ehea_qp(adapter->handle, 0, qp->fw_handle,
2183 EHEA_BMASK_SET(H_QPCB0_ALL, 0xFFFF), cb0);
2184 if (hret != H_SUCCESS) {
2185 ehea_error("query_ehea_qp failed (4)");
2186 goto out;
2187 }
2188
2189 ret = 0;
2190out:
2191 kfree(cb0);
2192 return ret;
2193}
2194
2195static int ehea_port_res_setup(struct ehea_port *port, int def_qps,
2196 int add_tx_qps)
2197{
2198 int ret, i;
2199 struct port_res_cfg pr_cfg, pr_cfg_small_rx;
2200 enum ehea_eq_type eq_type = EHEA_EQ;
2201
2202 port->qp_eq = ehea_create_eq(port->adapter, eq_type,
2203 EHEA_MAX_ENTRIES_EQ, 1);
2204 if (!port->qp_eq) {
2205 ret = -EINVAL;
2206 ehea_error("ehea_create_eq failed (qp_eq)");
2207 goto out_kill_eq;
2208 }
2209
2210 pr_cfg.max_entries_rcq = rq1_entries + rq2_entries + rq3_entries;
Jan-Bernd Themann18604c52007-02-28 18:34:10 +01002211 pr_cfg.max_entries_scq = sq_entries * 2;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002212 pr_cfg.max_entries_sq = sq_entries;
2213 pr_cfg.max_entries_rq1 = rq1_entries;
2214 pr_cfg.max_entries_rq2 = rq2_entries;
2215 pr_cfg.max_entries_rq3 = rq3_entries;
2216
2217 pr_cfg_small_rx.max_entries_rcq = 1;
2218 pr_cfg_small_rx.max_entries_scq = sq_entries;
2219 pr_cfg_small_rx.max_entries_sq = sq_entries;
2220 pr_cfg_small_rx.max_entries_rq1 = 1;
2221 pr_cfg_small_rx.max_entries_rq2 = 1;
2222 pr_cfg_small_rx.max_entries_rq3 = 1;
2223
2224 for (i = 0; i < def_qps; i++) {
2225 ret = ehea_init_port_res(port, &port->port_res[i], &pr_cfg, i);
2226 if (ret)
2227 goto out_clean_pr;
2228 }
2229 for (i = def_qps; i < def_qps + add_tx_qps; i++) {
2230 ret = ehea_init_port_res(port, &port->port_res[i],
2231 &pr_cfg_small_rx, i);
2232 if (ret)
2233 goto out_clean_pr;
2234 }
2235
2236 return 0;
2237
2238out_clean_pr:
2239 while (--i >= 0)
2240 ehea_clean_portres(port, &port->port_res[i]);
2241
2242out_kill_eq:
2243 ehea_destroy_eq(port->qp_eq);
2244 return ret;
2245}
2246
2247static int ehea_clean_all_portres(struct ehea_port *port)
2248{
2249 int ret = 0;
2250 int i;
2251
2252 for(i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++)
2253 ret |= ehea_clean_portres(port, &port->port_res[i]);
2254
2255 ret |= ehea_destroy_eq(port->qp_eq);
2256
2257 return ret;
2258}
2259
Thomas Klein35cf2e22007-08-06 13:55:14 +02002260static void ehea_remove_adapter_mr(struct ehea_adapter *adapter)
Thomas Klein1211bb62007-04-26 11:56:43 +02002261{
Thomas Klein35cf2e22007-08-06 13:55:14 +02002262 if (adapter->active_ports)
2263 return;
Thomas Klein1211bb62007-04-26 11:56:43 +02002264
2265 ehea_rem_mr(&adapter->mr);
2266}
2267
Thomas Klein35cf2e22007-08-06 13:55:14 +02002268static int ehea_add_adapter_mr(struct ehea_adapter *adapter)
Thomas Klein1211bb62007-04-26 11:56:43 +02002269{
Thomas Klein35cf2e22007-08-06 13:55:14 +02002270 if (adapter->active_ports)
2271 return 0;
Thomas Klein1211bb62007-04-26 11:56:43 +02002272
2273 return ehea_reg_kernel_mr(adapter, &adapter->mr);
2274}
2275
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002276static int ehea_up(struct net_device *dev)
2277{
2278 int ret, i;
2279 struct ehea_port *port = netdev_priv(dev);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002280
2281 if (port->state == EHEA_PORT_UP)
2282 return 0;
2283
2284 ret = ehea_port_res_setup(port, port->num_def_qps,
2285 port->num_add_tx_qps);
2286 if (ret) {
2287 ehea_error("port_res_failed");
2288 goto out;
2289 }
2290
2291 /* Set default QP for this port */
2292 ret = ehea_configure_port(port);
2293 if (ret) {
2294 ehea_error("ehea_configure_port failed. ret:%d", ret);
2295 goto out_clean_pr;
2296 }
2297
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002298 ret = ehea_reg_interrupts(dev);
2299 if (ret) {
Thomas Kleinf9e29222007-07-18 17:34:09 +02002300 ehea_error("reg_interrupts failed. ret:%d", ret);
2301 goto out_clean_pr;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002302 }
2303
2304 for(i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++) {
2305 ret = ehea_activate_qp(port->adapter, port->port_res[i].qp);
2306 if (ret) {
2307 ehea_error("activate_qp failed");
2308 goto out_free_irqs;
2309 }
2310 }
2311
2312 for(i = 0; i < port->num_def_qps; i++) {
2313 ret = ehea_fill_port_res(&port->port_res[i]);
2314 if (ret) {
2315 ehea_error("out_free_irqs");
2316 goto out_free_irqs;
2317 }
2318 }
2319
2320 ret = 0;
2321 port->state = EHEA_PORT_UP;
2322 goto out;
2323
2324out_free_irqs:
2325 ehea_free_interrupts(dev);
2326
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002327out_clean_pr:
2328 ehea_clean_all_portres(port);
2329out:
Thomas Klein44c82152007-07-11 16:32:00 +02002330 if (ret)
2331 ehea_info("Failed starting %s. ret=%i", dev->name, ret);
2332
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002333 return ret;
2334}
2335
Stephen Hemmingerbea33482007-10-03 16:41:36 -07002336static void port_napi_disable(struct ehea_port *port)
2337{
2338 int i;
2339
Jan-Bernd Themann0173b792007-10-24 11:53:34 +02002340 for (i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++)
Stephen Hemmingerbea33482007-10-03 16:41:36 -07002341 napi_disable(&port->port_res[i].napi);
2342}
2343
2344static void port_napi_enable(struct ehea_port *port)
2345{
2346 int i;
2347
Jan-Bernd Themann0173b792007-10-24 11:53:34 +02002348 for (i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++)
Stephen Hemmingerbea33482007-10-03 16:41:36 -07002349 napi_enable(&port->port_res[i].napi);
2350}
2351
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002352static int ehea_open(struct net_device *dev)
2353{
2354 int ret;
2355 struct ehea_port *port = netdev_priv(dev);
2356
2357 down(&port->port_lock);
2358
2359 if (netif_msg_ifup(port))
2360 ehea_info("enabling port %s", dev->name);
2361
2362 ret = ehea_up(dev);
Stephen Hemmingerbea33482007-10-03 16:41:36 -07002363 if (!ret) {
2364 port_napi_enable(port);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002365 netif_start_queue(dev);
Stephen Hemmingerbea33482007-10-03 16:41:36 -07002366 }
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002367
2368 up(&port->port_lock);
2369
2370 return ret;
2371}
2372
2373static int ehea_down(struct net_device *dev)
2374{
Stephen Hemmingerbea33482007-10-03 16:41:36 -07002375 int ret;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002376 struct ehea_port *port = netdev_priv(dev);
2377
2378 if (port->state == EHEA_PORT_DOWN)
2379 return 0;
2380
2381 ehea_drop_multicast_list(dev);
2382 ehea_free_interrupts(dev);
2383
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002384 port->state = EHEA_PORT_DOWN;
Thomas Klein44c82152007-07-11 16:32:00 +02002385
2386 ret = ehea_clean_all_portres(port);
2387 if (ret)
2388 ehea_info("Failed freeing resources for %s. ret=%i",
2389 dev->name, ret);
2390
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002391 return ret;
2392}
2393
2394static int ehea_stop(struct net_device *dev)
2395{
2396 int ret;
2397 struct ehea_port *port = netdev_priv(dev);
2398
2399 if (netif_msg_ifdown(port))
2400 ehea_info("disabling port %s", dev->name);
2401
Jan-Bernd Themann3bf76b82007-10-08 16:01:33 +02002402 flush_scheduled_work();
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002403 down(&port->port_lock);
2404 netif_stop_queue(dev);
Jan-Bernd Themann0173b792007-10-24 11:53:34 +02002405 port_napi_disable(port);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002406 ret = ehea_down(dev);
2407 up(&port->port_lock);
2408 return ret;
2409}
2410
Jan-Bernd Themann2c694482007-10-01 16:33:18 +02002411void ehea_purge_sq(struct ehea_qp *orig_qp)
2412{
2413 struct ehea_qp qp = *orig_qp;
2414 struct ehea_qp_init_attr *init_attr = &qp.init_attr;
2415 struct ehea_swqe *swqe;
2416 int wqe_index;
2417 int i;
2418
2419 for (i = 0; i < init_attr->act_nr_send_wqes; i++) {
2420 swqe = ehea_get_swqe(&qp, &wqe_index);
2421 swqe->tx_control |= EHEA_SWQE_PURGE;
2422 }
2423}
2424
2425int ehea_stop_qps(struct net_device *dev)
2426{
2427 struct ehea_port *port = netdev_priv(dev);
2428 struct ehea_adapter *adapter = port->adapter;
2429 struct hcp_modify_qp_cb0* cb0;
2430 int ret = -EIO;
2431 int dret;
2432 int i;
2433 u64 hret;
2434 u64 dummy64 = 0;
2435 u16 dummy16 = 0;
2436
2437 cb0 = kzalloc(PAGE_SIZE, GFP_KERNEL);
2438 if (!cb0) {
2439 ret = -ENOMEM;
2440 goto out;
2441 }
2442
2443 for (i = 0; i < (port->num_def_qps + port->num_add_tx_qps); i++) {
2444 struct ehea_port_res *pr = &port->port_res[i];
2445 struct ehea_qp *qp = pr->qp;
2446
2447 /* Purge send queue */
2448 ehea_purge_sq(qp);
2449
2450 /* Disable queue pair */
2451 hret = ehea_h_query_ehea_qp(adapter->handle, 0, qp->fw_handle,
2452 EHEA_BMASK_SET(H_QPCB0_ALL, 0xFFFF),
2453 cb0);
2454 if (hret != H_SUCCESS) {
2455 ehea_error("query_ehea_qp failed (1)");
2456 goto out;
2457 }
2458
2459 cb0->qp_ctl_reg = (cb0->qp_ctl_reg & H_QP_CR_RES_STATE) << 8;
2460 cb0->qp_ctl_reg &= ~H_QP_CR_ENABLED;
2461
2462 hret = ehea_h_modify_ehea_qp(adapter->handle, 0, qp->fw_handle,
2463 EHEA_BMASK_SET(H_QPCB0_QP_CTL_REG,
2464 1), cb0, &dummy64,
2465 &dummy64, &dummy16, &dummy16);
2466 if (hret != H_SUCCESS) {
2467 ehea_error("modify_ehea_qp failed (1)");
2468 goto out;
2469 }
2470
2471 hret = ehea_h_query_ehea_qp(adapter->handle, 0, qp->fw_handle,
2472 EHEA_BMASK_SET(H_QPCB0_ALL, 0xFFFF),
2473 cb0);
2474 if (hret != H_SUCCESS) {
2475 ehea_error("query_ehea_qp failed (2)");
2476 goto out;
2477 }
2478
2479 /* deregister shared memory regions */
2480 dret = ehea_rem_smrs(pr);
2481 if (dret) {
2482 ehea_error("unreg shared memory region failed");
2483 goto out;
2484 }
2485 }
2486
2487 ret = 0;
2488out:
2489 kfree(cb0);
2490
2491 return ret;
2492}
2493
2494void ehea_update_rqs(struct ehea_qp *orig_qp, struct ehea_port_res * pr)
2495{
2496 struct ehea_qp qp = *orig_qp;
2497 struct ehea_qp_init_attr *init_attr = &qp.init_attr;
2498 struct ehea_rwqe *rwqe;
2499 struct sk_buff **skba_rq2 = pr->rq2_skba.arr;
2500 struct sk_buff **skba_rq3 = pr->rq3_skba.arr;
2501 struct sk_buff *skb;
2502 u32 lkey = pr->recv_mr.lkey;
2503
2504
2505 int i;
2506 int index;
2507
2508 for (i = 0; i < init_attr->act_nr_rwqes_rq2 + 1; i++) {
2509 rwqe = ehea_get_next_rwqe(&qp, 2);
2510 rwqe->sg_list[0].l_key = lkey;
2511 index = EHEA_BMASK_GET(EHEA_WR_ID_INDEX, rwqe->wr_id);
2512 skb = skba_rq2[index];
2513 if (skb)
2514 rwqe->sg_list[0].vaddr = ehea_map_vaddr(skb->data);
2515 }
2516
2517 for (i = 0; i < init_attr->act_nr_rwqes_rq3 + 1; i++) {
2518 rwqe = ehea_get_next_rwqe(&qp, 3);
2519 rwqe->sg_list[0].l_key = lkey;
2520 index = EHEA_BMASK_GET(EHEA_WR_ID_INDEX, rwqe->wr_id);
2521 skb = skba_rq3[index];
2522 if (skb)
2523 rwqe->sg_list[0].vaddr = ehea_map_vaddr(skb->data);
2524 }
2525}
2526
2527int ehea_restart_qps(struct net_device *dev)
2528{
2529 struct ehea_port *port = netdev_priv(dev);
2530 struct ehea_adapter *adapter = port->adapter;
2531 int ret = 0;
2532 int i;
2533
2534 struct hcp_modify_qp_cb0* cb0;
2535 u64 hret;
2536 u64 dummy64 = 0;
2537 u16 dummy16 = 0;
2538
2539 cb0 = kzalloc(PAGE_SIZE, GFP_KERNEL);
2540 if (!cb0) {
2541 ret = -ENOMEM;
2542 goto out;
2543 }
2544
2545 for (i = 0; i < (port->num_def_qps + port->num_add_tx_qps); i++) {
2546 struct ehea_port_res *pr = &port->port_res[i];
2547 struct ehea_qp *qp = pr->qp;
2548
2549 ret = ehea_gen_smrs(pr);
2550 if (ret) {
2551 ehea_error("creation of shared memory regions failed");
2552 goto out;
2553 }
2554
2555 ehea_update_rqs(qp, pr);
2556
2557 /* Enable queue pair */
2558 hret = ehea_h_query_ehea_qp(adapter->handle, 0, qp->fw_handle,
2559 EHEA_BMASK_SET(H_QPCB0_ALL, 0xFFFF),
2560 cb0);
2561 if (hret != H_SUCCESS) {
2562 ehea_error("query_ehea_qp failed (1)");
2563 goto out;
2564 }
2565
2566 cb0->qp_ctl_reg = (cb0->qp_ctl_reg & H_QP_CR_RES_STATE) << 8;
2567 cb0->qp_ctl_reg |= H_QP_CR_ENABLED;
2568
2569 hret = ehea_h_modify_ehea_qp(adapter->handle, 0, qp->fw_handle,
2570 EHEA_BMASK_SET(H_QPCB0_QP_CTL_REG,
2571 1), cb0, &dummy64,
2572 &dummy64, &dummy16, &dummy16);
2573 if (hret != H_SUCCESS) {
2574 ehea_error("modify_ehea_qp failed (1)");
2575 goto out;
2576 }
2577
2578 hret = ehea_h_query_ehea_qp(adapter->handle, 0, qp->fw_handle,
2579 EHEA_BMASK_SET(H_QPCB0_ALL, 0xFFFF),
2580 cb0);
2581 if (hret != H_SUCCESS) {
2582 ehea_error("query_ehea_qp failed (2)");
2583 goto out;
2584 }
2585
2586 /* refill entire queue */
2587 ehea_refill_rq1(pr, pr->rq1_skba.index, 0);
2588 ehea_refill_rq2(pr, 0);
2589 ehea_refill_rq3(pr, 0);
2590 }
2591out:
2592 kfree(cb0);
2593
2594 return ret;
2595}
2596
David Howellsc4028952006-11-22 14:57:56 +00002597static void ehea_reset_port(struct work_struct *work)
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002598{
2599 int ret;
David Howellsc4028952006-11-22 14:57:56 +00002600 struct ehea_port *port =
2601 container_of(work, struct ehea_port, reset_task);
2602 struct net_device *dev = port->netdev;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002603
2604 port->resets++;
2605 down(&port->port_lock);
2606 netif_stop_queue(dev);
Stephen Hemmingerbea33482007-10-03 16:41:36 -07002607
2608 port_napi_disable(port);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002609
Thomas Klein44c82152007-07-11 16:32:00 +02002610 ehea_down(dev);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002611
2612 ret = ehea_up(dev);
Thomas Klein44c82152007-07-11 16:32:00 +02002613 if (ret)
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002614 goto out;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002615
Jan-Bernd Themann2c694482007-10-01 16:33:18 +02002616 ehea_set_multicast_list(dev);
2617
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002618 if (netif_msg_timer(port))
2619 ehea_info("Device %s resetted successfully", dev->name);
2620
Stephen Hemmingerbea33482007-10-03 16:41:36 -07002621 port_napi_enable(port);
2622
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002623 netif_wake_queue(dev);
2624out:
2625 up(&port->port_lock);
2626 return;
2627}
2628
Thomas Klein44c82152007-07-11 16:32:00 +02002629static void ehea_rereg_mrs(struct work_struct *work)
2630{
2631 int ret, i;
2632 struct ehea_adapter *adapter;
2633
Jan-Bernd Themann2c694482007-10-01 16:33:18 +02002634 down(&dlpar_mem_lock);
Thomas Klein44c82152007-07-11 16:32:00 +02002635 ehea_info("LPAR memory enlarged - re-initializing driver");
2636
2637 list_for_each_entry(adapter, &adapter_list, list)
2638 if (adapter->active_ports) {
2639 /* Shutdown all ports */
2640 for (i = 0; i < EHEA_MAX_PORTS; i++) {
2641 struct ehea_port *port = adapter->port[i];
2642
2643 if (port) {
2644 struct net_device *dev = port->netdev;
2645
2646 if (dev->flags & IFF_UP) {
Thomas Klein44c82152007-07-11 16:32:00 +02002647 down(&port->port_lock);
2648 netif_stop_queue(dev);
Jan-Bernd Themann2c694482007-10-01 16:33:18 +02002649 ret = ehea_stop_qps(dev);
2650 if (ret) {
2651 up(&port->port_lock);
2652 goto out;
2653 }
Stephen Hemmingerbea33482007-10-03 16:41:36 -07002654 port_napi_disable(port);
Thomas Klein44c82152007-07-11 16:32:00 +02002655 up(&port->port_lock);
2656 }
2657 }
2658 }
2659
2660 /* Unregister old memory region */
2661 ret = ehea_rem_mr(&adapter->mr);
2662 if (ret) {
2663 ehea_error("unregister MR failed - driver"
2664 " inoperable!");
2665 goto out;
2666 }
2667 }
2668
2669 ehea_destroy_busmap();
Thomas Klein44c82152007-07-11 16:32:00 +02002670 ret = ehea_create_busmap();
Jan-Bernd Themann2c694482007-10-01 16:33:18 +02002671 if (ret) {
2672 ehea_error("creating ehea busmap failed");
Thomas Klein44c82152007-07-11 16:32:00 +02002673 goto out;
Jan-Bernd Themann2c694482007-10-01 16:33:18 +02002674 }
Thomas Klein44c82152007-07-11 16:32:00 +02002675
2676 clear_bit(__EHEA_STOP_XFER, &ehea_driver_flags);
2677
2678 list_for_each_entry(adapter, &adapter_list, list)
2679 if (adapter->active_ports) {
2680 /* Register new memory region */
2681 ret = ehea_reg_kernel_mr(adapter, &adapter->mr);
2682 if (ret) {
2683 ehea_error("register MR failed - driver"
2684 " inoperable!");
2685 goto out;
2686 }
2687
2688 /* Restart all ports */
2689 for (i = 0; i < EHEA_MAX_PORTS; i++) {
2690 struct ehea_port *port = adapter->port[i];
2691
2692 if (port) {
2693 struct net_device *dev = port->netdev;
2694
2695 if (dev->flags & IFF_UP) {
Thomas Klein44c82152007-07-11 16:32:00 +02002696 down(&port->port_lock);
Jan-Bernd Themann2c694482007-10-01 16:33:18 +02002697 port_napi_enable(port);
2698 ret = ehea_restart_qps(dev);
2699 if (!ret)
Thomas Klein44c82152007-07-11 16:32:00 +02002700 netif_wake_queue(dev);
Thomas Klein44c82152007-07-11 16:32:00 +02002701 up(&port->port_lock);
2702 }
2703 }
2704 }
2705 }
Jan-Bernd Themann2c694482007-10-01 16:33:18 +02002706 up(&dlpar_mem_lock);
2707 ehea_info("re-initializing driver complete");
Thomas Klein44c82152007-07-11 16:32:00 +02002708out:
2709 return;
2710}
2711
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002712static void ehea_tx_watchdog(struct net_device *dev)
2713{
2714 struct ehea_port *port = netdev_priv(dev);
2715
Jan-Bernd Themann2c694482007-10-01 16:33:18 +02002716 if (netif_carrier_ok(dev) &&
2717 !test_bit(__EHEA_STOP_XFER, &ehea_driver_flags))
Jan-Bernd Themann3bf76b82007-10-08 16:01:33 +02002718 schedule_work(&port->reset_task);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002719}
2720
2721int ehea_sense_adapter_attr(struct ehea_adapter *adapter)
2722{
2723 struct hcp_query_ehea *cb;
2724 u64 hret;
2725 int ret;
2726
Thomas Kleina1d261c2006-11-03 17:48:23 +01002727 cb = kzalloc(PAGE_SIZE, GFP_KERNEL);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002728 if (!cb) {
2729 ret = -ENOMEM;
2730 goto out;
2731 }
2732
2733 hret = ehea_h_query_ehea(adapter->handle, cb);
2734
2735 if (hret != H_SUCCESS) {
2736 ret = -EIO;
2737 goto out_herr;
2738 }
2739
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002740 adapter->max_mc_mac = cb->max_mc_mac - 1;
2741 ret = 0;
2742
2743out_herr:
2744 kfree(cb);
2745out:
2746 return ret;
2747}
2748
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01002749int ehea_get_jumboframe_status(struct ehea_port *port, int *jumbo)
2750{
2751 struct hcp_ehea_port_cb4 *cb4;
2752 u64 hret;
2753 int ret = 0;
2754
2755 *jumbo = 0;
2756
2757 /* (Try to) enable *jumbo frames */
2758 cb4 = kzalloc(PAGE_SIZE, GFP_KERNEL);
2759 if (!cb4) {
2760 ehea_error("no mem for cb4");
2761 ret = -ENOMEM;
2762 goto out;
2763 } else {
2764 hret = ehea_h_query_ehea_port(port->adapter->handle,
2765 port->logical_port_id,
2766 H_PORT_CB4,
2767 H_PORT_CB4_JUMBO, cb4);
2768 if (hret == H_SUCCESS) {
2769 if (cb4->jumbo_frame)
2770 *jumbo = 1;
2771 else {
2772 cb4->jumbo_frame = 1;
2773 hret = ehea_h_modify_ehea_port(port->adapter->
2774 handle,
2775 port->
2776 logical_port_id,
2777 H_PORT_CB4,
2778 H_PORT_CB4_JUMBO,
2779 cb4);
2780 if (hret == H_SUCCESS)
2781 *jumbo = 1;
2782 }
2783 } else
2784 ret = -EINVAL;
2785
2786 kfree(cb4);
2787 }
2788out:
2789 return ret;
2790}
2791
2792static ssize_t ehea_show_port_id(struct device *dev,
2793 struct device_attribute *attr, char *buf)
2794{
2795 struct ehea_port *port = container_of(dev, struct ehea_port, ofdev.dev);
Jan-Bernd Themanna8e34fd2007-08-22 16:20:58 +02002796 return sprintf(buf, "%d", port->logical_port_id);
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01002797}
2798
2799static DEVICE_ATTR(log_port_id, S_IRUSR | S_IRGRP | S_IROTH, ehea_show_port_id,
2800 NULL);
2801
2802static void __devinit logical_port_release(struct device *dev)
2803{
2804 struct ehea_port *port = container_of(dev, struct ehea_port, ofdev.dev);
2805 of_node_put(port->ofdev.node);
2806}
2807
Thomas Kleind1dea382007-04-26 11:56:13 +02002808static int ehea_driver_sysfs_add(struct device *dev,
Jan-Bernd Themannd1d25aa2007-07-02 13:00:46 +02002809 struct device_driver *driver)
Thomas Kleind1dea382007-04-26 11:56:13 +02002810{
2811 int ret;
2812
2813 ret = sysfs_create_link(&driver->kobj, &dev->kobj,
2814 kobject_name(&dev->kobj));
2815 if (ret == 0) {
2816 ret = sysfs_create_link(&dev->kobj, &driver->kobj,
2817 "driver");
2818 if (ret)
2819 sysfs_remove_link(&driver->kobj,
2820 kobject_name(&dev->kobj));
2821 }
2822 return ret;
2823}
2824
2825static void ehea_driver_sysfs_remove(struct device *dev,
Jan-Bernd Themannd1d25aa2007-07-02 13:00:46 +02002826 struct device_driver *driver)
Thomas Kleind1dea382007-04-26 11:56:13 +02002827{
2828 struct device_driver *drv = driver;
2829
2830 if (drv) {
2831 sysfs_remove_link(&drv->kobj, kobject_name(&dev->kobj));
2832 sysfs_remove_link(&dev->kobj, "driver");
2833 }
2834}
2835
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01002836static struct device *ehea_register_port(struct ehea_port *port,
2837 struct device_node *dn)
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002838{
2839 int ret;
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01002840
2841 port->ofdev.node = of_node_get(dn);
Joachim Fenkes6b08f3a2007-09-26 19:45:51 +10002842 port->ofdev.dev.parent = &port->adapter->ofdev->dev;
Thomas Kleind1dea382007-04-26 11:56:13 +02002843 port->ofdev.dev.bus = &ibmebus_bus_type;
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01002844
Thomas Kleind1dea382007-04-26 11:56:13 +02002845 sprintf(port->ofdev.dev.bus_id, "port%d", port_name_cnt++);
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01002846 port->ofdev.dev.release = logical_port_release;
2847
2848 ret = of_device_register(&port->ofdev);
2849 if (ret) {
2850 ehea_error("failed to register device. ret=%d", ret);
2851 goto out;
2852 }
2853
2854 ret = device_create_file(&port->ofdev.dev, &dev_attr_log_port_id);
Jan-Bernd Themannd1d25aa2007-07-02 13:00:46 +02002855 if (ret) {
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01002856 ehea_error("failed to register attributes, ret=%d", ret);
2857 goto out_unreg_of_dev;
2858 }
Jan-Bernd Themanne542aa62007-03-22 17:50:24 +01002859
Thomas Kleind1dea382007-04-26 11:56:13 +02002860 ret = ehea_driver_sysfs_add(&port->ofdev.dev, &ehea_driver.driver);
2861 if (ret) {
2862 ehea_error("failed to register sysfs driver link");
2863 goto out_rem_dev_file;
2864 }
2865
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01002866 return &port->ofdev.dev;
2867
Thomas Kleind1dea382007-04-26 11:56:13 +02002868out_rem_dev_file:
2869 device_remove_file(&port->ofdev.dev, &dev_attr_log_port_id);
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01002870out_unreg_of_dev:
2871 of_device_unregister(&port->ofdev);
2872out:
2873 return NULL;
2874}
2875
2876static void ehea_unregister_port(struct ehea_port *port)
2877{
Thomas Kleind1dea382007-04-26 11:56:13 +02002878 ehea_driver_sysfs_remove(&port->ofdev.dev, &ehea_driver.driver);
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01002879 device_remove_file(&port->ofdev.dev, &dev_attr_log_port_id);
2880 of_device_unregister(&port->ofdev);
2881}
2882
2883struct ehea_port *ehea_setup_single_port(struct ehea_adapter *adapter,
2884 u32 logical_port_id,
2885 struct device_node *dn)
2886{
2887 int ret;
2888 struct net_device *dev;
2889 struct ehea_port *port;
2890 struct device *port_dev;
2891 int jumbo;
2892
2893 /* allocate memory for the port structures */
2894 dev = alloc_etherdev(sizeof(struct ehea_port));
2895
2896 if (!dev) {
2897 ehea_error("no mem for net_device");
2898 ret = -ENOMEM;
2899 goto out_err;
2900 }
2901
2902 port = netdev_priv(dev);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002903
2904 sema_init(&port->port_lock, 1);
2905 port->state = EHEA_PORT_DOWN;
2906 port->sig_comp_iv = sq_entries / 10;
2907
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01002908 port->adapter = adapter;
2909 port->netdev = dev;
2910 port->logical_port_id = logical_port_id;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002911
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01002912 port->msg_enable = netif_msg_init(msg_level, EHEA_MSG_DEFAULT);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002913
2914 port->mc_list = kzalloc(sizeof(struct ehea_mc_list), GFP_KERNEL);
2915 if (!port->mc_list) {
2916 ret = -ENOMEM;
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01002917 goto out_free_ethdev;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002918 }
2919
2920 INIT_LIST_HEAD(&port->mc_list->list);
2921
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002922 ret = ehea_sense_port_attr(port);
2923 if (ret)
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01002924 goto out_free_mc_list;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002925
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01002926 port_dev = ehea_register_port(port, dn);
2927 if (!port_dev)
2928 goto out_free_mc_list;
Thomas Klein9c750b72007-01-29 18:44:01 +01002929
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01002930 SET_NETDEV_DEV(dev, port_dev);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002931
2932 /* initialize net_device structure */
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002933 memcpy(dev->dev_addr, &port->mac_addr, ETH_ALEN);
2934
2935 dev->open = ehea_open;
Jan-Bernd Themann8d22c972007-07-23 16:05:03 +02002936#ifdef CONFIG_NET_POLL_CONTROLLER
2937 dev->poll_controller = ehea_netpoll;
2938#endif
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002939 dev->stop = ehea_stop;
2940 dev->hard_start_xmit = ehea_start_xmit;
2941 dev->get_stats = ehea_get_stats;
2942 dev->set_multicast_list = ehea_set_multicast_list;
2943 dev->set_mac_address = ehea_set_mac_addr;
2944 dev->change_mtu = ehea_change_mtu;
2945 dev->vlan_rx_register = ehea_vlan_rx_register;
2946 dev->vlan_rx_add_vid = ehea_vlan_rx_add_vid;
2947 dev->vlan_rx_kill_vid = ehea_vlan_rx_kill_vid;
2948 dev->features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_TSO
2949 | NETIF_F_HIGHDMA | NETIF_F_HW_CSUM | NETIF_F_HW_VLAN_TX
2950 | NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER
2951 | NETIF_F_LLTX;
2952 dev->tx_timeout = &ehea_tx_watchdog;
2953 dev->watchdog_timeo = EHEA_WATCH_DOG_TIMEOUT;
2954
David Howellsc4028952006-11-22 14:57:56 +00002955 INIT_WORK(&port->reset_task, ehea_reset_port);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002956
Thomas Kleinf9e29222007-07-18 17:34:09 +02002957 ret = ehea_broadcast_reg_helper(port, H_REG_BCMC);
2958 if (ret) {
2959 ret = -EIO;
2960 goto out_unreg_port;
2961 }
2962
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002963 ehea_set_ethtool_ops(dev);
2964
2965 ret = register_netdev(dev);
2966 if (ret) {
2967 ehea_error("register_netdev failed. ret=%d", ret);
Thomas Kleinf9e29222007-07-18 17:34:09 +02002968 goto out_dereg_bc;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002969 }
2970
Jan-Bernd Themannd4dc4ec2007-09-25 16:16:34 -07002971 port->lro_max_aggr = lro_max_aggr;
2972
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01002973 ret = ehea_get_jumboframe_status(port, &jumbo);
Jan-Bernd Themanne542aa62007-03-22 17:50:24 +01002974 if (ret)
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01002975 ehea_error("failed determining jumbo frame status for %s",
2976 port->netdev->name);
2977
Thomas Klein9c750b72007-01-29 18:44:01 +01002978 ehea_info("%s: Jumbo frames are %sabled", dev->name,
2979 jumbo == 1 ? "en" : "dis");
2980
Thomas Klein44c82152007-07-11 16:32:00 +02002981 adapter->active_ports++;
2982
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01002983 return port;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002984
Thomas Kleinf9e29222007-07-18 17:34:09 +02002985out_dereg_bc:
2986 ehea_broadcast_reg_helper(port, H_DEREG_BCMC);
2987
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01002988out_unreg_port:
2989 ehea_unregister_port(port);
2990
2991out_free_mc_list:
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02002992 kfree(port->mc_list);
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01002993
2994out_free_ethdev:
2995 free_netdev(dev);
2996
2997out_err:
2998 ehea_error("setting up logical port with id=%d failed, ret=%d",
2999 logical_port_id, ret);
3000 return NULL;
3001}
3002
3003static void ehea_shutdown_single_port(struct ehea_port *port)
3004{
3005 unregister_netdev(port->netdev);
3006 ehea_unregister_port(port);
Thomas Kleinf9e29222007-07-18 17:34:09 +02003007 ehea_broadcast_reg_helper(port, H_DEREG_BCMC);
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01003008 kfree(port->mc_list);
3009 free_netdev(port->netdev);
Thomas Klein44c82152007-07-11 16:32:00 +02003010 port->adapter->active_ports--;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02003011}
3012
3013static int ehea_setup_ports(struct ehea_adapter *adapter)
3014{
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01003015 struct device_node *lhea_dn;
3016 struct device_node *eth_dn = NULL;
Jan-Bernd Themannd1d25aa2007-07-02 13:00:46 +02003017
Stephen Rothwell9f9a3b82007-05-01 13:51:32 +10003018 const u32 *dn_log_port_id;
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01003019 int i = 0;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02003020
Joachim Fenkes6b08f3a2007-09-26 19:45:51 +10003021 lhea_dn = adapter->ofdev->node;
Jan-Bernd Themann1eef4e02007-03-22 17:49:42 +01003022 while ((eth_dn = of_get_next_child(lhea_dn, eth_dn))) {
Jan-Bernd Themanne542aa62007-03-22 17:50:24 +01003023
Stephen Rothwell40cd3a42007-05-01 13:54:02 +10003024 dn_log_port_id = of_get_property(eth_dn, "ibm,hea-port-no",
Jan-Bernd Themannd1d25aa2007-07-02 13:00:46 +02003025 NULL);
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01003026 if (!dn_log_port_id) {
3027 ehea_error("bad device node: eth_dn name=%s",
3028 eth_dn->full_name);
3029 continue;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02003030 }
3031
Thomas Klein1211bb62007-04-26 11:56:43 +02003032 if (ehea_add_adapter_mr(adapter)) {
3033 ehea_error("creating MR failed");
3034 of_node_put(eth_dn);
3035 return -EIO;
3036 }
3037
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01003038 adapter->port[i] = ehea_setup_single_port(adapter,
3039 *dn_log_port_id,
3040 eth_dn);
3041 if (adapter->port[i])
3042 ehea_info("%s -> logical port id #%d",
Jan-Bernd Themanne542aa62007-03-22 17:50:24 +01003043 adapter->port[i]->netdev->name,
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01003044 *dn_log_port_id);
Thomas Klein1211bb62007-04-26 11:56:43 +02003045 else
3046 ehea_remove_adapter_mr(adapter);
3047
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01003048 i++;
Jan-Bernd Themann1eef4e02007-03-22 17:49:42 +01003049 };
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02003050
Thomas Klein1211bb62007-04-26 11:56:43 +02003051 return 0;
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01003052}
3053
Jan-Bernd Themanne542aa62007-03-22 17:50:24 +01003054static struct device_node *ehea_get_eth_dn(struct ehea_adapter *adapter,
3055 u32 logical_port_id)
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01003056{
3057 struct device_node *lhea_dn;
3058 struct device_node *eth_dn = NULL;
Stephen Rothwell9f9a3b82007-05-01 13:51:32 +10003059 const u32 *dn_log_port_id;
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01003060
Joachim Fenkes6b08f3a2007-09-26 19:45:51 +10003061 lhea_dn = adapter->ofdev->node;
Jan-Bernd Themann1eef4e02007-03-22 17:49:42 +01003062 while ((eth_dn = of_get_next_child(lhea_dn, eth_dn))) {
Jan-Bernd Themanne542aa62007-03-22 17:50:24 +01003063
Stephen Rothwell40cd3a42007-05-01 13:54:02 +10003064 dn_log_port_id = of_get_property(eth_dn, "ibm,hea-port-no",
Jan-Bernd Themannd1d25aa2007-07-02 13:00:46 +02003065 NULL);
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01003066 if (dn_log_port_id)
3067 if (*dn_log_port_id == logical_port_id)
3068 return eth_dn;
Jan-Bernd Themann1eef4e02007-03-22 17:49:42 +01003069 };
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01003070
3071 return NULL;
3072}
3073
3074static ssize_t ehea_probe_port(struct device *dev,
3075 struct device_attribute *attr,
3076 const char *buf, size_t count)
3077{
3078 struct ehea_adapter *adapter = dev->driver_data;
3079 struct ehea_port *port;
3080 struct device_node *eth_dn = NULL;
3081 int i;
3082
3083 u32 logical_port_id;
3084
Jan-Bernd Themanna8e34fd2007-08-22 16:20:58 +02003085 sscanf(buf, "%d", &logical_port_id);
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01003086
3087 port = ehea_get_port(adapter, logical_port_id);
3088
3089 if (port) {
3090 ehea_info("adding port with logical port id=%d failed. port "
3091 "already configured as %s.", logical_port_id,
3092 port->netdev->name);
3093 return -EINVAL;
3094 }
Jan-Bernd Themanne542aa62007-03-22 17:50:24 +01003095
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01003096 eth_dn = ehea_get_eth_dn(adapter, logical_port_id);
3097
3098 if (!eth_dn) {
3099 ehea_info("no logical port with id %d found", logical_port_id);
3100 return -EINVAL;
3101 }
Jan-Bernd Themanne542aa62007-03-22 17:50:24 +01003102
Thomas Klein1211bb62007-04-26 11:56:43 +02003103 if (ehea_add_adapter_mr(adapter)) {
3104 ehea_error("creating MR failed");
3105 return -EIO;
3106 }
3107
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01003108 port = ehea_setup_single_port(adapter, logical_port_id, eth_dn);
3109
Jan-Bernd Themann1eef4e02007-03-22 17:49:42 +01003110 of_node_put(eth_dn);
3111
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01003112 if (port) {
3113 for (i=0; i < EHEA_MAX_PORTS; i++)
3114 if (!adapter->port[i]) {
3115 adapter->port[i] = port;
3116 break;
3117 }
3118
3119 ehea_info("added %s (logical port id=%d)", port->netdev->name,
3120 logical_port_id);
Thomas Klein1211bb62007-04-26 11:56:43 +02003121 } else {
3122 ehea_remove_adapter_mr(adapter);
Jan-Bernd Themanne542aa62007-03-22 17:50:24 +01003123 return -EIO;
Thomas Klein1211bb62007-04-26 11:56:43 +02003124 }
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01003125
3126 return (ssize_t) count;
3127}
3128
3129static ssize_t ehea_remove_port(struct device *dev,
3130 struct device_attribute *attr,
3131 const char *buf, size_t count)
3132{
3133 struct ehea_adapter *adapter = dev->driver_data;
3134 struct ehea_port *port;
3135 int i;
3136 u32 logical_port_id;
3137
Jan-Bernd Themanna8e34fd2007-08-22 16:20:58 +02003138 sscanf(buf, "%d", &logical_port_id);
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01003139
3140 port = ehea_get_port(adapter, logical_port_id);
3141
3142 if (port) {
3143 ehea_info("removed %s (logical port id=%d)", port->netdev->name,
3144 logical_port_id);
3145
3146 ehea_shutdown_single_port(port);
3147
3148 for (i=0; i < EHEA_MAX_PORTS; i++)
3149 if (adapter->port[i] == port) {
3150 adapter->port[i] = NULL;
3151 break;
3152 }
3153 } else {
3154 ehea_error("removing port with logical port id=%d failed. port "
3155 "not configured.", logical_port_id);
3156 return -EINVAL;
3157 }
3158
Thomas Klein1211bb62007-04-26 11:56:43 +02003159 ehea_remove_adapter_mr(adapter);
3160
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01003161 return (ssize_t) count;
3162}
3163
3164static DEVICE_ATTR(probe_port, S_IWUSR, NULL, ehea_probe_port);
3165static DEVICE_ATTR(remove_port, S_IWUSR, NULL, ehea_remove_port);
3166
Joachim Fenkes6b08f3a2007-09-26 19:45:51 +10003167int ehea_create_device_sysfs(struct of_device *dev)
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01003168{
Joachim Fenkes6b08f3a2007-09-26 19:45:51 +10003169 int ret = device_create_file(&dev->dev, &dev_attr_probe_port);
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01003170 if (ret)
3171 goto out;
3172
Joachim Fenkes6b08f3a2007-09-26 19:45:51 +10003173 ret = device_create_file(&dev->dev, &dev_attr_remove_port);
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01003174out:
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02003175 return ret;
3176}
3177
Joachim Fenkes6b08f3a2007-09-26 19:45:51 +10003178void ehea_remove_device_sysfs(struct of_device *dev)
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01003179{
Joachim Fenkes6b08f3a2007-09-26 19:45:51 +10003180 device_remove_file(&dev->dev, &dev_attr_probe_port);
3181 device_remove_file(&dev->dev, &dev_attr_remove_port);
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01003182}
3183
Joachim Fenkes6b08f3a2007-09-26 19:45:51 +10003184static int __devinit ehea_probe_adapter(struct of_device *dev,
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01003185 const struct of_device_id *id)
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02003186{
3187 struct ehea_adapter *adapter;
Stephen Rothwell9f9a3b82007-05-01 13:51:32 +10003188 const u64 *adapter_handle;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02003189 int ret;
3190
Joachim Fenkes6b08f3a2007-09-26 19:45:51 +10003191 if (!dev || !dev->node) {
Jan-Bernd Themann1eef4e02007-03-22 17:49:42 +01003192 ehea_error("Invalid ibmebus device probed");
3193 return -EINVAL;
3194 }
3195
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02003196 adapter = kzalloc(sizeof(*adapter), GFP_KERNEL);
3197 if (!adapter) {
3198 ret = -ENOMEM;
Joachim Fenkes6b08f3a2007-09-26 19:45:51 +10003199 dev_err(&dev->dev, "no mem for ehea_adapter\n");
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02003200 goto out;
3201 }
3202
Thomas Klein44c82152007-07-11 16:32:00 +02003203 list_add(&adapter->list, &adapter_list);
3204
Joachim Fenkes6b08f3a2007-09-26 19:45:51 +10003205 adapter->ofdev = dev;
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01003206
Joachim Fenkes6b08f3a2007-09-26 19:45:51 +10003207 adapter_handle = of_get_property(dev->node, "ibm,hea-handle",
Jan-Bernd Themannd1d25aa2007-07-02 13:00:46 +02003208 NULL);
Thomas Klein061bf3c2007-01-22 12:52:20 +01003209 if (adapter_handle)
3210 adapter->handle = *adapter_handle;
3211
3212 if (!adapter->handle) {
Joachim Fenkes6b08f3a2007-09-26 19:45:51 +10003213 dev_err(&dev->dev, "failed getting handle for adapter"
3214 " '%s'\n", dev->node->full_name);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02003215 ret = -ENODEV;
3216 goto out_free_ad;
3217 }
3218
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02003219 adapter->pd = EHEA_PD_ID;
3220
Joachim Fenkes6b08f3a2007-09-26 19:45:51 +10003221 dev->dev.driver_data = adapter;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02003222
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02003223
3224 /* initialize adapter and ports */
3225 /* get adapter properties */
3226 ret = ehea_sense_adapter_attr(adapter);
3227 if (ret) {
Joe Perches898eb712007-10-18 03:06:30 -07003228 dev_err(&dev->dev, "sense_adapter_attr failed: %d\n", ret);
Thomas Klein1211bb62007-04-26 11:56:43 +02003229 goto out_free_ad;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02003230 }
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02003231
3232 adapter->neq = ehea_create_eq(adapter,
3233 EHEA_NEQ, EHEA_MAX_ENTRIES_EQ, 1);
3234 if (!adapter->neq) {
Jan-Bernd Themann1eef4e02007-03-22 17:49:42 +01003235 ret = -EIO;
Joe Perches898eb712007-10-18 03:06:30 -07003236 dev_err(&dev->dev, "NEQ creation failed\n");
Thomas Klein1211bb62007-04-26 11:56:43 +02003237 goto out_free_ad;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02003238 }
3239
3240 tasklet_init(&adapter->neq_tasklet, ehea_neq_tasklet,
3241 (unsigned long)adapter);
3242
Joachim Fenkes6b08f3a2007-09-26 19:45:51 +10003243 ret = ibmebus_request_irq(adapter->neq->attr.ist1,
Thomas Gleixner38515e92007-02-14 00:33:16 -08003244 ehea_interrupt_neq, IRQF_DISABLED,
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02003245 "ehea_neq", adapter);
3246 if (ret) {
Joe Perches898eb712007-10-18 03:06:30 -07003247 dev_err(&dev->dev, "requesting NEQ IRQ failed\n");
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02003248 goto out_kill_eq;
3249 }
3250
Jan-Bernd Themann1eef4e02007-03-22 17:49:42 +01003251 ret = ehea_create_device_sysfs(dev);
3252 if (ret)
Jan-Bernd Themann3bf76b82007-10-08 16:01:33 +02003253 goto out_free_irq;
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01003254
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02003255 ret = ehea_setup_ports(adapter);
3256 if (ret) {
Joe Perches898eb712007-10-18 03:06:30 -07003257 dev_err(&dev->dev, "setup_ports failed\n");
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01003258 goto out_rem_dev_sysfs;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02003259 }
3260
3261 ret = 0;
3262 goto out;
3263
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01003264out_rem_dev_sysfs:
3265 ehea_remove_device_sysfs(dev);
3266
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02003267out_free_irq:
Joachim Fenkes6b08f3a2007-09-26 19:45:51 +10003268 ibmebus_free_irq(adapter->neq->attr.ist1, adapter);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02003269
3270out_kill_eq:
3271 ehea_destroy_eq(adapter->neq);
3272
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02003273out_free_ad:
3274 kfree(adapter);
3275out:
3276 return ret;
3277}
3278
Joachim Fenkes6b08f3a2007-09-26 19:45:51 +10003279static int __devexit ehea_remove(struct of_device *dev)
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02003280{
Joachim Fenkes6b08f3a2007-09-26 19:45:51 +10003281 struct ehea_adapter *adapter = dev->dev.driver_data;
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02003282 int i;
3283
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01003284 for (i = 0; i < EHEA_MAX_PORTS; i++)
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02003285 if (adapter->port[i]) {
3286 ehea_shutdown_single_port(adapter->port[i]);
3287 adapter->port[i] = NULL;
3288 }
Jan-Bernd Themann1acf2312007-02-28 18:34:02 +01003289
3290 ehea_remove_device_sysfs(dev);
3291
Jan-Bernd Themann3bf76b82007-10-08 16:01:33 +02003292 flush_scheduled_work();
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02003293
Joachim Fenkes6b08f3a2007-09-26 19:45:51 +10003294 ibmebus_free_irq(adapter->neq->attr.ist1, adapter);
Thomas Kleind4150a22007-01-29 18:44:41 +01003295 tasklet_kill(&adapter->neq_tasklet);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02003296
3297 ehea_destroy_eq(adapter->neq);
Thomas Klein1211bb62007-04-26 11:56:43 +02003298 ehea_remove_adapter_mr(adapter);
Thomas Klein44c82152007-07-11 16:32:00 +02003299 list_del(&adapter->list);
3300
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02003301 kfree(adapter);
Thomas Klein44c82152007-07-11 16:32:00 +02003302
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02003303 return 0;
3304}
3305
Jan-Bernd Themann2a6f4e42007-10-26 14:37:28 +02003306static int ehea_reboot_notifier(struct notifier_block *nb,
3307 unsigned long action, void *unused)
3308{
3309 if (action == SYS_RESTART) {
3310 ehea_info("Reboot: freeing all eHEA resources");
3311 ibmebus_unregister_driver(&ehea_driver);
3312 }
3313 return NOTIFY_DONE;
3314}
3315
3316static struct notifier_block ehea_reboot_nb = {
3317 .notifier_call = ehea_reboot_notifier,
3318};
3319
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02003320static int check_module_parm(void)
3321{
3322 int ret = 0;
3323
3324 if ((rq1_entries < EHEA_MIN_ENTRIES_QP) ||
3325 (rq1_entries > EHEA_MAX_ENTRIES_RQ1)) {
3326 ehea_info("Bad parameter: rq1_entries");
3327 ret = -EINVAL;
3328 }
3329 if ((rq2_entries < EHEA_MIN_ENTRIES_QP) ||
3330 (rq2_entries > EHEA_MAX_ENTRIES_RQ2)) {
3331 ehea_info("Bad parameter: rq2_entries");
3332 ret = -EINVAL;
3333 }
3334 if ((rq3_entries < EHEA_MIN_ENTRIES_QP) ||
3335 (rq3_entries > EHEA_MAX_ENTRIES_RQ3)) {
3336 ehea_info("Bad parameter: rq3_entries");
3337 ret = -EINVAL;
3338 }
3339 if ((sq_entries < EHEA_MIN_ENTRIES_QP) ||
3340 (sq_entries > EHEA_MAX_ENTRIES_SQ)) {
3341 ehea_info("Bad parameter: sq_entries");
3342 ret = -EINVAL;
3343 }
3344
3345 return ret;
3346}
3347
Jan-Bernd Themann4c3ca4d2007-07-05 09:26:25 +02003348static ssize_t ehea_show_capabilities(struct device_driver *drv,
3349 char *buf)
3350{
3351 return sprintf(buf, "%d", EHEA_CAPABILITIES);
3352}
3353
3354static DRIVER_ATTR(capabilities, S_IRUSR | S_IRGRP | S_IROTH,
3355 ehea_show_capabilities, NULL);
3356
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02003357int __init ehea_module_init(void)
3358{
3359 int ret;
3360
3361 printk(KERN_INFO "IBM eHEA ethernet device driver (Release %s)\n",
3362 DRV_VERSION);
3363
Thomas Klein44c82152007-07-11 16:32:00 +02003364
3365 INIT_WORK(&ehea_rereg_mr_task, ehea_rereg_mrs);
Jan-Bernd Themann2c694482007-10-01 16:33:18 +02003366 sema_init(&dlpar_mem_lock, 1);
Thomas Klein44c82152007-07-11 16:32:00 +02003367
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02003368 ret = check_module_parm();
3369 if (ret)
3370 goto out;
Thomas Klein44c82152007-07-11 16:32:00 +02003371
3372 ret = ehea_create_busmap();
3373 if (ret)
3374 goto out;
3375
Jan-Bernd Themann2a6f4e42007-10-26 14:37:28 +02003376 register_reboot_notifier(&ehea_reboot_nb);
3377
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02003378 ret = ibmebus_register_driver(&ehea_driver);
Jan-Bernd Themann4c3ca4d2007-07-05 09:26:25 +02003379 if (ret) {
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02003380 ehea_error("failed registering eHEA device driver on ebus");
Jan-Bernd Themann4c3ca4d2007-07-05 09:26:25 +02003381 goto out;
3382 }
3383
3384 ret = driver_create_file(&ehea_driver.driver,
3385 &driver_attr_capabilities);
3386 if (ret) {
3387 ehea_error("failed to register capabilities attribute, ret=%d",
3388 ret);
Jan-Bernd Themann2a6f4e42007-10-26 14:37:28 +02003389 unregister_reboot_notifier(&ehea_reboot_nb);
Jan-Bernd Themann4c3ca4d2007-07-05 09:26:25 +02003390 ibmebus_unregister_driver(&ehea_driver);
3391 goto out;
3392 }
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02003393
3394out:
3395 return ret;
3396}
3397
3398static void __exit ehea_module_exit(void)
3399{
Jan-Bernd Themann3bf76b82007-10-08 16:01:33 +02003400 flush_scheduled_work();
Jan-Bernd Themann4c3ca4d2007-07-05 09:26:25 +02003401 driver_remove_file(&ehea_driver.driver, &driver_attr_capabilities);
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02003402 ibmebus_unregister_driver(&ehea_driver);
Jan-Bernd Themann2a6f4e42007-10-26 14:37:28 +02003403 unregister_reboot_notifier(&ehea_reboot_nb);
Thomas Klein44c82152007-07-11 16:32:00 +02003404 ehea_destroy_busmap();
Jan-Bernd Themann7a291082006-09-13 17:44:31 +02003405}
3406
3407module_init(ehea_module_init);
3408module_exit(ehea_module_exit);