|
@@ -107,9 +107,14 @@ static uint32_t crb_cmd_producer[4] = {
|
|
|
|
|
|
void
|
|
void
|
|
netxen_nic_update_cmd_producer(struct netxen_adapter *adapter,
|
|
netxen_nic_update_cmd_producer(struct netxen_adapter *adapter,
|
|
- struct nx_host_tx_ring *tx_ring, u32 producer)
|
|
|
|
|
|
+ struct nx_host_tx_ring *tx_ring)
|
|
{
|
|
{
|
|
- NXWR32(adapter, tx_ring->crb_cmd_producer, producer);
|
|
|
|
|
|
+ NXWR32(adapter, tx_ring->crb_cmd_producer, tx_ring->producer);
|
|
|
|
+
|
|
|
|
+ if (netxen_tx_avail(tx_ring) <= TX_STOP_THRESH) {
|
|
|
|
+ netif_stop_queue(adapter->netdev);
|
|
|
|
+ smp_mb();
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
static uint32_t crb_cmd_consumer[4] = {
|
|
static uint32_t crb_cmd_consumer[4] = {
|
|
@@ -119,9 +124,9 @@ static uint32_t crb_cmd_consumer[4] = {
|
|
|
|
|
|
static inline void
|
|
static inline void
|
|
netxen_nic_update_cmd_consumer(struct netxen_adapter *adapter,
|
|
netxen_nic_update_cmd_consumer(struct netxen_adapter *adapter,
|
|
- struct nx_host_tx_ring *tx_ring, u32 consumer)
|
|
|
|
|
|
+ struct nx_host_tx_ring *tx_ring)
|
|
{
|
|
{
|
|
- NXWR32(adapter, tx_ring->crb_cmd_consumer, consumer);
|
|
|
|
|
|
+ NXWR32(adapter, tx_ring->crb_cmd_consumer, tx_ring->sw_consumer);
|
|
}
|
|
}
|
|
|
|
|
|
static uint32_t msi_tgt_status[8] = {
|
|
static uint32_t msi_tgt_status[8] = {
|
|
@@ -900,8 +905,11 @@ netxen_nic_attach(struct netxen_adapter *adapter)
|
|
tx_ring->crb_cmd_producer = crb_cmd_producer[adapter->portnum];
|
|
tx_ring->crb_cmd_producer = crb_cmd_producer[adapter->portnum];
|
|
tx_ring->crb_cmd_consumer = crb_cmd_consumer[adapter->portnum];
|
|
tx_ring->crb_cmd_consumer = crb_cmd_consumer[adapter->portnum];
|
|
|
|
|
|
- netxen_nic_update_cmd_producer(adapter, tx_ring, 0);
|
|
|
|
- netxen_nic_update_cmd_consumer(adapter, tx_ring, 0);
|
|
|
|
|
|
+ tx_ring->producer = 0;
|
|
|
|
+ tx_ring->sw_consumer = 0;
|
|
|
|
+
|
|
|
|
+ netxen_nic_update_cmd_producer(adapter, tx_ring);
|
|
|
|
+ netxen_nic_update_cmd_consumer(adapter, tx_ring);
|
|
}
|
|
}
|
|
|
|
|
|
for (ring = 0; ring < adapter->max_rds_rings; ring++) {
|
|
for (ring = 0; ring < adapter->max_rds_rings; ring++) {
|
|
@@ -1362,7 +1370,7 @@ netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
|
|
dma_addr_t temp_dma;
|
|
dma_addr_t temp_dma;
|
|
int i, k;
|
|
int i, k;
|
|
|
|
|
|
- u32 producer, consumer;
|
|
|
|
|
|
+ u32 producer;
|
|
int frag_count, no_of_desc;
|
|
int frag_count, no_of_desc;
|
|
u32 num_txd = tx_ring->num_desc;
|
|
u32 num_txd = tx_ring->num_desc;
|
|
bool is_tso = false;
|
|
bool is_tso = false;
|
|
@@ -1372,15 +1380,13 @@ netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
|
|
/* 4 fragments per cmd des */
|
|
/* 4 fragments per cmd des */
|
|
no_of_desc = (frag_count + 3) >> 2;
|
|
no_of_desc = (frag_count + 3) >> 2;
|
|
|
|
|
|
- producer = tx_ring->producer;
|
|
|
|
- smp_mb();
|
|
|
|
- consumer = tx_ring->sw_consumer;
|
|
|
|
- if ((no_of_desc+2) >= find_diff_among(producer, consumer, num_txd)) {
|
|
|
|
|
|
+ if (unlikely(no_of_desc + 2) > netxen_tx_avail(tx_ring)) {
|
|
netif_stop_queue(netdev);
|
|
netif_stop_queue(netdev);
|
|
- smp_mb();
|
|
|
|
return NETDEV_TX_BUSY;
|
|
return NETDEV_TX_BUSY;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ producer = tx_ring->producer;
|
|
|
|
+
|
|
hwdesc = &tx_ring->desc_head[producer];
|
|
hwdesc = &tx_ring->desc_head[producer];
|
|
netxen_clear_cmddesc((u64 *)hwdesc);
|
|
netxen_clear_cmddesc((u64 *)hwdesc);
|
|
pbuf = &tx_ring->cmd_buf_arr[producer];
|
|
pbuf = &tx_ring->cmd_buf_arr[producer];
|
|
@@ -1493,7 +1499,7 @@ netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
|
|
tx_ring->producer = producer;
|
|
tx_ring->producer = producer;
|
|
adapter->stats.txbytes += skb->len;
|
|
adapter->stats.txbytes += skb->len;
|
|
|
|
|
|
- netxen_nic_update_cmd_producer(adapter, tx_ring, producer);
|
|
|
|
|
|
+ netxen_nic_update_cmd_producer(adapter, tx_ring);
|
|
|
|
|
|
adapter->stats.xmitcalled++;
|
|
adapter->stats.xmitcalled++;
|
|
|
|
|