diff options
Diffstat (limited to 'drivers/net/netxen/netxen_nic_hw.c')
-rw-r--r-- | drivers/net/netxen/netxen_nic_hw.c | 198 |
1 files changed, 183 insertions, 15 deletions
diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c index d46b4dff783d..9d4e9c9dbe0a 100644 --- a/drivers/net/netxen/netxen_nic_hw.c +++ b/drivers/net/netxen/netxen_nic_hw.c | |||
@@ -314,8 +314,10 @@ int netxen_nic_set_mac(struct net_device *netdev, void *p) | |||
314 | 314 | ||
315 | memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); | 315 | memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); |
316 | 316 | ||
317 | if (adapter->macaddr_set) | 317 | /* For P3, MAC addr is not set in NIU */ |
318 | adapter->macaddr_set(adapter, addr->sa_data); | 318 | if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) |
319 | if (adapter->macaddr_set) | ||
320 | adapter->macaddr_set(adapter, addr->sa_data); | ||
319 | 321 | ||
320 | return 0; | 322 | return 0; |
321 | } | 323 | } |
@@ -405,10 +407,7 @@ netxen_nic_set_mcast_addr(struct netxen_adapter *adapter, | |||
405 | return 0; | 407 | return 0; |
406 | } | 408 | } |
407 | 409 | ||
408 | /* | 410 | void netxen_p2_nic_set_multi(struct net_device *netdev) |
409 | * netxen_nic_set_multi - Multicast | ||
410 | */ | ||
411 | void netxen_nic_set_multi(struct net_device *netdev) | ||
412 | { | 411 | { |
413 | struct netxen_adapter *adapter = netdev_priv(netdev); | 412 | struct netxen_adapter *adapter = netdev_priv(netdev); |
414 | struct dev_mc_list *mc_ptr; | 413 | struct dev_mc_list *mc_ptr; |
@@ -456,18 +455,186 @@ void netxen_nic_set_multi(struct net_device *netdev) | |||
456 | netxen_nic_set_mcast_addr(adapter, index, null_addr); | 455 | netxen_nic_set_mcast_addr(adapter, index, null_addr); |
457 | } | 456 | } |
458 | 457 | ||
458 | static int nx_p3_nic_add_mac(struct netxen_adapter *adapter, | ||
459 | u8 *addr, nx_mac_list_t **add_list, nx_mac_list_t **del_list) | ||
460 | { | ||
461 | nx_mac_list_t *cur, *prev; | ||
462 | |||
463 | /* if in del_list, move it to adapter->mac_list */ | ||
464 | for (cur = *del_list, prev = NULL; cur;) { | ||
465 | if (memcmp(addr, cur->mac_addr, ETH_ALEN) == 0) { | ||
466 | if (prev == NULL) | ||
467 | *del_list = cur->next; | ||
468 | else | ||
469 | prev->next = cur->next; | ||
470 | cur->next = adapter->mac_list; | ||
471 | adapter->mac_list = cur; | ||
472 | return 0; | ||
473 | } | ||
474 | prev = cur; | ||
475 | cur = cur->next; | ||
476 | } | ||
477 | |||
478 | /* make sure to add each mac address only once */ | ||
479 | for (cur = adapter->mac_list; cur; cur = cur->next) { | ||
480 | if (memcmp(addr, cur->mac_addr, ETH_ALEN) == 0) | ||
481 | return 0; | ||
482 | } | ||
483 | /* not in del_list, create new entry and add to add_list */ | ||
484 | cur = kmalloc(sizeof(*cur), in_atomic()? GFP_ATOMIC : GFP_KERNEL); | ||
485 | if (cur == NULL) { | ||
486 | printk(KERN_ERR "%s: cannot allocate memory. MAC filtering may" | ||
487 | "not work properly from now.\n", __func__); | ||
488 | return -1; | ||
489 | } | ||
490 | |||
491 | memcpy(cur->mac_addr, addr, ETH_ALEN); | ||
492 | cur->next = *add_list; | ||
493 | *add_list = cur; | ||
494 | return 0; | ||
495 | } | ||
496 | |||
497 | static int | ||
498 | netxen_send_cmd_descs(struct netxen_adapter *adapter, | ||
499 | struct cmd_desc_type0 *cmd_desc_arr, int nr_elements) | ||
500 | { | ||
501 | uint32_t i, producer; | ||
502 | struct netxen_cmd_buffer *pbuf; | ||
503 | struct cmd_desc_type0 *cmd_desc; | ||
504 | |||
505 | if (nr_elements > MAX_PENDING_DESC_BLOCK_SIZE || nr_elements == 0) { | ||
506 | printk(KERN_WARNING "%s: Too many command descriptors in a " | ||
507 | "request\n", __func__); | ||
508 | return -EINVAL; | ||
509 | } | ||
510 | |||
511 | i = 0; | ||
512 | |||
513 | producer = adapter->cmd_producer; | ||
514 | do { | ||
515 | cmd_desc = &cmd_desc_arr[i]; | ||
516 | |||
517 | pbuf = &adapter->cmd_buf_arr[producer]; | ||
518 | pbuf->mss = 0; | ||
519 | pbuf->total_length = 0; | ||
520 | pbuf->skb = NULL; | ||
521 | pbuf->cmd = 0; | ||
522 | pbuf->frag_count = 0; | ||
523 | pbuf->port = 0; | ||
524 | |||
525 | /* adapter->ahw.cmd_desc_head[producer] = *cmd_desc; */ | ||
526 | memcpy(&adapter->ahw.cmd_desc_head[producer], | ||
527 | &cmd_desc_arr[i], sizeof(struct cmd_desc_type0)); | ||
528 | |||
529 | producer = get_next_index(producer, | ||
530 | adapter->max_tx_desc_count); | ||
531 | i++; | ||
532 | |||
533 | } while (i != nr_elements); | ||
534 | |||
535 | adapter->cmd_producer = producer; | ||
536 | |||
537 | /* write producer index to start the xmit */ | ||
538 | |||
539 | netxen_nic_update_cmd_producer(adapter, adapter->cmd_producer); | ||
540 | |||
541 | return 0; | ||
542 | } | ||
543 | |||
544 | #define NIC_REQUEST 0x14 | ||
545 | #define NETXEN_MAC_EVENT 0x1 | ||
546 | |||
547 | static int nx_p3_sre_macaddr_change(struct net_device *dev, | ||
548 | u8 *addr, unsigned op) | ||
549 | { | ||
550 | struct netxen_adapter *adapter = (struct netxen_adapter *)dev->priv; | ||
551 | nx_nic_req_t req; | ||
552 | nx_mac_req_t mac_req; | ||
553 | int rv; | ||
554 | |||
555 | memset(&req, 0, sizeof(nx_nic_req_t)); | ||
556 | req.qhdr |= (NIC_REQUEST << 23); | ||
557 | req.req_hdr |= NETXEN_MAC_EVENT; | ||
558 | req.req_hdr |= ((u64)adapter->portnum << 16); | ||
559 | mac_req.op = op; | ||
560 | memcpy(&mac_req.mac_addr, addr, 6); | ||
561 | req.words[0] = cpu_to_le64(*(u64 *)&mac_req); | ||
562 | |||
563 | rv = netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1); | ||
564 | if (rv != 0) { | ||
565 | printk(KERN_ERR "ERROR. Could not send mac update\n"); | ||
566 | return rv; | ||
567 | } | ||
568 | |||
569 | return 0; | ||
570 | } | ||
571 | |||
572 | void netxen_p3_nic_set_multi(struct net_device *netdev) | ||
573 | { | ||
574 | struct netxen_adapter *adapter = netdev_priv(netdev); | ||
575 | nx_mac_list_t *cur, *next, *del_list, *add_list = NULL; | ||
576 | struct dev_mc_list *mc_ptr; | ||
577 | u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; | ||
578 | |||
579 | adapter->set_promisc(adapter, NETXEN_NIU_PROMISC_MODE); | ||
580 | |||
581 | /* | ||
582 | * Programming mac addresses will automaticly enabling L2 filtering. | ||
583 | * HW will replace timestamp with L2 conid when L2 filtering is | ||
584 | * enabled. This causes problem for LSA. Do not enabling L2 filtering | ||
585 | * until that problem is fixed. | ||
586 | */ | ||
587 | if ((netdev->flags & IFF_PROMISC) || | ||
588 | (netdev->mc_count > adapter->max_mc_count)) | ||
589 | return; | ||
590 | |||
591 | del_list = adapter->mac_list; | ||
592 | adapter->mac_list = NULL; | ||
593 | |||
594 | nx_p3_nic_add_mac(adapter, netdev->dev_addr, &add_list, &del_list); | ||
595 | if (netdev->mc_count > 0) { | ||
596 | nx_p3_nic_add_mac(adapter, bcast_addr, &add_list, &del_list); | ||
597 | for (mc_ptr = netdev->mc_list; mc_ptr; | ||
598 | mc_ptr = mc_ptr->next) { | ||
599 | nx_p3_nic_add_mac(adapter, mc_ptr->dmi_addr, | ||
600 | &add_list, &del_list); | ||
601 | } | ||
602 | } | ||
603 | for (cur = del_list; cur;) { | ||
604 | nx_p3_sre_macaddr_change(netdev, cur->mac_addr, NETXEN_MAC_DEL); | ||
605 | next = cur->next; | ||
606 | kfree(cur); | ||
607 | cur = next; | ||
608 | } | ||
609 | for (cur = add_list; cur;) { | ||
610 | nx_p3_sre_macaddr_change(netdev, cur->mac_addr, NETXEN_MAC_ADD); | ||
611 | next = cur->next; | ||
612 | cur->next = adapter->mac_list; | ||
613 | adapter->mac_list = cur; | ||
614 | cur = next; | ||
615 | } | ||
616 | } | ||
617 | |||
459 | /* | 618 | /* |
460 | * netxen_nic_change_mtu - Change the Maximum Transfer Unit | 619 | * netxen_nic_change_mtu - Change the Maximum Transfer Unit |
461 | * @returns 0 on success, negative on failure | 620 | * @returns 0 on success, negative on failure |
462 | */ | 621 | */ |
622 | |||
623 | #define MTU_FUDGE_FACTOR 100 | ||
624 | |||
463 | int netxen_nic_change_mtu(struct net_device *netdev, int mtu) | 625 | int netxen_nic_change_mtu(struct net_device *netdev, int mtu) |
464 | { | 626 | { |
465 | struct netxen_adapter *adapter = netdev_priv(netdev); | 627 | struct netxen_adapter *adapter = netdev_priv(netdev); |
466 | int eff_mtu = mtu + NETXEN_ENET_HEADER_SIZE + NETXEN_ETH_FCS_SIZE; | 628 | int max_mtu; |
467 | 629 | ||
468 | if ((eff_mtu > NETXEN_MAX_MTU) || (eff_mtu < NETXEN_MIN_MTU)) { | 630 | if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) |
469 | printk(KERN_ERR "%s: %s %d is not supported.\n", | 631 | max_mtu = P3_MAX_MTU; |
470 | netxen_nic_driver_name, netdev->name, mtu); | 632 | else |
633 | max_mtu = P2_MAX_MTU; | ||
634 | |||
635 | if (mtu > max_mtu) { | ||
636 | printk(KERN_ERR "%s: mtu > %d bytes unsupported\n", | ||
637 | netdev->name, max_mtu); | ||
471 | return -EINVAL; | 638 | return -EINVAL; |
472 | } | 639 | } |
473 | 640 | ||
@@ -475,6 +642,12 @@ int netxen_nic_change_mtu(struct net_device *netdev, int mtu) | |||
475 | adapter->set_mtu(adapter, mtu); | 642 | adapter->set_mtu(adapter, mtu); |
476 | netdev->mtu = mtu; | 643 | netdev->mtu = mtu; |
477 | 644 | ||
645 | mtu += MTU_FUDGE_FACTOR; | ||
646 | if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) | ||
647 | nx_fw_cmd_set_mtu(adapter, mtu); | ||
648 | else if (adapter->set_mtu) | ||
649 | adapter->set_mtu(adapter, mtu); | ||
650 | |||
478 | return 0; | 651 | return 0; |
479 | } | 652 | } |
480 | 653 | ||
@@ -1882,11 +2055,6 @@ int netxen_nic_set_mtu_xgb(struct netxen_adapter *adapter, int new_mtu) | |||
1882 | return 0; | 2055 | return 0; |
1883 | } | 2056 | } |
1884 | 2057 | ||
1885 | void netxen_nic_init_niu_gb(struct netxen_adapter *adapter) | ||
1886 | { | ||
1887 | netxen_niu_gbe_init_port(adapter, adapter->physical_port); | ||
1888 | } | ||
1889 | |||
1890 | void | 2058 | void |
1891 | netxen_crb_writelit_adapter(struct netxen_adapter *adapter, | 2059 | netxen_crb_writelit_adapter(struct netxen_adapter *adapter, |
1892 | unsigned long off, int data) | 2060 | unsigned long off, int data) |