*bytes_compl += skb->len;
}
-void octeon_report_sent_bytes_to_bql(void *buf, int reqtype)
+int octeon_report_sent_bytes_to_bql(void *buf, int reqtype)
{
struct octnet_buf_free_info *finfo;
struct sk_buff *skb;
break;
default:
- return;
+ return 0;
}
txq = netdev_get_tx_queue(skb->dev, skb_get_queue_mapping(skb));
netdev_tx_sent_queue(txq, skb->len);
+
+ return netif_xmit_stopped(txq);
}
void liquidio_link_ctrl_cmd_completion(void *nctrl_ptr)
*/
static inline int send_nic_timestamp_pkt(struct octeon_device *oct,
struct octnic_data_pkt *ndata,
- struct octnet_buf_free_info *finfo)
+ struct octnet_buf_free_info *finfo,
+ int xmit_more)
{
int retval;
struct octeon_soft_command *sc;
len = (u32)((struct octeon_instr_ih2 *)
(&sc->cmd.cmd2.ih2))->dlengsz;
- ring_doorbell = 1;
+ ring_doorbell = !xmit_more;
retval = octeon_send_command(oct, sc->iq_no, ring_doorbell, &sc->cmd,
sc, len, ndata->reqtype);
union tx_info *tx_info;
int status = 0;
int q_idx = 0, iq_no = 0;
- int j;
+ int j, xmit_more = 0;
u64 dptr = 0;
u32 tag = 0;
irh->vlan = skb_vlan_tag_get(skb) & 0xfff;
}
+ xmit_more = skb->xmit_more;
+
if (unlikely(cmdsetup.s.timestamp))
- status = send_nic_timestamp_pkt(oct, &ndata, finfo);
+ status = send_nic_timestamp_pkt(oct, &ndata, finfo, xmit_more);
else
- status = octnet_send_nic_data_pkt(oct, &ndata);
+ status = octnet_send_nic_data_pkt(oct, &ndata, xmit_more);
if (status == IQ_SEND_FAILED)
goto lio_xmit_failed;
netif_info(lio, tx_queued, lio->netdev, "Transmit queued successfully\n");
if (status == IQ_SEND_STOP)
- stop_q(lio->netdev, q_idx);
+ stop_q(netdev, q_idx);
netif_trans_update(netdev);
if (dptr)
dma_unmap_single(&oct->pci_dev->dev, dptr,
ndata.datasize, DMA_TO_DEVICE);
+
+ octeon_ring_doorbell_locked(oct, iq_no);
+
tx_buffer_free(skb);
return NETDEV_TX_OK;
}
*/
static int send_nic_timestamp_pkt(struct octeon_device *oct,
struct octnic_data_pkt *ndata,
- struct octnet_buf_free_info *finfo)
+ struct octnet_buf_free_info *finfo,
+ int xmit_more)
{
struct octeon_soft_command *sc;
int ring_doorbell;
len = (u32)((struct octeon_instr_ih3 *)(&sc->cmd.cmd3.ih3))->dlengsz;
- ring_doorbell = 1;
+ ring_doorbell = !xmit_more;
retval = octeon_send_command(oct, sc->iq_no, ring_doorbell, &sc->cmd,
sc, len, ndata->reqtype);
struct octeon_device *oct;
int q_idx = 0, iq_no = 0;
union tx_info *tx_info;
+ int xmit_more = 0;
struct lio *lio;
int status = 0;
u64 dptr = 0;
irh->vlan = skb_vlan_tag_get(skb) & VLAN_VID_MASK;
}
+ xmit_more = skb->xmit_more;
+
if (unlikely(cmdsetup.s.timestamp))
- status = send_nic_timestamp_pkt(oct, &ndata, finfo);
+ status = send_nic_timestamp_pkt(oct, &ndata, finfo, xmit_more);
else
- status = octnet_send_nic_data_pkt(oct, &ndata);
+ status = octnet_send_nic_data_pkt(oct, &ndata, xmit_more);
if (status == IQ_SEND_FAILED)
goto lio_xmit_failed;
if (status == IQ_SEND_STOP) {
dev_err(&oct->pci_dev->dev, "Rcvd IQ_SEND_STOP signal; stopping IQ-%d\n",
iq_no);
- stop_q(lio->netdev, q_idx);
+ stop_q(netdev, q_idx);
}
netif_trans_update(netdev);
if (dptr)
dma_unmap_single(&oct->pci_dev->dev, dptr,
ndata.datasize, DMA_TO_DEVICE);
+
+ octeon_ring_doorbell_locked(oct, iq_no);
+
tx_buffer_free(skb);
return NETDEV_TX_OK;
}
#define MAX_OCTEON_LINKS MAX_OCTEON_NICIF
#define MAX_OCTEON_MULTICAST_ADDR 32
+#define MAX_OCTEON_FILL_COUNT 8
+
/* CN6xxx IQ configuration macros */
#define CN6XXX_MAX_INPUT_QUEUES 32
#define CN6XXX_MAX_IQ_DESCRIPTORS 2048
int lio_wait_for_instr_fetch(struct octeon_device *oct);
+void
+octeon_ring_doorbell_locked(struct octeon_device *oct, u32 iq_no);
+
int
octeon_register_reqtype_free_fn(struct octeon_device *oct, int reqtype,
void (*fn)(void *));
};
/* BQL-related functions */
-void octeon_report_sent_bytes_to_bql(void *buf, int reqtype);
+int octeon_report_sent_bytes_to_bql(void *buf, int reqtype);
void octeon_update_tx_completion_counters(void *buf, int reqtype,
unsigned int *pkts_compl,
unsigned int *bytes_compl);
}
int octnet_send_nic_data_pkt(struct octeon_device *oct,
- struct octnic_data_pkt *ndata)
+ struct octnic_data_pkt *ndata,
+ int xmit_more)
{
- int ring_doorbell = 1;
+ int ring_doorbell = !xmit_more;
return octeon_send_command(oct, ndata->q_no, ring_doorbell, &ndata->cmd,
ndata->buf, ndata->datasize,
* queue should be stopped, and IQ_SEND_OK if it sent okay.
*/
int octnet_send_nic_data_pkt(struct octeon_device *oct,
- struct octnic_data_pkt *ndata);
+ struct octnic_data_pkt *ndata,
+ int xmit_more);
/** Send a NIC control packet to the device
* @param oct - octeon device pointer
}
}
+void
+octeon_ring_doorbell_locked(struct octeon_device *oct, u32 iq_no)
+{
+ struct octeon_instr_queue *iq;
+
+ iq = oct->instr_queue[iq_no];
+ spin_lock(&iq->post_lock);
+ if (iq->fill_cnt)
+ ring_doorbell(oct, iq);
+ spin_unlock(&iq->post_lock);
+}
+
static inline void __copy_cmd_into_iq(struct octeon_instr_queue *iq,
u8 *cmd)
{
u32 force_db, void *cmd, void *buf,
u32 datasize, u32 reqtype)
{
+ int xmit_stopped;
struct iq_post_status st;
struct octeon_instr_queue *iq = oct->instr_queue[iq_no];
st = __post_command2(iq, cmd);
if (st.status != IQ_SEND_FAILED) {
- octeon_report_sent_bytes_to_bql(buf, reqtype);
+ xmit_stopped = octeon_report_sent_bytes_to_bql(buf, reqtype);
__add_to_request_list(iq, st.index, buf, reqtype);
INCR_INSTRQUEUE_PKT_COUNT(oct, iq_no, bytes_sent, datasize);
INCR_INSTRQUEUE_PKT_COUNT(oct, iq_no, instr_posted, 1);
- if (force_db)
+ if (iq->fill_cnt >= MAX_OCTEON_FILL_COUNT || force_db ||
+ xmit_stopped || st.status == IQ_SEND_STOP)
ring_doorbell(oct, iq);
} else {
INCR_INSTRQUEUE_PKT_COUNT(oct, iq_no, instr_dropped, 1);