aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ehea/ehea_main.c
diff options
context:
space:
mode:
authorJan-Bernd Themann <ossthema@de.ibm.com>2007-10-01 10:33:18 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-10-10 19:54:05 -0400
commit2c69448bbcedebeb8409ddb05fbc7d3fe1cfbda7 (patch)
tree143d29f88c4983f0437b9114c0784469f59a956a /drivers/net/ehea/ehea_main.c
parent31a5bb04d59931eb4657826213a439d37d12d4a9 (diff)
ehea: DLPAR memory add fix
Due to stability issues in high load situations the HW queue handling has to be changed. The HW queues are now stopped and restarted again instead of destroying and allocating new HW queues. Signed-off-by: Jan-Bernd Themann <themann@de.ibm.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/net/ehea/ehea_main.c')
-rw-r--r--drivers/net/ehea/ehea_main.c276
1 files changed, 246 insertions, 30 deletions
diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c
index 62d6c1e5f9d3..5bc0a1530eb7 100644
--- a/drivers/net/ehea/ehea_main.c
+++ b/drivers/net/ehea/ehea_main.c
@@ -97,6 +97,7 @@ u64 ehea_driver_flags = 0;
97struct workqueue_struct *ehea_driver_wq; 97struct workqueue_struct *ehea_driver_wq;
98struct work_struct ehea_rereg_mr_task; 98struct work_struct ehea_rereg_mr_task;
99 99
100struct semaphore dlpar_mem_lock;
100 101
101static int __devinit ehea_probe_adapter(struct ibmebus_dev *dev, 102static int __devinit ehea_probe_adapter(struct ibmebus_dev *dev,
102 const struct of_device_id *id); 103 const struct of_device_id *id);
@@ -177,16 +178,24 @@ static void ehea_refill_rq1(struct ehea_port_res *pr, int index, int nr_of_wqes)
177 struct sk_buff **skb_arr_rq1 = pr->rq1_skba.arr; 178 struct sk_buff **skb_arr_rq1 = pr->rq1_skba.arr;
178 struct net_device *dev = pr->port->netdev; 179 struct net_device *dev = pr->port->netdev;
179 int max_index_mask = pr->rq1_skba.len - 1; 180 int max_index_mask = pr->rq1_skba.len - 1;
181 int fill_wqes = pr->rq1_skba.os_skbs + nr_of_wqes;
182 int adder = 0;
180 int i; 183 int i;
181 184
182 if (!nr_of_wqes) 185 pr->rq1_skba.os_skbs = 0;
186
187 if (unlikely(test_bit(__EHEA_STOP_XFER, &ehea_driver_flags))) {
188 pr->rq1_skba.index = index;
189 pr->rq1_skba.os_skbs = fill_wqes;
183 return; 190 return;
191 }
184 192
185 for (i = 0; i < nr_of_wqes; i++) { 193 for (i = 0; i < fill_wqes; i++) {
186 if (!skb_arr_rq1[index]) { 194 if (!skb_arr_rq1[index]) {
187 skb_arr_rq1[index] = netdev_alloc_skb(dev, 195 skb_arr_rq1[index] = netdev_alloc_skb(dev,
188 EHEA_L_PKT_SIZE); 196 EHEA_L_PKT_SIZE);
189 if (!skb_arr_rq1[index]) { 197 if (!skb_arr_rq1[index]) {
198 pr->rq1_skba.os_skbs = fill_wqes - i;
190 ehea_error("%s: no mem for skb/%d wqes filled", 199 ehea_error("%s: no mem for skb/%d wqes filled",
191 dev->name, i); 200 dev->name, i);
192 break; 201 break;
@@ -194,9 +203,14 @@ static void ehea_refill_rq1(struct ehea_port_res *pr, int index, int nr_of_wqes)
194 } 203 }
195 index--; 204 index--;
196 index &= max_index_mask; 205 index &= max_index_mask;
206 adder++;
197 } 207 }
208
209 if (adder == 0)
210 return;
211
198 /* Ring doorbell */ 212 /* Ring doorbell */
199 ehea_update_rq1a(pr->qp, i); 213 ehea_update_rq1a(pr->qp, adder);
200} 214}
201 215
202static int ehea_init_fill_rq1(struct ehea_port_res *pr, int nr_rq1a) 216static int ehea_init_fill_rq1(struct ehea_port_res *pr, int nr_rq1a)
@@ -230,16 +244,21 @@ static int ehea_refill_rq_def(struct ehea_port_res *pr,
230 struct sk_buff **skb_arr = q_skba->arr; 244 struct sk_buff **skb_arr = q_skba->arr;
231 struct ehea_rwqe *rwqe; 245 struct ehea_rwqe *rwqe;
232 int i, index, max_index_mask, fill_wqes; 246 int i, index, max_index_mask, fill_wqes;
247 int adder = 0;
233 int ret = 0; 248 int ret = 0;
234 249
235 fill_wqes = q_skba->os_skbs + num_wqes; 250 fill_wqes = q_skba->os_skbs + num_wqes;
251 q_skba->os_skbs = 0;
236 252
237 if (!fill_wqes) 253 if (unlikely(test_bit(__EHEA_STOP_XFER, &ehea_driver_flags))) {
254 q_skba->os_skbs = fill_wqes;
238 return ret; 255 return ret;
256 }
239 257
240 index = q_skba->index; 258 index = q_skba->index;
241 max_index_mask = q_skba->len - 1; 259 max_index_mask = q_skba->len - 1;
242 for (i = 0; i < fill_wqes; i++) { 260 for (i = 0; i < fill_wqes; i++) {
261 u64 tmp_addr;
243 struct sk_buff *skb = netdev_alloc_skb(dev, packet_size); 262 struct sk_buff *skb = netdev_alloc_skb(dev, packet_size);
244 if (!skb) { 263 if (!skb) {
245 ehea_error("%s: no mem for skb/%d wqes filled", 264 ehea_error("%s: no mem for skb/%d wqes filled",
@@ -251,30 +270,37 @@ static int ehea_refill_rq_def(struct ehea_port_res *pr,
251 skb_reserve(skb, NET_IP_ALIGN); 270 skb_reserve(skb, NET_IP_ALIGN);
252 271
253 skb_arr[index] = skb; 272 skb_arr[index] = skb;
273 tmp_addr = ehea_map_vaddr(skb->data);
274 if (tmp_addr == -1) {
275 dev_kfree_skb(skb);
276 q_skba->os_skbs = fill_wqes - i;
277 ret = 0;
278 break;
279 }
254 280
255 rwqe = ehea_get_next_rwqe(qp, rq_nr); 281 rwqe = ehea_get_next_rwqe(qp, rq_nr);
256 rwqe->wr_id = EHEA_BMASK_SET(EHEA_WR_ID_TYPE, wqe_type) 282 rwqe->wr_id = EHEA_BMASK_SET(EHEA_WR_ID_TYPE, wqe_type)
257 | EHEA_BMASK_SET(EHEA_WR_ID_INDEX, index); 283 | EHEA_BMASK_SET(EHEA_WR_ID_INDEX, index);
258 rwqe->sg_list[0].l_key = pr->recv_mr.lkey; 284 rwqe->sg_list[0].l_key = pr->recv_mr.lkey;
259 rwqe->sg_list[0].vaddr = ehea_map_vaddr(skb->data); 285 rwqe->sg_list[0].vaddr = tmp_addr;
260 rwqe->sg_list[0].len = packet_size; 286 rwqe->sg_list[0].len = packet_size;
261 rwqe->data_segments = 1; 287 rwqe->data_segments = 1;
262 288
263 index++; 289 index++;
264 index &= max_index_mask; 290 index &= max_index_mask;
265 291 adder++;
266 if (unlikely(test_bit(__EHEA_STOP_XFER, &ehea_driver_flags)))
267 goto out;
268 } 292 }
269 293
270 q_skba->index = index; 294 q_skba->index = index;
295 if (adder == 0)
296 goto out;
271 297
272 /* Ring doorbell */ 298 /* Ring doorbell */
273 iosync(); 299 iosync();
274 if (rq_nr == 2) 300 if (rq_nr == 2)
275 ehea_update_rq2a(pr->qp, i); 301 ehea_update_rq2a(pr->qp, adder);
276 else 302 else
277 ehea_update_rq3a(pr->qp, i); 303 ehea_update_rq3a(pr->qp, adder);
278out: 304out:
279 return ret; 305 return ret;
280} 306}
@@ -1967,11 +1993,12 @@ static int ehea_start_xmit(struct sk_buff *skb, struct net_device *dev)
1967 ehea_dump(swqe, 512, "swqe"); 1993 ehea_dump(swqe, 512, "swqe");
1968 } 1994 }
1969 1995
1970 if (unlikely(test_bit(__EHEA_STOP_XFER, &ehea_driver_flags))) 1996 if (unlikely(test_bit(__EHEA_STOP_XFER, &ehea_driver_flags))) {
1971 goto out; 1997 netif_stop_queue(dev);
1998 swqe->tx_control |= EHEA_SWQE_PURGE;
1999 }
1972 2000
1973 ehea_post_swqe(pr->qp, swqe); 2001 ehea_post_swqe(pr->qp, swqe);
1974 pr->tx_packets++;
1975 2002
1976 if (unlikely(atomic_read(&pr->swqe_avail) <= 1)) { 2003 if (unlikely(atomic_read(&pr->swqe_avail) <= 1)) {
1977 spin_lock_irqsave(&pr->netif_queue, flags); 2004 spin_lock_irqsave(&pr->netif_queue, flags);
@@ -1984,7 +2011,7 @@ static int ehea_start_xmit(struct sk_buff *skb, struct net_device *dev)
1984 } 2011 }
1985 dev->trans_start = jiffies; 2012 dev->trans_start = jiffies;
1986 spin_unlock(&pr->xmit_lock); 2013 spin_unlock(&pr->xmit_lock);
1987out: 2014
1988 return NETDEV_TX_OK; 2015 return NETDEV_TX_OK;
1989} 2016}
1990 2017
@@ -2376,6 +2403,192 @@ static int ehea_stop(struct net_device *dev)
2376 return ret; 2403 return ret;
2377} 2404}
2378 2405
2406void ehea_purge_sq(struct ehea_qp *orig_qp)
2407{
2408 struct ehea_qp qp = *orig_qp;
2409 struct ehea_qp_init_attr *init_attr = &qp.init_attr;
2410 struct ehea_swqe *swqe;
2411 int wqe_index;
2412 int i;
2413
2414 for (i = 0; i < init_attr->act_nr_send_wqes; i++) {
2415 swqe = ehea_get_swqe(&qp, &wqe_index);
2416 swqe->tx_control |= EHEA_SWQE_PURGE;
2417 }
2418}
2419
2420int ehea_stop_qps(struct net_device *dev)
2421{
2422 struct ehea_port *port = netdev_priv(dev);
2423 struct ehea_adapter *adapter = port->adapter;
2424 struct hcp_modify_qp_cb0* cb0;
2425 int ret = -EIO;
2426 int dret;
2427 int i;
2428 u64 hret;
2429 u64 dummy64 = 0;
2430 u16 dummy16 = 0;
2431
2432 cb0 = kzalloc(PAGE_SIZE, GFP_KERNEL);
2433 if (!cb0) {
2434 ret = -ENOMEM;
2435 goto out;
2436 }
2437
2438 for (i = 0; i < (port->num_def_qps + port->num_add_tx_qps); i++) {
2439 struct ehea_port_res *pr = &port->port_res[i];
2440 struct ehea_qp *qp = pr->qp;
2441
2442 /* Purge send queue */
2443 ehea_purge_sq(qp);
2444
2445 /* Disable queue pair */
2446 hret = ehea_h_query_ehea_qp(adapter->handle, 0, qp->fw_handle,
2447 EHEA_BMASK_SET(H_QPCB0_ALL, 0xFFFF),
2448 cb0);
2449 if (hret != H_SUCCESS) {
2450 ehea_error("query_ehea_qp failed (1)");
2451 goto out;
2452 }
2453
2454 cb0->qp_ctl_reg = (cb0->qp_ctl_reg & H_QP_CR_RES_STATE) << 8;
2455 cb0->qp_ctl_reg &= ~H_QP_CR_ENABLED;
2456
2457 hret = ehea_h_modify_ehea_qp(adapter->handle, 0, qp->fw_handle,
2458 EHEA_BMASK_SET(H_QPCB0_QP_CTL_REG,
2459 1), cb0, &dummy64,
2460 &dummy64, &dummy16, &dummy16);
2461 if (hret != H_SUCCESS) {
2462 ehea_error("modify_ehea_qp failed (1)");
2463 goto out;
2464 }
2465
2466 hret = ehea_h_query_ehea_qp(adapter->handle, 0, qp->fw_handle,
2467 EHEA_BMASK_SET(H_QPCB0_ALL, 0xFFFF),
2468 cb0);
2469 if (hret != H_SUCCESS) {
2470 ehea_error("query_ehea_qp failed (2)");
2471 goto out;
2472 }
2473
2474 /* deregister shared memory regions */
2475 dret = ehea_rem_smrs(pr);
2476 if (dret) {
2477 ehea_error("unreg shared memory region failed");
2478 goto out;
2479 }
2480 }
2481
2482 ret = 0;
2483out:
2484 kfree(cb0);
2485
2486 return ret;
2487}
2488
2489void ehea_update_rqs(struct ehea_qp *orig_qp, struct ehea_port_res * pr)
2490{
2491 struct ehea_qp qp = *orig_qp;
2492 struct ehea_qp_init_attr *init_attr = &qp.init_attr;
2493 struct ehea_rwqe *rwqe;
2494 struct sk_buff **skba_rq2 = pr->rq2_skba.arr;
2495 struct sk_buff **skba_rq3 = pr->rq3_skba.arr;
2496 struct sk_buff *skb;
2497 u32 lkey = pr->recv_mr.lkey;
2498
2499
2500 int i;
2501 int index;
2502
2503 for (i = 0; i < init_attr->act_nr_rwqes_rq2 + 1; i++) {
2504 rwqe = ehea_get_next_rwqe(&qp, 2);
2505 rwqe->sg_list[0].l_key = lkey;
2506 index = EHEA_BMASK_GET(EHEA_WR_ID_INDEX, rwqe->wr_id);
2507 skb = skba_rq2[index];
2508 if (skb)
2509 rwqe->sg_list[0].vaddr = ehea_map_vaddr(skb->data);
2510 }
2511
2512 for (i = 0; i < init_attr->act_nr_rwqes_rq3 + 1; i++) {
2513 rwqe = ehea_get_next_rwqe(&qp, 3);
2514 rwqe->sg_list[0].l_key = lkey;
2515 index = EHEA_BMASK_GET(EHEA_WR_ID_INDEX, rwqe->wr_id);
2516 skb = skba_rq3[index];
2517 if (skb)
2518 rwqe->sg_list[0].vaddr = ehea_map_vaddr(skb->data);
2519 }
2520}
2521
2522int ehea_restart_qps(struct net_device *dev)
2523{
2524 struct ehea_port *port = netdev_priv(dev);
2525 struct ehea_adapter *adapter = port->adapter;
2526 int ret = 0;
2527 int i;
2528
2529 struct hcp_modify_qp_cb0* cb0;
2530 u64 hret;
2531 u64 dummy64 = 0;
2532 u16 dummy16 = 0;
2533
2534 cb0 = kzalloc(PAGE_SIZE, GFP_KERNEL);
2535 if (!cb0) {
2536 ret = -ENOMEM;
2537 goto out;
2538 }
2539
2540 for (i = 0; i < (port->num_def_qps + port->num_add_tx_qps); i++) {
2541 struct ehea_port_res *pr = &port->port_res[i];
2542 struct ehea_qp *qp = pr->qp;
2543
2544 ret = ehea_gen_smrs(pr);
2545 if (ret) {
2546 ehea_error("creation of shared memory regions failed");
2547 goto out;
2548 }
2549
2550 ehea_update_rqs(qp, pr);
2551
2552 /* Enable queue pair */
2553 hret = ehea_h_query_ehea_qp(adapter->handle, 0, qp->fw_handle,
2554 EHEA_BMASK_SET(H_QPCB0_ALL, 0xFFFF),
2555 cb0);
2556 if (hret != H_SUCCESS) {
2557 ehea_error("query_ehea_qp failed (1)");
2558 goto out;
2559 }
2560
2561 cb0->qp_ctl_reg = (cb0->qp_ctl_reg & H_QP_CR_RES_STATE) << 8;
2562 cb0->qp_ctl_reg |= H_QP_CR_ENABLED;
2563
2564 hret = ehea_h_modify_ehea_qp(adapter->handle, 0, qp->fw_handle,
2565 EHEA_BMASK_SET(H_QPCB0_QP_CTL_REG,
2566 1), cb0, &dummy64,
2567 &dummy64, &dummy16, &dummy16);
2568 if (hret != H_SUCCESS) {
2569 ehea_error("modify_ehea_qp failed (1)");
2570 goto out;
2571 }
2572
2573 hret = ehea_h_query_ehea_qp(adapter->handle, 0, qp->fw_handle,
2574 EHEA_BMASK_SET(H_QPCB0_ALL, 0xFFFF),
2575 cb0);
2576 if (hret != H_SUCCESS) {
2577 ehea_error("query_ehea_qp failed (2)");
2578 goto out;
2579 }
2580
2581 /* refill entire queue */
2582 ehea_refill_rq1(pr, pr->rq1_skba.index, 0);
2583 ehea_refill_rq2(pr, 0);
2584 ehea_refill_rq3(pr, 0);
2585 }
2586out:
2587 kfree(cb0);
2588
2589 return ret;
2590}
2591
2379static void ehea_reset_port(struct work_struct *work) 2592static void ehea_reset_port(struct work_struct *work)
2380{ 2593{
2381 int ret; 2594 int ret;
@@ -2395,6 +2608,8 @@ static void ehea_reset_port(struct work_struct *work)
2395 if (ret) 2608 if (ret)
2396 goto out; 2609 goto out;
2397 2610
2611 ehea_set_multicast_list(dev);
2612
2398 if (netif_msg_timer(port)) 2613 if (netif_msg_timer(port))
2399 ehea_info("Device %s resetted successfully", dev->name); 2614 ehea_info("Device %s resetted successfully", dev->name);
2400 2615
@@ -2411,6 +2626,7 @@ static void ehea_rereg_mrs(struct work_struct *work)
2411 int ret, i; 2626 int ret, i;
2412 struct ehea_adapter *adapter; 2627 struct ehea_adapter *adapter;
2413 2628
2629 down(&dlpar_mem_lock);
2414 ehea_info("LPAR memory enlarged - re-initializing driver"); 2630 ehea_info("LPAR memory enlarged - re-initializing driver");
2415 2631
2416 list_for_each_entry(adapter, &adapter_list, list) 2632 list_for_each_entry(adapter, &adapter_list, list)
@@ -2423,14 +2639,14 @@ static void ehea_rereg_mrs(struct work_struct *work)
2423 struct net_device *dev = port->netdev; 2639 struct net_device *dev = port->netdev;
2424 2640
2425 if (dev->flags & IFF_UP) { 2641 if (dev->flags & IFF_UP) {
2426 ehea_info("stopping %s",
2427 dev->name);
2428 down(&port->port_lock); 2642 down(&port->port_lock);
2429 netif_stop_queue(dev); 2643 netif_stop_queue(dev);
2430 2644 ret = ehea_stop_qps(dev);
2645 if (ret) {
2646 up(&port->port_lock);
2647 goto out;
2648 }
2431 port_napi_disable(port); 2649 port_napi_disable(port);
2432
2433 ehea_down(dev);
2434 up(&port->port_lock); 2650 up(&port->port_lock);
2435 } 2651 }
2436 } 2652 }
@@ -2446,10 +2662,11 @@ static void ehea_rereg_mrs(struct work_struct *work)
2446 } 2662 }
2447 2663
2448 ehea_destroy_busmap(); 2664 ehea_destroy_busmap();
2449
2450 ret = ehea_create_busmap(); 2665 ret = ehea_create_busmap();
2451 if (ret) 2666 if (ret) {
2667 ehea_error("creating ehea busmap failed");
2452 goto out; 2668 goto out;
2669 }
2453 2670
2454 clear_bit(__EHEA_STOP_XFER, &ehea_driver_flags); 2671 clear_bit(__EHEA_STOP_XFER, &ehea_driver_flags);
2455 2672
@@ -2471,21 +2688,18 @@ static void ehea_rereg_mrs(struct work_struct *work)
2471 struct net_device *dev = port->netdev; 2688 struct net_device *dev = port->netdev;
2472 2689
2473 if (dev->flags & IFF_UP) { 2690 if (dev->flags & IFF_UP) {
2474 ehea_info("restarting %s",
2475 dev->name);
2476 down(&port->port_lock); 2691 down(&port->port_lock);
2477 2692 port_napi_enable(port);
2478 ret = ehea_up(dev); 2693 ret = ehea_restart_qps(dev);
2479 if (!ret) { 2694 if (!ret)
2480 port_napi_enable(port);
2481 netif_wake_queue(dev); 2695 netif_wake_queue(dev);
2482 }
2483
2484 up(&port->port_lock); 2696 up(&port->port_lock);
2485 } 2697 }
2486 } 2698 }
2487 } 2699 }
2488 } 2700 }
2701 up(&dlpar_mem_lock);
2702 ehea_info("re-initializing driver complete");
2489out: 2703out:
2490 return; 2704 return;
2491} 2705}
@@ -2494,7 +2708,8 @@ static void ehea_tx_watchdog(struct net_device *dev)
2494{ 2708{
2495 struct ehea_port *port = netdev_priv(dev); 2709 struct ehea_port *port = netdev_priv(dev);
2496 2710
2497 if (netif_carrier_ok(dev)) 2711 if (netif_carrier_ok(dev) &&
2712 !test_bit(__EHEA_STOP_XFER, &ehea_driver_flags))
2498 queue_work(port->adapter->ehea_wq, &port->reset_task); 2713 queue_work(port->adapter->ehea_wq, &port->reset_task);
2499} 2714}
2500 2715
@@ -3139,6 +3354,7 @@ int __init ehea_module_init(void)
3139 ehea_driver_wq = create_workqueue("ehea_driver_wq"); 3354 ehea_driver_wq = create_workqueue("ehea_driver_wq");
3140 3355
3141 INIT_WORK(&ehea_rereg_mr_task, ehea_rereg_mrs); 3356 INIT_WORK(&ehea_rereg_mr_task, ehea_rereg_mrs);
3357 sema_init(&dlpar_mem_lock, 1);
3142 3358
3143 ret = check_module_parm(); 3359 ret = check_module_parm();
3144 if (ret) 3360 if (ret)