diff options
author | raghavendra.koushik@neterion.com <raghavendra.koushik@neterion.com> | 2005-08-03 15:41:38 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@pobox.com> | 2005-08-11 00:10:46 -0400 |
commit | 303bcb4b675d7284a1097dd1c18c995c0179883a (patch) | |
tree | 1ac3e3adc6deb4f0c6c5ba987adcc28b66fa2f64 /drivers/net/s2io.c | |
parent | 0b1f7ebe455ba4f1f46e7024150eeddbbf08addc (diff) |
[PATCH] S2io: Errors found during review
Hi,
This is a patch to incorporate comments from earlier 12 patches.
It also fixes a few issues we found during this time.
Following is a list of changes in this patch. Item 1 incorporates
earlier comments. Issues addressed in items 2 to 4 were discovered
recently.
1. wmb() call in s2io_xmit() replaced with mmiowb().
2. The dtx_control register was earlier programmed incorrectly
for Xframe II adapter.
3. As suggested by hardware team, after a reset, in case of
Xframe II adapter, we clear certain spurious errors by
clearing PCI-X ECC status register, "detected parity error"
bit in PCI_STATUS register and PCI_STATUS bit in txpic_int register.
4. On IBM PPC platforms, we found that in the Rx buffer replenish
function, two memory writes(one to the the descriptor length and
another to the ownership) were getting reordered. This was causing
the adapter to see the ownership transfered to it before the length
was updated.
One solution was to add a wmb() but since this would turnout expensive
on some platforms if called for every descriptor, we set the ownership
bit and other fields of '2' to 'N' Rx descriptors followed by a wmb()
and then set the ownership of first descriptor ('1').
Here the value 'N' is configurable by making it a module loadable
parameter (rxsync_frequency).
(NOTE: This parameter is a power of 2).
5. Bumped up the driver version no. to 2.0.2.1
Signed-off-by: Ravinandan Arakali <ravinandan.arakali@neterion.com>
Signed-off-by: Raghavendra Koushik <raghavendra.koushik@neterion.com>
Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
Diffstat (limited to 'drivers/net/s2io.c')
-rw-r--r-- | drivers/net/s2io.c | 54 |
1 files changed, 40 insertions, 14 deletions
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index abf910e40334..e083351e3f42 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c | |||
@@ -67,7 +67,7 @@ | |||
67 | 67 | ||
68 | /* S2io Driver name & version. */ | 68 | /* S2io Driver name & version. */ |
69 | static char s2io_driver_name[] = "Neterion"; | 69 | static char s2io_driver_name[] = "Neterion"; |
70 | static char s2io_driver_version[] = "Version 2.0.2.0"; | 70 | static char s2io_driver_version[] = "Version 2.0.2.1"; |
71 | 71 | ||
72 | static inline int RXD_IS_UP2DT(RxD_t *rxdp) | 72 | static inline int RXD_IS_UP2DT(RxD_t *rxdp) |
73 | { | 73 | { |
@@ -301,6 +301,8 @@ static unsigned int bimodal = 0; | |||
301 | #ifndef CONFIG_S2IO_NAPI | 301 | #ifndef CONFIG_S2IO_NAPI |
302 | static unsigned int indicate_max_pkts; | 302 | static unsigned int indicate_max_pkts; |
303 | #endif | 303 | #endif |
304 | /* Frequency of Rx desc syncs expressed as power of 2 */ | ||
305 | static unsigned int rxsync_frequency = 3; | ||
304 | 306 | ||
305 | /* | 307 | /* |
306 | * S2IO device table. | 308 | * S2IO device table. |
@@ -837,7 +839,7 @@ static int init_nic(struct s2io_nic *nic) | |||
837 | */ | 839 | */ |
838 | if (nic->device_type & XFRAME_II_DEVICE) { | 840 | if (nic->device_type & XFRAME_II_DEVICE) { |
839 | while (herc_act_dtx_cfg[dtx_cnt] != END_SIGN) { | 841 | while (herc_act_dtx_cfg[dtx_cnt] != END_SIGN) { |
840 | SPECIAL_REG_WRITE(xena_dtx_cfg[dtx_cnt], | 842 | SPECIAL_REG_WRITE(herc_act_dtx_cfg[dtx_cnt], |
841 | &bar0->dtx_control, UF); | 843 | &bar0->dtx_control, UF); |
842 | if (dtx_cnt & 0x1) | 844 | if (dtx_cnt & 0x1) |
843 | msleep(1); /* Necessary!! */ | 845 | msleep(1); /* Necessary!! */ |
@@ -2083,6 +2085,7 @@ int fill_rx_buffers(struct s2io_nic *nic, int ring_no) | |||
2083 | #ifndef CONFIG_S2IO_NAPI | 2085 | #ifndef CONFIG_S2IO_NAPI |
2084 | unsigned long flags; | 2086 | unsigned long flags; |
2085 | #endif | 2087 | #endif |
2088 | RxD_t *first_rxdp = NULL; | ||
2086 | 2089 | ||
2087 | mac_control = &nic->mac_control; | 2090 | mac_control = &nic->mac_control; |
2088 | config = &nic->config; | 2091 | config = &nic->config; |
@@ -2202,6 +2205,10 @@ int fill_rx_buffers(struct s2io_nic *nic, int ring_no) | |||
2202 | if (!skb) { | 2205 | if (!skb) { |
2203 | DBG_PRINT(ERR_DBG, "%s: Out of ", dev->name); | 2206 | DBG_PRINT(ERR_DBG, "%s: Out of ", dev->name); |
2204 | DBG_PRINT(ERR_DBG, "memory to allocate SKBs\n"); | 2207 | DBG_PRINT(ERR_DBG, "memory to allocate SKBs\n"); |
2208 | if (first_rxdp) { | ||
2209 | wmb(); | ||
2210 | first_rxdp->Control_1 |= RXD_OWN_XENA; | ||
2211 | } | ||
2205 | return -ENOMEM; | 2212 | return -ENOMEM; |
2206 | } | 2213 | } |
2207 | #ifndef CONFIG_2BUFF_MODE | 2214 | #ifndef CONFIG_2BUFF_MODE |
@@ -2212,7 +2219,8 @@ int fill_rx_buffers(struct s2io_nic *nic, int ring_no) | |||
2212 | rxdp->Control_2 &= (~MASK_BUFFER0_SIZE); | 2219 | rxdp->Control_2 &= (~MASK_BUFFER0_SIZE); |
2213 | rxdp->Control_2 |= SET_BUFFER0_SIZE(size); | 2220 | rxdp->Control_2 |= SET_BUFFER0_SIZE(size); |
2214 | rxdp->Host_Control = (unsigned long) (skb); | 2221 | rxdp->Host_Control = (unsigned long) (skb); |
2215 | rxdp->Control_1 |= RXD_OWN_XENA; | 2222 | if (alloc_tab & ((1 << rxsync_frequency) - 1)) |
2223 | rxdp->Control_1 |= RXD_OWN_XENA; | ||
2216 | off++; | 2224 | off++; |
2217 | off %= (MAX_RXDS_PER_BLOCK + 1); | 2225 | off %= (MAX_RXDS_PER_BLOCK + 1); |
2218 | mac_control->rings[ring_no].rx_curr_put_info.offset = off; | 2226 | mac_control->rings[ring_no].rx_curr_put_info.offset = off; |
@@ -2239,17 +2247,34 @@ int fill_rx_buffers(struct s2io_nic *nic, int ring_no) | |||
2239 | rxdp->Control_2 |= SET_BUFFER1_SIZE(1); /* dummy. */ | 2247 | rxdp->Control_2 |= SET_BUFFER1_SIZE(1); /* dummy. */ |
2240 | rxdp->Control_2 |= BIT(0); /* Set Buffer_Empty bit. */ | 2248 | rxdp->Control_2 |= BIT(0); /* Set Buffer_Empty bit. */ |
2241 | rxdp->Host_Control = (u64) ((unsigned long) (skb)); | 2249 | rxdp->Host_Control = (u64) ((unsigned long) (skb)); |
2242 | rxdp->Control_1 |= RXD_OWN_XENA; | 2250 | if (alloc_tab & ((1 << rxsync_frequency) - 1)) |
2251 | rxdp->Control_1 |= RXD_OWN_XENA; | ||
2243 | off++; | 2252 | off++; |
2244 | mac_control->rings[ring_no].rx_curr_put_info.offset = off; | 2253 | mac_control->rings[ring_no].rx_curr_put_info.offset = off; |
2245 | #endif | 2254 | #endif |
2246 | rxdp->Control_2 |= SET_RXD_MARKER; | 2255 | rxdp->Control_2 |= SET_RXD_MARKER; |
2247 | 2256 | ||
2257 | if (!(alloc_tab & ((1 << rxsync_frequency) - 1))) { | ||
2258 | if (first_rxdp) { | ||
2259 | wmb(); | ||
2260 | first_rxdp->Control_1 |= RXD_OWN_XENA; | ||
2261 | } | ||
2262 | first_rxdp = rxdp; | ||
2263 | } | ||
2248 | atomic_inc(&nic->rx_bufs_left[ring_no]); | 2264 | atomic_inc(&nic->rx_bufs_left[ring_no]); |
2249 | alloc_tab++; | 2265 | alloc_tab++; |
2250 | } | 2266 | } |
2251 | 2267 | ||
2252 | end: | 2268 | end: |
2269 | /* Transfer ownership of first descriptor to adapter just before | ||
2270 | * exiting. Before that, use memory barrier so that ownership | ||
2271 | * and other fields are seen by adapter correctly. | ||
2272 | */ | ||
2273 | if (first_rxdp) { | ||
2274 | wmb(); | ||
2275 | first_rxdp->Control_1 |= RXD_OWN_XENA; | ||
2276 | } | ||
2277 | |||
2253 | return SUCCESS; | 2278 | return SUCCESS; |
2254 | } | 2279 | } |
2255 | 2280 | ||
@@ -2783,16 +2808,16 @@ void s2io_reset(nic_t * sp) | |||
2783 | s2io_set_swapper(sp); | 2808 | s2io_set_swapper(sp); |
2784 | 2809 | ||
2785 | /* Clear certain PCI/PCI-X fields after reset */ | 2810 | /* Clear certain PCI/PCI-X fields after reset */ |
2786 | pci_read_config_word(sp->pdev, PCI_COMMAND, &pci_cmd); | 2811 | if (sp->device_type == XFRAME_II_DEVICE) { |
2787 | pci_cmd &= 0x7FFF; /* Clear parity err detect bit */ | 2812 | /* Clear parity err detect bit */ |
2788 | pci_write_config_word(sp->pdev, PCI_COMMAND, pci_cmd); | 2813 | pci_write_config_word(sp->pdev, PCI_STATUS, 0x8000); |
2789 | 2814 | ||
2790 | val64 = readq(&bar0->txpic_int_reg); | 2815 | /* Clearing PCIX Ecc status register */ |
2791 | val64 &= ~BIT(62); /* Clearing PCI_STATUS error reflected here */ | 2816 | pci_write_config_dword(sp->pdev, 0x68, 0x7C); |
2792 | writeq(val64, &bar0->txpic_int_reg); | ||
2793 | 2817 | ||
2794 | /* Clearing PCIX Ecc status register */ | 2818 | /* Clearing PCI_STATUS error reflected here */ |
2795 | pci_write_config_dword(sp->pdev, 0x68, 0); | 2819 | writeq(BIT(62), &bar0->txpic_int_reg); |
2820 | } | ||
2796 | 2821 | ||
2797 | /* Reset device statistics maintained by OS */ | 2822 | /* Reset device statistics maintained by OS */ |
2798 | memset(&sp->stats, 0, sizeof (struct net_device_stats)); | 2823 | memset(&sp->stats, 0, sizeof (struct net_device_stats)); |
@@ -3168,8 +3193,6 @@ int s2io_xmit(struct sk_buff *skb, struct net_device *dev) | |||
3168 | val64 = mac_control->fifos[queue].list_info[put_off].list_phy_addr; | 3193 | val64 = mac_control->fifos[queue].list_info[put_off].list_phy_addr; |
3169 | writeq(val64, &tx_fifo->TxDL_Pointer); | 3194 | writeq(val64, &tx_fifo->TxDL_Pointer); |
3170 | 3195 | ||
3171 | wmb(); | ||
3172 | |||
3173 | val64 = (TX_FIFO_LAST_TXD_NUM(frg_cnt) | TX_FIFO_FIRST_LIST | | 3196 | val64 = (TX_FIFO_LAST_TXD_NUM(frg_cnt) | TX_FIFO_FIRST_LIST | |
3174 | TX_FIFO_LAST_LIST); | 3197 | TX_FIFO_LAST_LIST); |
3175 | 3198 | ||
@@ -3179,6 +3202,8 @@ int s2io_xmit(struct sk_buff *skb, struct net_device *dev) | |||
3179 | #endif | 3202 | #endif |
3180 | writeq(val64, &tx_fifo->List_Control); | 3203 | writeq(val64, &tx_fifo->List_Control); |
3181 | 3204 | ||
3205 | mmiowb(); | ||
3206 | |||
3182 | put_off++; | 3207 | put_off++; |
3183 | put_off %= mac_control->fifos[queue].tx_curr_put_info.fifo_len + 1; | 3208 | put_off %= mac_control->fifos[queue].tx_curr_put_info.fifo_len + 1; |
3184 | mac_control->fifos[queue].tx_curr_put_info.offset = put_off; | 3209 | mac_control->fifos[queue].tx_curr_put_info.offset = put_off; |
@@ -5172,6 +5197,7 @@ module_param(bimodal, bool, 0); | |||
5172 | #ifndef CONFIG_S2IO_NAPI | 5197 | #ifndef CONFIG_S2IO_NAPI |
5173 | module_param(indicate_max_pkts, int, 0); | 5198 | module_param(indicate_max_pkts, int, 0); |
5174 | #endif | 5199 | #endif |
5200 | module_param(rxsync_frequency, int, 0); | ||
5175 | 5201 | ||
5176 | /** | 5202 | /** |
5177 | * s2io_init_nic - Initialization of the adapter . | 5203 | * s2io_init_nic - Initialization of the adapter . |