aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/s2io.c
diff options
context:
space:
mode:
authorraghavendra.koushik@neterion.com <raghavendra.koushik@neterion.com>2005-08-03 15:41:38 -0400
committerJeff Garzik <jgarzik@pobox.com>2005-08-11 00:10:46 -0400
commit303bcb4b675d7284a1097dd1c18c995c0179883a (patch)
tree1ac3e3adc6deb4f0c6c5ba987adcc28b66fa2f64 /drivers/net/s2io.c
parent0b1f7ebe455ba4f1f46e7024150eeddbbf08addc (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.c54
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. */
69static char s2io_driver_name[] = "Neterion"; 69static char s2io_driver_name[] = "Neterion";
70static char s2io_driver_version[] = "Version 2.0.2.0"; 70static char s2io_driver_version[] = "Version 2.0.2.1";
71 71
72static inline int RXD_IS_UP2DT(RxD_t *rxdp) 72static 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
302static unsigned int indicate_max_pkts; 302static unsigned int indicate_max_pkts;
303#endif 303#endif
304/* Frequency of Rx desc syncs expressed as power of 2 */
305static 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
5173module_param(indicate_max_pkts, int, 0); 5198module_param(indicate_max_pkts, int, 0);
5174#endif 5199#endif
5200module_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 .