ncsi-manage.c (2ac5e38ea4203852d6e99edd3cf11f044b0a409f) | ncsi-manage.c (16e8c4ca21a238cdf0355475bf15bd72e92feb8f) |
---|---|
1/* 2 * Copyright Gavin Shan, IBM Corporation 2016. 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 */ --- 14 unchanged lines hidden (view full) --- 23 24#include "internal.h" 25#include "ncsi-pkt.h" 26#include "ncsi-netlink.h" 27 28LIST_HEAD(ncsi_dev_list); 29DEFINE_SPINLOCK(ncsi_dev_lock); 30 | 1/* 2 * Copyright Gavin Shan, IBM Corporation 2016. 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 */ --- 14 unchanged lines hidden (view full) --- 23 24#include "internal.h" 25#include "ncsi-pkt.h" 26#include "ncsi-netlink.h" 27 28LIST_HEAD(ncsi_dev_list); 29DEFINE_SPINLOCK(ncsi_dev_lock); 30 |
31bool ncsi_channel_has_link(struct ncsi_channel *channel) 32{ 33 return !!(channel->modes[NCSI_MODE_LINK].data[2] & 0x1); 34} 35 36bool ncsi_channel_is_last(struct ncsi_dev_priv *ndp, 37 struct ncsi_channel *channel) 38{ 39 struct ncsi_package *np; 40 struct ncsi_channel *nc; 41 42 NCSI_FOR_EACH_PACKAGE(ndp, np) 43 NCSI_FOR_EACH_CHANNEL(np, nc) { 44 if (nc == channel) 45 continue; 46 if (nc->state == NCSI_CHANNEL_ACTIVE && 47 ncsi_channel_has_link(nc)) 48 return false; 49 } 50 51 return true; 52} 53 |
|
31static void ncsi_report_link(struct ncsi_dev_priv *ndp, bool force_down) 32{ 33 struct ncsi_dev *nd = &ndp->ndev; 34 struct ncsi_package *np; 35 struct ncsi_channel *nc; 36 unsigned long flags; 37 38 nd->state = ncsi_dev_state_functional; --- 8 unchanged lines hidden (view full) --- 47 spin_lock_irqsave(&nc->lock, flags); 48 49 if (!list_empty(&nc->link) || 50 nc->state != NCSI_CHANNEL_ACTIVE) { 51 spin_unlock_irqrestore(&nc->lock, flags); 52 continue; 53 } 54 | 54static void ncsi_report_link(struct ncsi_dev_priv *ndp, bool force_down) 55{ 56 struct ncsi_dev *nd = &ndp->ndev; 57 struct ncsi_package *np; 58 struct ncsi_channel *nc; 59 unsigned long flags; 60 61 nd->state = ncsi_dev_state_functional; --- 8 unchanged lines hidden (view full) --- 70 spin_lock_irqsave(&nc->lock, flags); 71 72 if (!list_empty(&nc->link) || 73 nc->state != NCSI_CHANNEL_ACTIVE) { 74 spin_unlock_irqrestore(&nc->lock, flags); 75 continue; 76 } 77 |
55 if (nc->modes[NCSI_MODE_LINK].data[2] & 0x1) { | 78 if (ncsi_channel_has_link(nc)) { |
56 spin_unlock_irqrestore(&nc->lock, flags); 57 nd->link_up = 1; 58 goto report; 59 } 60 61 spin_unlock_irqrestore(&nc->lock, flags); 62 } 63 } --- 44 unchanged lines hidden (view full) --- 108 netdev_err(ndp->ndev.dev, "Error %d sending GLS\n", 109 ret); 110 break; 111 case NCSI_CHANNEL_MONITOR_WAIT ... NCSI_CHANNEL_MONITOR_WAIT_MAX: 112 break; 113 default: 114 netdev_err(ndp->ndev.dev, "NCSI Channel %d timed out!\n", 115 nc->id); | 79 spin_unlock_irqrestore(&nc->lock, flags); 80 nd->link_up = 1; 81 goto report; 82 } 83 84 spin_unlock_irqrestore(&nc->lock, flags); 85 } 86 } --- 44 unchanged lines hidden (view full) --- 131 netdev_err(ndp->ndev.dev, "Error %d sending GLS\n", 132 ret); 133 break; 134 case NCSI_CHANNEL_MONITOR_WAIT ... NCSI_CHANNEL_MONITOR_WAIT_MAX: 135 break; 136 default: 137 netdev_err(ndp->ndev.dev, "NCSI Channel %d timed out!\n", 138 nc->id); |
116 if (!(ndp->flags & NCSI_DEV_HWA)) { 117 ncsi_report_link(ndp, true); 118 ndp->flags |= NCSI_DEV_RESHUFFLE; 119 } | 139 ncsi_report_link(ndp, true); 140 ndp->flags |= NCSI_DEV_RESHUFFLE; |
120 121 ncsi_stop_channel_monitor(nc); 122 123 ncm = &nc->modes[NCSI_MODE_LINK]; 124 spin_lock_irqsave(&nc->lock, flags); 125 nc->state = NCSI_CHANNEL_INVISIBLE; 126 ncm->data[2] &= ~0x1; 127 spin_unlock_irqrestore(&nc->lock, flags); --- 136 unchanged lines hidden (view full) --- 264 np = kzalloc(sizeof(*np), GFP_ATOMIC); 265 if (!np) 266 return NULL; 267 268 np->id = id; 269 np->ndp = ndp; 270 spin_lock_init(&np->lock); 271 INIT_LIST_HEAD(&np->channels); | 141 142 ncsi_stop_channel_monitor(nc); 143 144 ncm = &nc->modes[NCSI_MODE_LINK]; 145 spin_lock_irqsave(&nc->lock, flags); 146 nc->state = NCSI_CHANNEL_INVISIBLE; 147 ncm->data[2] &= ~0x1; 148 spin_unlock_irqrestore(&nc->lock, flags); --- 136 unchanged lines hidden (view full) --- 285 np = kzalloc(sizeof(*np), GFP_ATOMIC); 286 if (!np) 287 return NULL; 288 289 np->id = id; 290 np->ndp = ndp; 291 spin_lock_init(&np->lock); 292 INIT_LIST_HEAD(&np->channels); |
293 np->channel_whitelist = UINT_MAX; |
|
272 273 spin_lock_irqsave(&ndp->lock, flags); 274 tmp = ncsi_find_package(ndp, id); 275 if (tmp) { 276 spin_unlock_irqrestore(&ndp->lock, flags); 277 kfree(np); 278 return tmp; 279 } --- 157 unchanged lines hidden (view full) --- 437 438 /* Release the request */ 439 ncsi_free_request(nr); 440} 441 442static void ncsi_suspend_channel(struct ncsi_dev_priv *ndp) 443{ 444 struct ncsi_dev *nd = &ndp->ndev; | 294 295 spin_lock_irqsave(&ndp->lock, flags); 296 tmp = ncsi_find_package(ndp, id); 297 if (tmp) { 298 spin_unlock_irqrestore(&ndp->lock, flags); 299 kfree(np); 300 return tmp; 301 } --- 157 unchanged lines hidden (view full) --- 459 460 /* Release the request */ 461 ncsi_free_request(nr); 462} 463 464static void ncsi_suspend_channel(struct ncsi_dev_priv *ndp) 465{ 466 struct ncsi_dev *nd = &ndp->ndev; |
445 struct ncsi_package *np = ndp->active_package; 446 struct ncsi_channel *nc = ndp->active_channel; | 467 struct ncsi_package *np; 468 struct ncsi_channel *nc, *tmp; |
447 struct ncsi_cmd_arg nca; 448 unsigned long flags; 449 int ret; 450 | 469 struct ncsi_cmd_arg nca; 470 unsigned long flags; 471 int ret; 472 |
473 np = ndp->active_package; 474 nc = ndp->active_channel; |
|
451 nca.ndp = ndp; 452 nca.req_flags = NCSI_REQ_FLAG_EVENT_DRIVEN; 453 switch (nd->state) { 454 case ncsi_dev_state_suspend: 455 nd->state = ncsi_dev_state_suspend_select; 456 /* Fall through */ 457 case ncsi_dev_state_suspend_select: 458 ndp->pending_req_num = 1; --- 59 unchanged lines hidden (view full) --- 518 nca.channel = nc->id; 519 nca.bytes[0] = 1; 520 521 nd->state = ncsi_dev_state_suspend_deselect; 522 ret = ncsi_xmit_cmd(&nca); 523 if (ret) 524 goto error; 525 | 475 nca.ndp = ndp; 476 nca.req_flags = NCSI_REQ_FLAG_EVENT_DRIVEN; 477 switch (nd->state) { 478 case ncsi_dev_state_suspend: 479 nd->state = ncsi_dev_state_suspend_select; 480 /* Fall through */ 481 case ncsi_dev_state_suspend_select: 482 ndp->pending_req_num = 1; --- 59 unchanged lines hidden (view full) --- 542 nca.channel = nc->id; 543 nca.bytes[0] = 1; 544 545 nd->state = ncsi_dev_state_suspend_deselect; 546 ret = ncsi_xmit_cmd(&nca); 547 if (ret) 548 goto error; 549 |
550 NCSI_FOR_EACH_CHANNEL(np, tmp) { 551 /* If there is another channel active on this package 552 * do not deselect the package. 553 */ 554 if (tmp != nc && tmp->state == NCSI_CHANNEL_ACTIVE) { 555 nd->state = ncsi_dev_state_suspend_done; 556 break; 557 } 558 } |
|
526 break; 527 case ncsi_dev_state_suspend_deselect: 528 ndp->pending_req_num = 1; 529 530 nca.type = NCSI_PKT_CMD_DP; 531 nca.package = np->id; 532 nca.channel = NCSI_RESERVED_CHANNEL; 533 534 nd->state = ncsi_dev_state_suspend_done; 535 ret = ncsi_xmit_cmd(&nca); 536 if (ret) 537 goto error; 538 539 break; 540 case ncsi_dev_state_suspend_done: 541 spin_lock_irqsave(&nc->lock, flags); 542 nc->state = NCSI_CHANNEL_INACTIVE; 543 spin_unlock_irqrestore(&nc->lock, flags); | 559 break; 560 case ncsi_dev_state_suspend_deselect: 561 ndp->pending_req_num = 1; 562 563 nca.type = NCSI_PKT_CMD_DP; 564 nca.package = np->id; 565 nca.channel = NCSI_RESERVED_CHANNEL; 566 567 nd->state = ncsi_dev_state_suspend_done; 568 ret = ncsi_xmit_cmd(&nca); 569 if (ret) 570 goto error; 571 572 break; 573 case ncsi_dev_state_suspend_done: 574 spin_lock_irqsave(&nc->lock, flags); 575 nc->state = NCSI_CHANNEL_INACTIVE; 576 spin_unlock_irqrestore(&nc->lock, flags); |
544 ncsi_process_next_channel(ndp); 545 | 577 if (ndp->flags & NCSI_DEV_RESET) 578 ncsi_reset_dev(nd); 579 else 580 ncsi_process_next_channel(ndp); |
546 break; 547 default: 548 netdev_warn(nd->dev, "Wrong NCSI state 0x%x in suspend\n", 549 nd->state); 550 } 551 552 return; 553error: --- 116 unchanged lines hidden (view full) --- 670 ret = ncsi_xmit_cmd(nca); 671 if (ret) 672 netdev_err(nca->ndp->ndev.dev, 673 "NCSI: Failed to transmit cmd 0x%x during configure\n", 674 nca->type); 675 return ret; 676} 677 | 581 break; 582 default: 583 netdev_warn(nd->dev, "Wrong NCSI state 0x%x in suspend\n", 584 nd->state); 585 } 586 587 return; 588error: --- 116 unchanged lines hidden (view full) --- 705 ret = ncsi_xmit_cmd(nca); 706 if (ret) 707 netdev_err(nca->ndp->ndev.dev, 708 "NCSI: Failed to transmit cmd 0x%x during configure\n", 709 nca->type); 710 return ret; 711} 712 |
713static int ncsi_oem_gma_handler_mlx(struct ncsi_cmd_arg *nca) 714{ 715 union { 716 u8 data_u8[NCSI_OEM_MLX_CMD_GMA_LEN]; 717 u32 data_u32[NCSI_OEM_MLX_CMD_GMA_LEN / sizeof(u32)]; 718 } u; 719 int ret = 0; 720 721 nca->payload = NCSI_OEM_MLX_CMD_GMA_LEN; 722 723 memset(&u, 0, sizeof(u)); 724 u.data_u32[0] = ntohl(NCSI_OEM_MFR_MLX_ID); 725 u.data_u8[5] = NCSI_OEM_MLX_CMD_GMA; 726 u.data_u8[6] = NCSI_OEM_MLX_CMD_GMA_PARAM; 727 728 nca->data = u.data_u8; 729 730 ret = ncsi_xmit_cmd(nca); 731 if (ret) 732 netdev_err(nca->ndp->ndev.dev, 733 "NCSI: Failed to transmit cmd 0x%x during configure\n", 734 nca->type); 735 return ret; 736} 737 |
|
678/* OEM Command handlers initialization */ 679static struct ncsi_oem_gma_handler { 680 unsigned int mfr_id; 681 int (*handler)(struct ncsi_cmd_arg *nca); 682} ncsi_oem_gma_handlers[] = { | 738/* OEM Command handlers initialization */ 739static struct ncsi_oem_gma_handler { 740 unsigned int mfr_id; 741 int (*handler)(struct ncsi_cmd_arg *nca); 742} ncsi_oem_gma_handlers[] = { |
683 { NCSI_OEM_MFR_BCM_ID, ncsi_oem_gma_handler_bcm } | 743 { NCSI_OEM_MFR_BCM_ID, ncsi_oem_gma_handler_bcm }, 744 { NCSI_OEM_MFR_MLX_ID, ncsi_oem_gma_handler_mlx } |
684}; 685 686static int ncsi_gma_handler(struct ncsi_cmd_arg *nca, unsigned int mf_id) 687{ 688 struct ncsi_oem_gma_handler *nch = NULL; 689 int i; 690 691 /* This function should only be called once, return if flag set */ --- 20 unchanged lines hidden (view full) --- 712 nca->ndp->gma_flag = 1; 713 714 /* Get Mac address from NCSI device */ 715 return nch->handler(nca); 716} 717 718#endif /* CONFIG_NCSI_OEM_CMD_GET_MAC */ 719 | 745}; 746 747static int ncsi_gma_handler(struct ncsi_cmd_arg *nca, unsigned int mf_id) 748{ 749 struct ncsi_oem_gma_handler *nch = NULL; 750 int i; 751 752 /* This function should only be called once, return if flag set */ --- 20 unchanged lines hidden (view full) --- 773 nca->ndp->gma_flag = 1; 774 775 /* Get Mac address from NCSI device */ 776 return nch->handler(nca); 777} 778 779#endif /* CONFIG_NCSI_OEM_CMD_GET_MAC */ 780 |
781/* Determine if a given channel from the channel_queue should be used for Tx */ 782static bool ncsi_channel_is_tx(struct ncsi_dev_priv *ndp, 783 struct ncsi_channel *nc) 784{ 785 struct ncsi_channel_mode *ncm; 786 struct ncsi_channel *channel; 787 struct ncsi_package *np; 788 789 /* Check if any other channel has Tx enabled; a channel may have already 790 * been configured and removed from the channel queue. 791 */ 792 NCSI_FOR_EACH_PACKAGE(ndp, np) { 793 if (!ndp->multi_package && np != nc->package) 794 continue; 795 NCSI_FOR_EACH_CHANNEL(np, channel) { 796 ncm = &channel->modes[NCSI_MODE_TX_ENABLE]; 797 if (ncm->enable) 798 return false; 799 } 800 } 801 802 /* This channel is the preferred channel and has link */ 803 list_for_each_entry_rcu(channel, &ndp->channel_queue, link) { 804 np = channel->package; 805 if (np->preferred_channel && 806 ncsi_channel_has_link(np->preferred_channel)) { 807 return np->preferred_channel == nc; 808 } 809 } 810 811 /* This channel has link */ 812 if (ncsi_channel_has_link(nc)) 813 return true; 814 815 list_for_each_entry_rcu(channel, &ndp->channel_queue, link) 816 if (ncsi_channel_has_link(channel)) 817 return false; 818 819 /* No other channel has link; default to this one */ 820 return true; 821} 822 823/* Change the active Tx channel in a multi-channel setup */ 824int ncsi_update_tx_channel(struct ncsi_dev_priv *ndp, 825 struct ncsi_package *package, 826 struct ncsi_channel *disable, 827 struct ncsi_channel *enable) 828{ 829 struct ncsi_cmd_arg nca; 830 struct ncsi_channel *nc; 831 struct ncsi_package *np; 832 int ret = 0; 833 834 if (!package->multi_channel && !ndp->multi_package) 835 netdev_warn(ndp->ndev.dev, 836 "NCSI: Trying to update Tx channel in single-channel mode\n"); 837 nca.ndp = ndp; 838 nca.req_flags = 0; 839 840 /* Find current channel with Tx enabled */ 841 NCSI_FOR_EACH_PACKAGE(ndp, np) { 842 if (disable) 843 break; 844 if (!ndp->multi_package && np != package) 845 continue; 846 847 NCSI_FOR_EACH_CHANNEL(np, nc) 848 if (nc->modes[NCSI_MODE_TX_ENABLE].enable) { 849 disable = nc; 850 break; 851 } 852 } 853 854 /* Find a suitable channel for Tx */ 855 NCSI_FOR_EACH_PACKAGE(ndp, np) { 856 if (enable) 857 break; 858 if (!ndp->multi_package && np != package) 859 continue; 860 if (!(ndp->package_whitelist & (0x1 << np->id))) 861 continue; 862 863 if (np->preferred_channel && 864 ncsi_channel_has_link(np->preferred_channel)) { 865 enable = np->preferred_channel; 866 break; 867 } 868 869 NCSI_FOR_EACH_CHANNEL(np, nc) { 870 if (!(np->channel_whitelist & 0x1 << nc->id)) 871 continue; 872 if (nc->state != NCSI_CHANNEL_ACTIVE) 873 continue; 874 if (ncsi_channel_has_link(nc)) { 875 enable = nc; 876 break; 877 } 878 } 879 } 880 881 if (disable == enable) 882 return -1; 883 884 if (!enable) 885 return -1; 886 887 if (disable) { 888 nca.channel = disable->id; 889 nca.package = disable->package->id; 890 nca.type = NCSI_PKT_CMD_DCNT; 891 ret = ncsi_xmit_cmd(&nca); 892 if (ret) 893 netdev_err(ndp->ndev.dev, 894 "Error %d sending DCNT\n", 895 ret); 896 } 897 898 netdev_info(ndp->ndev.dev, "NCSI: channel %u enables Tx\n", enable->id); 899 900 nca.channel = enable->id; 901 nca.package = enable->package->id; 902 nca.type = NCSI_PKT_CMD_ECNT; 903 ret = ncsi_xmit_cmd(&nca); 904 if (ret) 905 netdev_err(ndp->ndev.dev, 906 "Error %d sending ECNT\n", 907 ret); 908 909 return ret; 910} 911 |
|
720static void ncsi_configure_channel(struct ncsi_dev_priv *ndp) 721{ | 912static void ncsi_configure_channel(struct ncsi_dev_priv *ndp) 913{ |
722 struct ncsi_dev *nd = &ndp->ndev; 723 struct net_device *dev = nd->dev; | |
724 struct ncsi_package *np = ndp->active_package; 725 struct ncsi_channel *nc = ndp->active_channel; 726 struct ncsi_channel *hot_nc = NULL; | 914 struct ncsi_package *np = ndp->active_package; 915 struct ncsi_channel *nc = ndp->active_channel; 916 struct ncsi_channel *hot_nc = NULL; |
917 struct ncsi_dev *nd = &ndp->ndev; 918 struct net_device *dev = nd->dev; |
|
727 struct ncsi_cmd_arg nca; 728 unsigned char index; 729 unsigned long flags; 730 int ret; 731 732 nca.ndp = ndp; 733 nca.req_flags = NCSI_REQ_FLAG_EVENT_DRIVEN; 734 switch (nd->state) { --- 105 unchanged lines hidden (view full) --- 840 for (index = 0; index < 6; index++) 841 nca.bytes[index] = dev->dev_addr[index]; 842 nca.bytes[6] = 0x1; 843 nca.bytes[7] = 0x1; 844 nd->state = ncsi_dev_state_config_ebf; 845 } else if (nd->state == ncsi_dev_state_config_ebf) { 846 nca.type = NCSI_PKT_CMD_EBF; 847 nca.dwords[0] = nc->caps[NCSI_CAP_BC].cap; | 919 struct ncsi_cmd_arg nca; 920 unsigned char index; 921 unsigned long flags; 922 int ret; 923 924 nca.ndp = ndp; 925 nca.req_flags = NCSI_REQ_FLAG_EVENT_DRIVEN; 926 switch (nd->state) { --- 105 unchanged lines hidden (view full) --- 1032 for (index = 0; index < 6; index++) 1033 nca.bytes[index] = dev->dev_addr[index]; 1034 nca.bytes[6] = 0x1; 1035 nca.bytes[7] = 0x1; 1036 nd->state = ncsi_dev_state_config_ebf; 1037 } else if (nd->state == ncsi_dev_state_config_ebf) { 1038 nca.type = NCSI_PKT_CMD_EBF; 1039 nca.dwords[0] = nc->caps[NCSI_CAP_BC].cap; |
848 nd->state = ncsi_dev_state_config_ecnt; | 1040 if (ncsi_channel_is_tx(ndp, nc)) 1041 nd->state = ncsi_dev_state_config_ecnt; 1042 else 1043 nd->state = ncsi_dev_state_config_ec; |
849#if IS_ENABLED(CONFIG_IPV6) 850 if (ndp->inet6_addr_num > 0 && 851 (nc->caps[NCSI_CAP_GENERIC].cap & 852 NCSI_CAP_GENERIC_MC)) 853 nd->state = ncsi_dev_state_config_egmf; | 1044#if IS_ENABLED(CONFIG_IPV6) 1045 if (ndp->inet6_addr_num > 0 && 1046 (nc->caps[NCSI_CAP_GENERIC].cap & 1047 NCSI_CAP_GENERIC_MC)) 1048 nd->state = ncsi_dev_state_config_egmf; |
854 else 855 nd->state = ncsi_dev_state_config_ecnt; | |
856 } else if (nd->state == ncsi_dev_state_config_egmf) { 857 nca.type = NCSI_PKT_CMD_EGMF; 858 nca.dwords[0] = nc->caps[NCSI_CAP_MC].cap; | 1049 } else if (nd->state == ncsi_dev_state_config_egmf) { 1050 nca.type = NCSI_PKT_CMD_EGMF; 1051 nca.dwords[0] = nc->caps[NCSI_CAP_MC].cap; |
859 nd->state = ncsi_dev_state_config_ecnt; | 1052 if (ncsi_channel_is_tx(ndp, nc)) 1053 nd->state = ncsi_dev_state_config_ecnt; 1054 else 1055 nd->state = ncsi_dev_state_config_ec; |
860#endif /* CONFIG_IPV6 */ 861 } else if (nd->state == ncsi_dev_state_config_ecnt) { | 1056#endif /* CONFIG_IPV6 */ 1057 } else if (nd->state == ncsi_dev_state_config_ecnt) { |
1058 if (np->preferred_channel && 1059 nc != np->preferred_channel) 1060 netdev_info(ndp->ndev.dev, 1061 "NCSI: Tx failed over to channel %u\n", 1062 nc->id); |
|
862 nca.type = NCSI_PKT_CMD_ECNT; 863 nd->state = ncsi_dev_state_config_ec; 864 } else if (nd->state == ncsi_dev_state_config_ec) { 865 /* Enable AEN if it's supported */ 866 nca.type = NCSI_PKT_CMD_EC; 867 nd->state = ncsi_dev_state_config_ae; 868 if (!(nc->caps[NCSI_CAP_AEN].cap & NCSI_CAP_AEN_MASK)) 869 nd->state = ncsi_dev_state_config_gls; --- 14 unchanged lines hidden (view full) --- 884 nca.type); 885 goto error; 886 } 887 break; 888 case ncsi_dev_state_config_done: 889 netdev_dbg(ndp->ndev.dev, "NCSI: channel %u config done\n", 890 nc->id); 891 spin_lock_irqsave(&nc->lock, flags); | 1063 nca.type = NCSI_PKT_CMD_ECNT; 1064 nd->state = ncsi_dev_state_config_ec; 1065 } else if (nd->state == ncsi_dev_state_config_ec) { 1066 /* Enable AEN if it's supported */ 1067 nca.type = NCSI_PKT_CMD_EC; 1068 nd->state = ncsi_dev_state_config_ae; 1069 if (!(nc->caps[NCSI_CAP_AEN].cap & NCSI_CAP_AEN_MASK)) 1070 nd->state = ncsi_dev_state_config_gls; --- 14 unchanged lines hidden (view full) --- 1085 nca.type); 1086 goto error; 1087 } 1088 break; 1089 case ncsi_dev_state_config_done: 1090 netdev_dbg(ndp->ndev.dev, "NCSI: channel %u config done\n", 1091 nc->id); 1092 spin_lock_irqsave(&nc->lock, flags); |
1093 nc->state = NCSI_CHANNEL_ACTIVE; 1094 1095 if (ndp->flags & NCSI_DEV_RESET) { 1096 /* A reset event happened during config, start it now */ 1097 nc->reconfigure_needed = false; 1098 spin_unlock_irqrestore(&nc->lock, flags); 1099 ncsi_reset_dev(nd); 1100 break; 1101 } 1102 |
|
892 if (nc->reconfigure_needed) { 893 /* This channel's configuration has been updated 894 * part-way during the config state - start the 895 * channel configuration over 896 */ 897 nc->reconfigure_needed = false; 898 nc->state = NCSI_CHANNEL_INACTIVE; 899 spin_unlock_irqrestore(&nc->lock, flags); --- 4 unchanged lines hidden (view full) --- 904 905 netdev_dbg(dev, "Dirty NCSI channel state reset\n"); 906 ncsi_process_next_channel(ndp); 907 break; 908 } 909 910 if (nc->modes[NCSI_MODE_LINK].data[2] & 0x1) { 911 hot_nc = nc; | 1103 if (nc->reconfigure_needed) { 1104 /* This channel's configuration has been updated 1105 * part-way during the config state - start the 1106 * channel configuration over 1107 */ 1108 nc->reconfigure_needed = false; 1109 nc->state = NCSI_CHANNEL_INACTIVE; 1110 spin_unlock_irqrestore(&nc->lock, flags); --- 4 unchanged lines hidden (view full) --- 1115 1116 netdev_dbg(dev, "Dirty NCSI channel state reset\n"); 1117 ncsi_process_next_channel(ndp); 1118 break; 1119 } 1120 1121 if (nc->modes[NCSI_MODE_LINK].data[2] & 0x1) { 1122 hot_nc = nc; |
912 nc->state = NCSI_CHANNEL_ACTIVE; | |
913 } else { 914 hot_nc = NULL; | 1123 } else { 1124 hot_nc = NULL; |
915 nc->state = NCSI_CHANNEL_INACTIVE; | |
916 netdev_dbg(ndp->ndev.dev, 917 "NCSI: channel %u link down after config\n", 918 nc->id); 919 } 920 spin_unlock_irqrestore(&nc->lock, flags); 921 922 /* Update the hot channel */ 923 spin_lock_irqsave(&ndp->lock, flags); --- 11 unchanged lines hidden (view full) --- 935 return; 936 937error: 938 ncsi_report_link(ndp, true); 939} 940 941static int ncsi_choose_active_channel(struct ncsi_dev_priv *ndp) 942{ | 1125 netdev_dbg(ndp->ndev.dev, 1126 "NCSI: channel %u link down after config\n", 1127 nc->id); 1128 } 1129 spin_unlock_irqrestore(&nc->lock, flags); 1130 1131 /* Update the hot channel */ 1132 spin_lock_irqsave(&ndp->lock, flags); --- 11 unchanged lines hidden (view full) --- 1144 return; 1145 1146error: 1147 ncsi_report_link(ndp, true); 1148} 1149 1150static int ncsi_choose_active_channel(struct ncsi_dev_priv *ndp) 1151{ |
943 struct ncsi_package *np, *force_package; 944 struct ncsi_channel *nc, *found, *hot_nc, *force_channel; | 1152 struct ncsi_channel *nc, *found, *hot_nc; |
945 struct ncsi_channel_mode *ncm; | 1153 struct ncsi_channel_mode *ncm; |
946 unsigned long flags; | 1154 unsigned long flags, cflags; 1155 struct ncsi_package *np; 1156 bool with_link; |
947 948 spin_lock_irqsave(&ndp->lock, flags); 949 hot_nc = ndp->hot_channel; | 1157 1158 spin_lock_irqsave(&ndp->lock, flags); 1159 hot_nc = ndp->hot_channel; |
950 force_channel = ndp->force_channel; 951 force_package = ndp->force_package; | |
952 spin_unlock_irqrestore(&ndp->lock, flags); 953 | 1160 spin_unlock_irqrestore(&ndp->lock, flags); 1161 |
954 /* Force a specific channel whether or not it has link if we have been 955 * configured to do so | 1162 /* By default the search is done once an inactive channel with up 1163 * link is found, unless a preferred channel is set. 1164 * If multi_package or multi_channel are configured all channels in the 1165 * whitelist are added to the channel queue. |
956 */ | 1166 */ |
957 if (force_package && force_channel) { 958 found = force_channel; 959 ncm = &found->modes[NCSI_MODE_LINK]; 960 if (!(ncm->data[2] & 0x1)) 961 netdev_info(ndp->ndev.dev, 962 "NCSI: Channel %u forced, but it is link down\n", 963 found->id); 964 goto out; 965 } 966 967 /* The search is done once an inactive channel with up 968 * link is found. 969 */ | |
970 found = NULL; | 1167 found = NULL; |
1168 with_link = false; |
|
971 NCSI_FOR_EACH_PACKAGE(ndp, np) { | 1169 NCSI_FOR_EACH_PACKAGE(ndp, np) { |
972 if (ndp->force_package && np != ndp->force_package) | 1170 if (!(ndp->package_whitelist & (0x1 << np->id))) |
973 continue; 974 NCSI_FOR_EACH_CHANNEL(np, nc) { | 1171 continue; 1172 NCSI_FOR_EACH_CHANNEL(np, nc) { |
975 spin_lock_irqsave(&nc->lock, flags); | 1173 if (!(np->channel_whitelist & (0x1 << nc->id))) 1174 continue; |
976 | 1175 |
1176 spin_lock_irqsave(&nc->lock, cflags); 1177 |
|
977 if (!list_empty(&nc->link) || 978 nc->state != NCSI_CHANNEL_INACTIVE) { | 1178 if (!list_empty(&nc->link) || 1179 nc->state != NCSI_CHANNEL_INACTIVE) { |
979 spin_unlock_irqrestore(&nc->lock, flags); | 1180 spin_unlock_irqrestore(&nc->lock, cflags); |
980 continue; 981 } 982 983 if (!found) 984 found = nc; 985 986 if (nc == hot_nc) 987 found = nc; 988 989 ncm = &nc->modes[NCSI_MODE_LINK]; 990 if (ncm->data[2] & 0x1) { | 1181 continue; 1182 } 1183 1184 if (!found) 1185 found = nc; 1186 1187 if (nc == hot_nc) 1188 found = nc; 1189 1190 ncm = &nc->modes[NCSI_MODE_LINK]; 1191 if (ncm->data[2] & 0x1) { |
991 spin_unlock_irqrestore(&nc->lock, flags); | |
992 found = nc; | 1192 found = nc; |
993 goto out; | 1193 with_link = true; |
994 } 995 | 1194 } 1195 |
996 spin_unlock_irqrestore(&nc->lock, flags); | 1196 /* If multi_channel is enabled configure all valid 1197 * channels whether or not they currently have link 1198 * so they will have AENs enabled. 1199 */ 1200 if (with_link || np->multi_channel) { 1201 spin_lock_irqsave(&ndp->lock, flags); 1202 list_add_tail_rcu(&nc->link, 1203 &ndp->channel_queue); 1204 spin_unlock_irqrestore(&ndp->lock, flags); 1205 1206 netdev_dbg(ndp->ndev.dev, 1207 "NCSI: Channel %u added to queue (link %s)\n", 1208 nc->id, 1209 ncm->data[2] & 0x1 ? "up" : "down"); 1210 } 1211 1212 spin_unlock_irqrestore(&nc->lock, cflags); 1213 1214 if (with_link && !np->multi_channel) 1215 break; |
997 } | 1216 } |
1217 if (with_link && !ndp->multi_package) 1218 break; |
|
998 } 999 | 1219 } 1220 |
1000 if (!found) { | 1221 if (list_empty(&ndp->channel_queue) && found) { 1222 netdev_info(ndp->ndev.dev, 1223 "NCSI: No channel with link found, configuring channel %u\n", 1224 found->id); 1225 spin_lock_irqsave(&ndp->lock, flags); 1226 list_add_tail_rcu(&found->link, &ndp->channel_queue); 1227 spin_unlock_irqrestore(&ndp->lock, flags); 1228 } else if (!found) { |
1001 netdev_warn(ndp->ndev.dev, | 1229 netdev_warn(ndp->ndev.dev, |
1002 "NCSI: No channel found with link\n"); | 1230 "NCSI: No channel found to configure!\n"); |
1003 ncsi_report_link(ndp, true); 1004 return -ENODEV; 1005 } 1006 | 1231 ncsi_report_link(ndp, true); 1232 return -ENODEV; 1233 } 1234 |
1007 ncm = &found->modes[NCSI_MODE_LINK]; 1008 netdev_dbg(ndp->ndev.dev, 1009 "NCSI: Channel %u added to queue (link %s)\n", 1010 found->id, ncm->data[2] & 0x1 ? "up" : "down"); 1011 1012out: 1013 spin_lock_irqsave(&ndp->lock, flags); 1014 list_add_tail_rcu(&found->link, &ndp->channel_queue); 1015 spin_unlock_irqrestore(&ndp->lock, flags); 1016 | |
1017 return ncsi_process_next_channel(ndp); 1018} 1019 1020static bool ncsi_check_hwa(struct ncsi_dev_priv *ndp) 1021{ 1022 struct ncsi_package *np; 1023 struct ncsi_channel *nc; 1024 unsigned int cap; --- 20 unchanged lines hidden (view full) --- 1045 ndp->flags |= NCSI_DEV_HWA; 1046 return true; 1047 } 1048 1049 ndp->flags &= ~NCSI_DEV_HWA; 1050 return false; 1051} 1052 | 1235 return ncsi_process_next_channel(ndp); 1236} 1237 1238static bool ncsi_check_hwa(struct ncsi_dev_priv *ndp) 1239{ 1240 struct ncsi_package *np; 1241 struct ncsi_channel *nc; 1242 unsigned int cap; --- 20 unchanged lines hidden (view full) --- 1263 ndp->flags |= NCSI_DEV_HWA; 1264 return true; 1265 } 1266 1267 ndp->flags &= ~NCSI_DEV_HWA; 1268 return false; 1269} 1270 |
1053static int ncsi_enable_hwa(struct ncsi_dev_priv *ndp) 1054{ 1055 struct ncsi_package *np; 1056 struct ncsi_channel *nc; 1057 unsigned long flags; 1058 1059 /* Move all available channels to processing queue */ 1060 spin_lock_irqsave(&ndp->lock, flags); 1061 NCSI_FOR_EACH_PACKAGE(ndp, np) { 1062 NCSI_FOR_EACH_CHANNEL(np, nc) { 1063 WARN_ON_ONCE(nc->state != NCSI_CHANNEL_INACTIVE || 1064 !list_empty(&nc->link)); 1065 ncsi_stop_channel_monitor(nc); 1066 list_add_tail_rcu(&nc->link, &ndp->channel_queue); 1067 } 1068 } 1069 spin_unlock_irqrestore(&ndp->lock, flags); 1070 1071 /* We can have no channels in extremely case */ 1072 if (list_empty(&ndp->channel_queue)) { 1073 netdev_err(ndp->ndev.dev, 1074 "NCSI: No available channels for HWA\n"); 1075 ncsi_report_link(ndp, false); 1076 return -ENOENT; 1077 } 1078 1079 return ncsi_process_next_channel(ndp); 1080} 1081 | |
1082static void ncsi_probe_channel(struct ncsi_dev_priv *ndp) 1083{ 1084 struct ncsi_dev *nd = &ndp->ndev; 1085 struct ncsi_package *np; 1086 struct ncsi_channel *nc; 1087 struct ncsi_cmd_arg nca; 1088 unsigned char index; 1089 int ret; --- 15 unchanged lines hidden (view full) --- 1105 ret = ncsi_xmit_cmd(&nca); 1106 if (ret) 1107 goto error; 1108 } 1109 1110 nd->state = ncsi_dev_state_probe_package; 1111 break; 1112 case ncsi_dev_state_probe_package: | 1271static void ncsi_probe_channel(struct ncsi_dev_priv *ndp) 1272{ 1273 struct ncsi_dev *nd = &ndp->ndev; 1274 struct ncsi_package *np; 1275 struct ncsi_channel *nc; 1276 struct ncsi_cmd_arg nca; 1277 unsigned char index; 1278 int ret; --- 15 unchanged lines hidden (view full) --- 1294 ret = ncsi_xmit_cmd(&nca); 1295 if (ret) 1296 goto error; 1297 } 1298 1299 nd->state = ncsi_dev_state_probe_package; 1300 break; 1301 case ncsi_dev_state_probe_package: |
1113 ndp->pending_req_num = 16; | 1302 ndp->pending_req_num = 1; |
1114 | 1303 |
1115 /* Select all possible packages */ | |
1116 nca.type = NCSI_PKT_CMD_SP; 1117 nca.bytes[0] = 1; | 1304 nca.type = NCSI_PKT_CMD_SP; 1305 nca.bytes[0] = 1; |
1306 nca.package = ndp->package_probe_id; |
|
1118 nca.channel = NCSI_RESERVED_CHANNEL; | 1307 nca.channel = NCSI_RESERVED_CHANNEL; |
1119 for (index = 0; index < 8; index++) { 1120 nca.package = index; 1121 ret = ncsi_xmit_cmd(&nca); 1122 if (ret) 1123 goto error; 1124 } 1125 1126 /* Disable all possible packages */ 1127 nca.type = NCSI_PKT_CMD_DP; 1128 for (index = 0; index < 8; index++) { 1129 nca.package = index; 1130 ret = ncsi_xmit_cmd(&nca); 1131 if (ret) 1132 goto error; 1133 } 1134 | 1308 ret = ncsi_xmit_cmd(&nca); 1309 if (ret) 1310 goto error; |
1135 nd->state = ncsi_dev_state_probe_channel; 1136 break; 1137 case ncsi_dev_state_probe_channel: | 1311 nd->state = ncsi_dev_state_probe_channel; 1312 break; 1313 case ncsi_dev_state_probe_channel: |
1138 if (!ndp->active_package) 1139 ndp->active_package = list_first_or_null_rcu( 1140 &ndp->packages, struct ncsi_package, node); 1141 else if (list_is_last(&ndp->active_package->node, 1142 &ndp->packages)) 1143 ndp->active_package = NULL; 1144 else 1145 ndp->active_package = list_next_entry( 1146 ndp->active_package, node); 1147 1148 /* All available packages and channels are enumerated. The 1149 * enumeration happens for once when the NCSI interface is 1150 * started. So we need continue to start the interface after 1151 * the enumeration. 1152 * 1153 * We have to choose an active channel before configuring it. 1154 * Note that we possibly don't have active channel in extreme 1155 * situation. 1156 */ | 1314 ndp->active_package = ncsi_find_package(ndp, 1315 ndp->package_probe_id); |
1157 if (!ndp->active_package) { | 1316 if (!ndp->active_package) { |
1158 ndp->flags |= NCSI_DEV_PROBED; 1159 if (ncsi_check_hwa(ndp)) 1160 ncsi_enable_hwa(ndp); 1161 else 1162 ncsi_choose_active_channel(ndp); 1163 return; | 1317 /* No response */ 1318 nd->state = ncsi_dev_state_probe_dp; 1319 schedule_work(&ndp->work); 1320 break; |
1164 } | 1321 } |
1165 1166 /* Select the active package */ 1167 ndp->pending_req_num = 1; 1168 nca.type = NCSI_PKT_CMD_SP; 1169 nca.bytes[0] = 1; 1170 nca.package = ndp->active_package->id; 1171 nca.channel = NCSI_RESERVED_CHANNEL; 1172 ret = ncsi_xmit_cmd(&nca); 1173 if (ret) 1174 goto error; 1175 | |
1176 nd->state = ncsi_dev_state_probe_cis; | 1322 nd->state = ncsi_dev_state_probe_cis; |
1323 schedule_work(&ndp->work); |
|
1177 break; 1178 case ncsi_dev_state_probe_cis: 1179 ndp->pending_req_num = NCSI_RESERVED_CHANNEL; 1180 1181 /* Clear initial state */ 1182 nca.type = NCSI_PKT_CMD_CIS; 1183 nca.package = ndp->active_package->id; 1184 for (index = 0; index < NCSI_RESERVED_CHANNEL; index++) { --- 32 unchanged lines hidden (view full) --- 1217 else if (nd->state == ncsi_dev_state_probe_gc) 1218 nd->state = ncsi_dev_state_probe_gls; 1219 else 1220 nd->state = ncsi_dev_state_probe_dp; 1221 break; 1222 case ncsi_dev_state_probe_dp: 1223 ndp->pending_req_num = 1; 1224 | 1324 break; 1325 case ncsi_dev_state_probe_cis: 1326 ndp->pending_req_num = NCSI_RESERVED_CHANNEL; 1327 1328 /* Clear initial state */ 1329 nca.type = NCSI_PKT_CMD_CIS; 1330 nca.package = ndp->active_package->id; 1331 for (index = 0; index < NCSI_RESERVED_CHANNEL; index++) { --- 32 unchanged lines hidden (view full) --- 1364 else if (nd->state == ncsi_dev_state_probe_gc) 1365 nd->state = ncsi_dev_state_probe_gls; 1366 else 1367 nd->state = ncsi_dev_state_probe_dp; 1368 break; 1369 case ncsi_dev_state_probe_dp: 1370 ndp->pending_req_num = 1; 1371 |
1225 /* Deselect the active package */ | 1372 /* Deselect the current package */ |
1226 nca.type = NCSI_PKT_CMD_DP; | 1373 nca.type = NCSI_PKT_CMD_DP; |
1227 nca.package = ndp->active_package->id; | 1374 nca.package = ndp->package_probe_id; |
1228 nca.channel = NCSI_RESERVED_CHANNEL; 1229 ret = ncsi_xmit_cmd(&nca); 1230 if (ret) 1231 goto error; 1232 | 1375 nca.channel = NCSI_RESERVED_CHANNEL; 1376 ret = ncsi_xmit_cmd(&nca); 1377 if (ret) 1378 goto error; 1379 |
1233 /* Scan channels in next package */ 1234 nd->state = ncsi_dev_state_probe_channel; | 1380 /* Probe next package */ 1381 ndp->package_probe_id++; 1382 if (ndp->package_probe_id >= 8) { 1383 /* Probe finished */ 1384 ndp->flags |= NCSI_DEV_PROBED; 1385 break; 1386 } 1387 nd->state = ncsi_dev_state_probe_package; 1388 ndp->active_package = NULL; |
1235 break; 1236 default: 1237 netdev_warn(nd->dev, "Wrong NCSI state 0x%0x in enumeration\n", 1238 nd->state); 1239 } 1240 | 1389 break; 1390 default: 1391 netdev_warn(nd->dev, "Wrong NCSI state 0x%0x in enumeration\n", 1392 nd->state); 1393 } 1394 |
1395 if (ndp->flags & NCSI_DEV_PROBED) { 1396 /* Check if all packages have HWA support */ 1397 ncsi_check_hwa(ndp); 1398 ncsi_choose_active_channel(ndp); 1399 } 1400 |
|
1241 return; 1242error: 1243 netdev_err(ndp->ndev.dev, 1244 "NCSI: Failed to transmit cmd 0x%x during probe\n", 1245 nca.type); 1246 ncsi_report_link(ndp, true); 1247} 1248 --- 302 unchanged lines hidden (view full) --- 1551 nd = &ndp->ndev; 1552 nd->state = ncsi_dev_state_registered; 1553 nd->dev = dev; 1554 nd->handler = handler; 1555 ndp->pending_req_num = 0; 1556 INIT_LIST_HEAD(&ndp->channel_queue); 1557 INIT_LIST_HEAD(&ndp->vlan_vids); 1558 INIT_WORK(&ndp->work, ncsi_dev_work); | 1401 return; 1402error: 1403 netdev_err(ndp->ndev.dev, 1404 "NCSI: Failed to transmit cmd 0x%x during probe\n", 1405 nca.type); 1406 ncsi_report_link(ndp, true); 1407} 1408 --- 302 unchanged lines hidden (view full) --- 1711 nd = &ndp->ndev; 1712 nd->state = ncsi_dev_state_registered; 1713 nd->dev = dev; 1714 nd->handler = handler; 1715 ndp->pending_req_num = 0; 1716 INIT_LIST_HEAD(&ndp->channel_queue); 1717 INIT_LIST_HEAD(&ndp->vlan_vids); 1718 INIT_WORK(&ndp->work, ncsi_dev_work); |
1719 ndp->package_whitelist = UINT_MAX; |
|
1559 1560 /* Initialize private NCSI device */ 1561 spin_lock_init(&ndp->lock); 1562 INIT_LIST_HEAD(&ndp->packages); 1563 ndp->request_id = NCSI_REQ_START_IDX; 1564 for (i = 0; i < ARRAY_SIZE(ndp->requests); i++) { 1565 ndp->requests[i].id = i; 1566 ndp->requests[i].ndp = ndp; --- 20 unchanged lines hidden (view full) --- 1587 1588 return nd; 1589} 1590EXPORT_SYMBOL_GPL(ncsi_register_dev); 1591 1592int ncsi_start_dev(struct ncsi_dev *nd) 1593{ 1594 struct ncsi_dev_priv *ndp = TO_NCSI_DEV_PRIV(nd); | 1720 1721 /* Initialize private NCSI device */ 1722 spin_lock_init(&ndp->lock); 1723 INIT_LIST_HEAD(&ndp->packages); 1724 ndp->request_id = NCSI_REQ_START_IDX; 1725 for (i = 0; i < ARRAY_SIZE(ndp->requests); i++) { 1726 ndp->requests[i].id = i; 1727 ndp->requests[i].ndp = ndp; --- 20 unchanged lines hidden (view full) --- 1748 1749 return nd; 1750} 1751EXPORT_SYMBOL_GPL(ncsi_register_dev); 1752 1753int ncsi_start_dev(struct ncsi_dev *nd) 1754{ 1755 struct ncsi_dev_priv *ndp = TO_NCSI_DEV_PRIV(nd); |
1595 int ret; | |
1596 1597 if (nd->state != ncsi_dev_state_registered && 1598 nd->state != ncsi_dev_state_functional) 1599 return -ENOTTY; 1600 1601 if (!(ndp->flags & NCSI_DEV_PROBED)) { | 1756 1757 if (nd->state != ncsi_dev_state_registered && 1758 nd->state != ncsi_dev_state_functional) 1759 return -ENOTTY; 1760 1761 if (!(ndp->flags & NCSI_DEV_PROBED)) { |
1762 ndp->package_probe_id = 0; |
|
1602 nd->state = ncsi_dev_state_probe; 1603 schedule_work(&ndp->work); 1604 return 0; 1605 } 1606 | 1763 nd->state = ncsi_dev_state_probe; 1764 schedule_work(&ndp->work); 1765 return 0; 1766 } 1767 |
1607 if (ndp->flags & NCSI_DEV_HWA) { 1608 netdev_info(ndp->ndev.dev, "NCSI: Enabling HWA mode\n"); 1609 ret = ncsi_enable_hwa(ndp); 1610 } else { 1611 ret = ncsi_choose_active_channel(ndp); 1612 } 1613 1614 return ret; | 1768 return ncsi_reset_dev(nd); |
1615} 1616EXPORT_SYMBOL_GPL(ncsi_start_dev); 1617 1618void ncsi_stop_dev(struct ncsi_dev *nd) 1619{ 1620 struct ncsi_dev_priv *ndp = TO_NCSI_DEV_PRIV(nd); 1621 struct ncsi_package *np; 1622 struct ncsi_channel *nc; 1623 bool chained; 1624 int old_state; 1625 unsigned long flags; 1626 | 1769} 1770EXPORT_SYMBOL_GPL(ncsi_start_dev); 1771 1772void ncsi_stop_dev(struct ncsi_dev *nd) 1773{ 1774 struct ncsi_dev_priv *ndp = TO_NCSI_DEV_PRIV(nd); 1775 struct ncsi_package *np; 1776 struct ncsi_channel *nc; 1777 bool chained; 1778 int old_state; 1779 unsigned long flags; 1780 |
1627 /* Stop the channel monitor and reset channel's state */ | 1781 /* Stop the channel monitor on any active channels. Don't reset the 1782 * channel state so we know which were active when ncsi_start_dev() 1783 * is next called. 1784 */ |
1628 NCSI_FOR_EACH_PACKAGE(ndp, np) { 1629 NCSI_FOR_EACH_CHANNEL(np, nc) { 1630 ncsi_stop_channel_monitor(nc); 1631 1632 spin_lock_irqsave(&nc->lock, flags); 1633 chained = !list_empty(&nc->link); 1634 old_state = nc->state; | 1785 NCSI_FOR_EACH_PACKAGE(ndp, np) { 1786 NCSI_FOR_EACH_CHANNEL(np, nc) { 1787 ncsi_stop_channel_monitor(nc); 1788 1789 spin_lock_irqsave(&nc->lock, flags); 1790 chained = !list_empty(&nc->link); 1791 old_state = nc->state; |
1635 nc->state = NCSI_CHANNEL_INACTIVE; | |
1636 spin_unlock_irqrestore(&nc->lock, flags); 1637 1638 WARN_ON_ONCE(chained || 1639 old_state == NCSI_CHANNEL_INVISIBLE); 1640 } 1641 } 1642 1643 netdev_dbg(ndp->ndev.dev, "NCSI: Stopping device\n"); 1644 ncsi_report_link(ndp, true); 1645} 1646EXPORT_SYMBOL_GPL(ncsi_stop_dev); 1647 | 1792 spin_unlock_irqrestore(&nc->lock, flags); 1793 1794 WARN_ON_ONCE(chained || 1795 old_state == NCSI_CHANNEL_INVISIBLE); 1796 } 1797 } 1798 1799 netdev_dbg(ndp->ndev.dev, "NCSI: Stopping device\n"); 1800 ncsi_report_link(ndp, true); 1801} 1802EXPORT_SYMBOL_GPL(ncsi_stop_dev); 1803 |
1804int ncsi_reset_dev(struct ncsi_dev *nd) 1805{ 1806 struct ncsi_dev_priv *ndp = TO_NCSI_DEV_PRIV(nd); 1807 struct ncsi_channel *nc, *active, *tmp; 1808 struct ncsi_package *np; 1809 unsigned long flags; 1810 1811 spin_lock_irqsave(&ndp->lock, flags); 1812 1813 if (!(ndp->flags & NCSI_DEV_RESET)) { 1814 /* Haven't been called yet, check states */ 1815 switch (nd->state & ncsi_dev_state_major) { 1816 case ncsi_dev_state_registered: 1817 case ncsi_dev_state_probe: 1818 /* Not even probed yet - do nothing */ 1819 spin_unlock_irqrestore(&ndp->lock, flags); 1820 return 0; 1821 case ncsi_dev_state_suspend: 1822 case ncsi_dev_state_config: 1823 /* Wait for the channel to finish its suspend/config 1824 * operation; once it finishes it will check for 1825 * NCSI_DEV_RESET and reset the state. 1826 */ 1827 ndp->flags |= NCSI_DEV_RESET; 1828 spin_unlock_irqrestore(&ndp->lock, flags); 1829 return 0; 1830 } 1831 } else { 1832 switch (nd->state) { 1833 case ncsi_dev_state_suspend_done: 1834 case ncsi_dev_state_config_done: 1835 case ncsi_dev_state_functional: 1836 /* Ok */ 1837 break; 1838 default: 1839 /* Current reset operation happening */ 1840 spin_unlock_irqrestore(&ndp->lock, flags); 1841 return 0; 1842 } 1843 } 1844 1845 if (!list_empty(&ndp->channel_queue)) { 1846 /* Clear any channel queue we may have interrupted */ 1847 list_for_each_entry_safe(nc, tmp, &ndp->channel_queue, link) 1848 list_del_init(&nc->link); 1849 } 1850 spin_unlock_irqrestore(&ndp->lock, flags); 1851 1852 active = NULL; 1853 NCSI_FOR_EACH_PACKAGE(ndp, np) { 1854 NCSI_FOR_EACH_CHANNEL(np, nc) { 1855 spin_lock_irqsave(&nc->lock, flags); 1856 1857 if (nc->state == NCSI_CHANNEL_ACTIVE) { 1858 active = nc; 1859 nc->state = NCSI_CHANNEL_INVISIBLE; 1860 spin_unlock_irqrestore(&nc->lock, flags); 1861 ncsi_stop_channel_monitor(nc); 1862 break; 1863 } 1864 1865 spin_unlock_irqrestore(&nc->lock, flags); 1866 } 1867 if (active) 1868 break; 1869 } 1870 1871 if (!active) { 1872 /* Done */ 1873 spin_lock_irqsave(&ndp->lock, flags); 1874 ndp->flags &= ~NCSI_DEV_RESET; 1875 spin_unlock_irqrestore(&ndp->lock, flags); 1876 return ncsi_choose_active_channel(ndp); 1877 } 1878 1879 spin_lock_irqsave(&ndp->lock, flags); 1880 ndp->flags |= NCSI_DEV_RESET; 1881 ndp->active_channel = active; 1882 ndp->active_package = active->package; 1883 spin_unlock_irqrestore(&ndp->lock, flags); 1884 1885 nd->state = ncsi_dev_state_suspend; 1886 schedule_work(&ndp->work); 1887 return 0; 1888} 1889 |
|
1648void ncsi_unregister_dev(struct ncsi_dev *nd) 1649{ 1650 struct ncsi_dev_priv *ndp = TO_NCSI_DEV_PRIV(nd); 1651 struct ncsi_package *np, *tmp; 1652 unsigned long flags; 1653 1654 dev_remove_pack(&ndp->ptype); 1655 --- 16 unchanged lines hidden --- | 1890void ncsi_unregister_dev(struct ncsi_dev *nd) 1891{ 1892 struct ncsi_dev_priv *ndp = TO_NCSI_DEV_PRIV(nd); 1893 struct ncsi_package *np, *tmp; 1894 unsigned long flags; 1895 1896 dev_remove_pack(&ndp->ptype); 1897 --- 16 unchanged lines hidden --- |