diff options
| -rw-r--r-- | drivers/net/ehea/ehea.h | 9 | ||||
| -rw-r--r-- | drivers/net/ehea/ehea_main.c | 439 |
2 files changed, 323 insertions, 125 deletions
diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h index 42295d61ecd8..e595d6b38e7c 100644 --- a/drivers/net/ehea/ehea.h +++ b/drivers/net/ehea/ehea.h | |||
| @@ -39,7 +39,7 @@ | |||
| 39 | #include <asm/io.h> | 39 | #include <asm/io.h> |
| 40 | 40 | ||
| 41 | #define DRV_NAME "ehea" | 41 | #define DRV_NAME "ehea" |
| 42 | #define DRV_VERSION "EHEA_0046" | 42 | #define DRV_VERSION "EHEA_0048" |
| 43 | 43 | ||
| 44 | #define EHEA_MSG_DEFAULT (NETIF_MSG_LINK | NETIF_MSG_TIMER \ | 44 | #define EHEA_MSG_DEFAULT (NETIF_MSG_LINK | NETIF_MSG_TIMER \ |
| 45 | | NETIF_MSG_RX_ERR | NETIF_MSG_TX_ERR) | 45 | | NETIF_MSG_RX_ERR | NETIF_MSG_TX_ERR) |
| @@ -380,10 +380,11 @@ struct ehea_port_res { | |||
| 380 | }; | 380 | }; |
| 381 | 381 | ||
| 382 | 382 | ||
| 383 | #define EHEA_MAX_PORTS 16 | ||
| 383 | struct ehea_adapter { | 384 | struct ehea_adapter { |
| 384 | u64 handle; | 385 | u64 handle; |
| 385 | u8 num_ports; | 386 | struct ibmebus_dev *ebus_dev; |
| 386 | struct ehea_port *port[16]; | 387 | struct ehea_port *port[EHEA_MAX_PORTS]; |
| 387 | struct ehea_eq *neq; /* notification event queue */ | 388 | struct ehea_eq *neq; /* notification event queue */ |
| 388 | struct workqueue_struct *ehea_wq; | 389 | struct workqueue_struct *ehea_wq; |
| 389 | struct tasklet_struct neq_tasklet; | 390 | struct tasklet_struct neq_tasklet; |
| @@ -406,7 +407,7 @@ struct ehea_port { | |||
| 406 | struct net_device *netdev; | 407 | struct net_device *netdev; |
| 407 | struct net_device_stats stats; | 408 | struct net_device_stats stats; |
| 408 | struct ehea_port_res port_res[EHEA_MAX_PORT_RES]; | 409 | struct ehea_port_res port_res[EHEA_MAX_PORT_RES]; |
| 409 | struct device_node *of_dev_node; /* Open Firmware Device Node */ | 410 | struct of_device ofdev; /* Open Firmware Device */ |
| 410 | struct ehea_mc_list *mc_list; /* Multicast MAC addresses */ | 411 | struct ehea_mc_list *mc_list; /* Multicast MAC addresses */ |
| 411 | struct vlan_group *vgrp; | 412 | struct vlan_group *vgrp; |
| 412 | struct ehea_eq *qp_eq; | 413 | struct ehea_eq *qp_eq; |
diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c index 58364a0ff378..3527b391214d 100644 --- a/drivers/net/ehea/ehea_main.c +++ b/drivers/net/ehea/ehea_main.c | |||
| @@ -580,7 +580,7 @@ static struct ehea_port *ehea_get_port(struct ehea_adapter *adapter, | |||
| 580 | { | 580 | { |
| 581 | int i; | 581 | int i; |
| 582 | 582 | ||
| 583 | for (i = 0; i < adapter->num_ports; i++) | 583 | for (i = 0; i < EHEA_MAX_PORTS; i++) |
| 584 | if (adapter->port[i]) | 584 | if (adapter->port[i]) |
| 585 | if (adapter->port[i]->logical_port_id == logical_port) | 585 | if (adapter->port[i]->logical_port_id == logical_port) |
| 586 | return adapter->port[i]; | 586 | return adapter->port[i]; |
| @@ -2276,8 +2276,6 @@ static void ehea_tx_watchdog(struct net_device *dev) | |||
| 2276 | int ehea_sense_adapter_attr(struct ehea_adapter *adapter) | 2276 | int ehea_sense_adapter_attr(struct ehea_adapter *adapter) |
| 2277 | { | 2277 | { |
| 2278 | struct hcp_query_ehea *cb; | 2278 | struct hcp_query_ehea *cb; |
| 2279 | struct device_node *lhea_dn = NULL; | ||
| 2280 | struct device_node *eth_dn = NULL; | ||
| 2281 | u64 hret; | 2279 | u64 hret; |
| 2282 | int ret; | 2280 | int ret; |
| 2283 | 2281 | ||
| @@ -2294,18 +2292,6 @@ int ehea_sense_adapter_attr(struct ehea_adapter *adapter) | |||
| 2294 | goto out_herr; | 2292 | goto out_herr; |
| 2295 | } | 2293 | } |
| 2296 | 2294 | ||
| 2297 | /* Determine the number of available logical ports | ||
| 2298 | * by counting the child nodes of the lhea OFDT entry | ||
| 2299 | */ | ||
| 2300 | adapter->num_ports = 0; | ||
| 2301 | lhea_dn = of_find_node_by_name(lhea_dn, "lhea"); | ||
| 2302 | do { | ||
| 2303 | eth_dn = of_get_next_child(lhea_dn, eth_dn); | ||
| 2304 | if (eth_dn) | ||
| 2305 | adapter->num_ports++; | ||
| 2306 | } while ( eth_dn ); | ||
| 2307 | of_node_put(lhea_dn); | ||
| 2308 | |||
| 2309 | adapter->max_mc_mac = cb->max_mc_mac - 1; | 2295 | adapter->max_mc_mac = cb->max_mc_mac - 1; |
| 2310 | ret = 0; | 2296 | ret = 0; |
| 2311 | 2297 | ||
| @@ -2315,79 +2301,150 @@ out: | |||
| 2315 | return ret; | 2301 | return ret; |
| 2316 | } | 2302 | } |
| 2317 | 2303 | ||
| 2318 | static int ehea_setup_single_port(struct ehea_port *port, | 2304 | int ehea_get_jumboframe_status(struct ehea_port *port, int *jumbo) |
| 2319 | struct device_node *dn) | ||
| 2320 | { | 2305 | { |
| 2321 | int ret; | ||
| 2322 | u64 hret; | ||
| 2323 | struct net_device *dev = port->netdev; | ||
| 2324 | struct ehea_adapter *adapter = port->adapter; | ||
| 2325 | struct hcp_ehea_port_cb4 *cb4; | 2306 | struct hcp_ehea_port_cb4 *cb4; |
| 2326 | u32 *dn_log_port_id; | 2307 | u64 hret; |
| 2327 | int jumbo = 0; | 2308 | int ret = 0; |
| 2328 | |||
| 2329 | sema_init(&port->port_lock, 1); | ||
| 2330 | port->state = EHEA_PORT_DOWN; | ||
| 2331 | port->sig_comp_iv = sq_entries / 10; | ||
| 2332 | |||
| 2333 | if (!dn) { | ||
| 2334 | ehea_error("bad device node: dn=%p", dn); | ||
| 2335 | ret = -EINVAL; | ||
| 2336 | goto out; | ||
| 2337 | } | ||
| 2338 | |||
| 2339 | port->of_dev_node = dn; | ||
| 2340 | |||
| 2341 | /* Determine logical port id */ | ||
| 2342 | dn_log_port_id = (u32*)get_property(dn, "ibm,hea-port-no", NULL); | ||
| 2343 | |||
| 2344 | if (!dn_log_port_id) { | ||
| 2345 | ehea_error("bad device node: dn_log_port_id=%p", | ||
| 2346 | dn_log_port_id); | ||
| 2347 | ret = -EINVAL; | ||
| 2348 | goto out; | ||
| 2349 | } | ||
| 2350 | port->logical_port_id = *dn_log_port_id; | ||
| 2351 | |||
| 2352 | port->mc_list = kzalloc(sizeof(struct ehea_mc_list), GFP_KERNEL); | ||
| 2353 | if (!port->mc_list) { | ||
| 2354 | ret = -ENOMEM; | ||
| 2355 | goto out; | ||
| 2356 | } | ||
| 2357 | |||
| 2358 | INIT_LIST_HEAD(&port->mc_list->list); | ||
| 2359 | 2309 | ||
| 2360 | ret = ehea_sense_port_attr(port); | 2310 | *jumbo = 0; |
| 2361 | if (ret) | ||
| 2362 | goto out; | ||
| 2363 | 2311 | ||
| 2364 | /* Enable Jumbo frames */ | 2312 | /* (Try to) enable *jumbo frames */ |
| 2365 | cb4 = kzalloc(PAGE_SIZE, GFP_KERNEL); | 2313 | cb4 = kzalloc(PAGE_SIZE, GFP_KERNEL); |
| 2366 | if (!cb4) { | 2314 | if (!cb4) { |
| 2367 | ehea_error("no mem for cb4"); | 2315 | ehea_error("no mem for cb4"); |
| 2316 | ret = -ENOMEM; | ||
| 2317 | goto out; | ||
| 2368 | } else { | 2318 | } else { |
| 2369 | hret = ehea_h_query_ehea_port(adapter->handle, | 2319 | hret = ehea_h_query_ehea_port(port->adapter->handle, |
| 2370 | port->logical_port_id, | 2320 | port->logical_port_id, |
| 2371 | H_PORT_CB4, | 2321 | H_PORT_CB4, |
| 2372 | H_PORT_CB4_JUMBO, cb4); | 2322 | H_PORT_CB4_JUMBO, cb4); |
| 2373 | |||
| 2374 | if (hret == H_SUCCESS) { | 2323 | if (hret == H_SUCCESS) { |
| 2375 | if (cb4->jumbo_frame) | 2324 | if (cb4->jumbo_frame) |
| 2376 | jumbo = 1; | 2325 | *jumbo = 1; |
| 2377 | else { | 2326 | else { |
| 2378 | cb4->jumbo_frame = 1; | 2327 | cb4->jumbo_frame = 1; |
| 2379 | hret = ehea_h_modify_ehea_port(adapter->handle, | 2328 | hret = ehea_h_modify_ehea_port(port->adapter-> |
| 2329 | handle, | ||
| 2380 | port-> | 2330 | port-> |
| 2381 | logical_port_id, | 2331 | logical_port_id, |
| 2382 | H_PORT_CB4, | 2332 | H_PORT_CB4, |
| 2383 | H_PORT_CB4_JUMBO, | 2333 | H_PORT_CB4_JUMBO, |
| 2384 | cb4); | 2334 | cb4); |
| 2385 | if (hret == H_SUCCESS) | 2335 | if (hret == H_SUCCESS) |
| 2386 | jumbo = 1; | 2336 | *jumbo = 1; |
| 2387 | } | 2337 | } |
| 2388 | } | 2338 | } else |
| 2339 | ret = -EINVAL; | ||
| 2340 | |||
| 2389 | kfree(cb4); | 2341 | kfree(cb4); |
| 2390 | } | 2342 | } |
| 2343 | out: | ||
| 2344 | return ret; | ||
| 2345 | } | ||
| 2346 | |||
| 2347 | static ssize_t ehea_show_port_id(struct device *dev, | ||
| 2348 | struct device_attribute *attr, char *buf) | ||
| 2349 | { | ||
| 2350 | struct ehea_port *port = container_of(dev, struct ehea_port, ofdev.dev); | ||
| 2351 | return sprintf(buf, "0x%X", port->logical_port_id); | ||
| 2352 | } | ||
| 2353 | |||
| 2354 | static DEVICE_ATTR(log_port_id, S_IRUSR | S_IRGRP | S_IROTH, ehea_show_port_id, | ||
| 2355 | NULL); | ||
| 2356 | |||
| 2357 | static void __devinit logical_port_release(struct device *dev) | ||
| 2358 | { | ||
| 2359 | struct ehea_port *port = container_of(dev, struct ehea_port, ofdev.dev); | ||
| 2360 | of_node_put(port->ofdev.node); | ||
| 2361 | } | ||
| 2362 | |||
| 2363 | static struct device *ehea_register_port(struct ehea_port *port, | ||
| 2364 | struct device_node *dn) | ||
| 2365 | { | ||
| 2366 | int ret; | ||
| 2367 | |||
| 2368 | port->ofdev.node = of_node_get(dn); | ||
| 2369 | port->ofdev.dev.parent = &port->adapter->ebus_dev->ofdev.dev; | ||
| 2370 | |||
| 2371 | sprintf(port->ofdev.dev.bus_id, "port%d", port->logical_port_id); | ||
| 2372 | port->ofdev.dev.release = logical_port_release; | ||
| 2373 | |||
| 2374 | ret = of_device_register(&port->ofdev); | ||
| 2375 | if (ret) { | ||
| 2376 | ehea_error("failed to register device. ret=%d", ret); | ||
| 2377 | goto out; | ||
| 2378 | } | ||
| 2379 | |||
| 2380 | ret = device_create_file(&port->ofdev.dev, &dev_attr_log_port_id); | ||
| 2381 | if (ret) { | ||
| 2382 | ehea_error("failed to register attributes, ret=%d", ret); | ||
| 2383 | goto out_unreg_of_dev; | ||
| 2384 | } | ||
| 2385 | |||
| 2386 | return &port->ofdev.dev; | ||
| 2387 | |||
| 2388 | out_unreg_of_dev: | ||
| 2389 | of_device_unregister(&port->ofdev); | ||
| 2390 | out: | ||
| 2391 | return NULL; | ||
| 2392 | } | ||
| 2393 | |||
| 2394 | static void ehea_unregister_port(struct ehea_port *port) | ||
| 2395 | { | ||
| 2396 | device_remove_file(&port->ofdev.dev, &dev_attr_log_port_id); | ||
| 2397 | of_device_unregister(&port->ofdev); | ||
| 2398 | } | ||
| 2399 | |||
| 2400 | struct ehea_port *ehea_setup_single_port(struct ehea_adapter *adapter, | ||
| 2401 | u32 logical_port_id, | ||
| 2402 | struct device_node *dn) | ||
| 2403 | { | ||
| 2404 | int ret; | ||
| 2405 | struct net_device *dev; | ||
| 2406 | struct ehea_port *port; | ||
| 2407 | struct device *port_dev; | ||
| 2408 | int jumbo; | ||
| 2409 | |||
| 2410 | /* allocate memory for the port structures */ | ||
| 2411 | dev = alloc_etherdev(sizeof(struct ehea_port)); | ||
| 2412 | |||
| 2413 | if (!dev) { | ||
| 2414 | ehea_error("no mem for net_device"); | ||
| 2415 | ret = -ENOMEM; | ||
| 2416 | goto out_err; | ||
| 2417 | } | ||
| 2418 | |||
| 2419 | port = netdev_priv(dev); | ||
| 2420 | |||
| 2421 | sema_init(&port->port_lock, 1); | ||
| 2422 | port->state = EHEA_PORT_DOWN; | ||
| 2423 | port->sig_comp_iv = sq_entries / 10; | ||
| 2424 | |||
| 2425 | port->adapter = adapter; | ||
| 2426 | port->netdev = dev; | ||
| 2427 | port->logical_port_id = logical_port_id; | ||
| 2428 | |||
| 2429 | port->msg_enable = netif_msg_init(msg_level, EHEA_MSG_DEFAULT); | ||
| 2430 | |||
| 2431 | port->mc_list = kzalloc(sizeof(struct ehea_mc_list), GFP_KERNEL); | ||
| 2432 | if (!port->mc_list) { | ||
| 2433 | ret = -ENOMEM; | ||
| 2434 | goto out_free_ethdev; | ||
| 2435 | } | ||
| 2436 | |||
| 2437 | INIT_LIST_HEAD(&port->mc_list->list); | ||
| 2438 | |||
| 2439 | ret = ehea_sense_port_attr(port); | ||
| 2440 | if (ret) | ||
| 2441 | goto out_free_mc_list; | ||
| 2442 | |||
| 2443 | port_dev = ehea_register_port(port, dn); | ||
| 2444 | if (!port_dev) | ||
| 2445 | goto out_free_mc_list; | ||
| 2446 | |||
| 2447 | SET_NETDEV_DEV(dev, port_dev); | ||
| 2391 | 2448 | ||
| 2392 | /* initialize net_device structure */ | 2449 | /* initialize net_device structure */ |
| 2393 | SET_MODULE_OWNER(dev); | 2450 | SET_MODULE_OWNER(dev); |
| @@ -2420,79 +2477,216 @@ static int ehea_setup_single_port(struct ehea_port *port, | |||
| 2420 | ret = register_netdev(dev); | 2477 | ret = register_netdev(dev); |
| 2421 | if (ret) { | 2478 | if (ret) { |
| 2422 | ehea_error("register_netdev failed. ret=%d", ret); | 2479 | ehea_error("register_netdev failed. ret=%d", ret); |
| 2423 | goto out_free; | 2480 | goto out_unreg_port; |
| 2424 | } | 2481 | } |
| 2425 | 2482 | ||
| 2483 | ret = ehea_get_jumboframe_status(port, &jumbo); | ||
| 2484 | if (ret) | ||
| 2485 | ehea_error("failed determining jumbo frame status for %s", | ||
| 2486 | port->netdev->name); | ||
| 2487 | |||
| 2426 | ehea_info("%s: Jumbo frames are %sabled", dev->name, | 2488 | ehea_info("%s: Jumbo frames are %sabled", dev->name, |
| 2427 | jumbo == 1 ? "en" : "dis"); | 2489 | jumbo == 1 ? "en" : "dis"); |
| 2428 | 2490 | ||
| 2429 | port->netdev = dev; | 2491 | return port; |
| 2430 | ret = 0; | ||
| 2431 | goto out; | ||
| 2432 | 2492 | ||
| 2433 | out_free: | 2493 | out_unreg_port: |
| 2494 | ehea_unregister_port(port); | ||
| 2495 | |||
| 2496 | out_free_mc_list: | ||
| 2434 | kfree(port->mc_list); | 2497 | kfree(port->mc_list); |
| 2435 | out: | 2498 | |
| 2436 | return ret; | 2499 | out_free_ethdev: |
| 2500 | free_netdev(dev); | ||
| 2501 | |||
| 2502 | out_err: | ||
| 2503 | ehea_error("setting up logical port with id=%d failed, ret=%d", | ||
| 2504 | logical_port_id, ret); | ||
| 2505 | return NULL; | ||
| 2506 | } | ||
| 2507 | |||
| 2508 | static void ehea_shutdown_single_port(struct ehea_port *port) | ||
| 2509 | { | ||
| 2510 | unregister_netdev(port->netdev); | ||
| 2511 | ehea_unregister_port(port); | ||
| 2512 | kfree(port->mc_list); | ||
| 2513 | free_netdev(port->netdev); | ||
| 2437 | } | 2514 | } |
| 2438 | 2515 | ||
| 2439 | static int ehea_setup_ports(struct ehea_adapter *adapter) | 2516 | static int ehea_setup_ports(struct ehea_adapter *adapter) |
| 2440 | { | 2517 | { |
| 2441 | int ret; | 2518 | struct device_node *lhea_dn; |
| 2519 | struct device_node *eth_dn = NULL; | ||
| 2520 | |||
| 2521 | u32 *dn_log_port_id; | ||
| 2442 | int port_setup_ok = 0; | 2522 | int port_setup_ok = 0; |
| 2443 | struct ehea_port *port; | 2523 | int i = 0; |
| 2444 | struct device_node *dn = NULL; | 2524 | |
| 2445 | struct net_device *dev; | 2525 | lhea_dn = adapter->ebus_dev->ofdev.node; |
| 2446 | int i; | 2526 | do { |
| 2527 | eth_dn = of_get_next_child(lhea_dn, eth_dn); | ||
| 2528 | if (!eth_dn) | ||
| 2529 | break; | ||
| 2447 | 2530 | ||
| 2448 | /* get port properties for all ports */ | 2531 | dn_log_port_id = (u32*)get_property(eth_dn, "ibm,hea-port-no", |
| 2449 | for (i = 0; i < adapter->num_ports; i++) { | 2532 | NULL); |
| 2533 | if (!dn_log_port_id) { | ||
| 2534 | ehea_error("bad device node: eth_dn name=%s", | ||
| 2535 | eth_dn->full_name); | ||
| 2536 | continue; | ||
| 2537 | } | ||
| 2450 | 2538 | ||
| 2539 | adapter->port[i] = ehea_setup_single_port(adapter, | ||
| 2540 | *dn_log_port_id, | ||
| 2541 | eth_dn); | ||
| 2451 | if (adapter->port[i]) | 2542 | if (adapter->port[i]) |
| 2452 | continue; /* port already up and running */ | 2543 | ehea_info("%s -> logical port id #%d", |
| 2544 | adapter->port[i]->netdev->name, | ||
| 2545 | *dn_log_port_id); | ||
| 2546 | i++; | ||
| 2547 | } while (eth_dn); | ||
| 2548 | |||
| 2549 | of_node_put(lhea_dn); | ||
| 2453 | 2550 | ||
| 2454 | /* allocate memory for the port structures */ | 2551 | /* Check for succesfully set up ports */ |
| 2455 | dev = alloc_etherdev(sizeof(struct ehea_port)); | 2552 | for (i = 0; i < EHEA_MAX_PORTS; i++) |
| 2553 | if (adapter->port[i]) | ||
| 2554 | port_setup_ok++; | ||
| 2456 | 2555 | ||
| 2457 | if (!dev) { | 2556 | if (port_setup_ok) |
| 2458 | ehea_error("no mem for net_device"); | 2557 | return 0; /* At least some ports are setup correctly */ |
| 2558 | |||
| 2559 | return -EINVAL; | ||
| 2560 | } | ||
| 2561 | |||
| 2562 | static struct device_node *ehea_get_eth_dn(struct ehea_adapter *adapter, | ||
| 2563 | u32 logical_port_id) | ||
| 2564 | { | ||
| 2565 | struct device_node *lhea_dn; | ||
| 2566 | struct device_node *eth_dn = NULL; | ||
| 2567 | u32 *dn_log_port_id; | ||
| 2568 | |||
| 2569 | lhea_dn = adapter->ebus_dev->ofdev.node; | ||
| 2570 | do { | ||
| 2571 | eth_dn = of_get_next_child(lhea_dn, eth_dn); | ||
| 2572 | if (!eth_dn) | ||
| 2459 | break; | 2573 | break; |
| 2460 | } | ||
| 2461 | 2574 | ||
| 2462 | port = netdev_priv(dev); | 2575 | dn_log_port_id = (u32*)get_property(eth_dn, "ibm,hea-port-no", |
| 2463 | port->adapter = adapter; | 2576 | NULL); |
| 2464 | port->netdev = dev; | ||
| 2465 | adapter->port[i] = port; | ||
| 2466 | port->msg_enable = netif_msg_init(msg_level, EHEA_MSG_DEFAULT); | ||
| 2467 | 2577 | ||
| 2468 | dn = of_find_node_by_name(dn, "ethernet"); | 2578 | if (dn_log_port_id) |
| 2469 | ret = ehea_setup_single_port(port, dn); | 2579 | if (*dn_log_port_id == logical_port_id) |
| 2470 | if (ret) { | 2580 | return eth_dn; |
| 2471 | /* Free mem for this port struct. The others will be | 2581 | |
| 2472 | processed on rollback */ | 2582 | } while (eth_dn); |
| 2473 | free_netdev(dev); | 2583 | |
| 2474 | adapter->port[i] = NULL; | 2584 | of_node_put(lhea_dn); |
| 2475 | ehea_error("eHEA port %d setup failed, ret=%d", i, ret); | 2585 | |
| 2476 | } | 2586 | return NULL; |
| 2587 | } | ||
| 2588 | |||
| 2589 | static ssize_t ehea_probe_port(struct device *dev, | ||
| 2590 | struct device_attribute *attr, | ||
| 2591 | const char *buf, size_t count) | ||
| 2592 | { | ||
| 2593 | struct ehea_adapter *adapter = dev->driver_data; | ||
| 2594 | struct ehea_port *port; | ||
| 2595 | struct device_node *eth_dn = NULL; | ||
| 2596 | int i; | ||
| 2597 | |||
| 2598 | u32 logical_port_id; | ||
| 2599 | |||
| 2600 | sscanf(buf, "%X", &logical_port_id); | ||
| 2601 | |||
| 2602 | port = ehea_get_port(adapter, logical_port_id); | ||
| 2603 | |||
| 2604 | if (port) { | ||
| 2605 | ehea_info("adding port with logical port id=%d failed. port " | ||
| 2606 | "already configured as %s.", logical_port_id, | ||
| 2607 | port->netdev->name); | ||
| 2608 | return -EINVAL; | ||
| 2477 | } | 2609 | } |
| 2610 | |||
| 2611 | eth_dn = ehea_get_eth_dn(adapter, logical_port_id); | ||
| 2478 | 2612 | ||
| 2479 | of_node_put(dn); | 2613 | if (!eth_dn) { |
| 2614 | ehea_info("no logical port with id %d found", logical_port_id); | ||
| 2615 | return -EINVAL; | ||
| 2616 | } | ||
| 2617 | |||
| 2618 | port = ehea_setup_single_port(adapter, logical_port_id, eth_dn); | ||
| 2480 | 2619 | ||
| 2481 | /* Check for succesfully set up ports */ | 2620 | if (port) { |
| 2482 | for (i = 0; i < adapter->num_ports; i++) | 2621 | for (i=0; i < EHEA_MAX_PORTS; i++) |
| 2483 | if (adapter->port[i]) | 2622 | if (!adapter->port[i]) { |
| 2484 | port_setup_ok++; | 2623 | adapter->port[i] = port; |
| 2624 | break; | ||
| 2625 | } | ||
| 2485 | 2626 | ||
| 2486 | if (port_setup_ok) | 2627 | ehea_info("added %s (logical port id=%d)", port->netdev->name, |
| 2487 | ret = 0; /* At least some ports are setup correctly */ | 2628 | logical_port_id); |
| 2488 | else | 2629 | } else |
| 2489 | ret = -EINVAL; | 2630 | return -EIO; |
| 2490 | 2631 | ||
| 2632 | return (ssize_t) count; | ||
| 2633 | } | ||
| 2634 | |||
| 2635 | static ssize_t ehea_remove_port(struct device *dev, | ||
| 2636 | struct device_attribute *attr, | ||
| 2637 | const char *buf, size_t count) | ||
| 2638 | { | ||
| 2639 | struct ehea_adapter *adapter = dev->driver_data; | ||
| 2640 | struct ehea_port *port; | ||
| 2641 | int i; | ||
| 2642 | u32 logical_port_id; | ||
| 2643 | |||
| 2644 | sscanf(buf, "%X", &logical_port_id); | ||
| 2645 | |||
| 2646 | port = ehea_get_port(adapter, logical_port_id); | ||
| 2647 | |||
| 2648 | if (port) { | ||
| 2649 | ehea_info("removed %s (logical port id=%d)", port->netdev->name, | ||
| 2650 | logical_port_id); | ||
| 2651 | |||
| 2652 | ehea_shutdown_single_port(port); | ||
| 2653 | |||
| 2654 | for (i=0; i < EHEA_MAX_PORTS; i++) | ||
| 2655 | if (adapter->port[i] == port) { | ||
| 2656 | adapter->port[i] = NULL; | ||
| 2657 | break; | ||
| 2658 | } | ||
| 2659 | } else { | ||
| 2660 | ehea_error("removing port with logical port id=%d failed. port " | ||
| 2661 | "not configured.", logical_port_id); | ||
| 2662 | return -EINVAL; | ||
| 2663 | } | ||
| 2664 | |||
| 2665 | return (ssize_t) count; | ||
| 2666 | } | ||
| 2667 | |||
| 2668 | static DEVICE_ATTR(probe_port, S_IWUSR, NULL, ehea_probe_port); | ||
| 2669 | static DEVICE_ATTR(remove_port, S_IWUSR, NULL, ehea_remove_port); | ||
| 2670 | |||
| 2671 | int ehea_create_device_sysfs(struct ibmebus_dev *dev) | ||
| 2672 | { | ||
| 2673 | int ret = device_create_file(&dev->ofdev.dev, &dev_attr_probe_port); | ||
| 2674 | if (ret) | ||
| 2675 | goto out; | ||
| 2676 | |||
| 2677 | ret = device_create_file(&dev->ofdev.dev, &dev_attr_remove_port); | ||
| 2678 | out: | ||
| 2491 | return ret; | 2679 | return ret; |
| 2492 | } | 2680 | } |
| 2493 | 2681 | ||
| 2494 | static int __devinit ehea_probe(struct ibmebus_dev *dev, | 2682 | void ehea_remove_device_sysfs(struct ibmebus_dev *dev) |
| 2495 | const struct of_device_id *id) | 2683 | { |
| 2684 | device_remove_file(&dev->ofdev.dev, &dev_attr_probe_port); | ||
| 2685 | device_remove_file(&dev->ofdev.dev, &dev_attr_remove_port); | ||
| 2686 | } | ||
| 2687 | |||
| 2688 | static int __devinit ehea_probe_adapter(struct ibmebus_dev *dev, | ||
| 2689 | const struct of_device_id *id) | ||
| 2496 | { | 2690 | { |
| 2497 | struct ehea_adapter *adapter; | 2691 | struct ehea_adapter *adapter; |
| 2498 | u64 *adapter_handle; | 2692 | u64 *adapter_handle; |
| @@ -2505,6 +2699,8 @@ static int __devinit ehea_probe(struct ibmebus_dev *dev, | |||
| 2505 | goto out; | 2699 | goto out; |
| 2506 | } | 2700 | } |
| 2507 | 2701 | ||
| 2702 | adapter->ebus_dev = dev; | ||
| 2703 | |||
| 2508 | adapter_handle = (u64*)get_property(dev->ofdev.node, "ibm,hea-handle", | 2704 | adapter_handle = (u64*)get_property(dev->ofdev.node, "ibm,hea-handle", |
| 2509 | NULL); | 2705 | NULL); |
| 2510 | if (adapter_handle) | 2706 | if (adapter_handle) |
| @@ -2534,7 +2730,6 @@ static int __devinit ehea_probe(struct ibmebus_dev *dev, | |||
| 2534 | dev_err(&dev->ofdev.dev, "sense_adapter_attr failed: %d", ret); | 2730 | dev_err(&dev->ofdev.dev, "sense_adapter_attr failed: %d", ret); |
| 2535 | goto out_free_res; | 2731 | goto out_free_res; |
| 2536 | } | 2732 | } |
| 2537 | dev_info(&dev->ofdev.dev, "%d eHEA ports found\n", adapter->num_ports); | ||
| 2538 | 2733 | ||
| 2539 | adapter->neq = ehea_create_eq(adapter, | 2734 | adapter->neq = ehea_create_eq(adapter, |
| 2540 | EHEA_NEQ, EHEA_MAX_ENTRIES_EQ, 1); | 2735 | EHEA_NEQ, EHEA_MAX_ENTRIES_EQ, 1); |
| @@ -2558,15 +2753,21 @@ static int __devinit ehea_probe(struct ibmebus_dev *dev, | |||
| 2558 | if (!adapter->ehea_wq) | 2753 | if (!adapter->ehea_wq) |
| 2559 | goto out_free_irq; | 2754 | goto out_free_irq; |
| 2560 | 2755 | ||
| 2756 | if (ehea_create_device_sysfs(dev)) | ||
| 2757 | goto out_kill_wq; | ||
| 2758 | |||
| 2561 | ret = ehea_setup_ports(adapter); | 2759 | ret = ehea_setup_ports(adapter); |
| 2562 | if (ret) { | 2760 | if (ret) { |
| 2563 | dev_err(&dev->ofdev.dev, "setup_ports failed"); | 2761 | dev_err(&dev->ofdev.dev, "setup_ports failed"); |
| 2564 | goto out_kill_wq; | 2762 | goto out_rem_dev_sysfs; |
| 2565 | } | 2763 | } |
| 2566 | 2764 | ||
| 2567 | ret = 0; | 2765 | ret = 0; |
| 2568 | goto out; | 2766 | goto out; |
| 2569 | 2767 | ||
| 2768 | out_rem_dev_sysfs: | ||
| 2769 | ehea_remove_device_sysfs(dev); | ||
| 2770 | |||
| 2570 | out_kill_wq: | 2771 | out_kill_wq: |
| 2571 | destroy_workqueue(adapter->ehea_wq); | 2772 | destroy_workqueue(adapter->ehea_wq); |
| 2572 | 2773 | ||
| @@ -2585,24 +2786,20 @@ out: | |||
| 2585 | return ret; | 2786 | return ret; |
| 2586 | } | 2787 | } |
| 2587 | 2788 | ||
| 2588 | static void ehea_shutdown_single_port(struct ehea_port *port) | ||
| 2589 | { | ||
| 2590 | unregister_netdev(port->netdev); | ||
| 2591 | kfree(port->mc_list); | ||
| 2592 | free_netdev(port->netdev); | ||
| 2593 | } | ||
| 2594 | |||
| 2595 | static int __devexit ehea_remove(struct ibmebus_dev *dev) | 2789 | static int __devexit ehea_remove(struct ibmebus_dev *dev) |
| 2596 | { | 2790 | { |
| 2597 | struct ehea_adapter *adapter = dev->ofdev.dev.driver_data; | 2791 | struct ehea_adapter *adapter = dev->ofdev.dev.driver_data; |
| 2598 | u64 hret; | 2792 | u64 hret; |
| 2599 | int i; | 2793 | int i; |
| 2600 | 2794 | ||
| 2601 | for (i = 0; i < adapter->num_ports; i++) | 2795 | for (i = 0; i < EHEA_MAX_PORTS; i++) |
| 2602 | if (adapter->port[i]) { | 2796 | if (adapter->port[i]) { |
| 2603 | ehea_shutdown_single_port(adapter->port[i]); | 2797 | ehea_shutdown_single_port(adapter->port[i]); |
| 2604 | adapter->port[i] = NULL; | 2798 | adapter->port[i] = NULL; |
| 2605 | } | 2799 | } |
| 2800 | |||
| 2801 | ehea_remove_device_sysfs(dev); | ||
| 2802 | |||
| 2606 | destroy_workqueue(adapter->ehea_wq); | 2803 | destroy_workqueue(adapter->ehea_wq); |
| 2607 | 2804 | ||
| 2608 | ibmebus_free_irq(NULL, adapter->neq->attr.ist1, adapter); | 2805 | ibmebus_free_irq(NULL, adapter->neq->attr.ist1, adapter); |
| @@ -2658,7 +2855,7 @@ static struct of_device_id ehea_device_table[] = { | |||
| 2658 | static struct ibmebus_driver ehea_driver = { | 2855 | static struct ibmebus_driver ehea_driver = { |
| 2659 | .name = "ehea", | 2856 | .name = "ehea", |
| 2660 | .id_table = ehea_device_table, | 2857 | .id_table = ehea_device_table, |
| 2661 | .probe = ehea_probe, | 2858 | .probe = ehea_probe_adapter, |
| 2662 | .remove = ehea_remove, | 2859 | .remove = ehea_remove, |
| 2663 | }; | 2860 | }; |
| 2664 | 2861 | ||
