diff options
Diffstat (limited to 'drivers/net/s2io.c')
| -rw-r--r-- | drivers/net/s2io.c | 496 |
1 files changed, 295 insertions, 201 deletions
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index 523478ebfd69..b5c1e663417d 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c | |||
| @@ -86,7 +86,7 @@ | |||
| 86 | #include "s2io.h" | 86 | #include "s2io.h" |
| 87 | #include "s2io-regs.h" | 87 | #include "s2io-regs.h" |
| 88 | 88 | ||
| 89 | #define DRV_VERSION "2.0.26.23" | 89 | #define DRV_VERSION "2.0.26.24" |
| 90 | 90 | ||
| 91 | /* S2io Driver name & version. */ | 91 | /* S2io Driver name & version. */ |
| 92 | static char s2io_driver_name[] = "Neterion"; | 92 | static char s2io_driver_name[] = "Neterion"; |
| @@ -1113,9 +1113,10 @@ static int s2io_on_nec_bridge(struct pci_dev *s2io_pdev) | |||
| 1113 | struct pci_dev *tdev = NULL; | 1113 | struct pci_dev *tdev = NULL; |
| 1114 | while ((tdev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, tdev)) != NULL) { | 1114 | while ((tdev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, tdev)) != NULL) { |
| 1115 | if (tdev->vendor == NEC_VENID && tdev->device == NEC_DEVID) { | 1115 | if (tdev->vendor == NEC_VENID && tdev->device == NEC_DEVID) { |
| 1116 | if (tdev->bus == s2io_pdev->bus->parent) | 1116 | if (tdev->bus == s2io_pdev->bus->parent) { |
| 1117 | pci_dev_put(tdev); | 1117 | pci_dev_put(tdev); |
| 1118 | return 1; | 1118 | return 1; |
| 1119 | } | ||
| 1119 | } | 1120 | } |
| 1120 | } | 1121 | } |
| 1121 | return 0; | 1122 | return 0; |
| @@ -1219,15 +1220,33 @@ static int init_tti(struct s2io_nic *nic, int link) | |||
| 1219 | TTI_DATA1_MEM_TX_URNG_B(0x10) | | 1220 | TTI_DATA1_MEM_TX_URNG_B(0x10) | |
| 1220 | TTI_DATA1_MEM_TX_URNG_C(0x30) | | 1221 | TTI_DATA1_MEM_TX_URNG_C(0x30) | |
| 1221 | TTI_DATA1_MEM_TX_TIMER_AC_EN; | 1222 | TTI_DATA1_MEM_TX_TIMER_AC_EN; |
| 1222 | 1223 | if (i == 0) | |
| 1223 | if (use_continuous_tx_intrs && (link == LINK_UP)) | 1224 | if (use_continuous_tx_intrs && (link == LINK_UP)) |
| 1224 | val64 |= TTI_DATA1_MEM_TX_TIMER_CI_EN; | 1225 | val64 |= TTI_DATA1_MEM_TX_TIMER_CI_EN; |
| 1225 | writeq(val64, &bar0->tti_data1_mem); | 1226 | writeq(val64, &bar0->tti_data1_mem); |
| 1226 | 1227 | ||
| 1227 | val64 = TTI_DATA2_MEM_TX_UFC_A(0x10) | | 1228 | if (nic->config.intr_type == MSI_X) { |
| 1228 | TTI_DATA2_MEM_TX_UFC_B(0x20) | | 1229 | val64 = TTI_DATA2_MEM_TX_UFC_A(0x10) | |
| 1229 | TTI_DATA2_MEM_TX_UFC_C(0x40) | | 1230 | TTI_DATA2_MEM_TX_UFC_B(0x100) | |
| 1230 | TTI_DATA2_MEM_TX_UFC_D(0x80); | 1231 | TTI_DATA2_MEM_TX_UFC_C(0x200) | |
| 1232 | TTI_DATA2_MEM_TX_UFC_D(0x300); | ||
| 1233 | } else { | ||
| 1234 | if ((nic->config.tx_steering_type == | ||
| 1235 | TX_DEFAULT_STEERING) && | ||
| 1236 | (config->tx_fifo_num > 1) && | ||
| 1237 | (i >= nic->udp_fifo_idx) && | ||
| 1238 | (i < (nic->udp_fifo_idx + | ||
| 1239 | nic->total_udp_fifos))) | ||
| 1240 | val64 = TTI_DATA2_MEM_TX_UFC_A(0x50) | | ||
| 1241 | TTI_DATA2_MEM_TX_UFC_B(0x80) | | ||
| 1242 | TTI_DATA2_MEM_TX_UFC_C(0x100) | | ||
| 1243 | TTI_DATA2_MEM_TX_UFC_D(0x120); | ||
| 1244 | else | ||
| 1245 | val64 = TTI_DATA2_MEM_TX_UFC_A(0x10) | | ||
| 1246 | TTI_DATA2_MEM_TX_UFC_B(0x20) | | ||
| 1247 | TTI_DATA2_MEM_TX_UFC_C(0x40) | | ||
| 1248 | TTI_DATA2_MEM_TX_UFC_D(0x80); | ||
| 1249 | } | ||
| 1231 | 1250 | ||
| 1232 | writeq(val64, &bar0->tti_data2_mem); | 1251 | writeq(val64, &bar0->tti_data2_mem); |
| 1233 | 1252 | ||
| @@ -2813,6 +2832,15 @@ static void free_rx_buffers(struct s2io_nic *sp) | |||
| 2813 | } | 2832 | } |
| 2814 | } | 2833 | } |
| 2815 | 2834 | ||
| 2835 | static int s2io_chk_rx_buffers(struct ring_info *ring) | ||
| 2836 | { | ||
| 2837 | if (fill_rx_buffers(ring) == -ENOMEM) { | ||
| 2838 | DBG_PRINT(INFO_DBG, "%s:Out of memory", ring->dev->name); | ||
| 2839 | DBG_PRINT(INFO_DBG, " in Rx Intr!!\n"); | ||
| 2840 | } | ||
| 2841 | return 0; | ||
| 2842 | } | ||
| 2843 | |||
| 2816 | /** | 2844 | /** |
| 2817 | * s2io_poll - Rx interrupt handler for NAPI support | 2845 | * s2io_poll - Rx interrupt handler for NAPI support |
| 2818 | * @napi : pointer to the napi structure. | 2846 | * @napi : pointer to the napi structure. |
| @@ -2826,57 +2854,73 @@ static void free_rx_buffers(struct s2io_nic *sp) | |||
| 2826 | * 0 on success and 1 if there are No Rx packets to be processed. | 2854 | * 0 on success and 1 if there are No Rx packets to be processed. |
| 2827 | */ | 2855 | */ |
| 2828 | 2856 | ||
| 2829 | static int s2io_poll(struct napi_struct *napi, int budget) | 2857 | static int s2io_poll_msix(struct napi_struct *napi, int budget) |
| 2830 | { | 2858 | { |
| 2831 | struct s2io_nic *nic = container_of(napi, struct s2io_nic, napi); | 2859 | struct ring_info *ring = container_of(napi, struct ring_info, napi); |
| 2832 | struct net_device *dev = nic->dev; | 2860 | struct net_device *dev = ring->dev; |
| 2833 | int pkt_cnt = 0, org_pkts_to_process; | ||
| 2834 | struct mac_info *mac_control; | ||
| 2835 | struct config_param *config; | 2861 | struct config_param *config; |
| 2862 | struct mac_info *mac_control; | ||
| 2863 | int pkts_processed = 0; | ||
| 2864 | u8 __iomem *addr = NULL; | ||
| 2865 | u8 val8 = 0; | ||
| 2866 | struct s2io_nic *nic = dev->priv; | ||
| 2836 | struct XENA_dev_config __iomem *bar0 = nic->bar0; | 2867 | struct XENA_dev_config __iomem *bar0 = nic->bar0; |
| 2837 | int i; | 2868 | int budget_org = budget; |
| 2838 | 2869 | ||
| 2839 | mac_control = &nic->mac_control; | ||
| 2840 | config = &nic->config; | 2870 | config = &nic->config; |
| 2871 | mac_control = &nic->mac_control; | ||
| 2841 | 2872 | ||
| 2842 | nic->pkts_to_process = budget; | 2873 | if (unlikely(!is_s2io_card_up(nic))) |
| 2843 | org_pkts_to_process = nic->pkts_to_process; | 2874 | return 0; |
| 2844 | 2875 | ||
| 2845 | writeq(S2IO_MINUS_ONE, &bar0->rx_traffic_int); | 2876 | pkts_processed = rx_intr_handler(ring, budget); |
| 2846 | readl(&bar0->rx_traffic_int); | 2877 | s2io_chk_rx_buffers(ring); |
| 2847 | 2878 | ||
| 2848 | for (i = 0; i < config->rx_ring_num; i++) { | 2879 | if (pkts_processed < budget_org) { |
| 2849 | rx_intr_handler(&mac_control->rings[i]); | 2880 | netif_rx_complete(dev, napi); |
| 2850 | pkt_cnt = org_pkts_to_process - nic->pkts_to_process; | 2881 | /*Re Enable MSI-Rx Vector*/ |
| 2851 | if (!nic->pkts_to_process) { | 2882 | addr = (u8 __iomem *)&bar0->xmsi_mask_reg; |
| 2852 | /* Quota for the current iteration has been met */ | 2883 | addr += 7 - ring->ring_no; |
| 2853 | goto no_rx; | 2884 | val8 = (ring->ring_no == 0) ? 0x3f : 0xbf; |
| 2854 | } | 2885 | writeb(val8, addr); |
| 2886 | val8 = readb(addr); | ||
| 2855 | } | 2887 | } |
| 2888 | return pkts_processed; | ||
| 2889 | } | ||
| 2890 | static int s2io_poll_inta(struct napi_struct *napi, int budget) | ||
| 2891 | { | ||
| 2892 | struct s2io_nic *nic = container_of(napi, struct s2io_nic, napi); | ||
| 2893 | struct ring_info *ring; | ||
| 2894 | struct net_device *dev = nic->dev; | ||
| 2895 | struct config_param *config; | ||
| 2896 | struct mac_info *mac_control; | ||
| 2897 | int pkts_processed = 0; | ||
| 2898 | int ring_pkts_processed, i; | ||
| 2899 | struct XENA_dev_config __iomem *bar0 = nic->bar0; | ||
| 2900 | int budget_org = budget; | ||
| 2856 | 2901 | ||
| 2857 | netif_rx_complete(dev, napi); | 2902 | config = &nic->config; |
| 2903 | mac_control = &nic->mac_control; | ||
| 2858 | 2904 | ||
| 2859 | for (i = 0; i < config->rx_ring_num; i++) { | 2905 | if (unlikely(!is_s2io_card_up(nic))) |
| 2860 | if (fill_rx_buffers(&mac_control->rings[i]) == -ENOMEM) { | 2906 | return 0; |
| 2861 | DBG_PRINT(INFO_DBG, "%s:Out of memory", dev->name); | ||
| 2862 | DBG_PRINT(INFO_DBG, " in Rx Poll!!\n"); | ||
| 2863 | break; | ||
| 2864 | } | ||
| 2865 | } | ||
| 2866 | /* Re enable the Rx interrupts. */ | ||
| 2867 | writeq(0x0, &bar0->rx_traffic_mask); | ||
| 2868 | readl(&bar0->rx_traffic_mask); | ||
| 2869 | return pkt_cnt; | ||
| 2870 | 2907 | ||
| 2871 | no_rx: | ||
| 2872 | for (i = 0; i < config->rx_ring_num; i++) { | 2908 | for (i = 0; i < config->rx_ring_num; i++) { |
| 2873 | if (fill_rx_buffers(&mac_control->rings[i]) == -ENOMEM) { | 2909 | ring = &mac_control->rings[i]; |
| 2874 | DBG_PRINT(INFO_DBG, "%s:Out of memory", dev->name); | 2910 | ring_pkts_processed = rx_intr_handler(ring, budget); |
| 2875 | DBG_PRINT(INFO_DBG, " in Rx Poll!!\n"); | 2911 | s2io_chk_rx_buffers(ring); |
| 2912 | pkts_processed += ring_pkts_processed; | ||
| 2913 | budget -= ring_pkts_processed; | ||
| 2914 | if (budget <= 0) | ||
| 2876 | break; | 2915 | break; |
| 2877 | } | ||
| 2878 | } | 2916 | } |
| 2879 | return pkt_cnt; | 2917 | if (pkts_processed < budget_org) { |
| 2918 | netif_rx_complete(dev, napi); | ||
| 2919 | /* Re enable the Rx interrupts for the ring */ | ||
| 2920 | writeq(0, &bar0->rx_traffic_mask); | ||
| 2921 | readl(&bar0->rx_traffic_mask); | ||
| 2922 | } | ||
| 2923 | return pkts_processed; | ||
| 2880 | } | 2924 | } |
| 2881 | 2925 | ||
| 2882 | #ifdef CONFIG_NET_POLL_CONTROLLER | 2926 | #ifdef CONFIG_NET_POLL_CONTROLLER |
| @@ -2918,7 +2962,7 @@ static void s2io_netpoll(struct net_device *dev) | |||
| 2918 | 2962 | ||
| 2919 | /* check for received packet and indicate up to network */ | 2963 | /* check for received packet and indicate up to network */ |
| 2920 | for (i = 0; i < config->rx_ring_num; i++) | 2964 | for (i = 0; i < config->rx_ring_num; i++) |
| 2921 | rx_intr_handler(&mac_control->rings[i]); | 2965 | rx_intr_handler(&mac_control->rings[i], 0); |
| 2922 | 2966 | ||
| 2923 | for (i = 0; i < config->rx_ring_num; i++) { | 2967 | for (i = 0; i < config->rx_ring_num; i++) { |
| 2924 | if (fill_rx_buffers(&mac_control->rings[i]) == -ENOMEM) { | 2968 | if (fill_rx_buffers(&mac_control->rings[i]) == -ENOMEM) { |
| @@ -2934,7 +2978,8 @@ static void s2io_netpoll(struct net_device *dev) | |||
| 2934 | 2978 | ||
| 2935 | /** | 2979 | /** |
| 2936 | * rx_intr_handler - Rx interrupt handler | 2980 | * rx_intr_handler - Rx interrupt handler |
| 2937 | * @nic: device private variable. | 2981 | * @ring_info: per ring structure. |
| 2982 | * @budget: budget for napi processing. | ||
| 2938 | * Description: | 2983 | * Description: |
| 2939 | * If the interrupt is because of a received frame or if the | 2984 | * If the interrupt is because of a received frame or if the |
| 2940 | * receive ring contains fresh as yet un-processed frames,this function is | 2985 | * receive ring contains fresh as yet un-processed frames,this function is |
| @@ -2942,15 +2987,15 @@ static void s2io_netpoll(struct net_device *dev) | |||
| 2942 | * stopped and sends the skb to the OSM's Rx handler and then increments | 2987 | * stopped and sends the skb to the OSM's Rx handler and then increments |
| 2943 | * the offset. | 2988 | * the offset. |
| 2944 | * Return Value: | 2989 | * Return Value: |
| 2945 | * NONE. | 2990 | * No. of napi packets processed. |
| 2946 | */ | 2991 | */ |
| 2947 | static void rx_intr_handler(struct ring_info *ring_data) | 2992 | static int rx_intr_handler(struct ring_info *ring_data, int budget) |
| 2948 | { | 2993 | { |
| 2949 | int get_block, put_block; | 2994 | int get_block, put_block; |
| 2950 | struct rx_curr_get_info get_info, put_info; | 2995 | struct rx_curr_get_info get_info, put_info; |
| 2951 | struct RxD_t *rxdp; | 2996 | struct RxD_t *rxdp; |
| 2952 | struct sk_buff *skb; | 2997 | struct sk_buff *skb; |
| 2953 | int pkt_cnt = 0; | 2998 | int pkt_cnt = 0, napi_pkts = 0; |
| 2954 | int i; | 2999 | int i; |
| 2955 | struct RxD1* rxdp1; | 3000 | struct RxD1* rxdp1; |
| 2956 | struct RxD3* rxdp3; | 3001 | struct RxD3* rxdp3; |
| @@ -2977,7 +3022,7 @@ static void rx_intr_handler(struct ring_info *ring_data) | |||
| 2977 | DBG_PRINT(ERR_DBG, "%s: The skb is ", | 3022 | DBG_PRINT(ERR_DBG, "%s: The skb is ", |
| 2978 | ring_data->dev->name); | 3023 | ring_data->dev->name); |
| 2979 | DBG_PRINT(ERR_DBG, "Null in Rx Intr\n"); | 3024 | DBG_PRINT(ERR_DBG, "Null in Rx Intr\n"); |
| 2980 | return; | 3025 | return 0; |
| 2981 | } | 3026 | } |
| 2982 | if (ring_data->rxd_mode == RXD_MODE_1) { | 3027 | if (ring_data->rxd_mode == RXD_MODE_1) { |
| 2983 | rxdp1 = (struct RxD1*)rxdp; | 3028 | rxdp1 = (struct RxD1*)rxdp; |
| @@ -3014,9 +3059,10 @@ static void rx_intr_handler(struct ring_info *ring_data) | |||
| 3014 | rxdp = ring_data->rx_blocks[get_block].block_virt_addr; | 3059 | rxdp = ring_data->rx_blocks[get_block].block_virt_addr; |
| 3015 | } | 3060 | } |
| 3016 | 3061 | ||
| 3017 | if(ring_data->nic->config.napi){ | 3062 | if (ring_data->nic->config.napi) { |
| 3018 | ring_data->nic->pkts_to_process -= 1; | 3063 | budget--; |
| 3019 | if (!ring_data->nic->pkts_to_process) | 3064 | napi_pkts++; |
| 3065 | if (!budget) | ||
| 3020 | break; | 3066 | break; |
| 3021 | } | 3067 | } |
| 3022 | pkt_cnt++; | 3068 | pkt_cnt++; |
| @@ -3034,6 +3080,7 @@ static void rx_intr_handler(struct ring_info *ring_data) | |||
| 3034 | } | 3080 | } |
| 3035 | } | 3081 | } |
| 3036 | } | 3082 | } |
| 3083 | return(napi_pkts); | ||
| 3037 | } | 3084 | } |
| 3038 | 3085 | ||
| 3039 | /** | 3086 | /** |
| @@ -3730,14 +3777,19 @@ static void restore_xmsi_data(struct s2io_nic *nic) | |||
| 3730 | { | 3777 | { |
| 3731 | struct XENA_dev_config __iomem *bar0 = nic->bar0; | 3778 | struct XENA_dev_config __iomem *bar0 = nic->bar0; |
| 3732 | u64 val64; | 3779 | u64 val64; |
| 3733 | int i; | 3780 | int i, msix_index; |
| 3781 | |||
| 3782 | |||
| 3783 | if (nic->device_type == XFRAME_I_DEVICE) | ||
| 3784 | return; | ||
| 3734 | 3785 | ||
| 3735 | for (i=0; i < MAX_REQUESTED_MSI_X; i++) { | 3786 | for (i=0; i < MAX_REQUESTED_MSI_X; i++) { |
| 3787 | msix_index = (i) ? ((i-1) * 8 + 1): 0; | ||
| 3736 | writeq(nic->msix_info[i].addr, &bar0->xmsi_address); | 3788 | writeq(nic->msix_info[i].addr, &bar0->xmsi_address); |
| 3737 | writeq(nic->msix_info[i].data, &bar0->xmsi_data); | 3789 | writeq(nic->msix_info[i].data, &bar0->xmsi_data); |
| 3738 | val64 = (s2BIT(7) | s2BIT(15) | vBIT(i, 26, 6)); | 3790 | val64 = (s2BIT(7) | s2BIT(15) | vBIT(msix_index, 26, 6)); |
| 3739 | writeq(val64, &bar0->xmsi_access); | 3791 | writeq(val64, &bar0->xmsi_access); |
| 3740 | if (wait_for_msix_trans(nic, i)) { | 3792 | if (wait_for_msix_trans(nic, msix_index)) { |
| 3741 | DBG_PRINT(ERR_DBG, "failed in %s\n", __FUNCTION__); | 3793 | DBG_PRINT(ERR_DBG, "failed in %s\n", __FUNCTION__); |
| 3742 | continue; | 3794 | continue; |
| 3743 | } | 3795 | } |
| @@ -3748,13 +3800,17 @@ static void store_xmsi_data(struct s2io_nic *nic) | |||
| 3748 | { | 3800 | { |
| 3749 | struct XENA_dev_config __iomem *bar0 = nic->bar0; | 3801 | struct XENA_dev_config __iomem *bar0 = nic->bar0; |
| 3750 | u64 val64, addr, data; | 3802 | u64 val64, addr, data; |
| 3751 | int i; | 3803 | int i, msix_index; |
| 3804 | |||
| 3805 | if (nic->device_type == XFRAME_I_DEVICE) | ||
| 3806 | return; | ||
| 3752 | 3807 | ||
| 3753 | /* Store and display */ | 3808 | /* Store and display */ |
| 3754 | for (i=0; i < MAX_REQUESTED_MSI_X; i++) { | 3809 | for (i=0; i < MAX_REQUESTED_MSI_X; i++) { |
| 3755 | val64 = (s2BIT(15) | vBIT(i, 26, 6)); | 3810 | msix_index = (i) ? ((i-1) * 8 + 1): 0; |
| 3811 | val64 = (s2BIT(15) | vBIT(msix_index, 26, 6)); | ||
| 3756 | writeq(val64, &bar0->xmsi_access); | 3812 | writeq(val64, &bar0->xmsi_access); |
| 3757 | if (wait_for_msix_trans(nic, i)) { | 3813 | if (wait_for_msix_trans(nic, msix_index)) { |
| 3758 | DBG_PRINT(ERR_DBG, "failed in %s\n", __FUNCTION__); | 3814 | DBG_PRINT(ERR_DBG, "failed in %s\n", __FUNCTION__); |
| 3759 | continue; | 3815 | continue; |
| 3760 | } | 3816 | } |
| @@ -3770,11 +3826,11 @@ static void store_xmsi_data(struct s2io_nic *nic) | |||
| 3770 | static int s2io_enable_msi_x(struct s2io_nic *nic) | 3826 | static int s2io_enable_msi_x(struct s2io_nic *nic) |
| 3771 | { | 3827 | { |
| 3772 | struct XENA_dev_config __iomem *bar0 = nic->bar0; | 3828 | struct XENA_dev_config __iomem *bar0 = nic->bar0; |
| 3773 | u64 tx_mat, rx_mat; | 3829 | u64 rx_mat; |
| 3774 | u16 msi_control; /* Temp variable */ | 3830 | u16 msi_control; /* Temp variable */ |
| 3775 | int ret, i, j, msix_indx = 1; | 3831 | int ret, i, j, msix_indx = 1; |
| 3776 | 3832 | ||
| 3777 | nic->entries = kcalloc(MAX_REQUESTED_MSI_X, sizeof(struct msix_entry), | 3833 | nic->entries = kmalloc(nic->num_entries * sizeof(struct msix_entry), |
| 3778 | GFP_KERNEL); | 3834 | GFP_KERNEL); |
| 3779 | if (!nic->entries) { | 3835 | if (!nic->entries) { |
| 3780 | DBG_PRINT(INFO_DBG, "%s: Memory allocation failed\n", \ | 3836 | DBG_PRINT(INFO_DBG, "%s: Memory allocation failed\n", \ |
| @@ -3783,10 +3839,12 @@ static int s2io_enable_msi_x(struct s2io_nic *nic) | |||
| 3783 | return -ENOMEM; | 3839 | return -ENOMEM; |
| 3784 | } | 3840 | } |
| 3785 | nic->mac_control.stats_info->sw_stat.mem_allocated | 3841 | nic->mac_control.stats_info->sw_stat.mem_allocated |
| 3786 | += (MAX_REQUESTED_MSI_X * sizeof(struct msix_entry)); | 3842 | += (nic->num_entries * sizeof(struct msix_entry)); |
| 3843 | |||
| 3844 | memset(nic->entries, 0, nic->num_entries * sizeof(struct msix_entry)); | ||
| 3787 | 3845 | ||
| 3788 | nic->s2io_entries = | 3846 | nic->s2io_entries = |
| 3789 | kcalloc(MAX_REQUESTED_MSI_X, sizeof(struct s2io_msix_entry), | 3847 | kmalloc(nic->num_entries * sizeof(struct s2io_msix_entry), |
| 3790 | GFP_KERNEL); | 3848 | GFP_KERNEL); |
| 3791 | if (!nic->s2io_entries) { | 3849 | if (!nic->s2io_entries) { |
| 3792 | DBG_PRINT(INFO_DBG, "%s: Memory allocation failed\n", | 3850 | DBG_PRINT(INFO_DBG, "%s: Memory allocation failed\n", |
| @@ -3794,60 +3852,52 @@ static int s2io_enable_msi_x(struct s2io_nic *nic) | |||
| 3794 | nic->mac_control.stats_info->sw_stat.mem_alloc_fail_cnt++; | 3852 | nic->mac_control.stats_info->sw_stat.mem_alloc_fail_cnt++; |
| 3795 | kfree(nic->entries); | 3853 | kfree(nic->entries); |
| 3796 | nic->mac_control.stats_info->sw_stat.mem_freed | 3854 | nic->mac_control.stats_info->sw_stat.mem_freed |
| 3797 | += (MAX_REQUESTED_MSI_X * sizeof(struct msix_entry)); | 3855 | += (nic->num_entries * sizeof(struct msix_entry)); |
| 3798 | return -ENOMEM; | 3856 | return -ENOMEM; |
| 3799 | } | 3857 | } |
| 3800 | nic->mac_control.stats_info->sw_stat.mem_allocated | 3858 | nic->mac_control.stats_info->sw_stat.mem_allocated |
| 3801 | += (MAX_REQUESTED_MSI_X * sizeof(struct s2io_msix_entry)); | 3859 | += (nic->num_entries * sizeof(struct s2io_msix_entry)); |
| 3802 | 3860 | memset(nic->s2io_entries, 0, | |
| 3803 | for (i=0; i< MAX_REQUESTED_MSI_X; i++) { | 3861 | nic->num_entries * sizeof(struct s2io_msix_entry)); |
| 3804 | nic->entries[i].entry = i; | 3862 | |
| 3805 | nic->s2io_entries[i].entry = i; | 3863 | nic->entries[0].entry = 0; |
| 3864 | nic->s2io_entries[0].entry = 0; | ||
| 3865 | nic->s2io_entries[0].in_use = MSIX_FLG; | ||
| 3866 | nic->s2io_entries[0].type = MSIX_ALARM_TYPE; | ||
| 3867 | nic->s2io_entries[0].arg = &nic->mac_control.fifos; | ||
| 3868 | |||
| 3869 | for (i = 1; i < nic->num_entries; i++) { | ||
| 3870 | nic->entries[i].entry = ((i - 1) * 8) + 1; | ||
| 3871 | nic->s2io_entries[i].entry = ((i - 1) * 8) + 1; | ||
| 3806 | nic->s2io_entries[i].arg = NULL; | 3872 | nic->s2io_entries[i].arg = NULL; |
| 3807 | nic->s2io_entries[i].in_use = 0; | 3873 | nic->s2io_entries[i].in_use = 0; |
| 3808 | } | 3874 | } |
| 3809 | 3875 | ||
| 3810 | tx_mat = readq(&bar0->tx_mat0_n[0]); | ||
| 3811 | for (i=0; i<nic->config.tx_fifo_num; i++, msix_indx++) { | ||
| 3812 | tx_mat |= TX_MAT_SET(i, msix_indx); | ||
| 3813 | nic->s2io_entries[msix_indx].arg = &nic->mac_control.fifos[i]; | ||
| 3814 | nic->s2io_entries[msix_indx].type = MSIX_FIFO_TYPE; | ||
| 3815 | nic->s2io_entries[msix_indx].in_use = MSIX_FLG; | ||
| 3816 | } | ||
| 3817 | writeq(tx_mat, &bar0->tx_mat0_n[0]); | ||
| 3818 | |||
| 3819 | rx_mat = readq(&bar0->rx_mat); | 3876 | rx_mat = readq(&bar0->rx_mat); |
| 3820 | for (j = 0; j < nic->config.rx_ring_num; j++, msix_indx++) { | 3877 | for (j = 0; j < nic->config.rx_ring_num; j++) { |
| 3821 | rx_mat |= RX_MAT_SET(j, msix_indx); | 3878 | rx_mat |= RX_MAT_SET(j, msix_indx); |
| 3822 | nic->s2io_entries[msix_indx].arg | 3879 | nic->s2io_entries[j+1].arg = &nic->mac_control.rings[j]; |
| 3823 | = &nic->mac_control.rings[j]; | 3880 | nic->s2io_entries[j+1].type = MSIX_RING_TYPE; |
| 3824 | nic->s2io_entries[msix_indx].type = MSIX_RING_TYPE; | 3881 | nic->s2io_entries[j+1].in_use = MSIX_FLG; |
| 3825 | nic->s2io_entries[msix_indx].in_use = MSIX_FLG; | 3882 | msix_indx += 8; |
| 3826 | } | 3883 | } |
| 3827 | writeq(rx_mat, &bar0->rx_mat); | 3884 | writeq(rx_mat, &bar0->rx_mat); |
| 3885 | readq(&bar0->rx_mat); | ||
| 3828 | 3886 | ||
| 3829 | nic->avail_msix_vectors = 0; | 3887 | ret = pci_enable_msix(nic->pdev, nic->entries, nic->num_entries); |
| 3830 | ret = pci_enable_msix(nic->pdev, nic->entries, MAX_REQUESTED_MSI_X); | ||
| 3831 | /* We fail init if error or we get less vectors than min required */ | 3888 | /* We fail init if error or we get less vectors than min required */ |
| 3832 | if (ret >= (nic->config.tx_fifo_num + nic->config.rx_ring_num + 1)) { | ||
| 3833 | nic->avail_msix_vectors = ret; | ||
| 3834 | ret = pci_enable_msix(nic->pdev, nic->entries, ret); | ||
| 3835 | } | ||
| 3836 | if (ret) { | 3889 | if (ret) { |
| 3837 | DBG_PRINT(ERR_DBG, "%s: Enabling MSIX failed\n", nic->dev->name); | 3890 | DBG_PRINT(ERR_DBG, "%s: Enabling MSIX failed\n", nic->dev->name); |
| 3838 | kfree(nic->entries); | 3891 | kfree(nic->entries); |
| 3839 | nic->mac_control.stats_info->sw_stat.mem_freed | 3892 | nic->mac_control.stats_info->sw_stat.mem_freed |
| 3840 | += (MAX_REQUESTED_MSI_X * sizeof(struct msix_entry)); | 3893 | += (nic->num_entries * sizeof(struct msix_entry)); |
| 3841 | kfree(nic->s2io_entries); | 3894 | kfree(nic->s2io_entries); |
| 3842 | nic->mac_control.stats_info->sw_stat.mem_freed | 3895 | nic->mac_control.stats_info->sw_stat.mem_freed |
| 3843 | += (MAX_REQUESTED_MSI_X * sizeof(struct s2io_msix_entry)); | 3896 | += (nic->num_entries * sizeof(struct s2io_msix_entry)); |
| 3844 | nic->entries = NULL; | 3897 | nic->entries = NULL; |
| 3845 | nic->s2io_entries = NULL; | 3898 | nic->s2io_entries = NULL; |
| 3846 | nic->avail_msix_vectors = 0; | ||
| 3847 | return -ENOMEM; | 3899 | return -ENOMEM; |
| 3848 | } | 3900 | } |
| 3849 | if (!nic->avail_msix_vectors) | ||
| 3850 | nic->avail_msix_vectors = MAX_REQUESTED_MSI_X; | ||
| 3851 | 3901 | ||
| 3852 | /* | 3902 | /* |
| 3853 | * To enable MSI-X, MSI also needs to be enabled, due to a bug | 3903 | * To enable MSI-X, MSI also needs to be enabled, due to a bug |
| @@ -3919,7 +3969,7 @@ static void remove_msix_isr(struct s2io_nic *sp) | |||
| 3919 | int i; | 3969 | int i; |
| 3920 | u16 msi_control; | 3970 | u16 msi_control; |
| 3921 | 3971 | ||
| 3922 | for (i = 0; i < MAX_REQUESTED_MSI_X; i++) { | 3972 | for (i = 0; i < sp->num_entries; i++) { |
| 3923 | if (sp->s2io_entries[i].in_use == | 3973 | if (sp->s2io_entries[i].in_use == |
| 3924 | MSIX_REGISTERED_SUCCESS) { | 3974 | MSIX_REGISTERED_SUCCESS) { |
| 3925 | int vector = sp->entries[i].vector; | 3975 | int vector = sp->entries[i].vector; |
| @@ -3975,29 +4025,6 @@ static int s2io_open(struct net_device *dev) | |||
| 3975 | netif_carrier_off(dev); | 4025 | netif_carrier_off(dev); |
| 3976 | sp->last_link_state = 0; | 4026 | sp->last_link_state = 0; |
| 3977 | 4027 | ||
| 3978 | if (sp->config.intr_type == MSI_X) { | ||
| 3979 | int ret = s2io_enable_msi_x(sp); | ||
| 3980 | |||
| 3981 | if (!ret) { | ||
| 3982 | ret = s2io_test_msi(sp); | ||
| 3983 | /* rollback MSI-X, will re-enable during add_isr() */ | ||
| 3984 | remove_msix_isr(sp); | ||
| 3985 | } | ||
| 3986 | if (ret) { | ||
| 3987 | |||
| 3988 | DBG_PRINT(ERR_DBG, | ||
| 3989 | "%s: MSI-X requested but failed to enable\n", | ||
| 3990 | dev->name); | ||
| 3991 | sp->config.intr_type = INTA; | ||
| 3992 | } | ||
| 3993 | } | ||
| 3994 | |||
| 3995 | /* NAPI doesn't work well with MSI(X) */ | ||
| 3996 | if (sp->config.intr_type != INTA) { | ||
| 3997 | if(sp->config.napi) | ||
| 3998 | sp->config.napi = 0; | ||
| 3999 | } | ||
| 4000 | |||
| 4001 | /* Initialize H/W and enable interrupts */ | 4028 | /* Initialize H/W and enable interrupts */ |
| 4002 | err = s2io_card_up(sp); | 4029 | err = s2io_card_up(sp); |
| 4003 | if (err) { | 4030 | if (err) { |
| @@ -4020,12 +4047,12 @@ hw_init_failed: | |||
| 4020 | if (sp->entries) { | 4047 | if (sp->entries) { |
| 4021 | kfree(sp->entries); | 4048 | kfree(sp->entries); |
| 4022 | sp->mac_control.stats_info->sw_stat.mem_freed | 4049 | sp->mac_control.stats_info->sw_stat.mem_freed |
| 4023 | += (MAX_REQUESTED_MSI_X * sizeof(struct msix_entry)); | 4050 | += (sp->num_entries * sizeof(struct msix_entry)); |
| 4024 | } | 4051 | } |
| 4025 | if (sp->s2io_entries) { | 4052 | if (sp->s2io_entries) { |
| 4026 | kfree(sp->s2io_entries); | 4053 | kfree(sp->s2io_entries); |
| 4027 | sp->mac_control.stats_info->sw_stat.mem_freed | 4054 | sp->mac_control.stats_info->sw_stat.mem_freed |
| 4028 | += (MAX_REQUESTED_MSI_X * sizeof(struct s2io_msix_entry)); | 4055 | += (sp->num_entries * sizeof(struct s2io_msix_entry)); |
| 4029 | } | 4056 | } |
| 4030 | } | 4057 | } |
| 4031 | return err; | 4058 | return err; |
| @@ -4327,40 +4354,65 @@ s2io_alarm_handle(unsigned long data) | |||
| 4327 | mod_timer(&sp->alarm_timer, jiffies + HZ / 2); | 4354 | mod_timer(&sp->alarm_timer, jiffies + HZ / 2); |
| 4328 | } | 4355 | } |
| 4329 | 4356 | ||
| 4330 | static int s2io_chk_rx_buffers(struct ring_info *ring) | ||
| 4331 | { | ||
| 4332 | if (fill_rx_buffers(ring) == -ENOMEM) { | ||
| 4333 | DBG_PRINT(INFO_DBG, "%s:Out of memory", ring->dev->name); | ||
| 4334 | DBG_PRINT(INFO_DBG, " in Rx Intr!!\n"); | ||
| 4335 | } | ||
| 4336 | return 0; | ||
| 4337 | } | ||
| 4338 | |||
| 4339 | static irqreturn_t s2io_msix_ring_handle(int irq, void *dev_id) | 4357 | static irqreturn_t s2io_msix_ring_handle(int irq, void *dev_id) |
| 4340 | { | 4358 | { |
| 4341 | struct ring_info *ring = (struct ring_info *)dev_id; | 4359 | struct ring_info *ring = (struct ring_info *)dev_id; |
| 4342 | struct s2io_nic *sp = ring->nic; | 4360 | struct s2io_nic *sp = ring->nic; |
| 4361 | struct XENA_dev_config __iomem *bar0 = sp->bar0; | ||
| 4362 | struct net_device *dev = sp->dev; | ||
| 4343 | 4363 | ||
| 4344 | if (!is_s2io_card_up(sp)) | 4364 | if (unlikely(!is_s2io_card_up(sp))) |
| 4345 | return IRQ_HANDLED; | 4365 | return IRQ_HANDLED; |
| 4346 | 4366 | ||
| 4347 | rx_intr_handler(ring); | 4367 | if (sp->config.napi) { |
| 4348 | s2io_chk_rx_buffers(ring); | 4368 | u8 __iomem *addr = NULL; |
| 4369 | u8 val8 = 0; | ||
| 4370 | |||
| 4371 | addr = (u8 __iomem *)&bar0->xmsi_mask_reg; | ||
| 4372 | addr += (7 - ring->ring_no); | ||
| 4373 | val8 = (ring->ring_no == 0) ? 0x7f : 0xff; | ||
| 4374 | writeb(val8, addr); | ||
| 4375 | val8 = readb(addr); | ||
| 4376 | netif_rx_schedule(dev, &ring->napi); | ||
| 4377 | } else { | ||
| 4378 | rx_intr_handler(ring, 0); | ||
| 4379 | s2io_chk_rx_buffers(ring); | ||
| 4380 | } | ||
| 4349 | 4381 | ||
| 4350 | return IRQ_HANDLED; | 4382 | return IRQ_HANDLED; |
| 4351 | } | 4383 | } |
| 4352 | 4384 | ||
| 4353 | static irqreturn_t s2io_msix_fifo_handle(int irq, void *dev_id) | 4385 | static irqreturn_t s2io_msix_fifo_handle(int irq, void *dev_id) |
| 4354 | { | 4386 | { |
| 4355 | struct fifo_info *fifo = (struct fifo_info *)dev_id; | 4387 | int i; |
| 4356 | struct s2io_nic *sp = fifo->nic; | 4388 | struct fifo_info *fifos = (struct fifo_info *)dev_id; |
| 4389 | struct s2io_nic *sp = fifos->nic; | ||
| 4390 | struct XENA_dev_config __iomem *bar0 = sp->bar0; | ||
| 4391 | struct config_param *config = &sp->config; | ||
| 4392 | u64 reason; | ||
| 4357 | 4393 | ||
| 4358 | if (!is_s2io_card_up(sp)) | 4394 | if (unlikely(!is_s2io_card_up(sp))) |
| 4395 | return IRQ_NONE; | ||
| 4396 | |||
| 4397 | reason = readq(&bar0->general_int_status); | ||
| 4398 | if (unlikely(reason == S2IO_MINUS_ONE)) | ||
| 4399 | /* Nothing much can be done. Get out */ | ||
| 4359 | return IRQ_HANDLED; | 4400 | return IRQ_HANDLED; |
| 4360 | 4401 | ||
| 4361 | tx_intr_handler(fifo); | 4402 | writeq(S2IO_MINUS_ONE, &bar0->general_int_mask); |
| 4403 | |||
| 4404 | if (reason & GEN_INTR_TXTRAFFIC) | ||
| 4405 | writeq(S2IO_MINUS_ONE, &bar0->tx_traffic_int); | ||
| 4406 | |||
| 4407 | for (i = 0; i < config->tx_fifo_num; i++) | ||
| 4408 | tx_intr_handler(&fifos[i]); | ||
| 4409 | |||
| 4410 | writeq(sp->general_int_mask, &bar0->general_int_mask); | ||
| 4411 | readl(&bar0->general_int_status); | ||
| 4412 | |||
| 4362 | return IRQ_HANDLED; | 4413 | return IRQ_HANDLED; |
| 4363 | } | 4414 | } |
| 4415 | |||
| 4364 | static void s2io_txpic_intr_handle(struct s2io_nic *sp) | 4416 | static void s2io_txpic_intr_handle(struct s2io_nic *sp) |
| 4365 | { | 4417 | { |
| 4366 | struct XENA_dev_config __iomem *bar0 = sp->bar0; | 4418 | struct XENA_dev_config __iomem *bar0 = sp->bar0; |
| @@ -4762,14 +4814,10 @@ static irqreturn_t s2io_isr(int irq, void *dev_id) | |||
| 4762 | 4814 | ||
| 4763 | if (config->napi) { | 4815 | if (config->napi) { |
| 4764 | if (reason & GEN_INTR_RXTRAFFIC) { | 4816 | if (reason & GEN_INTR_RXTRAFFIC) { |
| 4765 | if (likely(netif_rx_schedule_prep(dev, | 4817 | netif_rx_schedule(dev, &sp->napi); |
| 4766 | &sp->napi))) { | 4818 | writeq(S2IO_MINUS_ONE, &bar0->rx_traffic_mask); |
| 4767 | __netif_rx_schedule(dev, &sp->napi); | 4819 | writeq(S2IO_MINUS_ONE, &bar0->rx_traffic_int); |
| 4768 | writeq(S2IO_MINUS_ONE, | 4820 | readl(&bar0->rx_traffic_int); |
| 4769 | &bar0->rx_traffic_mask); | ||
| 4770 | } else | ||
| 4771 | writeq(S2IO_MINUS_ONE, | ||
| 4772 | &bar0->rx_traffic_int); | ||
| 4773 | } | 4821 | } |
| 4774 | } else { | 4822 | } else { |
| 4775 | /* | 4823 | /* |
| @@ -4781,7 +4829,7 @@ static irqreturn_t s2io_isr(int irq, void *dev_id) | |||
| 4781 | writeq(S2IO_MINUS_ONE, &bar0->rx_traffic_int); | 4829 | writeq(S2IO_MINUS_ONE, &bar0->rx_traffic_int); |
| 4782 | 4830 | ||
| 4783 | for (i = 0; i < config->rx_ring_num; i++) | 4831 | for (i = 0; i < config->rx_ring_num; i++) |
| 4784 | rx_intr_handler(&mac_control->rings[i]); | 4832 | rx_intr_handler(&mac_control->rings[i], 0); |
| 4785 | } | 4833 | } |
| 4786 | 4834 | ||
| 4787 | /* | 4835 | /* |
| @@ -6984,62 +7032,62 @@ static int s2io_add_isr(struct s2io_nic * sp) | |||
| 6984 | 7032 | ||
| 6985 | /* After proper initialization of H/W, register ISR */ | 7033 | /* After proper initialization of H/W, register ISR */ |
| 6986 | if (sp->config.intr_type == MSI_X) { | 7034 | if (sp->config.intr_type == MSI_X) { |
| 6987 | int i, msix_tx_cnt=0,msix_rx_cnt=0; | 7035 | int i, msix_rx_cnt = 0; |
| 6988 | 7036 | ||
| 6989 | for (i=1; (sp->s2io_entries[i].in_use == MSIX_FLG); i++) { | 7037 | for (i = 0; i < sp->num_entries; i++) { |
| 6990 | if (sp->s2io_entries[i].type == MSIX_FIFO_TYPE) { | 7038 | if (sp->s2io_entries[i].in_use == MSIX_FLG) { |
| 6991 | sprintf(sp->desc[i], "%s:MSI-X-%d-TX", | 7039 | if (sp->s2io_entries[i].type == |
| 7040 | MSIX_RING_TYPE) { | ||
| 7041 | sprintf(sp->desc[i], "%s:MSI-X-%d-RX", | ||
| 7042 | dev->name, i); | ||
| 7043 | err = request_irq(sp->entries[i].vector, | ||
| 7044 | s2io_msix_ring_handle, 0, | ||
| 7045 | sp->desc[i], | ||
| 7046 | sp->s2io_entries[i].arg); | ||
| 7047 | } else if (sp->s2io_entries[i].type == | ||
| 7048 | MSIX_ALARM_TYPE) { | ||
| 7049 | sprintf(sp->desc[i], "%s:MSI-X-%d-TX", | ||
| 6992 | dev->name, i); | 7050 | dev->name, i); |
| 6993 | err = request_irq(sp->entries[i].vector, | 7051 | err = request_irq(sp->entries[i].vector, |
| 6994 | s2io_msix_fifo_handle, 0, sp->desc[i], | 7052 | s2io_msix_fifo_handle, 0, |
| 6995 | sp->s2io_entries[i].arg); | 7053 | sp->desc[i], |
| 6996 | /* If either data or addr is zero print it */ | 7054 | sp->s2io_entries[i].arg); |
| 6997 | if(!(sp->msix_info[i].addr && | 7055 | |
| 6998 | sp->msix_info[i].data)) { | ||
| 6999 | DBG_PRINT(ERR_DBG, "%s @ Addr:0x%llx " | ||
| 7000 | "Data:0x%llx\n",sp->desc[i], | ||
| 7001 | (unsigned long long) | ||
| 7002 | sp->msix_info[i].addr, | ||
| 7003 | (unsigned long long) | ||
| 7004 | sp->msix_info[i].data); | ||
| 7005 | } else { | ||
| 7006 | msix_tx_cnt++; | ||
| 7007 | } | 7056 | } |
| 7008 | } else { | 7057 | /* if either data or addr is zero print it. */ |
| 7009 | sprintf(sp->desc[i], "%s:MSI-X-%d-RX", | 7058 | if (!(sp->msix_info[i].addr && |
| 7010 | dev->name, i); | ||
| 7011 | err = request_irq(sp->entries[i].vector, | ||
| 7012 | s2io_msix_ring_handle, 0, sp->desc[i], | ||
| 7013 | sp->s2io_entries[i].arg); | ||
| 7014 | /* If either data or addr is zero print it */ | ||
| 7015 | if(!(sp->msix_info[i].addr && | ||
| 7016 | sp->msix_info[i].data)) { | 7059 | sp->msix_info[i].data)) { |
| 7017 | DBG_PRINT(ERR_DBG, "%s @ Addr:0x%llx " | 7060 | DBG_PRINT(ERR_DBG, |
| 7018 | "Data:0x%llx\n",sp->desc[i], | 7061 | "%s @Addr:0x%llx Data:0x%llx\n", |
| 7062 | sp->desc[i], | ||
| 7019 | (unsigned long long) | 7063 | (unsigned long long) |
| 7020 | sp->msix_info[i].addr, | 7064 | sp->msix_info[i].addr, |
| 7021 | (unsigned long long) | 7065 | (unsigned long long) |
| 7022 | sp->msix_info[i].data); | 7066 | ntohl(sp->msix_info[i].data)); |
| 7023 | } else { | 7067 | } else |
| 7024 | msix_rx_cnt++; | 7068 | msix_rx_cnt++; |
| 7069 | if (err) { | ||
| 7070 | remove_msix_isr(sp); | ||
| 7071 | |||
| 7072 | DBG_PRINT(ERR_DBG, | ||
| 7073 | "%s:MSI-X-%d registration " | ||
| 7074 | "failed\n", dev->name, i); | ||
| 7075 | |||
| 7076 | DBG_PRINT(ERR_DBG, | ||
| 7077 | "%s: Defaulting to INTA\n", | ||
| 7078 | dev->name); | ||
| 7079 | sp->config.intr_type = INTA; | ||
| 7080 | break; | ||
| 7025 | } | 7081 | } |
| 7082 | sp->s2io_entries[i].in_use = | ||
| 7083 | MSIX_REGISTERED_SUCCESS; | ||
| 7026 | } | 7084 | } |
| 7027 | if (err) { | ||
| 7028 | remove_msix_isr(sp); | ||
| 7029 | DBG_PRINT(ERR_DBG,"%s:MSI-X-%d registration " | ||
| 7030 | "failed\n", dev->name, i); | ||
| 7031 | DBG_PRINT(ERR_DBG, "%s: defaulting to INTA\n", | ||
| 7032 | dev->name); | ||
| 7033 | sp->config.intr_type = INTA; | ||
| 7034 | break; | ||
| 7035 | } | ||
| 7036 | sp->s2io_entries[i].in_use = MSIX_REGISTERED_SUCCESS; | ||
| 7037 | } | 7085 | } |
| 7038 | if (!err) { | 7086 | if (!err) { |
| 7039 | printk(KERN_INFO "MSI-X-TX %d entries enabled\n", | ||
| 7040 | msix_tx_cnt); | ||
| 7041 | printk(KERN_INFO "MSI-X-RX %d entries enabled\n", | 7087 | printk(KERN_INFO "MSI-X-RX %d entries enabled\n", |
| 7042 | msix_rx_cnt); | 7088 | --msix_rx_cnt); |
| 7089 | DBG_PRINT(INFO_DBG, "MSI-X-TX entries enabled" | ||
| 7090 | " through alarm vector\n"); | ||
| 7043 | } | 7091 | } |
| 7044 | } | 7092 | } |
| 7045 | if (sp->config.intr_type == INTA) { | 7093 | if (sp->config.intr_type == INTA) { |
| @@ -7080,8 +7128,15 @@ static void do_s2io_card_down(struct s2io_nic * sp, int do_io) | |||
| 7080 | clear_bit(__S2IO_STATE_CARD_UP, &sp->state); | 7128 | clear_bit(__S2IO_STATE_CARD_UP, &sp->state); |
| 7081 | 7129 | ||
| 7082 | /* Disable napi */ | 7130 | /* Disable napi */ |
| 7083 | if (config->napi) | 7131 | if (sp->config.napi) { |
| 7084 | napi_disable(&sp->napi); | 7132 | int off = 0; |
| 7133 | if (config->intr_type == MSI_X) { | ||
| 7134 | for (; off < sp->config.rx_ring_num; off++) | ||
| 7135 | napi_disable(&sp->mac_control.rings[off].napi); | ||
| 7136 | } | ||
| 7137 | else | ||
| 7138 | napi_disable(&sp->napi); | ||
| 7139 | } | ||
| 7085 | 7140 | ||
| 7086 | /* disable Tx and Rx traffic on the NIC */ | 7141 | /* disable Tx and Rx traffic on the NIC */ |
| 7087 | if (do_io) | 7142 | if (do_io) |
| @@ -7173,8 +7228,15 @@ static int s2io_card_up(struct s2io_nic * sp) | |||
| 7173 | } | 7228 | } |
| 7174 | 7229 | ||
| 7175 | /* Initialise napi */ | 7230 | /* Initialise napi */ |
| 7176 | if (config->napi) | 7231 | if (config->napi) { |
| 7177 | napi_enable(&sp->napi); | 7232 | int i; |
| 7233 | if (config->intr_type == MSI_X) { | ||
| 7234 | for (i = 0; i < sp->config.rx_ring_num; i++) | ||
| 7235 | napi_enable(&sp->mac_control.rings[i].napi); | ||
| 7236 | } else { | ||
| 7237 | napi_enable(&sp->napi); | ||
| 7238 | } | ||
| 7239 | } | ||
| 7178 | 7240 | ||
| 7179 | /* Maintain the state prior to the open */ | 7241 | /* Maintain the state prior to the open */ |
| 7180 | if (sp->promisc_flg) | 7242 | if (sp->promisc_flg) |
| @@ -7217,7 +7279,7 @@ static int s2io_card_up(struct s2io_nic * sp) | |||
| 7217 | /* Enable select interrupts */ | 7279 | /* Enable select interrupts */ |
| 7218 | en_dis_err_alarms(sp, ENA_ALL_INTRS, ENABLE_INTRS); | 7280 | en_dis_err_alarms(sp, ENA_ALL_INTRS, ENABLE_INTRS); |
| 7219 | if (sp->config.intr_type != INTA) | 7281 | if (sp->config.intr_type != INTA) |
| 7220 | en_dis_able_nic_intrs(sp, ENA_ALL_INTRS, DISABLE_INTRS); | 7282 | en_dis_able_nic_intrs(sp, TX_TRAFFIC_INTR, ENABLE_INTRS); |
| 7221 | else { | 7283 | else { |
| 7222 | interruptible = TX_TRAFFIC_INTR | RX_TRAFFIC_INTR; | 7284 | interruptible = TX_TRAFFIC_INTR | RX_TRAFFIC_INTR; |
| 7223 | interruptible |= TX_PIC_INTR; | 7285 | interruptible |= TX_PIC_INTR; |
| @@ -7615,9 +7677,6 @@ static int s2io_verify_parm(struct pci_dev *pdev, u8 *dev_intr_type, | |||
| 7615 | rx_ring_num = MAX_RX_RINGS; | 7677 | rx_ring_num = MAX_RX_RINGS; |
| 7616 | } | 7678 | } |
| 7617 | 7679 | ||
| 7618 | if (*dev_intr_type != INTA) | ||
| 7619 | napi = 0; | ||
| 7620 | |||
| 7621 | if ((*dev_intr_type != INTA) && (*dev_intr_type != MSI_X)) { | 7680 | if ((*dev_intr_type != INTA) && (*dev_intr_type != MSI_X)) { |
| 7622 | DBG_PRINT(ERR_DBG, "s2io: Wrong intr_type requested. " | 7681 | DBG_PRINT(ERR_DBG, "s2io: Wrong intr_type requested. " |
| 7623 | "Defaulting to INTA\n"); | 7682 | "Defaulting to INTA\n"); |
| @@ -7918,8 +7977,6 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) | |||
| 7918 | * will use eth_mac_addr() for dev->set_mac_address | 7977 | * will use eth_mac_addr() for dev->set_mac_address |
| 7919 | * mac address will be set every time dev->open() is called | 7978 | * mac address will be set every time dev->open() is called |
| 7920 | */ | 7979 | */ |
| 7921 | netif_napi_add(dev, &sp->napi, s2io_poll, 32); | ||
| 7922 | |||
| 7923 | #ifdef CONFIG_NET_POLL_CONTROLLER | 7980 | #ifdef CONFIG_NET_POLL_CONTROLLER |
| 7924 | dev->poll_controller = s2io_netpoll; | 7981 | dev->poll_controller = s2io_netpoll; |
| 7925 | #endif | 7982 | #endif |
| @@ -7963,6 +8020,32 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) | |||
| 7963 | } | 8020 | } |
| 7964 | } | 8021 | } |
| 7965 | 8022 | ||
| 8023 | if (sp->config.intr_type == MSI_X) { | ||
| 8024 | sp->num_entries = config->rx_ring_num + 1; | ||
| 8025 | ret = s2io_enable_msi_x(sp); | ||
| 8026 | |||
| 8027 | if (!ret) { | ||
| 8028 | ret = s2io_test_msi(sp); | ||
| 8029 | /* rollback MSI-X, will re-enable during add_isr() */ | ||
| 8030 | remove_msix_isr(sp); | ||
| 8031 | } | ||
| 8032 | if (ret) { | ||
| 8033 | |||
| 8034 | DBG_PRINT(ERR_DBG, | ||
| 8035 | "%s: MSI-X requested but failed to enable\n", | ||
| 8036 | dev->name); | ||
| 8037 | sp->config.intr_type = INTA; | ||
| 8038 | } | ||
| 8039 | } | ||
| 8040 | |||
| 8041 | if (config->intr_type == MSI_X) { | ||
| 8042 | for (i = 0; i < config->rx_ring_num ; i++) | ||
| 8043 | netif_napi_add(dev, &mac_control->rings[i].napi, | ||
| 8044 | s2io_poll_msix, 64); | ||
| 8045 | } else { | ||
| 8046 | netif_napi_add(dev, &sp->napi, s2io_poll_inta, 64); | ||
| 8047 | } | ||
| 8048 | |||
| 7966 | /* Not needed for Herc */ | 8049 | /* Not needed for Herc */ |
| 7967 | if (sp->device_type & XFRAME_I_DEVICE) { | 8050 | if (sp->device_type & XFRAME_I_DEVICE) { |
| 7968 | /* | 8051 | /* |
| @@ -8013,6 +8096,11 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) | |||
| 8013 | /* store mac addresses from CAM to s2io_nic structure */ | 8096 | /* store mac addresses from CAM to s2io_nic structure */ |
| 8014 | do_s2io_store_unicast_mc(sp); | 8097 | do_s2io_store_unicast_mc(sp); |
| 8015 | 8098 | ||
| 8099 | /* Configure MSIX vector for number of rings configured plus one */ | ||
| 8100 | if ((sp->device_type == XFRAME_II_DEVICE) && | ||
| 8101 | (config->intr_type == MSI_X)) | ||
| 8102 | sp->num_entries = config->rx_ring_num + 1; | ||
| 8103 | |||
| 8016 | /* Store the values of the MSIX table in the s2io_nic structure */ | 8104 | /* Store the values of the MSIX table in the s2io_nic structure */ |
| 8017 | store_xmsi_data(sp); | 8105 | store_xmsi_data(sp); |
| 8018 | /* reset Nic and bring it to known state */ | 8106 | /* reset Nic and bring it to known state */ |
| @@ -8078,8 +8166,14 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) | |||
| 8078 | break; | 8166 | break; |
| 8079 | } | 8167 | } |
| 8080 | 8168 | ||
| 8081 | if (napi) | 8169 | switch (sp->config.napi) { |
| 8170 | case 0: | ||
| 8171 | DBG_PRINT(ERR_DBG, "%s: NAPI disabled\n", dev->name); | ||
| 8172 | break; | ||
| 8173 | case 1: | ||
| 8082 | DBG_PRINT(ERR_DBG, "%s: NAPI enabled\n", dev->name); | 8174 | DBG_PRINT(ERR_DBG, "%s: NAPI enabled\n", dev->name); |
| 8175 | break; | ||
| 8176 | } | ||
| 8083 | 8177 | ||
| 8084 | DBG_PRINT(ERR_DBG, "%s: Using %d Tx fifo(s)\n", dev->name, | 8178 | DBG_PRINT(ERR_DBG, "%s: Using %d Tx fifo(s)\n", dev->name, |
| 8085 | sp->config.tx_fifo_num); | 8179 | sp->config.tx_fifo_num); |
